From: Joey Date: 2006-05-09T04:40:56+09:00 Subject: Re: ml style 'let' impl - fun with metaprogramming... ------=_Part_10894_27975587.1147117253765 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html On 5/8/06, ara.t.howard@noaa.gov wrote: > > > 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 =3D> [] do > list << 42 > p list # =3D> [42] > end > # > # you can, of course, nest blocks > # > let :list =3D> [] do > list << 'forty-two' > > let :list =3D> [] do > list << 42 > p list # =3D> [42] > end > > p list # =3D> ['forty-two'] > end > # > # the return value of let allows one to get a handle on the context > to > # retrieve values later if needed. > # > context =3D > let :a =3D> nil, :b =3D> nil do > self.a =3D 4 > self.b =3D 2 > end > p [context.a, context.b] # [4, 2] > # > # note that the special variable '_' is a shorthand for 'self' insid= e > the > # block. > # > context =3D > let :a =3D> nil, :b =3D> nil do > _.a =3D 4 > _.b =3D 2 > end > p [context.a, context.b] # [4, 2] > # > # 'open' getter/setters are allowed > # > context =3D > let :a =3D> nil, :b =3D> 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 =3D let(:a, :b =3D> 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 =3D argv.partition{|arg| Hash =3D=3D=3D arg} > hashes.inject(h=3D{}){|h,h2| h.update h2} > list.each{|elem| h[elem] =3D nil} > > blank_slate =3D 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 _(); @_ ||=3D self; end > > h.each do |k,v| > get, set, iff, var =3D "#{ k }", "#{ k }=3D", "#{ 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 > -- > be kind whenever possible... it is always possible. > - h.h. the 14th dali lama > > ------=_Part_10894_27975587.1147117253765--