KAWAのappend-mapにバグ?
開発中のプログラムが不可解なところで暴走する原因を追っていたら、どうやらKAWAのバグらしいものを見つけてしまった。
再現する最小のコードは以下の通り。
(require 'list-lib) (define (foo x) (cond ((= x 0) '(a)) ((= x 1) '(b)) (else '()))) (append-map foo '(0 1 2)) (append-map foo '(0 1 2))
実行すると、2回目のappend-mapの呼び出しから返ってこなくなる。
同様のプログラムをGaucheで実行すると問題ないので、多分KAWAのバグだろう。具体的には、gnu/kawa/slib/srfi1.scmのappend-mapの定義で、
(define (append-map f lis1 . lists) (if (pair? lists) (apply append! (apply map (cons f (cons lis1 lists)))) (apply append! (map f lis1))))
append!→appendだと思う(実際、この関数を使うとGaucheでも暴走した)。
おそらくappend-mapの第1引数に与える関数内で定数を返すと、それが破壊的に変更されて問題が起きるということだろうけど、念のためソースコードに含まれるappend-mapの呼び出しをすべて(apply append (map ...))に置き換えた。これによって多少効率が悪くなった分は後でチューニングすることにして、今は気にしない。
追記
もっと直接的なバグの例
(require 'list-lib) (define a '(a)) (define b '(b)) (define c '()) (define (foo x) (cond ((= x 0) a) ((= x 1) b) (else c))) (append-map foo '(0 1 2))
このプログラムを実行した後で、aが'(a b)になっている。