## Hashes ##------- # Hashes are like an unordered arrays, where each value is associated # with a string (known as a key), rather than a positional index. # Hashes use the % sigil and are created by enumerating pairs of keys and # values. my %person = name => 'Andreas', lastname => 'Stoa', age => 41; say %person{'name'}; # accessing an element %person{'age'} = 25; # updating the value of an element %person{'country'} = 'Greece'; # adding a new pair # All values of a hash can have type constraints. my Int %binaries = zero => 0, one => 1; my %booleans of Bool = t => True, f => False; # similar thing # The keys of a hash can also have type constraints. my %doubles{Int} of Int; # constraining both keys and values say %doubles{21} = 42; ## Some methods ##------------- my %natural-satellites = ( # during assignment, pairs can be sorrounded by parens mercury => 0, jupiter => 79, venus => 0, saturn => 62, earth => 1, nepture => 14, mars => 2, uranus => 27 ); # `keys` - returns a list of keys of the hash. my @planets = %natural-satellites.keys; say @planets; # (earth uranus nepture saturn venus mercury jupiter mars) # `values` - returns a list of values of the hash. my @satellites = %natural-satellites.values; say @satellites; # (1 27 14 62 0 0 79 2) # `kv` - returns a list of both keys and values. say %natural-satellites.kv; # (earth 1 uranus 27 nepture 14 saturn 62 venus 0 # mercury 0 jupiter 79 mars 2) # `pairs` - returns a list of pairs (key/value). say %natural-satellites.pairs; # (earth => 1 uranus => 27 nepture => 14 # saturn => 62 venus => 0 mercury => 0 # jupiter => 79 mars => 2) # `antipairs` - returns a list of inverted pairs (value/key). say %natural-satellites.antipairs; # (1 => earth 27 => uranus 14 => nepture # 62 => saturn 0 => venus 0 => mercury # 79 => jupiter 2 => mars) # `elems` - returns number of pairs in the hash. say %natural-satellites.elems; # 8 ## Hash comphrehensions ##--------------------- my @numbers = 1, 2, 3, 4, 5; my @letters = <A B C D E>; # Postfix form of for and blocks can be combined to make list comphrehensions. my %square-nums = %( {$_ => $_**2} for @numbers ); # %() is an alternative way of # creating a hash. say %square-nums; # {1 => 1, 2 => 4, 3 => 9, 4 => 16, 5 => 25} # Conditionals can be applied too. my %square-even-nums = %( {$_ => $_**2} if $_ %% 2 for @numbers ); my %square-even-nums = %( {$_ => $_**2} if $_ !%% 2 for @numbers ); say %square-even-nums; # {2 => 4, 4 => 16} say %square-odd-nums; # {1 => 1, 3 => 9, 5 => 25} # To obtain a one-to-correspondence, use the zip operator `Z`. my @letters-nums = %( {$_[0] => $_[1]} for @letters Z @numbers ); say @letters-nums; # {A => 1, B => 2, C => 3, D => 4, E => 5} # Or using the flat function. my @letters-nums1 = %( flat @letters Z @numbers ); say @letters-nums1; # {A => 1, B => 2, C => 3, D => 4, E => 5} ## bag union my $a = bag <a a a b b c>; my $b = bag <a b b b>; say $a (|) $b; say $a (&) $b; say $a (+) $b; say $a (.) $b; ## bags my %words := Bag.new(slurp.comb(/\w+/).map(*.lc)); say "%words{}"; ## count words my %words; for slurp.comb(/\w+/).map(*.lc) -> $word { %words{$word}++; } for %words.pairs.sort(-*.value).map({ $_.key, $_.value }) -> $word, $count { say "$word: $count"; } ## 散列 my %dev = 'pugs'=>'audreyt', 'pct'=>'pm', "STD"=>'larry'; my %same_dev = :rakudo('jnthn'), :testsuite('moritz'); # adverb (pair) syntax works as well my %too_dev = ('audreyt', 'pugs', 'pm', 'pct', 'larry', "STD"); # lists get autoconverted in hash context my %compiler = Parrot => {Rakudo => 'jnthn'}, SMOP => {Mildew => 'ruoso'}; # hash of hashes (HoH) say %dev.perl; say %same_dev.perl; say %too_dev.perl; say %compiler.perl; # Hash Slices my $name='pugs'; my $value = %dev{'pugs'}; # just give me the value related to that key, like in P5 my $value1 = %dev<STD>; # <> autoquotes like qw() in P5 my $value2 = %dev<<$name>>; # same thing, just with eval say $value; say $value2; my @values = %dev{'pugs', 'STD'}; my @values2 = %dev<pugs STD>; my @values3 = %dev<<pugs STD $name>>; say @values; say @values2; say @values3; say %compiler<Parrot><Rakudo>; # value in a HoH, returns 'jnthn' say %compiler<SMOP>; # returns the Pair: Mildew => 'ruoso' # %dev {'audrey'}; # error, spaces between varname and braces (postcircumfix operator) are no longer allowed say %dev\ {'pugs'}; # works, quote the space # %dev .<dukeleto>; # error say %dev\ .{'pugs'}; # works too, "long dot style", because its its an object in truth say %dev.{'pugs'}; # Hash Methods say 'this hash has some pairs' if ? %dev; # bool context, true if hash has any pairs say 'this hash has '~ + %dev ~' pairs'; # numeric context, returns number of pairs(keys) say ~ %dev; # string context, nicely formatted 2 column table using \t and \n my $table = %dev; # same as ~ %dev say $table; # ("pugs" => "audreyt", "pct" => "pm", "STD" => "larry").hash say %dev.say; # stringified, but only $key and $value are separated by \t #("pugs" => "audreyt", "pct" => "pm", "STD" => "larry").hash my @pairs = %dev; # list of all containing pairs say @pairs; # "pugs" => "audreyt" "pct" => "pm" "STD" => "larry" say %dev.pairs; # same thing in all context # "pugs" => "audreyt" "pct" => "pm" "STD" => "larry" say %dev.elems; # same as + %dev or + %dev.pairs # 3 say %dev.keys; # returns the list with all keys say %dev.values; # list of all values say %dev.kv; # flat list with key1, value1, key 2 ... say %dev.invert; # reverse all key => value relations say %dev.push(@pairs); # inserts a list of pairs, if a key is already present in %dev, both values gets added to an array # ("pugs" => ["audreyt", "audreyt"], "pct" => ["pm", "pm"], "STD" => ["larry", "larry"]).hash my @another_pairs='Rakudo'=>'Perl6'; say %same_dev.push(@another_pairs); ## key-of # You can also destructure hashes (and classes, which you'll learn about later !) # The syntax is basically `%hash-name (:key($variable-to-store-value-in))`. # The hash can stay anonymous if you only need the values you extracted. sub key-of(% (:value($val), :qua($qua))) { say "Got val $val, $qua times."; } # Then call it with a hash: (you need to keep the brackets for it to be a hash) key-of({value => 'foo', qua => 1}); my %hash = value => 'Perl6', qua => '2016'; key-of(%hash); # the same (for an equivalent `%hash`); ## pick 和 roll my $bag = bag "red" => 2, "blue" => 10; say $bag.roll(10); # 随机生成 10 组 say $bag.pick(*).join("\n"); $bag = bag "red" => 20000000000000000001, "blue" => 100000000000000000000; say $bag.roll(10); say $bag.pick(10).join(" "); ## 切片 # Semilists are semicolon lists my %hash = a => {b => 2, c => 4}; say %hash{"a"}{"b"}.perl; # 2 say %hash{"a";"b"}.perl; # (2,) my @sliceable = [[ ^10 ], ['a'..'h'], ['Ⅰ'..'Ⅺ']]; say @sliceable[ ^3; 4..6 ]; ## SetHash my $haԭ = SetHash.new(); $haԭ{'a'} = True; say $haԭ, " in a ", $haԭ.^name;