Perl 有一个未定义函数的概念。已声明但未定义的函数。
sub foo;
foo(); # Undefined subroutine error
bar(); # Undefined subroutine error
Run Code Online (Sandbox Code Playgroud)
该函数foo现在存在于符号表中,可用于解析方法调用。但为什么这个“功能”会存在呢?在 C 中,这是因为函数是类型检查的,有时您希望在定义之前进行调用(例如解决循环依赖)。但 Perl 没有这样的功能,所有函数符号都是在运行时而不是编译时解析的。
如果是为了原型,那么如果没有原型,为什么还要存在未定义的函数呢?
如果它不是为了原型,它为什么存在?
为什么在方法解析中使用未定义的子例程?为什么不完全忽略它们——你不能调用它们,而且据我所知(最多)它们是内部实现细节?这就是为什么如果函数没有定义,我们就不能像它不存在一样继续方法解析(看起来不会那么混乱)。
hob*_*bbs 30
它与原型有关,函数的声明(或不声明)确实在编译时产生影响。考虑
\n print foo + 42;\nRun Code Online (Sandbox Code Playgroud)\n单独来看,这相当于print(\'foo\' + 42);\xe2\x80\x94foo是一个“裸字”。如果您strict \'subs\'启用了,它会给您一个编译错误,指出禁止裸字。
sub foo;\n print foo + 42;\nRun Code Online (Sandbox Code Playgroud)\n这相当于print(foo(42));编译器知道这foo是一个 sub 并且它没有原型,因此它以“列表操作”方式消耗它后面的所有内容,而它后面的是术语+42。
sub foo();\n print foo + 42;\nRun Code Online (Sandbox Code Playgroud)\n这相当于print(foo() + 42);编译器知道它foo有一个原型并且它不带任何参数,因此不会查找任何参数,并且fooand42将成为运算符的操作数+。
sub foo($);\n print foo + 42;\nRun Code Online (Sandbox Code Playgroud)\n与情况 2 一样,这相当于print(foo(42)). 我想我可能可以用一个测试来区分它们。
重点是,无论子程序是否已知,都会在编译时产生影响,Perl 为您提供了在定义子程序体之前声明该事实的选项,但很少需要这样做。
\n至于为什么它会对方法解析顺序 \xe2\x80\x94 产生影响,很可能是一个副作用,但并没有错。前向声明子应该意味着您打算在编译完成之前提供定义。如果不这样做,那么当您尝试调用它时将会出现运行时错误。对我来说,如果这样的声明位于 MRO 的包中,那么这意味着“这里应该有一个方法,但我忘记了”,并且当 MRO 到达该包时您会收到错误。
\n我想说,这与其他类型相同;只是它如何解析的产物。
my $hr = { a => 1 }; # $hr name introduced at compile time, assigned or not
Run Code Online (Sandbox Code Playgroud)
所以同样如此
sub name { ... }; # "name" "declared" at compile time
Run Code Online (Sandbox Code Playgroud)
说只是与说——然后有一个没有附加定义的符号几乎sub name;相同。my $hr;
我不知道解析器是如何工作的,但我猜它必须sub name先采取并稍后“绑定”定义,所以碰巧我们也可以说 justsub name;并拥有该名称。
我的意思是说,这就是“原因”,根据问题“但是为什么这个“功能”甚至存在? ”
但是,一旦编译器提前知道存在具有该名称的子程序,那么该事实可能会有各种用途。
我可以想到这些原因:
如果子程序具有原型或属性,则允许在调用子程序之后放置子程序的定义。
值得注意的细节:
允许声明 AUTOLOADed 和类似的子程序。
值得注意的细节:
可以用作抽象方法。
| 归档时间: |
|
| 查看次数: |
2549 次 |
| 最近记录: |