in reply to Re: 'return:' instead of 'return'
in thread 'return:' instead of 'return'

Thanks for the explanation. If I understand correctly, by default the result of evaluating the last statement is returned when no explicit return is provided, and since declaring a label is not a statement, it doesn't get evaluated. I had expected something more like the behaviour from this:
sub fn { sub { 3 } }
Where it's not the 3 that gets returned, rather it's a coderef to an anonymous subroutine.

As for 'wrong', you've guessed my meaning well. If the code is likely to mislead someone making changes at some point in the future, it is 'wrong' now. Since the 'return:' label doesn't cause the subroutine to return, putting code after it could have unexpected side-effects for anyone mistaking it for a normal 'return'.

BTW, is 'return 3;' a statement? If so, is it then a special exception to the rule 'blocks return the value of the last statement executed', or is the value of 'return 3' equal to 3 ?


- Boldra

Replies are listed 'Best First'.
Re^3: 'return:' instead of 'return'
by JavaFan (Canon) on Jun 12, 2009 at 09:54 UTC
    I had expected something more like the behaviour from this:
    sub fn { sub { 3 } }
    Where it's not the 3 that gets returned, rather it's a coderef to an anonymous subroutine.
    Are you suggesting you didn't even try to run:
    sub fn { return: 3 }
    and see what it returns? Printing the return value of fn would have instantly revealed fn had returned '3', and not a code reference.
    BTW, is 'return 3;' a statement?
    Most certainly. What else could it be? It's not some pretty decorations.
    If so, is it then a special exception to the rule 'blocks return the value of the last statement executed'
    It's a statement. But it's not a block.
    is the value of 'return 3' equal to 3 ?
    sub foo {return 3;} print foo(); __END__ 3
    So, what do you think?
      Naturally I ran it. Had it returned '1', as I had expected, I would have told my friend "here's a bug, fix it". Since it actually worked, I'll have to go to him and say "here's why I think this is bad style".

      As for your second snippet, I don't know that that answers the question - or maybe the problem is that my question just doesn't make sense. In your example 'return' exits the subroutine and the subroutine then evaluates to '3'. But what does 'return' evaluate to?

      This code:
      perl -wE 'sub fn{ return 3 and die("bury me where this arrow lands") } + say fn'
      also prints 3, but I assume the die is not executed because the subroutine has exited, not because the 'return' did not evaluate to true. I can't think of an example which would clearly show the difference (between what return evaluates to and what the subroutine evaluates to) maybe because there really isn't a difference?


      - Boldra
        Yes, there is no difference and why should there be any? return exists because you might want to leave the subroutine in the middle instead of at the end or leave from more than one location in the subroutine. And it exists to make it explicit what value is returned, it makes the program easier to read and less errorprone. If you have Damian Conways book 'Perl Best Pratices' at hand, it gives an example why explicit returning is better style, in section 'Implicit Returns'
        But what does 'return' evaluate to?
        When in doubt, don't consult Perlmonks. Read the documentation. Not only do you get your answer faster, it isn't buried between posts that don't answer your questions. It also doesn't require other people to read the documentation for you.
        $ perldoc -f return return EXPR return Returns from a subroutine, "eval", or "do FILE" with th +e value given in EXPR. Evaluation of EXPR may be in list, scal +ar, 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 li +st in list context, the undefined value in scalar context, an +d (of course) nothing at all in a void context. (Note that in the absence of an explicit "return", a subroutine, eval, or do FILE will automatically return +the value of the last expression evaluated.)
Re^3: 'return:' instead of 'return'
by ikegami (Patriarch) on Jun 12, 2009 at 16:30 UTC

    BTW, is 'return 3;' a statement? If so, is it then a special exception to the rule 'blocks return the value of the last statement executed', or is the value of 'return 3' equal to 3 ?

    No exception. That's indeed what a block returns, and the same goes for subs. They return the the value of the last statement executed.

    sub foo { if (0) { # <- Last statement executed 1 } } # Foo returned 0.
    sub foo { if (2) { 3 # <- Last statement executed } } # Foo returned 3.
    sub foo { return 4; # <- Last statement executed 5 } # Foo returned 4.