3

I have a subroutine taking multiple arguments and want to make a reference to it with one of the arguments set, so that the reference takes one argument less. Optimal case would be

my $subref = \&routine($arg1);
...
my $result = $subref->($arg2,$arg3);

In perlref there is an example with an anonymous subroutine like this, however I cannot get the equivalent with a named one working.

Below is a full fledged example of what I mean. While $func (ref to anonymous sub) and $func2 (ref to named sub, but without arguments) work. $func3 gives the error "Not a CODE reference[...]".

Have I missed something or is this actually impossible?

use strict;
use warnings;

sub args{
    my $arg1 = (shift or "none");
    my $arg2 = (shift or "none");
    my $arg3 = (shift or "none");
    my (undef, undef, undef, $function) = caller(0);
    return "me: $function\narg1 = $arg1\narg2 = $arg2\narg3 = $arg3\n";
}

sub just_a_ref {
    return \&args;
}

sub new_arg_anon {
    my $arg = shift;
    return sub{
        my $arg1 = $arg;
        my $arg2 = (shift or "none");
        my $arg3 = (shift or "none");
        my (undef, undef, undef, $function) = caller(0);
        return "me: $function\narg1 = $arg1\narg2 = $arg2\narg3 = $arg3\n";
    }
}

sub new_arg {
    my $arg = shift;
    return \&args($arg);
}


my $func = new_arg_anon("one");
print $func->("two","three");     #works fine
my $func2 = just_a_ref();
print $func2->("un", "deux", "trois");  #works fine
my $func3 = new_arg("eins");
print $func3->("zwei", "drei");   #Not a CODE reference


2 Answers 2

4

You have to create a new anonymous function that does exactly that. Call the target function with one argument set and passing the rest of the arguments to it. In your example the new_arg function should be:

sub new_arg {
    my $arg = shift;
    return sub {args($arg, @_)};
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Much simpler than I have feared as well.
3

\&args($arg) is \( args($arg) ), that is, a reference to the return value of the function call args($arg), not a reference to the function args called with the argument $arg.

print $func3;   # SCALAR(0x8000a1a50)

To make a reference to a function that executes the args subroutine with $arg as the first argument, use

sub new_arg {
    my $arg = shift;
    return sub { args($arg,@_) };
}

(look at that, just like Georg Mavridis's answer)

1 Comment

"just like..." -- and no worse, even comes with an explanation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.