proglog

主にプログラミングに関する断片的メモ

schemeで変数名を式で。データファイル処理

schemeでset!の第1引き数を式にしたい。
もちろん、シンボル、あるいは変数名を返すもの。

perlで言うと、例えば、

@arry = ('foo','bar','baz','qux','quux');

for($i = 0; $i <5; ++$i){
    ${ $arry[$i] } = $i;
}

print $foo , "\n";
print $bar , "\n";
print $baz , "\n";
print $qux , "\n";
print $quux , "\n";

こんな感じに使えるような。

なんでかと言うと、Javaでいう.propertiesファイルとか、YAMLとかjsonとかいう「key=value」形式的なデータファイルを、schemeで処理したい。
xmlほどのものじゃなく。

これはそもそもS式を使え、ということなんだろう。
で、

(prof-dir "~/Application Data/Mozilla/Firefox/Profiles/xxxxxxx")
(user-agent "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP)")
(blog_id "1111111")

という平たいペアのリストをreadで読み込んで、対応する変数にset!する。

(use file.util)
(define ldb-data "ldb-data.scm")
(define prof-dir #f)
(define user-agent #f)
(define blog_id #f)

(call-with-input-file (build-path (current-directory) ldb-data)
  (lambda (inp)
    (let loop ((sexp (read inp)))
      (unless (eof-object? sexp)
	(case (list-ref sexp 0)
	  ((prof-dir) (set! prof-dir (list-ref sexp 1)))
	  ((user-agent) (set! user-agent (list-ref sexp 1)))
	  ((blog_id) (set! blog_id (list-ref sexp 1)))
	  (else 'ERROR))
	(loop (read inp))))))

これだと、変数が増えると、その分caseのパターンが増えていく。
そこで、ちょっと変える

(call-with-input-file (build-path (current-directory) ldb-data)
  (lambda (inp)
    (let loop ((sexp (read inp)))
      (unless (eof-object? sexp)
	(eval `(set! ,(list-ref sexp 0) ,(list-ref sexp 1)) (interaction-environment))
	(loop (read inp))))))

準クォートとevalを使ってみたけど、なんか持って回ったやり方に見える。

素直に、

(set! prof-dir "~/Application Data/Mozilla/Firefox/Profiles/xxxxxxx")

という形で書いたデータファイルにしたほうがいいんだろうか。