From: Joel VanderWerf Date: 2006-04-27T02:56:27+09:00 Subject: Re: Rake task dependeny vs. method call I'm really confused about the rest of the examples (it looks to me like task uidgen is sometimes acting as a "singleton service" and sometimes as a "parametric service"), but I think I understand this one: ara.t.howard@noaa.gov wrote: > as far as i can tell it also fails to detect cycles: > > harp:~ > cat b.rb > require 'tasklib' > > task :b => :a and task :a => :b > > b() > > > harp:~ > ruby b.rb > ./tasklib.rb:21:in `a': stack level too deep (SystemStackError) > from (eval):8:in `a' > from ./tasklib.rb:21:in `b' > from ./tasklib.rb:21:in `b' > from (eval):8:in `b' > from ./tasklib.rb:21:in `a' > from ./tasklib.rb:21:in `a' > from (eval):8:in `a' > from ./tasklib.rb:21:in `b' > ... 2219 levels... > from ./tasklib.rb:21:in `b' > from ./tasklib.rb:21:in `b' > from (eval):8:in `b' > from b.rb:5 This means that we are just using different code :) Here's mine (pls. excuse the module_eval string argument, it is very old code), with a stripped down version of T's task code: module Task def cache(method_name) module_eval %{ alias :__compute_#{method_name} :#{method_name} def #{method_name} if @#{method_name}_cached @#{method_name} else @#{method_name}_cached = true @#{method_name} = __compute_#{method_name} end end } end def task( args, &action ) if Hash === args raise ArgumentError, "#{args.size} for 1" if args.size != 1 name, *deps = *(args.to_a.flatten) name = name.to_sym deps = deps.compact.collect{ |e| e.to_sym } else name, deps = args.to_sym, [] end (@task_dependencies||={})[ name ] = deps (class << self; self; end).class_eval do define_method( name ) do deps.each{ |d| send(d) } action.call if action end cache name end end end include Task task :b => :a do puts "b" end task :a => :b do puts "a" end b() Output: a b -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407