Re: Mini-Tutorial: Scalar vs List Assignment Operator
by JavaFan (Canon) on Aug 20, 2009 at 16:39 UTC
|
Beside my (...) there are also our (...) and local (...) that generate list context. sub (...) with sub an lvalue subroutine doesn't generate list context. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
$ perl -wle'sub f :lvalue { $x,$y } f()=(4,5); print $x,$y'
Useless use of a constant in void context at -e line 1.
Use of uninitialized value in print at -e line 1.
5
$ perl -wle'sub f :lvalue { $x,$y } (f())=(4,5); print $x,$y'
45
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Mini-Tutorial: Scalar vs List Assignment Operator
by dec (Beadle) on Aug 21, 2009 at 00:48 UTC
|
You should maybe look up the wantarray documentation, since it seems it could be very relevant here. In case you don't know, it lets a function determine what context it has been called in (list, scalar or void). Handy when you want to be able to respond differently to different calling contexts ... or even just raise an error/warning when called with the wrong context, eg:
sub pedantic_syswrite {
my $context=wantarray;
if (defined ($context)) {
if ($context) { # caller wants an array, which is (mostly) silly f
+or write
die "write doesn't return an array, silly!\n";
} else { # scalar context
# no warning, because user should always check return value
syswrite @_;
}
} else { # void context
die "I'm not going to write if you don't check my return value\n";
}
}
So, ok, maybe the code shouldn't die when called in a list context :-/ But it demonstrates how you might use it. | [reply] [Watch: Dir/Any] [d/l] |
|
I disagree with your strategy of preventing a function that returns a scalar from being called in list context. It limits options without adding benefits. (The other way around makes some sense.) But deciding what to have a sub return is a lengthy topic entirely unrelated to the behaviour of the assignment operators. Discussions specifically touching on the appropriateness of using wantarray have surfaced before, once not too long ago. Your thoughts would be better suited in that conversation or in a new conversation.
Also note that our Tutorials section has a tutorial on context.
By the way, syswrite(@_) doesn't work. Due to syswrite's prototype, the call is equivalent to syswrite(scalar(@_)) and results in a compilation error. You need something like:
if (@_ == 2) { syswrite($_[0], $_[1] ) }
elsif (@_ == 3) { syswrite($_[0], $_[1], $_[2] ) }
elsif (@_ == 4) { syswrite($_[0], $_[1], $_[2], $_[3]) }
else { die }
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
On "preventing a function that returns a scalar from being called in list context".. yes, I agree. I did say that it probably wasn't a good idea. The idea was just to show how to use wantarray: ie, how to test the various return values.
I had a suspicion as well when I wrote the code that the syswrite wasn't correct. Thanks for pointing it out.
With all that was wrong with my post, don't I at least get some credit for suggesting that programmers should test the return value of syswrite instead of assuming it works? Besides flagging that wantarray could be useful here (if only so the programmer has a way to test directly whether a particular construct implies a list or array context) that's the other point I was trying to make.
| [reply] [Watch: Dir/Any] |
|
|
|
|
Re: Mini-Tutorial: Scalar vs List Assignment Operator
by biohisham (Priest) on Aug 22, 2009 at 14:23 UTC
|
| [reply] [Watch: Dir/Any] [d/l] |
|
The purpose of grep is to filter a list. It does so by evaluating a piece of code for each item in the argument list. It wants a yes/no answer from the code it executes, so scalar context is warranted.
The purpose of map is to transform a list. There is no correlation between in the size of the input list and the size of the output list. A given element may be transformed into zero, one or many elements, so list context is warranted.
To tie this back to the subject at hand, this is basically how all operators work:
- If an operator requires exactly one value for an operand (such as either operand of the scalar assignment operator), the operator will impose a scalar context on that operand.
- If an operator requires multiple values for an operand (such as either operand of the list assignment operator), the operator will impose a list context on that operand.
| [reply] [Watch: Dir/Any] [d/l] [select] |