Как передать анонимные подпрограммы при вызове Perl-подпрограммы? - PullRequest
2 голосов
/ 18 сентября 2010

mysub получает ссылку на подпрограмму в качестве первого аргумента.

Могу ли я просто позвонить mysub(sub{some subroutine body here})? То есть определить анонимную подпрограмму прямо при вызове?

Синтаксис в порядке (действительно ли передается ссылка на sub)?

Ответы [ 3 ]

8 голосов
/ 18 сентября 2010

Что случилось, когда вы попробовали это?Это, безусловно, лучший способ проверить, работают ли подобные вещи.

Но, да, этот синтаксис будет работать просто отлично.

#!/usr/bin/perl

use strict;
use warnings;

sub run_sub {
  shift->();
}

run_sub( sub { print "hello\n"; } );
5 голосов
/ 18 сентября 2010

Поскольку передача ссылок на подпрограммы в другие подпрограммы является довольно распространенным шаблоном, Perl даже имеет несколько синтаксических приемов, чтобы сделать его еще более плавным:

sub function1 {          # normal declaration, implicit `(@)` prototype
    my $code = shift;
    $code->(@_);
}

sub function2 (&@) {     # prototyped declaration
    my $code = shift;
    $code->(@_);
}

function1 должен называться: function1 sub{...}, any_other_args

function2 имеет прототип (&@), который указывает компилятору наложить контекст подпрограммы на первый аргумент (а затем принять любое количество дополнительных аргументов).

Таким образом, вы можете назвать его как function2 {...} any_other_args, который отражает способ, которым встроенные функции более высокого порядка, такие как map, grep и sort, принимают свои кодовые блоки.Обратите внимание, что после блока кода нет запятой, как и в случае с bultins.

Более подробную информацию о прототипах можно найти здесь: http://perldoc.perl.org/perlsub.html#Prototypes

Имейте в виду, что прототипы Perl НЕ предназначены дляпроверка аргументов, это подсказки компилятору, которые позволяют вам писать подпрограммы, которые ведут себя как встроенные.

2 голосов
/ 18 сентября 2010

В качестве альтернативы (к ответу @ davorg ) вы можете использовать:

sub run_sub
{
    my($funcref) = @_;
    &$funcref();
}

Более многословно, конечно; также немного яснее, я думаю. Но это Perl - TMTOWTDI!

...