【问题标题】:Dynamically generate a function of varying arity with pattern matching in Elixir?在 Elixir 中通过模式匹配动态生成不同数量的函数?
【发布时间】:2021-03-09 14:58:20
【问题描述】:

有点 similar to this question 对于 Ocaml,我想在 Elixir 中动态生成具有不同数量的函数,这些函数可用于对不同的输入进行模式匹配。

例如,如果我在运行时获得列表项的无限输入,例如,

[1, 2, 3]
[1, 2, 1]
[1, 2, 3, 4]
# ... etc ...

我想在这样定义的模块上生成函数:

defmodule Example do
  def func([x, y, z]), do: [x, y, z]
  def func([x, y, x]), do: [x, y, x]
  def func ([a, b, c, d]), do: [a, b, c, d]
end

这可能吗?如果可以,怎么做?我知道如果输入是在编译时定义的,你可以用宏来做到这一点,但由于输入是在运行时实时发生的,所以宏似乎不起作用。

【问题讨论】:

    标签: elixir


    【解决方案1】:

    通过一点元编程以及Macro.generate_arguments/2Kernel.SpecialForms.unquote/1Kernel.SpecialForms.unquote_splicing/1 的帮助,这是可能的。

    defmodule Dyn do
      @expected_input [
        [1, 2, 3],
        [1, 2, 1],
        [1, 2, 3, 4]
      ] |> Enum.map(&length/1) |> Enum.uniq()
    
      for arity <- @expected_input do
        args = Macro.generate_arguments(arity, __MODULE__)
        def func(unquote(args)), do: unquote(args)
        def func(unquote_splicing(args)), do: unquote(args)
      end
    end
    

    如下图所示:

    iex|1 ▶ Dyn.func 1, 2, 3
    [1, 2, 3]
    iex|2 ▶ Dyn.func [1, 2, 3, 4]
    [1, 2, 3, 4]
    iex|3 ▶ Dyn.func [1, 2]    
    ** (FunctionClauseError) no function clause matching in Dyn.func/1 
    

    请注意,上面的代码为作为数组的两个参数以及多个参数生成子句。

    【讨论】:

      猜你喜欢
      • 2018-04-03
      • 2019-11-07
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 2018-11-24
      • 2020-01-23
      相关资源
      最近更新 更多