I cracked open an Elixir book last night, and with the benefit of a few chapters, I can see how Elixir's pattern matching can obviate some of the issues I have with purely dynamic, Rails style programming.
I also note that there appears to already be more static typing going on than I realised. In your add_comment/2 code, for instance, you focus on the {published: true} pattern matching. That is very neat, but what stands out more to me is that all clauses of that function require BlogPost, a struct type.
Am I right in thinking that every instance of BlogPost type must be constructed explicitly in your code? I.e. that every possible instance of BlogPost in the code base is knowable at compile time, along with its entire life cycle?
Or does Elixir partake of the horror that is duck typing, where any conforming untyped map of indeterminate provenance will pass the guard check for a BlogPost?
> Would you like another undefined method exception on that NilClass?
Don't take my word for it but IIRC structs are implemented as maps with a __struct__ key with the struct name, and that's used to implement checks and balances at different levels of compilation, linting and so on.
In practice I find that I hardly ever need to think about things like this. A few times I've done macro expansion to peek under the hood and figure something out but that's partially Lisp damage, I could probably just as well have read some documentation.
> Am I right in thinking that every instance of BlogPost type must be constructed explicitly in your code? I.e. that every possible instance of BlogPost in the code base is knowable at compile time, along with its entire life cycle?
Almost. You can create a struct dynamically at runtime like this:
struct(BlogPost, %{title: "The Title"})
# => %BlogPost{title: "The Title"}
… but you rarely need to. In fact I'm not sure I've ever used `struct/2` in real life. 99.9% of all the structs you ever create will have their types known at compile-time.
> any conforming untyped map of indeterminate provenance will pass the guard check for a BlogPost?
Nope. In the `add_comment/2` example, If I pass anything except a %BlogPost{} to that function, I'll get an error.
While I remain haunted by thoughts of someone e.g. deserialising a YAML file into a map, which then sneaks in some __struct__ key and squeaks past the guard clause, I also appreciate this seems fairly unlikely in practice. I think I'm just traumatised by Rails. It sounds like the culture around Elixir eschews excessive cutesiness, though. Promising!
I cracked open an Elixir book last night, and with the benefit of a few chapters, I can see how Elixir's pattern matching can obviate some of the issues I have with purely dynamic, Rails style programming.
I also note that there appears to already be more static typing going on than I realised. In your add_comment/2 code, for instance, you focus on the {published: true} pattern matching. That is very neat, but what stands out more to me is that all clauses of that function require BlogPost, a struct type.
Am I right in thinking that every instance of BlogPost type must be constructed explicitly in your code? I.e. that every possible instance of BlogPost in the code base is knowable at compile time, along with its entire life cycle?
Or does Elixir partake of the horror that is duck typing, where any conforming untyped map of indeterminate provenance will pass the guard check for a BlogPost?
> Would you like another undefined method exception on that NilClass?
*thousand yard stare*