123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- ;;; srfi-11.scm --- let-values and let*-values
- ;; Copyright (C) 2000, 2001, 2002, 2004, 2006, 2009 Free Software Foundation, Inc.
- ;;
- ;; This library is free software; you can redistribute it and/or
- ;; modify it under the terms of the GNU Lesser General Public
- ;; License as published by the Free Software Foundation; either
- ;; version 3 of the License, or (at your option) any later version.
- ;;
- ;; This library is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;; Lesser General Public License for more details.
- ;;
- ;; You should have received a copy of the GNU Lesser General Public
- ;; License along with this library; if not, write to the Free Software
- ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- ;;; Commentary:
- ;; This module exports two syntax forms: let-values and let*-values.
- ;;
- ;; Sample usage:
- ;;
- ;; (let-values (((x y . z) (foo a b))
- ;; ((p q) (bar c)))
- ;; (baz x y z p q))
- ;;
- ;; This binds `x' and `y' to the first to values returned by `foo',
- ;; `z' to the rest of the values from `foo', and `p' and `q' to the
- ;; values returned by `bar'. All of these are available to `baz'.
- ;;
- ;; let*-values : let-values :: let* : let
- ;;
- ;; This module is fully documented in the Guile Reference Manual.
- ;;; Code:
- (define-module (srfi srfi-11)
- :export-syntax (let-values let*-values))
- (cond-expand-provide (current-module) '(srfi-11))
- ;;;;;;;;;;;;;;
- ;; let-values
- ;;
- ;; Current approach is to translate
- ;;
- ;; (let-values (((x y . z) (foo a b))
- ;; ((p q) (bar c)))
- ;; (baz x y z p q))
- ;;
- ;; into
- ;;
- ;; (call-with-values (lambda () (foo a b))
- ;; (lambda (<tmp-x> <tmp-y> . <tmp-z>)
- ;; (call-with-values (lambda () (bar c))
- ;; (lambda (<tmp-p> <tmp-q>)
- ;; (let ((x <tmp-x>)
- ;; (y <tmp-y>)
- ;; (z <tmp-z>)
- ;; (p <tmp-p>)
- ;; (q <tmp-q>))
- ;; (baz x y z p q))))))
- ;; We could really use quasisyntax here...
- (define-syntax let-values
- (lambda (x)
- (syntax-case x ()
- ((_ ((binds exp)) b0 b1 ...)
- (syntax (call-with-values (lambda () exp)
- (lambda binds b0 b1 ...))))
- ((_ (clause ...) b0 b1 ...)
- (let lp ((clauses (syntax (clause ...)))
- (ids '())
- (tmps '()))
- (if (null? clauses)
- (with-syntax (((id ...) ids)
- ((tmp ...) tmps))
- (syntax (let ((id tmp) ...)
- b0 b1 ...)))
- (syntax-case (car clauses) ()
- (((var ...) exp)
- (with-syntax (((new-tmp ...) (generate-temporaries
- (syntax (var ...))))
- ((id ...) ids)
- ((tmp ...) tmps))
- (with-syntax ((inner (lp (cdr clauses)
- (syntax (var ... id ...))
- (syntax (new-tmp ... tmp ...)))))
- (syntax (call-with-values (lambda () exp)
- (lambda (new-tmp ...) inner))))))
- ((vars exp)
- (with-syntax ((((new-tmp . new-var) ...)
- (let lp ((vars (syntax vars)))
- (syntax-case vars ()
- ((id . rest)
- (acons (syntax id)
- (car
- (generate-temporaries (syntax (id))))
- (lp (syntax rest))))
- (id (acons (syntax id)
- (car
- (generate-temporaries (syntax (id))))
- '())))))
- ((id ...) ids)
- ((tmp ...) tmps))
- (with-syntax ((inner (lp (cdr clauses)
- (syntax (new-var ... id ...))
- (syntax (new-tmp ... tmp ...))))
- (args (let lp ((tmps (syntax (new-tmp ...))))
- (syntax-case tmps ()
- ((id) (syntax id))
- ((id . rest) (cons (syntax id)
- (lp (syntax rest))))))))
- (syntax (call-with-values (lambda () exp)
- (lambda args inner)))))))))))))
- ;;;;;;;;;;;;;;
- ;; let*-values
- ;;
- ;; Current approach is to translate
- ;;
- ;; (let*-values (((x y z) (foo a b))
- ;; ((p q) (bar c)))
- ;; (baz x y z p q))
- ;;
- ;; into
- ;;
- ;; (call-with-values (lambda () (foo a b))
- ;; (lambda (x y z)
- ;; (call-with-values (lambda (bar c))
- ;; (lambda (p q)
- ;; (baz x y z p q)))))
- (define-syntax let*-values
- (syntax-rules ()
- ((let*-values () body ...)
- (let () body ...))
- ((let*-values ((vars-1 binding-1) (vars-2 binding-2) ...) body ...)
- (call-with-values (lambda () binding-1)
- (lambda vars-1
- (let*-values ((vars-2 binding-2) ...)
- body ...))))))
- ;;; srfi-11.scm ends here
|