in reply to Data structure / hash reference question

hperange:

I generally avoid that practice, as it's easy to get confused. Sometimes I want a shorthand variable for a member, like color, but also want to use the hashref, too. In that case, I normally have two variables $rColor and $color, where $rColor is the reference. This keeps them visually distinct, but related (to me, anyway). If I wasn't using the reference, I'd avoid the issue altogether by making a subroutine that simply returned the color:

$class = '...'; $color = color_of($class); sub color_of { $class = shift; my $t = first { $class =~ /$_->{'re'}/ } @rules; return $color->{'color'}; }

Having said all that, it really depends on usage. I occasionally find it more convenient to reuse the variable. In limited scope, it can often be clear and obvious enough to not warrant the extra effort:

for my $foo (...) { my $color = first { $class =~ /$_->{'re'}/ } @rules; $color = $color->{'color'}; ... }

With this bit, I'm setting up the variable at the top of the loop, so it's clear (to me) that the first line is simply an interim step. If the for body were longer, and I switched between the hash version and scalar version, it would be confusing. In this case, it would be nice if there were a simple way to do it in one go, like:

my $color = ${first { $class =~ /$_->{'re'}/ } @rules}->{'color'};

But if it exists, then I haven't found it.

...roboticus

When your only tool is a hammer, all problems look like your thumb.

Replies are listed 'Best First'.
Re^2: Data structure / hash reference question
by stevieb (Canon) on Apr 21, 2012 at 14:36 UTC

    You were close :)

    my $class = 'regex1'; my $color = ( first { $class =~ /$_->{'re'}/ } @rules )->{ color }; + print "$color\n";

      stevieb:

      You'd think that as long as I've been toying around with perl, I'd've figured it out or stumbled across it by now.

      I tried several "obvious" things, none of which worked:

      $color = ${ ... }->{color}; $color = $${ ... }->{color}; $color = ${%{ ... }}{color};

      The parenthesis are a surprise to me, but I'm glad it's possible to avoid the two-step!

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

        I love learning new things :)

        If I recall correctly, I found the basis for this trick years ago after figuring there must be a simpler way to do this:

        # want fourth word my $str = "one two three four five"; my @array = split / /, $str; my $word = $array[3];

        I monkeyed about and accidentally came up with this:

        my $str = "one two three four five"; my $word = ( split / /, $str )[3];

        Combined with my current knowledge of refs and anonymous data and where they are handy, I revisited the parens and came to the conclusion that the value after the expression is evaluated within the parens can be operated on directly.

        You were close with the first one - you just didn't need the dereferencing arrow ->. This should work:

        $color = ${ ... }{color};

        Why? Because if ... is a hashref, then %{...} is a plain old hash.

        If our hash was called %foo then we'd access a value in it as $foo{color} - that is, change the sigil from % to $, and add the key in curlies. Our hash is called %{...} but we can still use the same technique.

        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Thanks, this works :)