Lightweight Language Lovers
PythonとRubyを比較してみる(Rubyだと日本語の扱いが楽です)
Ruby だと日本語の扱いが楽で、基本的な漢字の切り出しや機種依存の判定などは Ruby FAQ 日本語の取り扱い に
やり方が書かれてあり、実はコーディングしなくても良かったのです。 (実際、SjisChars_py.rb では
$KCODE = 'NONE' としてわざわざこの機能を殺しています。)
Python でも同様の事が可能 http://www.python.jp/Zope/articles/japanese みたいなのですが、 限られた時間では、いろいろ調べたりインストールする時間が惜しく、1から書いてしまいました。
「楽」というのは、この手間のことも言っています。
まず、
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 だと、書いてからしばらく経つと読むのが辛くなってしまいます。
また、完成するまで何度も書き直したのですが、その際、コード片をまったくためらわず消すことができました。「書いては消し」が躊躇なくできるのです。いろいろな手法が気軽に試せるのは、学習効果という面でもLLの非常に良いところです。