Probablemente esté familiarizado con la siguiente abreviatura de Ruby ( aes 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}.
Lea más sobre esta sintaxis en " ¿Qué significa mapa (&: nombre) en Ruby? ".
A través de la sintaxis &:class, está realizando una llamada classa un método para cada elemento de la matriz.
Mi pregunta es: ¿puede proporcionar argumentos a la llamada al método? Y si es así, ¿cómo?
Por ejemplo, ¿cómo se convierte 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 sabe 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

Symbol#withpuede no existir en la biblioteca principal y definir ese método es menos destructivo que redefinir un método existente, todavía está cambiando (es decir, sobrescribiendo) la implementación de la clase principal de la biblioteca ruby. La práctica debe realizarse con mucha moderación y mucha precaución. \ n \ n Considere heredar de la clase existente y modificar la clase recién creada. Esto generalmente logra resultados comparables sin los efectos secundarios negativos de cambiar las clases de rubí centrales.Symbolclase, no es trivial (si es posible), ya que es una clase central (no tiene ningúnnewmétodo, por ejemplo), y su uso será engorroso (si es posible), lo que anulará la propósito de la mejora ... si puede mostrar una implementación que lo usa y logra resultados comparables, ¡comparta!withmétodo, definacall. Entonces puedes hacer cosas comoa.map(&:+.(2))ya queobject.()usa el#callmétodo. Y mientras lo hace, puede escribir cosas divertidas como:+.(2).(3) #=> 5: se siente como LISPy, ¿no?Por tu ejemplo se puede hacer
a.map(&2.method(:+)).Así es como funciona :-
2.method(:+)da unMethodobjeto. Luego&, en2.method(:+)realidad, es un#to_procmétodo de llamada , que lo convierte en unProcobjeto. Luego sigue ¿Cómo llamas al operador &: en Ruby? .fuente
Pryresultados anteriores, puede obtenerlo, ¿cómo está funcionando?+es conmutativo.Como confirma la publicación a la que vinculó,
a.map(&:class)no es una abreviatura dea.map {|x| x.class}sino dea.map(&:class.to_proc).Esto significa que
to_procse invoca todo lo que sigue al&operador.Entonces podrías darle directamente un
Procen su lugar:Sé que lo más probable es que esto anule el propósito de su pregunta, pero no puedo ver otra forma de evitarlo; no es que usted especifique a qué método llamar, simplemente le pasa algo que responda
to_proc.fuente
my_proc = Proc.new{|i| i + 1},[1,2,3,4].map(&my_proc) => [2,3,4,5]Respuesta corta: No.
Siguiendo la respuesta de @ rkon, también puedes hacer esto:
fuente
&->(_){_ + 2}sea más corto que{|x| x + 2}.En lugar de parchear las clases principales usted mismo, como en la respuesta aceptada, es más corto y más limpio usar la funcionalidad de la gema Facetas :
fuente
Hay otra opción nativa para enumerables que, en mi opinión, es bonita solo para dos argumentos. la clase
Enumerabletiene el métodowith_objectque luego devuelve otroEnumerable.Entonces puede llamar al
&operador para obtener un método con cada elemento y el objeto como argumentos.Ejemplo:
En el caso de que quiera más argumentos debería repetir el proceso pero es feo en mi opinión:
fuente
No estoy seguro de lo que
Symbol#withya se publicó, lo simplifiqué un poco y funciona bien:(también se usa en
public_sendlugar desendpara evitar llamar a métodos privados, tambiéncallerya lo usa ruby, por lo que esto era confuso)fuente