在 Clojure REPL 中使用 long let 表达式

Working with long let expressions in Clojure REPL

我经常遇到这种情况,想知道是否有简单的解决方案。假设我有一个 Clojure 源文件,它有一个 let 表达式,如下所示:

(let [a (...)
      b (...)
      c (...)
      d (...)
      e (...)
      f (...)
      g (...)
      h (...)] 
  (...))

其中每个值都取决于上面的某些值。

然后,当我想手动使用在 REPL 中定义 h 的表达式时(假设至少一个输入是某个巨大的映射 JSON 响应或类似的东西手动输入更痛苦),然后我发现自己手动做

(def a (...))
(def b (...))
(def c (...))
(def d (...))
(def e (...))
(def f (...))
(def g (...))

在我什至可以开始尝试弄乱 h 之前。

所以通常这意味着在 REPL 中输入 (def ),然后移动我的鼠标,从 let 表达式中复制 a (...),然后粘贴回 (def )按回车键,然后返回并为 b 做同样的事情,依此类推。

有没有更快的方法来解决这个问题?

这里有一个可能对你有用的技巧:

(let [a (...)
      b (...)
      c (...)
      d (...)
      e (...)
      f (...)
      g (...)
      h (...)
      _ (def h' h)] 
  (...))

显然你永远不会希望在代码中检查这样的东西,但是对于在 REPL 中进行黑客攻击它可能就足够了。

您还可以编写一个宏,它采用 let 形式的绑定并将其转换为一系列 def 形式。

(defmacro letdef [bindings]
  (apply list `do (for [[s expr] (partition-all 2 bindings)]
                    `(def ~s ~expr))))

(letdef [a 1
         b 2
         c 3
         etc (+ a b c)])

(println etc) ;=> 6