Могу ли я ссылаться на именованную подпрограмму с некоторыми аргументами - PullRequest
3 голосов
/ 15 апреля 2020

У меня есть подпрограмма, принимающая несколько аргументов, и я хочу сделать ссылку на нее с одним из установленных аргументов, чтобы ссылка принимала на один аргумент меньше. Оптимальным случаем будет

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

В perlref есть пример с такой анонимной подпрограммой, однако я не могу получить эквивалент с именованной работающей.

Ниже приведен полноценный пример того, что я имею в виду. В то время как $ fun c (ref to anonymous sub) и $ func2 (ref to named sub, но без аргументов) работают. $ func3 выдает ошибку «Не ссылка на код [...]».

Я что-то пропустил или это на самом деле невозможно?

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 ]

4 голосов
/ 15 апреля 2020

Вы должны создать новую анонимную функцию, которая делает именно это. Вызовите целевую функцию с одним установленным аргументом и передайте ей остальные аргументы. В вашем примере функция new_arg должна быть:

sub new_arg {
    my $arg = shift;
    return sub {args($arg, @_)};
}
3 голосов
/ 15 апреля 2020

\&args($arg) - это \( args($arg) ), то есть ссылка на возвращаемое значение вызова функции args($arg), а не ссылка на функцию args, вызываемую с аргументом $arg.

print $func3;   # SCALAR(0x8000a1a50)

Чтобы сделать ссылку на функцию, которая выполняет подпрограмму args с $arg в качестве первого аргумента, используйте

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

(посмотрите на это так же, как ответ Георга Мавридиса)

...