strange return value

F

fxnoria

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
 
P

Paul Lalli

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?

[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
 
F

fxnoria

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

T Beck

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 said:
[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

T Beck

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
 
A

Anno Siegel

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


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.

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
 
B

Big and Blue

Anno said:
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?
 
T

Tassilo v. Parseval

Also sprach Big and Blue:
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.


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.
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
 
T

T Beck

Anno said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,946
Members
47,497
Latest member
PilarLumpk

Latest Threads

Top