schema-tools icon indicating copy to clipboard operation
schema-tools copied to clipboard

Support recursive in get-in

Open obeah opened this issue 9 years ago • 8 comments

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))))

obeah avatar Mar 27 '16 09:03 obeah

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 avatar Mar 27 '16 09:03 Deraen

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

Deraen avatar Mar 27 '16 09:03 Deraen

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

ikitommi avatar Mar 27 '16 09:03 ikitommi

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

Deraen avatar Mar 27 '16 09:03 Deraen

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...

ikitommi avatar Mar 27 '16 10:03 ikitommi

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.

obeah avatar Mar 27 '16 10:03 obeah

@obeah It is also somewhat unpredictable with recursive:

(get-in {:a {:b (s/recursive Foo)}} [:a :b])
;; Foo
;; or (s/recursive Foo) ?

Deraen avatar Mar 27 '16 10:03 Deraen

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.

obeah avatar Mar 27 '16 11:03 obeah