MacにVimをインストールする

Macで、日本語を扱えるVimをインストールしてみました。

Macports

日本語パッチを適用したvim-app
http://lapangan.net/darwinports/index.php?PrivatePortfile%2FVim72
をローカルポートからインストールしましたが、以下のエラーで、失敗。

Undefined symbols:
"__Xsetlocale", referenced from:
_get_locale_val in ex_cmds2.o
_ex_language in ex_cmds2.o
_ex_language in ex_cmds2.o
_ex_language in ex_cmds2.o
_main in main.o
_main in main.o
_enc_locale in mbyte.o
_DoPythonCommand in if_python.o
_DoPythonCommand in if_python.o
_DoPythonCommand in if_python.o
_mac_lang_init in os_mac_conv.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[1]: *** [Vim] Error 1
make: *** [all] Error 2

Error: Status 1 encountered during processing.

macvim-kaoriya

dmgファイルのMacVimを下記のサイトからダウンロードして、無事、インストール完了。
バイナリ形式なので、インストールもすぐ終わるのが良いところ。
http://code.google.com/p/macvim-kaoriya/downloads/list

.vimrc, .gvimrc

MS-Windowsで使用していたものをコピー。
改行コードをCRLF -> LFに変換することを忘れずに。

ターミナルからの起動

ターミナルからコマンドで起動するために、.bash_profileに下記のalisaを追加。

alias mvi="/Applications/MacVim.app/Contents/MacOS/Vim -g"

CSVファイルの処理速度比較

RubyCSVファイルを処理するときの速度を比較してみました。
CSVを解析して、配列の配列に格納する処理時間です。

テストデータ

バイト数 行数
8,438,199 byte 50,000行

結果

String#splitで単純に、パース処理をした場合

  • ruby1.8より、1.9の方が、遅い。おそらくM17Nのため。
  • mingwは、速い。
  • JRubyが一番速い。
CSVライブラリで処理した場合

  • ruby1.9が一番速い。
  • JRubyとMRI1.8は、それほど変わらない。
  • IronRubyでは、faster csvを使った方が遅い。

コード*1

require 'csv'
require 'fastercsv'
require 'benchmark'

FILE_NAME = 'csv_test.txt'

def csv_lib
  CSV.read(FILE_NAME)
end

#farster csvは、ruby1.9では、動作しない
def faster_csv
  FasterCSV.read(FILE_NAME)
end

def regexp
  data = []
  open(FILE_NAME, "r") do |file|
    file.each_line do |line|
      line.chomp!
      data << line.split(',')
    end
  end
  data
end

Rubyのバージョン

Gem CSVライブラリ

fastercsv (1.5.3)

OS

MS-Windows XP SP3

                        • -

ちなみに同じテストデータを使って、Javaでの処理速度も計測してみました。

結果

String#split() 0.593秒
opencsv 0.547秒

http://sourceforge.jp/projects/sfnet_opencsv/
ありゃ!?、split()の方が遅くなった!
まあ、計測誤差範囲ということでしょう。

コード

import java.io.*;
import java.util.*;

import au.com.bytecode.opencsv.*;

class CsvTest
{
	void split(String file) throws Exception
	{
		List<String[]> data = new ArrayList<String[]>();
		BufferedReader br = new BufferedReader(new FileReader(file));
		String line = "";
		while ((line = br.readLine()) != null)
		{
			data.add(line.split(","));
		}
		br.close();
	}

	void openCsv(String file) throws Exception
	{
		CSVReader reader = new CSVReader(new FileReader(file));
		List<String[]> data = reader.readAll();
	}
}

javaバージョン

1.6.0_17

opencsvバージョン

1.3.0

*1:ruby1.9では、fastercsvが標準ライブラリになったそうです。このため、ruby1.9では、Gem fastercsvはありません

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プログラムは、やりたいことをそのまま表現できているので、書き易いし、読み易い。
確かに、楽しいかもしれない。