Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a splat operator in Elixir?

Tags:

elixir

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

Is there a splat operator equivalent, such as *opts, in Elixir? Is there is way to pass multiple options, instead of a list of options, to the exec function as arguments?

like image 327
Kit Ko Avatar asked Aug 21 '15 09:08

Kit Ko


People also ask

What is a splat operator?

What is the Splat Operator? The * (or splat) operator allows a method to take an arbitrary number of arguments and is perfect for situations when you would not know in advance how many arguments will be passed in to a method. Here's an example: def name_greeting(*names) names.

Is there a spread operator in Ruby?

In both Ruby and JavaScript, you can use splat/spread to build up a new array from existing arrays.

What does splat do Ruby?

Splat operator or start (*) arguments in Ruby define they way they are received to a variable. Single splat operator can be used to receive arguments as an array to a variable or destructure an array into arguments. Double splat operator can be used to destructure a hash.


2 Answers

There is not a splat operator. Functions in Elixir (and Erlang) are defined by their name and arity (String.downcase/1, Enum.member?/2) and a variadic function would go against this.

This is mention by one of the Erlang authors Joe Armstrong's in his book "Programming Erlang: Software for a Concurrent World":

1) a function's arity is part of its name and
2) there are no variadic functions.

If you want to call a function with a list of arguments (the opposite of what you want) can use Kernel.apply/3.

E.g.

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

apply(Test, :add, [1, 2, 3])
like image 88
Gazler Avatar answered Sep 22 '22 13:09

Gazler


You cannot specify a variable arity for functions in Elixir (or Erlang either for that matter) as Gazier said. Simplest thing to do is to pass a List in place of the parameter that you want to vary in number and then use pattern matching to decompose it properly. Given your example above it'd look like this:

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: I did not test this code because I don't want to install Porcelain but it should basically be correct.

like image 36
Onorio Catenacci Avatar answered Sep 20 '22 13:09

Onorio Catenacci