【问题标题】:How to bind functions in let evaluating them later如何在稍后评估它们时绑定函数
【发布时间】:2019-05-30 10:59:56
【问题描述】:

我正在学习 Clojure 以将其与 Quil 一起使用来制作生成艺术,我想尝试更多地了解 let 函数和 reader 宏。

我尝试从文档中阅读阅读器宏,但找不到明确的答案。

我目前有这段代码:

(let [dabs (take 10 (repeatedly #(make-watercolor 
                                   (mkpt 
                                     (randomNormal 0.1 0.9) 
                                     (randomNormal 0.1 0.9))
                                   (w (randomNormal 0.4 0.7)))))]
    (draw-multiple-watercolor dabs 3))

这很丑陋,而且不可读。 我想精简重复的函数,将其拆分成更小的部分,但由于这些部分将被多次评估并且内部具有随机性,我无法将它们的结果存储在变量中并使用它,而是需要在需要时评估它们。

我的问题是:有没有办法做这样的事情

(let [randCoord (randomNormal 0.1 0.9) ;This..
      randPoint (mkpt randCoord randCoord) ;..and this doesn't should be evaluated here, but on the repeatedly function calls
      dabs (take 10 (repeatedly #(make-watercolor 
                                   randPoint ;Evaluation here
                                   (w (randomNormal 0.4 0.7)))))]
    (draw-multiple-watercolor dabs 3))

【问题讨论】:

  • 你觉得(let [make-wc-fn #(make-watercolor ...), dabs (take 10 (repeatedly make-wc-fn))] ...)丑吗?我认为是嵌套而不是匿名函数的使用使代码变得一团糟。给这个函数起自己的名字,它就不再被定义在一个嵌套很深的地方。

标签: clojure quil


【解决方案1】:

一种选择是使用与传递给 repeatedly 的函数相同的方法:只需将表达式包装在不带参数的函数中(或仅带您想要更改的参数),然后它们将每次调用函数时都会进行评估。

(let [rand-coord (fn [] (randomNormal 0.1 0.9)) ;; or #(randomNormal 0.1 0.9)
      make-dab #(make-watercolor (mkpt (rand-coord) (rand-coord))
                                 (w (randomNormal 0.4 0.7)))
      dabs (take 10 (repeatedly make-dab))]
  (draw-multiple-watercolor dabs 3))

还可以查看 letfn 以在非顶级/命名空间范围内定义函数。

您可能还会发现 threading 宏,例如 ->->>as->some->cond-> 等,可以使某些代码更具可读性。例如,如果您将draw-multiple-watercolor 更改为采用它的 dabs last 序列(这对于在 Clojure 中对序列进行操作的函数来说是相当普遍的做法),那么您可以执行以下操作:

(let [rand-coord (fn [] (randomNormal 0.1 0.9)) ;; or #(randomNormal 0.1 0.9)
      make-dab #(make-watercolor (mkpt (rand-coord) (rand-coord))
                                 (w (randomNormal 0.4 0.7)))]
  (->> make-dab
       (repeatedly 10) ;; note: repeatedly can take a # of iterations
       (draw-multiple-watercolor 3)))

【讨论】:

  • 我记得我像您的评论所说的那样尝试了 #() 宏,但我没有设法让它与随机的东西一起工作,我稍后再试一次,让你知道。感谢您的回复!
  • 我刚试过,效果很好!我没有将绑定函数与 () 一起使用,因此它之前正在运行,但没有正确使用 random 给我始终相同的结果。现在它就像一个魅力,谢谢!
  • @elkiwy 很好,我还使用 Quil 来可视化一些 Advent of Code 问题here。玩得开心!
猜你喜欢
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多