如何绑定函数以便稍后对其进行评估
How to bind functions in let evaluating them later
我正在学习 Clojure 以将其与 Quil 结合使用来制作生成艺术,我想尝试更多地了解 let 函数和 reader 宏。
我尝试从文档中阅读有关 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))
一个选项是使用与传递给 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
以在 non-top-level/namespace 范围内定义函数。
您可能还会发现 threading 宏,例如 ->
、->>
、as->
、some->
、cond->
,等可以使一些代码更具可读性。例如,如果您更改 draw-multiple-watercolor
以获取其 dab 序列 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)))
我正在学习 Clojure 以将其与 Quil 结合使用来制作生成艺术,我想尝试更多地了解 let 函数和 reader 宏。
我尝试从文档中阅读有关 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))
一个选项是使用与传递给 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
以在 non-top-level/namespace 范围内定义函数。
您可能还会发现 threading 宏,例如 ->
、->>
、as->
、some->
、cond->
,等可以使一些代码更具可读性。例如,如果您更改 draw-multiple-watercolor
以获取其 dab 序列 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)))