【发布时间】:2020-02-04 08:59:18
【问题描述】:
不带引号的词在 Perl 中似乎有很多含义。
print STDERR $msg;
$hash{key}
func( param => $arg )
my $x = str;
如何确定这些的含义?
【问题讨论】:
不带引号的词在 Perl 中似乎有很多含义。
print STDERR $msg;
$hash{key}
func( param => $arg )
my $x = str;
如何确定这些的含义?
【问题讨论】:
下图显示 Perl 如何按优先级降序解析标识符。
除非另有说明,否则它也适用于由:: 链接的标识符(我将其称为“合格标识符”)。
语法定义的含义,当语法预期时。
sub foo { } # «foo» («sub» is covered later)
sub main::foo { } # «main::foo» («sub» is covered later)
method Class # «Class» («method» is covered later)
method Some::Class # «Some::Class» («method» is covered later)
$foo
$main::foo
//i
=head
<<FOO
Class::
Some::Class::
LABEL:
字符串字面量,后跟=> 或整个哈希索引表达式时。
这不适用于合格的标识符。
my %h = ( a => 1 );
$h{a}
变量名,当整个解引用表达式。
${foo}
${main::foo}
请注意,使用关键字、命名运算符或声明的子名称将导致ambiguous use 警告。
关键字。
while (1) { }
sub { }
use
__END__
Sub 调用,当以前导入的 sub 的名称时。
use Time::HiRes qw( time );
time
main::time
调用命名列表运算符、命名一元运算符或命名空元运算符。
print $x, $y, $z;
$c = chr $i;
$t = time;
$t = CORE::time;
标签,当用作next、last、redo 或goto 的操作数时。
将合格标识符视为标签会导致编译错误,因为标签不能是合格标识符。
next LABEL;
子调用或内联常量,当之前声明的子或常量的名称时。
sub foo { }
foo # Calls sub «foo»
main::foo # Calls sub «foo»
sub bar;
bar # Calls sub «bar»
use constant FOO => 123;
FOO # Replaced with the value of the constant.
间接方法调用,后跟可能限定标识符、后缀为::的可能限定标识符、标量(包括数组元素或散列元素)或块。
method Class # Calls method «method» («Class» is covered earlier)
method Some::Class # Calls method «method» («Some::Class» is covered earlier)
method Class:: # Calls method «method» («Class» is covered earlier)
method Some::Class:: # Calls method «method» («Some::Class» is covered earlier)
method $o # Calls method «method»
method { $o } # Calls method «method»
Base::method Class # Calls method «Base::method» («Class» is covered earlier)
您可以使用no indirect pragma 在以这种方式解析代码时发出警告。
Glob,当用作期望文件句柄的运算符的操作数时。
open(FH, '>', $qfn) or die $!; # Equivalent to open(*FH, ...) or ...;
print FH "Hello, World!\n"; # Equivalent to print *FH ...;
print main::FH "Hello, World!\n"; # Equivalent to print *main::FH ...;
字符串字面量,在以下情况下:
当用作直接方法调用的调用者时。
Class->method(@args) # Uses the string «Class» as the invocant.
Some::Class->method(@args) # Uses the string «Some::Class» as the invocant.
用作一元减号的操作数时。
-foo
-foo::bar
当用作原型为* 的子参数时。
sub myprint(*@);
myprint(FH, "Hello, World\n");
myprint(main::FH, "Hello, World\n");
字符串字面量。 use strict qw( subs ); 不允许这样做。
希望我没有错过任何一个。
感谢@mosvy、@Grinnz 和@stevesliva!每个人都发现了一些我错过的案例。
目前失踪:
funcname 在sort funcname。
BEGIN 和类似的。它们有时充当关键字,有时充当声明的子项。
导入名为print 的子不遵循上述步骤。
$ perl -M5.010 -e'
use subs qw( time );
eval { time; };
say $@ =~ /Undefined sub/ ? "ok" : "bad";
'
ok
$ perl -M5.010 -e'
use subs qw( system );
eval { system; };
say $@ =~ /Undefined sub/ ? "ok" : "bad";
'
ok
$ perl -M5.010 -e'
use subs qw( print );
eval { print; };
say $@ =~ /Undefined sub/ ? "ok" : "bad";
'
bad
我不知道是什么让那个特别,我不知道是否还有其他的。我猜是因为print 没有原型,而system 也没有原型。
【讨论】:
package method args 语法吗? use strict; sub bar::foo {} foo bar foo bar。不,它与print STDOUT 不一样,因为print(STDOUT "foo\n") 有效,但通常不是method(PKG "foo\n")。
method package args。作为推论,一些像 print/say 和 system/exec 这样的内置函数接受第一个不带逗号的参数,假装使用间接对象语法,但实际上是解析器的特殊情况。
sort 的第一个参数,它采用裸词作为子名称,而不管严格的“子”。
goto eval 'some_sub' 中的eval 被视为运算符(#6),但goto some_sub 中的some_sub 被视为标签(#7),而不是子调用(#9)。