Qué hace un operador doble * (splat)


¿Has visto una función declarada así?

def foo a, **b
  ...
end

Entiendo que un único * es el operador splat. ¿Qué significa **?

 166
Author: sawa, 2013-08-17

3 answers

Ruby 2.0 introdujo argumentos de palabras clave, y ** actúa como *, pero para argumentos de palabras clave. Devuelve un Hash con pares clave / valor.

Para este código:

def foo(a, *b, **c)
  [a, b, c]
end

Aquí hay una demostración:

> foo 10
=> [10, [], {}]
> foo 10, 20, 30
=> [10, [20, 30], {}]
> foo 10, 20, 30, d: 40, e: 50
=> [10, [20, 30], {:d=>40, :e=>50}]
> foo 10, d: 40, e: 50
=> [10, [], {:d=>40, :e=>50}]
 302
Author: Dogbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-17 13:11:15

Es el operador double splat que está disponible desde Ruby 2.0.

Captura todos los argumentos de palabras clave (que también puede ser un hash simple, que era la forma idiomática de emular argumentos de palabras clave antes de que se convirtieran en parte del lenguaje Ruby)

def my_method(**options)
  puts options.inspect
end

my_method(key: "value")

El código anterior imprime {key:value} en la consola.

Al igual que el operador splat único captura todos los argumentos regulares, pero en lugar de un array se obtiene un hash .

Ejemplo de la vida real:

Por ejemplo en Rails el método cycle se ve así:

def cycle(first_value, *values)
  options = values.extract_options!
  # ...
end

Este método se puede llamar así: cycle("red", "green", "blue", name: "colors").

Este es un patrón bastante común: Se acepta una lista de argumentos y el último es un hash de opciones, que se puede extraer, por ejemplo, usando extract_options! de ActiveSupport.

En Ruby 2.0 puede simplificar estos métodos:

def cycle(first_value, *values, **options)
  # Same code as above without further changes!
end

Es cierto que es solo una mejora menor si usted es ya está usando ActiveSupport pero para Ruby llano el código gana bastante concisión.

 34
Author: Daniel Rikowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 06:55:44

Además, puede usarlo en el lado de llamada de esta manera:

def foo(opts); p opts end
bar = {a:1, b:2}

foo(bar, c: 3)
=> ArgumentError: wrong number of arguments (given 2, expected 1)

foo(**bar, c: 3)
=> {:a=>1, :b=>2, :c=>3}
 8
Author: kuboon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-26 22:50:08