Вам нужен объект 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
Просто обратите внимание, что вы не можете установить аргумент по умолчанию в таком объявлении блока. Поэтому вам нужно использовать знак и установить значение по умолчанию в самом коде процедуры.
Или, в зависимости от вашего объема всего этого, может быть проще передать вместо этого имя метода.
def weightedknn(data, vec1, k = 5, weightf = :gaussian)
...
weight = self.send(weightf)
...
end
В этом случае вы просто вызываете метод, определенный для объекта, а не передаете полный фрагмент кода. В зависимости от того, как вы это структурируете, вам может потребоваться заменить self.send
наobject_that_has_the_these_math_methods.send
И последнее, но не менее важное: вы можете повесить блок на метод.
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
Но похоже, что вы хотели бы здесь больше многоразовых фрагментов кода.
foo.bar(a,b)
send, это такfoo.send(:bar, a, b)
. Оператор splat (*) позволяет вам сделать это,foo.send(:bar, *[a,b])
если вы обнаружите, что хотите иметь произвольный удлиненный массив аргументов - при условии, что метод bar может их впитатьКомментарии, относящиеся к блокам и процедурам, верны в том смысле, что они более обычны в Ruby. Но вы можете передать метод, если хотите. Вы вызываете,
method
чтобы получить метод и.call
вызвать его:источник
method( :<name> )
что при преобразовании имени метода в вызываемый символ вы вызываете только один раз. Вы можете сохранить этот результат в переменной или параметре и с этого момента продолжать передавать его дочерним функциям, как и любую другую переменную ...SomewhereElse.method(:method_name)
. Это круто!:func.class
но это простоsymbol
Вы можете передать метод как параметр с
method(:function)
way. Вот очень простой пример:источник
method_with_function_as_param(Class.method(:method_name),...)
а неmethod(:Class.method_name)
method
. Сделал свой день, но, думаю, именно поэтому я предпочитаю функциональные языки, не нужно делать такую акробатику, чтобы получить то, что вы хотите. Все равно рубин копаюОбычный способ Ruby сделать это - использовать блок.
Это будет примерно так:
И используется как:
Этот шаблон широко используется в Ruby.
источник
Вы можете использовать
&
оператор вMethod
экземпляре вашего метода, чтобы преобразовать метод в блок .Пример:
Подробнее на http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
источник
Вы должны вызвать метод "call" объекта функции:
РЕДАКТИРОВАТЬ: как объяснено в комментариях, этот подход неверен. Это сработает, если вы используете Procs вместо обычных функций.
источник
weightf = gaussian
в списке аргументов, он фактически пытается выполнитьgaussian
и назначить результат как значение по умолчанию для весаf. У вызова нет обязательных аргументов и сбоев. Итак, weightf - это еще даже не объект proc с методом вызова.Я бы рекомендовал использовать амперсанд для доступа к именованным блокам внутри функции. Следуя рекомендациям, приведенным в этой статье, вы можете написать что-то вроде этого (это настоящая вырезка из моей рабочей программы):
Afterwerds вы можете вызвать эту функцию следующим образом:
Если вам не нужно фильтровать свой выбор, вы просто опускаете блок:
Вот и все о мощи блоков Ruby.
источник
вы также можете использовать eval и передать метод как строковый аргумент, а затем просто оценить его в другом методе.
источник
eval
может выполнять произвольный код, поэтому он чрезвычайно уязвим для различных атак.