In case they help others, here are a couple of "helper" functions that I've found useful.
maybe()
I often want specs or schemas that also accept a nil value. Rather than littering my specs with spec(is_nil() or (...)), I have a maybe() helper function:
def maybe(spec), do: one_of([spec(is_nil()), spec])
Example:
def order(), do: spec(is_integer() and (&(&1 >= 0)))
@contract get_order() :: maybe(order())
def get_order(), do: Enum.random([nil, 0, 1, 2, 3])
Perhaps it's something that could be included in the library as a bit of syntactic sugar.
regex()
When using Regex.match? in specs, it's important to also check for is_binary(). Otherwise, when you send, say, a nil value you'll get a no function clause matching in Regex.match?/2 error with a stacktrace that only points to Norm's own code. (It will still crash when wrapped in my maybe() helper function.)
So that I don't forget any is_binary() clauses, I use my own regex() helper function(s).
def flip(p2, p1, func), do: apply(func, [p1, p2])
def regex(regex), do: spec(is_binary() and flip(regex, &Regex.match?/2))
Example:
def date(), do: regex(~r/^20\d\d-\d\d-\d\d$/)
Perhaps match() or match?() would be better naming than regex().
In case they help others, here are a couple of "helper" functions that I've found useful.
maybe()I often want specs or schemas that also accept a
nilvalue. Rather than littering my specs withspec(is_nil() or (...)), I have amaybe()helper function:Example:
Perhaps it's something that could be included in the library as a bit of syntactic sugar.
regex()When using
Regex.match?in specs, it's important to also check foris_binary(). Otherwise, when you send, say, anilvalue you'll get ano function clause matching in Regex.match?/2error with a stacktrace that only points to Norm's own code. (It will still crash when wrapped in mymaybe()helper function.)So that I don't forget any
is_binary()clauses, I use my ownregex()helper function(s).Example:
Perhaps
match()ormatch?()would be better naming thanregex().