O que significa `& method (: function)`?

15

O que &method(:function)significa isso ? Por exemplo, eu tenho esta linha:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
fonte
Duas excelentes respostas (até agora). Sortudo!
Cary Swoveland

Respostas:

13

Digamos que temos um método

def add_one(num)
  num + 1
end

e uma variedade de strings

arr = ["1", "2"]

Queremos mapa lista de strings para as saídas correspondentes add_one.

Para começar, podemos ligar

nums = arr.map(&:to_i)

É a mesma coisa que

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

Você pode ver O que significa map (&: name) no Ruby? para mais informações sobre isso.

No entanto, não funcionará para chamar:

nums.map(&:add_one)

Por quê? Porque os números não têm método incorporado add_one. Então você receberá um NoMethodError.

Portanto, em vez de fornecer apenas um nome de método, :add_one você pode passar um método vinculado method(:add_one) :

nums.map(&method(:add_one))

Agora, em vez de cada número ser usado como receptor para o add_onemétodo, eles serão usados ​​como argumentos . Portanto, é essencialmente o mesmo que:

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

Para dar outro exemplo, compare o seguinte:

[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
fonte
Nitpick: Object#methodretorna um limite Method , não um UnboundMethod. O método está vinculado a um receptor porque você está chamando-o em uma instância e, portanto, sabe o que selfé, enquanto Module#instance_methodretorna um UnboundMethodporque não pode saber com qual instância ele será usado.
Jörg W Mittag
@ JörgWMittag Ok, obrigado pela correção, você está certo, eu devo ter misturado tudo .instance_methodporque estava passando pela memória (defeituosa)
max pleaner
10

method(:function)é um envio de mensagem (às vezes chamado de chamada de método ) para o receptor implícito (ou seja self). Está enviando a mensagem methodpara o receptor implícito (ie self), passando :functioncomo o único argumento.

:functioné um Symbolliteral, ou seja, é a notação literal de a Symbol. Symbolé um tipo de dados que representa "o nome de algo".

O operador de e comercial de prefixo unário &"desenrola" a Procem um bloco . Ou seja, permite que você passe um Proconde é esperado um bloco . Se o objeto ainda não for um Proc, será enviada a to_procmensagem permitindo que ele se converta em um Proc. (O operador é legal apenas em uma lista de argumentos e apenas para o último argumento. É o duplo do &sigilo em uma lista de parâmetros, que "rola" um bloco em um Procobjeto.)

Procé um tipo de dados que representa o código executável. É a classe principal da biblioteca de Ruby para sub-rotinas de primeira classe.

Então, o que isto significa, é chamar o methodmétodo em selfcom :functioncomo argumento, chamada to_procno valor de retorno, o que resulta "desenrolar" Procobjeto em um bloco e passar esse bloco para a chamada para integratealgo como se você tivesse escrito como

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

O methodmétodo aqui provavelmente é o Object#methodmétodo, que retorna um objeto vinculado Method .

Então, em suma, isso é um pouco equivalente a

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

Mas expresso no que é comumente chamado de estilo sem ponto .

Jörg W Mittag
fonte