我想定义一个Perl函数(称之为"差异"),它取决于命令行参数.以下代码不起作用:
if ("square" eq $ARGV[0]) {sub difference {return ($_[0] - $_[1]) ** 2}} elsif ("constant" eq $ARGV[0]) {sub difference {return 1}}
似乎忽略了条件,因此无论$ ARGV [0]的值如何,"差异"函数都会得到第二个定义.
我可以通过在函数中添加一个条件来使代码工作:
sub difference { if ("square" eq $ARGV[0]) {return ($_[0] - $_[1]) ** 2} elsif ("constant" eq $ARGV[0]) {return 1} }
但这并不是我的意图 - 我不需要在执行期间每次评估条件.我只需要一种方法来影响函数的定义.
我的问题是:
为什么第一个结构不起作用?
为什么它没有给出错误,或者其他迹象表明出现了问题?
有没有办法在Perl中有条件地定义函数?
Ryan Bright.. 24
其他人已经提出了您请求的语法,但我建议为此使用更明确的子例程引用,以便您可以在不操作定义的情况下自由地操作引用.例如:
sub square_difference { return ($_[0] - $_[1]) ** 2 } sub constant_difference { return 1 } my %lookup = ( 'square' => \&square_difference, 'constant' => \&constant_difference, ); my $difference = $lookup{$ARGV[0]} || die "USAGE: $0 square|constant\n"; print &$difference(4, 1), "\n";
它是相同的基本方法,但我认为这种语法可以让你更方便地将参数映射到子程序.请注意,如果您遇到这种情况,这是战略模式的变体.
其他人已经提出了您请求的语法,但我建议为此使用更明确的子例程引用,以便您可以在不操作定义的情况下自由地操作引用.例如:
sub square_difference { return ($_[0] - $_[1]) ** 2 } sub constant_difference { return 1 } my %lookup = ( 'square' => \&square_difference, 'constant' => \&constant_difference, ); my $difference = $lookup{$ARGV[0]} || die "USAGE: $0 square|constant\n"; print &$difference(4, 1), "\n";
它是相同的基本方法,但我认为这种语法可以让你更方便地将参数映射到子程序.请注意,如果您遇到这种情况,这是战略模式的变体.
您想要做的事情可以像这样实现:
if ($ARGV[0] eq 'square') { *difference = sub { return ($_[0] - $_[1]) ** 2 }; } elsif ($ARGV[0] eq 'constant') { *difference = sub { return 1 }; }
我个人并没有做过很多这样的事情,但你可能想用一个变量来保存子程序:
my $difference; if ("square" eq $ARGV[0]) {$difference = sub {return ($_[0] - $_[1]) ** 2}} elsif ("constant" eq $ARGV[0]) {$difference = sub {return 1}}
致电:
&{ $difference }(args);
要么:
&$difference(args);
或者,正如Leon Timmermans所建议的那样:
$difference->(args);
一些解释 - 这声明了一个名为的变量,$difference
并根据您的条件将其设置为保存对匿名子例程的引用.所以你必须取消引用 $difference
作为子程序(因此&
在前面),以便它调用子程序.
编辑:代码测试和工作.
还有一个编辑:
耶稣,我习惯了use
ING strict
和warnings
我忘了他们是可选的.
不过实话说.永远use strict;
和use warnings;
.这将有助于捕捉这样的事情,并给你很好的有用的错误信息,解释什么是错的.我从来没有在生活中使用调试器因为strict
和warnings
- 这就是错误检查消息的好坏.他们会抓住这样的各种事情,甚至会给你一些有用的信息,说明他们为什么错了.
所以,无论何时你写东西,无论多小(除非它被混淆),总是use strict;
和use warnings;
.
Subs是在编译时定义的 - >如果你启用了"使用警告",你会看到有关子例程重定义的错误消息.