# Ml style 'let' impl - fun with metaprogramming

**URL:** <https://www.ruby-forum.com/t/ml-style-let-impl-fun-with-metaprogramming/94604>\
**Category:** Ruby\
**Created:** [May 8, 2006, 9:24pm UTC](https://www.ruby-forum.com/t/ml-style-let-impl-fun-with-metaprogramming/94604 "2006-05-08T21:24:06Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [May 8, 2006, 9:24pm UTC](https://www.ruby-forum.com/t/ml-style-let-impl-fun-with-metaprogramming/94604/1 "2006-05-08T21:24:06Z")

</div>

i was just playing with this - an ml style let for ruby:

```
 harp:~ > cat a.rb
 require 'let'
 #
 # let allows you to setup local variables that will only be in 

```

scope for the  
# following block in an ml style  
#  
let :list =\> [] do  
list \<\< 42  
p list # =\> [42]  
end  
#  
# you can, of course, nest blocks  
#  
let :list =\> [] do  
list \<\< ‘forty-two’

```
     let :list => [] do
       list << 42
       p list # => [42]
     end

     p list # => ['forty-two']
   end
 #
 # the return value of let allows one to get a handle on the context 

```

to  
# retrieve values later if needed.  
#  
context =  
let :a =\> nil, :b =\> nil do  
self.a = 4  
self.b = 2  
end  
p [context.a, context.b] # [4, 2]  
#  
# note that the special variable ‘\_’ is a shorthand for ‘self’  
inside the  
# block.  
#  
context =  
let :a =\> nil, :b =\> nil do  
\_.a = 4  
\_.b = 2  
end  
p [context.a, context.b] # [4, 2]  
#  
# ‘open’ getter/setters are allowed  
#  
context =  
let :a =\> nil, :b =\> nil do  
a 4  
b 2  
end  
p [context.a, context.b] # [4, 2]  
#  
# ‘let’ params may be a list or hash. iff list values default to  
nil.  
#  
context = let(:a, :b =\> 2){ a 4 }  
p [context.a, context.b] # [4, 2]

```
 harp:~ > ruby a.rb
 [42]
 [42]
 ["forty-two"]
 [4, 2]
 [4, 2]
 [4, 2]
 [4, 2]

 harp:~ > cat let.rb
 def let *argv, &b
 #--{{{
   hashes, list = argv.partition{|arg| Hash === arg}
   hashes.inject(h={}){|h,h2| h.update h2}
   list.each{|elem| h[elem] = nil}

   blank_slate = Class.new{
     %w( inspect instance_eval instance_variable_get 

```

instance\_variable\_set ).each do |m|  
alias\_method “ **#{ m }** ”, “#{ m }”  
end

```
     instance_methods.each{|m| m !~ %r/^__/ and undef_method m}

     def _(); @_ ||= self; end

     h.each do |k,v|
       get, set, iff, var = "#{ k }", "#{ k }=", "#{ k }?", "@#{ k 

```

}"  
define\_method(get) do |\*argv|  
case argv.size  
when 0  
unless eval(“defined? #{ var }”)  
**instance\_variable\_set** var, v  
end  
**instance\_variable\_get** var  
when 1  
**send** set, \*argv  
else  
raise ArgumentError, “#{ argv.size } instead of 0 or 1”  
end  
end  
define\_method(set) do |arg|  
**instance\_variable\_set** var, arg  
end  
alias\_method iff, get  
end

```
   }.new

   blank_slate. __instance_eval__ &b
   blank_slate
 #--}}}
 end

```

it’s kind of fun but perhaps not incredibly useful. thoughts?

-a

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [May 8, 2006, 9:42pm UTC](https://www.ruby-forum.com/t/ml-style-let-impl-fun-with-metaprogramming/94604/2 "2006-05-08T21:42:58Z")

</div>

[http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html](http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html)
