flip in clojure

1,530 views
Skip to first unread message

Vagmi Mudumbai

unread,
Apr 30, 2015, 7:31:05 PM4/30/15
to clo...@googlegroups.com
Hi,

I was introducing one of my colleagues to clojure[1] and we were
trying to parse the reddit json as an exercise.

(require '(clj-http.client :as client))
(require '(clojure.data.json :as json))

(def ^:const REDDIT-URL "http://reddit.com/r/clojure.json?limit=100")
(def ^:const headers {:headers {"User-Agent" "showoffclojure.core by vagmi"}})

(let [entries_ (-> REDDIT-URL
(client/get headers)
(:body)
(json/read-str :key-fn keyword)
(:data)
(:children))]
(map :data entries))

It would have been nice if we were able to write the map as a part of
the threading macro. So if there were a flip function like in haskell,
we could flip the args to the function hand have the map in the
threading macro. I could not find one so I wrote one.

(defn flip [fn_]
(fn [x y & args]
(apply fn_ (into [y x] args))))

Now I can bring in the map as a part of the -> threading macro.

(-> REDDIT-URL
(client/get headers)
(:body)
(json/read-str :key-fn keyword)
(:data)
(:children)
((flip map) :data))

This seems to be rather easy and useful and gets rid of the let block.
Are there any implications to performance or impact to laziness by
using flip? This would be useful even on the transduced version of
map like ((flip transduce) (map :data)) on the last expression.

Regards,
Vagmi


[1]: (http://blog.tarkalabs.com/2015/04/30/experience-report-introducing-an-experienced-ruby-developer-to-clojure/)
and

Ben Wolfson

unread,
Apr 30, 2015, 7:44:57 PM4/30/15
to clo...@googlegroups.com
->> and -> actually play nice with each other in this direction:

(-> 4
      range
      (->> (map inc))
      last)

results in 4, because we end up with (-> (range 4) (->> (map inc)) last) --> (-> (->> (range 4) (map inc)) last) --> (last (->> (range 4) (map inc))) --> (last (map inc (range 4))). Though all this saves you is a single function call, and flip is a useful thing to have around anyway.

btw, as far as "flip", you don't need the "into" call; you can just do:

(defn flip [f] (fn [x y & args] (apply f y x args))

though I don't know how if this is actually significant.


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure." [Larousse, "Drink" entry]

Sean Corfield

unread,
Apr 30, 2015, 8:26:20 PM4/30/15
to clo...@googlegroups.com
I wonder how many code bases out there have their own variant of `flip`?

Here’s ours:

(defn flip
  "Like partial except you supply everything but the first argument."
  ([f b] (fn [a] (f a b)))
  ([f b c] (fn [a] (f a b c)))
  ([f b c d & more]
   (fn [a] (apply f a b c d more))))

Sean

Jony Hudson

unread,
Apr 30, 2015, 8:49:44 PM4/30/15
to clo...@googlegroups.com
Another option is to use `as->` https://clojuredocs.org/clojure.core/as-%3E . It's more verbose ... I kind of like that aspect of it, but it may not be to everyone's taste.


Jony

Robert Levy

unread,
Apr 30, 2015, 9:16:41 PM4/30/15
to clo...@googlegroups.com
from https://github.com/rplevy/mostly-useful (not updated in a while)

(defn flip
  "given a function, create a flipped 2-argument function"
  [f]
  (fn [a b] (f b a)))

(defmacro flop
  "create a version of a function with a modified arity as specified by a
   vector of zero-indexed positions, e.g. [0 3 1 2]"
  [f positions]
  (let [syms (vec (repeatedly (count positions) gensym))]
    `(fn [~@syms] (~f ~@(map syms positions)))))



--

Ruslan Prokopchuk

unread,
May 2, 2015, 12:17:27 AM5/2/15
to clo...@googlegroups.com
And do not miss https://github.com/LonoCloud/synthread for more complex cases ;-)

пятница, 1 мая 2015 г., 2:31:05 UTC+3 пользователь Vagmi Mudumbai написал:
Reply all
Reply to author
Forward
0 new messages