> Any ~~ (10 => 'ten');
No such method '10' for invocant of type 'Any'
in block <unit> at <unknown file> line 1
Also https://colabti.org/irclogger/irclogger_log/perl6?date=2018-12-02#l617
> Any ~~ (10 => 'ten');
False
No such method '10', which is... Odd.
Linux miskatonic 4.18.19_1 #1 SMP PREEMPT Wed Nov 14 23:03:54 UTC 2018 x86_64 GNU/Linuxperl6 -v): ➜ ~ perl6 -v
This is Rakudo version 2018.10 built on MoarVM version 2018.10
implementing Perl 6.c.
This looks to be proper functionality to me, although really very awkward in this explicit key => pair situation.
As seen here, when smartmatching an object to a Pair it will call the "key" method and compare truthiness of the method's result with that of the Pair's value.
multi method ACCEPTS(Pair:D: Mu $other) {
$other."$!key"().Bool === $!value.Bool
}
It's really useful when used with an implicit colon-pair.
'/path/to/my/file.ext'.IO ~~ :e
OR
my @a = lazy 1, 2, 3;
say @a ~~ :lazy # OUTPUT: True
say @a ~~ :!lazy # OUTPUT: False
In these explicit pair instances it definitely comes across as awkward and a bit confusing, I think. Maybe this is a case where a more awesome error message would be a good idea? I'm not sure what it would say exactly though.
One argument: in the language, we do follow the principle that smartmatching is never meant to throw and this behaviour clearly violates it.
Another argument: since the behaviour is defined in terms of calling a method, I think returning any value, and especially False is a sizeable footgun. Above, $file ~~ :e was chosen as an example. Imagine a code, where this check guards some serious operation, such as purging some data, except you have a bug in your code and $file isn't an IO::Path object, but just a Str, which does NOT have method .e. Currently, such a bug will be quickly discovered, but if we'd return False instead, the check will silently fail and the logic will proceed on the assumption the file doesn't exist.
more awesome error message
👍
although really very awkward in this explicit key => pair situation
Well, it is a golfed example. Real example is that I have a hash of pairs and when get something, I want to check if it was in this Hash or not, or I just got Any. The issue is that it can be not only pair, but a type object too, so I cannot use .defined, because such values would fail. So I was going to match Any ~~ $maybe-pair-or-a-type-object to check. I already rewrote it with :exists check though.
Now I see why it tries a call, and I have never used ~~ :e like checks before, yet it looks usable. Searching if method exists on left side would be an expensive operation, I guess.
There is no issue from me now, so it can be even closed, I think, it is my own fault to be trying to avoid :exists usage.
Still a less than awesome error message, Is it worth catching the "No such method" and printing something a bit more self-explanatory?
Added improved error message with b6c8f5ed19 , so closing this ticket.
Most helpful comment
Added improved error message with b6c8f5ed19 , so closing this ticket.