如何创建一个接受多个块的Perl子例程?

时间:2014-11-20 16:44:18

标签: perl function subroutine

使用原型,您可以创建一个子程序,接受一段代码作为其第一个参数:

sub example (&) {
   my $code_ref = shift;
   $code_ref->();
}
example { print "Hello\n" };

我怎么能做同样的事情,但有多个代码块?我想使用代码块,而不是变量或sub { ... }

这不起作用:

sub example2 (&&) {
   my $code_ref = shift;
   my $code_ref2 = shift;
   $code_ref->();
   $code_ref2->();
}
example2 { print "One\n" } { print "Hello\n" };

它给出了这个错误:

Not enough arguments for main::example2

5 个答案:

答案 0 :(得分:9)

我希望您意识到这只是代码调节,而您所实现的只是一种更整洁的语法而牺牲了清晰度?

Perl不允许您将多个裸块传递给子例程,但第二个实际参数可能是对子例程的调用,该子例程也占用一个块并简单地返回代码引用。

该程序演示。请注意,我已选择pleasealso作为子例程的名称。但是你必须使用适合你自己的代码功能的东西,并且不太可能与即将到来的核心语言扩展冲突。

use strict;
use warnings;

sub please(&$) {
  my ($code1, $code2) = @_;
  $code1->();
  $code2->();
}

sub also(&) {
  $_[0];
}

please { print "aaa\n" } also { print "bbb\n" };

<强>输出

aaa
bbb

答案 1 :(得分:1)

适合我...

sub example2  {
   my $code_ref = shift;
   my $code_ref2 = shift;
   $code_ref->();
   $code_ref2->();
}
example2 ( sub { print "One\n" }, sub { print "Hello\n" });

仅仅为了TMTOWTDI的目的,这里的方法有点像OP请求的方式

首先,制作一个源过滤器

package poop;

use Filter::Util::Call;

sub import {
    my ($type) = @_;
    my ($ref)  = [];
    filter_add( bless $ref );
}

sub filter {
    my ($self) = @_;
    my ($status);
if (( $status = filter_read() ) > 0) { 
        if(!/sub/ && /example2/) {
            s/\{/sub \{/g;
            }
        }

    $status;
}
1;

其次必须使用过滤器

use poop;

sub example2  {
   my $code_ref = shift;
   my $code_ref2 = shift;
   $code_ref->();
   $code_ref2->();
}
example2 ( { print "One\n" }, { print "Hello\n" });

PS。这是可怕的,没有人希望看到这实际上在生产

答案 2 :(得分:1)

你试过在两个街区之间插一个逗号吗?

 You have:           example { print "One\n" } { print "Hello\n" };
 You probably want:  example { print "One\n" }, { print "Hello\n" };

我错了......

但这对我有用:

     example { print "One\n" } sub { print "Hello\n" };

答案 3 :(得分:0)

你可以eval

use experimental 'signatures';
use feature 'say'; 

sub doublethecode ($block1, $block2) { eval { $block1; }; eval { $block2;} } ;
doublethecode \&{ print "OH " }, \&{ say for qw/HAI YOU LOLCAT :-P/  }; 

<强>输出

OH, HAI
YOU
LOLCAT
:-P

然后忽略\&,你就在那里。

v5.20开始,您可以同时使用签名和:prototype属性。 signatures功能提供了更“通用”的语法和极简主义的参数检查。也许有一天,未来的perl会有一个“内置”(可选的,高度灵活的)类型系统,但是现在原型并不是那样的。如下所示:

sub doublethecode :prototype(\&\&) ($cr1, $cr2) { $cr1 ; $cr2 ; }

不是它看起来的样子。由于原型,signatures:prototype(&&)签名可能无法提供您的想法,这可能已经足够了:

sub doublethecode { eval { shift };  eval{ shift } } ;
doublethecode &{ print "perl" }, &{ print "6" }

<强>输出

perl6

为确保perl不认为{}是哈希值,&是必需的。但实际上......在这里使用匿名子程序sub { } 是错误的吗?

答案 4 :(得分:0)

Fwiw,在Perl 6中:

sub doublecode (&foo, &bar) { foo(), bar() }
doublecode { print 1 }, { print 2 } # prints 12

但请参阅my partial list of caveats about Perl 6