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

时间:2009-01-30 22:00:08

标签: perl hash coderef

是否可以在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');

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

5 个答案:

答案 0 :(得分:11)

看起来你错误地分配了哈希值。使用{}构造一个匿名哈希引用,您可以将其指定给标量。但是你要分配一个命名的哈希(%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');

答案 1 :(得分:6)

那是因为在第一种情况下,你创建一个hashref而不是一个hash,你想要的是:

my $array;
$array = { one => ... }; # not %array = { .. };
...
$array->{one}->('thing');

答案 2 :(得分:4)

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

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

例如:

use strict;
use warnings;

foo('bar');
foo();

sub foo {
    no warnings 'uninitialized';

    my $foo = shift || 'DEFAULT';

    print "Foo is $foo\n";
} 

一致使用严格和警告的pragma将为您节省数小时的时间。

答案 3 :(得分:3)

我花了两个小时试图在不久前在脚本中追踪这个exact braces-vs-parentheses problem。如果您使用-w切换到Perl,那么您将收到一条警告“参考找到了偶数大小的列表预期”,这至少可以提供一个线索。今天,所有Perl脚本都应该以:

开头
#!/usr/bin/perl -w

use strict;

你的Perl生活将变得不那么令人沮丧。

答案 4 :(得分: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');