This () stuff does have VERY practical uses!
If you have a subroutine and you want to return
"nothing", meaning not "undef", not "zero", I
mean absolutely "nothing", what do you do?
This little gem, is on page 136 of "Effective Perl". It passes without even a
comment!! Whoa!
Lets say that we have:
@output = map{zoomy_function}@input;
Map{} is a critter that processes each @input and
spews out an @output (map{} is a transformation operator).
But, what would happen if for example the zoomy_function within
map{} decides that it wants to "throw a value away". How do you
do that? In Perl you can't even just exit a sub.
The value of the last statement in a Perl sub is gonna get returned.
What is that return value gonna be? "undef","0","-1"?
In Perl, you can return (), which means that NOTHING is returned!
Something can just come into the func and no result ever comes out.
The "black hole" of map().
| [reply] |
If you have a subroutine and you want to return "nothing" ...
But my questions in Re^2: reset particular variable were in the context of a discussion of differences between the $var = (); and $var = undef; et al statements, differences I still don't see.
WRT the examples you give in Re^3: reset particular variable, I realize now that what you mean by 'nothing' is 'an empty list'. I see the difference between returning an empty list and returning a list consisting of a single item that is undef (an undefined something).
Also WRT Re^3: reset particular variable, you say In Perl you can't even just exit a sub. But if you do an explicit return; from a subroutine as opposed to an implicit return (i.e., falling off the end of the subroutine), then isn't the value returned always perfectly 'defined' semantically, dependent on the calling context of the subroutine? See examples below.
Other than documentary emphasis, is there any reason to prefer any of the other alternatves given below over a simple return; statement? (Actually, I seem to recall that there exists an obscure case in which return; and return (); differ materially, but I don't have time right now to follow it up.)
>perl -wMstrict -le
"sub Sr { return }
sub Se { return () }
sub Sw { return wantarray ? () : undef }
print q{'}, Sr, q{' '}, join(q{' '}, 0+Sr, ''.Sr), q{'};
print q{'}, Se, q{' '}, join(q{' '}, 0+Se, ''.Se), q{'};
print q{'}, Sw, q{' '}, join(q{' '}, 0+Sw, ''.Sw), q{'};
"
Use of uninitialized value in addition (+) at -e line 1.
Use of uninitialized value in concatenation (.) or string ...
'' '0' ''
Use of uninitialized value in addition (+) at -e line 1.
Use of uninitialized value in concatenation (.) or string ...
'' '0' ''
Use of uninitialized value in addition (+) at -e line 1.
Use of uninitialized value in concatenation (.) or string ...
'' '0' ''
| [reply] [d/l] [select] |
Actually, I seem to recall that there exists an obscure case in which return; and return (); differ materially..
Yes, Perl "bare return" does things that might not be expected. Basically, I figure it is a bad idea to use a "bare" "return;" and I just don't do it. The below code is a simple demo... "return" will return something unless you tell it to return "nothing". As I mentioned before, "returning nothing" is useful in map{}, but for a normal function, I would return "undef".
#!/usr/bin/perl -w
use strict;
sub x
{
my $a =5;
}
print x; #prints 5
Update: This part was wrong...goof in my testing! got a bit confused while doing this quickly...Oooops...I'll have to look at some other code I did awhile ago to find a better example...I think I have one somewhere. Anyway the idea of returning $x or () from within map{} is right idea to "skip" a value in output list.
sub x1
{
my $a =5;
return;
}
print x1; #still prints 5! Whoa!
#"return'" returns value of last true statement.
#if you don't specify something else for it to return.
sub x2
{
my $a =5;
return ();
}
print "x2:",x2; #prints "x2:" , ie nothing from sub x2
Update:
I don't see any basic disagreement or argument, but perhaps a misunderstanding of the application for this:
But my questions in Re^2: reset particular variable were in the context of a discussion of differences between the $var = (); and $var = undef; et al statements, differences I still don't see.
@outputlist = map{..code...}@inputlist;
If I can "skip a value", instead of returning "undef" from the map, then say @outputlist could have fewer items in the list than @inputlist. Later when @outputlist is processed, there doesn't have to be code that says "check for undefined value", because there won't be any.
| [reply] [d/l] [select] |