编程学习biancheng.45soft.com 本站提供了各种在线教程和资料,供大家学习与参考.
编程学习
当前位置: 主页 > Perl > 函数 >

Perl 函数


为了便于参考,本章以字母顺序(注:有时候,紧密联系的函数在系统手册页里组合在一起,因此我们在这里也将尊重那些分组。比如,要寻找 endpwent 的描述,你得先找 getpwent。)描述内建的 Perl 函数。每个函数描述以一个该函数语法的简短概要开头。象 THIS 这样的参数名字代表实际表达式的占位符,而跟在语法概要后面的文本将描述提供(或者省略)该实际参数的语意。


你可以把函数和文本以及变量想象成一个表达式里的项。或者你可以把它们想象成前缀操作符,处理它后面的参数。要知道我们有一半时间叫它们操作符。


这些操作符,哦,是函数,中有一些接受一个 LIST 作为一个参数。这个 LIST 的元素应该用逗号分隔(或者用 =>,它只是逗号的一种有趣的形式)。这个 LIST 的元素在列表环境中计算,所以每个元素都会返回一个标量或者一个列表值——取决于它对列表环境的敏感程度。每个返回的值,不管是标量还是列表,都会被解释成一个总体标量值序列的一部分。也就是说,把所有列表平面化成一个列表。从接收参数的函数的角度来看,全部参数 LIST 总是一个一维列表数值。(要把一个数组代换成一个元素,你必须明确地创建一个引用并用它代换该数组。)


预定义的 Perl 函数既可以带着圆括弧使用,也可以不带圆括弧使用;在本章中的语法概要里是省略圆括弧的。如果你确实使用圆括弧,其简单但有时有些怪异的规则如下:如果它看上去象函数,那它就是函数,所以优先级并不紧要。否则,它就是一个列表操作符或者一个单目操作符,而优先级就有关系了。这里要小心,因为就算你在关键字和它的左圆括弧之间放了空格,也不能不让它成为一个函数:

print 1+2*4       # 打印 9。
print(1+2) * 4;   # 打印 3!
print (1+2)*4;    # 还是打印 3!
print +(1+2)*4;   # 打印12。
print ((1+2)*4)   # 打印12。

如果你带着 -w 开关运行 Perl,它会警告你这些问题。比如,上面的第二和第三行产生下面这样的信息:

print (...) interpreted as function at - line 2.
Useless use of integer multiplcation in void context at - line 2.

给定一些函数的简单定义的前提下,你可以使用的传递参数的方法有相当可观的自由度。比如,使用 chmod 的最常见的方法就是把文件权限(模式)作为一个初始参数传递:

chmod 0644, @array

但是 chmod 的定义只是说:

chmod LIST

所以你也可以说:

unshift @array, 0644;
chmod @array;

如果列表的第一个参数不是一个有效的模式,chmod 调用将失败。但这是一种运行时语意问题,和调用它的语法没有关系。如果该语意要求任何特殊的参数必须先传递,那么文本将描述这些限制。


与简单的 LIST 函数相反,其他函数强制附加的语法约束。比如,push 的语法概要看起来象下面这样:

push ARRAY,LIST

这意味着 push 要求一个正确的数组作为它的第一个参数,但是不在乎随后的参数。那就是最后的 LIST 的意思。(LIST 总是最后出现,因为它把所有剩下的数值都吃掉。)如果一个语法概要在 LIST 之前包含任何参数,那么编译器会认为那些参数是有语法区别的,而不仅仅是在它稍后运行时解释器看到的语意区别。这样的参数从来不会放在列表环境里计算。它们可能会在标量环境里计算,或者它们也可能是象 push 里的数组一样的引用参数。(描述会告诉你某个参数是哪种类型。)


对于那些自身的操作直接基于 C 库的函数,我们不想复制你的系统的文档。如果一个 function 描述里说:参阅 function(2),它的意思就是你应该查看对应的 C 版本的函数,学习更多其语意方面的内容。如果你安装了手册页,那么圆括弧里的数字指示你查阅手册页时会看到的系统程序员手册一节。(当然,如果你没装手册页那么你也看不到。)


这些手册页可能记载了一些系统相关的行为,象 shadow 口令文件,访问控制列表,等等。许多来自 Unix 里的 C 库的 Perl 函数现在甚至在非 Unix 平台上都有仿真。比如,也许你的操作系统可能不支持 flocl(2) 或 fork(2) 系统调用,但 Perl 也会通过使用所有你的平台提供的设施尽可能地模拟这些调用。


有时候,你会发现那些记载了的 C 函数比对应的 Perl 函数的参数多。通常,那些缺少了的参数是 Perl 已经知道的东西,比如前面一个参数的长度,所以你用不着给 Perl 提供它们。任何其他的不同都是因为 Perl 和 C 在声明文件句柄和成功/失败值上的区别造成的。


通常,Perl 里用做系统调用封装的函数和该系统调用同名(比如 chown(2),fork(2), closedir(2),等等),都是成功时返回真,而失败时返回 undef,在随后的描述里也有提到。这样的特性与这些操作的 C 库的接口是不同的,C 接口在失败时都返回 -1。这条规则的例外是 wait,waitpid,和 syscall。系统调用在失败的时候还设置特殊的 $!($OS_ERROR)变量。除非故意,其他函数并不这样做。


对于那些在标量或者列表环境中都可以使用的函数,在标量环境中失败的时候通常是返回一个假值(通常是 undef)来表明而在列表环境中通常是返回空列表。成功地执行通常是用返回一个(在环境中)可以计算出真值的数值来表明的。


记住下面的规则:没有任何规则把一个函数在列表环境中的行为和在标量环境中的行为相互联系起来,反之亦然。这两种情况可能是做两件完全不同的事情。


每个函数都知道它被调用的环境。同一个函数,如果它在列表环境中调用时返回一个列表,那么它在标量环境中调用将返回它认为最合适的任何类型的数值。有些函数返回它在列表环境中返回的列表的长度,有些操作符返回列表中的第一个数值。有些函数返回列表中最后的数值。有些函数返回“其他”数值——如果那些东西可以通过数字或者名字找出。有些函数返回成功操作的计数。通常,Perl 函数会干你想干的事情,除非你想要一致性。


最后一条注意:我们已经非常注意保持自己对“字节”和“字符”两个术语的使用的一致性了。因历史原因,这些术语已经是互相混淆在一起了(并且它们自身也含糊不清)。但是当我们说 “字节”的时候,我们的意思总是一个八位字节,8位。而当我们说到“字符”的时候,我们的意思是一个抽象的字符,“通常”是一个 Unicode 字符,它在你的字串里可能会用一个或更多个字节代表。


不过要注意我们说的“通常”。Perl 在 use bytes 声明的范围里故意混淆了字节和字符的概念,所以如果我们说到“字符”,那么在 use bytes 环境里时你应该把它看作一个字节,否则,看作一个 Unicode。换句话说,use bytes 只是把字符的定义封装回到了老版本的 Perl 里的概念。因此,如果我们说一个标量 reverse 一个字符一个字符地反转一个字串,你就别问我们这里真的意思是字符还是字节,因为答案就是,“没错,它就是干这事。”

Perl
Perl 函数