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

It is humiliating to constantly live with your dreams 2 steps further away than your skill set.
I have a working simple "compute a weighted average over time periods" program written and tested. Now it must grow to handle:
  • an arbitrary number of independent data streams.
  • live in threads::shared space (why no OO or modules used)

    I am attempting to create a shared hash, with each keyed member containing scalars for period start, period end, period total; and an array of decay stages. The initialization currently does not cause any error messages:

    our %WA: shared; our $WAlock: shared; ... my ($key, $dtg, $bytes) = @_; if (!defined $WA{$key}) { { lock $WAlock; $WA{$key} = &share({}); #hook shared anon hash; { lock $WA{$key}; $WA{$key}{PS}=$dtg; # PS period Start $WA{$key}{PE}=$dtg + $secs; # PE period End $WA{$key}{PT}=0; # PT period Total $WA{$key}{stgs} =(); # list of decaying values for my $i (0..$rnds-1){ $WA{$key}{stags}[$i]=0; # init all stages to 0 } } } } # end of (! defined) entry being initialized
    Clean compile does not mean this really does what I want.

    The problem is when I attempt to do some array manipulations (unshift) on the set of decay stages. Here I am trying (unsuccessfully) to address the array for the 'unshift' command.

    sub reportWA{ # $key my $key = shift; my $NewWA; unshift @{WA{$key}{stags}}, $WA{$key}{PT}; #insert PT at [0] -line +110 $NewWA=$WA{$key}{PT}; # $periodTotal * 1 $#{@{WA{$key}{stags}}} = $rnds-1; # truncate off oldest stage for my $i (1..$rnds-1){ ${WA{$key}{stags}}[$i] *= $wght; #stag[n] = initial * (wght**n) $NewWA += ${WA{$key}{stags}}[$i]; } #plog sprintf "stages = %s" ,join (", ",@stags); $NewWA /= $rnds; printf " %d %d %8.2f %s\n" , $key,$WA{$key}{PE} ,$NewWA, join (", ",@{WA{$key}{stags}}); } ------- Errors generated start with these : Scalar value @{WA{$key} better written as ${WA{$key} at ThWgtAvg1.pl l +ine 110. Useless use of unshift with no values at ThWgtAvg1.pl line 110. Scalar value @{WA{$key} better written as ${WA{$key} at ThWgtAvg1.pl l +ine 113. Scalar value @{WA{$key} better written as ${WA{$key} at ThWgtAvg1.pl l +ine 121. Type of arg 1 to unshift must be array (not hash slice) at ThWgtAvg1.p +l line 110, near "}{stags" syntax error at ThWgtAvg1.pl line 110, near "}{stags" ...
    So ... I am lost the forest of braces and brackets... How do I code access to that 'stags' list? <<bow>>
  • Replies are listed 'Best First'.
    Re: Referencing an array in a complex hashed data structure
    by kyle (Abbot) on Dec 08, 2008 at 19:48 UTC

      See here: "$#{@{WA{$key}{stags}}} = $rnds-1;".

      I think Perl is complaining about the "$" missing before "WA", but I think that expression really should read "$#{$WA{$key}{stags}} = $rnds-1;". A similar problem appears in your unshift line. See References quick reference.

    Re: Referencing an array in a complex hashed data structure
    by GrandFather (Saint) on Dec 08, 2008 at 19:51 UTC

      Wherever you have {WA{ replace it with {$WA{.

      You can clean up code like this a lot if you create a temporary variable:

      sub reportWA{ # $key my $key = shift; my $NewWA; my $stags = $WA{$key}{stags}; unshift @$stags, $WA{$key}{PT}; #insert PT at [0] -line 110 $NewWA=$WA{$key}{PT}; # $periodTotal * 1 $#$stags = $rnds-1; # truncate off oldest stage for my $i (1..$rnds-1){ $stags->[$i] *= 10; #stag[n] = initial * (wght**n) $NewWA += $stags->[$i]; } $NewWA /= $rnds; printf " %d %d %8.2f %s\n" , $key,$WA{$key}{PE} ,$NewWA, join (", ",@$stags); }

      Perl's payment curve coincides with its learning curve.
    Re: Referencing an array in a complex hashed data structure
    by kennethk (Abbot) on Dec 08, 2008 at 19:45 UTC

      I think you should probably change $WA{$key}{stgs} =(); to $WA{$key}{stags} =[];, i.e. setting stags to a array_ref and using the same key as your initialization (stags in place of stgs).

      As well, in place of unshift @{WA{$key}{stags}} you should have unshift @{$WA{$key}{stags}}, repeating that change in the following lines.

        Thanks;
        I gave that a try and it produced a run-time message of:
        Invalid value for shared scalar at ThWgtAvg1.pl line 73, <IPT> line 1.

        but "= &share([]);" did work.
        I had a problem with that 2 years ago.. I was told it was a prototyping thing..

    Re: Referencing an array in a complex hashed data structure
    by BrowserUk (Patriarch) on Dec 08, 2008 at 20:00 UTC
      So ... I am lost the forest of braces and brackets...

      Then for goodness sake, use some horizontal whitespace!. Ie. spaces.

      The only place you've used any is between the function name join, and its open paren where is is completely useless as the paren forms a natural delimiter!

      The same snippet with some added makes it easy to see the problems:

      sub reportWA{ # $key my $key = shift; my $NewWA; unshift @{ WA{ $key }{ stags } }, $WA{$key}{PT}; unshift @{ $WA{ $key }{ stags } }, $WA{$key}{PT}; $NewWA = $WA{ $key }{ PT }; $#{ @{ WA{ $key }{ stags } } } = $rnds-1; for my $i ( 1 .. $rnds -1 ){ ${ WA{ $key }{ stags } }[ $i ] *= $wght; $NewWA += ${ WA{ $key }{ stags } }[ $i ]; } #plog sprintf "stages = %s" ,join (", ",@stags); $NewWA /= $rnds; printf " %d %d %8.2f %s\n" , $key, $WA{ $key }{ PE }, $NewWA, join( ", ", @{ WA{ $key }{ stags } } ); }

      The same with the errors highlighted:

      sub reportWA{ # $key my $key = shift; my $NewWA; unshift @{ $WA{ $key }{ stags } }, $WA{$key}{PT}; #............^ $NewWA = $WA{ $key }{ PT }; $#{ @{ WA{ $key }{ stags } } } = $rnds-1; #........^ ......missing $ for my $i (1..$rnds-1){ ${ WA{ $key }{ stags } }[ $i ] *= $wght; #......^...missing $ $NewWA += ${ WA{ $key }{ stags } }[ $i ]; #................^..........missing $ } #plog sprintf "stages = %s" ,join (", ",@stags); $NewWA /= $rnds; printf " %d %d %8.2f %s\n" , $key, $WA{ $key }{ PE }, $NewWA, join( ", ", @{ WA{ $key }{ stags } } ); #.............................^......missing $ }

      There may be more errors, but once you fixed those, there'll be less noise from the compiler that should allow you to see what's going on.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        There was another run-time error. But for closure, the program is executing and I am listing the end result below.

        The key was realizing the the anon array was really a reference to an anon array, which clicked in the dereference mode of thought ...

        if (!defined $WA{$key}) { { lock $WAlock; $WA{$key} = &share({}); #hook shared anon hash; { lock %{$WA{$key}}; $WA{$key}{PS}=$dtg; # PS period Start $WA{$key}{PE}=$dtg + $secs; # PE period End $WA{$key}{PT}=0; # PT period Total $WA{$key}{stags} = &share([]); for my $i (0..$rnds-1){ ${$WA{$key}{stags}}[$i]=0; # init all stages to 0 } } } } # end of (! defined) entry being initialized .... and ..... sub reportWA{ # $key my $key = shift; my $NewWA; unshift @{$WA{$key}{stags}}, $WA{$key}{PT}; $NewWA=$WA{$key}{PT}; # $periodTotal * 1 $#{$WA{$key}{stags}} = $rnds-1; for my $i (1..$rnds-1){ ${WA{$key}{stags}}[$i] *= $wght; #stg[n] = initial * (wght**n) $NewWA += ${WA{$key}{stags}}[$i]; } #plog sprintf "stages = %s" ,join (", ",@stgs); $NewWA /= $rnds; printf " %d %d %8.2f %s\n" , $key,$WA{$key}{PE} ,$NewWA, join (", ",@{$WA{$key}{stags}}); }
        Thank you all, and the speed was amazing..