# Let/as with local variable hiding

**URL:** <https://www.ruby-forum.com/t/let-as-with-local-variable-hiding/120448>\
**Category:** Ruby\
**Created:** [November 17, 2007, 12:19am UTC](https://www.ruby-forum.com/t/let-as-with-local-variable-hiding/120448 "2007-11-17T00:19:50Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![ara.t.howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a8b319/32.png) [@ara.t.howard](https://www.ruby-forum.com/u/ara.t.howard)\
**Post date:** [November 17, 2007, 12:19am UTC](https://www.ruby-forum.com/t/let-as-with-local-variable-hiding/120448/1 "2007-11-17T00:19:50Z")

</div>

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/](http://codeforpeople.com/)
