Closed vitalyper closed 8 years ago
Can you please clarify what you mean by "lexical closure" in this context? There is not currently a s/let
macro, if that's what you mean. It's something we've thought about, but I don't think it's possible to support with the same performance that the existing schema macros provide. I'm happy to elaborate more if you have questions, but if you can describe your use case in more detail and what you're hoping to get from Schema it would be very useful in providing a helpful response. Thanks!
Thanks for quick reply.
There is not currently a s/let macro, if that's what you mean.
Answers the question.
foo returns a function (lexical closure over empty args in this case) which could be called like
(foo-fn :t 11)
where in let I want to destruct and assert that s/Int was passed in.
It's something we've thought about, but I don't think it's possible to support with the same performance that the existing schema macros provide.
It is sad, as it limits Schema to function args use case only. FWIK, in Scheme at least, let is sugar on top of anonymous functions (lambda in Scheme). So I would hope that s/let could piggyback on s/defn.
No problem, thanks for the details.
I guess my question is, why do you want to schematize the args? Do you want to check the schemas at test time? Or just for documentation purposes?
The issue is that creating the schema checker is somewhat expensive, and unlike s/defn or s/fn (which are typically created once and called many times), there is nowhere to 'hoist' this creation so that it can be done once and then used repeatedly. (Instead, the checker would have to be created each time). That could be acceptable for some use cases, but it's something we would have to think about more.
Of course, you can still do schema checking inside a function by manually using s/validate
or s/validator
(which can be used to manually hoist the creation outside).
My use case is to use Schema coercion and validation when receiving raw data from json or rest. As below shows there is a workaround - use map destructuring in let.
user> (s/def UserInfo
{:name s/Str
:id Long})
#'user/UserInfo
user> (defn new-user-mgr []
;; Keep state
;; (let [users (ref {})])
(fn [op & args]
(condp = op
:list (comment (@users))
;; Want to destruct UserInfo as a whole
;; :add (let [[user-info :- UserInfo] (nth args 0)]
;; As a workaround we could destruct as map
:add (let [{name :name id :id} (nth args 0)]
;; add user to users
(println "name" name "id" id)))))
#'user/new-user-mgr
user> ((new-user-mgr) :add {:name "john" :id 11})
name john id 11
nil
user>
So, after some more thinking schema destructuring in let doesn't buy me that much - UserInfo is just Schema verified and coerced clojure map.
Please feel free to close this.
OK, thanks. You might also look into letk
in our plumbing
lib -- it does safe map destructuring.,
Is there a way to make this work or "let destructuring" is not supported?
java.lang.Exception: Unsupported binding form: :-