Есть ли в Elixir оператор splat?

defmodule UnixCommands do
    alias Porcelain.Result
        def run(command, *opts) do
             %Result{out: output, status: _} = Porcelain.exec(command, [opts])
             IO.puts output
        end
end

Существует ли эквивалент оператора splat, например * opts, в Elixir? Есть ли способ передать несколько опций вместо списка параметров функции exec в качестве аргументов?

Ответ 1

Нет оператора splat. Функции в Elixir (и Erlang) определяются их именем и arity (String.downcase/1, Enum.member?/2), и вариационная функция будет идти против этого.

Об этом говорит один из авторов Erlang Joe Armstrong в его книге "Программирование Erlang: программное обеспечение для параллельного мира":

1) функция arity является частью ее имени и
2) нет вариационных функций.

Если вы хотите вызвать функцию со списком аргументов (напротив того, что вы хотите), можете использовать Kernel.apply/3.

например.

defmodule Test do
  def add(a, b, c) do
    a + b + c 
  end
end

apply(Test, :add, [1, 2, 3])

Ответ 2

Вы не можете указать переменную arity для функций в Elixir (или Erlang, если на то пошло), как сказал Газир. Проще всего сделать, чтобы передать список вместо параметра, который вы хотите изменить по числу, а затем использовать сопоставление образцов, чтобы разложить его должным образом. Учитывая ваш пример выше, он будет выглядеть следующим образом:

defmodule UnixCommands do
  alias Porcelain.Result
  def run(command,[opts]) do
    optlist = opts |> Enum.reduce(fn o-> "#{o} " end)
    %Result{out: output, status: _} = Porcelain.exec(command, optlist)
  end
end  

NB: я не тестировал этот код, потому что я не хочу устанавливать Porcelain, но он должен быть в основном правильным.