Re: wantarray - surprise behaviour
by ikegami (Patriarch) on Aug 31, 2004 at 19:16 UTC
|
If you're looking beyond the parens, you're looking too far (unless it's the arglist of a prototyped function). ( 1 => blah() ) is just ( 1, blah() ), and this is clearly a list context for blah() because (1, @a) will return (1, 'a', 'b') and not (1, 2) (assuming @a = qw(a b);).
| [reply] [d/l] [select] |
|
|
Not having used wantarray before, I looked it up in the docs. It says:
Returns true if the context of the currently executing subroutine is looking for a list value.
Does that mean the context where the wantarray is, or where the function call is?
If it's where wantarray is, print provides the list context, doesn't it?
If it's where the function is called as a hash value, couldn't you're example just as easily be (1, $a), instead of (1, @a)? Now that I'm thinking about it, maybe you're saying (1, @a) because the last statement in blah() is a print statment and providing list context?
Just trying to wrap my mind completely around this, too.
TheEnigma
| [reply] [d/l] [select] |
|
|
$hash{'a'} = 'b'
$hash{'c'} = 'd'
$hash{'e'} = 'f'
It's useful to think of the () as an operator creating an anonymous list.
couldn't you're example just as easily be (1, $a), instead of (1, @a)?
Yes, a scalar can be be provided when an a list is expected. However, I used @a because an array behaves differently in scalar and list contexts. (It returns the number of elements in the former, and the list of elements in the latter.)
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
|
Adding to what others have said, it might be easier to get your head around this concept if you think of arrays and hashes as both being fancy kinds of lists. You can assign one to the other and maintain the same information (unlike assigning a list to a scalar, which only gives you the length of the list).
@a = ( 1, 2, 3, 4 );
%h = @a;
print $h{1}; # prints 2
print $h{3}; # prints 4
print $h{2}; # prints nothing (undefined hash element)
@b = %h;
print $b[2]; # Unknown, since the hash doesn't maintain order
# Exact behavior is undefined, and often
# changes between perl versions.
$ref = { @a }; # $ref gets a hash ref, but the anonoymous ref
# is built with an array.
"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.
| [reply] [d/l] |
|
|
|
|
In this example, "the context of the currently executing subroutine" ("blah()") is:
( 1 => blah() )
It has nothing to do with what is happening inside blah(). | [reply] [d/l] [select] |
|
|
wantarray refers to where the function was called from.Returns true if the context of the currently executing subroutine is looking for a list value. Returns false if the context is looking for a scalar. Returns the undefined value if the context is looking for no value (void context).
When you call a subroutine, all arguments are sent in list context, thus the way to get the arguments back inside the sub is using the ($arg1, $arg2) = @_;
It's always list context, even if the list only contains a single value.
| [reply] |
|
|
blah(); # void
$x = blah(); # scalar
@x = blah(); # list
Anything you can dream up that can be assigned into fits into one of those categories. But dont trick yourself into thinking something like this will try a list assignment:
my $x = []; # $x is now an (empty) arrayref
$x = blah(); # $x is a scalar - wantarray reports 0
So, even though $x is an arrayref, an arrayref is NOT a list, its a scalar. A reference to be specific. | [reply] [d/l] [select] |
|
|
It is in list context because, and only because, the assignment operator is aassign and not sassign. I.e. since you're assigning to an aggregate the RHS will be in list context. It has nothing to do with the parenthesis or the comma. ( 1 => blah() ) can just as well be in scalar context in which case blah() will be called in scalar context.
$a = ( 1 => blah() );
__END__
wantarray =
ihb
Read argumentation in its context! | [reply] [d/l] [select] |
|
|
Right conclusion, wrong reasoning. Except in a few special cases, parens do not create lists. In the expression
my %hash = (1, blah ());
the parens are used for precedence, and nothing else. It's needed because the precedence of the comma operator is lower than the precedence of the assignment operator. List context is given because of the assigment to an aggregate - a hash. If the expression would be:
my %hash = blah ();
then blah() will be called in list context, and if the expression would be:
my $scalar = (1, blah ());
blah() will be called in scalar context.
What (1, @a) returns depends on the context. In scalar context, the value of (1, @a), with @a a two element array, will be 2. | [reply] [d/l] [select] |
Re: wantarray - surprise behaviour (=>)
by tye (Sage) on Aug 31, 2004 at 23:55 UTC
|
It would have been better if => had imposed scalar context on both of its sides (and string context on its left side).
This will happen in Perl6 (last I heard, as near as I can tell) but, unfortunately, people were too quickly off using => for all manner of silly things that would break if sanity were inflicted upon them so backward compatability prevents the fixing of this "gotcha" in Perl 5.
| [reply] [d/l] [select] |
Re: wantarray - surprise behaviour
by davido (Cardinal) on Sep 01, 2004 at 05:16 UTC
|
If you want to use wantarray to tell you the context of an entity within a larger expression (which is what you seem to be trying to do), you have to call wantarray from within a sub, inserted into that larger expression.
So the following two examples will do what you're seeking:
print bleah(), "\n";
sub context {
return wantarray() ? "List" : "Scalar";
}
sub bleah {
return ( "Context: " . context() );
...or if you're trying your hand at obfu...
print bleah(), "\n";
sub bleah {
return ( "Context: "
. &{sub { wantarray() ? "List" : "Scalar" }}() );
}
The second example creates an anonymous sub in which wantarray may reside, and then dereferences the anonymous sub, executing it within the concatenation expression.
| [reply] [d/l] [select] |
Re: wantarray - surprise behaviour
by Anonymous Monk on Sep 01, 2004 at 05:02 UTC
|
| [reply] |