>Or DWIM "${\foo()}" to force scalar context. Everytime I come across that
>construct I have to wonder why it's not called in scalar context. The '$'
>would seem to imply it should.
Huh? No more than
$x = scalar reverse fn();
would cause reverse() to call fn() in scalar context. The reverse()
listop confers list context upon its right-hand operand(s). Likewise,
so too does the \ listop confer list context upon its right-hand operand.
>I have to assume \foo() is actually \(foo()) or some such.
I don't know what that means. \foo() is \foo(). It's not any
different than \(foo()), and certainly not meriting an "actually".
IMHO, this is
>entirely non-intuitive. Can anyone enlighten me as to why this is as it is?
>I believe there was a p5p discussion about this, but I dread delving into
>the archives again..
Try this, from the Third Camel('s old draft):
As mentioned earlier, the backslash operator, although usually used
on a single referent to generate a single reference, doesn't have
to be. When used on a list of referents, it produces a list of
corresponding references. The second line of both pairs of examples
below does the same thing as the first line, but has the backslash
automatically distributed throughout the whole list.
@reflist = (\$s, \@a, \%h, \&f); # List of four references
@reflist = \($s, @a %h, &f); # Same thing
If a parenthesized list contains exactly one array or hash, then all
of its values are interpolated and references to each returned.
@reflist = \(@x); # Interpolate array, then get refs
@reflist = map { \$_ } @x; # Same thing
This also occurs when there are internal parentheses:
@reflist = \(@x, (@y)); # But only single aggregates expand
@reflist = (\@x, map { \$_ } @y); # Same thing
If you try this with a hash, the result will contain references
to the values (as you'd expect), but references to I<copies>
of the keys (as you might not expect).
Since array and hash slices are really just lists, you can
backslash a slice of either of these to get a list of references.
Each of the next three lines does exactly the same thing.
@envrefs = \@ENV{'HOME', 'TERM'}; # Backslashing a slice
@envrefs = \( $ENV{HOME}, $ENV{TERM} ); # Backslashing a list
@envrefs = ( \$ENV{HOME}, \$ENV{TERM} ); # A list of two references
Since functions can return lists, you can apply a backslash to
them. If you have more than one function to call, first
interpolate each function's return values into a larger list
and then backslash the whole thing.
@reflist = \fx();
@reflist = map { \$_ } fx(); # Same thing
@reflist = \( fx(), fy(), fz() );
@reflist = ( \fx(), \fy(), \fz() ); # Same thing
@reflist = map { \$_ } fx(), fy(), fz(); # Same thing
The backslash operator always supplies a list context to its
operand, so those functions are all called in list context. If
the backslash is itself in scalar context, you'll end up with
a reference to the last value from the list returned by the
function.
@reflist = \localtime(); # Ref to each of nine time elements
$lastref = \localtime(); # Ref to whether it's daylight savings time
In this regard, the backslash behaves like the named Perl list
operators, such as C<print>, C<reverse>, and C<sort>, which
always supply a list context on their right no matter what might
be happening on their left. As with named list operators, use
an explicit C<scalar> to force what follows into scalar context.
$dateref = \scalar localtime(); # \"Sat Jul 16 11:42:18 2000"
--tom