Estou tentando mexer um pouco com Ruby. Para tanto procuro implementar os algoritmos (dados em Python) do livro "Programming Collective Intelligence" Ruby.
No capítulo 8 o autor passa um método a como parâmetro. Isso parece funcionar em Python, mas não em Ruby.
Eu tenho aqui o método
def gaussian(dist, sigma=10.0)
foo
end
e deseja chamar isso com outro método
def weightedknn(data, vec1, k = 5, weightf = gaussian)
foo
weight = weightf(dist)
foo
end
Tudo que eu tenho é um erro
ArgumentError: wrong number of arguments (0 for 1)
fonte
foo.bar(a,b)
com o envio, éfoo.send(:bar, a, b)
. O operador splat (*) permite que você façafoo.send(:bar, *[a,b])
se quiser ter uma matriz de argumentos de comprimento arbitrário - assumindo que o método bar pode absorvê-losOs comentários referentes a blocos e Procs estão corretos por serem mais usuais em Ruby. Mas você pode passar um método, se quiser. Você chama
method
para obter o método e.call
chamá-lo:fonte
method( :<name> )
apenas uma vez ao converter o nome do seu método em um símbolo que pode ser chamado . Você pode armazenar esse resultado em uma variável ou parâmetro e continuar passando para funçõesSomewhereElse.method(:method_name)
. Isso é bem legal!:func.class
mas é apenas umsymbol
Você pode passar um método como parâmetro com
method(:function)
way. Abaixo está um exemplo muito simples:fonte
method_with_function_as_param(Class.method(:method_name),...)
e nãomethod(:Class.method_name)
method
. Fez meu dia, mas acho que é por isso que prefiro linguagens funcionais, não há necessidade de fazer tais acrobacias para conseguir o que deseja. Enfim, eu escavo o rubiA maneira normal do Ruby de fazer isso é usar um bloco.
Então, seria algo como:
E usado como:
Este padrão é usado extensivamente em Ruby.
fonte
Você pode usar o
&
operador naMethod
instância do seu método para converter o método em um bloco .Exemplo:
Mais detalhes em http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
fonte
Você deve chamar o método "call" do objeto de função:
EDITAR: conforme explicado nos comentários, essa abordagem está errada. Funcionaria se você estiver usando Procs em vez de funções normais.
fonte
weightf = gaussian
na lista de argumentos, ele está na verdade tentando executargaussian
e atribuir o resultado como o valor padrão de weightf. A chamada não requer argumentos e travamentos. Portanto, weightf ainda não é um objeto proc com um método de chamada.Eu recomendaria usar o e comercial para ter acesso a blocos nomeados dentro de uma função. Seguindo as recomendações fornecidas neste artigo, você pode escrever algo assim (este é um recado real do meu programa de trabalho):
Depois de responder, você pode chamar essa função assim:
Se você não precisa filtrar sua seleção, simplesmente omite o bloco:
Tanto para o poder dos blocos Ruby.
fonte
você também pode usar "eval" e passar o método como um argumento de string e, em seguida, simplesmente evalá-lo no outro método.
fonte
eval
pode executar código arbitrário, por isso é extremamente vulnerável a vários ataques.