【问题标题】:Is there a Perl strict symbol resolution syntax for functions?函数是否有 Perl 严格的符号解析语法?
【发布时间】:2020-04-09 04:45:27
【问题描述】:

我想知道如何在编译时强制解析 subs。

对于某些背景,使用 perl,我可以在编译时使用附加到包名称末尾的 :: 严格解析包符号。例如。

perl -wE'use warnings FATAL => "bareword"; die 7; Foo::; die 42'
Bareword "Foo::" refers to nonexistent package at -e line 1.

您会在上面的代码中注意到,我们并没有死于 7 或 42。我们在运行时阶段之前就死了。这仅适用于解析包名称。我可以使用具有上述语法的方法解析运算符 (->) 并在运行时解析函数名称,

perl -E'use warnings FATAL => "bareword"; die 7; Foo::->bar(); die 42'
Bareword "Foo::" refers to nonexistent package at -e line 1.

但这并不是我想要的,

  • 如果我声明一个包Foo 缺少一个子bar,并且我想在该包中调用不存在的函数bar,我将不再获得编译-时间错误,

      perl -E'package Foo {}; use warnings FATAL => "bareword"; die 7; Foo::->bar(); die 42'
      7 at -e line 1.
    

    您可以在此处看到,当() 附加到符号末尾时,它会在运行时解析;但是,当:: 附加到符号的末尾时,尽管它被假定为包名称,但它会在编译时解析。

  • -> 运算符正在使用运行时方法解析。它搜索@ISA,并提供类的第一个参数。

如果Foo 在编译时没有bar 子,我想死。

【问题讨论】:

标签: function perl compilation symbols compile-time


【解决方案1】:

调用不带括号的函数将尝试在解析阶段解析符号,这也包括完全限定符号。棘手的部分是当它没有解决时会发生什么。在 use strict 'subs' 下,它会因为禁止使用裸字字符串而死。

use strict;
use warnings;
Foo::bar; # Bareword "Foo::bar" not allowed while "strict subs" in use

当有争论时,这会变得更加棘手。它仍然会尝试将其解析为裸字字符串,因此当它后面跟着一些在那里没有意义的东西时可能会报告语法错误。

use strict;
use warnings;
Foo::bar 42; # Number found where operator expected

其他时候,它会将其解析为间接方法调用,然后将错误推迟到运行时,甚至最终可能会做一些你没有预料到的事情。

use strict;
use warnings;
my $foo;
Foo::bar $foo; # Can't call method "bar" on an undefined value

基本上,Perl 非常努力地弄清楚语法应该是什么意思,因此当它不起作用时,并不总是以有用的错误消息告终。

【讨论】:

  • 你能说清楚吗,有没有什么方法可以用括号来做到这一点,这种方法适用于变量,而无需间接对象语法?
  • 不是自动的,这正是解析器符号检查正在做的事情,括号导致它被推迟,问题是它只有很多后备选项。您可以显式检查一个函数是否定义为 BEGIN { die "Foo::bar is undefined" unless defined &Foo::bar }
  • 是的,我知道我可以明确地写出来。我只是想有一种方法可以强迫它。因为这正是我想要的,而且这似乎是strict 应该做的事情。特别是当 perl 不允许重载时。看起来符号要么存在,要么不存在,通常可以在编译时确定。
  • 当然,如果不存在间接对象表示法,这一切都会简单得多。
  • 考虑使用括号故意延迟符号解析的常见情况:调用稍后在同一文件中定义的子例程,而无需预先声明它。
猜你喜欢
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 2013-11-03
相关资源
最近更新 更多