2007/08/20

先週、2004年ごろには Gauche に KAKAI のライブラリがあったらしいとか書いたけど、sourceforge のページから今でもダウンロードできると shiro さんに教えていただいた。ありがとうございます。(そして、ろくに確認せず適当なことを書いていてすみません。)

しかもインストールしたら使えた。
(use text.kakasi)
(kakasi-begin :JH :p)
(display (kakasi-convert "素子"))
(newline)
(kakasi-end)
これを kakasi-trial.scm とすると、
$ gosh -V
Gauche scheme interpreter, version 0.8.10 [utf-8,pthreads]
$ gosh kakasi-trial.scm
{もとこ|そし}

2007/08/17

[2010年6月3日 追記]改良版はこちら

emacs で、検索パターンをその後の編集中ずっとハイライトにしたい。インクリメンタルサーチの結果でもハイライトされるけど、あれだと編集をはじめるとハイライトが解除されてしまうので、使えない。
具体的には、作業中のバッファであるパターンを一時的にハイライトして、それを確認しながらを作業するための方法がほしい。こんな具合。

highlight

この例は、 ja タグで囲まれた部分をハイライトするようにしたところ。普段はハイライト不要なんだけど、たとえば「 ja にも en にも出てくる語を検索して周辺の文章を編集したいんだけど en 内にあるほうは無視してもいいや」といった作業に便利じゃない?

で、とりあえず作ってみた関数。
;;; let designated pattern be highlight
(defun highlight-regexp (re)
(interactive "sRegexp: \n")
(make-face 'my-highlight-face)
(set-face-foreground 'my-highlight-face "black")
(set-face-background 'my-highlight-face "yellow")
(defvar my-highlight-face 'my-highlight-face)
(setq font-lock-keywords (list (list re 0 my-highlight-face t)))
(font-lock-fontify-buffer))
M-x highlight-regexp すると正規表現の入力を促されるので、そこで適切なパターンを指定すると、上の例のようにハイライトされる。そういえば解除するときのことは考えてなかった。あと、上の例ではなんとなく改行をまたいだマッチに成功してるけど、emacs の正規表現である以上、改行をまたいだパターンのマッチは期待通りにいかないと覚悟すべき。やっぱりこのエディタは、本当のところは文章のパワー編集には向かないんじゃないだろうか。

まあ問題はあるけど、ここまではよかった。

実はいま c さんに、「xyzzy で同じことがしたい」と脅されている。xyzzy は普段使ってないから、色の付け方とかわからんのですよ……。
Windows なら EmEditorとかで GUI のメニューから同じようなことができるから、とりあえずそっちでいいんじゃないかなあ。だめ?

2007/08/16

2007/08/15

cさんに「索引の読み仮名をひらがなで明示的に指定するのは前時代すぎてあほみたいだ。休み明けまでに何とかしとけ」と恫喝されたので、彼女が休みのあいだに急いで対策することにした。

まあ、実際の cさんはそんなひどい言い方をする人ではなく、ちょうかわいいんだけど、たしかに LaTeX ベースで本を作っていると索引のふりがな入力がうっとうしい。労力の問題だけでなく、原稿にひらがなが氾濫して読みにくくなるという意味でもうっとうしい。

漢字かな変換にはKAKASIを使うのが常套なんだろうな。Gauche には Ruby とちがって KAKASI のライブラリはないけれど、ほとんどジョーカーみたいな c-wrapper がある。
これで libkakasi.h に宣言されているCの関数が Gauche から使える。
(use gauche.charconv)
(use c-wrapper)
(c-load-library "/usr/lib/libkakasi.so.2.1.0")
(c-include "/usr/include/libkakasi.h")

(define (kanji->hira str)
(let ((base-ces "utf-8")
(kakasi-ces "iso2022jp"))
(kakasi_getopt_argv 3 '("kakasi" "-JH" "-p"))
(ces-convert
(x->string (kakasi_do (ces-convert str base-ces kakasi-ces)))
kakasi-ces base-ces)))
KAKASIがUTF-8を扱えないのが厄介だけど、それ以外はとても素直に Gauche で漢字かな変換ができる。

gosh> (kanji->hira "素子")
{もとこ|そし}
さて、この「素子」のようにユニークな読みを決定できない項目があると困っちゃうんだけど、「もとこ」か「そし」かの判断を機械的にすべきではなさそうだ
(「この素子を開発したのは素子さんです」問題)。だから、こういうのだけは人力であらかじめ指定しておくのが最適な対応だと思うのですが、それでかまわないでしょうか?> cさん
こんなふうにマークアップ原稿がLaTeXへと変換されるようにします。
<p>
この素子を開発したのは素子さんです。
<indexterm><i1 sortas="そし">素子<i2>開発者</i2></i1></indexterm>
<indexterm><i1 sortas="もとこ">素子</i1></indexterm>
<indexterm><i1>開発者</i1></indexterm>
</p>

この素子を開発したのは素子さんです。\index{そし@素子!かいはつしゃ@開発者}\index{もとこ@素子}\index{かいはつしゃ@開発者}



参考:
今日の一行::ひらかなのインデックス の cut-sea さんの解
ごとけんさんの ruby-kakasi の kakasi.c

2007/08/10

もう、PostScriptでフィボナッチ数列くらいなら昼休みにコーヒー飲みながらでも考えられる。
/fib {0 1 2 index -1 1 {pop exch 1 index add} for} def

ただ、せっかく PostScript なので、結果を印刷とかもしたい。印刷には show オペレータを使うわけだけど、show は文字列(string)しかとれない。fib オペレータが返すのは数値(integer)なので、文字列の型に変換する必要がある。

PostScript で型を文字列に変換するには、=string cvs とすればいいようだ。
%!
/fib {0 1 2 index -1 1 {pop exch 1 index add} for} def
/Palatino-Linotype findfont 300 scalefont setfont
10 10 moveto
11 fib == =string cvs show
これでページの左下に大きく「89」と印刷される。やっぱりPalatinoフォントの数字は美しい。

fib-11

さらにグラフなど描いてみる。
%!
/fib {0 1 2 index -1 1 {pop exch 1 index add} for} def
20 setlinewidth

1 1 21 { % for
/i exch def
/x 27 i mul def

0 setgray
/Palatino-Linotype findfont 10 scalefont setfont
10 x 5 sub exch moveto
i fib == =string cvs show

/r {rand i mod 21 div} def
r r r setrgbcolor
newpath
x 30 moveto
i fib == 10 div 30 add x exch lineto
stroke
} for

showpage

fib

2007/08/07

PostScript で階乗のつづき。こんどは for 文で。
/func {1 exch -1 1 {mul} for} def
ようするに、自分がしたい操作に必要な変数が、適切な数だけ適切な順番でスタックに積まれているようにすればいいらしい。そしてスタックというやつからは、直前に積んだものだけを取り出すことができる。

たとえば上記で定義した階乗のオペランド func を以下のように呼び出すと、
GS> 5 func
まず 5 がスタックに積まれる。この 5 は「funcへの引数」のつもりなんだけど、スタックから見るとそんなつもりはなくて、ただ値が積まれただけ。次は func を積むんだけど、func は上記のように定義されているので、その定義の一番最初にある 1 がスタックに積まれる。この時点のスタックの状態はこんな感じ。
 1 
---
5
func の定義によれば、次は exch だ。これは、それまでスタックの1番上にあった要素とその下の要素を入れ替える。つまり、スタックの状態はこうなる。
 5
---
1
さらに -1 と 1 を順番に積んで、スタックの状態はこうなる。
 1 
---
-1
---
5
---
1
ここで、本文が mul だけの for が登場する。for というオペレータは、スタックの値を 3つ消費し、それぞれの値を深いほうから順番に「繰り返しの最初」「繰り返しの更新」「繰り返しの終わり」として本文を繰り返す。ただし毎回の繰り返しでは、スタックの先頭に、そのターンにおける変数のようなものが積まれる。こう書くと複雑だけど、ようは最初に本文を実行するときには「5」が、2回目は「4」が、...、5回目は「1」がスタックの先頭に積まれるということ。つまり1回目の繰り返しのとき、スタックの状態はこう。
 5
---
1
本文の mul は、このスタックから値を 2つ取り出して、それらの積をあらためてスタックに積む。したがってスタックの状態は、
5
2回目の繰り返しに際してスタックの先頭に「4」が積まれる。
 4 
---
5
このスタックで mul を適用すると、
 20
3回目の繰り返しに際してスタックの先頭に「3」が積まれる。
 3 
---
20
mul を適用して
 60
4回目の繰り返しに際してスタックの先頭に「2」が積まれる。
 2 
---
60
mul を適用して
120
5回目の繰り返しに際してスタックの先頭に「1」が積まれる。
 1 
---
120
mul を適用して
120
おしまい。こうして最後のスタックの値を取り出せば(そのためには == を使う)、5の階乗の値が得られる。

たぶん用語の使い方はいいかげん。はやく教科書こないかな。

2007/08/06

PostScript が意外におもしろいので真剣に勉強してみようと思う。教科書は、Web で PDF が全部公開されている "Thinking in PostScript" に決めた。書籍はもうとっくに絶版らしい。でも物理的な本が手もとにないとつらいんだよなあ。Amazon マーケットプレイスにも出品されているけどバカみたいに高額なので(6000円以上)、US の同様のサービスに注文した(600円くらい)。まだ届かない。出荷された気配もない。もう待ちきれないよう。

というわけで、試行錯誤しながら階乗を考えてみた。
 /func {dup 1 eq {1 mul} {dup 1 sub func mul} ifelse} def
実行結果。
GS> 10 func ==
3628800
GS> 20 func ==
2.43290202e+18
GS> 100 func ==
inf.0
どうやら再帰的なオペレータの定義ができるらしい。はじめは、ふつうに for を使って解こうとしたんだけど、わかりませんでした。

ところで Emacs の ps-mode は GS のビューワーと連動して出力結果がリアルタイムで見られてすごい。便利すぎ。ただしお絵描きを始めると日付が変わるようだ。