Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

How to pass a variable to function selected from a hash

by cat2014 (Monk)
on Jan 18, 2001 at 04:12 UTC ( #52644=perlquestion: print w/replies, xml ) Need Help??
cat2014 has asked for the wisdom of the Perl Monks concerning the following question:

I'll start by saying that I have absolutely no idea what this thing that I'm calling a decision hash actually is. That aside, I've got a hash constructed which has strings as keys & function calls as values. I'm using it as a case statement- calling the hash with some value that will match a key so that a function will be run on the input that I'm providing.

My problem is with how to get something to be passed into the selected function. It looks like whatever i pass in is turned into "1" -but you can return whatever you want. Am I totally wasting my time getting this to work, or is there actually someway to set up a hash to have a value passed in & run a function on it?

the program:

#!/usr/bin/perl -w use strict; use Data::Dumper; &main; sub main{ my $i = "x"; my @choices = ("a", "b", "c"); my %decision_hash = (a => \&mirror_input, b => \&return_reference, c => \&do_stuff); foreach my $case(@choices) { my @results = &{$decision_hash{$case}}($i); print "$case:"; print Dumper(@results); } } sub mirror_input { my $input = @_; print "input:"; print Dumper($input); print "\n"; return $input; } sub return_reference { my $input = @_; my %temp; $temp{1} = ["z", "x", "y"]; $temp{2} = ["s", "d", "f"]; return \%temp; } sub do_stuff { my $input = @_; my $new = "something new"; return ($new); }

here is the output:

input:$VAR1 = 1; a:$VAR1 = 1; b:$VAR1 = { 1 => [ 'z', 'x', 'y' ], 2 => [ 's', 'd', 'f' ] }; c:$VAR1 = 'something new';

I'm *really* hoping that someone will just tell me that i'm overlooking something incredibly obvious here.

Replies are listed 'Best First'.
Re: How to pass a variable to function selected from a hash
by eg (Friar) on Jan 18, 2001 at 04:22 UTC

    In your subroutines,

    my $input = @_;

    should be something like

    my $input = shift();

    The way you're doing it, you're looking at the array @_ in scalar context, which, of course, returns the number of elements in the array.

      You can also do:

      my ($input) = @_;

      I use shift, myself though, when I'm sure there's but one argument.

      Philosophy can be made out of anything. Or less -- Jerry A. Fodor

      Sweet! That works- thank you!

      I'd always been told that shifting off my input was a Bad Horrible Not Good thing to do, but I guess that in this case, this is better.

        Who told you that? I certainly do not agree that that is true in general.

        Using shift to handle fixed arguments is a standard idiom in Perl. It sometimes not the clearest way to express yourself, but avoiding is not always better either. Use it when it fits. Sometimes that is a matter of taste. In this case I would use it.

        For more on what bit you, see Arrays are not lists.

        For your actual problem you may be glad to find out that there is no need to actually name your handler functions. Just use sub to declare them. When combined with closures (as explained in perlref) this leads to some powerful programming techniques which are as different from standard procedural and OO programing as they are from each other. For more on that I recommend some of my posts that touch on functional techniques (a couple of which are on my home node) and visiting MJD's site and looking around.

        I would just like to mention that the way to first encounter functional programming is not how I did it. I was told to find out why a several-hundred line program was slow. I spent a good chunk of a day reading something written by a tired programmer in a hurry. When I finally figuring out that a key step was the line that read:

        print join ",", map { &{$field_info{$_}{format}}($deal) } @fields;
        I was far from pleased. And even though I have since learned to like the technique and use it, I make sure that anyone who will have to read my code gets a much gentler introduction to how it works. :-)

        BTW I was successful in speeding the program up. In fact there is a significant performance mistake in the above line. Given that $deal is a data structure and we are looping over a set of deals, what improvement can you find?

Re: How to pass a variable to function selected from a hash
by chipmunk (Parson) on Jan 18, 2001 at 04:42 UTC
    By the way, as an alternative to &{$subref}(@args), you might like this syntax:
    $subref->(@args); # or, for a subref in a hash: $hash{key}->(@args); # in 5.6, you can even leave out the -> if you want: $hash{key}(@args);
Re: How to pass a variable to function selected from a hash
by arturo (Vicar) on Jan 18, 2001 at 04:34 UTC

    Ugly solution, off the top of my head. I hate myself for proposing this. I hope someone will save us from:

    Define a global (or file-level my variable), $val, have each sub do my $arg = $val ... ?

    There's got to be a better way though =)

    Update Oh, OK. I thought the problem was that the args weren't being passed to the coderefs at all =) Nothing to see, move along ... I'll feel foolish either way =)

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://52644]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2017-02-21 13:32 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (310 votes). Check out past polls.