> better? > > class CachedLambda < Struct.new(:block, :cache) If we're thinking Lispy, well, why don't we stay in that mode?... ;] We could implement such a cache for lambda functions with one, uh, two, more lambda functions... ---------------------------------------------------------------- fac = lambda{|n| n < 2 ? 1 : (1..n).inject{|f, i| f * i}} tri = lambda{|n, r| fac[n] / (fac[r] * fac[n-r])} size = lambda{|r| tri[r-1, r / 2].to_s.size + 1} line = lambda{|y, r| (0..y).map{|x| tri[y,x].to_s.center size[r]}} lines = lambda{|r| (0...r).map{|y| line[y, r]}} pascal = lambda{|r| lines[r].map{|l| l.join.center(size[r]*r).rstrip}} cache = lambda{|f| h={} ; lambda{|*args| h[args] ||= f[*args]}} fac = cache[fac] tri = cache[tri] size = cache[size] line = cache[line] lines = cache[lines] pascal = cache[pascal] puts pascal[(ARGV[0] || 15).to_i] ---------------------------------------------------------------- Refactoring gives us shorter, but less readable code: ---------------------------------------------------------------- def c_lambda(&b) lambda{|f| h={} ; lambda{|*args| h[*args] ||= f[*args]}}[lambda(&b)] end fac = c_lambda{|n| n < 2 ? 1 : (1..n).inject{|f, i| f * i}} tri = c_lambda{|n, r| fac[n] / (fac[r] * fac[n-r])} size = c_lambda{|r| tri[r-1, r / 2].to_s.size + 1} line = c_lambda{|y, r| (0..y).map{|x| tri[y,x].to_s.center size[r]}} lines = c_lambda{|r| (0...r).map{|y| line[y, r]}} pascal = c_lambda{|r| lines[r].map{|l| l.join.center(size[r]*r).rstrip}} puts pascal[(ARGV[0] || 15).to_i] ---------------------------------------------------------------- gegroet, Erik V. - http://www.erikveen.dds.nl/