Subject: Re: LAND*: an AND with local bindings
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1998/02/26
Newsgroups: comp.lang.scheme
Message-ID: <6d3bb3$3804h@fido.asd.sgi.com>

<oleg@pobox.com> wrote:
+---------------
| Like an ordinary AND, a LAND* special form evaluates its arguments -
| expressions - one after another in order till the first one that
| yields #f. Unlike AND, however, a non-#f result of one expressions can
| be bound to a fresh variable and used in the subsequent expressions.
+---------------

See also the "anaphoric AND" and "anaphoric OR" macros in Paul
Graham's book, "On Lisp". They let you do similar things, but
with the just-previous intermediate value bound to the implied
variable "it" (yes, deliberate capture!), rather than being explicit
as LAND*.  Oleg's examples:

	(or (LAND* ((c (read-char))
		    ((not (eof-object? c))))
	      (string-set! some-str i c)
	      (++! i))
	    (do-process-eof))

and:

	(LAND* ((my-list (compute-list))
		((not (null? my-list))))
	  (do-something my-list))

could be written in Graham's style ["aand" = anaphoric AND] as:

	(or (aand (read-char)
		  (and (not (eof-object? it))	; note: plain "and"
		       (begin
		         (string-set! some-str i it)
		         (++! i)
		         #t))
	    (do-process-eof))

and:

	(aand (compute-list)
	      (and (not (null? it))
	           (do-something it)))

The main difference is that Graham's macros re-bind the same variable "it"
to each intermediate result of the "aand", which gets clumsy at times.
Oleg allows more than one intermediate result, each of which continue
to be bound across the entire rest of the LAND*.

Personally, when I first saw Graham's "anaphoric AND" I found it cute,
but not compelling, and I'm afraid I'm not that excited about Oleg's
"LAND*", either. I think both the above examples can be written more
clearly in plain Scheme (well, almost plain -- I assume "++!" is a macro?):

	(let ((c (read-char)))
	  (cond ((eof-object? c)
		 (do-process-eof))
		(else
		 (string-set! some-str i it)
		 (++! i))))
and:
	(let ((ls (compute-list)))
	  (when (not (null? ls))
	    (do-something ls)))


-Rob

p.s. Of course, if you use DO or named-LET you can eliminate the
side-effecting "++!" and "string-set!", and maybe add some safety
from buffer overflows, too.

-----
Rob Warnock, 7L-551		rpw3@sgi.com   http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673 [New area code!]
2011 N. Shoreline Blvd.		FAX: 650-933-4392
Mountain View, CA  94043	PP-ASEL-IA