metosin / schema-tools

Clojure(Script) tools for Plumatic Schema
http://metosin.github.io/schema-tools/
Eclipse Public License 2.0
107 stars 16 forks source link

Support recursive in get-in #30

Open obeah opened 8 years ago

obeah commented 8 years ago

Hi,

it seems recursive is not supported by get-in. Was it omitted on purpose? With small modifications it works for my use case:

(defn- unwrap-recursive [m]
  (cond
    (recursive? m) (deref (:derefable m)) ; probably use schema-value
    :else m))
(defn- get-in-schema [m k & [default]]
  (unwrap-recursive (unwrap-sequence-schemas (get m (key-in-schema m k) default))))
Deraen commented 8 years ago

Yes, it was reverted on purpose. Using schema-value proved too unpredictable and broke existing code: https://github.com/metosin/schema-tools/commit/240f8a5f973d4f6b6036aebcbf110c04909bd65d

Deraen commented 8 years ago

We are interested in finding a way to support this. Ideas welcome.

Some ideas here: https://github.com/metosin/schema-tools/issues/8#issuecomment-199649328

ikitommi commented 8 years ago

Could there be a separately special get-in-value, which would walk over schema Records?

Deraen commented 8 years ago

Perhaps. I think -value postfix doesn't clearly indicate that Schema values would be walked over all along the path. Maybe -values is better?

ikitommi commented 8 years ago

There is already get-schema-value which walks over one level and is documented "Returns the sub-schema or sub-schemas of given schema.". So, get-in-schema-value could be coherent name...

obeah commented 8 years ago

Thanks. I understand the problem with "conditional", "maybe" etc. (actually will be doing some special form of get-in for my particular use case of "conditional" - it will return a union of values for all possible branches). As for "recursive" I definitely missing smth - it seems to me it would be just enough to resolve it to actual underlying schema and continue but you obviously encountered some issues with that.

Deraen commented 8 years ago

@obeah It is also somewhat unpredictable with recursive:

(get-in {:a {:b (s/recursive Foo)}} [:a :b])
;; Foo
;; or (s/recursive Foo) ?
obeah commented 8 years ago

thanks, got it. It seems that for this particular case, current implementation returns recursive, not underlying schema: (get-in {:a {:b (s/recursive Foo)}} [:a :b])

But for the case when caller wants to go one or more levels deeper then it seems reasonable to resolve "recursive" to actual schema and continue. So (get-in {:a {:b (s/recursive Foo)}} [:a :b :key-in-foo]) would return schema for :key-in-foo.