使用元组作为Elixir

时间:2017-02-26 21:50:17

标签: elixir argument-unpacking

我正在Elixir中编写游戏引擎。 (是的,我知道它不是一种本身就适合的语言 - 重点是看非典型语言的使用如何影响结果的结构。)

因此,我有几个主管在游戏开始时运行 - 但他们究竟应该监督什么取决于游戏。我的想法是让用户在config.exs文件中列出必要的子节点,加上参数和选项作为元组列表,然后管理程序本身只需从应用程序环境中提取这些元组并使用它们内容作为worker\2(或worker\3的参数,视情况而定)。

但是,我找不到任何Elixir等同于Python的元组解包。我可以通过一个简单的函数自己完成这个特定的案例:

def unpack_worker({module, args}) do
  worker(module, args)
end

def unpack_worker({module, args, opts}) do
  worker(module, args, opts)
end

但是这种情况充其量只是笨拙,并且必须为每种我可能需要这种可配置性的功能再次编写。

3 个答案:

答案 0 :(得分:5)

我相信您正在寻找Tuple.to_list/1apply/3

有了这些,你可以根据元组的内容调用正确的arity函数:

def unpack_worker(args) do
  apply(__MODULE__, :worker, Tuple.to_list(args))
end

如果您现在致电unpack_worker({}),则会致电worker()unpack_worker({:foo})会致电worker(:foo),依此类推。

演示:

defmodule A do
  def worker, do: IO.puts 0
  def worker(_), do: IO.puts 1
  def worker(_, _), do: IO.puts 2
  def worker(_, _, _), do: IO.puts 3

  def unpack_worker(tuple), do: apply(__MODULE__, :worker, Tuple.to_list(tuple))
end

A.unpack_worker({})
A.unpack_worker({:a})
A.unpack_worker({:a, :b})
A.unpack_worker({:a, :b, :c})

输出:

0
1
2
3

答案 1 :(得分:1)

我认为您需要知道元组的大小才能正确访问元素。也许为您的用例更好的数据结构将是一个关键字列表,特别是考虑到它是你从配置得到的?然后你可以解压工人:,args:并留下余数作为选项?

答案 2 :(得分:0)

我相信您需要elem/2tuple_size/1功能的组合。

iex(1)> a = {:foo, :bar, :baz}
{:foo, :bar, :baz}
iex(2)> tuple_size(a)
3
iex(3)> elem(a, 0)
:foo
iex(4)> elem(a, 5)
** (ArgumentError) argument error
    :erlang.element(6, {:foo, :bar, :baz})

请注意,如果要求元组中不存在的索引元素,则会出现参数错误。这意味着您仍然需要使用if / case / cond /多个函数头或其他东西来区分您尝试执行的操作。