in reply to Re: A dispatch table to match named params of a sub
in thread A dispatch table to match named params of a sub

The trouble with dereferencing: $sub{t01}{name}(@{$sub{t01}{args}});, is that all my other subs take a single argument, their dispatch entry looks like:

{ name => \&mysub, arg => "some string" }

So I have this one snowflake-of-a-sub that wants named params :( How can handle this exception elegantly?

Neil Watson
watson-wilson.ca

Replies are listed 'Best First'.
Re^3: A dispatch table to match named params of a sub
by roboticus (Chancellor) on Jun 29, 2015 at 16:51 UTC

    nielwatson:

    That shouldn't be a problem: Just put all arguments in your dispatch has in arrayrefs, and when they're unwrapped, they'll be simple positional parameters. Having one is just fine. It's probably the most general form, as you can also pass an array of arguments, too, so you get it all: single arguments, multiple arguments, arrays, hashes and named arguments (hashes!).

    $ cat sploot.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use Test::More; my %sub = ( t01=>{ name=>\&mine, args=>[qw/one first two second/] }, t02=>{ name=>\&yours, args=>[ 'foo' ] }, t03=>{ name=>\&ours, args=>[qw/The quick red fox/] }, ); for my $T (keys %sub) { $sub{$T}->{name}->(@{$sub{$T}{args}}); } done_testing; sub mine { # named arguments example my %args = @_; ok( $args{one} eq 'first', 'arg one' ); ok( $args{two} eq 'second', 'arg two' ); } sub yours { # single argument example my $message = shift; ok( $message eq 'foo', 'A single argument' ); } sub ours { # array example my @args = @_; ok( "The quick red fox" eq join(" ", @args), 'Argument array' ); } Roboticus@Waubli ~ $ perl sploot.pl ok 1 - Argument array ok 2 - A single argument ok 3 - arg one ok 4 - arg two 1..4

    Update: Added array example & text

    ...roboticus

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

Re^3: A dispatch table to match named params of a sub
by roboticus (Chancellor) on Jun 29, 2015 at 17:04 UTC

    nielwatson:

    Note: I posted this as a separate reply to prevent it from getting tangled up in the update above.

    Since all your other subroutines take a single argument, you could also pass in an arrayref (as you currently do) and expand it into a hash inside the subroutine, *or* pass in a hashref and use it directly:

    $ cat sploot2.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use Test::More; my %sub = ( t01=>{ name=>\&mine, args=>[qw/one first two second/] }, t02=>{ name=>\&mine2, args=>{qw/one first two second/} }, ); for my $T (keys %sub) { $sub{$T}->{name}->($sub{$T}{args}); } done_testing; sub mine { # named arguments example my %args = @{$_[0]}; ok( $args{one} eq 'first', 'arg one' ); ok( $args{two} eq 'second', 'arg two' ); } sub mine2 { # named arguments example my $args = shift; ok( $args->{one} eq 'first', 'arg one (b)' ); ok( $args->{two} eq 'second', 'arg two (b)' ); } Roboticus@Waubli ~ $ perl sploot2.pl ok 1 - arg one (b) ok 2 - arg two (b) ok 3 - arg one ok 4 - arg two 1..4

    ...roboticus

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