Structs’ success typing is the same as common garden maps to Dialyzer, right?
What are the preferred ways to enforce a particular struct?
Structs’ success typing is the same as common garden maps to Dialyzer, right?
What are the preferred ways to enforce a particular struct?
In Elixir you can pattern match on the struct’s type so for example:
defmodule StructTest do
defstruct name: "Foo!"
end
defmodule TestStruct do
def takesStruct(struct = %StructTest{}) do
IO.puts(inspect struct)
end
end
The takesStruct function will only match for instances of the %StructTest{} structure.
You can see more information at the Typespecs page in the Documentation.
To match a Struct inside a typespec, use the normal %StructName{}
syntax.
EDIT: The documentation moved to a new location.
As far as I can see Dialyzer likens structs to any general map %{}, which means you lose the specificity…
Erlang 19 introduces more advanced support from dialyzer for maps -
checking specific keys and general key types. Support for those new
features is in Elixir 1.3 as well. Here’s the PR that introduced them:
oh really? this is very nice. when’s the eta? (if there is one)
1.3 rc0 was just released today.
Erlang 19-rc was released couple days ago. I’d expect final release
probably in the matter of next couple weeks.
Hello!
I am totally new to Elixir and I just found your response because I am trying to figure out this pattern matching for types
is def takesStruct(struct = %StructTest{}) do
equivalent to def takesStruct(%StructTest{} = struct) do
?
As I understand, def takesStruct(%StructTest{} = struct) do
is checking that struct is of type StructTest, am I right? or is it explicitly requiring an empty struct? (I dont think it is even possible…)
Thank you in advance
It’s just matching on a %StructTest, empty or not, you can’t have a struct that is empty, since a struct is just a map with pre-defined fields. You can match on an empty map though, with a guard clause, def empty(%{} = variable) when variable == %{} do
, or on empty struct fields directly def empty(%StructTest{some_field: nil}) do
, of course if you set a default on the field it won’t work
def takesStruct(%StructTest{} = struct) do
, means:
%StructTest{}
struct, otherwise it will not be invokedstruct
variable, which you can use later in the function body.Thank you both, now it is clear