“[”如何成为 PHP 语言规范中的运算符?
How can "[" be an operator in the PHP language specification?
在 http://php.net/manual/en/language.operators.precedence.php 网页上,第二高优先级包含一个名为 [
的左结合运算符。
我不明白。是 [
用于 access/modify 数组条目,如 $myArray[23]
吗?我无法想象任何代码片段我们需要知道其他运算符的 "precedence",或者 [
的 "associativity" 有用的地方。
在PHP中,您可以使用[]
初始化空数组,因此为了了解如何定义数组,下一个字符的优先级定义了如何初始化数组。
由于数组是语法结构的一部分,它在任何数学之前完成,因此它比其他计算运算符具有更高的优先级。
var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array's must be known before applying the operator
不过老实说我不太明白这个问题。在大多数编程语言中,[
和 ]
与数组关联,数组是始终具有高优先级(如果不是最高)
的基本语法的一部分
这只是意味着数组变量(左关联性 - $first)将在数组键(右关联性 - $second)之前计算
$first[$second]
当数组具有多个维度时,这很有意义
$first[$second][$third][$fourth]
这是一个非常有效的问题。
1。 [...]
之间的优先级
首先,PHP 在查看
[
的右侧,因为括号需要一个结束括号,所以
中间的每个运算符都优先于左括号。
示例:
$a[1+2]
+
有优先权,即首先 1+2 必须在 PHP 确定之前计算
从 $a.
检索的元素
但是运算符优先级列表与此无关。
2。结合性
其次是评估连续对 []
的顺序,如下所示:
$b[1][2]
PHP 将首先评估 $b[1]
,然后将 [2]
应用于它。这是 left-to-right
评估并且是 左结合性 .
的目的
但手头的问题与其说是结合性,不如说是关于其他运算符的优先级。
3。优先于左侧的运算符
该列表指出 clone
和 new
运算符优先于 [
,这不容易测试。
首先,大多数将 new
与方括号组合在一起的结构都被认为是无效的
句法。例如,这两个语句:
$a = new myClass()[0];
$a = new myClass[0];
会给出解析错误:
syntax error, unexpected '['
PHP 要求您添加括号以使语法有效。所以我们无法测试
优先规则是这样的。
但还有另一种方法,使用包含 class 名称的变量:
$a = new $test[0];
这个 是 有效的语法,但现在的挑战是制作一个 class 来创建一些东西
就像一个数组。
这不是一件容易的事,因为对象 属性 是这样引用的:obj->prop
,不是
喜欢 obj["prop"]
。但是,可以使用 ArrayObject class which can deal with square brackets. The idea is to extend this class and redefine the offsetGet method 来确保 class 的新对象具有 return.
的数组元素
为了使对象可打印,我最终使用了神奇的方法 __toString,当需要将对象转换为字符串时执行该方法。
所以我想出了这个set-up,定义了两个相似的classes:
class T extends ArrayObject {
public function __toString() {
return "I am a T object";
}
public function offsetGet ($offset) {
return "I am a T object's array element";
}
}
class TestClass extends ArrayObject {
public function __toString() {
return "I am a TestClass object";
}
public function offsetGet ($offset) {
return "I am a TestClass object's array element";
}
}
$test = "TestClass";
有了这个 set-up 我们可以测试一些东西。
测试 1
echo new $test;
这条语句创建了一个新的TestClass实例,然后需要将其转换为
字符串,因此 __toString 方法在该新实例上被调用,即 returns:
I am a TestClass object
这符合预期。
测试 2
echo (new $test)[0];
这里我们从相同的操作开始,因为括号强制首先执行 new
操作。这次PHP并没有将创建的对象转换为字符串,而是从中请求数组元素0。此请求由 offsetGet 方法响应,因此上述语句输出:
I am a TestClass object's array element
测试 3
echo new ($test[0]);
这个想法是强制执行相反的顺序。可悲的是,PHP 不允许这种语法,因此必须将语句分成两部分才能获得预期的评估顺序:
$name = $test[0];
echo new $name;
所以现在先执行[
,取值的第一个字符
$test,即 "T",然后 new
应用于它。这就是为什么我
还定义了一个 T class。 echo
在那个实例上调用 __toString,结果是:
I am a T object
现在进行最终测试,看看没有括号时的顺序是什么:
测试 4
echo new $test[0];
这是有效的语法,并且...
4。结论
输出为:
I am a T object
所以事实上,PHP 在 new
运算符之前应用了 [
,尽管在
operator precedence table!
5。比较 clone
与 new
clone
运算符与 [
结合使用时具有相似的行为。奇怪的是,clone
和 new
在语法规则上并不完全相等。使用 clone
:
重复测试 2
echo (clone $test)[0];
产生解析错误:
syntax error, unexpected '['
但是用 clone
重复的测试 4 表明 [
优先于它。
@bishop 告知这重现了长期存在的文档错误 #61513: "clone
operator precedence is wrong"。
在 http://php.net/manual/en/language.operators.precedence.php 网页上,第二高优先级包含一个名为 [
的左结合运算符。
我不明白。是 [
用于 access/modify 数组条目,如 $myArray[23]
吗?我无法想象任何代码片段我们需要知道其他运算符的 "precedence",或者 [
的 "associativity" 有用的地方。
在PHP中,您可以使用[]
初始化空数组,因此为了了解如何定义数组,下一个字符的优先级定义了如何初始化数组。
由于数组是语法结构的一部分,它在任何数学之前完成,因此它比其他计算运算符具有更高的优先级。
var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array's must be known before applying the operator
不过老实说我不太明白这个问题。在大多数编程语言中,[
和 ]
与数组关联,数组是始终具有高优先级(如果不是最高)
这只是意味着数组变量(左关联性 - $first)将在数组键(右关联性 - $second)之前计算
$first[$second]
当数组具有多个维度时,这很有意义
$first[$second][$third][$fourth]
这是一个非常有效的问题。
1。 [...]
之间的优先级首先,PHP 在查看
[
的右侧,因为括号需要一个结束括号,所以
中间的每个运算符都优先于左括号。
示例:
$a[1+2]
+
有优先权,即首先 1+2 必须在 PHP 确定之前计算
从 $a.
但是运算符优先级列表与此无关。
2。结合性
其次是评估连续对 []
的顺序,如下所示:
$b[1][2]
PHP 将首先评估 $b[1]
,然后将 [2]
应用于它。这是 left-to-right
评估并且是 左结合性 .
但手头的问题与其说是结合性,不如说是关于其他运算符的优先级。
3。优先于左侧的运算符
该列表指出 clone
和 new
运算符优先于 [
,这不容易测试。
首先,大多数将 new
与方括号组合在一起的结构都被认为是无效的
句法。例如,这两个语句:
$a = new myClass()[0];
$a = new myClass[0];
会给出解析错误:
syntax error, unexpected '['
PHP 要求您添加括号以使语法有效。所以我们无法测试 优先规则是这样的。
但还有另一种方法,使用包含 class 名称的变量:
$a = new $test[0];
这个 是 有效的语法,但现在的挑战是制作一个 class 来创建一些东西 就像一个数组。
这不是一件容易的事,因为对象 属性 是这样引用的:obj->prop
,不是
喜欢 obj["prop"]
。但是,可以使用 ArrayObject class which can deal with square brackets. The idea is to extend this class and redefine the offsetGet method 来确保 class 的新对象具有 return.
为了使对象可打印,我最终使用了神奇的方法 __toString,当需要将对象转换为字符串时执行该方法。
所以我想出了这个set-up,定义了两个相似的classes:
class T extends ArrayObject {
public function __toString() {
return "I am a T object";
}
public function offsetGet ($offset) {
return "I am a T object's array element";
}
}
class TestClass extends ArrayObject {
public function __toString() {
return "I am a TestClass object";
}
public function offsetGet ($offset) {
return "I am a TestClass object's array element";
}
}
$test = "TestClass";
有了这个 set-up 我们可以测试一些东西。
测试 1
echo new $test;
这条语句创建了一个新的TestClass实例,然后需要将其转换为 字符串,因此 __toString 方法在该新实例上被调用,即 returns:
I am a TestClass object
这符合预期。
测试 2
echo (new $test)[0];
这里我们从相同的操作开始,因为括号强制首先执行 new
操作。这次PHP并没有将创建的对象转换为字符串,而是从中请求数组元素0。此请求由 offsetGet 方法响应,因此上述语句输出:
I am a TestClass object's array element
测试 3
echo new ($test[0]);
这个想法是强制执行相反的顺序。可悲的是,PHP 不允许这种语法,因此必须将语句分成两部分才能获得预期的评估顺序:
$name = $test[0];
echo new $name;
所以现在先执行[
,取值的第一个字符
$test,即 "T",然后 new
应用于它。这就是为什么我
还定义了一个 T class。 echo
在那个实例上调用 __toString,结果是:
I am a T object
现在进行最终测试,看看没有括号时的顺序是什么:
测试 4
echo new $test[0];
这是有效的语法,并且...
4。结论
输出为:
I am a T object
所以事实上,PHP 在 new
运算符之前应用了 [
,尽管在
operator precedence table!
5。比较 clone
与 new
clone
运算符与 [
结合使用时具有相似的行为。奇怪的是,clone
和 new
在语法规则上并不完全相等。使用 clone
:
echo (clone $test)[0];
产生解析错误:
syntax error, unexpected '['
但是用 clone
重复的测试 4 表明 [
优先于它。
@bishop 告知这重现了长期存在的文档错误 #61513: "clone
operator precedence is wrong"。