open函数的文档将open()
的语法显示为:
- 打开FILEHANDLE,EXPR
- 打开FILEHANDLE、MODE、EXPR
- 打开FILEHANDLE、MODE、EXPR、LIST
- 打开FILEHANDLE、MODE、REFERENCE
- 打开FILEHANDLE
在下面的例子中,它们有一个普通的$前缀变量用于文件句柄的地方:
open(my $fh, "<", "input.txt")
以及使用裸词的示例:
open(FOO, "|tr '[a-z]' '[A-Z]'");
一个问题是,在每种情况下,"我对文件句柄使用__"中的每个样式的名称是什么?另一个问题是,为什么他们开始在文档中为open()
使用裸词?后面的用法似乎都不涉及正常的文件名open()
s。在这些情况下,前缀为$的形式是不可接受的吗?
裸词形式本质上只是向后兼容性的历史遗留。在新代码中,使用词法变量几乎总是正确的做法。
→顺便提一下,$x
是一个词汇标量变量,其中FOO
,正如您所说,被称为裸词
详细信息/压缩
正如@Joe_Z在评论中指出的那样,为了完整起见,词法文件句柄对象是"相对较新的",这是Perl5.005和5.6之间相当重要的重写的一部分(它们甚至在该版本号中获得了整整一个数量级…)。
然而,从技术上讲,光字FOO
(或,例如STDIN
)在单独的命名空间中被解释为仅用于文件句柄。由于文件句柄名称空间没有sigil(如$ @ % &
),因此只有两种方法可以在该名称空间中引用文件句柄:
- 你可以在某些函数的间接对象槽中引用它,比如
print
,由于历史原因,CCD_9会(在幕后)推断出一个单词必须引用一个文件句柄 - 您可以使用一个typeglob,比如
*FOO
,它指的是"任何命名空间中碰巧绑定到符号FOO
的任何东西
请注意,在某些语言中,如C或Scheme,单个符号没有类型sigils,因此所有符号只能以一种方式绑定(例如,在C中不能有名为printf
的变量和名为CCD13的函数……通常),而在Perl或(例如)Common Lisp中,相同的符号foo
可以绑定到许多不同的东西;区别在于,Perl实际上要求您在大多数上下文中使用sigils来消除"您指的是哪个foo
"的歧义。$foo
、@foo
=@foo[ $x .. $y]
、$foo[ $n ]
、%foo
=@foo{ $k1, $k2 }
=$foo{ $k }
、&foo
等。
然而,使用裸词作为文件句柄,你会失去一些能力:
值得注意的是,为了在本地或词法上(而不是全局)绑定它们,您需要在每个命名空间中绑定每个符号,因为没有可用的sigil。因此,my $foo
和my @foo
可以生活在两个不同的暂存区(范围)中,其中一个可能比另一个更长寿;但my *foo
将同时包括这两个,以及文件句柄foo
(以及可能的其他模糊的角情况,如format
说明符,尽管我不会发誓)。
将一个裸词风格的文件句柄传递到函数中也是非常困难的,等等。
基本上,裸词继承了全局范围的所有缺点,而没有词汇变量的优点。
perldoc perldata
有一个关于Typeglobs和Filehandles的很好的部分,它可能也更清楚地解释了这些事情。我手头没有复印件,但我相信《骆驼》在这个主题上也会有更多的细节。
正如BPRocock所说,my $x
现在是首选,而FOO
被认为是过时的,因为FOO
是一种全局变量,因此它可能与其他地方使用的名称冲突。鼓励使用$x
还有另一个原因:$x
将在作用域结束时自动使用close
。