为什么我从这段代码中得到一个错误?

问题描述:

我对clojure很陌生,正试图突破一些我不断遇到的问题。有问题的代码是函数v3应接受4个参数:为什么我从这段代码中得到一个错误?

  • 一分钟和一个最大整数,mima,与 random-numbers函数的使用在一定范围内找到号码,
  • 另一整数,cnt,以表示我多少个号码想在我的 最终名单,并
  • tones,这是一个随机数字有 匹配一旦我计算一列整数模说号码12。

该函数应该运行,直到o是包含也可在tones列表随机数长度cnt的列表。

我的文件汇编就好了,但是当我想用的东西来运行函数本身在REPL,比如像(v3 58 52 15 '(0 2 4 5 7 9))我收到以下错误:

ClassCastException clojure.langLazySeq cannot be cast to java.lang.Number clojure.langNumbers.reminder (Numbers.java:173)

这里是我的代码

(defn random-numbers [start end n] 
    (repeatedly n #(+ (rand-int (- end start)) start))) 

(defn m12 [input] 
    (mod input 12)) 

(defn in? [coll elm] 
    (some #(= elm %) coll)) 

(defn v3 [ma mi cnt tones] 
    (let [o '()] 
     (loop [] 
      (when(< (count o) cnt) 
       (let [a (m12 (random-numbers mi ma 1))] 
        (if (in? tones a) 
         (conj o a))))) 
     (println o))) 
+0

是不是这只是国防部需要一个号码,你给它一个序列? –

+0

我想可能是这样,随机数函数可能会返回一个1的序列。我会尝试,谢谢:) – Sturla

+0

这样的问题坐在[CodeReview](http://codereview.stackexchange.com/)比在Stackoverflow更好。 – Thumbnail

首先,在同一行上输入括号,而不是在“Java”中输入更多的惯用Clojure。

当我调试代码,我看到它失败在调用m12random-numbers返回序列和m12调用mod预计的数字。

可以通过例如从random-numbers返回的顺序采取的第一个元素解决这个问题:

(defn v3 
    [ma mi cnt tones] 
    (let [o '()] 
    (loop [] 
     (when (< (count o) cnt) 
     (let [a (m12 (first (random-numbers mi ma 1)))] 
      (if (in? tones a) 
      (conj o a))))) 
    (println o))) 

/编辑我不知道你的代码是应该做的,但这并没有阻止我做出更多的改变。如果您使用loop,则通常也会看到recur“重复”回到循环目标。否则它没有太大的作用。我添加了以下东西:

  1. a recur到循环。
  2. let声明添加到loop载体(起始值)。
  3. println陈述在if陈述的错误条款中。
  4. 删除第一个if-检查计数的陈述
  5. 将列表更改为向量。当您使用create code structures结构时(例如while writing macros),您可以在矢量上使用列表。

参见:

(defn v3 
    [ma mi cnt tones] 
    (loop [o []] 
    (if (< (count o) cnt) 
     (let [a (m12 (first (random-numbers mi ma 1)))] 
     (if (in? tones a) 
      (recur (conj o a)) 
      (println "a not in tones, o:" o))) 
     (println "already " cnt "tones generated")))) 

如果运行(v3 58 52 4 [0 2 4 5 7 9])(注意,我改变了你15 cnt 4,改变了列表的向量)几次,你会得到例如以下的输出:

a not in tones, o: [4 4]
a not in tones, o: [9 5 5]
a not in tones, o: []
already 4 tones generated
a not in tones, o: [7]

希望这会有所帮助。

+0

感谢您的建议,我会在下一次寻求帮助之前尝试突破我的Java习惯。如果您调试我的代码,您看到了什么?看起来你的评论可能已经过早地结束了。 编辑:没关系,我现在可以看到其余的,谢谢你的帮助。 – Sturla

我想我明白你在做什么。

这是自动构图练习。您的v3功能意在由mi n和ma的x给出的范围内,以产生的音调

  • 的序列。
  • 音类从一组给定音类(tones

m12函数返回音类音色的,所以让我们把它叫做得出:

(defn tone-class [tone] 
    (mod tone 12)) 

虽然我们认为,如果我们相反地加上数字,我认为您的random-number函数更容易阅读:

(defn random-number [start end] 
    (+ start (rand-int (- end start)))) 

请注意,可能的值包括start而不是end,正如the standard range一样。

除了各种针对clojure语义的攻击(如@Erwin所述)之外,v3的算法还存在问题。如果我们要修复它(我们会),它会生成一系列音调类别,而不是音调。被解释为音调,这些不会超出基本八度音阶,但宽于指定的音调范围。

修复后的v3

(defn v3 [mi ma cnt tones] 
    (let [tone-set (set tones)] 
    (loop [o '()] 
     (if (< (count o) cnt) 
     (let [a (tone-class (random-number mi ma))] 
      (recur (if (tone-set a) (conj o a) o))) 
     o)))) 
  • 一开始,我已经关掉的mima顺序与 range等以符合。
  • 我们将tones设置为一个集合,因此其作为 成员函数。
  • 然后我们循环,直到结果序列o足够大。
  • 我们返回结果而不是打印它。

在循环中,我们再次出现在同一o如果考生a不适合,但(conj o a)如果这样做。让我们试试吧!

(v3 52 58 15 '(0 2 4 5 7 9)) 
;(4 5 9 7 7 5 7 7 9 7 5 7 4 9 7) 

注意,既不0也不2出现,虽然他们是在tones。这是因为音调范围52到58会映射到音调类别范围4到10.

现在让我们累积音调而不是音调类别。我们需要移动的转换测试中,替换...

 (let [a (tone-class (random-number mi ma))] 
      (recur (if (tone-set a) (conj o a) o))) 

...与...

 (let [a (random-number mi ma)] 
      (recur (if (tone-set (tone-class a)) (conj o a) o))) 

这给了我们,例如,

(v3 52 58 15 '(0 2 4 5 7 9)) 
;(53 52 52 52 55 55 55 53 52 55 53 57 52 53 57) 

的惯用语v3

一个惯用的版本会使用the sequence library

(defn v3 [mi ma cnt tones] 
    (let [tone-set (set tones) 
     numbers (repeatedly #(random-number mi ma)) 
     in-tones (filter (comp tone-set tone-class) numbers)] 
    (take cnt in-tones))) 

这会首先产生序列前沿。虽然通过查看结果无法判断,但上述修复后的版本会将其重新置于前面。

另一种惯用的v3

使用->> threading macro捕捉功能级联调用:

(defn v3 [mi ma cnt tones] 
    (->> (repeatedly #(random-number mi ma)) 
     (filter (comp (set tones) tone-class)) 
     (take cnt))) 
+0

很好完成。谢谢。 –