Reader macros for easy function currying and composition.

Upstream URL


Maciej Pasternacki <>


BSD sans advertising clause (see file COPYING for details)


Curly is set of two reader macros for easy function currying andcomposition. It was inspired by Arc's syntax for currying, usingsquare brackets. Curly creates anonymous functions (lambdas) withliteral function composition instead of trying smarter approach(like using (REDUCE #'FUNCALL ...)) so that the compiler is able todo more optimizations.

ASDF system definition is included in curly.asd file.

Latest version of Curly can be obtained on its GitHub page:

1.1Square bracket macro

Square bracket macro does simple currying:

:CURLY> '[foo] :(LAMBDA (#:G2705) (FOO #:G2705)) :CURLY> '[foo bar] :(LAMBDA (#:G2706) (FOO BAR #:G2706)) :CURLY> '[foo bar baz] :(LAMBDA (#:G2707) (FOO BAR BAZ #:G2707))

By using symbol configured by CURLY:*BLANK-ARGUMENT* user can put anonymous function's parameter in desired place, not necessarily at end of argument list. By default, blank argument is a single star, but it can be set e.g. to underscore to better match Arc:

:CURLY> '[foo bar * baz] :(LAMBDA (#:G2709) (FOO BAR #:G2709 BAZ)) :CURLY> '[foo * bar baz] :(LAMBDA (#:G2710) (FOO #:G2710 BAR BAZ))

Curly interpretes blank argument only in argument position; blank argument in functional position is left untouched:

:CURLY> '[* foo bar baz] :(LAMBDA (#:G2711) (* FOO BAR BAZ #:G2711)) :CURLY> '[* foo * baz] :(LAMBDA (#:G2712) (* FOO #:G2712 BAZ))

1.2Curly bracket macro

Curly bracket does function composition, which may be coupled withcurrying. Let's start from simple composition:

:CURLY> '{foo bar} :(LAMBDA (#:G2714) (FOO (BAR #:G2714))) :CURLY> '{foo bar baz} :(LAMBDA (#:G2715) (FOO (BAR (BAZ #:G2715)))) :CURLY> '{foo bar baz quux} :(LAMBDA (#:G2716) (FOO (BAR (BAZ (QUUX #:G2716)))))

And so on, and so on. When instead of a function name there is a list within the braces, this means currying:

:CURLY> '{foo (bar 23) baz quux} :(LAMBDA (#:G2721) (FOO (BAR 23 (BAZ (QUUX #:G2721))))) :CURLY> '{foo (bar 16) (baz 23 42) quux} :(LAMBDA (#:G2723) (FOO (BAR 16 (BAZ 23 42 (QUUX #:G2723)))))

Of course, when currying within braces, blank argument can be used as well:

:CURLY> '{foo (bar 16) (baz 23 * 42) quux} :(LAMBDA (#:G2724) (FOO (BAR 16 (BAZ 23 (QUUX #:G2724) 42)))) :CURLY> '{foo (bar 16) (baz * 23 42) quux} :(LAMBDA (#:G2725) (FOO (BAR 16 (BAZ (QUUX #:G2725) 23 42)))


All Curly functions, macros and variables are exported from packageCURLY.


Variable: specifies symbol that is used to indicate blank argumentfor currying. Default value is '*.

2.2CURLY-READER stream character

Function: reader macro function for curly braces (composition).

2.3SQUARE-READER stream character

Function: reader macro function for square braces (currying).

2.4MAKE-CURLY-READTABLE &optional (original-readtable readtable)

Function: returns modified copy of ORIGINAL-READTABLE that hasCurly reader macros turned on.


Macro: enable curly syntax for current file.


Macro: disable curly syntax for current file.

Warning: Calling DISABLE-CURLY-SYNTAX when curly syntax is not enabled can give funny results. Also, reading multiple files using ENABLE-CURLY-SYNTAX and DISABLE-CURLY-SYNTAX in different threads can invoke a disaster. ENABLE-CURLY-SYNTAX itself is safe.


Unit tests are included in tests.lisp file. To run test, you needFiveAM testing framework along with required Arnesi library from

To run the tests, simply load curly with ASDF, and then type into REPL:

(asdf:operate 'asdf:test-op :curly)

Dependencies (1)

  • fiveam

Dependents (0)

    • GitHub
    • Quicklisp