I am trying to mess around a little bit with Ruby. Therefor I try to implement the algorithms (given in Python) from the book "Programming Collective Intelligence" Ruby.
In chapter 8 the author passes a method a as parameter. This seems to work in Python but not in Ruby.
I have here the method
def gaussian(dist, sigma=10.0)
foo
end
and want to call this with another method
def weightedknn(data, vec1, k = 5, weightf = gaussian)
foo
weight = weightf(dist)
foo
end
All I got is an error
ArgumentError: wrong number of arguments (0 for 1)
I would recommend to use ampersand to have an access to named blocks within a function. Following the recommendations given in this article you can write something like this (this is a real scrap from my working program):
Afterwerds, you can call this function like this:
If you don't need to filter your selection, you simply omit the block:
So much for the power of Ruby blocks.
The comments referring to blocks and Procs are correct in that they are more usual in Ruby. But you can pass a method if you want. You call
method
to get the method and.call
to call it:You want a proc object:
Just note that you can't set a default argument in a block declaration like that. So you need to use a splat and setup the default in the proc code itself.
Or, depending on your scope of all this, it may be easier to pass in a method name instead.
In this case you are just calling a method that is defined on an object rather than passing in a complete chunk of code. Depending on how you structure this you may need replace
self.send
withobject_that_has_the_these_math_methods.send
Last but not least, you can hang a block off the method.
But it sounds like you would like more reusable chunks of code here.
You can pass a method as parameter with
method(:function)
way. Below is a very simple example:You can use the
&
operator on theMethod
instance of your method to convert the method to a block.Example:
More details at http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
You have to call the method "call" of the function object:
EDIT: as explained in the comments, this approach is wrong. It would work if you're using Procs instead of normal functions.