Cygwinでライブラリをビルドするときの注意点
CygwinでGMPをビルドしたんだけど、スタティックライブラリはできているのに、DLLがない。はて? と思ってconfigure.inを調べたところ、Cygwinでは--enable-sharedと--enable-staticが排他的な関係になっていた。gmp.hの内容がそれぞれで違ってくるからだそうだ。
言われてみれば、WindowsのDLLでは、関数をエクスポートやインポートするときに、修飾子を使ったりするんだったっけ。納得。
備忘録とチラシの裏を兼ねる
CygwinでGMPをビルドしたんだけど、スタティックライブラリはできているのに、DLLがない。はて? と思ってconfigure.inを調べたところ、Cygwinでは--enable-sharedと--enable-staticが排他的な関係になっていた。gmp.hの内容がそれぞれで違ってくるからだそうだ。
言われてみれば、WindowsのDLLでは、関数をエクスポートやインポートするときに、修飾子を使ったりするんだったっけ。納得。
モナド的な何かに向かってを見て、when-bindみたいなマクロなら、Gaucheにもありそうだと思って探したところ、やっぱりあった。
(let ((the-value (func-which-returns-useful-value-or-#f)))
(if the-value
(do-something-based-on the-value)))
こういう処理を、
(and-let* ((the-value (func-which-returns-useful-value-or-#f)))
(do-something-based-on the-value))
こう書ける。条件式が減らせて見通しも良くなる。
なお、束縛する変数がひとつの場合、例によって、if-let1というGauche独自のマクロがあり、
(if-let1 the-value (func-which-returns-useful-value-or-#f)
(do-something-based-on the-value))
のように書ける。
ただ、and-let*にしても、if-let1にしても、変数への束縛がある分、参照元の>>=より冗長になってしまうので、そういうパターンがかなりの頻度で現われるなら、束縛まで省略できる手続きを自分で定義した方が良いかもしれない。Haskellを知らない自分としては、>>=だと分かりづらいから、and-composeとかだろうか。
関数的なプログラミングをしていると、手続きの結果を別の手続きに渡して、さらにその結果を別の手続きに、みたいな処理が日常的に出てくるけど、処理が複雑になると、ネストが深くなったり、見通しが悪くなったりする。
composeを使うと、そういった問題を避けられることがある。
;; 手続きの結果を順に渡す場合
(a
(b
(c
(d
(e x)))))
;; composeで手続きを合成する場合
((compose a b c d e)
x)
composeはR5RSやR6RS、SRFIにはない手続きのようだけど、Gauche以外にもPLT Schemeでも使うことができる。
(use gauche.process)
(define current-code-page
(let1 cp #f
(lambda ()
(unless cp
(set! cp ((#/: (\d+)$/ (process-output->string '(chcp))) 1)))
cp)))
;; pathに不完全文字列になるエントリがあるとエラー
(directory-list path)
;; 低レベルならエラーになる処理は含まれない
(sys-readdir path)
Gaucheのfile.utilは0.8.14の現時点では、パスがASCII以外でエンコードされているケースを考慮してないので、CP932などでエンコードされたパスを処理する場合、エラーになることがある。具体的には、パスにGaucheの内部エンコードで許されないバイト表現が含まれる場合。パスは不完全文字列として処理されるけど、不完全文字列には許されない処理をfile.utilの各関数内部でしているため、エラーになる。
他の人が原因を見つけてそうだな、と思いながらも、コードを読んで原因を見つけたところで、やっぱり他の人が原因を見つけていたのを知った。Gauche-devel-jpメーリングリストの「パス名での不完全文字列の扱い」というメールに詳しい。徒労だ。