¿Qué significa `& method (: function)`?

15

Que &method(:function)significa Por ejemplo, tengo esta línea:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
fuente
Dos excelentes respuestas (hasta ahora). ¡Eres afortunado!
Cary Swoveland

Respuestas:

13

Digamos que tenemos un método

def add_one(num)
  num + 1
end

y una variedad de cuerdas

arr = ["1", "2"]

Queremos mapla lista de cadenas a sus salidas correspondientes de add_one.

Para empezar podemos llamar

nums = arr.map(&:to_i)

Esto es lo mismo que

nums = arr.map do |str|
  str.to_i
end

Puedes ver ¿Qué significa map (&: name) en Ruby? Para más información sobre esto.

Sin embargo, no funcionará llamar:

nums.map(&:add_one)

¿Por qué? Porque los números no tienen un método incorporado add_one. Entonces obtendrás un NoMethodError.

Entonces, en lugar de proporcionar solo un nombre de método :add_one , puede pasar un método enlazado method(:add_one) :

nums.map(&method(:add_one))

Ahora, en lugar de usar cada número como receptor para el add_onemétodo, se usarán como argumentos . Entonces, es esencialmente lo mismo que:

nums.map do |num|
  add_one(num)
end

Para dar otro ejemplo, compare lo siguiente:

[1].map(&:puts)
# this is the same as [1].map { |num| num.puts }
# it raises NoMethodError

[1].map(&method(:puts))
# this is the same as [1].map { |num| puts num }
# it prints 1 successfully
max pleaner
fuente
Nitpick: Object#methoddevuelve un límite Method , no un UnboundMethod. El método está vinculado a un receptor porque lo está llamando a una instancia y, por lo tanto, sabe lo que selfes, mientras que Module#instance_methoddevuelve un UnboundMethodporque no puede saber con qué instancia se utilizará.
Jörg W Mittag
@ JörgWMittag Ok, gracias por la corrección, tienes razón, debo haber estado .instance_method
confundiéndolo
10

method(:function)es un mensaje enviado (a veces llamado una llamada de método ) al receptor implícito (es decir self). Está enviando el mensaje methodal receptor implícito (es decir self), pasando :functioncomo único argumento.

:functiones un Symbolliteral, es decir, es la notación literal de a Symbol. Symboles un tipo de datos que representa "el nombre de algo".

El operador de ampersand del prefijo unario &"desenrolla" Procun bloque . Es decir, le permite pasar un lugar Procdonde se espera un bloqueo . Si el objeto aún no es un Proc, se le enviará el to_procmensaje permitiéndole convertirse en un Proc. (El operador solo es legal en una lista de argumentos y solo para el último argumento. Es el doble del &sigilo en una lista de parámetros, que "rueda" un bloque en un Procobjeto).

Proces un tipo de datos que representa el código ejecutable. Es la clase de biblioteca principal de Ruby para subrutinas de primera clase.

Por lo tanto, lo que hace esto, es llamar al methodmétodo en selfla :functionque el argumento, llamada to_procen el valor de retorno "desenrolle" el resultado Procobjeto en un bloque y pasar ese bloque a la llamada a integratealgo como si se hubiera escrito como

res = integrate(0, 1, a) do
  # something
end

El methodmétodo aquí es más probable, el Object#methodmétodo, que devuelve un objeto vinculado Method .

Entonces, en general, esto es algo equivalente a

res = integrate(0, 1, a) do |*args, &block|
  function(*args, &block)
end

Pero expresado en lo que comúnmente se llama estilo sin puntos .

Jörg W Mittag
fuente