When both optionals and keywords are used, the first keyword marks the end
of the optionals. svn: r2322
This commit is contained in:
parent
d9e3e1e267
commit
70d2fa327d
|
@ -384,10 +384,30 @@
|
||||||
[body (make-keys-body expr)])
|
[body (make-keys-body expr)])
|
||||||
(syntax/loc stx (lambda vars body)))]
|
(syntax/loc stx (lambda vars body)))]
|
||||||
;; both opts and keys => combine the above two
|
;; both opts and keys => combine the above two
|
||||||
|
;; (the problem with this is that things that follow the required
|
||||||
|
;; arguments are always taken as optionals, even if they're keywords, so
|
||||||
|
;; the following piece of code is used.)
|
||||||
|
#;
|
||||||
[else
|
[else
|
||||||
(let ([clauses (make-opt-clauses (make-keys-body expr) rest*)])
|
(let ([clauses (make-opt-clauses (make-keys-body expr) rest*)])
|
||||||
(with-syntax ([name name] [clauses clauses])
|
(with-syntax ([name name] [clauses clauses])
|
||||||
(syntax/loc stx (letrec ([name (case-lambda . clauses)]) name))))]))
|
(syntax/loc stx (letrec ([name (case-lambda . clauses)]) name))))]
|
||||||
|
;; both opts and keys => pop optionals as long as they're not keywords
|
||||||
|
[else
|
||||||
|
(with-syntax
|
||||||
|
([rest rest*]
|
||||||
|
[vars (append! vars rest*)]
|
||||||
|
[body (make-keys-body expr)]
|
||||||
|
[((optvar optexpr) ...)
|
||||||
|
(apply append
|
||||||
|
(map (lambda (opt)
|
||||||
|
(with-syntax ([(ovar odef) opt] [rest rest*])
|
||||||
|
(list #'[otmp (if (null? rest)
|
||||||
|
#t (keyword? (car rest)))]
|
||||||
|
#'[ovar (if otmp odef (car rest))]
|
||||||
|
#'[rest (if otmp rest (cdr rest))])))
|
||||||
|
opts))])
|
||||||
|
(syntax/loc stx (lambda vars (let* ([optvar optexpr] ...) body))))]))
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ formals expr0 expr ...)
|
[(_ formals expr0 expr ...)
|
||||||
(generate-body #'formals #'(let () expr0 expr ...))]))
|
(generate-body #'formals #'(let () expr0 expr ...))]))
|
||||||
|
|
|
@ -227,14 +227,34 @@
|
||||||
|
|
||||||
;; optionals and keys
|
;; optionals and keys
|
||||||
(let ([f (lambda/kw (#:optional a b #:key c d) (list a b c d))])
|
(let ([f (lambda/kw (#:optional a b #:key c d) (list a b c d))])
|
||||||
|
;; the parts that are commented out are relying on the old (CL-like)
|
||||||
|
;; behavior of always treating the first arguments as optionals. Now a
|
||||||
|
;; keyword marks the end of the optionals.
|
||||||
(t '(#f #f #f #f) <= (f)
|
(t '(#f #f #f #f) <= (f)
|
||||||
'(1 #f #f #f) <= (f 1)
|
'(1 #f #f #f) <= (f 1)
|
||||||
'(1 2 #f #f) <= (f 1 2)
|
'(1 2 #f #f) <= (f 1 2)
|
||||||
'(#:c #:d #f #f) <= (f #:c #:d)
|
;; '(#:c #:d #f #f) <= (f #:c #:d)
|
||||||
'(#:c 1 #f #f) <= (f #:c 1)
|
;; '(#:c 1 #f #f) <= (f #:c 1)
|
||||||
'(1 2 #:d #f) <= (f 1 2 #:c #:d)
|
'(1 2 #:d #f) <= (f 1 2 #:c #:d)
|
||||||
'(#:c #:d #:d #f) <= (f #:c #:d #:c #:d)
|
;; '(#:c #:d #:d #f) <= (f #:c #:d #:c #:d)
|
||||||
'(#:c 1 #:d #f) <= (f #:c 1 #:c #:d)))
|
;; '(#:c 1 #:d #f) <= (f #:c 1 #:c #:d)
|
||||||
|
;; Test new behavior on the commented expressions that are valid
|
||||||
|
'(#f #f #:d #f) <= (f #:c #:d)
|
||||||
|
'(#f #f 1 #f) <= (f #:c 1)
|
||||||
|
;; Now test the new behavior
|
||||||
|
'(#f #f #f 2) <= (f #:d 2)
|
||||||
|
'(1 #f #f 2) <= (f 1 #:d 2)
|
||||||
|
'(1 2 #f 2) <= (f 1 2 #:d 2)
|
||||||
|
'(1 #f #f 2) <= (f 1 #f #:d 2)))
|
||||||
|
(let ([f (lambda/kw (x #:optional a b #:key c d) (list x a b c d))])
|
||||||
|
;; also test that the required argument is still working fine
|
||||||
|
(t '(0 #f #f #f 2) <= (f 0 #:d 2)
|
||||||
|
'(0 1 #f #f 2) <= (f 0 1 #:d 2)
|
||||||
|
'(0 1 2 #f 2) <= (f 0 1 2 #:d 2)
|
||||||
|
'(0 1 #f #f 2) <= (f 0 1 #f #:d 2)
|
||||||
|
'(#:x 1 #f #f 2) <= (f #:x 1 #f #:d 2)
|
||||||
|
;; and test errors
|
||||||
|
:rt-err: <= (f 0 #:c 2 #:c 3)))
|
||||||
|
|
||||||
;; multi-level arg lists with #:body specs
|
;; multi-level arg lists with #:body specs
|
||||||
(let ([f (lambda/kw (#:key x y #:body (z)) (list x y z))])
|
(let ([f (lambda/kw (#:key x y #:body (z)) (list x y z))])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user