MenTaLguY wrote:
On Sat, 2006-02-18 at 23:41 +0900, Patrick H. wrote:
I also have 13; however, two lines exceed 80 columns. Additionally,
I
have no support for multiple attributes on one line – seems logical
to have…
13 seems to be the lower limit without seriously golfing. My “best”
solution at this point runs about 18 lines, but it’d be 13 if I took
out
all the blank lines and one line that makes it faster but doesn’t
affect
the semantics.
Mine’s at 9 without any real golfing. No newlines though. Maximum line
length’s 67, and that’s the largest by far. I use “cond ? true : false”
4 times though, and that could be cleaner, I imagine.
However: While it passes all the tests, it might have some poor flaws in
real world use.
i.e:
- Anything with the same hash would have the same attributes. (i.e: 2
string objects containing the same text)
- Every instance of the class that uses the attribute is kept in
memory so long as the class is.
- foo? returns the value, instead of exact true/false. While this is
legit, it can’t be used in (a.foo? == false) conditionals. But that’s
unrubylike anyway
My solution is attached. Actually, two different styles of the same
solution. Neither one is anywhere near 13 lines – I’ll be very
interested to see the work of people who actually know this language.
A couple of subtleties. (1) The first time the attribute is set, I
redefine the setter and getter to just be ivar accessors. (2) I only
ever evaluate the block once: the initial version of the getter calls
the setter with the result of evaluating the block.
And I’ll echo everyone else: excellent quiz.
Luke B.
“Harold H.” [email protected] writes:
attr_* are written in c if I’m not mistaken. That might explain (at
least some of) the difference.
Not only that, it directly circumvents further method calls and
accesses the instance variable table directly. No way to beat that in
pure Ruby.
+1 on this being an excellent quiz. Thanks again Ara
Full ack.
This was not my first solution. It wasn’t until Timothy G.
posted his benchmarking method I realized I ought to be supporting
multiple variables for a single call. This wasn’t needed for passing
the koans, but I thought it would be neat to do.
Thanks for a fun quiz!
/Christoffer
def attribute(*definition, &block)
raise “Name missing when creating attribute” unless
definition.length > 0
definition.each do |entry|
if entry.respond_to?(:to_hash)
entry.to_hash.each_pair { |key, value| insert_attribute(key,
value, block) }
else
insert_attribute(entry, nil, block)
end
end
end
def insert_attribute(name, value, block)
default_value = block ? “instance_eval(&block)” : “value”
begin
attr_writer name.to_s
eval(“define_method(:#{name}) { return @#{name} if defined? @#
{name}; @#{name} = #{default_value}}”)
eval(“define_method(:#{name}?) { self.#{name} != nil }”) # this
could also simply alias the getter and still pass.
rescue SyntaxError
raise “Illegal attribute name ‘#{name}’”
end
end
Ruby Q. wrote:
metakoans.rb is an arduous set of exercises designed to stretch
meta-programming muscle. the focus is on a single method ‘attribute’ which
behaves much like the built-in ‘attr’, but whose properties require delving
deep into the depths of meta-ruby.
Here we go then.
I have a golfed (8 lines) and a regular solution (21 lines) and
generally do the simplest thing that makes the tests work.
Got it to run in two tries by the way. I failed the fourtytwo test at
first. After that everything worked fine. 
And thanks for a great quiz. Being able to do things test first rules!
Hi,
It’s 18 lines when you strip comments. The only thing with it is that
the #{sym}? query method doesn’t behave exactly right (returning true or
false) but it makes it a bit quicker.
Also I wished for instance_exec to allow the symbol to be passed to the
default block…
Thanks, Ara, for a cool quiz - I had more fun reading the quiz code than
writing my solution 
class Module
call-seq:
attribute :a -> true
attribute :a, :c => 45, :d => ‘stuff’ -> true
attribute(:a) { || default } -> true
attribute(:a, :b, :c => 4) { || default a, b } -> true
def attribute(*args, &blk)
args.inject({}) { |hsh,arg|
(arg.respond_to?(:to_hash) ? hsh.merge!(arg) : hsh[arg] = nil) ;
hsh
}.each { |sym, default|
ivar = :"@#{sym}"
define_method(sym) do
if instance_variables.include? ivar.to_s
instance_variable_get(ivar)
else
instance_variable_set(ivar, default || (instance_eval &blk if
blk))
# Ruby 1.9: (instance_exec(sym,
&blk) if blk))
end
end
# define_method("#{sym}?") { instance_variable_get(ivar) ? true :
false }
alias_method “#{sym}?”, sym
attr_writer sym
}.any?
end
end
The sane:
class Module
def attribute(arg, val=nil, &blk)
if arg.is_a?(Hash)
arg.each{|k,v| attribute(k,v)}
return
end
define_method(arg) do ||
if instance_variables.include?("@#{arg}")
instance_variable_get("@#{arg}")
else
blk ? instance_eval(&blk) : val
end
end
define_method("#{arg}?"){|| !send(arg).nil?}
attr_writer(arg)
end
end
The insane:
class Module
def attribute(a, &b)
b or return (Hash===a ? a : {a=>nil}).each{|k,v| attribute(k){v}}
define_method(a){(x=eval("@#{a}")) ? x[0] : instance_eval(&b)}
define_method("#{a}?"){!send(a).nil?}
define_method("#{a}="){|v| instance_variable_set("@#{a}", [v])}
end
end
On 2/19/06, George O. [email protected] wrote:
…
define_method(“#{arg}?”){|| !send(arg).nil?}
…
what about send(arg) == false ?
Here is my solution, pretty similar to the one george posted, though
it doesn’t support multiple attributes.
class Module
def attribute(a,&blk)
a,val = a.to_a[0] if a.kind_of? Hash
attr_accessor a
define_method(a+‘?’) { !!send(a) }
define_method(a) {
if instance_variables.include?(‘@’+a)
instance_variable_get(‘@’+a)
else
val || instance_eval(&blk)
end
} if val || blk
end
end
This solution is by memory, it seems my website
is down. I will post a corrected version if there
are any bugs in this but hopefully the idea is
clear.
knowledge.rb
class Module
def attribute(*args, &block)
# Normalise
args = args.inject([]) {|memo, arg|
if arg.kind_of? Hash
arg.map {|k,v| memo << [k, (block or lambda {v})]}; memo
else
memo << [arg, (block or lambda {instance_variable_get
“@#{arg}”})]
end
}
# Generate
args.each {|name, block|
# Retrieval
define_method("#{name}") {instance_variable_get "@#{name}" or
instance_eval &block}
# Query
define_method("#{name}?") {send “#{name}”}
# Assignment
define_method("#{name}=") {|value|
# Generate a simple accessor to avoid problems with nils and
defaults
class << self; self; end.send ‘define_method’, “#{name}”, lambda
{value} unless value
instance_variable_set “#{name}”, value
}
}
end # attribute
end # class Module
Should handle multiple arguments, block supercedes hash
parameters and so on. Not very pretty or particularly fast.
E
First the benchmarks:
% ruby bm1.rb
user system total real
attr 15.250000 0.130000 15.380000 ( 18.405451)
attribute 64.520000 0.730000 65.250000 ( 74.519375)
irb(main):001:0> 74.519/18.405
=> a 4X slowdown
% ruby bm2.rb
user system total real
attr_accessor 0.130000 0.000000 0.130000 ( 0.185192)
attribute-plain 0.370000 0.010000 0.380000 ( 0.662546)
attribute-default 0.590000 0.010000 0.600000 ( 0.794125)
Then the comments:
Nice quiz. I have been using ruby for 6 years and have never needed
define_method.
The binding of the instance method fortytwo from the class scope was
something
I hadn’t thought of. I now understand (I think) why one would use
define_method.
I also consider it a success when I can write code that doesn’t
include all a bunch of
call to instance_variable_set/get. All in all, I think the code came
out pretty clean.
And lastly the code:
class Module
def attribute(*parms, &block)
return parms[0].each { |p,v| attribute§ {v} } if parms
[0].kind_of?(Hash)
parms.each { |parm|
define_method("__#{parm}__", block) unless block.nil?
class_eval %{
attr_writer :#{parm}
def #{parm}
defined?(@#{parm}) ? @#{parm} : __#{parm}__
end
def #{parm}?
(defined?(@#{parm}) || defined?(__#{parm}__)) && !#
{parm}.nil?
end
}
}
end
end
== Or 10 lines of golf
class Module
def attribute(*parms, &block)
return parms[0].each { |p,v| attribute§ {v} } if parms
[0].kind_of?(Hash)
parms.each { |parm|
define_method("#{parm}", block) unless block.nil?
class_eval %{attr_writer :#{parm}
def #{parm};defined?(@#{parm}) ? @#{parm} : #{parm};end
def #{parm}?;(defined?(@#{parm}) || defined?(#{parm}))
&& !#{parm}.nil?;end}}
end
end
Jim F.
Florian Groß [email protected] writes:
generally do the simplest thing that makes the tests work.
Got it to run in two tries by the way. I failed the fourtytwo test at
first. After that everything worked fine. 
Here’s my solution, done in two tries too. Took about 15 minutes, I
think.
class Module
def attribute(a, &block)
if a.kind_of? Hash
a, default = a.to_a.first
else
default = nil
end
a = a.to_sym
ivar = "@#{a}"
define_method(a) {
if instance_variables.include? ivar
instance_variable_get ivar
else
block ? instance_eval(&block) : default
end
}
define_method("#{a}=") { |v| instance_variable_set ivar, v }
define_method("#{a}?") { !!__send__(a) }
end
end
And thanks for a great quiz. Being able to do things test first rules!
Yeah, it really was a fun quiz.
This is definitely a great quiz. I had a ton of fun working and and
learned a great deal about Ruby as well. I am relatively a Nuby.
Anyway, here is what I came up with:
class Module
def attribute(*objects, &block)
objects.each { |object|
attr = object.is_a?(Hash) ? object : {object => nil}
symbol = attr.keys[0]
default = block || lambda { attr[symbol] }
define_method("#{symbol}?") { instance_eval &default }
class_eval “alias #{symbol} #{symbol}?”
define_method("#{symbol}=") { |value|
instance_eval %{
def #{symbol}?; @#{symbol}; end
alias #{symbol} #{symbol}?
@#{symbol} = value
}
}
}
end
end
Jim F. [email protected] writes:
Nice quiz. I have been using ruby for 6 years and have never needed
define_method.
%-)
Here is mine. Nothing too extraordinary or different than other
solutions, but it is fairly short and readable.
class Module
def attribute(x, &block)
name, value = x.to_a[0] # produces a warning is x is a symbol
ivar = “@#{name}”
define_method(name) do
if instance_variables.include?(ivar)
instance_variable_get(ivar)
else
value || (instance_eval &block if block)
end
end
attr_writer name
define_method("#{name}?") { !!send(name) }
end
end
As others have said, this was a cool quiz. While the meta-programming
part was interesting, I think this quiz is a better advertisement for
test-first coding than anything! Very cool and fun test suite. Thanks
Ara.
Ryan
On Feb 19, 2006, at 8:21 AM, Florian Groß wrote:
Ruby Q. wrote:
metakoans.rb is an arduous set of exercises designed to stretch
meta-programming muscle. the focus is on a single method
‘attribute’ which
behaves much like the built-in ‘attr’, but whose properties
require delving
deep into the depths of meta-ruby.
Here we go then.
Here’s what I coded up, back when Ara sent me the quiz. Everyone
else found much prettier code though. 
James Edward G. II
#!/usr/local/bin/ruby -w
class Module
def attribute( name, &block )
if name.is_a? Hash
name.each do |attr_name, default|
define_method(attr_name) do
if instance_variables.include?("@#{attr_name}")
instance_variable_get("@#{attr_name}")
else
default
end
end
define_method("#{attr_name}=") do |value|
instance_variable_set("@#{attr_name}", value)
end
define_method("#{attr_name}?") do
send(attr_name) ? true : false
end
end
elsif block
define_method(name) do
if instance_variables.include?("@#{name}")
instance_variable_get("@#{name}")
else
instance_eval(&block)
end
end
define_method("#{name}=") do |value|
instance_variable_set("@#{name}", value)
end
define_method("#{name}?") do
send(name) ? true : false
end
else
define_method(name) do
instance_variable_get("@#{name}")
end
define_method("#{name}=") do |value|
instance_variable_set("@#{name}", value)
end
define_method("#{name}?") do
send(name) ? true : false
end
end
end
end
Here’s mine, it’s 8 one-liners of which one is randomly picked:
[
lambda{
puts “humbleness is a virtue”
def attribute(*a) end; module MetaKoans; def assert; 0 end end
},lambda{
puts “sometimes thinking about a problem makes it worse”
class MetaStudent; def ponder(a) 0 end end
},lambda{
puts “finish what you started”
def method_missing(*a) end; def abort(a) 0 end
},lambda{
puts “don’t overextend yourself”
public; def extend(m) def koan_0; 0 end end
},lambda{
puts “know thyself”;$-w=nil
class Array;def grep(a) [:id] end end
},lambda{
puts “don’t send a student to do a guru’s job”
class MetaStudent; def send(a) 0 end end
},lambda{
puts “question what you have been taught”
module MetaKoans; 9.times{|i| eval(“def koan_#{i+1};0 end”)} end
},lambda{
puts “appearances can deceive”
l=IO.read $0; puts (1…9).map{|@i| “koan_#@i”+l[998,28] }, l[1343,37];
exit
}
].instance_eval{ self[rand(size)][] }
My solution follows - I think it’s pretty straightforward. 16 lines
without golf. The only part I don’t really like is the a_init_
sentinel I had to add to pass Koan9. I messed around with redefining
the initializer in the call to a=, but I couldn’t get that to work
right.
One thing I noted: I could get through koans 1-5 with a def a; 42; end

class Object
def attribute name, &block
init_proc = proc {nil}
if block_given?
init_proc = block
elsif name.kind_of? Hash
v = name.values.first
name = name.keys.first
init_proc = proc{v}
end
self.send(:define_method, “#{name}init”, init_proc)
self.class_eval “def #{name}; if !@#{name}&&!@#{name}init then
@#{name}=#{name}init; @#{name}init=true; end; @#{name}; end”
self.class_eval “def #{name}?; !(self.#{name}.nil?); end”
self.class_eval “def #{name}=(v); @#{name}=v; end”
end
end
-Adam
I have the longest solution shown. 50 LINES!
Here it is:
class Module
def attribute( attrib, &block )
if attrib.is_a? String
then
if (block_given?) then
property_with_block_init(attrib, block )
else
property(attrib)
end
elsif attrib.is_a? Hash
attrib.each_pair do
|property, value|
property_with_default( property, value )
end
else
end
end
def property(name)
self.module_eval %Q{
attr_accessor name.to_sym
def #{name}?
not not #{name}
end
}
end
def property_with_block_init(name, block)
property(name)
self.module_eval do
define_method( name.to_sym ) do
if self.instance_variables.member?("@" + name) then
self.instance_variable_get("@" + name)
else
instance_eval( &block )
end
end
end
end
def property_with_default( name, value )
property(name)
self.module_eval do
define_method( name.to_sym ) do
if self.instance_variables.member?("@" + name) then
self.instance_variable_get("@" + name)
else
value
end
end
end
end
end
On Feb 19, 2006, at 1:36 PM, Ilmari H. wrote:
Here’s mine, it’s 8 one-liners of which one is randomly picked:
[snip - powerful meditation solving code]
This solution was priceless. 
James Edward G. II