Re: Elegant way to return true or nothing from a subroutine?
by ysth (Canon) on Oct 10, 2006 at 02:10 UTC
|
The builtins you seem to be referring to do not return nothing; they return a special false value that is "" in string context and 0 in numeric context (without warning the way "" would). This is very different from
nothing:
$ perl -w
sub nothing { return; }
sub something { return 0 == 1; }
my @foo;
push @foo, nothing();
print "foo has " . @foo . " elements after pushing nothing.\n";
push @foo, something();
print "foo has " . @foo . " element after pushing something.\n";
__END__
foo has 0 elements after pushing nothing.
foo has 1 element after pushing something.
(return; with no arguments does indeed return an empty list in list context, but undef in scalar context, which is very different from the usual false value.)
The easiest way is to use the not-not operator; given your example:
sub foo {
return !! shift->{some_obj}->some_method;
}
Some people prefer:
sub foo {
return ( shift->{some_obj}->some_method ) ? 1 : 0;
}
and I can see an argument being made for having the false return value be either 0 or "", not both. But just using !! is convenient.
If you actually do want nothing for false in a list context, do
sub foo {
return ( shift->{some_obj}->some_method ) ? 1 : ();
}
or
sub foo {
return shift->{some_obj}->some_method || ();
}
if true values other than 1 are permissable. | [reply] [d/l] [select] |
Re: Elegant way to return true or nothing from a subroutine?
by BrowserUk (Patriarch) on Oct 10, 2006 at 01:51 UTC
|
If you want to cater for being called in a list context, I'd use
sub foo {
return !!shift->{some_obj}->some_method() || ();
}
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Re: Elegant way to return true or nothing from a subroutine?
by GrandFather (Saint) on Oct 10, 2006 at 01:37 UTC
|
sub foo {
return !! shift->{some_obj}->some_method;
}
or even:
sub foo {
!! shift->{some_obj}->some_method;
}
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
What does the !! mean? I thought it would be not not (in other words, true..)
| [reply] [d/l] |
|
Ignoring non-integer values for brevity, the not not transformation maps 0 to 0 and everything else to 1:
my @nums = (-2 .. 2);
for my $num (@nums) {
printf "!!%2d => %d\n", $num, !!$num;
}
gives
!!-2 => 1
!!-1 => 1
!! 0 => 0
!! 1 => 1
!! 2 => 1
| [reply] [d/l] [select] |
|
Re: Elegant way to return true or nothing from a subroutine?
by jasonk (Parson) on Oct 10, 2006 at 12:30 UTC
|
return; does not return "nothing", as the documentation clearly states:
return EXPR
return Returns from a subroutine, "eval", or "do FILE" with the value
given in EXPR. Evaluation of EXPR may be in list, scalar, or
void context, depending on how the return value will be used,
and the context may vary from one execution to the next (see
"wantarray"). If no EXPR is given, returns an empty list in
list context, the undefined value in scalar context, and (of
course) nothing at all in a void context.
So the equivalent to simply return; is return wantarray ? () : undef.
We're not surrounded, we're in a target-rich environment! |
---|
| [reply] [d/l] [select] |
|
jasonk,
Actually, the documentation clearly states it does return nothing provided the sub was called in a void context. Unfortunately there isn't a clear way to say:
return defined(wantarray)
? wantarray ? () : undef
: NOTHING;
| [reply] [d/l] |
|
As fortunately, this never matters, because by definition nobody gets to look at the return value in void context.
| [reply] |
Re: Elegant way to return true or nothing from a subroutine?
by chargrill (Parson) on Oct 10, 2006 at 01:32 UTC
|
sub foo {
return shift->{some_obj}->some_method ? 1 : undef;
}
--chargrill
s**lil*; $*=join'',sort split q**; s;.*;grr; &&s+(.(.)).+$2$1+; $; =
qq-$_-;s,.*,ahc,;$,.=chop for split q,,,reverse;print for($,,$;,$*,$/)
| [reply] [d/l] [select] |
|
#!/usr/bin/perl -w
use strict;
sub ret_undef { return undef }
sub ret_nothing { return; }
print ret_nothing(), "\n";
print ret_undef(), "\n";
my @foo = ret_nothing();
print "Elements in foo: ", scalar @foo, "\n";
print @foo;
my @bar = ret_undef();
print "Elements in bar: ", scalar @bar, "\n";
print @bar;
| [reply] [d/l] |
|
use strict;
use warnings;
use Data::Dump::Streamer;
my $value = undef;
print !!$value;
my $nothing = nothing ();
my $retNothing = retNothing ();
my $retUndef = retUndef ();
my $retFalse = retFalse ();
my $retFalse2 = -retFalse ();
Dump (\$nothing);
Dump (\$retNothing);
Dump (\$retUndef);
Dump (\$retFalse);
Dump (\$retFalse2);
sub nothing {
}
sub retNothing {
return;
}
sub retUndef {
return undef;
}
sub retFalse {
return 1 == 0;
}
Prints:
$SCALAR1 = \do { my $v = undef };
$SCALAR1 = \do { my $v = undef };
$SCALAR1 = \do { my $v = undef };
$SCALAR1 = \do { my $v = '' };
$SCALAR1 = \do { my $v = 0 };
Updated to add two false cases
and in list context :)
...
my @nothing = nothing ();
my @retNothing = retNothing ();
my @retUndef = retUndef ();
my @retFalse = retFalse ();
my @retFalse2 = -retFalse ();
Dump (\@nothing);
Dump (\@retNothing);
Dump (\@retUndef);
Dump (\@retFalse);
Dump (\@retFalse2);
...
Prints:
$ARRAY1 = [];
$ARRAY1 = [];
$ARRAY1 = [ undef ];
$ARRAY1 = [ '' ];
$ARRAY1 = [ 0 ];
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
|
Re: Elegant way to return true or nothing from a subroutine?
by CountZero (Bishop) on Oct 10, 2006 at 05:48 UTC
|
Do you care to explain why you want false to be nothing rather than zero or undef? For ages these values have served us well, but perhaps you have found a good reason why this is not a good idea anymore.
CountZero "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law
| [reply] [d/l] [select] |
Re: Elegant way to return true or nothing from a subroutine?
by Anonymous Monk on Oct 10, 2006 at 07:34 UTC
|
The only way to return 'nothing' from a subroutine is to call it in void context. Otherwise, it will always return something. An argument less return in scalar context will return the undefined value. In list context, such a thing will return an empty list (which some may call 'nothing'). Buildins often return the empty string in scalar context, a false but defined value, that doesn't have a length when printed. But it certainly isn't 'nothing'. | [reply] |
Re: Elegant way to return true or nothing from a subroutine?
by pdcawley (Hermit) on Oct 10, 2006 at 11:00 UTC
|
sub foo {
shift->{some_obj}->some_method && 1 || return
}
Personally I think your attachment to requiring that all your true values be 1 is vaguely silly. A better solution would seem to be:
sub foo {
shift->{some_obj}->some_method || return
}
Wah! Guess who's been programming in ruby recently. I initially wrote those as sub foo; ...; end | [reply] [d/l] [select] |