将关键字作为可选标志实现到函数的最佳方法是什么? 我想进行函数调用,例如:
(myfunction 5)
(myfunction 6 :do-this)
(myfunction 3 :go-here)
(myfunction 2 :do-this :do-that)
使用defn,我可以定义一个函数,例如:
(defn myfunction [value & flags] ... )
但flags
成为一个列表。我可以编写自己的函数来搜索列表,但是这样的函数不包含在核心库中,所以我认为它不是惯用的。
我现在正在使用的是:
(defn flag-set? [list flag] (not (empty? (filter #(= flag %) list))))
(defn flag-add [list flag] (cons flag list))
(defn flag-remove [list flag] (filter #(not= flag %) list))
答案 0 :(得分:9)
列表(以及向量和地图)不是基于值的查找的数据结构的良好选择(将是线性时间),这就是为什么clojure.core没有这样的函数。
集合确实通过“contains?”提供快速的基于值的查找,那么如何
(defn foo [value & flags]
(let [flags (set flags)]
(if (contains? flags :add-one)
(inc value)
value)))
如果没有多个标志,您可以使用这样的解构:
(defn foo [value & [flag]] …)
答案 1 :(得分:5)
clojure.contrib.def
包含defnk
- 宏,这使得使用关键字参数定义函数更加容易。
答案 2 :(得分:1)
您可以对destructuring可选参数使用哈希映射绑定,如下所示:
(defn myfunction
[value & {:keys [go-there do-this do-that times] :or {times 1}}]
{:pre [(integer? times) (< 0 times)]}
(println "Saw a" value)
(when go-there
(dotimes [n times]
(when do-this (println "Did THIS with" value))
(when do-that (println "Did THAT with" value)))))
上述功能可以通过以下方式调用:
(myfunction "foo" :go-there true :do-this true :do-that false :times 5)
请注意,您可以使用:or {times 1}
子句为键定义默认值。由于默认值,以下函数调用仅循环一次:
(myfunction "foo" :go-there true :do-this true :do-that false)
此外,Clojure的precondition expressions允许方便地测试参数,这也适用于结构化键的值,因为它可以在参数后面的{:pre [...]}
表达式中看到绑定。由于前置条件检查,以下调用将失败:
(myfunction "foo" :go-there true :do-this true :do-that false :times -1)
答案 3 :(得分:0)
严格来说,这不是最有效的写作方式,但很明显
(defn myfunction [value & flags] (cond (contains? (set flags) :a) 1 (contains? (set flags) :b) 2)
将因子(设置标志)提高效率可能更有效。