Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the gain I can have with blocks over regular methods?

Tags:

ruby

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 !

like image 853
Cristiano Fontes Avatar asked Dec 21 '22 18:12

Cristiano Fontes


2 Answers

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
like image 140
mikej Avatar answered Mar 03 '23 13:03

mikej


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 &

like image 26
Tyler Eaves Avatar answered Mar 03 '23 11:03

Tyler Eaves