如何在Perl代码中省略临时变量$n优化FLAGS过滤逻辑?
Perl中省略grep临时变量调用对象方法的可行语法
你可以通过两种方式省略临时变量$n,直接在grep块里用$_->[0]作为方法名调用:
方法1:使用${\(...)}强制插值
Perl里如果要把表达式直接作为方法名调用,需要用${\(表达式)}明确告诉解释器先计算表达式的值,再作为方法名使用。写法如下:
[grep { $self->${\($_->[0])}() } FLAGS]
这里${\($_->[0])}会先取出数组引用的首个元素(方法名),再让$self调用该方法。
方法2:利用can方法获取代码引用
can是Perl对象的内置方法,会返回对应方法的代码引用(若方法存在),之后直接调用这个代码引用并传入$self作为第一个参数(对象方法调用的本质就是把对象作为第一个参数传给子例程):
[grep { $self->can($_->[0])->($self) } FLAGS]
这种写法更健壮:如果FLAGS里存在不存在的方法名,can会返回undef,调用undef会返回false,直接被grep过滤掉,不会触发方法不存在的报错。
为什么直接写会报错?
你尝试的无临时变量写法$self->$_->[0](),会被Perl解析成先调用$self->$_(把当前数组引用$_当作方法名,逻辑完全错误),再尝试取返回值的[0]元素并调用,自然会触发报错。
最小可运行示例
use strict; use warnings; package MyObj; sub new { my ($class, %args) = @_; bless \%args, $class; } sub is_active { shift->{active} // 0 } sub is_visible { shift->{visible} // 0 } sub is_enabled { shift->{enabled} // 0 } use constant FLAGS => ( ['is_active'], ['is_visible'], ['is_enabled'], ); sub get_set_flags { my $self = shift; # 任选一种写法即可 return [map { $_->[0] } grep { $self->${\($_->[0])}() } FLAGS]; # return [map { $_->[0] } grep { $self->can($_->[0])->($self) } FLAGS]; } package main; my $obj = MyObj->new(active => 1, enabled => 0); my $set_flags = $obj->get_set_flags(); print "已设置的标志:" . join(', ', @$set_flags) . "\n"; # 输出:已设置的标志:is_active
内容的提问来源于stack exchange,提问作者U. Windl
相关产品推荐
相关产品推荐

