Clojure中代理命名参数的惯用方法

Clojure中代理命名参数的惯用方法,clojure,amazonica,Clojure,Amazonica,我需要一个函数,它将的sqs/receive message精简包装,以便添加默认等待时间。该函数需要一个队列URL,然后接受任意数量的可选命名参数,这些参数应原封不动地传递给sqs/receive message。我想这样称呼它: (my-receive-message "https://sqs.us-east-1.amazonaws.com/123/test-q" :max-number-of-messages 10

我需要一个函数,它将的
sqs/receive message
精简包装,以便添加默认等待时间。该函数需要一个队列URL,然后接受任意数量的可选命名参数,这些参数应原封不动地传递给
sqs/receive message
。我想这样称呼它:

(my-receive-message "https://sqs.us-east-1.amazonaws.com/123/test-q"
                    :max-number-of-messages 10
                    :delete true)
(sqs/receive-message :queue-url "https://sqs.us-east-1.amazonaws.com/123/test-q"
                     :wait-time-seconds 20
                     :max-number-of-messages 10
                     :delete true)
这将导致调用
sqs/receive message
,如下所示:

(my-receive-message "https://sqs.us-east-1.amazonaws.com/123/test-q"
                    :max-number-of-messages 10
                    :delete true)
(sqs/receive-message :queue-url "https://sqs.us-east-1.amazonaws.com/123/test-q"
                     :wait-time-seconds 20
                     :max-number-of-messages 10
                     :delete true)

这是我经常想做的事情,但我还没有找到一个好方法。有一种惯用的方法可以做到这一点吗?

在合并的参数上使用
apply

(defn my-receive-message
  [url & {:as args}]
  (apply sqs/receive-message (-> {:queue-url url
                                  :wait-time-seconds 20}
                                 (merge args)
                                 seq 
                                 flatten)))

您始终可以编写宏:

(defmacro my-receive-message [url & opts]
  `(sqs/receive-message 
      ~@(flatten (seq (merge {:queue-url url :wait-time-seconds 20}
                             (apply hash-map opts))))))

(请注意,这与Guillermo的函数几乎完全相同。主要区别在于您不必
应用sqs/receive message
——无引号拼接(
~@
)隐式处理
应用
部分。)

如何销毁args参数?[url&{:as args}](为了避免应用散列映射args)另外,您可能希望以另一种方式进行合并,以便我的接收消息的调用方可以覆盖默认的waits这正是我要查找的!我错过的是
seq
在我将地图展平之前将其展平。这真的很好,但我读过的每一本Clojure书中的“更喜欢函数而不是宏”这几个字仍在我耳边回响这通常是一条很好的经验法则。由于参数分解,Guillermo的函数更简单/更流畅,我想我可能也会选择函数版本。打得好,丹尼!