PHP中的语言结构和“内置”函数有什么区别?
我知道include
, isset
, require
, print
, echo
,还有一些不是函数,而是语言结构。
其中一些语言结构需要括号,其他语言则不需要。
require 'file.php'; isset($x);
有些人有回报价值,有些则没有。
print 'foo'; //1 echo 'foo'; //no return value
那么,语言结构和内置函数之间的内部差异是什么?
(这个比我想要的要长,请耐心等待。)
大多数语言都是由一些被称为“语法”的东西组成的:语言由几个明确定义的关键字组成,用这种语法可以构build完整的expression式范围。
例如,假设你有一个简单的四函数算术“语言”,它只以一位数的整数作为input,完全忽略了操作的顺序(我告诉你这是一种简单的语言)。 该语言可以通过以下语法来定义:
// The | means "or" and the := represents definition $expression := $number | $expression $operator $expression $number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 $operator := + | - | * | /
从这三条规则中,可以构build任意数量的单数字input算术expression式。 然后,您可以为此语法编写一个parsing器,将任何有效的input分解为其组件types( $expression
, $number
或$operator
)并处理结果。 例如,expression式3 + 4 * 5
可以分解如下:
// Parentheses used for ease of explanation; they have no true syntactical meaning $expression = 3 + 4 * 5 = $expression $operator (4 * 5) // Expand into $exp $op $exp = $number $operator $expression // Rewrite: $exp -> $num = $number $operator $expression $operator $expression // Expand again = $number $operator $number $operator $number // Rewrite again
现在我们有了一个完全parsing的语法,用我们定义的语言来表示原始expression式。 一旦我们有了这个,我们可以通过编写一个parsing器来查找$number $operator $number
的所有组合的结果,并且只剩下一个$number
时候就吐出一个结果。
请注意,我们原始expression式的最终parsing版本中没有留下$expression
结构。 这是因为$expression
总是可以减less到我们的语言中的其他东西的组合。
PHP是相同的:语言结构被认为是相当于我们的$number
或$operator
。 它们不能被简化成其他的语言结构 ; 相反,他们是build立语言的基础单位。 函数和语言结构之间的关键区别在于:parsing器直接处理语言结构。 它将function简化为语言结构。
语言构造可能需要或不需要括号的原因以及某些返回值的原因,而其他原因则完全取决于PHPparsing器实现的具体技术细节。 我对parsing器的工作方式并不十分熟悉,所以我不能专门解决这些问题,但想象一下,以这种方式开始的语言:
$expression := ($expression) | ...
实际上,这种语言可以自由地采取它find的任何expression式,并摆脱周围的括号。 PHP(在这里,我正在使用纯猜测)可能会采用类似的语言结构: print("Hello")
可能会减lessprint "Hello"
之前分析,反之亦然(语言定义可以添加圆括号以及摆脱他们)。
这就是为什么你不能重新定义echo
或print
这样的语言结构的根源:它们被有效地硬编码到parsing器中,而函数被映射到一组语言结构,parsing器允许你在编译或者编译时改变映射运行时replace您自己的一组语言结构或expression式。
在一天结束时,结构和expression式之间的内部差异是这样的:语言结构被parsing器理解和处理。 由语言提供的内置函数在parsing之前被映射并简化为一组语言结构。
更多信息:
- Backus-Naurforms ,用于定义forms语言的语法(yacc使用这种forms)
编辑:通过其他一些答案阅读,人们说得好点。 其中:
- 内build的语言比函数更快。 这是真的,如果只是勉强的,因为在parsing之前,PHP解释器不需要将该函数映射到其语言内置的等价物。 然而,在现代机器上,差异是微不足道的。
- 内置的语言绕过错误检查。 这可能会也可能不会是真实的,这取决于每个内置的PHP内部实现。 通常情况下,函数通常会有更高级的错误检查和其他没有的function。
- 语言结构不能用作函数callback。 这是真的,因为构造不是一个function 。 他们是独立的实体。 当你编译一个内build函数时,你不会编码一个带参数的函数 – 内build函数的语法直接由parsing器处理,并且被识别为一个内build函数,而不是一个函数。 (如果考虑具有一streamfunction的语言,这可能会更容易理解:实际上,您可以将对象作为对象传递给函数,而不能使用内build函数来实现。
语言结构是由语言本身提供的(例如“if”,“while”等指令)。 因此他们的名字。
这样做的一个结果就是它们比预定义或用户定义的函数调用要快(或者我多次听说过/读过)
我不知道它是如何完成的,但是他们可以做的一件事(因为直接集成到了语言中)正在绕过某种error handling机制。 例如,isset()可以与不存在的variables一起使用,不会引起任何注意,警告或错误。
function test($param) {} if (test($a)) { // Notice: Undefined variable: a } if (isset($b)) { // No notice }
*请注意,并非所有语言的结构都是这样。
函数和语言结构之间的另一个区别是,其中一些可以不带括号的方式调用,就像关键字一样。
例如 :
echo 'test'; // language construct => OK function my_function($param) {} my_function 'test'; // function => Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING
这里也不是所有语言结构的情况。
我想绝对没有办法“禁用”一种语言结构,因为它是语言本身的一部分。 另一方面,很多“内置的”PHP函数并不是真正的内置的,因为它们是由扩展提供的,因此它们总是处于活动状态(但不是全部)
另一个区别是,语言结构不能被用作“函数指针”(我的意思是,callback,例如):
$a = array(10, 20); function test($param) {echo $param . '<br />';} array_map('test', $a); // OK (function) array_map('echo', $a); // Warning: array_map() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name
我现在没有任何其他的想法了…我对PHP的内部知识不太了解…所以现在就这样吧^^
如果你在这里没有得到太多的答案,也许你可以问这个邮件列表的内部 (见http://www.php.net/mailing-lists.php ),那里有很多PHP核心开发者; 他们是那些可能会知道那些东西^^
(我真的很感兴趣的其他答案,btw ^^)
作为参考: PHP中关键字和语言结构的列表
通过代码涉水后,我发现phpparsingyacc文件中的一些语句。 所以他们是特例。
(请参阅Zend / zend_language_parser.y)
除此之外,我不认为还有其他的区别。
您可以覆盖内置函数 。 关键词是永远的。