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

Hi Monks!

I am trying to call two subs at the same time at this particular time once I call this value "results" in my dispatch table code.
Is it possible and how can it be done? This is not working!

... my %general = ( data => sub { info( who=> $q->param('who') || '', why=> $q->param('why') || '', ) }, results => sub { names( first => $q->param('first'), zip => $q->param('zip'), ) }, sub { info( who => $q->param('who') || '', why => $q->param('why') || '', ) }, ); ...


Thank for looking!

Replies are listed 'Best First'.
Re: Call to subs in a Dispatch Table
by jeffa (Bishop) on May 06, 2015 at 19:41 UTC

    You should wrap the calls to your subroutines inside the SAME anonymous sub, like so:

    use strict; use warnings; use Data::Dumper; sub info { print Dumper \@_ }; sub names { print Dumper \@_ }; my %general = ( data => sub { info( who => 'data who', why => 'data why', ) }, results => sub { names( first => 'results first', zip => 'results zip', ); info( who => 'results who', why => 'results why', ); }, ); $general{data}->(); $general{results}->();

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Call to subs in a Dispatch Table
by Laurent_R (Canon) on May 07, 2015 at 22:13 UTC
    You could have the first subroutine call the second one (simpler solution, but perhaps not really what you need), or you could store store in the result entry of your hash a reference to an array of subroutines. Perhaps something like this (untested, because of insufficient information):
    my %general = ( data => sub { info( who=> $q->param('who') || '', why=> $q->param('why') || '', ) }, results => [ sub { names( first => $q->param('first'), zip => $q->param('zip'), ) }, sub { info( who => $q->param('who') || '', why => $q->param('why') || '', ) }, ] );

    Je suis Charlie.
Re: Call to subs in a Dispatch Table
by soonix (Chancellor) on May 08, 2015 at 11:50 UTC

    With "at the same time" you don't want to say "in parallel", do you?

    If you want to call the code from the "data" key, you can do so if you separate declaration from assignment, like this
    my %general; %general = ( ...
    then you can call it from "inside", like this:
    results => sub { names( first => $q->param('first'), zip => $q->param('zip'), ); $general{data}->(); },
    BEWARE this creates a circular reference, which probably won't be a problem here, but you should be aware of the fact.

    Update: OOPS! of course I didn't mean to call $general{results} - thanks AnomalousMonk - corrected

    Further Update: obviously, the interpreter is less strict than the manual: according to perlref I'm allowed to say &{$general{data}}() ("method 2") or $general{data}->() ("method 3", but when I tried it out before posting (with a simpler example), the syntax $general{data}() also worked. Perhaps this is a version specific thing (strawberry 5.14.2.1)

      ... this creates a circular reference, which probably won't be a problem ...

      It also creates a circular, i.e., infinite, execution loop, which probably will be a problem.

      c:\@Work\Perl\monks>perl -wMstrict -le "sub names { print qq{@_}; } ;; my %dispatch; %dispatch = ( circular => sub { names('fu', 'bar'); sleep 1; $dispatch{circular}->(); }, straight => sub { names('a', 'ok'); }, ); ;; $dispatch{straight}->(); $dispatch{circular}->(); " a ok fu bar fu bar fu bar fu bar Terminating on signal SIGINT(2)


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

      ... the interpreter is less strict than the manual... Perhaps this is ... version specific ...

      It is not version specific, as demonstrated by this example under ActiveState 5.8.9:

      c:\@Work\Perl>perl -wMstrict -le "print qq{perl version $]}; ;; my %hash = ( func => sub { print qq{hi $_[0]}; }, elem => [ 'fee', 'fie', 'foe', ], ); ;; $hash{func}('there'); $hash{func}->('sailor'); ;; print $hash{elem}[2]; print $hash{elem}->[1]; " perl version 5.008009 hi there hi sailor foe fie
      AFAIK, this is universal.

      As I mentioned in my /msg to you, I also thought the syntax  $general{data}() would not work. I'm sure this is discussed somewhere, but I haven't had the time yet to search it out. Basically, use of  -> (see The Arrow Operator in perlop) is only required at "top" level in a nested hash, array or code reference chain that's accessed initially by reference. That's because everything below the topmost level in a multi-dimensional structure must always be a reference of some kind (if it's not a simple string or number), and Perl implicitly understands this.


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