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)])
|
||||
(syntax/loc stx (lambda vars body)))]
|
||||
;; 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
|
||||
(let ([clauses (make-opt-clauses (make-keys-body expr) rest*)])
|
||||
(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 ()
|
||||
[(_ formals expr0 expr ...)
|
||||
(generate-body #'formals #'(let () expr0 expr ...))]))
|
||||
|
|
|
@ -227,14 +227,34 @@
|
|||
|
||||
;; optionals and keys
|
||||
(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)
|
||||
'(1 #f #f #f) <= (f 1)
|
||||
'(1 2 #f #f) <= (f 1 2)
|
||||
'(#:c #:d #f #f) <= (f #:c #:d)
|
||||
'(#:c 1 #f #f) <= (f #:c 1)
|
||||
;; '(#:c #:d #f #f) <= (f #:c #:d)
|
||||
;; '(#:c 1 #f #f) <= (f #:c 1)
|
||||
'(1 2 #:d #f) <= (f 1 2 #:c #:d)
|
||||
'(#:c #:d #:d #f) <= (f #:c #:d #:c #:d)
|
||||
'(#:c 1 #:d #f) <= (f #:c 1 #:c #:d)))
|
||||
;; '(#:c #:d #:d #f) <= (f #:c #:d #: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
|
||||
(let ([f (lambda/kw (#:key x y #:body (z)) (list x y z))])
|
||||
|
|
Loading…
Reference in New Issue
Block a user