Implement SRFI 2: AND-LET*
authorTaylor R. Campbell <net/mumble/campbell>
Fri, 9 Dec 2005 20:25:59 +0000 (20:25 +0000)
committerTaylor R. Campbell <net/mumble/campbell>
Fri, 9 Dec 2005 20:25:59 +0000 (20:25 +0000)
v7/doc/ref-manual/scheme.texinfo
v7/doc/ref-manual/special-forms.texi
v7/src/edwin/schmod.scm
v7/src/runtime/mit-syntax.scm

index 86b4aa8840efb5b67bc4939cd0f472ae743da9a1..673dcade82ebb0d7411d242179cac13826673676 100644 (file)
@@ -1,10 +1,10 @@
 \input texinfo @c -*-texinfo-*-
-@comment $Id: scheme.texinfo,v 1.134 2005/05/20 02:15:49 cph Exp $
+@comment $Id: scheme.texinfo,v 1.135 2005/12/09 20:25:58 riastradh Exp $
 @comment %**start of header
 @setfilename mit-scheme-ref
 @set EDITION 1.103
 @set VERSION 7.7.90+
-@set UPDATED 2005-05-19
+@set UPDATED 2005-12-09
 @settitle MIT/GNU Scheme @value{VERSION}
 @comment %**end of header
 @setchapternewpage odd
@@ -179,6 +179,7 @@ SRFI syntax
 
 * cond-expand (SRFI 0)::        
 * receive (SRFI 8)::            
+* and-let* (SRFI 2)::
 * define-record-type (SRFI 9)::  
 
 Numbers
index 15f0b393b72c08886e7c29d56e6bfe9db6165541..958690a252730361a4cf01985ca5187ae5f11a77 100644 (file)
@@ -1,9 +1,9 @@
 @c This file is part of the MIT/GNU Scheme Reference Manual.
-@c $Id: special-forms.texi,v 1.2 2003/04/25 20:40:22 cph Exp $
+@c $Id: special-forms.texi,v 1.3 2005/12/09 20:25:59 riastradh Exp $
 
 @c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology
 @c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology
-@c Copyright 2002,2003 Massachusetts Institute of Technology
+@c Copyright 2002,2003,2005 Massachusetts Institute of Technology
 @c See file scheme.texinfo for copying conditions.
 
 @node Special Forms, Equivalence Predicates, Overview, Top
@@ -2771,6 +2771,7 @@ existing practice rather than introducing new functionality.
 @menu
 * cond-expand (SRFI 0)::        
 * receive (SRFI 8)::            
+* and-let* (SRFI 2)::
 * define-record-type (SRFI 9)::  
 @end menu
 
@@ -2847,7 +2848,7 @@ special form is allowed.  This is an extension of the semantics defined
 by @acronym{SRFI 0}, which only allows @code{cond-expand} at top level.
 @end deffn
 
-@node receive (SRFI 8), define-record-type (SRFI 9), cond-expand (SRFI 0), SRFI syntax
+@node receive (SRFI 8), and-let* (SRFI 2), cond-expand (SRFI 0), SRFI syntax
 @subsection receive (SRFI 8)
 
 @cindex SRFI 8
@@ -2939,7 +2940,57 @@ the extended environment.  The results of the last expression in the
 body are the values of the @samp{receive} expression.
 @end deffn
 
-@node define-record-type (SRFI 9),  , receive (SRFI 8), SRFI syntax
+@node and-let* (SRFI 2), define-record-type (SRFI 9), receive (SRFI 8), SRFI syntax
+@subsection and-let* (SRFI 2)
+
+@cindex SRFI 2
+@uref{http://srfi.schemers.org/srfi-2/srfi-2.html,@acronym{SRFI} 2}
+provides a form that combines @samp{and} and @samp{let*} for a
+logically short-circuiting sequential binding operator.
+
+@deffn {special form} and-let* (clause @dots{}) body
+Runs through each of the clauses left-to-right, short-circuiting like
+@samp{and} in that the first false clause will result in the whole
+@samp{and-let*} form returning false.  If a body is supplied, and all
+of the clauses evaluate true, then the body is evaluated sequentially
+as if in a @samp{begin} form, and the value of the @samp{and-let*}
+expression is the value of the last body form, evaluated in a tail
+position with respect to the @samp{and-let*} expression.  If no body
+is supplied, the value of the last clause, also evaluated in a tail
+position with respect to the @samp{and-let*} expression, is used
+instead.
+
+Each @var{clause} should have one of the following forms:
+
+@table @samp
+@item @var{identifier}
+in which case @var{identifier}'s value is tested.
+
+@item (@var{expression})
+in which case the value of @var{expression} is tested.
+
+@item (@var{identifier} @var{expression})
+in which case @var{expression} is evaluated, and, if its value is not
+false, @var{identifier} is bound to that value for the remainder of
+the clauses and the optional body.
+@end table
+@end deffn
+
+@comment More examples, please!
+
+Example:
+
+@example
+@group
+(and-let* ((list (compute-list))
+           ((pair? list))
+           (item (car list))
+           ((integer? item)))
+  (sqrt item))
+@end group
+@end example
+
+@node define-record-type (SRFI 9),  , and-let* (SRFI 2), SRFI syntax
 @subsection define-record-type (SRFI 9)
 
 @cindex SRFI 9
index 8b2b889994b7296d492568aaa5aaae413abc9c1d..333c921ae98f2e333d33ac4ebd496da2b054112f 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: schmod.scm,v 1.72 2005/06/10 01:50:46 cph Exp $
+$Id: schmod.scm,v 1.73 2005/12/09 20:25:59 riastradh Exp $
 
 Copyright 1986,1989,1990,1991,1992,1998 Massachusetts Institute of Technology
 Copyright 2000,2001,2002,2003,2004,2005 Massachusetts Institute of Technology
@@ -179,6 +179,7 @@ The following commands evaluate Scheme expressions:
               CALL-WITH-OUTPUT-FILE WITH-OUTPUT-TO-FILE)
 
            ;; SRFI keywords:
+            (1 AND-LET*)
            (2 RECEIVE)
            (3 DEFINE-RECORD-TYPE)
 
index 44a24f85706194de63964f2ae19aabc42eb58d33..9d730620051109c113dfbfa3bb247cc308831bc3 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: mit-syntax.scm,v 14.23 2005/11/20 04:12:59 riastradh Exp $
+$Id: mit-syntax.scm,v 14.24 2005/12/09 20:25:59 riastradh Exp $
 
 Copyright 1989,1990,1991,2001,2002,2003 Massachusetts Institute of Technology
 Copyright 2004 Massachusetts Institute of Technology
@@ -335,6 +335,7 @@ USA.
 
 (define supported-srfi-features
   '(SRFI-0
+    SRFI-2
     SRFI-6
     SRFI-8
     SRFI-9
@@ -810,6 +811,52 @@ USA.
          (syntax-check '(KEYWORD EXPRESSION) form history)
          (descend-quasiquote (cadr form) 0 finalize-quasiquote)))))))
 \f
+;;;; SRFI 2: AND-LET*
+
+;;; The SRFI document is a little unclear about the semantics, imposes
+;;; the weird restriction that variables may be duplicated (citing
+;;; LET*'s similar restriction, which doesn't actually exist), and the
+;;; reference implementation is highly non-standard and hard to
+;;; follow.  This passes all of the tests except for the one that
+;;; detects duplicate bound variables, though.
+
+(define-er-macro-transformer 'AND-LET* system-global-environment
+  (lambda (form rename compare)
+    compare
+    (let ((%and (rename 'AND))
+          (%let (rename 'LET))
+          (%begin (rename 'BEGIN)))
+      (cond ((syntax-match? '(() * FORM) (cdr form))
+             `(,%begin #T ,@(cddr form)))
+            ((syntax-match? '((* DATUM) * FORM) (cdr form))
+             (let ((clauses (cadr form))
+                   (body (cddr form)))
+               (define (expand clause recur)
+                 (cond ((syntax-match? 'IDENTIFIER clause)
+                        (recur clause))
+                       ((syntax-match? '(EXPRESSION) clause)
+                        (recur (car clause)))
+                       ((syntax-match? '(IDENTIFIER EXPRESSION) clause)
+                        (let ((tail (recur (car clause))))
+                          (and tail `(,%let (,clause) ,tail))))
+                       (else #f)))
+               (define (recur clauses make-body)
+                 (expand (car clauses)
+                         (let ((clauses (cdr clauses)))
+                           (if (null? clauses)
+                               make-body
+                               (lambda (conjunct)
+                                 `(,%and ,conjunct
+                                         ,(recur clauses make-body)))))))
+               (or (recur clauses
+                          (if (null? body)
+                              (lambda (conjunct) conjunct)
+                              (lambda (conjunct)
+                                `(,%and ,conjunct (,%begin ,@body)))))
+                   (ill-formed-syntax form))))
+            (else
+             (ill-formed-syntax form))))))
+\f
 ;;;; MIT-specific syntax
 
 (define-er-macro-transformer 'ACCESS system-global-environment