On Sun, 05 Apr 2020, Joseph Brenner wrote:
> I find in Raku that (as expected) I can use an object as a hash key:
>
> class Rutabaga { method color { say "purple (and white)"; } }
>
> my $obj = Rutabaga.new
> my %vegeout;
> %vegeout{ $obj } = "this works";
>
> And for something I was doing I wanted to save up
> data about matches for various different regexs,
> so I thought I could just use a hash for this, like so:
>
> my (%match_locs, $loc);
>
> my $godzilla_rx = rx:i{ << godzilla >> };
> if $text ~~ m/$godzilla_rx/ {
> $loc = $/.from;
> say "Godzilla: Found at $loc!";
> %match_locs{ $godzilla_rx } = $loc;
> }
>
> But using a regex object as a hash key evidently doesn't work,
> it gives you the warning message:
>
> # Regex object coerced to string (please use .gist or .perl to do that)
>
> And what's worse is it coerces to an *empty list* which means *every*
> regex is treated as the same key.
>
> If you I follow the advice to use the *.perl, then that works, of course:
>
> %match_locs{ $godzilla_rx.perl } = $loc;
>
> But you wouldn't be able to use the keys of the hash as a regex
> object later, which seems sub-optimal, though not a concern for
> my present purposes.
The same thing happened with your Rutabaga object. It had a default
Str method that was called when you used it as a hash key. It didn't
really store the object in the key but just its .Str:
%vegeout.keys.any ~~ Rutabaga; # OUTPUT: «False»
%vegeout.keys.all ~~ Str; # OUTPUT: «True»
%vegeout.keys[0] === $obj; # OUTPUT: «False»
This is because Hash objects, by default, have Str(Any) keys, meaning
Str and coercing when required. If you want a Hash which allows any
kind of object as key, you have to declare it such:
my $obj = Rutabaga.new;
my %vegeout{Any}; # <-- see:
https://docs.raku.org/language/hashmap#Non-string_keys_(object_hash)
%vegeout{$obj} = "this works";
%vegeout.keys.all ~~ Rutabaga; # OUTPUT: «True»
%vegeout.keys[0] === $obj; # OUTPUT: «True»
This will also work with Regex objects.
Regards,
Tobias
--
"There's an old saying: Don't change anything... ever!" -- Mr. Monk