Elixir 函数中的元组或关键字列表

Tuples or Keyword Lists in Elixir functions

Programming Elixir 书的第 221 页指出,如果我们想将 call 中的多个值传递给 GenServer,我们应该使用元组:

def handle_call({:set_number, new_number}, _from, _current_number) do
{ :reply, new_number, new_number }
end

iex> GenServer.call(pid, {:set_number, 999})

在我看来,关键字列表更适合这种情况:

def handle_call([ set_number: new_number ], _from, _current_number) do
  { :reply, new_number, new_number + 1 }
end

iex(2)> GenServer.call pid, set_number: 999

这样我就可以完全避免大括号,而且我使用关键字列表的目的似乎是:传递 options/arguments。

这种做法有什么问题吗?还是我违反了一些最佳实践?

Keyword Lists 是 2 项元组的列表。所以 [set_number: 999] 等同于 [{:set_number, 999}].

通常在这些情况下使用元组,因为它们比关键字列表更通用。关键字列表仅限于 2 项元组,而在某些情况下您想要传递 3 项元组(或更多)。考虑存储键值 GenServer 的情况。要存储一个值,您需要以 {:put, key, value}.

的形式传递一个 3 项元组

"Avoiding braces altogether" 不应该是所用数据类型的决定因素。另请注意,客户端不应该知道服务器实现,因此,您通常定义一个客户端 API.

defmodule MyModule do
  use GenServer

  #client API
  def set_number(pid, number) do
    GenServer.call(pid, {:set_number, number})
  end

  def handle_call({:set_number, new_number}, _from, _current_number) do
    { :reply, new_number, new_number }
  end
end

现在从 iex 开始,您只需调用:

iex > MyModule.set_number(pid, 999)

这样,如果您需要更改服务器实现,则无需更改客户端。