[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Prevent keyword argumets from appearing in the rest
From: |
Panicz Maciej Godek |
Subject: |
Re: Prevent keyword argumets from appearing in the rest |
Date: |
Wed, 21 Sep 2016 19:05:46 +0200 |
For the record, I eventually came up with the following code:
(define-module (extra define-keywords)
#:use-module (ice-9 nice-9)
#:use-module (extra attributes)
#:replace ((define/keywords . define*)))
(define-syntax define/keywords
(lambda (x)
(define* (required args #:optional (gathered '()))
(match args
(((? symbol?) #:= . _)
(values (reverse gathered) args))
(((? symbol? s) . rest)
(required rest `(,s . ,gathered)))
(_
(values (reverse gathered) args))))
(define* (optional args #:optional (gathered '()))
(match args
(((? symbol? s) #:= value . rest)
(optional rest `((,s ,value) . ,gathered)))
(_
(values (reverse gathered) args))))
(define* (keyword args #:optional (gathered '()))
(match args
(((? keyword? k) (? symbol? s) #:= value . rest)
(keyword rest `((,s ,value ,k) . ,gathered)))
(((? keyword? k) (? symbol? s) . rest)
(keyword rest `((,s #f ,k) . ,gathered)))
(_
(values (reverse gathered) args))))
(define (required+optional+keyword+rest+keys args)
(let* ((required args* (required (syntax->datum args)))
(optional args** (optional args*))
(keyword rest (keyword args**))
(((names values keys) ...) keyword))
(datum->syntax x `(,required ,optional ,keyword ,rest ,keys))))
(syntax-case x ()
((_ (proc . args) body ...)
(with-syntax ((((required ...) (optional ...) (keyword ...) rest
keys)
(required+optional+keyword+rest+keys #'args)))
#'(define proc
(lambda* (required ... #:optional optional ...
#:key keyword ...
#:allow-other-keys . rest)
(let ((rest (remove-attributes 'keys rest)))
body ...))))))))
In addition to removing the supported keywords from the "rest" list, it
provides an alternative (incompatible) syntax for optional and keyword
arguments:
(define* (f r1 r2 r3 opt1 #:= 1 opt2 #:= 2 #:key1 k1 #:key2 k2 #:= 7)
...)
where r1, r2 and r3 are required, opt1 and opt2 optional (with default
values of 1 and 2, respectively), and variables k1 and k2 are accessible
via #:key1 and #:key2 keywords, where in addition k2 has a default value 7.
I'm not sure whether the use of #:= keyword is a good idea -- probably not.
But I'm not a big fan of the current syntax either.
The definition requires the (ice-9 nice-9) library, which -- traditionally
-- can be found here:
https://github.com/panicz/pamphlet/blob/master/libraries/ice-9/nice-9.scm
In addition, it requires a definition of "remove-attributes":
(define (remove-attributes attributes #;from attribute-list)
(match attribute-list
(((? keyword? key) value . rest)
(if (member key attributes)
(remove-attributes attributes rest)
`(,key ,value . ,(remove-attributes attributes #;from rest))))
(_
attribute-list)))