【问题标题】:Clojure- Defining a variable inside of a function?Clojure-在函数内部定义变量?
【发布时间】:2018-07-31 13:11:54
【问题描述】:

我有这个变量,hand,当我自己定义它时它工作得很好。

(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))))))

我想在这里的这个函数中使用这个变量。当我先定义变量然后在函数中使用它的名称时,这很好用。

(reduce + (vec (map #(let [x %]
                      (cond
                        (= x 1) 1
                        :else 0
                        ))
                yourHand)))

当我尝试像这样在函数中定义变量时,问题就出现了。

(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)))))))))

如果不是两件事,这将是不必要的。首先,如果可能的话,我想把这个程序浓缩成一个函数(我认为它/是/可能的!)。其次,我需要在程序的另一点使用这个变量,所以我需要能够以某种方式引用它。

无论如何,当我尝试评估上述函数时,它抱怨它不知道“如何从:clojure.lang.Var 创建 ISeq”。 (这是错误:IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Var clojure.lang.RT.seqFrom (RT.java:542))我假设这意味着它不知道如何将我的变量用作向量...但是当我在函数外部定义变量时,它似乎可以将其用作向量!

有什么建议吗?

【问题讨论】:

    标签: clojure functional-programming var


    【解决方案1】:

    您不应该尝试在函数内部使用def。一般defs 用于顶级命名空间值;加载命名空间后(通常)不会改变的东西。

    让我们稍微重构一下代码以获得一些不依赖于顶级/静态命名空间值的可重用函数。代替(def yourHand ...),我们可以有一个生成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,你可以这样得到它:

    (def your-hand (deal-hand))
    

    我们可以将您的reduce 包装在另一个需要帮助的函数中

    (defn score-hand [hand] ;; I made a few simplifications here, but logic is the same
      (reduce + (mapv #(if (= 1 %) 1 0) hand)))
    

    现在您有两个可重复使用的函数,可以生成和计分:

    (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
    

    如果您需要在程序的其他部分使用手,请考虑如何构建函数以将手作为输入,以及手如何在程序的函数中流动。

    【讨论】:

      猜你喜欢
      • 2021-08-20
      • 1970-01-01
      • 2019-10-05
      • 1970-01-01
      • 2022-11-22
      • 2016-06-16
      • 1970-01-01
      • 2020-06-04
      • 2022-11-23
      相关资源
      最近更新 更多