Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 带有可选参数的DSL语法_Clojure_Dsl - Fatal编程技术网

Clojure 带有可选参数的DSL语法

Clojure 带有可选参数的DSL语法,clojure,dsl,Clojure,Dsl,我正在尝试处理以下DSL: (simple-query (is :category "car/audi/80") (is :price 15000)) 这非常顺利,所以我又添加了一件事——传递给查询的选项: (simple-query {:page 1 :limit 100} (is :category "car/audi/80") (is :price 15000)) 现在我有一个问题,如何以最文明的方式处理这个案件。正如您所看到的,simple query可能将hash

我正在尝试处理以下DSL:

(simple-query 
  (is :category "car/audi/80")
  (is :price 15000))
这非常顺利,所以我又添加了一件事——传递给查询的选项:

(simple-query {:page 1 :limit 100}
  (is :category "car/audi/80")
  (is :price 15000))
现在我有一个问题,如何以最文明的方式处理这个案件。正如您所看到的,
simple query
可能将hash-map作为第一个元素(后面是一长串条件)获取,或者可能根本没有hash-map选项。此外,我希望将默认设置作为一组默认选项,以防在查询中某些(或全部)选项未明确提供

这就是我想出来的:

(def ^{:dynamic true} *defaults* {:page 1 
                                  :limit 50})

(defn simple-query [& body]
  (let [opts (first body) 
        [params criteria] (if (map? opts) 
                             [(merge *defaults* opts) (rest body)]
                             [*defaults* body])]
       (execute-query params criteria)))

我觉得有点乱。你知道如何简化这个结构吗?

为了在我自己的代码中解决这个问题,我有一个方便的函数,我想让你见见<编码>在时拍摄

user> (defn take-when [pred [x & more :as fail]]
        (if (pred x) [x more] [nil fail]))
#'user/take-when
user> (take-when map? [{:foo :bar} 1 2 3])
[{:foo :bar} (1 2 3)]
user> (take-when map? [1 2 3])
[nil [1 2 3]]
所以我们可以使用它为可选的map-first参数实现一个解析器

user> (defn maybe-first-map [& args]
        (let [defaults         {:foo :bar}
              [maybe-map args] (take-when map? args)
              options          (merge defaults maybe-map)]
          ... ;; do work
          ))
因此,就我而言,您提出的解决方案或多或少是正确的,我将通过分解用于获取选项映射的解析器(这里是我的
take when
helper)和分解将默认值合并到它自己的绑定语句来清理它


一般来说,使用动态变量存储配置是一种反模式,这是因为在惰性评估时可能会出现错误行为。

这样的情况怎么样

(defn simple-query
  [& body]
  (if (map? (first body))
    (execute-query (merge *defaults* (first body)) (rest body))
    (execute-query *defaults* body)))

是的,现在看起来好多了。我不知道你描述的反模式。有没有其他方法可以在函数之间共享此类默认值以避免重复它们?如果您想共享“默认”值,那么我建议在某个地方定义默认配置。常见的用例通常是客户端采用默认配置并自行更新。有关使用动态变量进行配置的危险性的更多信息,请参阅。@MichalI不确定我在想什么,您不需要递归调用-请参阅我的编辑。