Shiro Kawai
shiro****@lava*****
2010年 8月 25日 (水) 22:36:54 JST
From: Masatake YAMATO <yamat****@redha*****> Subject: [Gauche-devel-jp] handing keyword in ref Date: Wed, 25 Aug 2010 19:37:49 +0900 (JST) > get-keywordの箇所でrefを使いたくなることが良くあります。 > こういったものを書いてみたので良かったら導入を検討してもらえませんか。 > > 大和 > > > > (define-method ref ((obj <list>) (keyword <keyword>)) > (get-keyword keyword obj)) > (define-method ref ((obj <list>) (keyword <keyword>) fallback) > (get-keyword keyword obj fallback)) > (define-method (setter ref) ((obj <list>) (keyword <keyword>) val) > (let1 r (memq keyword obj) > (if r > (set-cdr! r (cons val (cdr (cdr r)))) > (set-cdr! (last-pair obj) (list keyword val))))) <list>はkeyword-value listとは限らない、というのが問題だと思います。 例えば空リストに対しては(setter ref)はうまく動かないですよね。 まあそれはドメインエラーだとする解釈も出来なくはないですが、 基本的なメソッドなのにすべての<list>に対して動かない、というのは 危険な感じがします。 もともとLispのリストは、型としては単一で、「使う側が好きなように 解釈する」というユルさが利点でもあり欠点でもあります。 get-keywordを使う場合はリストをplist形式のマップとみなしている わけですが、同じマップとしての使い方でもalist形式がありますし、 また単なる要素の集合とみなすこともできます。 これは使い手の解釈に委ねられているので、<list>としてディスパッチする メソッドがひとつの見方を固定してしまうのはちとまずい。 むしろ、使う側がget-keywordなりassocなりmemberなりの 個別の関数を用いることで、「今はリストを(plist|alist|集合)と みなしているよ」と明示できることの方が重要ではないかと思います。 delete-keyword!があるのでadd-keyword!があってもいいかな、とは 思いました (指定キーワードがplist中に存在すれば破壊的変更、 無ければ先頭に追加。なのでcallerは必ず戻り値を使う。) なお、テストコードでリテラルリストを変更してます。気をつけてください。 > (test* "ref+set! for keyword(0)" > '(:a 1 :b 9 :c 3) > (begin > (set! (ref x :b) 9) > x)) それと、上の(setter ref)の定義だとkeyword-value listの valueのところにたまたま一致するキーワードが入ってるとまずいですね。 --shiro