From: "ara.t.howard" Date: 2007-11-17T08:18:25+09:00 Subject: let/as with local variable hiding this was kind of fun cfp: ~> cat a.rb class Object def let *a, &b Let.evaluate *a, &b end def as local, kvs = {}, &block kvs.update local => self Let.evaluate kvs, &block end class Let instance_methods.each{|m| undef_method m unless m[%r/^__/]} Instance_eval = Object.instance_method :instance_eval Instance_variable_set = Object.instance_method :instance_variable_set def self.evaluate kvs = {}, &block current = {} binding = block.binding undefined = Object.new begin push_vars kvs, current, binding, undefined let = new singleton_class = class << let self end instance_eval = Instance_eval.bind let instance_variable_set = Instance_variable_set.bind let singleton_class.module_eval{ kvs.keys.each{|k| attr k} } instance_eval.call{ kvs.each{|k,v| instance_variable_set.call "@#{ k }", v} } instance_eval.call &block ensure pop_vars current, binding, undefined end end def self.push_vars kvs, current, binding, undefined kvs.each do |k,v| current[k] = begin eval "#{ k }", binding rescue NameError undefined end eval "#{ k } = ObjectSpace._id2ref #{ v.object_id }", binding unless current[k] == undefined end end def self.pop_vars current, binding, undefined current.each do |k,v| next if v == undefined eval "#{ k } = ObjectSpace._id2ref #{ v.object_id }", binding end end end end a = 40 b = 2 c = 'forty-two' p let(:x => a, :y => b){ x + y } #=> 42 p a.as(:b){ a + b } #=> 80 p a.as(:x, :y => b){ x + y } #=> 42 p let(:c => a, :d => b){ c + d } #=> 42 p a #=> 40 p b #=> 2 p c #=> "forty-two" i know people have done 'let' before on ruby-talk but, iirc, not and impl which allowed shadowing locals. a @ http://codeforpeople.com/ -- share your knowledge. it's a way to achieve immortality. h.h. the 14th dalai lama