thanks all for your patience,
Ara, Pit for your help;
here is my solution, if you are interested,
now you can get rid of instance variables in your Ruby code :)
#
module M
def add_loc name, reader_only=false, ini=nil
skl = class << self ; self ; end
skl.module_eval{
v = ini
define_method name.to_sym, lambda{ v }
define_method "#{name}=".to_sym, lambda{ |a| v = a } unless
reader_only
}
end
end
#
class CA ; include M ; end
ca = CA.new
ca.add_loc :pocket, true, [] # reader only
ca.add_loc :bag
ca.pocket << 10
ca.bag = :book
#
class CB ; include M ; end
cb = CB.new
cb.add_loc :address_book, true, {}; cb.address_book["me"] = "my address"
cb.add_loc :bag; cb.bag = :apple
#
p [ca.pocket, ca.bag]
p [cb.address_book, cb.bag]
#
---------- Capture Output ----------
[[10], :book]
[{"me"=>"my address"}, :apple]
regards
Sergey
--
There are 10 kinds of people in the world; those who know binary, and those
who don't.
----- Original Message -----
From: "Sergey Volkov" <gm.vlkv / gmail.com>
To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
Sent: Thursday, May 11, 2006 4:33 AM
Subject: Re: plz help with binding
> Sorry, guys,
> I must admit - I was not right about Ruby closures;
> most probably about metaprogramming neither,
> so, please disregard my previous message;
>
> closures work in Ruby perfectly, my mistake was that arr_meth was executed
> only once inside class definition:
> #
> class C
> def self.arr_meth( sym )
> arr = []
> define_method sym.to_sym, lambda{ arr }
> end
> arr_meth :arm
> end
> #
> closure was created, but it was then shared between all class instances,
> so Ara was absolutely right - we have to create new closure for each
> individual instance, and this can not be implemented on class level (no
> instances yet!);
>
> I still do not want to modify class code to add instance_var-less storage,
> so at this moment I have implemented external function to extend class
> with new method (thanks, Ara!):
> #!/bin/ruby
> module M
> def self.add_loc obj, name, ini=[]
> skl = class << obj ; self ; end
> skl.module_eval{
> v = ini
> define_method name.to_sym, lambda{ v }
> }
> end
> end
> #
> ca = Object.new
> M.add_loc ca,:pocket; ca.pocket << 10
> M.add_loc ca,:bag; ca.bag << :book
> #
> cb = Object.new
> M.add_loc cb,:pocket; cb.pocket << 20
> M.add_loc cb,:bag; cb.bag << :apple
> #
> p [ca.pocket, ca.bag]
> p [cb.pocket, cb.bag]
> ---------- Capture Output ----------
> [[10], [:book]]
> [[20], [:apple]]
>
> Hidden instance slots created! In this example they contain array, but
> accessors can be implemented without any problem.
> Any ideas about better API?
> thanks
> regards
> Sergey
> --
> oh - please do not forget to be kind!
>
> ----- Original Message -----
> From: "Sergey Volkov" <gm.vlkv / gmail.com>
> To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
> Sent: Thursday, May 11, 2006 3:39 AM
> Subject: Re: plz help with binding
>
>
>> This is cool!
>> But not for average (read big enterprise) level programmer :(
>> How can I follow 'keep it simple, stupid!' approach with Ruby
>> metaprogramming?
>> How many Ruby programmers can reproduce this code with easy?
>> Can such code code be supported in production environment?
>>
>> I'm not asking, I'm crying!
>> I'd like to ask Matz: give me real lexical closure and clean up meta
>> class mess, please!!!
>>
>> Or should we admit, that Ruby metaprogramming is for real programmers
>> only?
>> Or I'm just plain stupid?
>>
>> Please advise;
>> thanks
>> bests
>> Sergey
>>
>> ----- Original Message -----
>> From: <ara.t.howard / noaa.gov>
>> To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
>> Sent: Thursday, May 11, 2006 2:11 AM
>> Subject: Re: plz help with binding
>>
>>
>>> On Thu, 11 May 2006, Sergey Volkov wrote:
>>>
>>>> Now I'm trying to create instance-var-less storage:
>>>
>>> an even trickier way:
>>>
>>> harp:~ > cat a.rb
>>> class C
>>> def self.arr_meth m
>>> m = m.to_s
>>> define_method(m) do
>>> singleton_class =
>>> class << self
>>> self
>>> end
>>> singleton_class.module_eval do
>>> a = []
>>> define_method m, lambda{ a }
>>> end
>>> send m # recurse into newly defined method
>>> end
>>> end
>>>
>>> arr_meth :arm
>>> end
>>>
>>> ca = C.new; ca.arm << 10
>>> cb = C.new; cb.arm << 20
>>>
>>> p ca.arm #-> [10, 20]
>>> p cb.arm #-> [10, 20]
>>> p( ca.arm.eql?( cb.arm ) ) #-> true
>>>
>>> harp:~ > ruby a.rb
>>> [10]
>>> [20]
>>> false
>>>
>>> -a
>>> --
>>> be kind whenever possible... it is always possible.
>>> - h.h. the 14th dali lama