destructuring-bind uses second value of initform as supplied-p value
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
When using destructuring-bind with a &key parameter that has a supplied-p variable, if the keyword is not supplied and the initform returns multiple values, the second value will be used as the value of the supplied-p variable instead of NIL:
[SBCL] CL-USER> (destructuring-bind
; => (1 2)
; should be (1 NIL)
[SBCL] CL-USER> (lisp-implement
"2.0.1"
[SBCL] CL-USER> *features*
(:QUICKLISP :SB-BSD-
:NON-BASE-
:IEEE-
:SB-THREAD :SB-UNICODE :SBCL :UNIX)
uname -a
Linux ouroboros 4.15.0-91-generic #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Changed in sbcl: | |
status: | New → Fix Committed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |
The source of the problem is pretty clear from the macroexpansion:
(destructuring-bind (&key (a (values :foo 'what) a?)) args
(SB- C::CHECK- DS-LIST/ &KEY ARGS 0 0 '(&KEY (A)) #(:A)))
(#: G487 (SB-C::DS-GETF #:G486 ':A))
((A A?)
(IF (EQL #:G487 0)
(VALUES :FOO 'WHAT)
(VALUES (CAR (TRULY-THE CONS #:G487)) T))))
(list args a a?))
=>
(SB-INT:BINDING* ((#:G486
(LIST ARGS A A?))
I think it can be fixed by wrapping another values call around the default value, i.e. in expand-ds-bind
(gen-test sense sup-p-form
(if sup-p-var `(values ,val-form t) val-form)
def)
should be
(gen-test sense sup-p-form
(if sup-p-var `(values ,val-form t) val-form)
`(values ,def nil))