2016-09-13 135 views
0

我對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

回答

3

首先,在同一行上輸入括號,而不是在「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

1

我想我明白你在做什麼。

這是自動構圖練習。您的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

很好完成。謝謝。 –

相關問題