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!

Thumper
  • 525
  • 1
  • 6
  • 21
  • 3
    You can also do `my %hash = ( function => \&someFunction )` which does not require `no strict 'refs'`. – TLP Jun 20 '12 at 17:35
  • @TLP +1, I was going to *answer* this. `use strict;` saves **so** much trouble... – Dallaylaen Jun 20 '12 at 18:45
  • 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! – Thumper Jun 21 '12 at 16:14

1 Answers1

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

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 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. – Thumper Jun 20 '12 at 16:57
  • Also, I forgot to mention I am fairly-new to Perl (maybe one month of experience), so this will really help my professional development. – Thumper Jun 20 '12 at 17:00
  • 1
    I'm a bit surprised because most people find the arrow notation most readable, but both are acceptable. – ikegami Jun 20 '12 at 17:48
  • 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. – Thumper Jun 20 '12 at 20:27
  • 2
    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 `->()`. :) – ikegami Jun 20 '12 at 20:41
  • I found out by just implementing it, and you are very correct, sir/ma'am. – Thumper Jun 21 '12 at 16:23