From: Robert Klemme Date: 2007-11-17T19:32:56+09:00 Subject: Re: Yielding an object and caring about the result: the cousin of Object#tap 2007/11/16, ara.t.howard : > > On Nov 15, 2007, at 1:05 PM, Robert Klemme wrote: > > > Interesting point although I am not sure whether #as is really > > functional (and thus, whether Daniel's remark is really close to > > the mark). If I think of functional programming paradigm first > > item that comes to mind is lack of side effects (other than IO > > probably). Here, #as just enables method chaining in a single > > statement where you would otherwise need multiple statements. From > > my point of view this is not functional vs. non functional. In the > > end it's mainly a question of scoping: whether you need multiple > > local variables in the current scope or can achieve the same with > > temporaries in nested and thus smaller scopes. FC has stressed > > this point several times. > > i guess it reminds of 'let' a little... > > this sprang to mind: > > 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 > 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 > end > end > end > > > a = 40 > b = 2 > c = 'forty-two' > > p let(:x => a, :y => b){ x + y } > > p a.as(:x){ x + b } > > p a.as(:x, :y => b){ x + y } > > # fatal flaw > p let(:c => a, :d => b){ c + d } > > > > cfp:~ > ruby a.rb > 42 > 42 > 42 > a.rb:44:in `+': can't convert Fixnum into String (TypeError) > from a.rb:44 > from a.rb:27:in `instance_eval' > from a.rb:27:in `call' > from a.rb:27:in `evaluate' > from a.rb:3:in `let' > from a.rb:44 > > > still - it's kind of interesting... Well, you could of course just do $ ruby -e 'def let;yield;end; let { x=10;y=20; puts x+y}' 30 $ ruby -e 'x=10;y=20; puts x+y' 30 :-) I guess "let" is in Ruby far less useful than in Lisp. :-) Kind regards robert -- use.inject do |as, often| as.you_can - without end