@akiva: @jaen @gfredericks Thanks for the suggestions, as I just have a very simple usecase now I go with data.json and provide a value function.
Hm, does prismatic have a concept of generics? What I want is to declare that, whatever comes into that function, has to be returned too. Is that possible?
Not sure what that means exactly, any example use case?
@jaen: If I pass in a date, then I want to return a date, if I pass in a String, I want to return a string, if I pass in T I want to return T.
By "prismatic" you mean schema, yes? So doesn't (schema.core/validate s/Int 12)
already do it?
Or am I misunderstanding something?
@jaen: Yes, I mean prismatic schema. These are two functions, both receive a parameter of whatever type
and may return the same type
This could be an invariant of a function, whatever type comes in, has to be returned
Does that make more sense?
How about
(s/set-fn-validation!)
(s/defn function :- ArgSchema [arg :- ArgSchema] ...)
this will verify your function takes and return the same shape of data (or throw otherwise). Is that something you mean?No, I dont talk about the shape directly, although, in a prismatic sense it might be the same. I am not sure how else to express this. Maybe you could have a look at: https://docs.oracle.com/javase/tutorial/java/generics/types.html "A Generic Version of the Box Class" if you want. The closest thing I can imagine is:
But this would also accepting that param is a Str, but returns an Inst
Which is not what I want
Ahh, so you mean like A -> A
.
For some reason I didn't catch on you wanted parametrically polymorphic function with same parameter and return type, sorry. Was to caught in the schema part of the question.
I'm not sure if schema supports any way of relating the parameter schemas to the return schema. Sounds like a core.typed
thing.
I imagine you could cheat with a conditional schema, like so:
(defmulti make-return-schema-for-fun (fn [& args] (mapv class args)))
(defmethod make-return-schema-for-fun [String] [_] s/Str)
(defmethod make-return-schema-for-fun [Integer] [_] s/Int)
(defmethod make-return-schema-for-fun [Long] [_] s/Int)
(defn fun [arg1]
(let [return-value (* 2 (Integer. arg1))] ; calculate function return here
(s/validate (make-return-schema-for-fun arg1) return-value)
return-value))
but that doesn't look too nice to me TBH...This code above will work with (fun 2)
but fail for (fun "2")
with a schema error, because input type doesn't match output type.
But again, that feels... weird, to say the least.
Interesting solution, but its more handcrafted and I agree, the logic itself is hidden inside 10 lines boilerplate code
Well, it's nice to finally see the limits of prismatic schema
Well, I guess it might have looked a bit nicer using actual conditional schema or that newfangled abstract schema map, but would still feel like a hack to me nonetheless.
(def FunSchema
(s/conditional
(comp string? :arg1)
{:arg1 s/Str :return s/Str}
(comp integer? :arg1)
{:arg1 s/Int :return s/Int}))
(defn fun [arg1]
(let [return-value (* 2 (Integer. arg1))] ; calculate function return here
(s/validate FunSchema {:arg1 arg1 :return return-value})
return-value))
You could macro it up to avoid writing out the boilerplate each time
But I would still feel somewhat iffy using this.
@jaen: Thanks, I'll take a not of it if I need it once really hard I might use it. But for my current usecase this is to much overload