There are a few things I "know" about Perl:
So if I have this:
sub my_test {
my @x = qw(a b c);
my @y = qw(x y z t);
return (@x, @y);
}
say my_test; # a b c x y z t
say scalar my_test;
I expect either of two result values:
7
, because that's how many items there are in the list qw(a b c x y z t)
. Indeed, this is what I get from scalar sub { @{[ qw(a b c x y z t) ]} }->()
.'t'
, because if you interpret the commas as the comma operator (sigh) you get ('a', 'b', 'c', 'x', 'y', 'z', 't')
which evaluates to 't'
. Indeed, this is what I get from scalar sub { qw(a b c x y z t) }->()
.What you do get instead is… 4, without warning. Why did I get a mix of list flattening and comma operator?
Similar story with hashes and this rather popular pattern:
sub default_override_hash {
my %defaults = (foo => 'bar', egg => 'quuz');
my %values = @_;
my %overrides = (__baz => '');
return (%defaults, %values, %overrides);
}
scalar default_override_hash; # '1/8'
How does scalar
know that default_override_hash
returned three hashes, and it should not only just get %overrides
(and not everything, and not ''
), but its scalar representation as a hash?
The most important point is: Lists don't flatten. (Lists are flat, but they don't flatten, because to do that they'd have to be nested first.)
,
(the comma operator) in list context is list concatenation. A , B
in list context evaluates A
and B
in list context, then concatenates the results.
A , B
in scalar context works like C (or JavaScript): It evaluates A
in void context, then evaluates (and returns) B
in scalar context. (A , B
in void context works the same, but evaluates B
in void context too.)
In return X
, the context of X
is the context of the function call itself. Thus sub my_test { return X } scalar my_test
is like scalar X
. It's like return
dynamically looks at the context the current sub call is in, and evaluates its operand expression accordingly.
perldoc perlsub
says:
A
return
statement may be used to exit a subroutine, optionally specifying the returned value, which will be evaluated in the appropriate context (list, scalar, or void) depending on the context of the subroutine call.)
As described above, @x, @y
in scalar context evaluates @x
in void context (which for an array does nothing), then evaluates and returns @y
in scalar context. An array in scalar context yields the number of elements it contains.
The same logic applies to %defaults, %values, %overrides
. ,
is left-associative, so this parses as (%defaults , %values) , %overrides
.
This evaluates %defaults , %values
in void context (which in turn evaluates %defaults
, then %values
in void context, which has no effect), then evaluates and returns %overrides
in scalar context. A hash in scalar context returns a (rather useless) string describing hash internals.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With