Don't understand: when('foo' and/or 'bar')

Discussion in 'Perl Misc' started by Wolfram Humann, May 18, 2010.

  1. Would someone be so kind to explain the following (quotes are for
    win32 perl):

    perl -E" $u='foo'; given($u){ when('foo' and 'bar'){say 'f'}
    default{say 'd'} } "
    d
    perl -E" $u='bar'; given($u){ when('foo' and 'bar'){say 'f'}
    default{say 'd'} } "
    f
    perl -E" $u='baz'; given($u){ when('foo' and 'bar'){say 'f'}
    default{say 'd'} } "
    d
    perl -E" $u='foo'; given($u){ when('foo' or 'bar'){say 'f'}
    default{say 'd'} } "
    f
    perl -E" $u='bar'; given($u){ when('foo' or 'bar'){say 'f'}
    default{say 'd'} } "
    d
    perl -E" $u='baz'; given($u){ when('foo' or 'bar'){say 'f'}
    default{say 'd'} } "
    d

    My expectation was: smart matching of two strings uses 'eq'. $u can
    not be equal to both 'foo' and 'bar' at the same time so in the 'and'
    case I always expect the default 'd'. In the 'or' case I expect 'f' to
    be printed if $u is either 'foo' or 'bar'.
    Why is my expectation wrong?
     
    Wolfram Humann, May 18, 2010
    #1
    1. Advertising

  2. Wolfram Humann

    Willem Guest

    Wolfram Humann wrote:
    ) Would someone be so kind to explain the following (quotes are for
    ) win32 perl):
    )
    ) perl -E" $u='foo'; given($u){ when('foo' and 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) d
    ) perl -E" $u='bar'; given($u){ when('foo' and 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) f
    ) perl -E" $u='baz'; given($u){ when('foo' and 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) d
    ) perl -E" $u='foo'; given($u){ when('foo' or 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) f
    ) perl -E" $u='bar'; given($u){ when('foo' or 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) d
    ) perl -E" $u='baz'; given($u){ when('foo' or 'bar'){say 'f'}
    ) default{say 'd'} } "
    ) d
    ) My expectation was: smart matching of two strings uses 'eq'. $u can
    ) not be equal to both 'foo' and 'bar' at the same time so in the 'and'
    ) case I always expect the default 'd'. In the 'or' case I expect 'f' to
    ) be printed if $u is either 'foo' or 'bar'.
    ) Why is my expectation wrong?

    print('foo' and 'bar'); # bar
    print('foo' or 'bar'); # foo

    I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, May 18, 2010
    #2
    1. Advertising

  3. On 18 Mai, 18:54, Willem <> wrote:
    > print('foo' and 'bar');  # bar
    > print('foo' or 'bar');   # foo
    >
    > I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.
    >


    Hm, sounds reasonable. However, it's not really what I expected from
    the explanation for "when(EXPR)" in perlsyn:
    Furthermore:
    If EXPR is ... && ... or ... and ..., the test is applied
    recursively to both arguments. If both arguments pass the test, then
    the argument is treated as boolean.
    If EXPR is ... || ... or ... or ..., the test is applied
    recursively to the first argument.
    These rules look complicated, but usually they will do what you
    want.

    As a matter of fact, if the 'and' and 'or' are evaluated before the
    smart matching applies, IMHO it would be better to state exactly that
    instead of saying "usually they will do what you want" :)
    Thanks for the reply,
    Wolfram
     
    Wolfram Humann, May 18, 2010
    #3
  4. Wolfram Humann

    Uri Guttman Guest

    >>>>> "WH" == Wolfram Humann <> writes:

    WH> On 18 Mai, 18:54, Willem <> wrote:
    >> print('foo' and 'bar');  # bar
    >> print('foo' or 'bar');   # foo
    >>
    >> I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.
    >>


    WH> Hm, sounds reasonable. However, it's not really what I expected from
    WH> the explanation for "when(EXPR)" in perlsyn:
    WH> Furthermore:
    WH> If EXPR is ... && ... or ... and ..., the test is applied
    WH> recursively to both arguments. If both arguments pass the test, then
    WH> the argument is treated as boolean.
    WH> If EXPR is ... || ... or ... or ..., the test is applied
    WH> recursively to the first argument.
    WH> These rules look complicated, but usually they will do what you
    WH> want.

    having read the docs i agree it isn't very clear. try it again with
    regexes like /foo/ and /bar/ also with && instead of 'and'. i feel the
    logic as the docs seem to say is $_ ~~ EXPR which makes it:

    $_ ~~ 'foo' and 'bar'
    that evaluates to
    ($_ ~~ 'foo') and 'bar'

    so it won't distribute as you think (and the docs seem to imply). this
    could be a bug in perl or the docs. i would raise the issue on p5p as
    this definitely seems ambiguous.

    also try explicit tests like $_ eq 'foo' which should work.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, May 18, 2010
    #4
  5. Wolfram Humann

    Guest

    On Tue, 18 May 2010 11:06:34 -0700 (PDT), Wolfram Humann <> wrote:

    >On 18 Mai, 18:54, Willem <> wrote:
    >> print('foo' and 'bar');  # bar
    >> print('foo' or 'bar');   # foo
    >>
    >> I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.
    >>

    >
    >Hm, sounds reasonable. However, it's not really what I expected from
    >the explanation for "when(EXPR)" in perlsyn:
    > Furthermore:
    > If EXPR is ... && ... or ... and ..., the test is applied
    >recursively to both arguments. If both arguments pass the test, then
    >the argument is treated as boolean.
    > If EXPR is ... || ... or ... or ..., the test is applied
    >recursively to the first argument.
    > These rules look complicated, but usually they will do what you
    >want.
    >
    >As a matter of fact, if the 'and' and 'or' are evaluated before the
    >smart matching applies, IMHO it would be better to state exactly that
    >instead of saying "usually they will do what you want" :)
    >Thanks for the reply,
    >Wolfram
    >


    Hum, hows that old given/when thing worky for ya?
    Recursive boolean expression, now where has that been all these years?

    -sln
     
    , May 18, 2010
    #5
  6. Wolfram Humann

    Willem Guest

    Wolfram Humann wrote:
    ) On 18 Mai, 18:54, Willem <> wrote:
    )> print('foo' and 'bar'); ?# bar
    )> print('foo' or 'bar'); ? # foo
    )>
    )> I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.
    )>
    )
    ) Hm, sounds reasonable. However, it's not really what I expected from
    ) the explanation for "when(EXPR)" in perlsyn:
    ) Furthermore:
    ) If EXPR is ... && ... or ... and ..., the test is applied
    ) recursively to both arguments. If both arguments pass the test, then
    ) the argument is treated as boolean.
    ) If EXPR is ... || ... or ... or ..., the test is applied
    ) recursively to the first argument.
    ) These rules look complicated, but usually they will do what you
    ) want.

    Perhaps you should read back and see what 'the test' is that they are
    talking about (it's the test to see if smart matching applies or not).

    In your case, the test doesn't apply, and smart matching is done.
    Then you get ($_ ~~ ('foo' or 'bar')), which evaluates to ($_ ~~ 'foo')

    ) As a matter of fact, if the 'and' and 'or' are evaluated before the
    ) smart matching applies, IMHO it would be better to state exactly that
    ) instead of saying "usually they will do what you want" :)

    The bit you quoted doesn't have to do with that, it's just about deciding
    when to apply smart matching or not. I guess a perl guru can give a more
    detailed explanation on that.

    Smart matching itself doesn't do anything special with &&, and, ||, or.
    ('bar' ~~ ('foo' or 'bar')) evaluates to 0.

    However, to get the behaviour for 'or' that you want, you can do something
    like: given($x) { when (['foo', 'bar']) { say 'f' } }


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, May 18, 2010
    #6
  7. Wolfram Humann

    C.DeRykus Guest

    On May 18, 9:54 am, Willem <> wrote:
    > Wolfram Humann wrote:
    >
    > ) Would someone be so kind to explain the following (quotes are for
    > ) win32 perl):
    > )
    > ) perl -E" $u='foo'; given($u){ when('foo' and 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) d
    > ) perl -E" $u='bar'; given($u){ when('foo' and 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) f
    > ) perl -E" $u='baz'; given($u){ when('foo' and 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) d
    > ) perl -E" $u='foo'; given($u){ when('foo' or 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) f
    > ) perl -E" $u='bar'; given($u){ when('foo' or 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) d
    > ) perl -E" $u='baz'; given($u){ when('foo' or 'bar'){say 'f'}
    > ) default{say 'd'} } "
    > ) d
    > ) My expectation was: smart matching of two strings uses 'eq'. $u can
    > ) not be equal to both 'foo' and 'bar' at the same time so in the 'and'
    > ) case I always expect the default 'd'. In the 'or' case I expect 'f' to
    > ) be printed if $u is either 'foo' or 'bar'.
    > ) Why is my expectation wrong?
    >
    > print('foo' and 'bar');  # bar
    > print('foo' or 'bar');   # foo
    >
    > I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.
    >


    That seems to be the case:

    perl -MO=Deparse -E"$u='foo'; given($u){ when('foo' and 'bar'){say
    'f'}
    default{say 'd'} } "
    BEGIN { ... }
    $u = 'foo';
    given ($u) {
    when ('bar') {
    say 'f';
    }
    default {
    say 'd';
    }
    }

    perl -MO=Deparse -E" $u='bar'; given($u){ when('foo' or 'bar'){
    say 'f'} default{ say 'd'} } "
    BEGIN { ... }
    $u = 'bar';
    given ($u) {
    when ('foo') {
    say 'f';
    }
    default {
    say 'd';
    }
    }


    --
    Charles DeRykus
     
    C.DeRykus, May 18, 2010
    #7
  8. Wolfram Humann

    Uri Guttman Guest

    >>>>> "CD" == C DeRykus <> writes:

    >> I guess the smart matching doesn't distribute ofer the 'and' or the 'or'.


    CD> That seems to be the case:

    CD> perl -MO=Deparse -E"$u='foo'; given($u){ when('foo' and 'bar'){say
    CD> 'f'}
    CD> default{say 'd'} } "
    CD> BEGIN { ... }
    CD> $u = 'foo';
    CD> given ($u) {
    CD> when ('bar') {

    'foo' and 'bar' compile time reduce to 'bar'.


    CD> say 'f';
    CD> }
    CD> default {
    CD> say 'd';
    CD> }
    CD> }

    CD> perl -MO=Deparse -E" $u='bar'; given($u){ when('foo' or 'bar'){
    CD> say 'f'} default{ say 'd'} } "
    CD> BEGIN { ... }
    CD> $u = 'bar';
    CD> given ($u) {
    CD> when ('foo') {

    'foo' or 'bar' compile time reduce to 'foo'.


    CD> say 'f';
    CD> }
    CD> default {
    CD> say 'd';
    CD> }
    CD> }

    given (pun intended) that, i would say the docs are buggy in this
    area. or at least ambiguous and should be fixed. the 'test' for type
    inside the when seems to be for simple types and not complex
    expressions. this makes some sense in that how would perl know which
    smart match mode to use for each part of a complex boolean expression?
    but the docs should explain that better as it does

    In fact "when(EXPR)" is treated as an implicit smart match most
    of the time. The exceptions are that when EXPR is:

    so it isn't all the time that is does a smart match.

    o If EXPR is "... && ..." or "... and ...", the test is applied
    recursively to both arguments. If both arguments pass the test,
    then the argument is treated as boolean.

    that is poorly written IMO. it seems to mean (as we have learned) the
    test for the TYPE is done on both boolean args. then this expression is
    run just as a boolean (and that is why the deparse drops the second
    boolean arg - it can't affect the boolean since the other arg is a
    constant). but how would you ever implicitly invoke smart matching if
    you have a boolean expression? the example in the docs shows:

    when (/^\d+$/ && $_ < 75) { ... }

    and that does not imply any smart matching. it is a regex against $_ and
    a normal expression.

    this does need some more explanation. i see a smart match tutorial in
    the future (prolly not from me!).

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, May 18, 2010
    #8
  9. On 2010-05-18, Uri Guttman <> wrote:
    > constant). but how would you ever implicitly invoke smart matching if
    > you have a boolean expression? the example in the docs shows:
    >
    > when (/^\d+$/ && $_ < 75) { ... }
    >
    > and that does not imply any smart matching. it is a regex against $_ and
    > a normal expression.
    >
    > this does need some more explanation. i see a smart match tutorial in
    > the future (prolly not from me!).


    I think the much more productive solution is to avoid smart matching
    completely. (I have no idea WHY it was added to the language; looks
    like a severely not-enough-thought-about feature...)

    Yours,
    Ilya
     
    Ilya Zakharevich, May 19, 2010
    #9
  10. Wolfram Humann

    Uri Guttman Guest

    >>>>> "IZ" == Ilya Zakharevich <> writes:

    IZ> On 2010-05-18, Uri Guttman <> wrote:
    >> constant). but how would you ever implicitly invoke smart matching if
    >> you have a boolean expression? the example in the docs shows:
    >>
    >> when (/^\d+$/ && $_ < 75) { ... }
    >>
    >> and that does not imply any smart matching. it is a regex against $_ and
    >> a normal expression.
    >>
    >> this does need some more explanation. i see a smart match tutorial in
    >> the future (prolly not from me!).


    IZ> I think the much more productive solution is to avoid smart matching
    IZ> completely. (I have no idea WHY it was added to the language; looks
    IZ> like a severely not-enough-thought-about feature...)

    this isn't a smart matching issue but a when/given issue and when it
    will use smart matching. if you want to bitch about a feature, then
    know which is which before you bitch! :)

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, May 19, 2010
    #10
  11. On 2010-05-19, Uri Guttman <> wrote:
    > >> this does need some more explanation. i see a smart match tutorial in
    > >> the future (prolly not from me!).


    > IZ> I think the much more productive solution is to avoid smart matching
    > IZ> completely. (I have no idea WHY it was added to the language; looks
    > IZ> like a severely not-enough-thought-about feature...)


    > this isn't a smart matching issue but a when/given issue and when it
    > will use smart matching. if you want to bitch about a feature, then
    > know which is which before you bitch! :)


    So it is "smarter than smart" matching. Do you see any difference?

    Ilya
     
    Ilya Zakharevich, May 19, 2010
    #11
  12. On May 18, 8:25 pm, "Uri Guttman" <> wrote:
    > having read the docs i agree it isn't very clear. try it again with
    > regexes like /foo/ and /bar/ also with && instead of 'and'.


    Going from 'and' and 'or' to '&&' and '||' makes no difference. '/foo/
    or /bar/' works -- but only because (/foo/ or /bar/) already does what
    I want without needing any given/when or smartmatching specials. When
    testing for undef I need to write 'when(/foo/ or !defined($_))'. Maybe
    Willem's solution below is better here.

    On May 18, 8:35 pm, Willem <> wrote:
    >
    > However, to get the behaviour for 'or' that you want, you can do something
    > like: given($x) { when (['foo', 'bar']) { say 'f' } }


    That extends nicely to when(['foo', undef]). Thanks for the idea. The
    only drawback is that the intention is not as obvious because the 'or'
    is implicit from the undelying 'grep'-like smartmatching.

    Thanks for all replies,
    Wolfram
     
    Wolfram Humann, May 19, 2010
    #12
  13. Wolfram Humann

    Uri Guttman Guest

    >>>>> "IZ" == Ilya Zakharevich <> writes:

    IZ> On 2010-05-19, Uri Guttman <> wrote:
    >> >> this does need some more explanation. i see a smart match tutorial in
    >> >> the future (prolly not from me!).


    IZ> I think the much more productive solution is to avoid smart matching
    IZ> completely. (I have no idea WHY it was added to the language; looks
    IZ> like a severely not-enough-thought-about feature...)

    >> this isn't a smart matching issue but a when/given issue and when it
    >> will use smart matching. if you want to bitch about a feature, then
    >> know which is which before you bitch! :)


    IZ> So it is "smarter than smart" matching. Do you see any difference?

    yes i see the difference. given/when decides whether to do boolean or
    smart matching. then smart matching may do some more decisions. fairly
    obvious differences in the phases.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, May 19, 2010
    #13
  14. Re: People don't understand: smart match, when etc

    On 2010-05-19, Uri Guttman <> wrote:
    > >> >> this does need some more explanation. i see a smart match tutorial in
    > >> >> the future (prolly not from me!).

    >
    > IZ> I think the much more productive solution is to avoid smart matching
    > IZ> completely. (I have no idea WHY it was added to the language; looks
    > IZ> like a severely not-enough-thought-about feature...)
    >
    > >> this isn't a smart matching issue but a when/given issue and when it
    > >> will use smart matching. if you want to bitch about a feature, then
    > >> know which is which before you bitch! :)

    >
    > IZ> So it is "smarter than smart" matching. Do you see any difference?
    >
    > yes i see the difference. given/when decides whether to do boolean or
    > smart matching. then smart matching may do some more decisions. fairly
    > obvious differences in the phases.


    What I meant is that the semantic of given/when is, by inheritance,
    yet more baroque than one of smart matching. People are just plain
    not able to juggle in mind that many logical switch tables.

    IMO, one should have left only "the most obvious entries" in the
    logic of smart matching [ones which can be deduced without
    confusion from a VERY short list of rules], and just plain PROHIBIT
    all the rest. One might have needed to be yet more strict with
    given/when... (Well, the more complex semantic could have been
    left on different keywords, clearly marking "this piece of code
    requires special attention".)

    IMO, one should have done the same with precedence tables of Perl -
    one should be able to prohibit all the non-obvious confusion-prone
    combinations via `use strict q(precedence)', forcing the user to use
    explicit parentheses.

    (The situation with RExen is kinda borderline; the complexity there is
    clearly "visually marked" by "bizarre delimiters". BTW: Now, when I
    added syntax highlight of RExen to CPerl, I think that this complexity
    went another notch down... I would not mind 2-3 more notches down,
    but I have not seen any promising idea yet...)

    Yours,
    Ilya
     
    Ilya Zakharevich, May 19, 2010
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    386
    John Roth
    Jul 29, 2005
  2. Jonathan Bartlett
    Replies:
    7
    Views:
    454
    Peter Nilsson
    Jul 8, 2005
  3. Wejn
    Replies:
    2
    Views:
    121
    Michal
    Nov 29, 2003
  4. Max Williams
    Replies:
    10
    Views:
    206
    Max Williams
    Dec 15, 2007
  5. Gunnar Hjalmarsson
    Replies:
    12
    Views:
    318
    Darren Dunham
    Feb 24, 2005
Loading...

Share This Page