「 Selfish: Ruby で Self 的プロトタイプベース!」の変更案

keita_yamaguchiさんのSelf関連の記事とても楽しく読まさせてもらっています。
さて、http://d.hatena.ne.jp/keita_yamaguchi/20080811/1218445378の記事なんですが、こうするとよりSelfに近いんじゃないかなと思うのですがどうでしょう?
やってることは、データの入っているslotは単純にデータを入れるのではなくreader兼setterのProcオブジェクトを入れるというものです。readerかsetterかはsetする値を指定するか否かで変わります。こうすることで、代入に=なんていう邪悪な記号が出てこないし、setterのメソッドチェーンも出来てうれしいのではないかなと思います。その代わり、効率が落ちますけど・・・。

追記1: 私の操作ミスで2回トラックバックが行ってしまいました。keita_yamaguchiさん申し訳ありません。
追記2: このパッチを当てると、1.9系じゃないと動かなくなります。ブロックのオプショナル引数を使いたいからです。

セッションはこんな感じになります。

require 'lib/selfish.rb'

a = _(:x => 1)                                                          # 
p a.x                                                                   #  => 1
p a.x 2                                                                 #  => #<Selfish::Object:0x1001b084 @slots={:x=>2}>
p a.x                                                                   #  => 2
p _(:sum => proc {|s| s.x + s.y}, :x => 1, :y => 2).sum                 #  => 3
p _(:_parent => _(:sum => proc {|s| s.x + s.y}), :x => 1, :y => 2).sum  #  => 3

パッチです

diff -uprN selfish.rb.org selfish.rb
--- selfish.rb.org	2008-08-12 20:47:20.500000000 +0900
+++ selfish.rb	2008-08-12 22:11:33.468750000 +0900
@@ -26,9 +26,14 @@ module Selfish
         visited << self
         if @slots.has_key?(selector)
           if @slots[selector].kind_of?(Proc)
-            [ @slots[selector] ] # method slot
+            cont = @slots[selector].call(nil)
+            if cont.kind_of?(Proc) then
+              [ cont ] # method slot
+            else
+              [ @slots[selector] ] # data slot
+            end
           else
-            [ proc{ slots[selector] } ] # data slot
+            [ proc{ slots[selector] } ] # Literal
           end
         else
           parent_lookup(selector, visited)
@@ -50,21 +55,27 @@ module Selfish
   end
 
   module SlotInterface
+    UNDEF_VALUE = [:undef]
     attr_reader :slots
 
     # Adds new slot.
     def add_slot(name, val=nil)
-      # data slot
-      @slots[name.to_sym] = val
-      # slot writer
-      @slots[:"#{name}="] = proc {|s, val| s.slots[name] = val }
+      # data reader/writer
+      @slots[name.to_sym] = ->(s, v = UNDEF_VALUE) {
+        if v == UNDEF_VALUE then
+          val
+        else
+          s.slots[name] = v
+          s
+        end
+      }
     end
 
     # Returns parents.
     def parents
       @slots.keys.select{|name|
         name.to_s =~ /\A_.*[^=]\Z/
-      }.map{|name| @slots[name]}
+      }.map{|name| @slots[name].call(nil)}
     end
   end