Clojure可以不用吗?

Hen*_*gon 6 clojure

我发现我很少let在Clojure中使用.出于某种原因,当我开始学习并从那时起就避免使用它时,我不喜欢它.当流动时,感觉流动停止了let.我想知道,你认为我们可以完全没有它吗?

Ron*_*ell 12

让我们提供一些好处.首先,它允许在功能上下文中进行值绑定.其次,它赋予了可读性好处.因此,虽然从技术上讲,人们可以废除它(在某种意义上你仍然可以在没有它的情况下进行编程),如果没有一个有价值的工具,语言就会变得贫穷.

关于let的好处之一是它有助于形式化指定计算的通用(数学)方法,在该方法中引入方便的绑定,然后引入简化的公式.很明显,绑定仅适用于"范围",并且它与更多数学公式的结合是有用的,特别是对于更多功能的程序员.

让阻塞出现在像Haskell这样的其他语言中并不是巧合.


Cub*_*bic 12

您可以更换任何发生(let [a1 b1 a2 b2...] ...)((fn [a1 a2 ...] ...) b1 b2 ...)所以是的,我们可以.我虽然使用了很多,但我宁愿不做它.

  • 实际上`(让[a1 b1 a2 b2] ...)`更好地解释为`(((fn [a1](fn [a2] ...))b1)b2)`.我的意思是你可以参考后续的绑定._Edit:_括号,我们都爱他们. (4认同)
  • @Hendekagon当然,您可以重构代码中的每一个let.我倾向于将它用于非常局部化的情况,而且我宁可使一个函数混乱,而不是混乱程序的其余部分,我只需要在一个地方使用一个行函数. (3认同)
  • 事实上,我认为这个答案可以解决问题:也许每次使用let都是一个分解另一个功能的机会?也许这表明代码的那部分太复杂了? (2认同)

Art*_*ldt 6

让我在防止宏中的多次执行方面是必不可少的:

(defmacro print-and-run [s-exp]
   `(do (println "running " (quote ~s-exp) "produced " ~s-exp)
        s-exp))
Run Code Online (Sandbox Code Playgroud)

会运行两次s-exp,这不是我们想要的:

(defmacro print-and-run [s-exp]
  `(let [result# s-exp]
    (do (println "running " (quote ~s-exp) "produced " result#)
        result#))
Run Code Online (Sandbox Code Playgroud)

通过将表达式的结果绑定到名称并引用该结果两次来修复此问题.

因为宏返回的表达式将成为另一个表达式的一部分(宏是生成s表达式的函数),它们需要生成本地绑定以防止多次执行并避免符号捕获.


mob*_*yte 5

我想我理解你的问题.如果错了,请纠正我.有时候"let"用于命令式编程风格.例如,

... (let [x (...)
          y (...x...)
          z (...x...y...)
          ....x...y...z...] ...
Run Code Online (Sandbox Code Playgroud)

这种模式来自命令式语言:

... { x = ...;
      y = ...x...;
      ...x...y...;} ...
Run Code Online (Sandbox Code Playgroud)

你避免这种风格,这就是为什么你也避免"让",不是吗?

在一些问题中,命令式样式减少了代码量.此外,有时用java或c写入更有效.在某些情况下,"let"只保存子表达式的值,而不管评估顺序如何.例如,

(... (let [a (...)
           b (...)...]
        (...a...b...a...b...) ;; still fp style
Run Code Online (Sandbox Code Playgroud)