<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>metaclass &#187; Benefits of Blocks Series</title>
	<atom:link href="http://www.learnruby.com/blog/category/programming/benefits-of-blocks-series/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.learnruby.com/blog</link>
	<description>reflections on Ruby, Learning, etc.</description>
	<lastBuildDate>Wed, 15 Jul 2009 21:59:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Blocks: Not Just Twisted Loops/Iterators, part 2</title>
		<link>http://www.learnruby.com/blog/2008/09/03/blocks-not-just-twisted-loopsiterators-part-2/</link>
		<comments>http://www.learnruby.com/blog/2008/09/03/blocks-not-just-twisted-loopsiterators-part-2/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 01:47:47 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Benefits of Blocks Series]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.learnruby.com/blog/?p=87</guid>
		<description><![CDATA[In the previous post in this series, I attempted to demonstrate some of the basic benefits of blocks by showing examples of listing, filtering, mapping, and sorting in Ruby and in Java.
In general, the Java solutions had to do most of the work themselves with their own loop constructs.  However the sorting example was [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.learnruby.com/blog/2008/08/24/blocks-not-just-twisted-loopsiterators-part-1/">previous post in this series</a>, I attempted to demonstrate some of the basic benefits of blocks by showing examples of listing, filtering, mapping, and sorting in Ruby and in Java.</p>
<p>In general, the Java solutions had to do most of the work themselves with their own loop constructs.  However the sorting example was a little different.  In Java we were able to pass some code into the Collections.sort method using Java&#8217;s anonymous inner classes.  So anonymous inner classes are somewhat close to Ruby&#8217;s blocks, at least as close as we can get.</p>
<p>With Collections.sort, there was a Comparator interface that we implemented in-line.  So if we want to see how close we can get with Java, we&#8217;ll have to create our own interface(s) for the methods we want to supply in-line and a class to hold the main logic in a series of class (i.e., <i>static</i>) methods.  We&#8217;ll create that infrastructure once and then be able to use it repeatedly.</p>
<p>To outline the plan, we will do two things: create an interface for each type of function we&#8217;ll be performing on a collection, and create a class &#8212; <i>Iterations</i> &#8212; to hold the static utility methods that perform the basic functionality.</p>
<p>Recall that for comparison purposes we had Ruby and Java versions of our Account class and a way to generate test accounts.  You can get those details in the <a href="http://www.learnruby.com/blog/2008/08/24/blocks-not-just-twisted-loopsiterators-part-1/">previous post</a>.</p>
<p><b>Listing</b></p>
<p>Let&#8217;s start out with the listing task.  We&#8217;ll first need our infrastructure &#8212; an interface that supports doing something to each element of a collection.</p>
<pre name="code" class="java">
public interface EachFunction&lt;T>
{
    public void perform(T value);
}
</pre>
<p>Note that we are using Java&#8217;s generics, so this will work in a &#8220;type-safe&#8221; manner as possible.</p>
<p>And in our Iterations class, we&#8217;ll add the following method:</p>
<pre name="code" class="java">
    public static&lt;T> void each(Collection&lt;T> inputs, EachFunction&lt;T> function)
    {
        for (T value : inputs) {
            function.perform(value);
        }
    }
</pre>
<p>As you can see, the each method takes a collection and a class (in our example we&#8217;ll use an anonymous inner class) that implements the EachFunction interface.  </p>
<p>With our one-time-only infrastructure in place, we can display a list of all the members in a collection with this code:</p>
<pre name="code" class="java">
        Iterations.each(accounts,
                        new EachFunction&lt;Account>() {
                            public void perform(Account a) {
                                System.out.println(a);
                            }
                        });
 </pre>
<p>Let&#8217;s compare it to our Ruby solution:</p>
<pre name="code" class="ruby">
  accounts.each do |account|
    puts account
  end
</pre>
<p>So the concept is the same.  However, the syntax requirements is far heavier on the Java side.  And, in the case of Ruby, the functionality for each is built into the Array class, where with Java we&#8217;re required to create a separate and clunky class full of static methods to house the functionality, which moves us away from a pure object-oriented implementation.</p>
<p><b>Selecting</b></p>
<p>We&#8217;ll see a similar pattern with the selecting.  We&#8217;ll start off with our interface that will allow us to convey our selection criteria:</p>
<pre name="code" class="java">
public interface SelectCondition&lt;T>
{
    public boolean isSelected(T value);
}
</pre>
<p>We&#8217;ll create our utility method in the Iterations class:</p>
<pre name="code" class="java">
    @SuppressWarnings("unchecked")
    public static &lt;T> Collection&lt;T> select(Collection&lt;T> inputs,
                                           SelectCondition&lt;T> condition)
    {
        try {
            Collection&lt;T> outputs = inputs.getClass().newInstance();
            for (T value : inputs) {
                if (condition.isSelected(value)) {
                    outputs.add(value);
                }
            }
            return outputs;
        } catch(Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }
</pre>
<p>We&#8217;re doing something somewhat tricky in creating a new collection to return to the caller.  We take the collection passed in, ask for its class, and then call <i>newInstance</i> on it.  Because the type information for generics is only kept at compile time &#8212; and lost at runtime (due to <a href="http://java.sun.com/docs/books/tutorial/java/generics/erasure.html">type erasure</a>) &#8212; the runtime types in the assignment cannot be assured.  So, to avoid a compiler warning we must add the <i>SupressWarnings</i> annotation.</p>
<p>Also, the call to <i>newInstance</i> can throw either <i>InstantiationException</i> or <i>IllegalAccessException</i>.  So the caller is not forced to deal with these exceptions, we&#8217;ll catch them ourselves and throw <i>UnsupportedOperationException</i>, which, being a descendent of <i>RuntimeException<i> does <i>not have to be</i> explicitly handled by the caller.</p>
<p>Finally, here&#8217;s our code to select those accounts with large balances:</p>
<pre name="code" class="java">
        Collection&lt;Account> bigAccounts =
            Iterations.select(accounts,
                              new SelectCondition&lt;Account>() {
                                  public boolean isSelected(Account a) {
                                      return a.balance >= 10000;
                                  }
                              });
</pre>
<p>And again, for comparison purposes, here&#8217;s the Ruby version:</p>
<pre name="code" class="ruby">
  big_accounts = accounts.select { |account| account.balance >= 10000 }
</pre>
<p><b>Mapping</b></p>
<p>Even though the pattern is pretty clear, for the sake of completeness, and in order to generate a nice package of functionality for Java programmers, let&#8217;s complete our task, first with mapping and finally with a Java version of <i>sort_by</i>.</p>
<p>The interface for mapping describes a method that takes input of one type and returns data of a type that can be different:</p>
<pre name="code" class="java">
public interface MapFunction&lt;InputT, OutputT>
{
    public OutputT mapOf(InputT value);
}
</pre>
<p>The utility method in the Iterations class for mapping:</p>
<pre name="code" class="java">
    @SuppressWarnings("unchecked")
    public static &lt;InputT, OutputT>
        Collection&lt;OutputT> map(Collection&lt;InputT> inputs,
                                MapFunction&lt;InputT, OutputT> mapper)
    {
        try {
            Collection&lt;OutputT> outputs = inputs.getClass().newInstance();
            for (InputT value : inputs) {
                outputs.add(mapper.mapOf(value));
            }
            return outputs;
        } catch(Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }
</pre>
<p>And some code that does mapping with the above infrastructure, turning a Collection of accounts to a collection of strings containing the holders&#8217; first names:</p>
<pre name="code" class="java">
        Collection&lt;String> firstNames =
            Iterations.map(accounts,
                           new MapFunction&lt;Account, String>() {
                               public String mapOf(Account account) {
                                   int firstSpace = account.holder.indexOf(' ');
                                   String firstName = account.holder.substring(0, firstSpace);
                                   return firstName;
                               }
                           });
</pre>
<p>And here, again, is the Ruby equivalent:</p>
<pre name="code" class="ruby">
  first_names = accounts.map { |account|
    first_space = account.holder.index(' ')
    account.holder.slice(0...first_space)
  }
</pre>
<p><b>Sorting</b></p>
<p>Ruby collections offer a <i>sort_by</i> method that comes in handy.  When the data being sorted is a bundle of data, you can use sort_by to extract part of the bundle as the sorting key.  Alternatively, you can calculate new data to sort by.</p>
<p>Interestingly, we do not need a new interface since we can use the same interface we used for mapping.  The mapping function will take an element of the collection and return data that will be used as that element&#8217;s <i>sort key</i>.  And that sort key could be of a different type.</p>
<p>To make this sort_by work, we&#8217;ll actually create new data type &#8212; <i>ComparablePair</i> &#8212; that associates a collection element with its sort key.  We put these ComparablePairs into a TreeSet, which is a sorted data structure, and then extract the elements in the sorted order and put them into a collection that is returned to the caller.</p>
<p>So here is our ComparablePair:</p>
<pre name="code" class="java">
    static class ComparablePair&lt;SortT extends Comparable&lt;SortT>, DataT>
        implements Comparable&lt;ComparablePair&lt;SortT, DataT>>
    {
        SortT sortValue;
        DataT dataValue;

        ComparablePair(SortT sortValue, DataT dataValue)
        {
            this.sortValue = sortValue;
            this.dataValue = dataValue;
        }

        public int compareTo(ComparablePair&lt;SortT, DataT> other)
        {
            return sortValue.compareTo(other.sortValue);
        }
    }
</pre>
<p>And here&#8217;s the code that creates the ComparablePairs, puts them in a TreeSet, which sorts the data as it&#8217;s inserted, and extracts the data from the TreeSet in sorted order and puts them in a new collection, that is finally returned:</p>
<pre name="code" class="java">
    @SuppressWarnings("unchecked")
    public static &lt;DataT, SortT extends Comparable&lt;SortT>>
        List&lt;DataT> sortBy(List&lt;DataT> inputs,
                           MapFunction&lt;DataT, SortT> sortMapper)
    {
        try {
            // do this first so exceptions generated as soon as possible
            List&lt;DataT> sortedList = inputs.getClass().newInstance();

            // sort the data (in pairs) by putting them into a sorted set
            TreeSet&lt;ComparablePair&lt;SortT, DataT>> sortedSet =
                new TreeSet&lt;ComparablePair&lt;SortT, DataT>>();
            for (DataT value : inputs) {
                ComparablePair&lt;SortT, DataT> sortable =
                    new ComparablePair&lt;SortT, DataT>(sortMapper.mapOf(value),
                                                     value);
                sortedSet.add(sortable);
            }

            // pull the sorted data out and put in our result list
            for (ComparablePair&lt;SortT, DataT> pair : sortedSet) {
                sortedList.add(pair.dataValue);
            }

            return sortedList;
        } catch(Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }
</pre>
<p>With that infrastructure in place, we can now sort the accounts by balance:</p>
<pre name="code" class="java">
        Collection&lt;Account> accountsByBalance =
            Iterations.sortBy(accounts,
                              new MapFunction&lt;Account, Double>() {
                                  public Double mapOf(Account a) {
                                      return a.balance;
                                  }
                              });
</pre>
<p>or, alternatively by the holder&#8217;s name:</p>
<pre name="code" class="java">
        Collection&lt;Account> accountsByName =
            Iterations.sortBy(accounts,
                              new MapFunction&lt;Account, String>() {
                                  public String mapOf(Account a) {
                                      return a.holder;
                                  }
                              });
</pre>
<p>And here are the two Ruby equivalents for sorting by balance:</p>
<pre name="code" class="ruby">
accounts_by_balance = accounts.sort_by { |account| account.balance }
</pre>
<p>and by holder&#8217;s name:</p>
<pre name="code" class="ruby">
accounts_by_holder = accounts.sort_by { |account| account.holder }
</pre>
<p><b>Conclusions</b></p>
<p>I find it interesting that by building a bit of infrastructure in the form of some basic interfaces and a class of utility methods, we can approach <i>the Ruby way</i> in Java.  It&#8217;s not perfect, though.  The syntax is not as nice, it&#8217;s a bit clunky to have to put all this code in a utility class, and we do have to suppress some compiler warnings.  However I&#8217;m pleased with the result.  It does show that Java has some features worth appreciating, but it also makes clear, I think, the role of Ruby&#8217;s blocks along with their benefits.</p>
<p>If you would like to see the full source code for these examples, the <a href='http://www.learnruby.com/blog/wp-content/uploads/2008/09/blocks-ruby-examples.zip'>Ruby source</a> and the <a href='http://www.learnruby.com/blog/wp-content/uploads/2008/09/blocks-java-examples.zip'>Java source code</a> can be downloaded as zip files.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.learnruby.com/blog/2008/09/03/blocks-not-just-twisted-loopsiterators-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blocks: Not Just Twisted Loops/Iterators, part 1</title>
		<link>http://www.learnruby.com/blog/2008/08/24/blocks-not-just-twisted-loopsiterators-part-1/</link>
		<comments>http://www.learnruby.com/blog/2008/08/24/blocks-not-just-twisted-loopsiterators-part-1/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 23:39:27 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Benefits of Blocks Series]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.learnruby.com/blog/?p=16</guid>
		<description><![CDATA[As my interest in Ruby was growing, a friend, who&#8217;d read the pickaxe book, told me that not only did he not find blocks all that compelling, he felt they inverted control in an odd, inelegant way.  I think he was saying that the code that should go on the &#8220;inside&#8221; was instead on [...]]]></description>
			<content:encoded><![CDATA[<p>As my interest in Ruby was growing, a friend, who&#8217;d read the pickaxe book, told me that not only did he not find blocks all that compelling, he felt they inverted control in an odd, inelegant way.  I think he was saying that the code that should go on the &#8220;inside&#8221; was instead on the &#8220;outside&#8221;, and that somehow it was a bad programming practice.</p>
<p>But this view fails to appreciate one of the great contributions of functional programming, that functions (code) can be data.  But you don&#8217;t have to wrap your mind around functional programming and ideas such as first class functions to appreciate blocks.  And I hope to make the point by calling upon practical examples rather than theory.</p>
<p>In this sequence of posts I will compare and contrast how you&#8217;d do things with Ruby&#8217;s blocks and how you&#8217;d do the same thing in some other, more popular programming languages.</p>
<p>I&#8217;ve will look at four ways collections are processed in Ruby with blocks:</p>
<ul>
<li>listing</li>
<li>filtering</li>
<li>mapping</li>
<li>sorting</li>
</ul>
<p>And for this post I will be comparing Ruby with Java.  Now of course there are generally multiple ways to do things in most programming languages.  With respect to the Java examples, I&#8217;ll use the more standard or obvious Java solutions.  In subsequent posts in this sereis, though, I&#8217;ll look at some Java alternatives and examine at least one additional language.</p>
<p><strong>Ruby Supporting Code</strong></p>
<p>We&#8217;ll need some data to manipulate, so let&#8217;s assume we have an Account class that models an account one might have at a bank.</p>
<pre name="code" class="ruby">
class Account
  attr_reader :number, :balance
  attr_accessor :holder

  def initialize number, balance, holder
    @number, @balance, @holder = number, balance, holder
  end

  def to_s
    @number.to_s + " : $" + format("%0.2f", @balance) + " (" + @holder + ")"
  end
end
</pre>
<p>And let&#8217;s provide a method that returns some test data:</p>
<pre name="code" class="ruby">
def get_test_accounts
  [
    Account.new(112111, 55000.00, "Moe Howard"),
    Account.new(161112, 75000.00, "Larry Fine"),
    Account.new(117113,  -100.00, "Shemp Howard"),
    Account.new(111814,   175.50, "Curly Howard"),
    Account.new(111195,  2500.00, "Joe Besser"),
    Account.new(111116, 56000.00, "Curly-Joe DeRita"),
  ]
end
</pre>
<p><strong>Java Supporting Code</strong></p>
<p>Now let&#8217;s provide the same supporting code in Java.  Here&#8217;s the Account class:</p>
<pre name="code" class="java">
public class Account
{
    int number;
    double balance;
    String holder;

    static final DecimalFormat balanceFormatter = new DecimalFormat("0.00");

    public Account(int number, double balance, String holder)
    {
        this.number = number;
        this.balance = balance;
        this.holder = holder;
    }

    public String toString()
    {
        return number + " : $" + balanceFormatter.format(balance) + " (" + holder + ")";
    }

    public int    getNumber()               { return number; }
    public double getBalance()              { return balance; }
    public String getHolder()               { return holder; }
    public void   setHolder(String holder)  { this.holder = holder; }
}
</pre>
<p>And here&#8217;s the code that supplies some test data (note: this code can return the data in the form of an Array, ArrayList, or HashSet):</p>
<pre name="code" class="java">
public class TestAccounts
{
    private static Account[] accountArray = {
        new Account(112111, 55000.00, "Moe Howard"),
        new Account(161112, 75000.00, "Larry Fine"),
        new Account(117113,  -100.00, "Shemp Howard"),
        new Account(111814,   175.50, "Curly Howard"),
        new Account(111195,  2500.00, "Joe Besser"),
        new Account(111116, 56000.00, "Curly-Joe DeRita") };

    private static List&lt;Account&gt; accountList = Arrays.asList(accountArray);

    public static Account[] getArray()
    {
        return accountArray;
    }

    public static ArrayList&lt;Account&gt; getArrayList()
    {
        return new ArrayList&lt;Account&gt;(accountList);
    }

    public static HashSet&lt;Account&gt; getHashSet()
    {
        return new HashSet&lt;Account&gt;(accountList);
    }
}
</pre>
<p><strong>Listing</strong></p>
<p>With the supporting code in hand, our first task will simply be to display all the accounts in the array.  And with blocks we end up with code like this:</p>
<pre name="code" class="ruby">
  accounts = get_test_accounts

  puts "List of all accounts:"
  accounts.each do |account|
    puts account
  end
</pre>
<p>And of course we could have done the same thing with one of Ruby&#8217;s loop constructs as well.</p>
<p>How could we code this in Java?  Well, there are a couple of ways.  In this post I will focus on using Java&#8217;s loop constructs, but in my next post on this topic I&#8217;ll demonstrate another way of approaching this in Java.  Here, though, is the loop example:</p>
<pre name="code" class="java">
        ArrayList&lt;Account&gt; accounts = TestAccounts.getArrayList();

        System.out.println("List of all accounts:");
        for (Account account : accounts) {
            System.out.println(account);
        }
</pre>
<p>There really isn&#8217;t much of a difference.  Pretty much six of one and half-a-dozen of the other.</p>
<p>But blocks aren&#8217;t only used as simple iterators, and by looking at these other uses we&#8217;ll get the opportunity to highlight the power of blocks.</p>
<p><strong>Filtering</strong></p>
<p>What if we wanted to generate a list of those accounts with balances that are at least $10,000?  Well here&#8217;s the Ruby code to do this, which uses Enumerable&#8217;s select method:</p>
<pre name="code" class="ruby">
  big_accounts = accounts.select { |account| account.balance &gt;= 10000 }
</pre>
<p>In Java, using loops, we have a little more work to do, work that Enumerable#select has built into it.  We need to create a collection to hold the result and manually insert the accounts that meet the criteria into this new collection:</p>
<pre name="code" class="java">
        ArrayList&lt;Account&gt; bigAccounts = new ArrayList&lt;Account&gt;();
        for (Account account : accounts) {
            if (account.balance &gt;= 10000) {
                bigAccounts.add(account);
            }
        }
</pre>
<p>Here the difference between the two languages is more significant.  Filtering in Ruby can be a one-liner, where in Java we have to do quite a bit:</p>
<ul>
<li>create the filtered collection</li>
<li>loop through the elements in the original collection</li>
<li>selectively add items to the filtered collection</li>
</ul>
<p><strong>Mapping</strong></p>
<p>Our next task will be mapping, sometimes called collecting, in which we take one collection of data and make a new collection of data through a mapping process.</p>
<p>For this task we will convert our array of Accounts to an array of Strings containing the holders first names, which we will determine by extracting all characters from the beginning of the string up to, but not including, the first space character.</p>
<p>So here is the Ruby code:</p>
<pre name="code" class="ruby">
  first_names = accounts.map { |account|
    first_space = account.holder.index(' ')
    account.holder.slice(0...first_space)
  }
</pre>
<p>And here&#8217;s the equivalent Java code:</p>
<pre name="code" class="java">
        ArrayList&lt;String> firstNames = new ArrayList&lt;String>();
        for (Account account : accounts) {
            int firstSpace = account.holder.indexOf(' ');
            String firstName = account.holder.substring(0, firstSpace);
            firstNames.add(firstName);
        }
</pre>
<p>The difference here is a little less obvious given that the internal logic is a little more complicated than in the filtering example above.  But those same three additional steps are required &#8212; creating the destination collection, looping through the elements in the original collection, and manually adding items to the destination collection.</p>
<p><strong>Sorting</strong></p>
<p>Finally we will look at sorting our data by various criteria &#8212; first by account balance and then by the holder&#8217;s name.</p>
<p>Ruby:</p>
<pre name="code" class="ruby">
  accounts_by_balance = accounts.sort_by { |account| account.balance }
</pre>
<p>and:</p>
<pre name="code" class="ruby">
  accounts_by_holder = accounts.sort_by { |account| account.holder }
</pre>
<p>With Java we have a little more work to do.  The Collections class has a sort method.  And that method can either sort the data in one of two ways.  If the data in the collection is inherently comparable (i.e., implements the Comparable interface) and that is the order that we want, then we just call sort.  But if we want to sort the data in different ways, then we must supply a Comparator that tells the sort method the ordering of two specific items.  We can either create a Comparator class and pass an instance of it in, or we can supply an anonymous inner class.  In order to better approximate Ruby&#8217;s way of doing this, we&#8217;ll use the anonymous inner class.</p>
<p>Java:</p>
<pre name="code" class="java">
        // copy accounts array and sort the copy
        List&lt;Account> accountsByBalance = new ArrayList&lt;Account>(accounts);
        Collections.sort(accountsByBalance,
                         new Comparator&lt;Account>() {
                             public int compare(Account a1, Account a2) {
                                 return Double.compare(a1.balance, a2.balance);
                             }
                         });
</pre>
<p>and:</p>
<pre name="code" class="java">
        // copy accounts array and sort the copy
        List&lt;Account> accountsByHolder = new ArrayList&lt;Account>(accounts);
        Collections.sort(accountsByHolder,
                         new Comparator&lt;Account>() {
                             public int compare(Account a1, Account a2) {
                                 return a1.holder.compareTo(a2.holder);
                             }
                         });
</pre>
<p>Here the difference is pretty significant.  With Java there is a lot of syntactic overhead compared to the Ruby one-liners.  Now if we needed to do these sorts frequently, we would not use the anonymous inner class.  We would instead create a regular Comparator class for each type of sort, and then pass instances into Collections.sort.  So the code overhead is there for the first time the sort is needed, but that cost is amortized with each additional time that sort is needed.</p>
<p><strong>Conclusions</strong></p>
<p>I think a few points become apparent when comparing these examples.  First, and perhaps most obviously, the Ruby code ends up being shorter.  The second point addresses why.  The Ruby methods that take blocks have all the common code in them &#8212; the code to iterate through the elements of the array along with the code to create the new collection in which the data will be placed.  In the Java examples, it&#8217;s typically the case that the the programmer is responsible for those tasks, so the programmer ends up repetitively writing the code for them.</p>
<p>So yes, my friend is correct in that there is a bit of inverting the inside/outside in Ruby.  But it&#8217;s there for a purpose.  When the outside remains fixed and the inside changes, we want a way to supply the inside from the &#8220;outside&#8221;.  And blocks provide a nice way to do this.</p>
<p><b><i>Update</i></b></p>
<p><a href="http://www.learnruby.com/blog/2008/09/03/blocks-not-just-twisted-loopsiterators-part-2/">Part 2 of this sequence</a> is available.</p>
<p>If you would like to see the full source code for these examples, the <a href='http://www.learnruby.com/blog/wp-content/uploads/2008/09/blocks-ruby-examples.zip'>Ruby source</a> and the <a href='http://www.learnruby.com/blog/wp-content/uploads/2008/09/blocks-java-examples.zip'>Java source code</a> can be downloaded as zip files.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.learnruby.com/blog/2008/08/24/blocks-not-just-twisted-loopsiterators-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
