Anaphoric Macros

New in version 0.9.12.

The anaphoric macros module makes functional programming in Hy very concise and easy to read.

An anaphoric macro is a type of programming macro that deliberately captures some form supplied to the macro which may be referred to by an anaphor (an expression referring to another).

—Wikipedia (

To use these macros you need to require the hy.extra.anaphoric module like so:

(require [hy.extra.anaphoric [*]])

These macros are implemented by replacing any use of the designated anaphoric symbols (it, in most cases) with a gensym. Consequently, it’s unwise to nest these macros where symbol replacement is happening. Symbol replacement typically takes place in body or form parameters, where the output of the expression may be returned. It is also recommended to avoid using an affected symbol as something other than a variable name, as in (print "My favorite Stephen King book is" 'it).


Usage: (ap-if test-form then-form else-form)

As if, but the result of the test form is named it in the subsequent forms. As with if, the else-clause is optional.

=> (import os)
=> (ap-if (.get os.environ "PYTHONPATH")
...  (print "Your PYTHONPATH is" it))


Usage: (ap-each xs body…)

Evaluate the body forms for each element it of xs and return None.

=> (ap-each [1 2 3] (print it))


Usage: (ap-each-while xs pred body…)

As ap-each, but the form pred is run before the body forms on each iteration, and the loop ends if pred is false.

=> (ap-each-while [1 2 3 4 5 6] (< it 4) (print it))


Usage: (ap-map form xs)

Create a generator like map() that yields each result of form evaluated with it bound to successive elements of xs.

=> (list (ap-map (* it 2) [1 2 3]))
[2, 4, 6]


Usage: (ap-map-when predfn rep xs)

As ap-map, but the predicate function predfn (yes, that’s a function, not an anaphoric form) is applied to each it, and the anaphoric mapping form rep is only applied if the predicate is true. Otherwise, it is yielded unchanged.

=> (list (ap-map-when odd? (* it 2) [1 2 3 4]))
[2, 2, 6, 4]

=> (list (ap-map-when even? (* it 2) [1 2 3 4]))
[1, 4, 3, 8]


Usage: (ap-filter form xs)

The filter() equivalent of ap-map.

=> (list (ap-filter (> (* it 2) 6) [1 2 3 4 5]))
[4, 5]


Usage: (ap-reject form xs)

Equivalent to (ap-filter (not form) xs).

=> (list (ap-reject (> (* it 2) 6) [1 2 3 4 5]))
[1, 2, 3]


Usage: (ap-dotimes n body…)

Equivalent to (ap-each (range n) body…).

 => (setv n [])
 => (ap-dotimes 3 (.append n it))
 => n
[0, 1, 2]


Usage: (ap-first form xs)

Evaluate the predicate form for each element it of xs. When the predicate is true, stop and return it. If the predicate is never true, return None.

=> (ap-first (> it 5) (range 10))


Usage: (ap-last form list)

Evaluate the predicate form for every element it of xs. Return the last element for which the predicate is true, or None if there is no such element.

=> (ap-last (> it 5) (range 10))


Usage: (ap-reduce form xs &optional initial-value)

This macro is an anaphoric version of reduce(). It works as follows:

  • Bind acc to the first element of xs, bind it to the second, and evaluate form.
  • Bind acc to the result, bind it to the third value of xs, and evaluate form again.
  • Bind acc to the result, and continue until xs is exhausted.

If initial-value is supplied, the process instead begins with acc set to initial-value and it set to the first element of xs.

=> (ap-reduce (+ it acc) (range 10))


Usage: #% expr

Makes an expression into a function with an implicit % parameter list.

A %i symbol designates the (1-based) i th parameter (such as %3). Only the maximum %i determines the number of %i parameters–the others need not appear in the expression. %* and %** name the &rest and &kwargs parameters, respectively.

=> (#%[%1 %6 42 [%2 %3] %* %4] 1 2 3 4 555 6 7 8)
[1, 6, 42, [2, 3], (7, 8), 4]
=> (#% %** :foo 2)
{"foo": 2}

When used on an s-expression, #% is similar to Clojure’s anonymous function literals–#().

=> (setv add-10 #%(+ 10 %1))
=> (add-10 6)

#% determines the parameter list by the presence of a %* or %** symbol and by the maximum %i symbol found anywhere in the expression, so nesting of #% forms is not recommended.