Laurent, 1. You are correct. juxt returns a vector. This is based on some old articles I wrote, and I must of missed those references. 2. Guilty :) The partial is (deliberate) overkill.
Sean On Dec 18, 4:17 am, Laurent PETIT <laurent.pe...@gmail.com> wrote: > Hello, > > 2009/12/18 Sean Devlin <francoisdev...@gmail.com> > > > > > > > Hello everyone, > > Today I'd like to shed some light on a new funciton in 1.1, juxt. In > > order to understand juxt(apose), I'd like to first talk about comp > > (ose). Comp can be defined in terms of reduce like so: > > > (defn my-comp [& fns] > > (fn [args] > > (reduce > > (fn[accum f](f accum)) > > (conj (reverse (seq fns)) args)))) > > > Granted, this isn't 100% equivalent to the Clojure comp function, but > > it is very, very close. What it demonstrates is that comp applies a > > list of functions in series using reduce. After writing Clojure for a > > while, one usually finds frequent need to apply a list of functions in > > parallel using map. juxt can be defined as follows > > > (defn juxt [& fns] > > (fn[ & arg] (map #(apply % args) fns))) > > > Notice that juxt creates a closure. The most straightforward case is > > to *predictably* access multiple values from a map. > > > user=>(def test-map {:a "1" :b "2" :c "3" :d "4"}) > > > user=>((juxt :a :c) test-map) > > ("1" "3") > > Which version of juxt are you using ? Mine (from branch 1.1.x) returns a > vector, not a list/seq > > > > > > > > > However, as one works with maps more and more, situations arise where > > it is desired to perform many operations on a map at once. For > > example > > > ;assume parse-int turns a string to an int appropriately > > user=>((juxt :a (comp parse-int :c)) test-map) > > ("1" 3) > > > Since juxt returns a closure, it is very useful in any place one would > > use a map operation as well. For example, this can make turning a > > list of maps into a list of lists very easy. Also, this made it very > > easy to determine if a sub-selection of a hash-map is equal to another > > hash- map > > > user=>(def test-juxt (juxt :a :c)) > > user=>(= (test-juxt {:a 1 :b 2 :c 3}) (test-juxt {:a 1 :b 34 :c 3})) > > true > > > One thing that is very interesting is that this function allows one to > > simulate the behavior of let in a point-free style. > > > ;This is deliberate overkill for a small example > > ;Generate a list of squares > > ;Notice that the juxt fn uses the range twice > > user=>((partial map (juxt identity #(* % %))) (range 1 6)) > > ((1 1) (2 4) (3 9) (4 16) (5 25)) > > We're used to you being in love with point-free style, but the above example > really does not need to use partial ? > (map (juxt (identity #(* % %)) (range 1 6)) > > ;-) > > Anyway thanks for sharing this since it's not in my zone of comfort so it's > interesting stuff to think about. > > > > > > > This also is useful when combined w/ clojure.contrib/group-by. > > Suppose you have a sales database with a table in it. This table keep > > tracks of each sale (:id), when it happened (:year, :quarter), who > > sold it (:sold-by), and what category (:category) the product was > > in. > > > It is obviously useful to group items by who sold it, or what category > > it was sold under. However, it is also interesting to see which > > employees are selling which items. This is a grouping by :sold-by > > AND :category. In order to get at this information we'd do the > > following. > > > ;Assume our sales data is a list of maps, in the sales-coll variable > > ;returns a map with two element vectors as keys, a list of maps as the > > vals. > > user=>(group-by (juxt :sold-by :category) sales-coll) > > <Lots-Of-Data> > > > Now, what happens when you need to change how you group the data? > > Instead of :sold-by & :category, you need :year & :quarter? juxt > > makes it easy. > > > user=>(group-by (juxt :year :category) sales-coll) > > <Lots-Of-Different-Data> > > > And finally, what happens when you need to break it down by all for > > variables simultaneously? > > > user=>(group-by (juxt :year :category :sold-by :category) sales-coll) > > <Our-Last-Data-Sample> > > > There are tons of other uses for juxt, and I would encourage you to > > experiment and find out some of these uses yourself. I hope these > > examples help everyone understand how to use the new operator. > > > Happy Hacking, > > Sean > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@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+unsubscr...@googlegroups.com<clojure%2bunsubscr...@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 post to this group, send email to clojure@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+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en