¿Qué hace un operador double * (splat)

¿Has visto una función declarada así?

def foo a, **b ... end 

Entiendo que un single * es el operador de splat. ¿Qué significa ** ?

    Ruby 2.0 introdujo argumentos de palabra clave, y ** actúa como * , pero para argumentos de palabra 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}] 

    Ese es el operador doble splat que está disponible desde Ruby 2.0.

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

     def my_method(**options) puts options.inspect end my_method(key: "value") 

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

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

    Ejemplo de la vida real:

    Por ejemplo, en Rails, el método del 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: acepta una lista de argumentos y la última es un hash de opciones, que se puede extraer, por ejemplo, utilizando extract_options! de ActiveSupport extract_options! .

    En Ruby 2.0 puedes simplificar estos métodos:

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

    Es cierto que solo se trata de una mejora menor si ya está usando ActiveSupport, pero para Ruby simple, el código adquiere mucha concisión.

    Además, puede usarlo en el lado del llamante como este:

     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}