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.
> 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+unsubscribe@googlegroups.com<clojure%2Bunsubscribe@googlegroups.com >
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en