Gaucheでも日本語を喋らせる(2)

「計算された未来」と言う事で、日蝕見物に大金をつぎ込んで南の島まで出かけた皆さん、 ご愁傷様でした。

私の所では、チラ見出来ました。道ゆく人が、携帯を空に向けているものだから、 私も空を仰いでみたら、見えた次第。

Googleのバナーも、日蝕モードに成っていたし、中国では、雲を吹き飛ばす大砲を 打ち上げるとか、得意の戦法で、お祭りでしたね。あと、eclipse方面の人達も、 日蝕記念バージョンとかを、出したのだろうか? 行ってみたけど それらしいのは、無かったよ。お祭り好きな人はいないのかな。

大体、何十年も先の事がぴたりと的中出来るのに、明日の天気さえ的中出来ない 現代科学技術の落差が、いとおかし。

ぴたり的中の基礎は、サロス周期に よるそうだ。明日の天気をぴたりと当てるには、蝶のはばたきまでも、考慮が必要。 だから、当たらないんです、と、ある予報官は弁明する。(かな?)

文字列の分解とひらがな化

今までは、KAKASIにその任をお願いしていたが、gauche業界での主流はmecab のようだ。時流に乗り遅れないように、mecabを使ってみる。

辞書込みのmecab-0.98pre3.exeを入れた。KAKASIと違って、辞書の在り処を設定する 必要も無いので、楽だ。(設定したのは、PATHだけ)

ちょっと試運転

c:\>mecab -O wakati
test123.45hello
test 123 . 45 hello
今日は、空を仰ぐ日です。
今日 は 、 空 を 仰ぐ 日 です 。
c:\>mecab -O yomi
今日は、空を見る日です。
キョウハ、ソラヲミルヒデス。
test123.45hello
test123.45hello

wakatiとyomiを一遍でやってくれるのが欲しいんだ。マニュアル片手に嗜好錯誤。(なかなか、 素敵な変換するなあ)

c:\>mecab --eos-format=\n --unk-format=%m\s --node-format=%pS%f[7]\s
今日は、空を仰ぐ日です。
キョウ ハ 、 ソラ ヲ アオグ ヒ デス 。
test12.345hello
test 12 . 345 hello

ちゃんとパースされて、後の処理が楽に行きそうな形になったな。

gaucheから、呼んでみる

上記を、gaucheから、呼びたい。変換前のデータを、mecabに渡し、結果をgauche界に 返してもらう事を考慮すると、使える手続きは限られてくる。また、文字コード 変換や、返り値をListにしたいと言う要望もある。

(use gauche.process)
(use gauche.charconv)

(define (trans str)
  (call-with-process-io  
  '("mecab" "--eos-format=\n" "--unk-format=%m\s" "--node-format=%pS%f[7]\s" )
   (lambda (in out)
     (display (ces-convert str 'utf-8 'sjis) out)
     (newline out)
     (flush out)
     (close-output-port out)
     (string-split (ces-convert (read-line in #t) 'sjis) " "))))

(trans "abc123def")

実験してみると、結果が返ってこない。同じコードをFreeBSDで実行すると、ちゃんと 分解されて、Listになって返ってくる。

待っている時に、Ctrl-Cで停止させると

*** UNHANDLED-SIGNAL-ERROR: unhandled signal 2 (SIGINT)
Stack Trace:
_______________________________________
  0  (sys-waitpid (process-pid process) :nohang nohang?)
        At line 235 of "c:\\app\\Gauche\\share\\gauche\\0.8.14\\lib/gauche/process.scm"
  1  (process-wait p)
        At line 337 of "c:\\app\\Gauche\\share\\gauche\\0.8.14\\lib/gauche/process.scm"
  2  h

どうやら、終了待ちのようだ。タスクマネージャで確認したら、mecabは起動してたけど 詳細なデータは取れないのかな? メニューを突付いてみたら、表示列で選べるようだ。

都合よく、PIPEへの、出入りを表示してくれるオプションは、勿論(M$の事だから) 有る訳は無い。それに、何処への出入りかも不明。DISKへか?メモリーへか? ちゃんと したマニュアルは有るのかな?

(define (call-with-process-io command proc :key ((:error err) #f)
                              (host #f) (on-abnormal-exit :error)
                              :allow-other-keys rest)
  (let* ((p (%apply-run-process command :pipe :pipe err host))
         (i (wrap-input-process-port p rest))
         (o (wrap-output-process-port p rest)))
    (unwind-protect (proc i o)
      (begin
        (close-output-port o)
        (close-input-port i)
        (process-wait p)
        (handle-abnormal-exit on-abnormal-exit p)))))

上記は、問題?の部分だけど、見えるって、いいなあ。勉強になります。 データ(終わりマークも含めて)が行かないので、ずっと待ってて、止まってる ように、gauche界からは観測される?

あれ? 終わりマークは、"\r\n" でも、"\n" でも、どちらでもいいのかな? いつも、良きに計らってもらっているから、気にした事無かったなあ。

shiroさんに相談

話は前後するけど、しゃとん経由で shiroさん、齋藤さんに相談してみた。上記は、以前、'(mecab ...)の部分を "mecab ..." としていて、醜いエラーを食らっていたのだ。

shiroさんからは、何点か調査依頼があり、PIPEの受け渡しがうまくいくかを検証した。

元になる、input.txtは、"abc123def\n"

(use gauche.process)
(let1
  p (run-process '("mecab" "-O" "wakati") :input "input.txt" :output :pipe)
 (read-line (process-output p) #t))

出力は、"abc 123 def " と、返ってきた。(報告、間違ってました。すみません)

(use gauche.process)
(let1
  p (run-process '("mecab" "-O" "wakati") :input :pipe :output "output.txt")
  (display "abc123def\n" (process-input p))
  (close-output-port (process-input p)))

こちらは、output.txt に、"abc 123 def \n" と、残っていた。

input, output の両方を PIPEにした、call-with-process-io は、read-lineで ブロックされてしまう、謎が残る結果でした。

使った環境は

でも、相談したおかげで、わけわかめな、command.com を避ける方法を教えて 頂けたし、これで、取りあえず先に進みます。

PS. しゃとんで、複数行を入力するのって、どうやるのでしょうか? Returnキーを叩くと、投稿されちゃうので、 今までは、 editorで書いておいてから、それを貼り付けてました。それが、見え々になって、ちょっと カッコ悪いです。