develooper Front page | perl.perl6.users | Postings from April 2020

Re: regex objects as hash keys

Thread Previous | Thread Next
From:
Joseph Brenner
Date:
April 6, 2020 05:20
Subject:
Re: regex objects as hash keys
Message ID:
CAFfgvXU8ff-xHp-5EtzapzwcmFT2BVUJvukRQ9g=Cje8meFhhg@mail.gmail.com
> 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 <tobs@taboege.de> 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
>

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About