Илья (>):
>> my @a = <a b c d>; my @b = <b d>; say @a.grep: { $_ eq any(@b) };
> bd
>
>> my @a = <a b c d>; my @b = <b d>; say @a.grep: { $_ ne any(@b) };
> abcd
>
> hm. I expect: ac
> But Rakudo and PUGS both return abcd. May by I missed something?

If you expected "ac", then you probably expected "$_ ne any(@b)" to
mean "$_ is not equal to any element in @b". This is a reasonable
expectation, but unfortunately, it's wrong.

Why? Well, "any(@b)" expands into "'b' | 'd'", i.e. an or-junction (a
'disjunction') of 'b' and 'd'. Because of the junction, the "ne"
comparison turns into the expression "$_ ne 'b' || $_ ne 'd'", which
is always true, since something is always distinct from at least one
of two distinct strings.

Take-home message: you never want to use negative comparison operators
and junctions together. They don't do what you think. Use prefix "not"
instead:

$ ./perl6 -e 'my @a = <a b c d>; my @b = <b d>; say @a.grep: { not $_
eq any(@b) }'
ac

>> my @a = <a b c d>; my @b = <b d>; say @a.grep: { $_ eq none(@b) };
> ac
>
>> my @a = <a b c d>; my @b = <b d>; say @a.grep: { $_ ne none(@b) };
>
> I expected ac there too.

Hm. "The element is not equal to none of @b"? :-) Somehow I doubt that
this expression falls under "self-explanatory" code.

Anyway, the expression turns into something like "!($_ ne 'b') && !($_
ne 'd')", which is why you get an empty result back, because something
cannot be equal to both 'b' and 'd' at the same time.

So, again: don't mix negated operators and junctions. It even says so in S02:

] Use of negative operators with syntactically recognizable junctions
] may produce a warning on code that works differently in English than
] in Perl. Instead of writing
]
]     if $a != 1 | 2 | 3 {...}
]
] you need to write
]
]     if not $a == 1 | 2 | 3 {...}
]
] However, this is only a syntactic warning, and
]
]     if $a != $b {...}
]
] will not complain if $b happens to contain a junction at runtime.

// Carl

Reply via email to