【问题标题】:How to have clojure support related values in binding?如何在绑定中让 clojure 支持相关值?
【发布时间】:2015-01-26 14:14:49
【问题描述】:

我使用绑定来简化调用中的状态传递。我目前有类似以下的内容

(binding [*private-key-path*  "/Users/dcapwell/.ssh/id_dsa"]
  (binding [*session* (session "localhost")]
   ...

我需要这样做的原因是会话函数需要定义 private-key-path。由于绑定不允许相关值,有没有更简单的方法可以在没有嵌套的情况下完成上述操作?

编辑:

目前使用 clj-ssh.ssh 进行原型设计。计划是让我当前对绑定的大部分使用成为静态配置(大多数已经是静态值,所以在启动时读取一次)。使用绑定作为简化原型设计的一种方式,这样我就不必在查看 API 的工作原理时不断传递东西。

我只是好奇如何让绑定相互依赖。当我使用 let 时,第二个绑定可以访问第一个绑定,但是当我这样做时,第二个绑定似乎无法访问第一个绑定。我假设会有另一个功能类似于绑定,但允许第二个绑定访问第一个。我还可以看到这在默认情况下不存在,因为它的状态比其他任何东西都多。

【问题讨论】:

  • 对不起,我不明白你为什么不将*private-key-path* 作为参数传递给会话函数。无论如何,你可以看看clojuredocs.org/clojure.core/with-redefs
  • 另外,binding - 像 let - 允许给出多个绑定,例如(binding [*out* some-stream, *err* some-stream] ...).
  • 就像 James Sharp 所说的,私钥路径应该是会话函数的参数。对每个可配置的设置都使用绑定的全局变量感觉根本不对。
  • 同意,我打算重写这个,所以这个配置来自一个配置。主要是想知道如果需要我怎么能依赖。
  • @JamesSharp 我尝试了 with-redefs ,在这种情况下似乎行为是相同的。绑定不会在会话调用之前发生。

标签: clojure


【解决方案1】:

已编辑:REPL 中的一些实验

(def ^:dynamic *a* "a not bound")
(def ^:dynamic *b* "b not bound")
(defn show-a! []
  *a*)
(binding [*a* 1 *b* (show-a!)] *b*) ;; => "a not bound"

(binding [*a* 1]
  (binding [*b* (show-a!)]
    *b*)) ;; => 1

我很惊讶地知道给定的代码与以下代码不同:

(binding [*private-key-path* "/Users/dcapwell/.ssh/id_dsa"
          *session*          (session "localhost")]
  ...)

因此,在 let 形式的情况下,Clojure 的括号往往比其他 Lisps 少,但在 binding 中则不然。

请反复考虑您的整体代码(和/或 API 设计?)。动态绑定很糟糕。你很快就会受苦。提示:让越来越多的代码可单元测试。

我不确定你想做什么,所以我推荐这个:

用于结构计算的称为“图形”的功能。再也不用担心函数之间的依赖关系了!

https://github.com/Prismatic/plumbing

【讨论】:

  • 这里的问题是 private-key-path 在调用会话之前没有被绑定。所以当 session 被调用时,该值为 nil(它在 def 中设置的值)
  • 同意绑定可能是个坏主意。目前使用它只是为了使用 ssh lib 进行原型制作,所以我可以看到如何破解它。我只是好奇为什么 private-key-path 不受调用会话时间的约束。
  • 你说得对,binding的嵌套绑定形式是并行的,不像let那样
猜你喜欢
  • 2010-12-04
  • 2019-07-28
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2012-04-07
  • 1970-01-01
相关资源
最近更新 更多