Lightweight Language Lovers
PythonとRubyを比較してみる(Rubyだと日本語の扱いが楽です)
Ruby だと日本語の扱いが楽で、基本的な漢字の切り出しや機種依存の判定などは Ruby FAQ 日本語の取り扱い に
やり方が書かれてあり、実はコーディングしなくても良かったのです。
(実際、SjisChars_py.rb では $KCODE = 'NONE' としてわざわざこの機能を殺しています。)
しかし、特徴をつかむことが目的ですから、ここでは日本語の扱いなどをみてみます。
まず、
class SjisChars $KCODE = "SJIS" KU13 = 0x8740..0x879c KU89_92 = 0xED40..0xEEFC KU115_9 = 0xFA40..0xFC4B GAIJI = 0xF040..0xF9FC
ですが、$KODE で漢字コードを設定しておくことが出来ます。これにより2バイト文字を解釈してくれます。
from..to で、コードの範囲を範囲オブジェクトとして定義しています。定数は大文字で始めます。
def initialize(chars)
@chars = chars
@reKisyu = mkRegexp(KU13, KU89_92, KU115_9)
@reGaiji = mkRegexp(GAIJI)
end
def mkRegexp(*ra)
ra.map! {|r| "[%s-%s]" % [[r.first].pack("n"), [r.last].pack("n")]}
Regexp.compile(ra.join("|"))
end
初期化の部分で、インスタンス変数の設定と、コード範囲を表す正規表現オブジェクトの生成を行っています。 Ruby FAQ を見ると、正規表現に漢字を使うことができるがわかります。
コード範囲から、/[始-終]|[始-終]|../ の正規表現を得るのが目的です。
- ra.map! ... 配列の各要素(コード範囲)に{ }を適用して更新
- {|r| }... それぞれのコード範囲(r)について、先頭(r.first)と最後(r.last)を数値から漢字に変換(ネットワークバイトオーダー("n")でpack)後、[始-終]の形に編集("[%s-%s]" %)
- [%s-%s]それぞれを | で join して目的とする正規表現に変換(Regexp.compile)
def scanSjis
@chars.split(//).each {|c| yield c, isKanji(c), isGaiji(c), isKisyu(c)}
end
def isKanji(c)
c.length == 2
end
def isGaiji(c)
@reGaiji.match(c) != nil
end
def isKisyu(c)
@reKisyu.match(c) != nil
end
は、文字列から漢字を考慮して切り出して(split(//))、判定しながら yield しています。
ここは、文字列.scan(正規表現) を使うと簡単なのですが、他のプログラムに組み込んで使う場合、 順序を保ったまま判定結果が返ってきたほうが良いので、このようにしています。
hexprint はおまけです。
あと、isKanji 等も1行で書いてしまえるので、もっと短くしようと思えば出来るのですが、可読性を高めるためある程度のところで止めています。
一番の感想は、「しばらく経ってから見ても読むのが苦にならない」ということです。
構文の細かな部分はともかく、文法的なノイズが少ないので文書を読む感覚で、アウトラインを把握するのが楽です。私は、Java だと、書いてからしばらく経つと読むのが辛くなってしまいます。