pc88mxer has asked for the wisdom of the Perl Monks concerning the following question:

Suppose %h is a HoH. Then @h{@a} is a hash slice. Is there a syntax for what is suggested by the (currently unrecognized) expression @h{@a}{@b}?

Code that computes what I'm trying to describe:

my @list; for my $a (@a) { for my $b (@b) { push(@list, $h{$a}{$b}); } } # return @list;
If not for a general list @b, how about if @b contains just a single element:

@h{@a}{$x}map { $_->{$x} } @h{@a}

Replies are listed 'Best First'.
Re: chained hash slices?
by ikegami (Patriarch) on Jun 03, 2008 at 05:06 UTC

    Nope, but what's wrong with

    map { @{$_}{@b} } @h{@a} map { $_->{$x} } @h{@a}
    They're both quite concise.
Re: chained hash slices?
by ysth (Canon) on Jun 03, 2008 at 07:15 UTC
    Expressions that read the double slice are easy to come by; aliases are harder. This seems to work though:
    @{ my $sub; my @refs = @h{@a}; do {$sub = sub { @refs ? $sub->(@_,@{po +p @refs}{@b}) : \@_ }}->() }
    I would love to hear how it could be simplified.
Re: chained hash slices?
by moritz (Cardinal) on Jun 03, 2008 at 06:11 UTC
    @h{@a} returns a list, so adding curly braces for slicing doesn't make sense at all:
    use strict; use warnings; use Data::Dumper; my %h = ( a => {b => 1}, c => {d => 2}, ); my @a = qw(a c); print Dumper @h{@a}; __END__ $VAR1 = { 'b' => 1 }; $VAR2 = { 'd' => 2 };

    If you want to slice that list, slice the indexing array instead:

    my %h = ( a => {b => 1}, c => {d => 2}, ); my @a = qw(a b c); print Dumper @h{@a[0, 2]};
      None of the following exist, so the result should be a list with 6 undef.
      • $h{a}{0}
      • $h{a}{2}
      • $h{b}{0}
      • $h{b}{2}
      • $h{c}{0}
      • $h{c}{2}
        So it seems the OP wants chained slice-dereferencing braces to calculate a cross product. That would be very unlike anything perl does at the moment.

        I don't see how @hash{@list}{@list} could work without being horribly magical, inconsistent and counter-intuitive. @hash{@list} returns a list of hash references, not a hash.

        If you want to change that, you'd have to invent a syntax like %hash{@list}, which merges all the hash refs into a single hash, which can be sliced in turn.

        And then you'd have to find a good way to deal with duplicates in the new hash.