Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share functions across protocol implementations in Elixir

Tags:

elixir

I am just working through Dave Thomas' book and am currently exploring Protocols in Elixir. I know I can fallback to a generic protocol implementation with @fallback_to_any true. For example:

defprotocol Caesar do
  @fallback_to_any true
  def encrypt(string, shift)
  def rot13(string)
end

defimpl Caesar, for: BitString do
  def encrypt(string, shift) do
    # implementation for binary
  end

  def rot13(string) do
    # implementation for binary
  end
end

defimpl Caesar, for: List do
  def encrypt(string, shift) do
    # implementation for character list
  end

  def rot13(string) do
    # implementation for character list
  end
end

defimpl Caesar, for: Any do
  def encrypt(string, shift) do
    # generic implementation
  end

  def rot13(string) do
    # generic implementation
  end
end

However in the above case, basically every implementation of rot13/1 would look like this:

def rot13(string) do
  Caesar.encrypt(string, 13)
end

Still, I currently have to repeat this in every implementation, which seems utterly wrong. Is there a way to share rot13/1 across all implementations of Caesar?

like image 395
Patrick Oscity Avatar asked Sep 25 '14 07:09

Patrick Oscity


1 Answers

So I found this question about delegation in implementations. It made me wonder whether defdelegate works inside protocols and indeed it does! So a possible solution to this is as follows:

defmodule Caesar.Shared do
  def rot13(string) do
    Caesar.encrypt(string, 13)
  end
end

defprotocol Caesar do
  def encrypt(string, shift)
  defdelegate rot13(string), to: Caesar.Shared
end

defimpl Caesar, for: BitString do
  def encrypt(string, shift) do
    # implementation for binary
  end
end

defimpl Caesar, for: List do
  def encrypt(string, shift) do
    # implementation for character list
  end
end

I'm still interested in other answers. Maybe there is still a better, more idiomatic way to do this directly inside the protocol definition.

like image 54
Patrick Oscity Avatar answered Jan 02 '23 20:01

Patrick Oscity