From: Sergey Volkov Date: 2006-05-11T18:10:18+09:00 Subject: Re: plz help with binding 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" To: "ruby-talk ML" 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" > To: "ruby-talk ML" > 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: >> To: "ruby-talk ML" >> 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