2017-02-26 92 views
0

我正在Elixir中编写游戏引擎。 (是的,我知道这不是一种固有的语言 - 关键是看非典型语言如何影响结果的结构。)使用元组作为Elixir中的函数的参数

因此,我有几个主管要运行游戏开始 - 但他们应该监督什么取决于游戏。我的想法是让用户在config.exs文件中列出所需的子元素,以及参数和选项,作为元组列表,然后管理程序本身只需从应用程序环境中提取这些元组并将其内容用作参数worker\2(或worker\3,如适用)。

但是,我找不到任何与Python的元组相同的Elixir解包。我可以做我自己用一个简单的功能这个特定的情况下:

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

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

但是,这充其量感觉笨拙,并且必须要对每一个对我可能需要这种可配置的功能将被再次写入。

回答

4

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

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

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

我想你需要知道元组的大小才能正确访问元素。也许你的用例更好的数据结构将是一个关键字列表,特别是考虑到它是你从配置中得到的东西?那么你可以解压worker :, args:并将其余部分作为选项保留下来?

0

我相信你会想要​​和tuple_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}) 

不过请注意,如果你不元组上的索引,在要求的元素,你得到的参数错误。这意味着您仍然需要使用多功能头或某些东西来区分您尝试执行的操作。