Enforce structure to implement function

Hello

Let’s say I have a library with a function, which accepts a structure name like: TestData. This function queries some data from the database and then returns with a TestData structure with the data inside by calling it’s TestData.new/1 function. Is there any way to enforce this function to accept only structures that have the new function implemented? My initial though was to use protocols, though it’s not working, because protocols work on structure objects, not on module names. Or if not, is there some idiomatic way to implement something like this?

Hello and welcome,

You might use behaviours to enforce what we call callbacks

2 Likes

In this case if I create a behaviour how could I enforce that the function parameter implements it? IIRC we can’t pattern match for behaviours? Or the only way to indicate to the users of the library that this function accepts structures in the parameter which implements this behaviour is a function doc?

You can’t, at least not without going into metaprogramming and at that point the solution you arrived at is most probably not idiomatic.

I would recommend to rethink the problem in terms of pattern match and data structures instead of modules that resemble classes.

1 Like

Thank you, I suspected this is the case and I will rethink instead as you suggested!

1 Like

You could have your “constructer” function as a second parameter. This way your module does not have to enforce the new/1 function.

defmodule Library do
  def build(module, fun) do
    data = Repo.one(module)
    fun.(data)
  end
end

Library.build(TestData, &TestData.new/1)
2 Likes