Type hints, guard clauses, @enforce_keys in real production code?

Is there a book or online resource which assumes knowledge of the info in the guide, and shows how these come together in production code? I.e., when do working programmers use these specification features?

I’m learning Elixir, and I might not understand this, but it feels like there are three different DSLs (mini languages) for types. TBH, this is the only aspect of Elixir that I find a little less than optimum. That is, three separate systems to learn which are somewhat equivalent. So e.g., it seems we have:

  1. The type specs
  2. The set of allowed expressions in guards, and
  3. Other language-level features like validations and @enforce_keys.

So I’d like to learn the coding conventions. Do Elixir programmers make use of all of these whenever possible? E.g., for every function parameter, its type is specified both as a type spec and (if possible) as a guard expression? Makes me wonder if guard expressions could be automatically generated from type specs.

1 Like

They do three very different things, though they can be used together for great effect.

Type specs are a mix of documentation and static code analysis tagging. They don’t, however provide any runtime features.

Header guards (and the other pattern matching goodies) allow you to break code out into discreet stanzas which are selected at runtime based on data passed to the function. So this is a runtime flow control structure.

Things like enforce_keys gives us tools to enforce contracts on data at time of creation .

So… doc/static analysis, runtime control flow, data contract enforcement …

I agree that all the tools can be a bit overwhelming at first while you sort them out into categories of what-does-what-where, but they do fall together nicely in practice and in use are quite smooth.

Elixir, as well as Erlang, have a larger toolbox for these things compared to some other fp languages (which give more or less a single The Way to approach data types), and AIUI this came about due to the dynamic typing that resulted from the requirements of a distributed language … languages that don’t have to handle that as a first class language feature are able to provide stronger or more unified approaches to types. My 0.02 in any case :slight_smile: