Rubyが楽しいってどういうこと!?

RubyのHP http://www.ruby-lang.org/ja/ には、A Programmer's Best Friendと書いてある。
Rubyは楽しい、という話もよく耳にするがどういうことなのだろうか?

よく見かける例として、

3.times { print "hello\n" }

がある。
まるで、英語のように書ける!というが、いまいちピンとこない。
日本語を母国語としている私には関係ないし、プログラミングをする人で、for文を知らない人はいないだろう。

そこで、もう少し実践的な例で、楽しさを考えてみたい。
こんな、Javaのコードがあった。

public class Hoge
{
    private static final String SEP = " - ";
    private String _a;
    /**
     * _aが存在する場合のみ存在する。
     */
    private String _b;
    /**
     * _bが存在する場合のみ存在する。
     */
    private String _c;
    /**
     * _cが存在する場合のみ存在する。
     */
    private String _d;
    /**
     * _dが存在する場合のみ存在する。
     */
    private String _e;

    /**
     * @return a, b, c, d, eを連結した文字列
     */
    public String getFoo()
    {
      StringBuffer result = new StringBuffer();
      if(_a != null)
      {
        result.append(_a);
      }
      if(_b != null)
      {
        result.append(SEP);
        result.append(_b);
      }
      if(_c != null)
      {
        result.append(SEP);
        result.append(_c);
      }
      if(_d != null)
      {
        result.append(SEP);
        result.append(_d);
      }
      if(_e != null)
      {
        result.append(SEP);
        result.append(_e);
      }

      return result.toString();
    }

    //_a, ... _eのsetter/getter
    public void setA(String a)
    {
      _a = a;
    }
    public void setB(String b)
    {
      _b = b;
    }
    public void setC(String c)
    {
      _c = c;
    }
    public void setD(String d)
    {
      _d = d;
    }
    public void setE(String e)
    {
      _e = e;
    }
}

これを単純にRubyで書き換えてみると、次のようになる。
attr_accessorは、便利だけど、特に何も変わらない。

class Hoge
  #rubyはsetter/getterを以下のように書ける
  attr_accessor :a, :b, :c, :d, :e

  SEP = " - ";

  def foo
    result = ''
    if(@a != nil)
      result.concat(@a)
    end
    if(@b != nil)
      result.concat(SEP)
      result.concat(@b)
    end
    if(@c != nil)
      result.concat(SEP)
      result.concat(@c)
    end
    if(@d != nil)
      result.concat(SEP)
      result.concat(@d)
    end
    if(@e != nil)
      result.concat(SEP)
      result.concat(@e)
    end
    return result
  end
end

もう少し、Rubyの構文を活用してみると、多少読み易くなる。
しかし、特に楽しい!という訳ではない。

class Hoge
  attr_accessor :a, :b, :c, :d

  SEP = " - ";

  def foo
    result = ''
    if(@a) #nilはfalseと評価される
      result << @a # << は、concatと同意語
    end
    if(@b)
      result << SEP
      result << @b
    end
    if(@c)
      result << SEP
      result << @c
    end
    if(@d)
      result << SEP
      result << @d
    end
    if(@e)
      result << SEP
      result << @e
    end
    result #メソッドは、必ず戻り値を返す。最後に評価された式が戻り値となる。
  end
end

Rubyっぽく書いてみると、だいぶ、短く書ける。

class Hoge
  attr_accessor :a, :b, :c, :d

  SEP = " - ";

  def foo
    [@a, @b, @c, @d, @e].compact.join(SEP)
  end
end

しかし、読みにくくなっては意味がない。
読んでみよう。

fooメソッドでやりたいことは、「@a, @b, ... を" - "で繋げた文字を返す」ことだ。
つまり、

  1. @a, @b, ...を順番に並べて、
  2. nilは、含まないようにして、
  3. " - "で連結する。

ということになる。rubyコードを読んでみると、

  1. [ ] : 並べる。 [ ]はArray(配列)のリテラル表記。
  2. Array#compact : コンパクトにする、compactは、Array中のnilを削除したArrayを返す。
  3. Array#join(sep) : 連結する。要素をsepで連結した文字列を返す。

上記のRubyプログラムは、やりたいことをそのまま表現できているので、書き易いし、読み易い。
確かに、楽しいかもしれない。