Clojure- 在函数内部定义变量? [英] Clojure- Defining a variable inside of a function?
问题描述
我有这个变量,hand,当我自己定义它时效果很好.
I have this variable, hand, that works just fine when I define it on its own.
(def yourHand
(map
;;fn
#(let [x %]
(cond
;;hearts
(< x 10) (* x -1)
(< x 13) -10
;;diamonds
(< x 23) (* (mod x 13) -1)
(< x 26) -10
;;clubs
(< x 36) (mod x 13)
(< x 39) 10
;;spades
(< x 49) (mod x 13)
(< x 52) 10
))
;;list
(take (rand-int 12) (repeatedly #(+ 1 (rand-int 52))))))
我想在此函数中使用此变量.当我先定义变量然后在函数中使用它的名称时,这很好用.
I would like to use this variable in this function here. This works just fine when I define the variable first then just use its name in the function.
(reduce + (vec (map #(let [x %]
(cond
(= x 1) 1
:else 0
))
yourHand)))
当我尝试在函数中定义变量时,问题就出现了,就像这样.
The issue arrises when I try to define the variable within the function, like this.
(reduce + (vec (map #(let [x %]
(cond
(= x 1) 1
:else 0
))
(def hand
(map
;;fn
#(let [x %]
(cond
;;hearts
(< x 10) (* x -1)
(< x 13) -10
;;diamonds
(< x 23) (* (mod x 13) -1)
(< x 26) -10
;;clubs
(< x 36) (mod x 13)
(< x 39) 10
;;spades
(< x 49) (mod x 13)
(< x 52) 10
))
;;list
(take (rand-int 12) (repeatedly #(+ 1 (rand-int 52)))))))))
如果不是两件事,这将是不必要的.首先,如果可能的话,我想把这个程序压缩成一个函数(我认为它/是/可能的!).其次,我需要在我的程序的另一个点使用这个变量,所以我需要能够以某种方式引用它.
This would not be necessary if not for 2 things. First, I would like to condense this program down to one function if possible (and I think it /is/ possible!). Second, I need to use this variable at another point in my program so I need to be able to reference it somehow.
无论如何,当我尝试评估上述函数时,它抱怨它不知道如何从:clojure.lang.Var 创建 ISeq".(这是错误:IllegalArgumentException 不知道如何从以下位置创建 ISeq:clojure.lang.Var clojure.lang.RT.seqFrom (RT.java:542))我假设这意味着它不知道如何将我的变量用作向量......但是当我在函数之外定义我的变量时,它似乎可以将它用作向量!
Anyway, when I try to evaluate the above function, it complains that it doesn't know "how to create ISeq from: clojure.lang.Var". (This is the error: IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Var clojure.lang.RT.seqFrom (RT.java:542)) I'm assuming this means that it doesn't know how to use my variable as a vector... but it seems to use it as a vector just fine when I define my variable outside of the function!
有什么建议吗?
推荐答案
你不应该尝试在函数内部def
.通常 def
用于顶级命名空间值;加载命名空间后(通常)不会改变的东西.
You shouldn't try to def
inside of functions. Generally def
s are for top-level namespace values; things that won't (normally) change after the namespace is loaded.
让我们稍微重构一下代码以获得一些不依赖于顶级/静态命名空间值的可重用函数.代替 (def yourHand ...)
我们可以有一个生成 hands 的函数:
Let's refactor the code a bit to get some reusable functions that don't depend on top-level/static namespace values. Instead of (def yourHand ...)
we can have a function that generates hands:
(defn deal-hand []
(map
;;fn
#(cond ;; you have a subtle bug here that sometimes returns nil
;;hearts
(< % 10) (* % -1)
(< % 13) -10
;;diamonds
(< % 23) (* (mod % 13) -1)
(< % 26) -10
;;clubs
(< % 36) (mod % 13)
(< % 39) 10
;;spades
(< % 49) (mod % 13)
(< % 52) 10)
;;list
(take (rand-int 12) (repeatedly #(inc (rand-int 52))))))
如果你还想要一个命名空间def
,你可以这样得到:
Then if you still wanted a namespace def
, you could get it like this:
(def your-hand (deal-hand))
而且我们可以将您的 reduce
包装在另一个帮助的函数中:
And we can wrap your reduce
in another function that takes a hand:
(defn score-hand [hand] ;; I made a few simplifications here, but logic is the same
(reduce + (mapv #(if (= 1 %) 1 0) hand)))
现在您有两个可重复使用的函数,可以生成和得分手:
Now you have two reusable functions that can generate and score hands:
(deal-hand)
=> (-10 -9 -9 -10 -3 7)
(deal-hand)
=> (8 -2 10 -9 1 2 -10 3 nil 5)
(score-hand (deal-hand))
=> 1
如果您需要在程序的其他部分使用手,请考虑如何构建函数以将手作为输入,以及手如何在程序的函数中流动.
If you need to use a hand in other parts of your program, think about how you can structure your functions to take hands as input, and how hands can flow through your program's functions.
这篇关于Clojure- 在函数内部定义变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!