I'm curious if there's been any discussion about adding assertions for regular destructured symbols (e.g. {f :foo, b :bar}). I realize it's a bit of a tougher ask given there's no existing left-hand keyword to add a ! to, but it's my primary way of destructuring, so I personally would get a lot of wear out of it.
One idea might be to add a new special keyword that would assert everything in the binding (e.g. {:assert {f :foo, b :bar}})?
They're not bindings, they're keys that aren't bound and while its tempting to make them look the same, ultimately making them look like bindings is misleading. We went back and forth on this before the release and we’re going back the other way.,
Why still have the ampersand?
As the separator between bindings (symbols or keywords) and non-bound keys (anything)
How will this play with :syms! and :strs!? Will they also require there to be keywords after & ?
Based on how I understand this so far (which may be wrong!), I was expecting to be able to write expressions like
(let [{:syms! [a & b]} {'a 1, 'b 2}]
a)
(let [{:strs! [a & "b"]} {"a" 1, "b" 2}]
a)
but these both throw on latest master. It seems the issue lies in destmap* https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4554-L4558 , which always rejects non-keywords, like b and "b". So my question is, should destmap* be able to distinguish based on the directive, to look something like this (directionally)?
(when (not preamp?)
(cond
(and (.startsWith (name dir) "keys") (not (keyword? bb)))
(throw
(new IllegalArgumentException
(str "'" bb
"' - binding symbols can only appear before '&', use keys after")))
(and (.startsWith (name dir) "syms") (not (symbol? bb)))
(throw
(new IllegalArgumentException ""))
(and (.startsWith (name dir) "strs") (not (string? bb)))
(throw
(new IllegalArgumentException "")))) I don't know The Answer, but Alex did say :keys! [& :foo :bar] is next alpha (not current).
it is still a wip, need spec updates also
prob best to just wait for the announcement where we can explain more fully all the changes
but I expect your original examples to be almost where it ends up except that {:syms! [a & b]} will require quoted symbol (normal data as key) vs unquoted for binding. {:syms! [a & 'b]}
Nice, i had been wondering about :select supporting nesting, looks like it will with that latest update. For example
(let [{:person/keys! [id & address]
:select sel
{:address/keys [street]} :person/address}
{:person/id 1
:person/first "John"
:person/last "Smith"
:person/address {:address/street "1 Main St"
:address/city "Anytown"
:address/zip "12345"}}]
sel)
this currently returns the full :person/address but looks like the next version will only select the :address/street from the inner address map. (though, with the earlier mentioned use of keywords after the &)
I'm really excited to see how these updates end up tying into spec, I'm struggling to imagine what that will look like.You can use :keys! [& :foo :bar] f :foo b :bar] to accomplish this with some admitted duplication.
(Note syntax here is as of next alpha, in flux from current)
The keys after & are not bound but required
gotcha so just leverage nonbinding
that works, thanks!
in current alpha3: :keys! [& foo bar] f :foo b :bar]
so foo becomaes :foo for non-bound? why?