Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

REBINDING specification

15 views
Skip to first unread message

Vebjorn Ljosa

unread,
Nov 24, 2001, 7:22:41 PM11/24/01
to
Here's another generally useful macro which exists several places out
there. I hope we can agree on a specification so it can be added to
Common Lisp Utilities (<URL:http://ww.telent.net/cliki/
Common%20Lisp%20Utilities>).

- Vebjorn


Macro REBINDING

Syntax:

REBINDING ( { var | (var prefix) }* ) form* => result

Arguments and Values:

var---a symbol; not evaluated.
prefix---a string designator; not evaluated. The default is var.
form---a form.
results---the values returned by the forms.

Description:

Evaluates a series of forms in the lexical environment that is
formed by adding the binding of each var to a fresh, uninterned
symbol, and the binding of that fresh, uninterned symbol to var's
original value, i.e., its value in the current lexical
environment.

The uninterned symbol is created as if by a call to GENSYM with
the string denoted by prefix---or, if prefix is not supplied, the
string denoted by var---as argument.

The forms are evaluated in order, and the values of all but the
last are discarded (that is, the body is an implicit progn).

Examples:

To avoid multiple evaluation, macros are often written in the
following fashion:

(defmacro foo (var1 var2)
(let ((v1 (gensym))
(v2 (gensym)))
`(let ((,v1 ,var1)
(,v2 ,var2))
(+ (* ,v1 ,v1) (* ,v2 ,v2)))))

With REBINDING, the same can be achieved with

(defmacro foo (var1 var2)
(rebinding ((var1 :var1-)
(var2 :var2-))
`(+ (* ,var1 ,var1) (* ,var2 ,var2))))

The form (foo bar baz) then macroexpands to

(let ((#:var1-1019 bar)
(#:var2-1020 baz))
(+ (/ #:var1-1019 #:var1-1019) (* #:var2-1020 #:var2-1020)))

Side Effects:

Might increase *GENSYM-COUNTER* once for each var.

Affected By:

*GENSYM-COUNTER*

Exceptional Situations:

None.

See Also:

WITH-UNIQUE-NAMES, GENSYM, LET, LAMBDA

Status:

First draft posted to comp.lang.lisp for discussion. Suggested
for eventual inclusion in the layered community standard known as
Common Lisp Utilities.

Reference Implementation:

(defmacro rebinding (bindings &body body)
(loop
for binding in bindings
for var = (if (consp binding) (car binding) binding)
for name = (gensym)
collect `(,name ,var) into renames
collect ``(,,var ,,name) into temps
finally (return `(let ,renames
(with-unique-names ,bindings
`(let (,,@temps)
,,@body))))))

--
Vebjorn Ljosa

Kalle Olavi Niemitalo

unread,
Nov 25, 2001, 4:06:13 AM11/25/01
to
Vebjorn Ljosa <ab...@ljosa.com> writes:

> results---the values returned by the forms.

If this were true, (let (x) (rebinding (x) t)) would evaluate to T.
Now it evaluates to (let ((#:x923 nil)) t).

> Evaluates a series of forms in the lexical environment that is
> formed by adding the binding of each var to a fresh, uninterned
> symbol, and the binding of that fresh, uninterned symbol to var's
> original value, i.e., its value in the current lexical
> environment.

The second set of bindings does not take effect when the
REBINDING form is evaluated. Rather, REBINDING puts a LET form
(or implementation-defined equivalent?) around the result (which
can be only one value) so that the bindings take effect when/if
the result is evaluated. Also, the LET form will evaluate the
original value of each var, instead of using them directly.

0 new messages