(let [{:keys! [card]
:missing m} {}]
[card m])
;; => [nil {:card nil}]
(let [{:req! {{:as c} :card}
:missing m} {}]
[c m])
;; => [#object[java.lang.Object 0x...] nil]
The input has no :card, but :card is required. Expected [nil {:card nil}], as for :keys!.
Instead:
1. m is nil, so the missing key is not reported.
2. c is bound to an internal "not found" object that should not leave Clojure's code.
3. :select returns data that was never in the input:
(def select-card
(selector {:req! {{:keys [a]} :card}
:missing m
:select s}))
(select-card {})
;; => {:select {:card {}}}
With a more usual nested form, the object is hidden and the bug is silent:
(let [{:req! {{:keys [number]} :card}
:missing m} {}]
[number m])
;; => [nil nil]
number is nil and looks normal, but :card is still not reported as missing.
It looks like for a simple name the not-found marker is checked, recorded as missing, and replaced with nil.
For a nested form that check is skipped, and the marker is passed into the nested form.
Without :missing, it throws Missing required key: :card, as expected.
Reproduced on Clojure 1.13.0-alpha10.