Shiro Kawai
shiro****@lava*****
2004年 11月 22日 (月) 19:31:11 JST
わかりました。これは結構深い問題で、根本的に直すにはwrite-objectの プロトコルを変えないとだめです。(もともとやばいことはわかっていたので、 いずれ直さないとならないんですが)。 とりあえず、今回の問題だけ対症的にfixするのは以下のパッチでOKです。 diff -u -r1.13 array.scm --- ext/uvector/array.scm 13 Sep 2004 20:22:50 -0000 1.13 +++ ext/uvector/array.scm 22 Nov 2004 10:18:11 -0000 @@ -76,7 +76,7 @@ (define-method write-object ((self class) port) (format port "#,(~A ~S" name (array->list (array-shape self))) (array-for-each (cut format port " ~S" <>) self) - (display ")" port)) + (format port ")")) (define-reader-ctor name (lambda (sh . inits) (list-fill-array! (make-array-internal class (apply shape sh)) inits)))))) 根本的な問題は、shared structureを表示するためにwrite/ssが2回 ツリーをたどらなければならないところにあります。1回目で共有構造を 見つけて、2回目で実際に書き出します。 ところが、ユーザ定義のwrite-objectメソッドがある場合、オブジェクト のどの構造がwrite時に辿られるかがわかりません。そこで、write/ssは まずダミーのportを作成してwrite-objectを呼びます。このダミーの ポートは実際の出力は行わず、そこに出力されたオブジェクトの共有構造の チェックだけを行います。で、2パス目に本当の出力ポートを使って write-objectを再び呼び出します。 今回問題が発生したのは、閉じ括弧を出力する (display ")" port) でした。 1パス目のダミーポートから見ると、これは毎回同一の(eq?な)文字列 ")" が 出力されてくることになるので、それを共有構造と考えてしまったのです。 write-object中で同じようなコードを使っているところはどこでも同じ 問題が発生します。 今のところ考えている解決策は、ユーザ定義のwrite-objectに余分な引数 contextを渡して行くようにして、write-object側でそれが1パス目なのか 2パス目なのかを判断するようにする、というものです。多分互換性を保つ ためにメソッド名もobject-writeかなんかに変えるでしょう。 --shiro