Is it possible to write a function definition such that it only takes an argument that implements a given protocol? The best I’ve found is the assert_impl!\2 function, but that can’t be used in a guard. I’ve also considered the fact that protocols define a type, but I’m at a loss as to how to match against those, either.
I’m not really sure what you are trying to do. If you want to create a guard
for protocol
function you can write is like that:
defprotocol Size do
@doc "Calculates the size (and not the length!) of a data structure"
def size(data)
@definitions Module.definitions_in(__MODULE__)
defguard defines?(name, arity) when {name, arity} in @definitions
end
require Size
Size.defines?(:size, 0) # false
Size.defines?(:size, 1) # true
If you want to check if module
implements Protocol
you would need to create a new file as code for it can’t be placed in same file as Protocol
. With such example code:
defprotocol Size do
@doc "Calculates the size (and not the length!) of a data structure"
def size(data)
end
defimpl Size, for: Tuple do
def size(tuple), do: tuple_size(tuple)
end
we can write a guard like:
defmodule Example do
path = :code.lib_dir(:example, :ebin)
@modules Protocol.extract_impls(Size, [path])
defguard implements_size?(module) when module in @modules
end
Example.implements_size?(Map) # false
Example.implements_size?(Tuple) # true
Note: In :code.lib_dir/2
as a first argument you need to give an application name which implements specific Protocol
.
3 Likes