Pau*_*ald 5 lisp refactoring clojure
我对clojure很新,而且我之前没有做过大量的lisp.我有一个包含以下内容的函数:
(defn chord
([scale degree num_voices]
(if
(keyword? degree)
(take num_voices (take-nth 2 (cycle (invert scale (.indexOf scale degree)))))
(take num_voices (take-nth 2 (cycle (invert scale degree))))))
Run Code Online (Sandbox Code Playgroud)
很显然,这个代码是差,因为有两个几乎相同的函数调用这里是最理想的,这里唯一的区别是(.indexOf scale degree)
VS degree
.
什么是Clojure/Lisp删除此代码重复的方法?我觉得它应该涉及让,但我不是积极的.还可以理解与该代码块相关的任何其他通用指针.
编辑:我根据andrew cooke的建议重新考虑了代码,该函数现在读取:
(defn chord
([scale degree num_voices]
(let [degree (if (keyword? degree) (.indexOf scale degree) degree)]
(take num_voices (take-nth 2 (cycle (invert scale degree))))
)
)
Run Code Online (Sandbox Code Playgroud)
感谢所有回答如此之快的人.
if
返回一个表达式,因此反转函数的结构:
(defn chord
([scale degree num_voices]
(take num_voices (take-nth 2 (cycle (invert scale (if (keyword? degree)
(.indexOf scale degree)
(invert scale degree))))))))
Run Code Online (Sandbox Code Playgroud)
如果你使用let来捕获结果,那可能会更好if
.
我会写:
(defn chord [scale degree num_voices]
(let [degree (if (keyword? degree) (.indexOf scale degree) degree)]
(take num_voices (take-nth 2 (cycle (invert scale degree)))))
Run Code Online (Sandbox Code Playgroud)
不确定它有帮助 - 没有一般原则,除了使用let
.也许,也许其他人不喜欢我影子价值观的方式degree
,但在这里我认为它有助于显示意图.
编辑:与其他答案相比,我已经拿出了价值.我更喜欢这种嵌入,因为我发现很长一段时间的嵌入式评估难以阅读.因人而异.
PS思考些[这一些天后]如果您正在使用多个地方这种风格(其中一个参数可以是一个值或从之前的值中提取数据的关键),那么我可能会考虑写一个宏来自动执行该过程(即生成带有自动生成的上述形式的fn的东西).主要的问题是决定如何以这种方式指出哪些参与者被处理(而且,我会担心这会如何混淆你正在使用的任何一个ide).