How do I declare a hash of hashes of numbers in Perl 6?

  • A+
Category:Languages

A hash, by default, converts all keys to strings. This causes issues when your keys are numbers which may be close:

> my %h; %h{1/3} = 1; %h{0.333333} = 2; dd %h; Hash %h = {"0.333333" => 2} 

This can, of course, be fixed as follows:

>  my %h{Real}; %h{1/3} = 1; %h{0.333333} = 2; dd %h; Hash[Any,Real] %h = (my Any %{Real} = 0.333333 => 2, <1/3> => 1) 

But now I need a hash of hashes of numbers, e.g. { 1/3 => { 2/3 => 1, 0.666667 => 2 } }.

> my %h{Real}; %h{1/3}{2/3} = 1; %h{1/3}{0.666667} = 2; dd %h; Hash[Any,Real] %h = (my Any %{Real} = <1/3> => ${"0.666667" => 2}) 

How do I fix that?

Best I can figure out is the following workaround:

> my %h{Real}; %h{1/3} //= my %{Real}; %h{1/3}{2/3} = 1; %h{1/3}{0.666667} = 2; dd %h; Hash[Any,Real] %h = (my Any %{Real} = <1/3> => $(my Any %{Real} = <2/3> => 1, 0.666667 => 2)) 

but that's just annoying.

 


The following works:

my Hash[Real,Real] %h{Real}; %h{1/3} .= new; %h{1/3}{2/3} = 1; 

Which is not great.


The following also works as a work-around.

my Hash[Real,Real] %h{Real}; %h does role {   method AT-KEY (|) is raw {     my /result = callsame;     result .= new unless defined result;     result   } }  %h{1/3}{2/3} = 1;  say %h{1/3}{2/3}; # 1 

If you have more than one such variable:

role Auto-Instantiate {   method AT-KEY (|) is raw {     my /result = callsame;     result .= new unless defined result;     result   } }  my Hash[Real,Real] %h{Real} does Auto-Instantiate; 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: