|
|
||
「他人のババア」とケータイ小説に共通している一番嫌なところは他人を無理に泣かせようとしているところだ。そういうふうに呈示されると他人の恋愛の話も、他人の祖母の話も無価値になってしまう。
ここ三週間ほど喉が悪い。風邪で喉を潰してしまったんだけど、風邪が治っても喉は治らず。昨晩は布団に入ってから寝るまで三時間ぐらいかかった(ずっとげほげほいってた)。
積極的にうがいしましょう。
一番簡単そうな FIFO のものを書いてみた。
うまくインターフェースを共通化して、基底のアルゴリズム(FIFO/LRU/NRU/ランダム/千里眼置換アルゴリズムなどなど)を例えば実行中にでも変更できるようにしておきたいものだ(性能が不安定なアルゴリズムを試して、ダメそうなら安定なものに切り替えるなど)。
更にスワップ機構付きコレクションを構成しうるデータ構造(list/vector/hash-table/tree-map などなど)も差し替えられるように出来たら嬉しいんだけど、どうしたもんかな……。以下の FIFO の例では「スワップ領域」と「物理メモリ空間」を区別しているのだけれど、そうせずに書かなければうまくいかないだろうと思う。つまり、基底コレクションは一つで、要素によって ghost だったり、そうでなかったりするのが望ましいということ。要素を ghost か with-swap-collection-element-mixin みたいな名前のオブジェクト(または、サブクラスのオブジェクト)に限って、そこに内部的な情報を格納すれば大体書けるはずだ。
そして、そうすれば with-swap-sequence も容易に実現できる。ということは、インデックス付きコレクション(つーか、シーケンス?)の実装も楽になる。それから instance-pool の基底コレクションにこれを使えば機能的にはオブジェクトの永続化が大体できあがる。
言葉でいうだけならなんと簡単なことか……。
(use gauche.collection) (use gauche.parameter) (define-class <with-swap-collection-meta> (<class>) ()) (define-class <with-swap-collection> (<collection>) ((%mist:ws:queue :init-keyword :queue) (%mist:ws:index :init-value 0) (%mist:ws:initial-value :init-keyword :initial-value) (%mist:ws:swap :init-value '())) :metaclass <with-swap-collection-meta>) (define default-with-swap-collection-size (make-parameter 200)) (define (%queue-of q) (slot-ref q '%mist:ws:queue)) (define (%index-of q) (slot-ref q '%mist:ws:index)) (define (%swap-of q) (slot-ref q '%mist:ws:swap)) (define (queue-length q) (vector-length (%queue-of q))) (define (current-value q) (vector-ref (%queue-of q) (%index-of q))) (define-method call-with-iterator ((coll <with-swap-collection>) proc . options) ;; &keyword start (let ((queue (slot-ref coll '%mist:ws:queue)) (ctx 'queue) ;; queue or swap (idx-of-queue 0) (len-queue (queue-length coll)) (swap (%swap-of coll))) (proc (lambda () (if (and (eq? ctx 'queue) (>= idx-of-queue len-queue)) (set! ctx 'swap)) (or (and (eq? ctx 'swap) (null? swap)))) (lambda () (if (eq? ctx 'queue) (begin0 (vector-ref queue idx-of-queue) (inc! idx-of-queue)) (begin0 (ghost->x (car swap)) (set! swap (cdr swap)))))))) (define-method call-with-builder ((coll <with-swap-collection-meta>) proc . options) ;; &keyword size (let1 q (make-with-swap-collection) (proc (lambda (v) (with-swap-collection-push! q v)) (lambda () q)))) (define-method write-object ((q <with-swap-collection>) port) (format port "#<ws-queue ~s :swap-size ~s :index ~s :queue ~s>" (eqv-hash q) (length (%swap-of q)) (%index-of q) (%queue-of q))) (define (make-with-swap-collection . may-be-size) (let1 initial-value (gensym) (make <with-swap-collection> :queue (make-vector (get-optional may-be-size (default-with-swap-collection-size)) initial-value) :initial-value initial-value))) (define (%swap-out! q) (let1 v (current-value q) (if (not (eq? v (slot-ref q '%mist:ws:initial-value))) (push! (slot-ref q '%mist:ws:swap) (x->ghost v))))) (define (with-swap-collection-push! q v) (let1 len (queue-length q) (if (<= len (%index-of q)) (slot-set! q '%mist:ws:index 0)) (%swap-out! q) (vector-set! (%queue-of q) (%index-of q) v) (inc! (slot-ref q '%mist:ws:index)) (undefined))) ;; sample code (define-class <number-ghost> () ((v :init-keyword :v))) (define-method write-object ((obj <number-ghost>) port) (display "<number-ghost>" port)) (define-method x->ghost ((obj <number>)) (make <number-ghost> :v obj)) (define-method ghost->x ((obj <number-ghost>)) (slot-ref obj 'v)) (let1 q (make-with-swap-collection 10) (dotimes (i 500) (with-swap-collection-push! q i)) (write q)(newline) (let1 vs (map (lambda (e) e) q) (write/ss (apply + vs))(newline) (write/ss (coerce-to <with-swap-collection> vs))))