Or broader: that the keys should be normalized (think NFKC()) before
usage?
Would it be easy to "delegate it to the hash"? (or use a hardly
noticeable wrapper)
--
Affijn, Ruud
"Gewoon is een tijger."
Dr.Ruud wrote:
> What would be the way to define-or-set that a specific hash has
> non-case-sensitive keys?
There are two things in this:
(1) The syntax to type the keys of a hash---too bad that I forgot it
and currently don't find it in the Synopsyses. Pointers welcome!
(2) A way to constrain a string to be case insensitive.
The latter could be nicely stated as
subset CaseInsensitive of Str where { .lc eq .uc }
but it actually is a constraint on the &infix:<eq>, not on
the strings. So I doubt that it works as expected. But then
I'm not sure if one can make subsets of operators at all:
subset CaseInsensitive of eq where { .lc eq .uc }
I guess you have to simply define CaseInsensitive as an alias---that is
an unconstraint subset---and overload &infix:<eq>. Then the hash
hopefully uses this operator when its key type is CaseInsensitive.
--
> Dr.Ruud wrote:
>
> > What would be the way to define-or-set that a specific hash has
> > non-case-sensitive keys?
>
> (2) A way to constrain a string to be case insensitive.
>
> subset CaseInsensitive of Str where { .lc eq .uc }
>
> but it actually is a constraint on the &infix:<eq>, not on
> the strings. So I doubt that it works as expected.
That depends on ones expectations! At best I'd expect that to be a set
of digits, symbols, and all the other characters which don't have
distinct upper- and lower-case forms.
> But then I'm not sure if one can make subsets of operators at all:
>
> subset CaseInsensitive of eq where { .lc eq .uc }
I wouldn't've thought so.
> I guess you have to simply define CaseInsensitive as an alias---that
> is an unconstraint subset---and overload &infix:<eq>. Then the hash
> hopefully uses this operator when its key type is CaseInsensitive.
But why would a hash be doing equality operations at all? Assuming that
a hash is implemented efficiently, as a hash, then it needs to be able
to map directly from a given key to its corresponding value, not to have
to compare the given key in turn against each of the stored keys to see
if they happen to match under some special meaning of eq.
You snipped Ruud's next bit:
> > Or broader: that the keys should be normalized (think NFKC()) before
> > usage?
That seems the obvious way to implement this, that all keys are
normalized (say with C<uc>, for this specific example) both on storage
and look-up. Then the main hashy bit doesn't have to change at all.
Many people have implemented such a thing using tied hashes in Perl 5.
So I guess you'd do the equivalent thing in Perl 6, whatever that is --
I've had a quick flick through the synposes and couldn't spot anywhere
that mentioned the obvious hooks for the Perl 5 C<FETCH> and C<RESTORE>
subs.
Smylers
>> What would be the way to define-or-set that a specific hash has
>> non-case-sensitive keys?
>
> There are two things in this:
> (1) The syntax to type the keys of a hash---too bad that I forgot it
> and currently don't find it in the Synopsyses. Pointers welcome!
> (2) A way to constrain a string to be case insensitive.
Yes, but also auto-normalization of incoming keys. Maybe like
Hash::Case::Preserve (=tie). Yes, maybe by an exception (on the type).
--
Groet, Ruud
Use a shaped hash with a key type that defines infix:<===> appropriately,
since object hashes are based on infix:<===> rather than infix:<eq>.
: Or broader: that the keys should be normalized (think NFKC()) before
: usage?
I think it would be up to the type to generate, transform to and/or
cache such a canonicalized key.
: Would it be easy to "delegate it to the hash"? (or use a hardly
: noticeable wrapper)
Probably--just give the hash a shape with a key type that is easily
coerced from the input types, I suspect. Hash keys could probably
afford to do an implicit .as(KeyType) even if the current language
were to disallow implicit conversions in general.
Larry
Smylers wrote:
> But why would a hash be doing equality operations at all?
I think it does so in the abstract. A concrete implementation
might use the .id method to get a hash value directly.
> Assuming that
> a hash is implemented efficiently, as a hash, then it needs to be able
> to map directly from a given key to its corresponding value, not to have
> to compare the given key in turn against each of the stored keys to see
> if they happen to match under some special meaning of eq.
>
> You snipped Ruud's next bit:
>
>
>>>Or broader: that the keys should be normalized (think NFKC()) before
>>>usage?
As $Larry pointed out, this all boils down to getting the key type
of the hash wired into the hash somehow. Assuming it dispatches on
the .id method the following might do:
class CaseInsensitive does Str
{
method id { self.uc.Str::id }
}
my %hash{CaseInsensitive};
As usual the compiler might optimize dynamic method lookup away
if the key type is known at compile time.
> That seems the obvious way to implement this, that all keys are
> normalized (say with C<uc>, for this specific example) both on storage
> and look-up. Then the main hashy bit doesn't have to change at all.
Yep. But the @Larry need to confirm that the Hash calls .id on strings
as well as on objects. Note that Array might rely on something similar
to access the numeric key. Then you could overload it e.g. to get a
modulo index:
class ModuloIndex does Int
{
method id { self % 10 }
}
my @array[ModuloIndex];
--
>> What would be the way to define-or-set that a specific hash has
>> non-case-sensitive keys?
>
> Use a shaped hash with a key type that defines infix:<===>
> appropriately, since object hashes are based on infix:<===> rather
> than infix:<eq>.
Suppose I want the keys to be Normalization-Form-C, and the values to be
regexes,
would this be the way to say that?
my Regex %hash{ NFC } ;
http://www.unicode.org/notes/tn5/
http://icu.sourceforge.net/
http://www.ibm.com/software/globalization/icu/
>> Or broader: that the keys should be normalized (think NFKC()) before
>> usage?
>
> I think it would be up to the type to generate, transform to and/or
> cache such a canonicalized key.
OK, alternatively "delegate it to the type".
>> Would it be easy to "delegate it to the hash"? (or use a hardly
>> noticeable wrapper)
>
> Probably--just give the hash a shape with a key type that is easily
> coerced from the input types, I suspect. Hash keys could probably
> afford to do an implicit .as(KeyType) even if the current language
> were to disallow implicit conversions in general.
Maybe not hash keys in general, but only hash keys of a type that needs
it. But wait, even stringification is coercion.