Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

call subroutines via hash

by fortesque (Acolyte)
on Jan 04, 2006 at 20:51 UTC ( [id://521012]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks:

I have been trying various ways to call multiple subroutines(windows XP, OS) (I'm writing a Tk program that has serveral hundred Tk callbacks) and so far have been unsuccessful. I'm a beginner and my Perl knowledge is limited, and more mechanical than intuitive.

The following experimental code calls only the first subroutine not the second.
It seems to recognize both subroutines but executes only the first one.

Can anyone help me figure out how to get the code to call the second subroutine as well?

Both subroutines work when run as standard named routines and not part of a hash.


Thanks

JWB
#!/usr/local/bin/perl use warnings; my $key; my $dispatch; my %dispatch = ( "foo" => sub { my $x = 3; my $ans = ($x**2); print "answer is: $ans \n"; #prints "answer is: 9" }, "moo" => sub { my @data = (3,7,15,28); my $radius; my $radius_ref = @data; foreach $radius(@$radius_ref) { print "my radius is: $radius \n"; my $area = 3.14159 * ( $radius ** 2); print "and circle area is $area \n"; } } ); #Perl PCB 5.2 reference my $input; foreach $input("foo", "moo"){ if ( exists ${dispatch}{ $input } ) { ${dispatch} {$input}( ); print "$input is the answer.\n"; } else { die "Cannot find the subroutine $input\n"; } }
#when code is run, "the answer is 9" is printed along with "moo is the answer" and "foo is the answer".

Replies are listed 'Best First'.
Re: call subroutines via hash
by eric256 (Parson) on Jan 04, 2006 at 21:00 UTC

    If you add use strict; to the top of your code you will immediatly get an error that tells you what went wrong. The line my $radius_ref = @data; is putting the value 4 in $radius_ref not a ref to data. Instead you could try  [@data] or just don't use a ref and do foreach  $radius(@data) {


    ___________
    Eric Hodges
      Eric:
      thanks!! Your approach works. Don't fully understand why but I'll try to figure it out.

      JWB
Re: call subroutines via hash
by smokemachine (Hermit) on Jan 04, 2006 at 21:00 UTC
    if i understood well (i don't speak english...) just change
    my $radius_ref = @data;
    to
    my $radius_ref = \@data;
      Smokemachine:
      your approach worked as well as Eric's. Now I'm really puzzled.

      JWB
        The above note by Errto explained why \@data works. As s?he said, it creates a reference to the array @data, and stores it in the scalar.

        Since you said you're confused by how both methods work, let me clear up eric256's method.

        $array_ref = [ ]; creates a new, empty array, and returns the reference to it. In this case, we assign it to $array_ref.
        $array2_ref = [1, 2, 3, 4]; creates a new array and initializes it with the values supplied. It returns the reference, which we once again store.
        $radius_ref = [@data] will create a new array initialized with the contents of @data.

        There's a really important distinction between using [@data] and \@data. They both create array references, but the method with the brackets creates a new array, while the slash method references your existing array. The example below should clear up any confusion you have.

        my @data = (1,2,3,4); my $existing_ref = \@data; my $new_ref = [@data]; $existing_ref->[0] = "a"; $new_ref->[2] = "c"; Now, @data contains (a,2,3,4) and $new_ref points to an array the contains (1,2,c,4)

        Hope that helped.

        Hi fortesque,

        In your code it seems like you want the variable $radius_ref to contain a reference to the array @radius. And I understand why you might expect that simply assigning it like my $radius_ref = @radius; might do that for you, and you wouldn't be the only one. Assigning to a scalar variable is one example of what's called scalar context in Perl. And when you have an array in scalar context, like here, what you get is the length of the array (that is, the number of elements in it). So $radius_ref will contain the number of elements in the array @radius.

        Whereas \@radius will take a reference to the array, which is what you want.

        This is explained in the Arrays section of perlintro, and in more detail in perldata.

Re: call subroutines via hash
by xdg (Monsignor) on Jan 04, 2006 at 20:55 UTC

    You need an explicit arrow operator to dereference (i.e. call) the subroutine.

    $dispatch{$input}->()

    (Update: First impressions are not always right. Thanks, Eric and Roy for catching my mistake.)

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Not in recent perls. The arrow-between-brackets-is-optional rule has been extended to sub refs.
      my %thingy; $thingy{foo} = sub { print "Cool!\n" }; $thingy{foo}();

      Caution: Contents may have been coded under pressure.

      Actualy thats not true. I'm not sure why, I thought the same thing until i went to run it. Turns out that part of the code works. ;)


      ___________
      Eric Hodges

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://521012]
Approved by xdg
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-03-29 07:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found