http://qs321.pair.com?node_id=1069299


in reply to perldelta unclear on 'given's fate

I imagine that given/when will be kept. However, the perception is that their current implementation is highly flawed. A new implementation will probably break some existing uses of given/when, so it makes sense to start warning people about this.

given originally used the lexical $_ rather than the global $_ (but this has changed in 5.18). This was confusing for many people.

when adds a whole extra layer of weird.

Quick quiz! What does this output?

use v5.10; use strict; no warnings; sub two () { 2 } sub three { 3 } sub english_number { my $number = shift; given ($number) { when ( 1 ) { return 'one' } when ( two ) { return 'two' } when ( three ) { return 'three' } when ( 4 ) { return 'four' } default { return 'more' } } } say english_number($_) for 1..5;
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

Replies are listed 'Best First'.
Re^2: perldelta unclear on 'given's fate
by iguanodon (Priest) on Jan 04, 2014 at 18:37 UTC
    A whole extra layer of weird indeed. I couldn't guess so I ran it... weirder than I expected. Can you please explain what's going on here?

      It basically comes down to a question of why does when(two) seem to work as expected, but when(three) screw up everything below it?

      when(EXPR) can mean two different things. It sometimes means if($_ ~~ EXPR), and it sometimes means if(EXPR). The rules by which the interpretation of when is decided are fairly convoluted, and have changed from Perl version to Perl version. In this case they're fairly easily explained.

      three is a sub call, so when(three) is interpreted as if(three). The three sub returns 3, so this condition always evaluates to true. Thus the subsequent condition when(4) and the default clause will never get triggered.

      two is a simple sub with a prototype of () though. Thus Perl treats it as a constant. It inlines the return value 2 when the when(two) is compiled. So Perl sees the condition as when(2) - that is, not a sub call at all - and interprets it as meaning when($_ ~~ 2).

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re^2: perldelta unclear on 'given's fate
by morelenmir (Beadle) on Jan 04, 2014 at 18:45 UTC

    Hmmm...

    I actually had to run that to work it out!

    It prints "one, two, three, three, three" because the 'three' routine resets the global $_ every time the flow of execution reaches it I think? But... why doesn't the same happen with the 'two ()' routine... Something to do with the parentheses - does that sub not effect the global $_?

    That's quite a mind-twister!!!