Check if a protocol is implemented without raising an error

suggestion
#1

The function Protocol.assert_impl is the only way to check it a module implements a protocol.
https://hexdocs.pm/elixir/Protocol.html#assert_impl!/2

In the case that a module does not implement a protocol this function raises an exception.
Currently to provide functionality in the case that a protocol is not implemented the exception must be caught.

Something like Protocol.is_impl? with the same functionality would be helpful.
I think that would be the most familiar api.

However something like Protcol.apply(term, procol) which returned {:ok, return} or {:error, :not_implemented} would also work.

5 Likes
#2

I think this could have a pretty good chance of getting accepted. The criticisms I see are:

  • This will be rarely used
  • You can implement this yourself

If you wanted to expand this to a proposal, you might argue against these points. For example, the first may not be a valid criticism, because it may be used about as much as assert_impl and maybe more if it existed.

You may also want to argue these points, which may overcome any criticism:

  • It fits within the existing feature set
  • The implementation is not complex
  • It fits in the goals and ethos of Elixir
  • It will substantially improve the ergonomics

Finally, for consistency, you may want to expand your proposal to cover Protocol.assert_protocol/1.

2 Likes
#3

You can’t know without trying to load the implementing module into the BEAM, and this will always raise if the module is not available in the load pathes. Of course, a none raising function can only work by catching and then returning false, which is unidiomatic and in general should be avoided.

So I assume, catching is left to the user in cases where he don’t want to crash to remind him of the complications of catching.

#4

This guideline is interesting.

You should avoid using exceptions for control-flow.

As a library author, it is your responsibility to make sure users are not required to use exceptions for control-flow in their applications. You can follow the same convention as Elixir here, using the name without ! for returning :ok / :error tuples and appending ! for a version of the function which raises an exception.

As this feature exists, it seems to require using exceptions as control-flow. However, if Elixir were to implement this in a way that didn’t require the user to use exceptions as control flow, Elixir itself would be using exceptions as control flow. The second quote seems to imply the library (Elixir in this case) should take on the burden.

It may be useful to show real code that cares about a module implementing a protocol and how it’s not possible to write that code without using exceptions as control flow.