[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: [QUIZ][SOLUTION] metakoans.rb (#67

Patrick Hurley

2/20/2006 5:11:00 PM

Ok here is my solution:

class Module
def attribute(sym, *more, &blk)
attribute(*more, &blk) unless more.empty?
if sym.is_a?(Hash)
sym.each_pair { |sym, dval| attribute(sym, &(blk || lambda { dval })) }
else
iname = "@#{sym}"
define_method(sym) do
if instance_variables.include?(iname)
instance_variable_get(iname)
else
if blk then instance_eval(&blk) end
end
end
attr_writer(sym)
alias_method("#{sym}?", sym)
end
end
end

A polite and fairly readable, if completely uncommented 19 lines with
support for multiple symbols both in and out of the hash. And here is
the same solution painfully golfed into 4 lines of code -- by the way,
having unit tests are invaluable when golfing, I should have realized
this as golfing is just a deranged form of refactoring, but not being
a golfer this was enlightening :-)

class Module;def attribute(s,*r,&b);attribute(*r,&b) if r.any? ;(Hash===s)?
(s.each {|s,d|attribute(s,&(b||lambda{d}))}):(define_method(s){
instance_variables.include?("@"+s)?instance_variable_get("@"+s):(b&&
instance_eval(&b)||nil)};attr_writer(s);alias_method(s+"?",s));end;end

pth


3 Answers

ToRA

2/20/2006 7:01:00 PM

0

Hey,

Genius quiz. I'm trying with my solution to avoid using def/class etc.
and solve just using the meta-programming methods (and without evaling
random strings); "just for fun", though I'm coming unstuck with
defining a method that can accept a block as a second argument....

Module.instance_eval do
define_method :attribute do |arg|
....

block_given? and yield always fail, and "do |arg,&block|" isn't legal
syntax...any suggestions?

Cheers,

Tris

MenTaLguY

2/20/2006 7:09:00 PM

0

Quoting ToRA <tristan.allwood@gmail.com>:

> block_given? and yield always fail, and "do |arg,&block|" isn't
> legal syntax...any suggestions?

Blocks that take blocks aren't possible in Ruby 1.8; you'll have to
use def and/or eval.

-mental


ToRA

2/20/2006 7:43:00 PM

0

> Blocks that take blocks aren't possible in Ruby 1.8; you'll have to
> use def and/or eval.

Ah, yeah...just found another post explaining this. :(

Oh well, my solution, don't think there's anything too novel in it
though...

Module.module_eval do
def attribute(arg,&block) # I bow to the impossible


case when block_given?
default_value = true
when Hash === arg
inst_var_name, default_value = arg.to_a.flatten
end

inst_var_name ||= arg
inst_var = "@#{inst_var_name || arg}"

define_method inst_var_name do
if default_value and not instance_variables.member?(inst_var)
if block_given?
instance_variable_set inst_var, instance_eval(&block)
else
instance_variable_set inst_var, default_value
end
end


instance_variable_get inst_var

end



define_method("#{inst_var_name}=") do |v|

instance_variable_set inst_var, v

end



alias_method("#{inst_var_name}?", inst_var_name)

end

end