Defining multiple-values binding forms 
Author Message
 Defining multiple-values binding forms

Since R5RS lacks standard multiple-values binding constructs analogous
to define, set!, let, etc., I'm trying to write my own using
define-syntax.  However, the only construct I've been able to
implement properly is let*-values.  In the other cases, I require
something along the lines of:

(define-syntax set!-values
 (syntax-rules ()
  ((set!-values (i1 i2 ...) expr)
   (call-with-values (lambda () expr)
     (lambda (v1 v2 ...)
       (set! i1 v1)
       (set! i2 v2)
       ...)))))

However, the implementations I've tried this on (MacGambit with SLib
and MzScheme with accompanying synrule library -- yes, I know it has
the forms I want built-in) give obscure errors when the form is
expanded.

I can't tell from the language in R5RS whether all the bound template
variables must be explicitly named, or if their number is permitted to
be determined implicitly by the template structure as I wish it to
here.

Is this indicative of a bug in these implementations of syntax-rules,
or is the template ill-formed?  If it is ill-formed, how could one
portably write macros for this sort of binding form?

Thanks for any help.

-Jesse Welton



Sun, 26 Nov 2000 03:00:00 GMT  
 Defining multiple-values binding forms


Quote:

>Since R5RS lacks standard multiple-values binding constructs analogous
>to define, set!, let, etc., I'm trying to write my own using
>define-syntax.  However, the only construct I've been able to
>implement properly is let*-values.  In the other cases, I require
>something along the lines of:

>(define-syntax set!-values
> (syntax-rules ()
>  ((set!-values (i1 i2 ...) expr)
>   (call-with-values (lambda () expr)
>     (lambda (v1 v2 ...)
>       (set! i1 v1)
>       (set! i2 v2)
>       ...)))))

>However, the implementations I've tried this on (MacGambit with SLib
>and MzScheme with accompanying synrule library -- yes, I know it has
>the forms I want built-in) give obscure errors when the form is
>expanded.

>I can't tell from the language in R5RS whether all the bound template
>variables must be explicitly named, or if their number is permitted to
>be determined implicitly by the template structure as I wish it to
>here.

>Is this indicative of a bug in these implementations of syntax-rules,
>or is the template ill-formed?  If it is ill-formed, how could one
>portably write macros for this sort of binding form?

This is one place where R5RS macros aren't much help.
A portable if clumsy workaround is to use an explicit
list instead of the more natural (defmacro) approach of
generating a bunch of new bound variables that
parallels an existing bunch of identifiers.  To wit:

(define-syntax setq-values
  (syntax-rules ()
    ((setq-values (x ...) e)
     (let ((xx '(x ...)))
       (call-with-values
         (lambda () e)
         (lambda vv
           (set! x (list-ref vv (index-of 'x xx)))
           ...))))))

(define index-of
  (lambda (x xx)
    (let loop ((i 0) (xx xx))
      (cond ((null? xx) #f)
            ((eq? (car xx) x) i)
            (else (loop (+ i 1) (cdr xx)))))))

Note that this will not work if there is identifier
duplication in (x ...).

--d



Sun, 26 Nov 2000 03:00:00 GMT  
 Defining multiple-values binding forms

Quote:

> Since R5RS lacks standard multiple-values binding constructs analogous
> to define, set!, let, etc., I'm trying to write my own using
> define-syntax.  However, the only construct I've been able to
> implement properly is let*-values.  In the other cases, I require
> something along the lines of:

> (define-syntax set!-values
>  (syntax-rules ()
>   ((set!-values (i1 i2 ...) expr)
>    (call-with-values (lambda () expr)
>      (lambda (v1 v2 ...)
>        (set! i1 v1)
>        (set! i2 v2)
>        ...)))))

One could do as follows, allowing several the form to have several
expressions:

(define-syntax set-values!-aux
  (syntax-rules ()
    ((_ () (?var ...) (?tmp ...))
     (lambda (?tmp ...) (set! ?var ?tmp) ...))
    ((_ (?var0 ?var1 ...) (?var ...) (?tmp ...))
     (set-values!-aux (?var1 ...) (?var ... ?var0) (?tmp ... x)))))

(define-syntax set-values!
  (syntax-rules ()
    ((_ (?var ...) ?expr0 . ?exprs)
     (call-with-values (lambda () ?expr0 . ?exprs)
                       (set-values!-aux (?var ...) () ())))))

This could be done using LETREC-SYNTAX instead of an auxiliary
DEFINE-SYNTAX, except that R5RS does not provide any way of quoting
the ... identifier so that it may be used in macro-generated macros.

Alternatively, one may use the trick outlined in the R5RS examples:

(define-syntax set-values!
  (syntax-rules ()
    ((_ "tmps" () (?var ...) (?tmp ...) ?producer)
     (call-with-values ?producer
                       (lambda (?tmp ...) (set! ?var ?tmp) ...)))
    ((_ "tmps" (?var0 ?var1 ...) (?var ...) (?tmp ...) ?producer)
     (set-values! "tmps" (?var1 ...) (?var ... ?var0) (?tmp ... x) ?producer))
    ((_ (?var ...) ?expr0 . ?exprs)
     (set-values! "tmps" (?var ...) () () (lambda () ?expr0 . ?exprs)))))



Mon, 27 Nov 2000 03:00:00 GMT  
 Defining multiple-values binding forms


Quote:

>One could do as follows, allowing several the form to have several
>expressions:

>(define-syntax set-values!-aux
>  (syntax-rules ()
>    ((_ () (?var ...) (?tmp ...))
>     (lambda (?tmp ...) (set! ?var ?tmp) ...))
>    ((_ (?var0 ?var1 ...) (?var ...) (?tmp ...))
>     (set-values!-aux (?var1 ...) (?var ... ?var0) (?tmp ... x)))))

>(define-syntax set-values!
>  (syntax-rules ()
>    ((_ (?var ...) ?expr0 . ?exprs)
>     (call-with-values (lambda () ?expr0 . ?exprs)
>                   (set-values!-aux (?var ...) () ())))))

>This could be done using LETREC-SYNTAX instead of an auxiliary
>DEFINE-SYNTAX, except that R5RS does not provide any way of quoting
>the ... identifier so that it may be used in macro-generated macros.

If one could express set-values! in terms of set-values!-aux without
using ellipses, would it then work?  Assuming I remember the syntax
correctly:

(define-syntax set-values!
  (letrec-syntax ((set-values!-aux
                   (syntax-rules ()
                     ((_ () (?var ...) (?tmp ...))
                      (lambda (?tmp ...) (set! ?var ?tmp) ...))
                     ((_ (?var0 ?var1 ...) (?var ...) (?tmp ...))
                      (set-values!-aux (?var1 ...)
                                       (?var ... ?var0)
                                       (?tmp ... x))))))
    (syntax-rules ()
      ((_ ?vars ?expr0 . ?exprs)
       (call-with-values (lambda () ?expr0 . ?exprs)
                         (set-values!-aux ?vars () ()))))))

Quote:
>Alternatively, one may use the trick outlined in the R5RS examples:

>(define-syntax set-values!
>  (syntax-rules ()
>    ((_ "tmps" () (?var ...) (?tmp ...) ?producer)
>     (call-with-values ?producer
>                   (lambda (?tmp ...) (set! ?var ?tmp) ...)))
>    ((_ "tmps" (?var0 ?var1 ...) (?var ...) (?tmp ...) ?producer)
>     (set-values! "tmps" (?var1 ...) (?var ... ?var0) (?tmp ... x) ?producer))
>    ((_ (?var ...) ?expr0 . ?exprs)
>     (set-values! "tmps" (?var ...) () () (lambda () ?expr0 . ?exprs)))))

Is there some good reason for doing this as opposed to using a
syntactic keyword to mark the helper form?

(define-syntax set-values!
  (syntax-rules (tmps-helper)
    ((_ tmps-helper () (?var ...) (?tmp ...) ?producer)
     (call-with-values ?producer
                       (lambda (?tmp ...) (set! ?var ?tmp) ...)))
    ((_ tmps-helper (?var0 ?var1 ...) (?var ...) (?tmp ...) ?producer)
     (set-values! "tmps" (?var1 ...) (?var ... ?var0) (?tmp ... x) ?producer))
    ((_ (?var ...) ?expr0 . ?exprs)
     (set-values! "tmps" (?var ...) () () (lambda () ?expr0 . ?exprs)))))

Something very like these methods was suggested to me by Henry Cejtin,
and my brain has subsequently started working much more efficiently.
I've nearly completed my suite, and anticipate no significant
troubles.  Thanks, all.

-Jesse Welton



Tue, 28 Nov 2000 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. (values (multiple-value-form)) whats the point?

2. Bindings visible in Gambit define-macro forms

3. multiple-value version of define-modify-macro ?

4. typing in bind of (value x y z) form

5. Final SRFI 8: RECEIVE: Binding to multiple values

6. SRFI 8: RECEIVE: Binding to multiple values

7. MULTIPLE-VALUE-BIND question

8. multiple-value binding let and let*

9. binding multiple values (Ex: Re: some small proposed changes to standard)

10. lambda list in MULTIPLE-VALUE-BIND?

11. with-slots and multiple-value-bind

12. Common Lisp summary and multiple value binding

 

 
Powered by phpBB® Forum Software