3

I need a function that thinly wraps amazonica's sqs/receive-message in order to add a default wait time. The function requires a queue URL, and then accepts any number of optional named parameters, which should be passed along to sqs/receive-message untouched. I would like to call it like this:

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

This should result in a call to sqs/receive-message like this:

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

This is something I find myself wanting to do fairly often, but I haven't found a nice way yet. Is there an idiomatic way to do this?

Stéphane Bruckert
  • 21,706
  • 14
  • 92
  • 130
Josh Glover
  • 25,142
  • 27
  • 92
  • 129

2 Answers2

5

Use apply over the merged parameters.

(defn my-receive-message
  [url & {:as args}]
  (apply sqs/receive-message (-> {:queue-url url
                                  :wait-time-seconds 20}
                                 (merge args)
                                 seq 
                                 flatten)))
guilespi
  • 4,672
  • 1
  • 15
  • 24
1

You could always write a macro:

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

(Note that this does pretty much exactly the same thing as Guillermo's function. The main difference is that you don't have to apply sqs/receive-message -- the unquote-splicing (~@) takes care of the apply part implicitly.)

Dave Yarwood
  • 2,866
  • 1
  • 17
  • 29
  • 2
    This is really nice, but the words "prefer functions to macros" from every Clojure book I've ever read are still ringing in my ears. ;) – Josh Glover Mar 07 '14 at 08:54
  • That is generally a good rule of thumb. Now that Guillermo's function is simpler/sleeker thanks to argument destructuring, I think I would probably go with the function version too. Good call, dAni! – Dave Yarwood Mar 07 '14 at 21:03