在Elixir中跨协议实现共享功能

Pat*_*ity 6 elixir

我正在阅读Dave Thomas的书,目前正在Elixir中探索Protocols.我知道我可以回退到通用协议实现@fallback_to_any true.例如:

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
Run Code Online (Sandbox Code Playgroud)

但是在上面的例子中,基本上每个实现rot13/1都会如下所示:

def rot13(string) do
  Caesar.encrypt(string, 13)
end
Run Code Online (Sandbox Code Playgroud)

不过,我现在必须在每个实施中重复这一点,这似乎是完全错误的.有没有办法分享rot13/1所有的实现Caesar

Pat*_*ity 12

所以我在实现中找到了关于委托的问题.它让我怀疑是否defdelegate在协议内工作,确实是这样!因此,可能的解决方案如下:

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
Run Code Online (Sandbox Code Playgroud)

我仍然对其他答案感兴趣.也许在协议定义中直接执行此操作仍然有更好,更惯用的方法.

  • 您的解决方案绝对是您要走的路! (4认同)