@@ -37,6 +37,23 @@ user_schema
3737]
3838```
3939
40+ Norm can also be used to specify contracts for function definitions:
41+
42+ ``` elixir
43+ defmodule Colors do
44+ use Norm
45+
46+ def rgb (), do: spec (is_integer () and & (&1 in 0 .. 255 ))
47+
48+ def hex (), do: spec (is_binary () and & String .starts_with? (&1 , " #" ))
49+
50+ @contract rgb_to_hex (r :: rgb (), g :: rgb (), b :: rgb ()) :: hex ()
51+ def rgb_to_hex (r, g, b) do
52+ # ...
53+ end
54+ end
55+ ```
56+
4057## Installation
4158
4259Add ` norm ` to your list of dependencies in ` mix.exs ` . If you'd like to use
@@ -385,6 +402,32 @@ gen(age) |> StreamData.map(&Integer.to_string/1) |> Enum.take(5)
385402This allows you to compose generators however you need to while keeping your
386403generation co-located with the specification of the data.
387404
405+ ## Adding contracts to functions
406+
407+ You can ` conform ` data wherever it makes sense to do so in your application.
408+ But one of the most common ways to use Norm is to validate a functions arguments
409+ and return value. Because this is such a common pattern, Norm provides function
410+ annotations similar to ` @spec ` :
411+
412+ ``` elixir
413+ defmodule Colors do
414+ use Norm
415+
416+ def rgb (), do: spec (is_integer () and & (&1 in 0 .. 255 ))
417+
418+ def hex (), do: spec (is_binary () and & String .starts_with? (&1 , " #" ))
419+
420+ @contract rgb_to_hex (r :: rgb (), g :: rgb (), b :: rgb ()) :: hex ()
421+ def rgb_to_hex (r, g, b) do
422+ # ...
423+ end
424+ end
425+ ```
426+
427+ If the arguments for ` rgb_to_hex ` don't conform to the specification or if
428+ ` rgb_to_hex ` does not return a value that conforms to ` hex ` then an error will
429+ be raised.
430+
388431## Should I use this?
389432
390433Norm is still early in its life so there may be some rough edges. But
0 commit comments