Perl: Problems calling subroutines by reference using a hash value
Asked Answered
A

1

5


In Perl, you are able to call a function by reference (or name) like so:

    my $functionName = 'someFunction';
    &$functionName();

    #someFunction defined here:
    sub someFunction { print "Hello World!"; }

What I am trying to do is use a value from a Hash, like so:

    my %hash = (
        functionName => 'someFunction',
    );

    &$hash{functionName}();

    #someFunction defined here:
    sub someFunction { print "Hello World!"; }

And the error I get is Global symbol "$hash" requires explicit package name.

My question is: Is there a correct way to do this without using an intermediate variable?
Any help on this would be greatly appreciated!

Adown answered 20/6, 2012 at 16:44 Comment(3)
You can also do my %hash = ( function => \&someFunction ) which does not require no strict 'refs'.Crampton
@Crampton +1, I was going to answer this. use strict; saves so much trouble...Amino
I am able to use that, but it adds some somewhat-unreadable code (for now)... I am dynamically setting the value of functionName at runtime and calling a function by its name. Perl is so fun!Adown
S
12

It's just a precedence issue that can be resolved by not omitting the curlies. You could use

&{ $hash{functionName} }()

Or use the alternate syntax:

$hash{functionName}->()

As between indexes, the -> can be omitted (but I don't omit it here):

$hash{functionName}()

Ref: Deferencing Syntax

Skew answered 20/6, 2012 at 16:47 Comment(6)
Wow, this is the first question I've ever asked on here, and was expecting a long wait. Thank you so much! I ended up using the first solution you posted. Great stuff! Thank you so much.Adown
Also, I forgot to mention I am fairly-new to Perl (maybe one month of experience), so this will really help my professional development.Adown
I'm a bit surprised because most people find the arrow notation most readable, but both are acceptable.Skew
My reasoning is because somewhere (can't remember where) I read that you cannot pass in parameters without the ampersand when calling a function by name. I pass in parameters to other functions, so I wanted to keep it consistent.Adown
That's not true at all. $ref->(@args) works perfectly line. &$ref (but not &$ref()) is very special, though. It reuses the parent's @_, something you normally want to avoid. Yet another reason to use ->(). :)Skew
I found out by just implementing it, and you are very correct, sir/ma'am.Adown

© 2022 - 2024 — McMap. All rights reserved.