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

The return is indeed a label. But labels don't label blocks, they label statements. A block is a form of a statement, but not all statements are blocks. In this case, the statement is 3. But even it it were a block, blocks don't return true/false. The return value of a block is the value of the last statement executed.

Does the label get evaluated at all?
Labels never get "evaluated".
Given that 'return' does little other than declare the end of the subroutine, is there really anything wrong with his usage?
'return' (as a statement) doesn't declare the end of a subroutine, it's just a way to exit the subroutine. You can have a return statement halfway the subroutine. Whether there's something "wrong" depends on what you mean by it. If 'fn' is supposed to return '3', then it will, regardless whether the label is there. But this is not a general return statement.
sub fn { if (1) { return: 3 } 2 }
is not going to return 3. It will return 2. So it that sense, the use to 'return:' is wrong.

Replies are listed 'Best First'.
Re^2: 'return:' instead of 'return'
by Boldra (Curate) on Jun 12, 2009 at 09:45 UTC
    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
      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

      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.