Vous voulez un objet 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
Notez simplement que vous ne pouvez pas définir d'argument par défaut dans une déclaration de bloc comme celle-ci. Vous devez donc utiliser un splat et configurer la valeur par défaut dans le code proc lui-même.
Ou, en fonction de votre portée de tout cela, il peut être plus facile de passer un nom de méthode à la place.
def weightedknn(data, vec1, k = 5, weightf = :gaussian)
...
weight = self.send(weightf)
...
end
Dans ce cas, vous appelez simplement une méthode qui est définie sur un objet plutôt que de passer un morceau complet de code. Selon la façon dont vous structurez cela , vous devrez peut - être remplacer self.send
parobject_that_has_the_these_math_methods.send
Dernier point mais non le moindre, vous pouvez suspendre un bloc de la méthode.
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
Mais il semble que vous aimeriez plus de morceaux de code réutilisables ici.
foo.bar(a,b)
avec send, c'est le casfoo.send(:bar, a, b)
. L'opérateur splat (*) vous permet de fairefoo.send(:bar, *[a,b])
si vous trouvez que vous souhaitez avoir un tableau d'arguments de longueur arbitraire - en supposant que la méthode de la barre puisse les absorberLes commentaires faisant référence aux blocs et aux processus sont corrects en ce sens qu'ils sont plus habituels dans Ruby. Mais vous pouvez passer une méthode si vous le souhaitez. Vous appelez
method
pour obtenir la méthode et.call
pour l'appeler:la source
method( :<name> )
qu'une seule fois lors de la conversion du nom de votre méthode en un symbole appelable. Vous pouvez stocker ce résultat dans une variable ou un paramètre et continuer à le transmettre aux fonctions enfants comme toute autre variable à partir de là ...SomewhereElse.method(:method_name)
. C'est plutôt cool!:func.class
mais c'est juste unsymbol
Vous pouvez passer une méthode en paramètre avec
method(:function)
way. Voici un exemple très simple:la source
method_with_function_as_param(Class.method(:method_name),...)
et nonmethod(:Class.method_name)
method
. Fait ma journée mais j'imagine que c'est pour ça que je préfère les langages fonctionnels, pas besoin de faire de telles acrobaties pour obtenir ce que l'on veut. Bref, je creuse le rubisLa manière normale de faire ceci par Ruby est d'utiliser un bloc.
Donc ce serait quelque chose comme:
Et utilisé comme:
Ce modèle est largement utilisé dans Ruby.
la source
Vous pouvez utiliser l'
&
opérateur sur l'Method
instance de votre méthode pour convertir la méthode en bloc .Exemple:
Plus de détails sur http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
la source
Vous devez appeler la méthode "call" de l'objet fonction:
EDIT: comme expliqué dans les commentaires, cette approche est erronée. Cela fonctionnerait si vous utilisez Procs au lieu des fonctions normales.
la source
weightf = gaussian
dans la liste arg, il essaie en fait d'exécutergaussian
et d'assigner le résultat comme valeur par défaut de weightf. L'appel n'a pas besoin d'arguments et de plantages. Donc weightf n'est même pas encore un objet proc avec une méthode d'appel.Je recommanderais d'utiliser une esperluette pour avoir accès aux blocs nommés dans une fonction. En suivant les recommandations données dans cet article, vous pouvez écrire quelque chose comme ceci (ceci est une vraie note de mon programme de travail):
Afterwerds, vous pouvez appeler cette fonction comme ceci:
Si vous n'avez pas besoin de filtrer votre sélection, vous omettez simplement le bloc:
Voilà pour la puissance des blocs Ruby.
la source
vous pouvez également utiliser "eval", passer la méthode en tant qu'argument de chaîne, puis simplement l'évaluer dans l'autre méthode.
la source
eval
peut exécuter du code arbitraire, il est donc extrêmement vulnérable à diverses attaques.