You can pattern match specific structs in your methods to prevent some leakage of type bugs. E.g. def f(z_struct = %Z{}) do ...
.
Can you do something similar if you don't know the type of struct, say, if you want a struct of a module that implements protocol P
.?
defprotocol P do
# ...
end
defmodule A do
defstruct :a
end
defimpl P, for: A do
# ...
end
defmodule B do
defstruct :b
end
defimpl P, for: B do
# ...
end
defmodule SomeMod do
def m(p) do
# ...
end
end
I.e. method SomeMod.m/1
should accept only an %A{} or a %B{} as parameter. If module C
implements P
later, m/1
should accept C
without code changes.
Can we do this elixir?
If the above doesnt explain well, think of it like accepting an interface in Java, where P
is the interface and A
and B
are the classes that implement P
.
That is impossible with guards / pattern matching in function clauses. The only way to assert this would be to use a reflection Kernel.impl_for/1
:
defmodule SomeMod do
def m(p) do
unless P.impl_for(p), do: raise MatchError, term: p
# ...
end
end