8

我确定这在某处的文档中有所介绍,但我一直无法找到它......我正在寻找可以调用名称存储在哈希中的类上的方法的语法糖(而不是一个简单的标量):

use strict; use warnings;

package Foo;
sub foo { print "in foo()\n" }

package main;
my %hash = (func => 'foo');

Foo->$hash{func};

如果我首先复制$hash{func}到一个标量变量中,那么我可以调用Foo->$func就好了......但是缺少什么来启用Foo->$hash{func}工作?

(编辑:我并不是要通过调用类上的方法来做任何特别的事情Foo——这可以很容易地成为一个有福的对象(在我的实际代码中它是);编写一个自包含的方法更容易使用类方法的示例。)

编辑 2:为了完整起见下面的评论,这就是我实际在做的事情(这是在 Moose 属性糖库中,使用Moose::Exporter创建):

# adds an accessor to a sibling module
sub foreignTable
{
    my ($meta, $table, %args) = @_;

    my $class = 'MyApp::Dir1::Dir2::' . $table;
    my $dbAccessor = lcfirst $table;

    eval "require $class" or do { die "Can't load $class: $@" };

    $meta->add_attribute(
        $table,
        is => 'ro',
        isa => $class,
        init_arg => undef,  # don't allow in constructor
        lazy => 1,
        predicate => 'has_' . $table,
        default => sub {
            my $this = shift;
            $this->debug("in builder for $class");

            ### here's the line that uses a hash value as the method name
            my @args = ($args{primaryKey} => $this->${\$args{primaryKey}});
            push @args, ( _dbObject => $this->_dbObject->$dbAccessor )
                if $args{fkRelationshipExists};

            $this->debug("passing these values to $class -> new: @args");
            $class->new(@args);
        },
    );
}

我已经用这个替换了上面的标记行:

        my $pk_accessor = $this->meta->find_attribute_by_name($args{primaryKey})->get_read_method_ref;
        my @args = ($args{primaryKey} => $this->$pk_accessor);

PS。我刚刚注意到,同样的技术(使用 Moose 元类来查找 coderef 而不是假设其命名约定)也不能用于谓词,因为Class::MOP::Attribute没有类似的get_predicate_method_ref访问器。:(

4

3 回答 3

14
Foo->${\$hash{func}};

但为了清楚起见,我可能仍将其写为:

my $method = $hash{func};
Foo->$method;
于 2009-12-02T22:35:15.910 回答
2

您存储子例程名称而不是对代码的引用是否有原因?

例如

use strict; use warnings;

package Foo;
sub foo { print "in foo()\n" }

package main;
my %hash = (func => \&Foo::foo);

$hash{func}->();

你不会传递类名,但如果这对你很重要,你可以使用类似的东西

my %hash = ( func => sub { return Foo->foo(@_) } );
于 2009-12-02T22:13:57.597 回答
1

Have you tried UNIVERSAL's can method? You should be able to implement something like this:

## untested
if ( my $code = $object->can( $hash{func} ) ) {
    $object->$code();
}

I made a useless, one-line example to demonstrate:

perl -MData::Dumper -le 'my %h = ( f => "Dump" ); my $o = Data::Dumper->new( [qw/1 2 3/] ); my $ref = $o->can( $h{f} ); print $o->$ref()'
于 2009-12-03T20:33:05.043 回答