我一直在学习Elixir,并尝试构建类似于Mars Rover Kata的应用程序
我正在使用GenServer维护单个流动站的状态,并在注册表的帮助下尝试生成一个密钥,即流动站名称
Rover.ex代码
defstruct [:x, :y, :direction, :name]
def start_link({x, y, d, name}) do
GenServer.start_link(__MODULE__, {x, y, d, name}, name: RegistryHelper.create_key(name))
end
def init({x, y, d, name}) do
{:ok, %Rover{x: x, y: y, direction: d, name: name}}
# {:ok, %{}}
end
def get_state(name) do
GenServer.call(RegistryHelper.create_key(name), :get_state)
end
def handle_call(:get_state, _from, state) do
{:reply, {:ok, {state.x, state.y, state.direction}}, state}
end
Registry_helper.ex
defmodule RegistryHelper do
@spec create_key(String.t) :: {:via, atom, {atom, String.t}}
def create_key(name), do: {:via, Registry, {Rover.Registry, name}}
@spec register(String.t) :: {:ok, pid} | {:error, {:already_registered, pid}}
def register(name), do: Registry.register(Rover.Registry, create_key(name), [])
@spec get_pid(String.t) :: pid
def get_pid(name) do
[{pid, _}] = Registry.lookup(Rover.Registry, name)
pid
end
end
** (ArgumentError) unknown registry: Rover.Registry
code: {:ok, _} = Rover.start_link({9, 9, :N, "rover0"})
stacktrace:
(elixir) lib/registry.ex:1154: Registry.key_info!/1
(elixir) lib/registry.ex:213: Registry.whereis_name/2
(stdlib) gen.erl:76: :gen.start/6
test/rover_test.exs:5: (test)
注册表模块是否有问题,或者我将参数传递给start_link的方式?
答案 0 :(得分:0)
您永远不会启动Registry
。除非您有更好的注册位置(例如Application.start/2
中的某个位置),否则最简单的解决方法是从Rover.start_link/1
开始注册:
def start_link({x, y, d, name}) do
# Better start it supervised!
Registry.start_link(keys: :unique, name: Rover.Registry)
GenServer.start_link(
__MODULE__, {x, y, d, name},
name: RegistryHelper.create_key(name))
end