为什么Perl open()文档使用两种不同的FILEHANDLE样式



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 $foomy @foo可以生活在两个不同的暂存区(范围)中,其中一个可能比另一个更长寿;但my *foo将同时包括这两个,以及文件句柄foo(以及可能的其他模糊的角情况,如format说明符,尽管我不会发誓)。

将一个裸词风格的文件句柄传递到函数中也是非常困难的,等等。

基本上,裸词继承了全局范围的所有缺点,而没有词汇变量的优点。

perldoc perldata有一个关于Typeglobs和Filehandles的很好的部分,它可能也更清楚地解释了这些事情。我手头没有复印件,但我相信《骆驼》在这个主题上也会有更多的细节。

正如BPRocock所说,my $x现在是首选,而FOO被认为是过时的,因为FOO是一种全局变量,因此它可能与其他地方使用的名称冲突。鼓励使用$x还有另一个原因:$x将在作用域结束时自动使用close

最新更新