- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这是一个一般性的问题,但为了解释它,我将使用一个具体的例子。
我有一个加载文档的函数。如果该文档不存在,它将创建它,如果它存在,它将把它转换为一个 JSON 数组。我总是希望此函数返回某种数组,无论 json_decode()
是否存在问题,或者文件是否不存在。目前我是这样做的......
function load($file) {
if( ! file_exists($file)) {
$handle = fopen($file, 'w');
fclose($handle);
}
$raw = file_get_contents($file);
$contents = json_decode($raw, TRUE);
return( ! $contents ? array() : $contents);
//cant use ternary shorthand "?:" in PHP 5.2, otherwise this would be shorter
}
现在,上面的代码没有任何问题(至少我认为没有问题而且它工作正常)。然而,我一直在寻找方法来改进我的代码并压缩它,同时保持它完全易读。那个 return 语句一直困扰着我,因为它看起来效率低下。所以今天我开始思考,我想到了一些事情。我记得看到 mysql 教程对 connect() 或 die();
的效果做了一些事情,所以我想,为什么不用 json_decode() 或 array();
?这甚至可以工作吗?所以我重写了我的函数以找出...
function load($file) {
if( ! file_exists($file)) {
$handle = fopen($file, 'w');
fclose($handle);
}
$raw = file_get_contents($file);
return json_decode($raw, TRUE) or array();
}
看起来,甚至读起来也很愉快。那么我的下一轮问题。这是好习惯吗?我明白,但其他人会吗?它真的有用吗,或者这是一个大团圆结局的错误?我环顾四周,发现我要问的是所谓的短路评估,而不是错误。很高兴知道。我使用这个新术语来改进我的搜索并找到了更多 Material 。
我发现的关于使用短路的内容并不多,而且我发现的大多数内容都以我询问的方式总是指的是 MySQL 连接。现在,我知道大多数人都反对使用 或 die()
术语,但这只是因为它是处理错误的一种不优雅的方式。对于我所询问的方法而言,这不是问题,因为我不打算使用 或 die()
。还有其他不使用它的理由吗?维基百科似乎是这么认为的,但只是引用了 C。我知道 PHP 是用 C 编写的,所以这绝对是相关信息。但是这个问题在 PHP 编译中已经被解决了吗?如果不是,是否像维基百科所说的那样糟糕?
这是来自维基百科的片段。
维基百科 - “短路会导致现代处理器的分支预测错误,并显着降低性能(一个显着的例子是光线追踪中高度优化的光线与轴对齐的框相交代码)[需要澄清]。一些编译器可以检测到这种情况并发出更快的代码,但由于可能违反 C 标准,这并不总是可能的。高度优化的代码应该使用其他方式来做到这一点(如手动使用汇编代码)“
大家怎么看?
编辑
我已经对另一个论坛进行了投票,并在那里获得了一些不错的结果。普遍的共识似乎是这种形式的变量赋值虽然有效,但并不受欢迎,甚至可能被认为是现实世界中的不良形式。我会继续关注实地情况,如果有任何新消息出现,我会对此进行更新。感谢 Corbin 和 Matt 的投入,尤其是 Corbin 整理了一些内容。 Here如果您感兴趣,请提供论坛帖子的链接。
最佳答案
您提出了几个不同的问题,所以我会尽力一一解答。
遗漏分支预测:除非您使用 C 或汇编语言编写代码,否则不要担心这一点。在 PHP 中,您与硬件相距甚远,以至于考虑分支预测对您没有帮助。无论哪种方式,这都将是一个非常微观的优化,尤其是在一个开始进行大量字符串解析的函数中。
Is there any other reason not to use this? Wikipedia seems to think so, but only in reference to C. I know PHP is written in C, so that is definitely pertinent information.
PHP 可能会将其解析为不同的执行结构。除非您计划将此功能运行数百万次,或者您知道这是一个瓶颈,否则我不会担心。在 2012 年,我发现使用 或
短路几乎不可能导致十亿分之一秒的差异。
至于格式,我发现 $a 或 $b
相当难看。我的头脑无法像在 if 子句中看到的那样理解短路。
if (a() || b())
在我看来,只有当 a() 的计算结果不为真时,b() 才会执行。
但是:
return a() or b();
对我来说没有同样的清晰度。
这显然只是一种意见,但我会提供两种替代方案来说明我可能会如何编写它(在我看来,这更清楚一点):
function load($file) {
if (!file_exists($file)) {
touch($file);
return array();
}
$raw = file_get_contents($file);
$contents = json_decode($raw, true);
if (is_array($contents)) {
return $contents;
} else {
return array();
}
}
如果您不关心文件是否真的被创建,您可以更进一步:
function load($file) {
$raw = file_get_contents($file);
if ($raw !== false) {
$contents = json_decode($raw, true);
if ($contents !== null) {
return $contents;
}
}
return array();
}
我想这些代码片段真的归结为个人喜好。第二个片段可能是我会选择的片段。其中的关键路径可能更清晰一些,但我觉得它在不牺牲可理解性的情况下保持简洁。
编辑:如果您是每个函数返回 1 个类型的人,则以下内容可能更可取:
function load($file) {
$contents = array();
$raw = file_get_contents($file);
if ($raw !== false) {
$contents = json_decode($raw, true);
if ($contents === null) {
$contents = array();
}
}
return $contents;
}
关于PHP 短路评估(好/坏?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10506936/
考虑 function foo(x) x isa Bar || throw(ArgumentError("x is not a Int64...")) dosomething(x) e
这个问题在这里已经有了答案: AndAlso/OrElse in VBA (8 个回答) 7年前关闭。 VBA 不会短路 VBA 不支持短路 - 显然是因为它只有按位 And/Or/Not 等操作。来
这个问题在这里已经有了答案: Java operator precedence guidelines (6 个答案) 关闭 7 年前。 你好,我有一个关于 java 中的优先级表的问题。它说 &&
a &= foo(); 只是被 C++ 中的 a = a && foo(); 取代还是还有更多内容? 我关心的是 foo() 的计算。如果 a 为假,它会被调用吗? 最佳答案 && 是否有嵌入式短路:
我正在尝试注释以下代码。 当同时定义了 zone 和 zones 时,或者当定义了 file 时(但不是同时定义了两者),该函数将起作用: def get_file(zone: str, zones:
给定远程beam.smp服务的已知TCP端口和名称,以及已知的cookie,是否可以短路Erlang分发协议(protocol)的Erlang端口映射器守护进程握手阶段并直接建立Erlang shel
我正在尝试注释以下代码。 当同时定义了 zone 和 zones 时,或者当定义了 file 时(但不是同时定义了两者),该函数将起作用: def get_file(zone: str, zones:
我需要从第二个表中查询数据,但前提是满足主表中的一组罕见条件: SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM ta
如标题所述,我想将 onchange 短路(在选择内部)。我有以下代码,但我只想发送一个硬编码值而不显示选择框。 "> [编辑] 对不起,我不清楚。我什至不想提供
我是 C++ 的新手,很好奇编译器如何处理 bool 值的惰性求值。例如, if(A == 1 || B == 2){...} 如果 A 确实等于 1,那么 B==2 部分是否曾经计算过? 最佳答案
我在尝试让这个 linq 语句起作用时遇到了一些麻烦。我正在使用 linq 查询设置搜索。我想要做的是,如果搜索为空或为空,让它忽略过滤的那一部分。所以我设置了很多 where 子句来缩短 where
这个问题在这里已经有了答案: How to short-circuit a reduce() operation on a Stream? (4 个答案) 关闭 4 年前。 在做项目的时候写了这行,
首先,我不是 Bash 专家。几个月前我发现,如果我同时使用 && 和 || 短路运算符和花括号,那么如果第一个语句以真实值退出,如果 true block 中的最后一条语句退出非零,那么 fail
我有一个使用逻辑 OR 运算符的 NSPredicate,如下所示: NSPredicate(format: "activeFrom == NULL OR %@ >= activeFrom", som
我是 C++ 的新手,很好奇编译器如何处理 bool 值的惰性求值。例如, if(A == 1 || B == 2){...} 如果 A 确实等于 1,那么 B==2 部分是否曾经计算过? 最佳答案
我需要从第二个表中查询数据,但前提是满足主表中的一组罕见条件: SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM ta
我遇到了这段代码: 我想我们可以归纳为: 然后我找到了这个 article on short circuits和另一个 more focused one一旦我知道他们叫什么。但是,我还是不明白。
据我了解和阅读,您可以在 if 语句(&& 或 ||)中使用短路,以使第二个条件不触发。如果您希望两个条件都触发,您可以使用单个操作数(& 或 |)。 假设我有如下内联 if 语句: var test
在玩弄编译时字符串(char 的可变参数列表)操作时,我需要实现一种方法来检查编译时字符串是否包含另一个(较小的)编译时字符串。 这是我的第一次尝试: template struct Contains
如果我有以下... a OrElse b ... 并且 a 是 真那么显然 b 永远不会被评估。但是如果我添加一个 Or ,然后呢? a OrElse b Or c c 是否/应该得到评估?如果我放入
我是一名优秀的程序员,十分优秀!