I am a Java programmer, and I am learning Ruby...
But I don't get where those blocks of codes can give me gain... like what's the purpose of passing a block as an argument ? why not have 2 specialized methods instead that can be reused ?
Why have some code in a block that cannot be reused ?
I would love some code examples...
Thanks for the help !
Consider some of the things you would use anonymous classes for in Java. e.g. often they are used for pluggable behaviour such as event listeners or to parametrize a method that has a general layout.
Imagine we want to write a method that takes a list and returns a new list containing the items from the given list for which a specified condition is true. In Java we would write an interface:
interface Condition {
boolean f(Object o);
}
and then we could write:
public List select(List list, Condition c) {
List result = new ArrayList();
for (Object item : list) {
if (c.f(item)) {
result.add(item);
}
}
return result;
}
and then if we wanted to select the even numbers from a list we could write:
List even = select(mylist, new Condition() {
public boolean f(Object o) {
return ((Integer) o) % 2 == 0;
}
});
To write the equivalent in Ruby it could be:
def select(list)
new_list = []
# note: I'm avoid using 'each' so as to not illustrate blocks
# using a method that needs a block
for item in list
# yield calls the block with the given parameters
new_list << item if yield(item)
end
return new_list
end
and then we could select the even numbers with simply
even = select(list) { |i| i % 2 == 0 }
Of course, this functionality is already built into Ruby so in practice you would just do
even = list.select { |i| i % 2 == 0 }
As another example, consider code to open a file. You could do:
f = open(somefile)
# work with the file
f.close
but you then need to think about putting your close
in an ensure
block in case an exception occurs whilst working with the file. Instead, you can do
open(somefile) do |f|
# work with the file here
# ruby will close it for us when the block terminates
end
The idea behind blocks is that it is a highly localized code where it is useful to have the definition at the call site. You can use an existing function as a block argument. Just pass it as an additional argument, and prefix it with an &
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With