Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Understanding the benefit of Given/When ...

by LanX (Canon)
on Mar 04, 2010 at 14:44 UTC ( #826710=perlquestion: print w/ replies, xml ) Need Help??
LanX has asked for the wisdom of the Perl Monks concerning the following question:

Honorable Monks,

After this discussion -> Re^6: while(){}continue{}; Useful? (Consistent!), I'm trying to understand the extended functionality of the new Given/When compared to the old workaround with For/Next.

As far as I understand,

  • In given/when I have to write a continue (statement not block!) where I omit the next statement. I need to "invert" the fall through.
  • In given/when I lose the continue-block which is always executed.
  • The when has an automatically built in smart match ~~. Nice ...but how can I take profit from this smart match if the parameter passed into given can only be a scalar?

    Maybe I missed something, please see the example code to understand what I mean:

    CODE:

    use feature "switch"; $,=$\="\t"; @test=qw/abc def abcdef nnn/; print "\n\n=== Given/When"; for (@test){ print "\nGIVEN($_):"; given($_) { when (/abc/) { print "abc";continue } when (/def/) { print "def" } when (/xyz/) { print "xyz" } default { print "default" } } } print "\n\n=== For"; for (@test){ for ($_){ print "\nFOR($_):"; if (/abc/) { print "abc"} if (/def/) { print "def" ;next} if (/xyz/) { print "xyz" ;next} print "default"; } } print "\n\n=== For/Continue"; # "simplifying" the former with post-ifs and && # using continue-block my @res; for (@test){ push (@res, "abc") if (/abc/); push (@res, "def") && next if (/def/); push (@res, "xyz") && next if (/xyz/); push (@res, "default"); } continue { print "\nFOR/CONT($_):",@res; @res=(); } print "\n\n === When smartmatch\n"; print "\n= GIVEN(\@test):\n"; given(@test) { print "whats tested is:",$_; when (/abc/) { print "abc";continue } when (/def/) { print "def" } when (/xyz/) { print "xyz" } default { print "default" } } print "\n= GIVEN(\\\@test):\n"; # does when act differently when a arr_reff is passed? given(\@test) { print "whats tested is:",$_; when (/abc/) { print "abc";continue } when (/def/) { print "def" } when (/xyz/) { print "xyz" } default { print "default" } } # whats the point of implicit smartmatch if only scalars can be testet +??? smartmatchingan array is different print "\nBUT: def ~~ \@test!" if @test ~~ /def/;
    OUTPUT:
    === Given/When GIVEN(abc): abc default GIVEN(def): def GIVEN(abcdef): abc def GIVEN(nnn): default === For FOR(abc): abc default FOR(def): def FOR(abcdef): abc def FOR(nnn): default === For/Continue FOR/CONT(abc): abc default FOR/CONT(def): def FOR/CONT(abcdef): abc def FOR/CONT(nnn): default === When smartmatch = GIVEN(@test): whats tested is: ARRAY(0x8a08a38) default = GIVEN(\@test): whats tested is: ARRAY(0x8a08a38) default BUT: def ~~ @test!

    Cheers Rolf

    UPDATE: extended given(Array) and given(Array_ref)

    Since given accepts arrays and automatically passes the ref without when reacting accordingly, I suppose it's a BUG!

  • Comment on Understanding the benefit of Given/When ...
    Select or Download Code
    Replies are listed 'Best First'.
    Re: Understanding the benefit of Given/When ...
    by ikegami (Pope) on Mar 04, 2010 at 15:14 UTC

      The when has an automatically built in smart match ~~. Nice ...but how can I take profit from this smart match if the parameter passed into given can only be a scalar?

      Maybe, but you can check that scalar against a variety of things, not all of them scalars.

      use 5.010; use strict; use warnings; my @x = qw( abc def ); given ("abc") { when (@x) { print "when\n"; } default { print "default\n"; } }

      I have no idea what you are asking.

        > I have no idea what you are asking.

        Maybe I'm not smart enough for Smart Match ;)

        It seems that the operands in Smart Match are swapped to what I expected after reading the docs

        Is perlsyn#Switch statements clear???

        Most of the power comes from implicit smart matching: when($foo) is exactly equivalent to when($_ ~~ $foo)
        ($_ was given)

        and

        # $a $b Type of Match Implied Matching Code # ====== ===== ===================== ============= ... # Array Regex array grep grep /$b/, @$a
        see perlsyn#Smart matching in detail

        so when writing

        given (@a) { when (/abc/) {} }

        I expect this to be tested:  @a ~~ /$b/ in the meaning of  grep /$b/, @$a

        Two possibilities:

        a) the docs need a rewrite!

        b) my brain needs a rewrite! ;)

        Cheers Rolf ...still confused...

        UPDATE: Sorry personally I think that ~~ is far too overloaden with functionality to be easily understood!!!

          I don't know why the following doesn't work:
          use 5.010; use strict; use warnings; my @a='abc'; given (@a) { when (/abc/ ) { print "abc\n" } when (1 ) { print "#\n" } when (['abc']) { print "copy\n" } when (\@a ) { print "self\n" } } # copy
          Why is it skipping Array Regex to go to Array Array?
    Re: Understanding the benefit of Given/When ...
    by JavaFan (Canon) on Mar 04, 2010 at 15:14 UTC
      I don't understand why you think a 'continue-block' is missing from given/when. 'continue-block' is associated with loops; give/when isn't a loop. There's no 'continue-block' for if/elsif/else either. But given that empty blocks are loops, you could write:
      { given ($foo) { when (/bar/) {...} when (/baz/) {...} } } continue { ... always executed ... }
      But I don't see what that buys you over:
      given ($foo) { when (/bar/) {...} when (/baz/) {...} } ... always executed ...
      So, why even want a continue block on given/when? It's not needed, and isn't consistent.
      Nice ...but how can I take profit from this smart match if the parameter passed into given can only be a scalar?
      To give one example:
      my $foo = "bar"; my @foo = qw [foo bar baz]; given ($foo) { when (@foo) {say "Match"} }
      will print Match.
        So, why even want a continue block on given/when? It's not needed, and isn't consistent.

        I see what you mean, maybe I'm still too attached to the concepts of the workaround...(which is easier to understand for me)

        Anyway I think you have a plus because you can use last for leaving without executing the continue block.

        # using continue-block my @res; for (@test){ push (@res, "abc") if (/abc/); push (@res, "def") && last if (/def/); push (@res, "xyz") && next if (/xyz/); push (@res, "default"); } continue { print "\nFOR/CONT($_):",@res; @res=(); }

        OUTPUT:

        === For/Continue FOR/CONT(abc): abc default

        Cheers Rolf

          my @test = qw[abc def ghi xyz]; my @res; for (@test) { when (/abc/) {push @res, "abc"; continue} when (/def/) {push @res, "def"; last} when (/xyz/) {push @res, "xyz"; next} default {push @res, "default"} } continue { print "FOR/CONT($_): @res\n"; @res = (); } __END__ FOR/CONT(abc): abc default

    Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Node Status?
    node history
    Node Type: perlquestion [id://826710]
    Approved by Corion
    Front-paged by jrsimmon
    help
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others about the Monastery: (8)
    As of 2015-07-07 23:43 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









      Results (93 votes), past polls