如何在子程序名称中启用点(。)?

时间:2014-05-28 18:07:54

标签: perl subroutine

我正在使用自动加载功能创建一个带动态访问器的模块。被调用的方法名称中将包含一个或多个点。用法示例:

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中使用的方式类似。

4 个答案:

答案 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 { }

请注意,如果尝试访问代理AUTOLOADcanDESTROYDOESimportisa,则会失败, ___newVERSION

如果您可以使用相同名称的方法和属性,请使用MyModule->a->get->(),您可以通过重载&{}来执行此操作。

答案 3 :(得分:0)

根据http://perldoc.perl.org/perldata.html#Identifier-parsing,我没有看到' mr.s'在utf8或非utf8源解析下验证为标识符。因此,它不是有效的子程序名称。