in reply to Re: Dynamic addressing in a hash
in thread Dynamic addressing in a hash

Hi hv.

I tried something similar but it ended up not referencing the actual element within the original hash. I see you have added an extra "next" operation to walk down the structure. Other responses have had a similar idea.

One question, hv: The // operator you use here:

$config->{$field} //= {};
The usual cheat-sheets list this only as similar to the bitwise || "or" operator. Please explain how you are using this here. The Camel book (4th Ed, p. 27) gives this example, though I've never seen this used:
$val ||= "2"; # Set $val to 2 if it isn't already "true".
which makes as much sense to me as *your* use of the // operator.

Please enlighten..

Thanks. (I waive consecutive translation. :-)

-- RP

Replies are listed 'Best First'.
Re^3: Dynamic addressing in a hash
by hv (Prior) on Sep 01, 2022 at 10:11 UTC

    One question, hv: The // operator you use here: $config->{$field} //= {}; ...

    It's a fair question, I glossed over some stuff there.

    The difference between || and // lies in what they are equivalent to: $a ||= $b is equivalent to $a = b unless $a, while $a //= $b is equivalent to $a = $b unless defined $a. In both cases the equivalence is exact, except that the expression for $a is evaluated only once.

    So that particular line says "initialize this value to an empty hashref if there is no defined value already there". But in essence, the line was actually a lazy shorthand for "insert your preferred error-handling behaviour here".

    The assumption is a) that there will never be a mismatch - you'll never have a string stored at $config{address} before trying to read or write $config{address}{virtual} - and b) that if for some reason a mismatch occurs, a fatal error is a good enough way to signal it.

    A tighter (and clearer) version might say something like:

    use Scalar::Util qw{ reftype }; $config->{$field} //= {}; die "invalid field '$field' at '$name'" unless reftype($config->{$fiel +d}) eq 'HASH';

    A looser, "just get it done" sort of approach might simply overwrite it:

    $config->{$field} = {} unless reftype($config->{$field}) eq 'HASH';

    Using $config->{$field} ||= {} would instead give you mixed behaviour - it will silently overwrite any value that's false in perl, like (0, 0.00, ""), but leave others to cause an error. For something like configuration values, it seemed unlikely to me that you would want to have it endemically treat those values differently from others.

    As AnomalousMonk says, this "defined-or" or "defaulting" operator // has been available since v5.10; since then, I find I use it far more often than I use ||.

      This is a STUNNING revelation, HV.

      Both hv and Lanx provided me with ideas that look quite promising, though I won't know until I test them myself.

      If I use the idea I will mention your "stage" name in the comments.

      Thanks MUCH!

      -- RP

Re^3: Dynamic addressing in a hash
by AnomalousMonk (Archbishop) on Sep 01, 2022 at 04:00 UTC
    $config->{$field} //= {};

    // is the Logical Defined-Or operator (see perlop), added with Perl version 5.10. So the example from the Camel book
        $val ||= "2"; # Set $val to 2 if it isn't already "true"
    exactly translates to
        $val //= "2"; # Set $val to "2" if $val isn't defined


    Give a man a fish:  <%-{-{-{-<