提问人:troubadour 提问时间:11/17/2023 更新时间:11/19/2023 访问量:97
一个Perl子例程有一个常量作为参数,如何在子例程中显示常量名称?
A Perl subroutine has a constant as parameter, how to display the constant name in the subroutine?
问:
一个简单的案例:
use constant MYCO => "myco value";
...
sub example {
my $var = shift; # contains "myco value"
# here I would like to print the constant name passed, so "MYCO"
}
...
example(MYCO);
# example(OTHER_CONSTANT1);
...
添加了用于过帐的行 添加了用于过帐的行 添加了用于过帐的行
答:
2赞
Rawley Fowler
11/17/2023
#1
如果不显式提供常量的名称作为其值的一部分,就无法做到这一点。
你可以做这样的事情:
use constant MYCO => ["myco value", "MYCO"];
sub example {
my $var = shift; # contains "myco value"
say $var->[0]; # value
say $var->[1]; # name
}
example(MYCO);
# example(OTHER_CONSTANT1);
老实说,在我看来,这是一种反模式。我更希望有一个子例程(这是Perl在后台对常量所做的,但不做任何保证)。然后只需按名称调用子例程作为参数即可。
sub MYCO { "myco value" }
sub example {
my $constant_name = shift;
my $value = __PACKAGE__->can($constant_name)->();
say $value;
say $constant_name;
}
example('MYCO');
编辑:在考虑了更多之后,如果你真的需要这个功能,你可能想把你的常量OO化。像这样:
package My::Constant;
sub name { shift->{name} }
sub value { shift->{value} }
sub new {
my ($class, $name, $value) = @_;
my $self = {};
($self->{value}, $self->{name}) = ($value, $name);
return bless($self, $class);
}
1;
然后,在现有代码中,您可以更习惯地定义常量,例如:
use My::Constant;
use constant MYCO => My::Constant->new("MYCO", "myco value");
sub example {
my $var = shift;
return unless ref($var) eq "My::Constant";
say $var->name;
say $var->value;
}
example(MYCO);
评论
0赞
troubadour
11/17/2023
谢谢,但是想象一下示例子例程中使用的许多常量作为参数,使用这种技巧的代码可能会很长.....我只是想知道是否存在一个预定义的函数,子例程中只有一个调用
0赞
Rawley Fowler
11/17/2023
你需要改变你的方法,如果你有大量的常量,并且需要它们的名字,你可能应该重构。
0赞
brian d foy
11/17/2023
这就是我通常的做法。
2赞
ikegami
11/17/2023
#2
除非这个问题没有意义
- 你把自己限制在特定的常量子集上,
- 它们都有独特的价值,并且
- 你不在乎这个常量是否被实际使用。
然后你可以做类似的事情
use constant;
my ( %widget_types, %widget_type_by_val );
BEGIN {
# Can't have two widget types with the same value.
%widget_types = (
FLOOB => 0,
GRINK => 1,
BLARP => 2,
);
%widget_type_name_by_val = reverse( %widget_types );
constant->import( \%widget_types );
}
sub get_widget_type_name_from_val {
return $widget_type_name_by_val{ $_[0] };
}
您可以将其放在导出常量的模块中。
package My::Widgets;
use constant;
use Exporter qw( import );
our @EXPORT_OK = qw(
get_widget_type_name_from_val
);
my ( %widget_types, %widget_type_by_val );
BEGIN {
# Can't have two widget types with the same value.
%widget_types = (
FLOOB => 0,
GRINK => 1,
BLARP => 2,
);
%widget_type_name_by_val = reverse( %widget_types );
constant->import( \%widget_types );
push @EXPORT_OK, keys( %widget_types );
}
sub get_widget_type_name_from_val {
return $widget_type_name_by_val{ $_[0] };
}
1
可能已经有一个模块为您做了类似的事情。
评论
example("myco value");
use constant ALIAS => "myco value";