1

是否可以在 Perl 的哈希构造函数中定义匿名子例程?

我正在尝试做这样的事情:

my %array = { one   => sub { print "first $_[0]" },
              two   => sub { print "next  $_[0]" },
              three => sub { print "last  $_[0]" }};

$array{$foo}->('thing');

但它不起作用。代码似乎可以运行和编译,但数组中的值是空白的。如果我这样做:

my %array;

$array{'one'}   = sub { print "first $_[0]" };
$array{'two'}   = sub { print "next  $_[0]" };
$array{'three'} = sub { print "last  $_[0]" };

$array{$foo}->('thing');

然后它似乎工作正常。所以我有一个解决方法,但这只是让我烦恼,我想知道是否有人知道这是否可能,如果有,语法是什么。

4

5 回答 5

11

看起来您错误地分配到哈希中。Using{}构造了一个匿名哈希引用,您将其分配给一个标量。但是您分配给一个命名的哈希 ( %array)。

您需要分配一个标量:

my $array = { one   => sub { print "first $_[0]" },
              two   => sub { print "next  $_[0]" },
              three => sub { print "last  $_[0]" }};

$array->{$foo}->('thing');

或者不使用匿名构造函数语法:

my %array = ( one   => sub { print "first $_[0]" },
              two   => sub { print "next  $_[0]" },
              three => sub { print "last  $_[0]" });

$array{$foo}->('thing');
于 2009-01-30T22:06:47.580 回答
6

那是因为在第一种情况下,您创建的是 hashref 而不是哈希,您想要的是:

my $array;
$array = { one => ... }; # not %array = { .. };
...
$array->{one}->('thing');
于 2009-01-30T22:06:33.150 回答
4

Greg Hewgill 走在正确的轨道上。始终启用strict编译指示。此外,始终启用警告——但我建议不要在代码中使用 -w 开关。

相反,请利用use warningspragma。这样,您可以在代码的词法范围区域中选择性地禁用特定的警告组。

例如:

use strict;
use warnings;

foo('bar');
foo();

sub foo {
    no warnings 'uninitialized';

    my $foo = shift || 'DEFAULT';

    print "Foo is $foo\n";
} 

始终使用 strict 和 warnings 编译指示将为您节省数小时的时间。

于 2009-01-30T23:21:41.143 回答
3

不久前,我花了大约两个小时试图在脚本中找出这个确切的大括号对括号问题。如果您使用-w切换到 Perl,那么您将收到一条警告“在预期偶数大小列表的位置找到引用”,这至少提供了在哪里查找的线索。今天,所有 Perl 脚本都应该以:

#!/usr/bin/perl -w

use strict;

您的 Perl 生活将变得无比沮丧。

于 2009-01-30T22:34:28.193 回答
2

它应该是括号,而不是花括号:

my %array = ( one   => sub { print "first $_[0]" },
              two   => sub { print "next  $_[0]" },
              three => sub { print "last  $_[0]" }});

'{ a => 1, b => 2 }' 产生对哈希的引用。所以以下也可以工作:

my $array = { one   => sub { print "first $_[0]" },
              two   => sub { print "next  $_[0]" },
              three => sub { print "last  $_[0]" }};

$array->{one}->('thing');
于 2009-01-30T22:10:19.647 回答