Quieres un objeto proc:
gaussian = Proc.new do |dist, *args|
sigma = args.first || 10.0
...
end
def weightedknn(data, vec1, k = 5, weightf = gaussian)
...
weight = weightf.call(dist)
...
end
Solo tenga en cuenta que no puede establecer un argumento predeterminado en una declaración de bloque como esa. Por lo tanto, debe usar un símbolo y configurar el valor predeterminado en el código de proceso.
O, dependiendo del alcance de todo esto, puede ser más fácil pasar un nombre de método en su lugar.
def weightedknn(data, vec1, k = 5, weightf = :gaussian)
...
weight = self.send(weightf)
...
end
En este caso, solo está llamando a un método que está definido en un objeto en lugar de pasar un fragmento completo de código. Dependiendo de cómo lo estructura, es posible que deba reemplazarlo self.send
conobject_that_has_the_these_math_methods.send
Por último, pero no menos importante, puede colgar un bloque del método.
def weightedknn(data, vec1, k = 5)
...
weight =
if block_given?
yield(dist)
else
gaussian.call(dist)
end
end
...
end
weightedknn(foo, bar) do |dist|
# square the dist
dist * dist
end
Pero parece que le gustaría tener más fragmentos de código reutilizables aquí.
foo.bar(a,b)
con enviar, lo esfoo.send(:bar, a, b)
. El operador splat (*) le permite hacerfoo.send(:bar, *[a,b])
si desea tener una matriz alargada arbitraria de argumentos, asumiendo que el método bar puede absorberlosLos comentarios referentes a bloques y Procs son correctos en que son más habituales en Ruby. Pero puedes pasar un método si quieres. Llamas
method
para obtener el método y.call
llamarlo:fuente
method( :<name> )
solo llama una vez al convertir el nombre de su método en un símbolo invocable. Puede almacenar ese resultado en una variable o un parámetro y seguir pasándolo a funciones secundarias como cualquier otra variable a partir de ese momento ...SomewhereElse.method(:method_name)
. ¡Eso es muy bonito!:func.class
pero eso es solo unsymbol
Puede pasar un método como parámetro con
method(:function)
way. A continuación se muestra un ejemplo muy simple:fuente
method_with_function_as_param(Class.method(:method_name),...)
y nomethod(:Class.method_name)
method
. Me alegró el día pero supongo que por eso prefiero los lenguajes funcionales, no hay necesidad de hacer tales acrobacias para conseguir lo que quieres. De todos modos, me gusta el rubíLa forma normal de Ruby para hacer esto es usar un bloque.
Entonces sería algo como:
Y usado como:
Este patrón se usa ampliamente en Ruby.
fuente
Puede utilizar el
&
operador en laMethod
instancia de su método para convertir el método en un bloque .Ejemplo:
Más detalles en http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
fuente
Tienes que llamar al método "llamada" del objeto de función:
EDITAR: como se explica en los comentarios, este enfoque es incorrecto. Funcionaría si utiliza Procs en lugar de funciones normales.
fuente
weightf = gaussian
en la listagaussian
de argumentos , en realidad está tratando de ejecutar y asignar el resultado como el valor predeterminado de weightf. La llamada no tiene argumentos requeridos y se bloquea. Entonces, weightf ni siquiera es un objeto proc con un método de llamada todavía.Recomendaría usar ampersand para tener acceso a bloques con nombre dentro de una función. Siguiendo las recomendaciones dadas en este artículo , puede escribir algo como esto (esto es un fragmento real de mi programa de trabajo):
Afterwerds, puede llamar a esta función así:
Si no necesita filtrar su selección, simplemente omita el bloque:
Hasta aquí el poder de los bloques Ruby.
fuente
también puede usar "eval" y pasar el método como un argumento de cadena, y luego simplemente evaluarlo en el otro método.
fuente
eval
puede ejecutar código arbitrario, por lo que es extremadamente vulnerable a varios ataques.