我正在学习Clojure并将其与Quil一起使用来制作生成艺术,我想尝试更多地了解let函数和读者宏。
我尝试从文档中阅读有关阅读器宏的信息,但找不到明确的答案。
我目前有这段代码:
(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))
答案 0 :(得分:3)
一种选择是使用与传递给repeatedly
的函数相同的方法:只将表达式包装在不带参数(或仅包含要更改的args)的函数中,然后将它们每次调用该函数都会被评估。
(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)))