Hi,
I want to suggest a "pipe" macro for dealing with collection streams,
as a one-line variation on the built in "->" macro.

Instead of writing a nested stream like this:
  ; "Take the first 3 elements of the odd numbers in the range 1 to
20"
  (take 3 (filter odd? (range 1 20)))

you can write this:
  ; "Take the range 1 to 20, filter the odd numbers, then take the
first 3"
  (pipe (range 1 20) (filter odd?) (take 3))

I think both forms have their place. The piped form seems useful when
you want to emphasise the collection, or when the chain gets very
long. It's also close to how I'd draw the chain on a whiteboard or
describe it in speech, and helps me to reason about the chain from
left to right in small "chunks".

The difference with "->" is this:
(-> x (f a b)) => (f x a b)
(pipe x (f a b)) => (f a b x)

The definition is the equivalent of the "->" macro (defined in
core.clj, line 984), swapping "~@(rest form) ~x" to "~x ~@(rest
form)":


(defmacro pipe
  "Threads the expr through the forms. Inserts x as the
  last item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  last item in second form, etc."
  ([x form] (if (seq? form)
              `(~(first form) ~@(rest form) ~x)
              (list form x)))
  ([x form & more] `(pipe (pipe ~x ~form) ~...@more)))


I've seen pipe written as a function with the use of reader macros, or
as macros built from scratch. I'm putting this one forward because the
tiny change in intention from "->" is reflected as a tiny delta in the
code.

Cheers,
Matt

--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to