简体   繁体   中英

How do I define an anonymous scalar ref in Perl?

如何在 Perl 中正确定义匿名标量引用?

my $scalar_ref = ?;

my $array_ref = [];

my $hash_ref = {};

If you want a reference to some mutable storage, there's no particularly neat direct syntax for it. About the best you can manage is

my $var;
my $sref = \$var;

Or neater

my $sref = \my $var;

Or if you don't want the variable itself to be in scope any more, you can use a do block:

my $sref = do { \my $tmp };

At this point you can pass $sref around by value, and any mutations to the scalar it references will be seen by others.

This technique of course works just as well for array or hash references, just that there's neater syntax for doing that with [] and {} :

my $aref = do { \my @tmp };  ## same as  my $aref = [];

my $href = do { \my %tmp };  ## same as  my $href = {};

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.

I'm not entirely sure why you need to but I'd suggest:

my $ref = \undef;
print ref $ref;

Or perhaps:

my $ref = \0; 

@LeoNerd's answer is spot on. Another option is to use a temporary anonymous hash value:

my $scalar_ref = \{_=>undef}->{_};
$$scalar_ref = "Hello!\n";
print $$scalar_ref;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM