> 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)
That's an interesting detail, I didn't get that that behavior wasn't
the default. Thanks much.
On 4/5/20, Tobias Boege <[email protected]> wrote:
> 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
>