Scheme macro source: define/keyed, for defining keyword-triggered arguments 
Author Message
 Scheme macro source: define/keyed, for defining keyword-triggered arguments

Rationale...

    There was a discussion going on recently about keyed arguments, named
    arguments, whatever.  You know, supplying a dozen arguments sucks when most
    are usually the same and only a couple are really volatile.  This is one
    solution.  A syntactic form define/keyed is used to define these
    interesting functions.  It creates syntactic forms with let-reminescent
    syntax.  For completeness, forms so defined can return the unembellished
    procedure by expanding the form bare, eg, (foo).

Example definition...

    (define/keyed (write* ((radix 10)
                           (port (current-output-port))
                           (length 10)
                           (depth 10))
                          value1 value2 . more)
      (blahbity blah)
      (blah))

Examples of use...

    (write* () #f #f)

    (write* ((port pearl-harbor)) 'you 'sunk 'my 'battleship)

    (apply (write*) my-radix my-port (list my-length my-depth my-value1 my-value2))

Example expansion...

    (begin (define (,some-gensym radix port length depth value1 value2 . more)
             (blahbity blah)
             (blah))
           (define-macro (write* . arguments)
             (if (null? arguments)
               ,some-gensym
               (let ((radix 10)
                     (port (current-output-port))
                     (length 10)
                     (depth 10))
                 (let ,(car arguments)
                   (,some-gensym radix port length depth . ,(cdr arguments)))))))

Credits...

    Similar versions independently developed by Oleg Kiselyov and myself.  My

    he got me to stop acting like a cranky child and use a gensym when I
    *really* wanted to simply expand to a procedure, waaahhhh.  Most macro
    facilities won't allow expansion to a procedure.  What's that all about?


_______________________________________________________________________________

;; Copyright (C) 1998 Andy Gaynor

;; Typical define-macro version.
;; Tested under Gambit.

(define-macro (define/keyed signature . body)
  (let* ((macro-name (car signature))
         ;; Got gensym?
         ;(procedure-name (gensym))
         (procedure-name (string->symbol (string-append "$$" (symbol->string macro-name))))
         (keyed-bindings (cadr signature))
         (positional-parameters (cddr signature))
         (keyed-parameters (map car keyed-bindings))
         (parameters (append keyed-parameters positional-parameters)))

            (define-macro (,macro-name . arguments)
              (if (null? arguments)
                ',procedure-name
                `(let ,',keyed-bindings
                   (let ,(car arguments)

;; Explicit-renaming version.
;; Hygienic except where intended.
;; Tested under Scheme48.

(define-syntax define/keyed
  (lambda (form rename compare)
    (let* ((signature (cadr form))
           (body (cddr form))
           (macro-name (car signature))
           ;; Got gensym?
           ;(procedure-name (gensym))
           (procedure-name (string->symbol (string-append "$$" (symbol->string macro-name))))
           (keyed-bindings (cadr signature))
           (positional-parameters (cddr signature))
           (keyed-parameters (map car keyed-bindings))
           (parameters (append keyed-parameters positional-parameters))
           ($begin (rename 'begin))
           ($define (rename 'define))
           ($define-syntax (rename 'define-syntax))
           ($lambda (rename 'lambda))
           ($let (rename 'let))
           ($if (rename 'if)))

                (,$define-syntax ,macro-name
                  (,$lambda (form rename compare)
                    (,$let ((arguments (cdr form)))
                      (,$if (null? arguments)
                        ',procedure-name
                        `(,',$let ,',keyed-bindings
                           (,',$let ,(car arguments)



Mon, 07 May 2001 03:00:00 GMT  
 Scheme macro source: define/keyed, for defining keyword-triggered arguments
Sorry, I forgot a couple things, as usual.

When calling a define/keyed form, the names bound in the keyed binding
section, the first form, are not restricted to the names defined for the
section in the define/keyed definition for the form.  It's just that the
defined ones are already bound to their default values by the time this
section is processed.

The main justification for using define/key is convenience, so I felt it
reasonable to allow this.  I'll somehow sleep nights with this little
impurity.  Besides, it was simpler.  :)

Here's a brief session.

Quote:
> (load "~silver/scheme/define-keyed.explicit-renaming.scm")

[foo adds 1, 2, and 3 to the sum of its arguments.
Quote:
> (define/keyed (foo ((a 1) (b 2) (c 3)) . more)

    (apply + a b c more))

[Note how d refers to a, b, and c.]

Quote:
> (foo ((d (+ a b c))) d)

12

[d is 6, plus a=0 + b=2 + c=3.

Quote:
> (foo ((d (+ a b c)) (a 0)) d)
11

I'd say that this behaviour is reasonable and intuitive.
In our individual first cuts, both Oleg and I allowed this construction.

As for indentation style, I'd say that define/keyed definitions should be
indented the way you indent a let.  To set indentation, Emacs users may find
the following Elisp fascinating
    (put 'write* 'scheme-indent-function 1)
Hmmm, now that I think about it, these indentation settings could be placed in
Scheme files themselves at the bottom.

    ;; This file sets x to 1 and creates a define/keyed form.

    (set! x 1)

    (define/keyed (write* ((radix 10)
                           (port (current-output-port))
                           (length 10)
                           (depth 10))
                          value1 value2 . more)
      (blahbity blah)
      (blah))

    ;; Local Variables:
    ;; eval: (put 'write* 'scheme-indent-function 1)
    ;; End:

Lots of other possibilities could be discussed, but the Emacs newsgroups are
probably more appropriate.  I only raised the issue at all because let forms
are usually indented differently.




Mon, 07 May 2001 03:00:00 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. Macros defining macros with define-syntax

2. define-macro -> define-syntax

3. define-macro vs define-syntax

4. MIT scheme doesn't support define-macro ?

5. define-macro in Dr.Scheme

6. Dr Scheme define-macro problem

7. Scheme-like macro defining for Common Lisp.

8. Question about a macro-defining macro

9. Macro-Defining Macros

10. help sought for macro defining macro

11. Load-time problem with a macro that defines a macro

12. Can TPB be defined outside defining modules?

 

 
Powered by phpBB® Forum Software