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 (https://en.wikipedia.org/wiki/Anaphoric_macro)

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

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

ap-if

Usage: (ap-if (foo) (print it))

Evaluates the first form for truthiness, and bind it to it in both the true and false branches.

ap-each

Usage: (ap-each [1 2 3 4 5] (print it))

Evaluate the form for each element in the list for side-effects.

ap-each-while

Usage: (ap-each-while list pred body)

Evaluate the form for each element where the predicate form returns True.

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

ap-map

Usage: (ap-map form list)

The anaphoric form of map works just like regular map except that instead of a function object it takes a Hy form. The special name it is bound to the current object from the list in the iteration.

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

ap-map-when

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

Evaluate a mapping over the list using a predicate function to determin when to apply the form.

=> (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]

ap-filter

Usage: (ap-filter form list)

As with ap-map we take a special form instead of a function to filter the elements of the list. The special name it is bound to the current element in the iteration.

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

ap-reject

Usage: (ap-reject form list)

This function does the opposite of ap-filter, it rejects the elements passing the predicate . The special name it is bound to the current element in the iteration.

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

ap-dotimes

Usage (ap-dotimes n body)

This function evaluates the body n times, with the special variable it bound from 0 to 1-n. It is useful for side-effects.

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

ap-first

Usage (ap-first predfn list)

This function returns the first element that passes the predicate or None, with the special variable it bound to the current element in iteration.

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

ap-last

Usage (ap-last predfn list)

This function returns the last element that passes the predicate or None, with the special variable it bound to the current element in iteration.

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

ap-reduce

Usage (ap-reduce form list &optional initial-value)

This function returns the result of applying form to the first 2 elements in the body and applying the result and the 3rd element etc. until the list is exhausted. Optionally an initial value can be supplied so the function will be applied to initial value and the first element instead. This exposes the element being iterated as it and the current accumulated value as acc.

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

ap-pipe

Usage (ap-pipe value form1 form2 ...)

Applies several forms in series to a value from left to right. The special variable ìt in each form is replaced by the result of the previous form.

=> (ap-pipe 3 (+ it 1) (/ 5 it))
1.25
=> (ap-pipe [4 5 6 7] (list (rest it)) (len it))
3

ap-compose

Usage (ap-compose form1 form2 ...)

Returns a function which applies several forms in series from left to right. The special variable ìt in each form is replaced by the result of the previous form.

=> (def op (ap-compose (+ it 1) (* it 3)))
=> (op 2)
9

xi

Usage (xi body ...)

Returns a function with parameters implicitly determined by the presence in the body of xi parameters. An xi symbol designates the ith parameter (1-based, e.g. x1, x2, x3, etc.), or all remaining parameters for xi itself. This is not a replacement for fn. The xi forms cannot be nested.

This is similar to Clojure’s anonymous function literals (#()).

=> ((xi identity [x1 x5 [x2 x3] xi x4]) 1 2 3 4 5 6 7 8)
[1, 5, [2, 3,] (6, 7, 8), 4]
=> (def add-10 (xi + 10 x1))
=> (add-10 6)
16