Ml style 'let' impl - fun with metaprogramming


#1

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


#2

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