On Sat, Jan 23, 2010 at 7:34 PM, Eduardo Cavazos <[email protected]>wrote:

> Hello,
>
> I've been messing about with a 'named-arguments' macro:
>
>    http://gist.github.com/284714


I am not convinced this is the right approach, since you are treading a bona
fide first class function for a macro.
What one would need is the ability to attach compile time attributes to a
function, in particular attributes containing the needed information about
the function signature. Then you could  write a single macro "call" such
that (call function-id (arg1 value1) ...) would expand to the right thing.
Of course this is not obvious since you should make it to work across
 modules and with separate compilation. Anyway, I have looked at your code
and notice that you do not check that the passed arguments are the expected
one. For instance (create-point (x 10) (y 20) (z 30)) would silently ignore
the "z" argument.
Since I had nothing better to do this Sunday morning I have translated you
code to use my sweet-macros library
(the one described in my Adventures):

(import (rnrs) (sweet-macros) (aps lang) (aps compat))

(def-syntax (named-arguments name ((parameter value) ...) name*)
  (with-syntax ((name-helper (identifier-append #'name "-helper")))
    #'(begin
        (def-syntax name-helper
          (syntax-match ()
             (sub (name-helper tbl)
                  (with-syntax (((val (... ...))
                                 (map (lambda (x)
                                        (datum->syntax #'name-helper
                                          (cdr (assq x (syntax->datum
#'tbl)))))
                                      (syntax->datum #'(parameter ...)))))
                    #'(name* val (... ...))))
             (sub (name-helper tbl (k v) rest (... ...))
                  (with-syntax ((new-tbl
                                 (datum->syntax #'name-helper
                                                (cons (cons (syntax->datum
#'k)
                                                            (syntax->datum
#'v))
                                                      (syntax->datum
#'tbl)))))
                    #'(name-helper new-tbl rest (... ...))))
             ))
        (def-syntax (name (k v) (... ...))
          (let ((expected-params (list 'parameter ...)))
            (for-each ;; check the passed parameters
             (lambda (param)
               (unless (memq param expected-params)
                 (error 'name "unexpected parameter" param)))
             (syntax->datum #'(k (... ...))))
          #'(name-helper ((parameter . value) ...) (k v) (... ...)))))))

;; example

(named-arguments create-point ((x 0) (y 0)) list)

(pretty-print
 (syntax-expand (named-arguments create-point ((x 0) (y 0)) list)))

(create-point)
(create-point (x 1))
;(create-point (x 1) (y 2) (z 3))
(display (syntax-expand (create-point (x 1) (y 2))))

Reply via email to