如何使用数组引用中的索引作为 Perl 中的方法引用? [英] How do I use an index in an array reference as a method reference in Perl?

查看:43
本文介绍了如何使用数组引用中的索引作为 Perl 中的方法引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类似于这个关于迭代子程序引用的问题,以及回答 这个关于 OO 调度表的问题,我想知道如何在引用中调用方法引用,而不是先删除它,或者是否有可能.

Similar to this question about iterating over subroutine references, and as a result of answering this question about a OO dispatch table, I was wondering how to call a method reference inside a reference, without removing it first, or if it was even possible.

例如:

package Class::Foo;
use 5.012;   #Yay autostrict!
use warnings;

# a basic constructor for illustration purposes....
sub new { 
    my $class = shift;
    return bless {@_}, $class;
}

# some subroutines for flavor...
sub sub1 { say 'in sub 1'; return shift->{a} }
sub sub2 { say 'in sub 2'; return shift->{b} }
sub sub3 { say 'in sub 3'; return shift->{c} }

# and a way to dynamically load the tests we're running...
sub sublist {
    my $self = shift; 
    return [
        $self->can('sub1'),
        $self->can('sub3'),
        $self->can('sub2'),
    ];
}

package main;

sub get_index { ... } # details of how we get the index not important    

my $instance = Class::Foo->new(a => 1, b => 2, c => 3);
my $subs = $instance->sublist();
my $index = get_index();

# <-- HERE

因此,在 HERE,我们可以:

So, at HERE, we could do:

my $ref = $subs->[$index];
$instance->$ref();

但是我们如何做到这一点,而不先删除引用?

but how would we do this, without removing the reference first?

更改了代码示例,这样人们就不会纠结于实现细节(叹气,尽我所能).这与我给出的第一个链接之间的重要区别在于该函数应该作为方法调用,而不是作为直接的子例程.

Changed code example so people don't get hung up on implementation details (sigh, tried my best). The important difference between this and the first link I gave was that the function should be invoked as a method, not as a straight subroutine.

编辑 2:

参见链接评论中的讨论 关于技术细节,以及为什么更长的方式(将子引用存储到变量,然后调用它)可能更可取.

See the discussion in the linked comment about the technical details, and why the longer way (storing the subref to a variable, then calling it) is probably preferable.

推荐答案

正如所写,你可以逃避

$tests->[$index]();

因为您问题中的方法没有使用 $self.

because the methods in your question aren't using $self.

您可以显式地传递 $instance,但这很笨拙.最好用闭包模拟委托:

You could pass $instance explicitly, but that's clunky. Better would be to simulate delegates with closures:

sub sublist {
    my $self = shift;
    my $sublist;
    for (qw/ sub1 sub3 sub2 /) {
      my $meth = $_;
      push @$sublist => sub { $self->$meth() };
    }
    return $sublist;
}

如果您更喜欢简洁,请使用

If you prefer to be concise, use

sub sublist {
    my $self = shift;
    return [ map { my $meth = $_; sub { $self->$meth() } }
             qw/ sub1 sub3 sub2 / ];
}

随便叫一个还是

$tests->[$index]();

但现在方法得到调用者.

but now the methods get invocants.

通过 can 获取子引用似乎是不必要的复杂性.如果运行时确定的方法名称列表可以调用,那么您可以大大简化代码:

Grabbing subrefs via can appears to be unnecessary complexity. If a runtime-determined list of names of methods to call will do, then you can simplify your code greatly:

sub sublist {
    my $self = shift; 
    return [ qw/ sub1 sub3 sub2 / ];
}

下面,我们将它们全部称为测试目的,但您也可以了解如何仅调用一个:

Below, we call them all for testing purposes, but you can also see how to call only one:

foreach my $method (@$subs) {
  my $x = $instance->$method();
  say "$method returned $x";
}

输出:

in sub 1
sub1 returned 1
in sub 3
sub3 returned 3
in sub 2
sub2 returned 2

这篇关于如何使用数组引用中的索引作为 Perl 中的方法引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆