clojure,文字向量与功能结果不同

时间:2013-09-22 15:08:13

标签: clojure type-conversion sound-synthesis

我正试图用泛音的泛音库创作音乐。为了产生有趣的声音,添加剂合成是有用的,这意味着我采用几种频率的正弦振荡器并简单地添加它们。在泛音中,为​​了创造一个合成器,我意识到这一点:

(definst myinst [freq 100]
  (* 0.2 (reduce + (map sin-osc [101.0 100 99.0]))))

为了更加可重用,我编写了一个函数,它接受一个频率并返回包含所有这些频率的列表,你可以在代码片段中看到:

(defn split-freq [freq]
  (apply vector (map #(* freq %) [1.01 1 0.99])))

执行(split-freq 100)时,REPL会给我以下内容:

[101.0 100 99.0]

与输入完全相同,我提供了上面的map函数。实际上,我复制了结果。现在,我试试这个:

(definst myinst [freq 100]
  (* 0.2 (reduce + (map sin-osc (split-freq freq)))))

不幸的是,REPL告诉我,我做错了:

CompilerException java.lang.ClassCastException: 
overtone.sc.machinery.ugen.sc_ugen.ControlProxy cannot be cast to java.lang.Number, 
compiling:(form-init1807789563491679853.clj:1)

但是这段代码很好用:

(definst myinst [freq 100]
  (* 0.2 (reduce + (map sin-osc (apply vector (map #(* freq %) [1.01 1 0.99]))))))

尽管如此,我只是简单地介绍了函数定义。

我认为我缺乏理解。我想,如果其中一个版本起作用,其他版本也必须正常工作。

我的问题是: 为什么我的“改进”版本不起作用? 为什么第一个片段有效? 我怎样才能规避这种行为?

Clojure 1.3.0
Overtone 0.8
(use 'overtone.core)

1 个答案:

答案 0 :(得分:1)

是的,你是对的,我还不明白噪音的评论。确实,你不能直接在你的函数中使用这个值“freq”,因为这个值在你的函数需要它时没有被绑定(在宏执行之前)

所以这里有一个解决这个问题的方法,也是使用let表单,它不是那么优雅,不能制作你自己的宏但是工作

(defn myinst [inst-name]
  (let [the-freq 100]
   (definst inst-name [freq the-freq] (* 0.2 (reduce + (map sin-osc (split-freq the-freq)))))))

您可以作为普通功能执行

((myinst "my-instrument"))

我希望能帮到你


以前的评论,现在无效回复

也许你在改进版本中的参数值声明中犯了错误

这是你的代码

(definst myinst [freq 100]
  (* 0.2 (reduce + (map sin-osc (split-freq freq)))))

而且,就像在clojure中你不能为参数函数指定默认值一样,如果你使用let表单来指定默认值

,你的改进版本也会有效。
(definst myinst []
  (let [freq 100]
    (* 0.2 (reduce + (map sin-osc (split-freq freq))))))