Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

strange return value

1 view
Skip to first unread message

fxn...@gmail.com

unread,
Oct 18, 2005, 4:14:29 PM10/18/05
to
In perlsub there is that sentence "The return value of a subroutine is
the value of the last expression evaluated by that sub, or the empty
list in the case of an empty sub." How would you explain the return
value of subroutines whose last statement is for instance a foreach
like this one?

% perl -wle 'sub foo { 1 for @_ } print 2 if foo(3) eq ""'
2

Why does that subroutine return the empty string?

-- fxn

Paul Lalli

unread,
Oct 18, 2005, 4:22:31 PM10/18/05
to

[Disclaimer: I have no proof of anything I'm about to say. It's just
what "makes sense" to me]

Because the body of the for loop isn't the last thing the for loop
executes. Perl has to do the test condition to determine if the loop
is going to iterate again. This is much more explicit in a C-style for
loop, but no less true in a foreach-style loop.

Paul Lalli

fxn...@gmail.com

unread,
Oct 19, 2005, 11:04:28 AM10/19/05
to
Yes, yes, that's the issue. We certainly can make a guess, but what I
want is to _know_ the answer.

See these tests, the returned value is defined and has kind of a dual
nature:

% perl -wle 'print 2 if 0 eq ""'
% perl -wle 'print 2 if 0 == ""'
Argument "" isn't numeric in numeric eq (==) at -e line 1.
2
% perl -wle 'sub foo { 1 for @_ } print 2 if defined foo(3)'
2
% perl -wle 'sub foo { 1 for @_ } print 2 if foo(3) == 0'
2


% perl -wle 'sub foo { 1 for @_ } print 2 if foo(3) eq ""'
2

% perl -wle 'sub foo { 0 } print 2 if foo(3) eq ""'
%

I would like to understand this in detail, or to be aware that they
enter unespecified behaviour if that was the case.

-- fxn

T Beck

unread,
Oct 19, 2005, 12:29:53 PM10/19/05
to
fxn...@gmail.com wrote:
> See these tests, the returned value is defined and has kind of a dual
> nature:
>
> % perl -wle 'print 2 if 0 eq ""'
> % perl -wle 'print 2 if 0 == ""'
> Argument "" isn't numeric in numeric eq (==) at -e line 1.
> 2
> % perl -wle 'sub foo { 1 for @_ } print 2 if defined foo(3)'
> 2
> % perl -wle 'sub foo { 1 for @_ } print 2 if foo(3) == 0'
> 2
> % perl -wle 'sub foo { 1 for @_ } print 2 if foo(3) eq ""'
> 2
> % perl -wle 'sub foo { 0 } print 2 if foo(3) eq ""'
> %

Also,

~>perl -wle 'sub foo { 1 until @_ } print 2 if foo(3) eq ""'
~>perl -wle 'sub foo { 1 until @_ } print foo(3) ; print "\n"'
1
~>

Paul Lalli wrote:
> [Disclaimer: I have no proof of anything I'm about to say. It's just
> what "makes sense" to me]
>
> Because the body of the for loop isn't the last thing the for loop
> executes. Perl has to do the test condition to determine if the loop
> is going to iterate again. This is much more explicit in a C-style for
> loop, but no less true in a foreach-style loop.


The Until test seems to lend credibility to Paul's guess that it's
returning the result of the last compare. The documentation (perlsyn)
says "Perl's C-style for loop works like the corresponding while
loop;", on while says "The while and until modifiers have the usual
'while loop' semantics." Until is just a negated while. Logically,
what Paul said makes sense for normal while loops (it has to evaluate
the conditional to know when to break out), but as far as I can tell
there's no documented return value of a while/until/for.

I'd steer clear of relying on it unless someone can find a place in the
docs that says this is the way it's supposed to behave, but it
certainly seems to be the way that it {does} behave (for the moment,
anyway)

-- T Beck

T Beck

unread,
Oct 19, 2005, 12:42:01 PM10/19/05
to

T Beck wrote:
> fxn...@gmail.com wrote:
> > See these tests, the returned value is defined and has kind of a dual
> > nature:
> >
> > % perl -wle 'print 2 if 0 eq ""'
> > % perl -wle 'print 2 if 0 == ""'
> > Argument "" isn't numeric in numeric eq (==) at -e line 1.
> > 2
> > % perl -wle 'sub foo { 1 for @_ } print 2 if defined foo(3)'
> > 2
>

Argh... I completely read over the part where you pointed out it was
defined. Apparently I haven't had enough coffee today...

> I'd steer clear of relying on it unless someone can find a place in the
> docs that says this is the way it's supposed to behave, but it
> certainly seems to be the way that it {does} behave (for the moment,
> anyway)

It still seems to be a constant behavior, but not very comforting.
You're right, the fact that it's returning an actual empty string is
weird, to say the least.

--T Beck

Anno Siegel

unread,
Oct 20, 2005, 4:14:45 PM10/20/05
to
T Beck <Tracy...@Infineon.com> wrote in comp.lang.perl.misc:

Not weird at all, but normal behavior for Perl's idea of a boolean. A
boolean false has a double nature in that its numeric value is 0 and its
string value is an empty string. (A boolean true is a normal 1). Another
scalar with independent numeric and string values is $!.

So this supports the theory that what the sub returns is the boolean
result of the last comparison, arguably the "last statement executed".
More evidence:

% perl -wle 'sub foo { 1 until $_[0] } print foo("quack")'
quack

However, I'm confident in saying that this is nowhere documented. In fact
I consider this a (harmless) bug, it should behave like a plain "return;".

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Big and Blue

unread,
Oct 21, 2005, 6:58:09 PM10/21/05
to
Anno Siegel wrote:

> So this supports the theory that what the sub returns is the boolean
> result of the last comparison, arguably the "last statement executed".

No argument at all, surely. If all that the sub() contains is the loop
then the test which ends the loop is the last statement executed in the sub.

> However, I'm confident in saying that this is nowhere documented.

Whereas I'm confident that it is documented that, in the absence of a
return statement, the return value of a sub() is the value of the last
statement executed.

> In fact
> I consider this a (harmless) bug, it should behave like a plain "return;".

I see no bug, but I'm also not sure what you think should behave like a
plain "return" (whcih actually returns undef in a scalar context and ()
in an array context, AFAIR).

If you want to be sure wat a sub() returns then use a return statement
- isn't that why it exists?

--
Just because I've written it doesn't mean that
either you or I have to believe it.

Tassilo v. Parseval

unread,
Oct 22, 2005, 2:46:52 AM10/22/05
to
Also sprach Big and Blue:

> Anno Siegel wrote:
>
>> So this supports the theory that what the sub returns is the boolean
>> result of the last comparison, arguably the "last statement executed".
>
> No argument at all, surely. If all that the sub() contains is the loop
> then the test which ends the loop is the last statement executed in the sub.
>
>> However, I'm confident in saying that this is nowhere documented.
>
> Whereas I'm confident that it is documented that, in the absence of a
> return statement, the return value of a sub() is the value of the last
> statement executed.

But statements don't necessarily have a return value, only expressions
do. There is currently a heated debate going on among the p5-porters
what should be done in case a statement is used as last thing in an
otherwise return-less sub. So far a documentation patch was applied so
the perldocs now state that using certain loop-constructs as last
statement in a sub yield an undefined result with respect to the return
value.

But the discussion isn't over yet.

>> In fact
>> I consider this a (harmless) bug, it should behave like a plain "return;".
>
> I see no bug, but I'm also not sure what you think should behave like a
> plain "return" (whcih actually returns undef in a scalar context and ()
> in an array context, AFAIR).
>
> If you want to be sure wat a sub() returns then use a return statement
> - isn't that why it exists?

Subroutines aren't the only thing that return values. How about a
do-block:

print do { 1 until 1 };

You cannot use return in those.

Tassilo
--
use bigint;
$n=71423350343770280161397026330337371139054411854220053437565440;
$m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);

T Beck

unread,
Oct 24, 2005, 2:12:57 PM10/24/05
to
Anno Siegel wrote:
>
> Not weird at all, but normal behavior for Perl's idea of a boolean. A
> boolean false has a double nature in that its numeric value is 0 and its
> string value is an empty string. (A boolean true is a normal 1). Another
> scalar with independent numeric and string values is $!.

Wow... I love to learn new things. I was always under the impression
that a 1 was typically returned for boolean true, and an undef was
returned for false. But I just checked (because I'm all about seeing
results for myself) and you're exactly right. It's $foo==0 and $foo eq
"" and defined $foo.

Thanks for the lesson, Anno.

--T Beck

0 new messages