Fork me on GitHub
#malli
<
2020-06-23
>
ikitommi05:06:00

mutual recursion, current status:

(mg/generate
  ::ping
  {:registry (mr/composite-registry
               (m/default-schemas)
               {::ping [:maybe [:tuple [:= "ping"] [:ref ::pong]]]
                ::pong [:maybe [:tuple [:= "pong"] [:ref ::ping]]]})
   :size 7, :seed 86})
; => ["ping" ["pong" ["ping" ["pong" ["ping" nil]]]]]
tested also a fail-fast on ambiguity with refs, so instead of:
(mg/generate
  ::ping
  {:registry (mr/composite-registry
               (m/default-schemas)
               {::ping [:maybe {:id ::pong} [:tuple [:= "ping"] [:ref ::pong]]]
                ::pong [:maybe [:tuple [:= "pong"] [:ref ::ping]]]})
   :size 7, :seed 86})
; => ["ping" ["ping" ["ping" ["ping" ["ping" nil]]]]]
the default code will throw instead:
Execution error (ExceptionInfo) at malli.core/fail! (core.cljc:80).
:malli.core/ambiguous-ref {:type :ref, :ref :user/pong}

Vincent Cantin06:06:10

@ikitommi [suggestion] if you can embed registries locally, then maybe you don't need to have support for a custom global registry - just ask the users to include their registry as a part of their models.

ikitommi06:06:49

The custom Schema elements can’t be embedded as data, if they are code. It’s good have a mechanism to add those to the schema registry. All user/project-defined that are just data COULD be used via embedded registries, a decision done in user space.

ikitommi07:06:25

I woudn’t register any project-spesific (data) schemas into global registry, as they can be references mosty as Vars.

ikitommi07:06:15

The recursive schemas could also be allowed to be introduces using Vars, but not sure if that’s a good idea.

ikitommi07:06:29

Something like:

(declare Pong)

(def Ping [:maybe [:tuple [:= "ping"] [:ref #'Pong]]])

(def Pong [:maybe [:tuple [:= "pong"] [:ref #'Ping]]])

ikitommi07:06:44

Imaginary example with not much boilerplate with schematized fns using custom schema element :db/ref registered into the global registry:

(m/defn my-fn [x :- int?, y :- [:maybe [:db/ref uuid?]]
  (println x y))

ikitommi07:06:33

About the Var refs - how would that be serialized? It could be done by having an asymmetric m/form for that component, which might be a bad idea:

(m/form [:maybe [:tuple [:= "ping"] [:ref #'Pong]])
;[:registry
; {:registry {::ping [:maybe {:id ::pong} [:tuple [:= "ping"] [:ref ::pong]]]
;             ::pong [:maybe [:tuple [:= "pong"] [:ref ::ping]]]}}
; [:ref ::ping]]

ikitommi07:06:47

this works now too:

(mg/generate
  [:registry
   {:registry {::ping [:maybe [:tuple [:= "ping"] [:ref ::pong]]]
               ::pong [:maybe [:tuple [:= "pong"] [:ref ::ping]]]}}
   [:ref ::ping]]
  {:size 7, :seed 86})
; => ["ping" ["pong" ["ping" ["pong" ["ping" nil]]]]]