10

Is there a idiomatic / built-in way to flip the argument order that is passed to a function in Clojure?

As I do here with the definition of a helper function:

(defn flip [f & xs]
   (apply f (reverse xs)))


(vector 1 2)       ; [1 2]
(flip vector 1 2)  ; [2 1]
Anton Harald
  • 5,772
  • 4
  • 27
  • 61
  • 3
    Yep, there is! You wrote it in your question. I'm not quite sure where this would be useful, though. Could you give a practical example? – Sam Estep Feb 21 '16 at 19:50
  • I'm working with a 2d vector, say a grid with an x and an y axis. Then I have a function operating on that grid: this function operates on a continuous sequence of fields in the grid, sometimes vertically, sometime horizontally. In order to let the function not worry about the axes, I pass a either (partial vector) or (partial flip vector) to it. through that sub-function the function can operate on the grid in a more abstract way. – Anton Harald Feb 21 '16 at 19:59
  • the same effect would happen if I'd swap the x and y axes in the grid when I need it. Mh, I'm not sure if that was explained well... – Anton Harald Feb 21 '16 at 20:00
  • Could you post a code example of that in your question? – Sam Estep Feb 21 '16 at 20:03
  • well, I tried to extract just the relevant parts. Here's a gist: https://gist.github.com/antonharald/68bb0cbbebf964264270 Hope that clarifies the need for flipping. but maybe there are other ways.. – Anton Harald Feb 21 '16 at 20:27
  • That gist isn't syntactically correct. Could you please post an [MCVE](http://stackoverflow.com/help/mcve) in your question? – Sam Estep Feb 21 '16 at 20:42
  • alright, I worked on the gist example. It's a valid program now. The functionality is lightly different now, I think the purpose should be more clear now. – Anton Harald Feb 21 '16 at 22:04
  • @SamEstep it is quite useful for threading expressions where you want a short-circuit if it returns nil, and for code readability you'll need to flip some arguments depending on the order in which you call your middleware and the order of params in which said middleware wants to receive data. ie. (some-> :transaction-id :body api-response (get-customer-info-by-id db-list) #(sendmail body subject (:email %)) Notice sendmail looks unreadable whereas the rest of expressions have uniformity. – Vlad A. Nov 14 '19 at 21:03

3 Answers3

7

I think it makes sense most times to create a flipped function that you use later, so the variation on your function would be this:

(defn flip [f]
  (fn [& xs]
    (apply f (reverse xs))))
Chris Murphy
  • 6,411
  • 1
  • 24
  • 42
6

A flip function does exist in other functional languages, but it's easy enough to do in Clojure as well, and you've already done it!

There are other ways to do it as well.

And here is a discussion about it from the Clojure mailing list.

johnbakers
  • 24,158
  • 24
  • 130
  • 258
4

You can also use anonymous inline function to re-define the order of arguments.

(vector "a" "b")          ; ["a" "b"]  
(#(vector %2 %1) "a" "b") ; ["b" "a"]
daShader
  • 243
  • 2
  • 7