or learn more

Monkeying with Clojure’s comp Function

Aug 18, 2010

A slight modification to Clojure’s comp function gives me more power:

[sourcecode lang=”clj” gist=”537860″] (defn comp+ ([] identity) ([f] f) ([f g] (fn ([] (f (g))) ([x] (f (g x))) ([x y] (f (g x y))) ([x y z] (f (g x y z))) ([x y z & args] (f (apply g x y z args))))) ([f g h] (fn ([] (f (g (h)))) ([x] (f (g (h x)))) ([x y] (f (g (h x y)))) ([x y z] (f (g (h x y z)))) ([x y z & args] (f (g (apply h x y z args)))))) ([f1 f2 f3 & fs] (let [fs (reverse (list* f1 f2 f3 fs))] (fn [& args] (loop [ret (apply (first fs) args) fs (next fs)] (if fs (recur ((first fs) ret) (next fs)) ret))))))

;; allowing (require ‘clojure.string)

(for [f (map #(apply comp+ %) [[keyword name] [] [name clojure.string/upper-case]]) e ‘[foo bar]] (f e))

;=> (:foo :bar foo bar “FOO” “BAR”) [/sourcecode]

I added a function body to comp+ handling the case where it’s given no function, returning the identity function. This let’s me use comp+ in more interesting ways without requiring that I handle the case of no arguments explicitly and without exploding when I don’t.

Just one of those little things I guess.


2 Comments, Comment or Ping

  1. Alf

    I’m a newbie to Clojure, but wanted to test the code. Couldn’t quite make it work though. Modified the test to the following:

    (require ‘clojure.contrib.string) (for [f (map #(apply comp+ %) [[keyword name] [] [clojure.contrib.string/upper-case name]]) e ‘[foo bar]] (f e)))

    The change was really just to require clojure.contrib string, and reversing the final vectors values from [name clojure.string/upper-case] to [clojure.contrib.string/upper-case name].

    This seems to give the expected result.

    Also wondering why you are not basing your comp+ function on the existing comp function. The following has the same result. Is this less efficient than copying the code?

    (defn comp+ ([] identity) ([f & fs] (apply comp f fs)))

  2. Thanks for the call on require — fixed.

    All of my “monkeying” posts work against the original source.

Reply to “Monkeying with Clojure’s comp Function”