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 :: Exporterで作成されたMoose属性sugarのライブラリにあります):

# 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。Class :: MOP :: Attributeには同様のアクセサーがないため、この同じ手法(Mooseメタクラスを使用して命名規則を想定するのではなくcoderefを検索する)を述語にも使用できないことに気づきました。:(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

UNIVERSALの メソッドを試しましたか?次のようなものを実装できるはずです。

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

私は、次のことを示すために、役に立たない1行の例を作成しました。

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 に答える