我正在使用自动加载功能创建一个带动态访问器的模块。被调用的方法名称中将包含一个或多个点。用法示例:
use MyModule;
my $var=MyModule->a.method.get;
#MyModule::a.method.get() is now defined
子程序名称中的点似乎是非法字符:
#!/usr/bin/perl
use warnings;
use strict;
sub mr.s
{
print "OK\n";
}
mr.s();
发出
Illegal declaration of subroutine main::mr at main.pl line 5
那么,如何在子程序名称中启用点?
据我所知,至少有些受访者可能会觉得不鼓励使用自动加载,以及尝试更改合法的子例程名称,而是提供更好的做法示例。我没有反对这些答案,也不认为它们的价值不高。不过,请尽量回答我原来的问题。
修改 为了澄清,最终目标是一个模块,当调用未定义的子例程时,它将根据其名称动态定义。为了实现这一点,我的意思是使用AUTOLOAD,其方式与this tutorial中使用的方式类似。
答案 0 :(得分:4)
你是对的,这个点在子程序名称中是非法的。这与自动加载无关,它们只是非法的。点用于字符串连接,因此您的示例是
MyModule->a.method.get
实际上会被解释为
MyModule->a() . method() . get()
答案 1 :(得分:2)
你不能那样做,不要像普通方法那样称呼它们[*]。
你的选择是放弃。并使用_或其他东西,或者不创建accessor subs,而是使用一个通用的get()函数,该函数将属性名称作为参数。
(*脚注:您可以创建此类方法并间接调用它们,如下所示:
package Foo;
use strict;
use warnings;
BEGIN {
no strict 'refs';
*{'foo.bar'} = sub {
use strict;
return 'foo.bar value';
}
}
package main;
use strict;
use warnings;
my $method = 'foo.bar';
my $value = Foo::->$method;
但这会让你头疼得多。)
答案 2 :(得分:1)
为什么要尝试使用Java(或其他)语法?在Perl中,它写成MyModule->a->get
。使用它。
package MyModule;
use strict;
use warnings;
sub AUTOLOAD {
my $self = shift;
my $name = our $AUTOLOAD =~ s/^.*:://r;
my $path = ref($self) ? $self->{path}.".".$name : $name;
if (is_path_method($path)) {
return call_method($path);
} else {
return MyModule->___new(path => $path);
}
}
sub ___new {
my $class = shift;
return bless({ @_ }, $class);
}
sub DESTROY { }
请注意,如果尝试访问代理AUTOLOAD
,can
,DESTROY
,DOES
,import
,isa
,则会失败, ___new
或VERSION
。
如果您可以使用相同名称的方法和属性,请使用MyModule->a->get->()
,您可以通过重载&{}
来执行此操作。
答案 3 :(得分:0)
根据http://perldoc.perl.org/perldata.html#Identifier-parsing,我没有看到' mr.s'在utf8或非utf8源解析下验证为标识符。因此,它不是有效的子程序名称。