Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multidimensional Hash Elements in Perl6

Tags:

hash

raku

I'm trying to assign hash variables in Perl6 as I would have in Perl. As I'm reading through a file, I take in certain elements and assign to a hash thus:

%key<$barcode><$position> = $sample-id

where in Perl5 this would have been

$key{$barcode}{$position} = $sample_id

I can print the hash assignments after I do so, so I think that the assignment is working.

When I print this hash with

say %key.perl;

this only gives

{"\$barcode" => ${"\$position" => "ZZ12345"}}

How can I print out this multidimensional hash like Perl5's Data::Dumper or DDP https://metacpan.org/pod/Data::Printer because say %key.perl doesn't seem to work for multidimensional hashes?

like image 924
con Avatar asked Jan 22 '19 16:01

con


2 Answers

<> is the same as {''} in perl5 so should only be used for string keys. If you want to use the variable names go with :

%key{$barcode}{$position} = $sample_id this should do the trick.

You can also use the double pointy brace option which does string interpolation.

%key<<$barcode>><<$position>> = $sample_id

like image 141
Scimon Proctor Avatar answered Nov 06 '22 01:11

Scimon Proctor


You misunderstood the Perl 6 language. (Which is understandable, and not the first time)

Below is an abridged history lesson of the feature you were trying to use.


In Perl 5 you didn't have to quote the key if the only thing between {} was a bare-word.

use v5.12;

my %hash;
$hash{fubar} = 'abc';
# $hash{'fubar'} = 'abc';

say qq'"@{[ $hash{fubar} ]}"';
# "abc"

That was a special-case, and one of the goals of the Perl 6 design is to have as few special-cases as possible. So the following does not work in Perl 6.

use v6.d;

my %hash;
%hash{fubar} = 'abc';
# %hash{ fubar() } = 'abc';

say qq'"%hash{fubar}"';
# say qq'"%hash{ fubar() }"';
===SORRY!=== Error while compiling ./test.p6
Undeclared routine:
    fubar used at lines 4, 7

That error means it failed to even compile.


There is a feature for quote words in both Perl languages.

use v5;
my @array = qw< a b c d >;
use v6;
my @array = qw< a b c d >;

In Perl 6 that can be shortened to

use v6;
my @array =   < a b c d >;

qw is really short for Q :q :w / Q :single :words in Perl 6. Which is enable single-quote behaviour and enable splitting into words. (split on whitespace)
(<> works because the infix operator < is not expected there.)

To make up for the automatic bareword quoting between {} which was not copied over, postcircumfix <> was added. It combines both of the qw and {} features.

use v6;
my %hash;

%hash{qw< foo bar baz >};
%hash{  < foo bar baz >};
%hash<    foo bar baz >;  # <---

There is an additional more advanced quotewords feature in Perl 6

use v6;
my $a = 'a b "c d"';

say qqww<< $a e f 'g h ' '$a'>>.perl;
say     << $a e f 'g h ' '$a'>>.perl;
say     «  $a e f 'g h ' '$a' ».perl;
# All 3 are exactly equivalent
# ("a", "b", "c d", "e", "f", "g h ", "\$a")

qqww is short for Q :qq :ww / Q :double :quotewords. Which is enable double-quote behaviour and enable quote-word-splitting.

The :double is what enables interpolation of $a.
:quotewords splits up words on spaces, but also allows quotes to control where things get split up.
(Note that :quotewords happens last)

(qqw and qww also work, but there is no shortened way to write them.)

There is also a postcircumfix <<>> / «».

use v6;
my %hash;
my $a = 'a b "c d "';

%hash{<< $a e f 'g h ' '$a' >>};
%hash<<  $a e f 'g h ' '$a' >>;
%hash«   $a e f 'g h ' '$a'  »;

# All 3 are exactly equivalent to
%hash{'a', 'b', 'c d ', 'e', 'f', 'g h ', '$a'};
#               ^^^^^^            ^^^^^^

This sort-of makes it so that postfix <> is less of a special case.


The reason that a lot of examples use %hash<fubar> is that it is idiomatic Perl 6.
Perhaps it should be seen as a more advanced feature in the docs and have reduced usage, because you are by far not the first person to make this mistake.

like image 2
Brad Gilbert Avatar answered Nov 06 '22 03:11

Brad Gilbert