Clojure,字面向量与函数结果不同

3

我正在尝试使用clojure的overtone库制作音乐。为了产生有趣的声音,加法合成是很有用的,这意味着我需要取多个不同频率的正弦振荡器并将它们简单地相加。在overtone中,我可以编写以下代码来创建实现该功能的合成器:

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

3
尝试对 definst 的调用进行宏展开。很可能 definst 是一个复杂的宏,将通常是函数(比如 +)的操作解释为合并一组信号的合成定义,而您的新 definst 表单打破了这个宏。Clojure 代码无法在 sc 合成器进程中运行,因此您的表单需要转换为 sc 合成器定义,并且实际上不是真正的 Clojure 代码。 - noisesmith
1个回答

1

抱歉,您是正确的,我没有理解noisesmith的评论。 事实上,您无法直接在函数中使用此值“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"))

我希望这能帮到你

Juan


之前的评论现在不是有效的回应

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

这是您的代码

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

谢谢,首先。definst是一个宏,正如noisesmith所指出的那样。它期望偶数个参数,每个第二个表示默认值。有趣的是,你的版本编译通过了,但我不能再用参数调用myinst了。我明白了,definst将其参数转换为我上面提到的这些奇怪类型。我需要将它们转换... - spiehr
嗯,不是很对。我想要“实例化”一个乐器(definst),并使用不同的频率。如果我正确理解您的解决方案,我需要为每个频率实例化一个乐器。我应该在我的问题中澄清这一点。此外,我认为这个问题更与Overtone有关,而不是Clojure。感谢您的努力! - spiehr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接