------art_68_25611621.1140442893761
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

here is my solution,

i wrote it before people asked specific questions about the semantics
of some operations, which means the semantics doesn't exactly map to
the ones later specified by ara. [somehow shows some of the
disadvantages with test-driven development =)]. none of the things
mentioned should be particularly hard to change though.

anyway, it's not terribly long, not terribly short, and i haven't
tested the performance, but i've  tried to layer my solution on top of
attr_accessor, instead of defining completely new methods, and by my
quick look through the other responses, not so many other decided to
it that way.

!g

------art_68_25611621.1140442893761
Content-Type: application/octet-stream; name=q67-know.rb
Content-Transfer-Encoding: 7bit
X-Attachment-Id: f_ejwun4m2
Content-Disposition: attachment; filename="q67-know.rb"

#!/usr/bin/env ruby
#
# Ruby Quiz #67, metakoans.rb
# http://www.rubyquiz.com/quiz67.html
#
# You should write an implementation of a single method 'attribute'
# which behaves much like the built-in 'attr', but whose properties
# require delving deep into the depths of meta-ruby. usage of the
# 'attribute' method follows the general form of
#
#   class C
#     attribute 'a'
#   end
#
#   o  ::new
#   o.a  2 # setter - sets @a
#   o.a # getter - gets @a
#   o.a? # query - true if @a
#
# The implementation should pass execution of the metakoans.rb script,
# without any problems, which should produce something like this:
#
#   dust:~ > ruby metakoans.rb q67-meta.rb
#   koan_1 has expanded your awareness
#   koan_2 has expanded your awareness
#   koan_3 has expanded your awareness
#   koan_4 has expanded your awareness
#   koan_5 has expanded your awareness
#   koan_6 has expanded your awareness
#   koan_7 has expanded your awareness
#   koan_8 has expanded your awareness
#   koan_9 has expanded your awareness
#   mountains are again merely mountains

class Object

  # Works much in the same way as isntance_variable_get, but with the
  # same features that the fetch method of Array and Hash, meaning
  # that an IndexError will be raised if a variable by the given name
  # doesn't exist.
  def instance_variable_fetch(name)
    r  nstance_variable_get(name)
    raise IndexError unless r or instance_variables.include?(name)
    r
  end

end

class Module

  # Works much in the same way as attr_accessor, but allows you to
  # specify a default value, either by using a hash as in:
  #
  #   attribute :a 42
  #
  # or by supplying a procedure:
  # 
  #   attribute :a { 42.to_s }
  # 
  # The method also provides an additional accessor function name?,
  # which might be more suiting in some contexts
  #
  def attribute(name, &block)
    if name.is_a?(Hash) and name.size 1
      name, default_value  ame.detect { true }
      block  roc { default_value }
    end
    module_eval do
      attr_accessor name
      if block
        define_method name do
          instance_variable_fetch("@#{name}") rescue instance_eval(&block)
        end
      end
      alias_method "#{name}?", name
    end
  end

end

if $0 __FILE__
  exec './metakoans.rb', $0
end


------art_68_25611621.1140442893761--