objetos metodos manejo lista instanciar importar herencia elemento como clases arreglo agregar ruby

metodos - ¿Puedes proporcionar argumentos a la sintaxis del mapa(&: método) en Ruby?



manejo de objetos en ruby (5)

Probablemente estés familiarizado con la siguiente taquigrafía de Ruby ( a es una matriz):

a.map(&:method)

Por ejemplo, intente lo siguiente en irb:

>> a=[:a, ''a'', 1, 1.0] => [:a, "a", 1, 1.0] >> a.map(&:class) => [Symbol, String, Fixnum, Float]

La sintaxis a.map(&:class) es una abreviatura de a.map {|x| x.class} a.map {|x| x.class} .

Lea más sobre esta sintaxis en " ¿Qué significa map (&: name) en Ruby? ".

A través de la sintaxis &:class , está haciendo una class llamada de método para cada elemento de matriz.

Mi pregunta es: ¿pueden proporcionar argumentos a la llamada al método? Y si es así, ¿cómo?

Por ejemplo, cómo convertir la siguiente sintaxis

a = [1,3,5,7,9] a.map {|x| x + 2}

a la &: sintaxis?

No estoy sugiriendo que la sintaxis &: sea ​​mejor. Simplemente estoy interesado en la mecánica de usar la sintaxis &: con argumentos.

Supongo que sabes que + es un método en la clase Integer. Puede probar lo siguiente en irb:

>> a=1 => 1 >> a+(1) => 2 >> a.send(:+, 1) => 2


Como confirma la publicación a la que vinculó, a.map(&:class) no es una abreviatura de a.map {|x| x.class} a.map {|x| x.class} pero para a.map(&:class.to_proc) .

Esto significa que se llama a to_proc en lo que sigue al operador & .

Entonces, puedes darle un Proc directamente:

a.map(&(Proc.new {|x| x+2}))

Sé que lo más probable es que esto derrote el propósito de su pregunta, pero no veo otra forma de to_proc : no es que especifique a qué método llamar, simplemente le pasa algo que responde a to_proc .


En lugar de parchear las clases básicas usted mismo, como en la respuesta aceptada, es más corto y más limpio utilizar la funcionalidad de la gema Facetas :

require ''facets'' a = [1,3,5,7,9] a.map &:+.(2)


Para su ejemplo, se puede hacer a.map(&2.method(:+)) .

Arup-iMac:$ pry [1] pry(main)> a = [1,3,5,7,9] => [1, 3, 5, 7, 9] [2] pry(main)> a.map(&2.method(:+)) => [3, 5, 7, 9, 11] [3] pry(main)>

Así es como funciona :-

[3] pry(main)> 2.method(:+) => #<Method: Fixnum#+> [4] pry(main)> 2.method(:+).to_proc => #<Proc:0x000001030cb990 (lambda)> [5] pry(main)> 2.method(:+).to_proc.call(1) => 3

2.method(:+) da un objeto Method . Entonces & , en 2.method(:+) , en realidad es un método de llamada #to_proc , que lo está convirtiendo en un objeto Proc . Luego, sigue ¿Cómo llamas al operador &: en Ruby? .


Puedes crear un parche simple en Symbol como este:

class Symbol def with(*args, &block) ->(caller, *rest) { caller.send(self, *rest, *args, &block) } end end

Lo cual le permitirá no solo hacer esto:

a = [1,3,5,7,9] a.map(&:+.with(2)) # => [3, 5, 7, 9, 11]

Pero también muchas otras cosas interesantes, como pasar múltiples parámetros:

arr = ["abc", "babc", "great", "fruit"] arr.map(&:center.with(20, ''*'')) # => ["********abc*********", "********babc********", "*******great********", "*******fruit********"] arr.map(&:[].with(1, 3)) # => ["bc", "abc", "rea", "rui"] arr.map(&:[].with(/a(.*)/)) # => ["abc", "abc", "at", nil] arr.map(&:[].with(/a(.*)/, 1)) # => ["bc", "bc", "t", nil]

E incluso trabajar con inject , que pasa dos argumentos al bloque:

%w(abecd ab cd).inject(&:gsub.with(''cde'')) # => "cdeeecde"

O algo súper genial como pasar bloques [taquigrafía] al bloque taquigráfico:

[[''0'', ''1''], [''2'', ''3'']].map(&:map.with(&:to_i)) # => [[0, 1], [2, 3]] [%w(a b), %w(c d)].map(&:inject.with(&:+)) # => ["ab", "cd"] [(1..5), (6..10)].map(&:map.with(&:*.with(2))) # => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Aquí hay una conversación que tuve con @ArupRakshit para explicarlo más a fondo:
¿Puedes proporcionar argumentos a la sintaxis del mapa (&: método) en Ruby?

Como @amcaplan sugirió en el comentario a continuación , puede crear una sintaxis más corta, si cambia el nombre del método with que desea call . En este caso, ruby ​​tiene un atajo incorporado para este método especial .() .

Entonces podrías usar lo anterior así:

class Symbol def call(*args, &block) ->(caller, *rest) { caller.send(self, *rest, *args, &block) } end end a = [1,3,5,7,9] a.map(&:+.(2)) # => [3, 5, 7, 9, 11] [(1..5), (6..10)].map(&:map.(&:*.(2))) # => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]


Respuesta corta: No.

Siguiendo la respuesta de @ rkon, también puedes hacer esto:

a = [1,3,5,7,9] a.map &->(_) { _ + 2 } # => [3, 5, 7, 9, 11]