I think I see what you are trying to do.
This is an exercise in automatic composition. Your v3 function is intended to generate a sequence of tones
- in a range given by
min and max.
- with tone class drawn from a given set of tone classes (
tones)
The m12 function returns the tone class of a tone, so let's call it that:
(defn tone-class [tone]
(mod tone 12))
While we're about it, I think your random-number function is easier to read if we add the numbers the other way round:
(defn random-number [start end]
(+ start (rand-int (- end start))))
Notice that the possible values include start but not end, just as the standard range does.
Apart from your various offences against clojure semantics, as described by @Erwin, there is a problem with the algorithm underlying v3. Were we to repair it (we will), it would generate a sequence of tone classes, not tones. Interpreted as tones, these do not move beyond the base octave, however wide the specified tone range.
A repaired 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))))
- For a start, I've switched the order of
mi and ma to conform with
range and the like.
- We turn
tones into a set, which therefore works as a
membership function.
- Then we loop until the resulting sequence,
o, is big enough.
- We return the result rather than print it.
Within the loop, we recur on the same o if the candidate a doesn't fit, but on (conj o a) if it does. Let's try it!
(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)
Notice that neither 0 nor 2 appears, though they are in tones. That's because the tone range 52 to 58 maps into tone class range 4 to 10.
Now let's accumulate tones instead of tone classes. We need to move conversion inside the test, replacing ...
(let [a (tone-class (random-number mi ma))]
(recur (if (tone-set a) (conj o a) o)))
... with ...
(let [a (random-number mi ma)]
(recur (if (tone-set (tone-class a)) (conj o a) o)))
This gives us, for example,
(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)
An idiomatic v3
An idiomatic version would use 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)))
This generates the sequence front first. Though you can't tell by looking at the outcome, the repaired version above generates it back to front.
An alternative idiomatic v3
Using the ->> threading macro to capture the cascade of function calls:
(defn v3 [mi ma cnt tones]
(->> (repeatedly #(random-number mi ma))
(filter (comp (set tones) tone-class))
(take cnt)))