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

I'm playing with dispatch tables and below is the code that I have right now. My question is how do I run the subroutines for the 'action' hash reference?

Also, how do I pass arguments to these subroutines?
#!/usr/bin/perl use warnings; use strict; my @dispatch_tables = ( { regex => qr/\w+/, action => sub { print "aaa" }, }, { regex => qr/\d+/, action => &hello_me( @_ ), }, ); $dispatch_tables[0]->{action}; # Wrong! $dispatch_tables[1]->{action}->( "1", "2" ); # Wrong!
Thanks.

Replies are listed 'Best First'.
Re: Subroutines in Dispatch Tables
by rcaputo (Chaplain) on Sep 22, 2009 at 22:14 UTC
Re: Subroutines in Dispatch Tables
by Limbic~Region (Chancellor) on Sep 22, 2009 at 23:32 UTC
    Anonymous Monk,
    I may have missed it but I don't think anyone who has replied so far has pointed out that what you have really isn't a traditional dispatch table. Have a look at Implementing Dispatch Tables. In your approach, all dispatches have to be integer based (array) where as with a hash, you have the luxury of using any scalar value.

    Cheers - L~R

      In your approach, all dispatches have to be integer based (array) where as with a hash, you have the luxury of using any scalar value.

      The last bit should be "any string", not "any scalar value".

      And in his approach, all dispatches have to be regex-based, and that's rather more luxurious than any constant string.

      The cost is in speed. His dispatch takes O(N) to find the correct dispatch, not O(1).

      my $action; for my $dispatch (@$dispatch_tables) { my $regex = $dispatch->{regex}; if ($input =~ $regex) { $action = $dispatch->{action}; last; } } die("No match\n") if !$action; $action->($input);
        ikegami,
        Good catch on s/scalar/string/. I meant to add a line indicating that you could actually use just about anything you wanted as a hash key but that it would end up being stringified and unlikely do what you wanted.

        Regarding the luxury of using regexes - if your problem space fits a very specific model, you can still avoid the O(N) by using the technique outlined at Re: Massive regexp search and replace. With this particular implementation, I originally assumed that the idea was to loop over the regexes as you indicate with O(N) but then the usage in the example implied they index would be known. I probably read too much into it. Update: I should have said - either you are limited to integer dispatch values for O(1) or you will have to loop over the entire list O(N).

        Cheers - L~R

      Thanks for the link. I was doing a super search on dispatch table and found this link.

      This was quite close to what I wanted. A regex pattern with an associated action. And I read the link above and people were giving positive reviews on how this 'type' of dispatch table is being used.
Re: Subroutines in Dispatch Tables
by Anonymous Monk on Sep 22, 2009 at 23:10 UTC
    How about this line?
    action => sub { print "aaa" }, ... $dispatch_tables[0]->{action}; # Wrong!
    How can this be executed?
      #!/usr/bin/perl use warnings; use strict; my @dispatch_tables = ( { regex => qr/\w+/, action => sub { print "aaa\n" }, }, { regex => qr/\d+/, action => \&hello_me, }, ); $dispatch_tables[0]->{action}->(); $dispatch_tables[1]->{action}->( "1", "2" ); sub hello_me { print "hello me: @_\n"; } __END__ aaa hello me: 1 2
      Update: I guess it is obvious, but if you cycle down this action list running regex'es, the sub hello_me will not get executed because word chars are _a-z0-9 (all of the things can be in a Perl identifier). In other words all digits are "word characters".

      I don't know what the "full" application will be like but I would be thinking of using a couple of simple structures, this table being the simple "action" hash for a particular case. 'onlydigits' => sub {}, 'mixed_alphanum' => sub{}. There would another structure to decide what case/situation that you are in. Here it is obvious what the regex does, the actual app may not be so simple and an "extra" level of translation may provide some documentation value.

Re: Subroutines in Dispatch Tables
by Bloodnok (Vicar) on Sep 23, 2009 at 09:20 UTC
    I have been engaged on a couple of client sites whereby, simply for perceived clarity, the notation &{ $ptr->{val} }(...); has been preferred over $ptr->{val}->(...);.

    Merely an observation ...

    A user level that continues to overstate my experience :-))

      Both those forms are more complex than they need be:

      $h{test} = sub{ print 'hi' };; $h{test}();; $p = \%h;; $p->{test}();; hi

      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.
        Indeed.

        However, there's a bit of information I haven't ('til now) divulged: In (AFAIR) both cases, despite the extensive use perl, the average perl 'reading age' was extremely low - typified by the lack ('til I introduced them) of dispatch tables anywhere (in matter of fact, the almost complete absence of other than the most simple of lookup tables) - I even encountered hashes keyed on sequential integers !!

        Having introduced them [dispatch tables] and using calls of the form you exemplify, the code was considered unreadable by virtue of the implication of the use of parentheses.

        However, they were eventually to adopt the structure - the final persuasive factor was the use of the form &{ ... }(...), which, they considered, would facilitate the readability of the code - since the fact that a call was being made (via a dispatch table) became explicit/obvious ... certainly to the reader of low perl 'reading age'.

        A user level that continues to overstate my experience :-))
Re: Subroutines in Dispatch Tables
by bichonfrise74 (Vicar) on Sep 22, 2009 at 22:28 UTC
    Oops... This is not correct.

    How about something like this?
    action => sub { print "aaa" },
    to
    action => \&{ print "aaa" },
      >perl -wMstrict -e "my $cr = \&{ print 'aaa' }; $cr->();" Undefined subroutine &main::1 called at -e line 1. aaa