链接“let”语句时最好使用“and”或“in”?

Posted

技术标签:

【中文标题】链接“let”语句时最好使用“and”或“in”?【英文标题】:Better to use "and" or "in" when chaining "let" statements? 【发布时间】:2011-09-15 02:21:44 【问题描述】:

我知道这可能是一个愚蠢的问题,但是......

如果我要链接一堆let 语句,而这些语句不需要 需要知道彼此的值,那么使用andin 更好吗?

例如,如果有的话,哪一个更可取:

let a = "foo"
and b = "bar"
and c = "baz"
in
  (* etc. *)

let a = "foo" in
let b = "bar" in
let c = "baz"
in
  (* etc. *)

我的直觉告诉我,前者应该是“更好的”(通过对“更好”的一个非常狭隘的定义),因为它创建了必要的最小范围数量,而后者是一个范围内的范围内-a-scope 编译器/解释器注意但最终并不重要且不必要的深度。

【问题讨论】:

【参考方案1】:

“哪个更好?”问题的答案只有当解释没有不同时才真正有意义。 ML 系列语言(至少是 SML 和 OCaml)既有并行初始化形式 (and) 又有顺序的、本质上是嵌套范围的形式 (in),因为它们在某些情况下都很有用。

在您的情况下,语义是相同的,因此您需要回答“什么对您来说最好读?”这个问题。也许(如果这不是为时过早的话)“可能会更有效地执行?”在您的情况下,替代方案是:

对于and 的情况:计算一堆字符串并并行绑定到三个标识符。

对于in 情况:将foo 绑定到a然后bar 绑定到b然后 绑定@987654329 @到c

哪个更好读?在这种情况下这是一个折腾,因为结果并不重要。你可以对一些说英语的人进行投票,但我怀疑会有很多偏好。也许大多数人会喜欢and,因为它将绑定分开,在表达式之前留下唯一的in

至于什么执行效率更高,我认为一个好的编译器可能会产生相同的代码,因为它可以检测绑定的顺序无关紧要。但也许您有一个编译器可以为多核处理器生成代码,使用and 会更好。或者可能是一个天真的编译器,它将所有 RHS 写入临时存储然后绑定它们,从而使 and 的情况变慢。

这些可能是非必要的优化问题,特别是因为它们涉及绑定并且可能不在紧密循环中。

底线:在这种情况下,这是一个 true 折腾;当结果很重要时,请确保正确使用并行与顺序。

【讨论】:

【参考方案2】:

我的意见是in 更好。 and 的使用意味着定义相互依赖。我认为最好清楚事实并非如此。另一方面,一些 OCaml 程序员确实更喜欢 and 用于非常短的定义,其中稍微更紧凑的符号看起来更清晰。当您可以将定义放在一行时尤其如此:

let a = "foo" and b = "bar" in

【讨论】:

即使使用let rec,它们能否相互依赖? 正如 nimrodm 所说,以下内容不起作用(意味着and 可能并不总是暗示依赖):let a = 3 and b = a + 7 in (* ... *)【参考方案3】:

我相信这与 Lisp 中 letlet* 之间的区别相同。 let*(功能类似于 in..in.. 结构 - 您问题中的第二个结构)有时用于隐藏 命令式 编程,因为它保证了表达式的顺序执行(请参阅 Paul Graham 所说的话关于 let* in On Lisp)。

所以,我会说前一种构造更好。但事实是,我认为后者在我见过的 Ocaml 程序中更常见。可能只是更容易使用,让一个在以前命名的表达式上构建。

【讨论】:

我完全忘记了保证顺序执行;谢谢你提醒我。【参考方案4】:

我会说 in 更好,因为它缩小了范围并更好地表达了意图。如果我看到所有这些定义以共享范围的方式链接在一起,我会觉得这样做是有原因的,并且会寻找它们如何相互影响。

【讨论】:

以上是关于链接“let”语句时最好使用“and”或“in”?的主要内容,如果未能解决你的问题,请参考以下文章

不使用 in 时 let 的范围是啥?

MYSQL IN 或多个条件

Lisp 的 let* 的 Ocaml 等价物?

为啥 for..of / for..in 循环可以使用 const 而普通的 for 循环在 JS 中只能使用 let 或 var 作为其变量? [复制]

MySQL 2 SQL数据使用(检索排序过滤:SELECT/FROM/LIMIT/ORDER BY/DESC/WHERE/AND/OR/IN/NOT)

在 OCaml 中分隔多个“let”声明,后跟一个“let in”表达式