http://www.perlmonks.org?node_id=1000956


in reply to ~~ and list literal

First, why what you have there doesn't work.

The arguments of ~~ are necessarily evaluated in scalar context. ($x ~~ @a is just a shorthand for $x ~~ \@a.) That means that ~~ ("x", "y", "z") is equivalent to ~~ "z", as you were advised by warnings.

Secondly, getting the behaviour you do want.

Well, you want the SCALAR ~~ ARRAY behaviour, so you'll need an reference to an array, so you'll need an array. "x" ~~ ["x", "y", "z"] and "x" ~~ any("x", "y", "z") are the most concise means of achieving that with ~~. (any provided by Smart::Match).

If you don't mind moving away from ~~, you could also use grep "x" eq $_, ("x", "y", "z").

Replies are listed 'Best First'.
Re^2: ~~ and list literal
by Anonymous Monk on Oct 25, 2012 at 23:26 UTC

    Hi ikegami,

    Thanks, I think I get it now why it doesn't work. Pity though because my eyes want "x" ~~ ("x", "y", "z") to work, it looks intuitive.

    About your suggestions: Smart::Match isn't core and it incurs some runtime penalty. And I believe grep doesn't shortcut?

      Funny, I ran into the exact same problem like ten minutes ago and decided to feed the error message to the Monastery which turned up this thread :) I was trying to make some older code visually simpler now that it requires 5.10.1+ anyway.

      Yeah, that listref is not the most intuitive construction although visually the square brackets work OK for me; round ones would look redundant. What I used before was List::MoreUtils, which while non-core is fairly ubiquitous and has "any" that does shortcut. Though with lists of a size that you want to specify as literals in the source it probably makes zero difference.

Re^2: ~~ and list literal
by Anonymous Monk on Oct 25, 2012 at 23:46 UTC

    Follow-up question:

    Why does "x" ~~ "a", "b", "c" always give 1? Running through Deparse gives: 'x' ~~ 'a', '???', 'c'. What is going on here?

    And why does "x" ~~ sub { "a", "b", "c" } also give 1? Smart match is giving me a headache...

      Why does "x" ~~ "a", "b", "c" always give 1?

      It doesn't; it evaluates to "c".

      "," is a very low precedence operator. "x" ~~ "a", "b", "c" means ("x" ~~ "a"), "b", "c", which evaluates to "c" in scalar context.

      And why does "x" ~~ sub { "a", "b", "c" } also give 1?

      It doesn't; it evaluates to "c".

      "x" ~~ sub { "a", "b", "c" } is the same as scalar( sub { "a", "b", "c" }->($x) ). Since  "a", "b", "c" evaluates to "c" in scalar context, that is what is returned.

      With the ~~ operator having much higher precedence than the comma, this is parsed as a comma-list of a smart-match whose result doesn't matter, more stuff that doesn't matter at all, and "c" which is true.

      The second one would pass "x" to the sub which again evaluates a comma-list and throws away everything (including the argument) but "c" which gets returned and is true.

      ...

      Because of precedence/binding

      Consider

      $ perl -le " $f = 1,2,3 ; print $f" 1 $ perl -MO=Deparse -le " $f = 1,2,3 ; print $f" BEGIN { $/ = "\n"; $\ = "\n"; } $f = 1, '???', '???'; print $f; -e syntax OK

      Compare it to

      $ perl -le " $f = ( 1,2,3 ); print $f" 3 $ perl -MO=Deparse -le " $f = ( 1,2,3 ) ; print $f" BEGIN { $/ = "\n"; $\ = "\n"; } $f = ('???', '???', 3); print $f; -e syntax OK

      Since smart is binary (like = in the above example), it works on two scalars, left-scalar operator right-scalar

      If you have no parentheses, the first scalar is taken, the closest, because assignment operator (=) has higher precedence than comma opeartor (it binds tighter).

      If you add parenthesis, then you have the fabled List in Scalar Context, then the comma operator return the last right item (rightest most)

      See Tutorials: Precedence for Idiots

      Since you're confused about precedence you're probably also confused about context, so see Tutorials: Context in Perl: Context tutorial, "List" Is a Four-Letter Word, Easy Reference for Contexts

      Smart match is giving me a headache...

      Stop using it :) worked for me :) Smart-match