Search code examples
perlreferencescalar

How do I define an anonymous scalar ref in Perl?


How do I properly define an anonymous scalar ref in Perl?

my $scalar_ref = ?;

my $array_ref = [];

my $hash_ref = {};


Solution

  • Usually you just declare and don't initialize it.

    my $foo; # will be undef.
    

    You have to consider that empty hash refs and empty array refs point to a data structure that has a representation. Both of them, when dereferenced, give you an empty list.

    perldata says (emphasis mine):

    There are actually two varieties of null strings (sometimes referred to as "empty" strings), a defined one and an undefined one. The defined version is just a string of length zero, such as "" . The undefined version is the value that indicates that there is no real value for something, such as when there was an error, or at end of file, or when you refer to an uninitialized variable or element of an array or hash. Although in early versions of Perl, an undefined scalar could become defined when first used in a place expecting a defined value, this no longer happens except for rare cases of autovivification as explained in perlref. You can use the defined() operator to determine whether a scalar value is defined (this has no meaning on arrays or hashes), and the undef() operator to produce an undefined value.

    So an empty scalar (which it didn't actually say) would be undef. If you want it to be a reference, make it one.

    use strict;
    use warnings;
    use Data::Printer;
    
    my $scalar_ref = \undef;
    my $scalar = $$scalar_ref;
    
    p $scalar_ref;
    p $scalar;
    

    This will output:

    \ undef
    undef
    

    However, as ikegami pointed out, it will be read-only because it's not a variable. LeoNerd provides a better approach for this in his answer.


    Anyway, my point is, an empty hash ref and an empty array ref when dereferenced both contain an empty list (). And that is not undef but nothing. But there is no nothing as a scalar value, because everything that is not nothing is a scalar value.

    my $a = [];
    
    say ref $r;     # ARRAY
    say scalar @$r; # 0
    say "'@$r'";    # ''
    

    So there is no real way to initialize with nothing. You can only not initialize. But Moose will turn it to undef anyway.

    What you could do is make it maybe a scalar ref.

    use strict;
    use warnings;
    use Data::Printer;
    
    {
        package Foo;
        use Moose;
    
        has bar => ( 
          is => 'rw', 
          isa => 'Maybe[ScalarRef]', 
          predicate => 'has_bar' 
        );
    }
    
    my $foo = Foo->new;
    
    p $foo->has_bar;
    p $foo;
    
    say $foo->bar;
    

    Output:

    ""
    
    Foo  {
        Parents       Moose::Object
        public methods (3) : bar, has_bar, meta
        private methods (0)
        internals: {}
    }
    Use of uninitialized value in say at scratch.pl line 268.
    

    The predicate gives a value that is not true (the empty string ""). undef is also not true. The people who made Moose decided to go with that, but it really doesn't matter.

    Probably what you want is not have a default value, but just make it a ScalarRef an required.


    Note that perlref doesn't say anything about initializing an empty scalar ref either.