Take the 2-minute tour ×

Is it possible to use/implement tacit programming (also known as point-free programming) in Lisp? And in case the answer is yes, has it been done?

share|improve this question

4 Answers 4

up vote 12 down vote accepted

This style of programming is possible in CL in principle, but, being a Lisp-2, one has to add several #'s and funcalls. Also, in contrast to Haskell for example, functions are not curried in CL, and there is no implicit partial application. In general, I think that such a style would not be very idiomatic CL.

For example, you could define partial application and composition like this:

(defun partial (function &rest args)
  (lambda (&rest args2) (apply function (append args args2))))

(defun comp (&rest functions)
  (flet ((step (f g) (lambda (x) (funcall f (funcall g x)))))
    (reduce #'step functions :initial-value #'identity)))

(Those are just quick examples I whipped up – they are not really tested or well thought-through for different use-cases.)

With those, something like map ((*2) . (+1)) xs in Haskell becomes:

CL-USER> (mapcar (comp (partial #'* 2) #'1+) '(1 2 3))
(4 6 8)

The sum example:

CL-USER> (defparameter *sum* (partial #'reduce #'+))
CL-USER> (funcall *sum* '(1 2 3))

(In this example, you could also set the function cell of a symbol instead of storing the function in the value cell, in order to get around the funcall.)

In Emacs Lisp, by the way, partial application is built-in as apply-partially.

In Qi/Shen, functions are curried, and implicit partial application (when functions are called with one argument) is supported:

(41-) (define comp F G -> (/. X (F (G X))))

(42-) ((comp (* 2) (+ 1)) 1)

(43-) (map (comp (* 2) (+ 1)) [1 2 3])
[4 6 8]

There is also syntactic threading sugar in Clojure that gives a similar feeling of "pipelining":

user=> (-> 0 inc (* 2))
share|improve this answer

You could use something like (this is does a little more than -> in Clojure):

(defmacro -> (obj &rest forms)
  "Similar to the -> macro from clojure, but with a tweak: if there is
  a $ symbol somewhere in the form, the object is not added as the
  first argument to the form, but instead replaces the $ symbol."
  (if forms
      (if (consp (car forms))
          (let* ((first-form (first forms))
                 (other-forms (rest forms))
                 (pos (position '$ first-form)))
            (if pos
                `(-> ,(append (subseq first-form 0 pos)
                              (list obj)
                              (subseq first-form (1+ pos)))
                `(-> ,(list* (first first-form) obj (rest first-form))
          `(-> ,(list (car forms) obj)
               ,@(cdr forms)))

(you must be careful to also export the symbol $ from the package in which you place -> - let's call that package tacit - and put tacit in the use clause of any package where you plan to use ->, so -> and $ are inherited)

Examples of usage:

(-> "TEST"

(-> "TEST"
    (elt $ 1))

This is more like F#'s |> (and the shell pipe) than Haskell's ., but they are pretty much the same thing (I prefer |>, but this is a matter of personal taste).

To see what -> is doing, just macroexpand the last example three times (in SLIME, this is accomplished by putting the cursor on the first ( in the example and typing C-c RET three times).

share|improve this answer

YES, it's possible and @danlei already explained very well. I am going to add up some examples from the book ANSI Common Lisp by Paul Graham, chapter 6.6 on function builders:

you can define a function builder like this:

(defun compose (&rest fns)
    #'(lambda (&rest args)

(defun curry (fn &rest args)
  #'(lambda (&rest args2)
      (apply fn (append args args2))))

and use it like this

(mapcar (compose #'list #'round #'sqrt)
        '(4 9 16 25))


((2) (3) (4) (5))

The compose function call:

(compose #'a #'b #'c)

is equlvalent to

#'(lambda (&rest args) (a (b (apply #'c args))))

This means compose can take any number of arguments, yeah.

Make a function which add 3 to argument:

(curry #'+ 3)

See more in the book.

share|improve this answer
but it does not make much sense. It leads to bad code. More difficult to read and debug. Plus - almost every CL compiler will generate slow code for that (consed arg lists, etc.). –  Rainer Joswig Jun 17 '12 at 22:33
@RainerJoswig You're right. This could show how flexible CL it is and what closure may help us... o_O –  juanitofatas Jun 18 '12 at 0:01
Your compose example works with my version too. I just had a little copy & paste error or typo in comp (wrong order of function calls in step, working version in the REPL) that's fixed now. Also, I think Rainer is right: While it sure it is nice to be able to do this in CL, it isn't very idiomatic. Haskell lends itself much more to this style of programming. (Graham's style, btw, is considered pretty idiosyncratic by many CL programmers.) –  danlei Jun 18 '12 at 9:29

Yes, this is possible in general with the right functions. For example, here is an example in Racket implementing sum from the Wikipedia page:

#lang racket
(define sum (curry foldr + 0))

Since procedures are not curried by default, it helps to use curry or write your functions in an explicitly curried style. You could abstract over this with a new define macro that uses currying.

share|improve this answer
The question is about Common Lisp, this answer is correct for Scheme, but not for CL –  Óscar López Jun 17 '12 at 20:43
Well, actually the question was about Lisp in general. I added CL as a tag since it's the Lisp dialect that I'm most familiar with but this answer using Scheme is useful as well. –  paldepind Jun 20 '12 at 8:34

Your Answer


