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

I'm using TinyPerl 5.8. Why am I getting an error in this script??? I am fiddling around with functions to see what happens when I modify my code. And according to the manual, this should work. And yet it doesn't work! Why?

Btw, I am trying to learn how to use "virtual functions" in Perl. Is there a better way than doing it like this?: my $Func = sub { ... };

use strict; use warnings; my $myFunction = sub { print "Hey, I am from Italy! @_\n"; }; printList(1, 2, 3, 4); $myFunction = sub { print "Hey, I am from Japan! @_\n"; }; printList(5, 6, 7); sub printList { print "\nprintList was called.\n"; &$myFunction->(); } exit; # # This program should print: # # printList was called. # Hey, I am from Italy! 1 2 3 4 # printList was called. # Hey, I am from Japan! 5 6 7 #

Replies are listed 'Best First'.
Re: I'm getting some weird error
by jwkrahn (Abbot) on Dec 05, 2018 at 07:10 UTC
      Thank you! Yes, that works now. But I don't understand why mine didn't work. It was saying
      printList was called. Hey, I am from Italy! 1 2 3 4 Can't use string ("1") as a subroutine ref while "strict refs" in use +at C:\DESKTOP\test.pl line 16. Press any key to continue . . .

      I wasn't trying to use "1" as a sub ref. What is that all about???

        You called your subroutine, and then tried to call its result again, as a subroutine:

        &$subref; # this calls the subroutine &$subref->(); # this calls the subroutine and tries to call the result + again, as a subroutine

        Using & is a bad idea in most cases.

        Perl offers two ways to dereference (most) datatypes.
        • with the right sigil like &$code_ref(ARGS)
        • with a deref arrow + bracket $code_ref->(ARGS)
        Same for hashes and arrays.

        You mixed both (and Corion explained what happend)

        See perlreftut and References quick reference for more.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: I'm getting some weird error
by Corion (Patriarch) on Dec 05, 2018 at 07:10 UTC

    What error do you get?

    What you are doing is not "virtual functions", but using anonymous functions. The subroutine stored in $myFunction does not have a name.

    Your syntax for calling the function is wrong/weird:

    &$myFunction->()

    Most likely you wanted:

    $myFunction->()
Re: I'm getting some weird error
by haukex (Archbishop) on Dec 05, 2018 at 12:05 UTC

    Because you're not passing any arguments in &$myFunction->() but are expecting to see the arguments to printList get output, I'm guessing that perhaps you were trying to call the sub like one would in &foo;, which leaves the original @_ unchanged (see perlsub). However, this is nowadays not considered a good practice, as leaving @_ unchanged can also easily lead to mistakes. Plus, using the &foo syntax avoids prototype checking, which is also something that one should only do if one knows what one is doing. If you do want to make use of the & functionality for whatever reason, the correct syntax is &$myFunction; - but as the others have said, it's usually better to be explicit and use $myFunction->(@_); instead. See also perlreftut and perlref on using references.

    Is there a better way than doing it like this?: my $Func = sub { ... };

    I'm not sure what you mean with "virtual functions" in this context, but my $Func = sub { ... }; is basically "the" way to create an anonymous subroutine and store a reference to it.