From: Willem on
Wolfram Humann wrote:
) On 18 Mai, 18:54, Willem <wil...(a)turtle.stack.nl> 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
From: C.DeRykus on
On May 18, 9:54 am, Willem <wil...(a)turtle.stack.nl> 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
From: Uri Guttman on
>>>>> "CD" == C DeRykus <derykus(a)gmail.com> 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 ------ uri(a)stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
From: Ilya Zakharevich on
On 2010-05-18, Uri Guttman <uri(a)StemSystems.com> 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
From: Wolfram Humann on
On May 18, 8:25 pm, "Uri Guttman" <u...(a)StemSystems.com> 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 <wil...(a)turtle.stack.nl> 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