注意:我知道这是不可接受的代码,我想了解解释器正在做什么,而不是建议如何实现相同的结果!
我已经阅读了足够的内容,意识到我不能也不应该尝试使用|,||或者XOR定义一个开关案例 - 所以请不要评论“不要那样做”的效果,我只是试图理解解释器做什么这些语句和了解行为的陌生感。我正在使用PHP 5.3.1。
这是我实际打算做的,现在正在使用,请不要推荐代码:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -5; //angle from goal
break;
case 1:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -10; //miss penalty
break;
case 3:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -10; //error penalty
break;
}
}
但如果我能做的话,我很好奇:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 || 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 || 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
而且,反过来说,这确实会运行,但是非常慢慢地(比如,秒),虽然它当然不是按照我想要的方式评估(0||1)
(事实上)今天是关于按位和逻辑运算符之间差异的一课。)
但对我来说更好奇的是我可以做到这一点,如果非常缓慢而不是我想要的结果:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
但我可以不这样做:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 XOR 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
这是PHP甚至不会评估的这些可怕,可怕的想法中唯一的一个。
我的问题是:为什么评估这些语句会花费更长时间,为什么最后一个例子不会运行?我认为PHP正在解释0 XOR 1并比较true
和false
,但我无法替换它们并让它仍然评估。有谁知道这里发生了什么?谢谢!
更新
评论请求var_dump($this->header)
(如果不明显,我将我的初始switch语句从7个案例截断为4个,以避免发送相同代码的垃圾邮件,但是,鉴于var_dump()
被要求,我选择发布整件事,万一它揭示了我无法预见的事情!)。另外,是的,事实证明,由于在设置array_values()
之前忘记调用$this->header
,我一直在使用关联数组,在下面的第二个答案中,已经将此错误变为解释持续时间switch
声明,而第一个答案和第二个答案是逻辑的伟大演练。
array(12) {
["theZone"]=>
NULL
["leftMiss"]=>
NULL
["rightMiss"]=>
NULL
["leftError"]=>
NULL
["rightError"]=>
NULL
["leftHit"]=>
NULL
["rightHit"]=>
NULL
["accuracy"]=>
string(5) "false"
["rt"]=>
string(4) "true"
["disease"]=>
string(3) "yes"
["bars"]=>
string(3) "yes"
["endMessage"]=>
NULL
}
答案 0 :(得分:2)
case
值必须为SINGLE值。你不能2 || 3
,因为它会评估为
case (2 or 3) -> case TRUE
同样,如果你使用&&
(and
),你就会得到
case (0 and 1) -> case FALSE
您可以对OR
逻辑使用'fallthrough'行为:
case 2:
case 3:
...code here ...
break;
XOR,你不能这样做。不是简单的案例陈述。
评论后续:
for ($i = 0; $i < 5; $i++) {
switch($i) {
case 0 xor 1: echo "0 xor 1: $i\n"; break;
case 2 xor 3: echo "2 xor 3: $i\n"; break;
}
}
将输出
2x3: 0
0x1: 1
0x1: 2
0x1: 3
0x1: 4
和
php > var_dump(2 xor 3);
bool(false)
php > var_dump(0 xor 1);
bool(true)
请记住,切换案例会评估相同的==
。他们是懒惰的比较,而不是检查类型。因此,2 xor 3
的评估方式与case false
的情况相同,这使得$ i = 0条件匹配。
答案 1 :(得分:1)
这不是让你陷入性能问题的开关。它可能是你的循环与你的开关结合。
我尝试用给出的第二个例子解释它。
但是,我只需要猜测,所以我必须假设您的$ this-&gt;标头数组如下所示(这将是导致性能泄漏的唯一原因):
$this->header = array(
999 => 10, // the value is irrelevant, only the key (2) matters
998 => 15
);
现在让我们玩解释器调试器。
set $i to 0
is $i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? no, because (0 == (0 || 1)) equals (0 == true) equals (false == true) can never be true
is ($i == (2 || 3))? no, because (0 == (2 || 3)) equals (0 == true) equals (false == true) will never comply
next loop, increment $i (set $i to 1)
is ($i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? yes, because (1 == (0 || 1)) equals (1 == true) equals (true == true)
go into case statement
set $this->header[1] to -5 (remember the index 1 does not exist so far in your array)
next loop, increment $i (set $i to 2)
is $i<count($this->header)? yes, because header size is 3 (remember? you just added a new index which incremented your header size)
is ($i == (0 || 1))? yes, because (2 == (0 || 1)) equals (2 == true equals (true == true)
go into case statement
set $this->header[2] to -5 (again index 2 did not exist so far)
next loop, increment $i (set $i to 3)
is $i<count($this->header)? yes, because header size is 4 (again, you just added a new index)
现在这将继续,直到标题大小等于$ i。在上面的例子中,这将在998次迭代之后发生,因为这将是第一次没有新的索引创建(现有的一个 - 998 - 只会被使用),导致计数($ this-&gt;标题)不改变。
在你的第一个例子中,这不会发生。在第四次迭代之后,标头大小将停止更改,因为case语句尝试比较整数值而不是布尔值。一旦到达索引5,它就会尝试与值1,2,3和4进行比较,并且不会匹配单个值,从而导致没有新的索引创建。
要解决性能问题,您应该确保数组中的每个键都存在,并且还要更改for循环,如下所示:
$size = count($this->header);
for($i=0; $i<$size); $i++) {...}
当然,这不会解决您的逻辑问题。但是,既然你问过发生了什么,我想这应该是一个很好的解释。
var_dump() - 循环前后你的$ this-&gt;标题数组应该证明我是正确的:)
===
很抱歉删除并取消删除此答案。只是想确保它真的像解释的那样。如果你能为我提供你的标题数组的var_dump,那就太好了。