Let's start Scheme

2018-03-30

Ephemeron を使ってみる

Ephemeron は SRFI-124で定義されているがどういったものなのか、どういう挙動が期待されるのかというのはなかなかに想像しづらい。ということで、ちょっと触りつつ解説してみる。

まず、 ephemeron とは何か?ものすごく簡単に言えば循環構造を許す弱対といえる。SRFI-124で定義されている ephemeron は一種の鍵対で、鍵が値から参照されてたとしても、その参照のみが生きているのであれば GC 対象になるというもの。日本語は難しいのでコードで説明してみる。
(let* ((key (cons 1 2))
       (value (cons key 1)))
  (make-ephemeron key value))
こんなのが鍵が値から参照されている状態である。この場合だと、鍵は値のみから参照されているので、ephemeron を作った直後に GC が発生すればどちらも回収されるというものである。

さて、実際の挙動を観察してみよう。SRFI-124 によれば ephemeron は MIT Scheme または Racket でサポートされているという(ちなみに、Sagittarius にもなんちゃってはあるが Chibi Scheme と同様のバグを抱えている。っていうか、これ Boehm GC 上で実装できるの?) MIT Scheme は手元にないので Racket を使ってみる。コードは以下の通り:
#lang racket

(define (make-weak v)
  (let* ((a (cons 1 2))
         (b (cons a v)))
    (make-ephemeron a b)))

(define e (make-weak 'a))
(write (ephemeron-value e)) (newline)
(collect-garbage 'major)
(write (ephemeron-value e)) (newline)
出力結果は以下:
Welcome to DrRacket, version 6.3 [3m].
Language: racket; memory limit: 128 MB.
((1 . 2) . a)
#f
GC 後には ephemeron の値が回収されているのがわかる。

ちょっとした追記:
この挙動と何が違うのか考えて見たのだが、鍵となる a が大域に設定されているのがまずいのかなぁというありきたりな推測。 set! でリセットしているが、内部のどこかでは参照が生きているとかそんなのではないだろうか?流石に Racket の中まではわからないので推測に過ぎないが…

No comments:

Post a Comment