chickadee » anaphora

anaphora

Inspired by Paul Graham's classic "On Lisp" this module introduces anaphoric macros, which are unhygienic by design. Hence they can not be implemented with syntax-rules! In fact, they introduce new identifiers behind the scene, mostly named it, which can be referenced in the body without being declared. Most of them are prefixed with an a to remind the user, that they pollute the namespace with undeclared identifiers. Remember, that in a natural language an anaphor is an expression, which refers back in the conversation: "Buy this book and read it."

For comparison, some of these unhygienic anaphoric macros are accompanied by named hygienic ones, each prefixed with an n. Like named let, they introduce an identifier as first parameter, which can be used in the body. That's the identifier, the anaphoric versions declare implicitly.

Programming interface

This documentation uses special ellipses, .. and ...., to repeat the pattern(s) to the left zero or one and one or many times respectively.

anaphora

(anaphora sym ..) procedure

Documentation procedure. Called without argument it returns the list of exported symbols, with one of those symbols as argument it returns its documentation.

aif

(aif test consequent alternative ..) syntax

Anaphoric version of if.

Binds the result of test to the symbol it, which can than be used in the consequent or the mandatory anternative.

(aif (memv 3 '(1 2 3 4 5)) it #f)

nif

(nif name test consequent alternative ..) syntax

Named version of if.

Binds the result of test to the symbol name, which can than be used in the consequent or the mandatory anternative.

(nif it (memv 3 '(1 2 3 4 5)) it #f)

awhen

(awhen test xpr . xprs) syntax

Anaphoric version of when, i.e. the one-armed if, which allows multiple expressions to be evaluated, if test succeeds. As with aif, the result of test is stored in the variable it, which can be refered in xpr ...

(awhen (memv 3 '(1 2 3 4 5))
  (print it)
  (reverse it))

nwhen

(nwhen name test xpr . xprs) syntax

Named version of when, i.e. the one-armed if, which allows multiple expressions to be evaluated, if test succeeds. As with nif, the result of test is stored in the variable name, which can be refered in the body.

(nwhen it (memv 3 '(1 2 3 4 5))
  (print it)
  (reverse it))

acond

(acond ((test xpr ...) ... (else ypr ...) ..)) syntax

Anaphoric version of cond.

The result of each test is stored in the variable it, which can be used in the corresponding expressions xpr ...

(acond
	((memv 6 '(1 2 3 4 5)) it)
	((memv 3 '(1 2 3 4 5)) it)
	(else it))

Note, that the ordinary cond macro does something similar with the literal symbol =>.

ncond

(ncond name ((test xpr ...) ... (else ypr ...) ..)) syntax

Named version of cond.

The result of each test is stored in the variable name, which can be used in the corresponding expressions xpr ...

(ncond it
	((memv 6 '(1 2 3 4 5)) it)
	((memv 3 '(1 2 3 4 5)) it)
	(else it))

Note, that the ordinary cond macro does something similar with the literal symbol =>.

awhile

(awhile test xpr . xprs) syntax

Anaphoric version of while.

The body xpr . xprs is evaluated as often, as the test is true. As usual, the result of this test, which often is the result of a poll operation, is named it and can be referenced in the body.

(let ((lst '(1 2 3 4 5 #f)) (res '()))
	(awhile (car lst)
		(set! res (cons (car lst) res))
		(set! lst (cdr lst)))
	res)

Of course, this is not the preferred programming style in Scheme ...

nwhile

(nwhile name test xpr . xprs) syntax

Named version of while.

The body xpr . xprs is evaluated as often, as the test is true. As usual, the result of this test, which often is the result of a poll operation, is named name and can be referenced in the body.

(let ((lst '(1 2 3 4 5 #f)) (res '()))
	(nwhile it (car lst)
		(set! res (cons (car lst) res))
		(set! lst (cdr lst)))
	res)

Of course, this is not the preferred programming style in Scheme ...

aand

(aand arg ...) syntax

Anaphoric version of and.

When sequentially evaluating the arguments arg ..., the anaphor it will be bound to the value of the previous argument.

(let ((lst '(1 2 3)))
  (aand lst (cdr it) (cdr it)))

nand

(nand name arg ...) syntax

Named version of and.

When sequentially evaluating the arguments arg ..., the identifier name will be bound to the value of the previous argument.

(let ((lst '(1 2 3 4)))
  (nand it lst (cdr it) (cdr it) (car it)))

alambda

(alambda args xpr . xprs) syntax

Anaphoric version of lambda.

The resulting procedure is bound to the anaphor self. This way, anonymous functions can be recursive as well.

(map (alambda (n) (if (zero? n) 1 (* n (self (- n 1)))))
     '(1 2 3 4 5))

nlambda

(nlambda name args xpr . xprs) syntax

Named version of lambda.

The resulting procedure is bound to the identifier name. This way, anonymous functions can be recursive as well.

(map (nlambda self (n) (if (zero? n) 1 (* n (self (- n 1)))))
     '(1 2 3 4 5))

define-anaphor

(define-anaphor name from rule) syntax

Hygienic macro which writes an anaphoric macro with implicit it, name, from another procedure or macro, from, with rule either #:cascade or #:first Note, that most of the macros above could have been created by means of define-anaphor.

(define-anaphor alist list #:cascade)
(alist 1 (+ it 2) (* it 3)) ; -> '(1 3 9)
(define-anaphor awhen when #:first)
(awhen (* 1 2 3 4 5) (* 2 it)) ; -> 240

define-properties

(define-properties name ...) syntax

Abstracting away get and put!. Defines for each name two macros, name and name!, the first being an accessor to the property name, the second the corresponding mutator.

(define-properties color weight)
(color! 'foo 'red)
(color 'foo) ; -> 'red
(weight! 'foo 5)
(weight 'foo) ;-> 5
(color! 'foo 'blue)
(color 'foo) ; -> 'blue
(weight! 'foo 50)
(weight 'foo) ; -> 50

list-recurser

(list-recurser recurser base) procedure

generates a procedure which traverses on the cdrs of its only list argument.

(define (lsome? ok?)
  (list-recurser (lambda (lst th) (or (ok? (car lst)) (th))) #f))
((lsome? odd?) '(2 4 5 6)) ; -> #t

alist-recurser

(alist-recurser recur-xpr base-xpr) syntax

anaphoric macro with internal symbols it, representing the current list, and go-on, representing traversal along cdrs. The result is a procedure, which recurs on its only list argument.

(define (alsome? ok?)
  (alist-recurser (or (ok? (car it)) (go-on)) #f))
((alsome? odd?) '(2 4 6)) ; -> #f

tree-recurser

(tree-recurser recurser base) procedure

generates a procedure which traverses on the cars and the cdrs of its only tree argument.

(define tcopy
  (tree-recurser (lambda (tree left right)
                   (cons (left) (or (right) '())))
                 identity))
(tcopy '(1 (2 (3 4) 5) 6)) ; -> '(1 (2 (3 4) 5) 6) 

atree-recurser

(atree-recurser recur-xpr base-xpr) syntax

anaphoric macro with internal symbols it, representing the current tree, go-left and go-right, representing traversal along cars and cdrs respectively. The result is a procedure, which recurs on its only list argument.

(define atcopy
  (atree-recurser (cons (go-left) (or (go-right) '())) it))
(atcopy '(1 (2 3 (4)) 5)) ; -> '(1 (2 3 (4)) 5)

Usage

(use anaphora)

Last update

Feb 11, 2014

Author

Juergen Lorenz

License

Copyright (c) 2011-2014, Juergen Lorenz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission. 
  
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Version History

0.6
tests replace simple-test with define-test and compound-test
0.5.1
documentation procedure beautified
0.5
added additional hygienic named macros
0.4
added define-anaphor, define-properties, tree-recurser, atree-recurser, list-recurser and alist-recurser
0.3
helper-module anaphora-helper removed
0.2
documentation dispatcher added
0.1
initial import

Contents »