2012/01/29
Gaucheで書き捨てツールのtips
こちらでGaucheを取り上げていただいた。 こういうちょっとしたツールに使われるのは本望なので、 ちょっと書きツールに便利なtipsをいくつか。
- Perl風にdieというのを定義して、
(die (format "~a: invalid argument" opt)
のように呼んでるけれど、実はexit
に「メッセージをformatしてcurrent-error-portに出力してからexitする」という機能があるので、format+dieはexitひとつでいける。(exit 1 "~a: invalid argument" opt)
- コマンドライン引数の扱いは、オプションをlet-argsでパーズした後、残りの引数に
matchをかける、っていうのをよくやる。
(use gauche.parseopt) (use util.match) (define (main args) (let-args (cdr args) ([#f "h|help" => (cut usage 0)] . args) (match args [(file) ...処理...] [_ (usage 1)])))
このパターンは頻出するので、let-argsを拡張してオプション以外の引数もbindできるように しちゃおうかなあ、と考えている。パーズできなかった場合のエラー処理をもうちょい 賢くしたいんだけど。 - あとはスタイルの好みだけど、
(or 条件チェック エラー)
,(and 条件チェック エラー)
はそれぞれ(unless 条件チェック エラー)
と(when 条件チェック エラー)
と書ける。when/unlessは戻り値が無い(未定義な)ので、「ここの節は副作用がある(戻らないことがある)」っていう意図を示せる。and/orは逆に戻り値に意味があることを示す時に使う。 (もっともCommon Lispではwhen/unlessにも戻り値があり、それはそれで便利に使えるので、Schemeでも戻り値があるほうがいい、って議論もある。) - ファイルの存在チェックをどこでやるかはツールの目的によるけど、使い捨てスクリプトならファイル読めなければ
process-output->string-list
がエラー出すんで、それを捕まえちゃってもいいかも。他のエラー (外部コマンドが見つけられないとか) の時も、スタックダンプを出すよりはメッセージ一行で終わらせちゃっていい、っていう用途であれば、処理全部をguardで囲んでエラーを一括して捕まえる、という手がある。 (もちろん、予想されるエラーだけ一行メッセージでexitして、 予想されないエラーはスタックトレース出したい、という用途であれば一括guardでない方がいい)。
そんなわけで、まあこんなふうにも書ける。
#!/usr/bin/gosh (use gauche.process) (use gauche.parseopt) (use util.match) (use file.util) (define (usage status) (exit status "usage: ~a <file>\n" *program-name*)) (define (main args) (let-args (cdr args) ([#f "h|help" (usage 0)] . args) (match args [(file) (guard (e [(<error> e) (exit 1 "~a" (~ e'message))]) (let ([fl (process-output->string-list '(funclen) :input opt)] [fn (process-output->string-list `(funcname ,opt))]) (unless (= (length fl) (length fn)) (error "funclen may have been failed")) (for-each (^[x y] (print (regexp-replace #/\w*$/ x y))) fl fn)))] [_ (usage 1)])) 0)
Tags: Programming, Gauche
Post a comment