2016-10-14 2 views
0

나는 Elixir에서 프로토콜을 정의한 다음 두 개의 모듈에서 구현하려고합니다. 내 문제는 그래서, 그 모듈은 단지 에이전트 래퍼이다 :Elixir에서 에이전트를 사용하여 프로토콜 구현

다음의 결과
defprotocol Proto do 
    def foo(proto) 
end 

defmodule A do 
    def start_link() do 
    Agent.start_link(fn -> :a end) 
    end 
end 

defimpl Proto, for: A do 
    def foo(proto) do 
    Agent.get(proto, fn a -> a end) 
    end 
end 

defmodule B do 
    def start_link() do 
    Agent.start_link(fn -> :b end) 
    end 

end 

defimpl Proto, for: B do 
    def foo(proto) do 
    Agent.get(proto, fn b -> b end) 
    end 
end 

{:ok, a_pid} = A.start_link() 
value = Proto.foo(a_pid) 

,

** (Protocol.UndefinedError) protocol Proto not implemented for #PID<0.88.0> 
    test.exs:1: Proto.impl_for!/1 
    test.exs:2: Proto.foo/1 
    (elixir) lib/code.ex:363: Code.require_file/2 

직접이 문제를 해결할 수있는 방법이 있나요?

답변

2

이와 같은 프로토콜을 사용하려면 AB 구조체를 만들어 각각 start_link 함수에서 반환해야합니다. Agent 함수를 호출하려면 Agent 주위에 래퍼가 필요합니다.

defprotocol Proto do 
    def foo(proto) 
end 

defmodule A do 
    defstruct [:pid] 

    def start_link() do 
    WrappedAgent.start_link(A, fn -> :a end) 
    end 
end 

defimpl Proto, for: A do 
    def foo(proto) do 
    WrappedAgent.get(proto, fn a -> {:a, a} end) 
    end 
end 

defmodule B do 
    defstruct [:pid] 

    def start_link() do 
    WrappedAgent.start_link(B, fn -> :b end) 
    end 
end 

defimpl Proto, for: B do 
    def foo(proto) do 
    WrappedAgent.get(proto, fn b -> {:b, b} end) 
    end 
end 

defmodule WrappedAgent do 
    def start_link(module, f) do 
    with {:ok, pid} <- Agent.start_link(f), 
     do: {:ok, %{__struct__: module, pid: pid}} 
    end 

    def get(%{pid: pid}, f), do: Agent.get(pid, f) 
end 

{:ok, a} = A.start_link() 
IO.inspect Proto.foo(a) 

{:ok, b} = B.start_link() 
IO.inspect Proto.foo(b) 

출력 :

{:a, :a} 
{:b, :b} 
+0

Perfect! 고맙습니다. 저는 엘릭서의 세계에 익숙하지 않아 언어의 철학을 익히는 데 약간의 시간이 걸릴 수 있습니다. –

2

그냥 조금 명확히하기, 프로토콜이 구현되는 동일한 구조를 더 구조체를 만들 경우 같은 재사용 할 수 있기 때문에 나는이에 대한 별도의 모듈을 만들었습니다 데이터 유형. 모든 표준 데이터 유형 및 모듈에서 정의한 모든 구조체에 대한 프로토콜을 구현할 수 있습니다.

[Atom, Integer, Float, BitString, Regexp, PID, Function, Reference, Port, Tuple, List, Map] 

"동일한 기능, 다른 데이터 유형"이라고 생각하십시오. 원래 생각에 더 가까운 행동과 대조하십시오. 이 모듈에서는 다른 모듈이 표준 방식으로 모듈을 사용하도록 허용하기 위해 모듈에 구현하는 것과 동일한 방식으로 (그리고 규칙 상 동일한 입력으로) 함수 세트를 정의합니다.