From: Greg Millam Date: 2006-02-20T04:55:30+09:00 Subject: Re: [SOLUTION] metakoans.rb (#67) Here's my solution: Took me about 15 minutes to solve the koans. I agree with everyone else: Great quiz =). Continuous fiddling with it made me late for a date, and when I tried explaining why, she just stared at me. "Meta cones? What's that?" Ah well! My koan solution, 9 lines: def one_attribute(arg,&b) name = (arg.is_a?(Hash) ? arg.keys[0] : arg).to_s p = Hash.new( arg.is_a?(Hash) ? arg[name] : nil ) fun = lambda { |*args| p[self] = *args unless args.empty? (p.include?(self) or !b) ? p[self] : instance_eval(&b) } ['','?','='].each { |ch| define_method(name+ch,&fun) } end And to make it accept multiple arguments to work with the benchmark suites (10 lines): def attribute(arg,&b) attribute(*rest,&b) if rest.any? name = (arg.is_a?(Hash) ? arg.keys[0] : arg).to_s p = Hash.new( arg.is_a?(Hash) ? arg[name] : nil ) fun = lambda { |*args| p[self] = *args unless args.empty? (p.include?(self) or !b) ? p[self] : instance_eval(&b) } ['','?','='].each { |ch| define_method(name+ch,&fun) } end With comments: def attribute(arg,&b) # Allow multiple attributes to be set and defined. attribute(*rest,&b) if rest.any? # The name of the attribute. name = (arg.is_a?(Hash) ? arg.keys[0] : arg).to_s # p holds all the attributes for each object. # This is wasteful since in real use, this would cause # Each object that's set an attribute to be kept in # memory. p = Hash.new( arg.is_a?(Hash) ? arg[name] : nil ) # The only method I define: It takes 1 or more arguments. # If it's given an argument, it assigns. In all cases, # It returns. fun = lambda { |*args| # Assign if necessary. p[self] = *args unless args.empty? # If it's been assigned, or there's no block, return # Its saved value (Or Hash's default) (p.include?(self) or !b) ? p[self] : instance_eval(&b) } # Assign that method to all 3 methods we need. ['','?','='].each { |ch| define_method(name+ch,&fun) } end More quizzes like this would be much appreciated. It rocked. Ara++ - Greg