[SOLUTION] metakoans.rb (#67)

Discussion in 'Ruby' started by Florian Groß, Feb 19, 2006.

  1. --------------060908050001010004030905
    Content-Type: text/plain; charset=ISO-8859-15; format=flowed
    Content-Transfer-Encoding: 7bit

    Ruby Quiz 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!

    --
    http://flgr.0x42.net/

    --------------060908050001010004030905
    Content-Type: application/x-ruby;
    name="flgr-metakoans-golfed.rb"
    Content-Transfer-Encoding: base64
    Content-Disposition: inline;
    filename="flgr-metakoans-golfed.rb"

    Y2xhc3MgTW9kdWxlOyBkZWYgYXR0cmlidXRlKG5hbWUsICZibG9jaykNCiAgbmFtZSwgZGVm
    YXVsdCA9ICpuYW1lLnNoaWZ0IGlmIG5hbWUuaXNfYT8oSGFzaCkNCiAgaXZhciwgZGVmYXVs
    dF9sYW1iZGEgPSAiQCN7bmFtZX0iLCBibG9jayB8fCBsYW1iZGEgeyBkZWZhdWx0IH0NCiAg
    ZGVmaW5lX21ldGhvZCg6IiN7bmFtZX09IikgeyB8dmFsfCBpbnN0YW5jZV92YXJpYWJsZV9z
    ZXQoaXZhciwgdmFsKSB9DQogIGRlZmluZV9tZXRob2QobmFtZSkgeyBpbnN0YW5jZV92YXJp
    YWJsZXMuaW5jbHVkZT8oaXZhcikgPw0KICAgIGluc3RhbmNlX3ZhcmlhYmxlX2dldChpdmFy
    KSA6IGluc3RhbmNlX2V2YWwoJmRlZmF1bHRfbGFtYmRhKSB9DQogIGFsaWFzX21ldGhvZCg6
    IiN7bmFtZX0/IiwgbmFtZSkNCmVuZDsgZW5kDQo=
    --------------060908050001010004030905
    Content-Type: application/x-ruby;
    name="flgr-metakoans.rb"
    Content-Transfer-Encoding: base64
    Content-Disposition: inline;
    filename="flgr-metakoans.rb"

    Y2xhc3MgTW9kdWxlDQogIGRlZiBhdHRyaWJ1dGUobmFtZSwgJmJsb2NrKQ0KICAgIG5hbWUs
    IGRlZmF1bHQgPSAqbmFtZS5zaGlmdCBpZiBuYW1lLmlzX2E/KEhhc2gpDQogICAgZGVmYXVs
    dF9sYW1iZGEgPSBibG9jayB8fCBsYW1iZGEgeyBkZWZhdWx0IH0NCiAgICBpdmFyID0gIkAj
    e25hbWV9Ig0KDQogICAgZGVmaW5lX21ldGhvZCg6IiN7bmFtZX09IikgZG8gfG5ld192YWx1
    ZXwNCiAgICAgIGluc3RhbmNlX3ZhcmlhYmxlX3NldChpdmFyLCBuZXdfdmFsdWUpDQogICAg
    ZW5kDQoNCiAgICBkZWZpbmVfbWV0aG9kKG5hbWUpIGRvDQogICAgICBpZiBpbnN0YW5jZV92
    YXJpYWJsZXMuaW5jbHVkZT8oaXZhcikgdGhlbg0KICAgICAgICBpbnN0YW5jZV92YXJpYWJs
    ZV9nZXQoaXZhcikNCiAgICAgIGVsc2UNCiAgICAgICAgaW5zdGFuY2VfZXZhbCgmZGVmYXVs
    dF9sYW1iZGEpDQogICAgICBlbmQNCiAgICBlbmQNCg0KICAgIGFsaWFzX21ldGhvZCg6IiN7
    bmFtZX0/IiwgbmFtZSkNCiAgZW5kDQplbmQNCg==
    --------------060908050001010004030905--
    Florian Groß, Feb 19, 2006
    #1
    1. Advertising

  2. On Feb 19, 2006, at 8:21 AM, Florian Gro=DF wrote:

    > Ruby Quiz wrote:
    >
    >> # metakoans.rb is an arduous set of exercises designed to =

    stretch
    >> # meta-programming muscle. the focus is on a single method =20
    >> 'attribute' which
    >> # behaves much like the built-in 'attr', but whose properties =20=


    >> 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 =20
    else found much prettier code though. ;)

    James Edward Gray 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}=3D") 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}=3D") 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}=3D") do |value|
    instance_variable_set("@#{name}", value)
    end

    define_method("#{name}?") do
    send(name) ? true : false
    end
    end
    end
    end
    James Edward Gray II, Feb 19, 2006
    #2
    1. Advertising

  3. 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 =3D x.to_a[0] # produces a warning is x is a symbol
    ivar =3D "@#{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
    Ryan Leavengood, Feb 19, 2006
    #3
  4. Florian Groß

    Michael Ulm Guest

    Christian Neukirchen wrote:

    > Florian Gro=DF <> writes:
    >=20
    >=20
    >>Ruby Quiz wrote:
    >>
    >>
    >>> # metakoans.rb is an arduous set of exercises designed to stretch
    >>> # meta-programming muscle. the focus is on a single method 'attribut=

    e' 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. :)

    >=20
    >=20
    > Here's my solution, done in two tries too. Took about 15 minutes, I
    > think.
    >=20
    >=20
    > class Module
    > def attribute(a, &block)
    > if a.kind_of? Hash
    > a, default =3D a.to_a.first
    > else
    > default =3D nil
    > end
    >=20
    > a =3D a.to_sym
    > ivar =3D "@#{a}"
    >=20
    > define_method(a) {
    > if instance_variables.include? ivar
    > instance_variable_get ivar
    > else
    > block ? instance_eval(&block) : default
    > end
    > }
    > define_method("#{a}=3D") { |v| instance_variable_set ivar, v }
    > define_method("#{a}?") { !!__send__(a) }
    > end
    > end
    >=20


    This demonstrates a problem I have with many solutions -- taking
    Florians as an example.

    class Test
    attribute 'a'
    end

    tst.a? # =3D> false OK
    tst.a =3D false # =3D> false OK
    tst.a? # =3D> false This should be true


    Regards,

    Michael

    --=20
    Michael Ulm
    R&D Team
    ISIS Information Systems Austria
    tel: +43 2236 27551-219, fax: +43 2236 21081
    e-mail:
    Visit our Website: www.isis-papyrus.com

    ---------------------------------------------------------------
    This e-mail is only intended for the recipient and not legally
    binding. Unauthorised use, publication, reproduction or
    disclosure of the content of this e-mail is not permitted.
    This email has been checked for known viruses, but ISIS accepts
    no responsibility for malicious or inappropriate content.
    ---------------------------------------------------------------
    Michael Ulm, Feb 20, 2006
    #4
  5. Florian Groß

    Michael Ulm Guest

    Michael Ulm wrote:

    --snip--
    >
    > This demonstrates a problem I have with many solutions -- taking
    > Florians as an example.
    >

    --snip--

    s/Florian/Christian/

    So sorry,

    Michael


    --
    Michael Ulm
    R&D Team
    ISIS Information Systems Austria
    tel: +43 2236 27551-219, fax: +43 2236 21081
    e-mail:
    Visit our Website: www.isis-papyrus.com

    ---------------------------------------------------------------
    This e-mail is only intended for the recipient and not legally
    binding. Unauthorised use, publication, reproduction or
    disclosure of the content of this e-mail is not permitted.
    This email has been checked for known viruses, but ISIS accepts
    no responsibility for malicious or inappropriate content.
    ---------------------------------------------------------------
    Michael Ulm, Feb 20, 2006
    #5
  6. On Feb 20, 2006, at 8:38 AM, Michael Ulm wrote:

    > This demonstrates a problem I have with many solutions -- taking
    > Florians as an example.
    >
    > class Test
    > attribute 'a'
    > end
    >
    > tst.a? # => false OK
    > tst.a = false # => false OK
    > tst.a? # => false This should be true


    I believe you are making the mistake that you expect attr_meth?() to
    tell you if an attribute is set. That's not the intention. attr_meth
    () returns true if the attribute holds a true value.

    I know this because I made the exact same mistake and Ara corrected
    me. ;)

    James Edward Gray II
    James Edward Gray II, Feb 20, 2006
    #6
  7. Florian Groß

    Michael Ulm Guest

    James Edward Gray II wrote:

    > On Feb 20, 2006, at 8:38 AM, Michael Ulm wrote:
    >
    >> This demonstrates a problem I have with many solutions -- taking
    >> Florians as an example.
    >>
    >> class Test
    >> attribute 'a'
    >> end
    >>
    >> tst.a? # => false OK
    >> tst.a = false # => false OK
    >> tst.a? # => false This should be true

    >
    >
    > I believe you are making the mistake that you expect attr_meth?() to
    > tell you if an attribute is set. That's not the intention. attr_meth
    > () returns true if the attribute holds a true value.
    >
    > I know this because I made the exact same mistake and Ara corrected
    > me. ;)


    I just checked the metakoans.rb file, and see that you are right:

    # o.a? # query - true if @a

    Had I defined the interface, this would behave differently. I guess
    this shows that I am not enlightened yet.

    Regards,

    Michael


    --
    Michael Ulm
    R&D Team
    ISIS Information Systems Austria
    tel: +43 2236 27551-219, fax: +43 2236 21081
    e-mail:
    Visit our Website: www.isis-papyrus.com

    ---------------------------------------------------------------
    This e-mail is only intended for the recipient and not legally
    binding. Unauthorised use, publication, reproduction or
    disclosure of the content of this e-mail is not permitted.
    This email has been checked for known viruses, but ISIS accepts
    no responsibility for malicious or inappropriate content.
    ---------------------------------------------------------------
    Michael Ulm, Feb 20, 2006
    #7
  8. --huq684BweRXVnRxX
    Content-Type: text/plain; charset=us-ascii
    Content-Disposition: inline

    Great quiz Ara, and here's my solution. For some reason I wasn't using
    instance_eval correctly, so I ended up defining an initalizer method for
    the attribute. Also, I seem to have implemented the attr? method in a
    manner different than most folks.

    enjoy,

    -jeremy

    --
    ========================================================================
    Jeremy Hinegardner


    --huq684BweRXVnRxX
    Content-Type: text/plain; charset=us-ascii
    Content-Disposition: attachment; filename="ruby-quiz_67.rb"


    # ruby quiz #67 - knowledge.rb
    #
    # Jeremy Hinegardner

    class Module

    def _make_attribute(name,value=nil)
    at = "@#{name}"
    sym = at.to_sym
    name_init = "_#{name}_init"

    if value.respond_to?("call") then
    define_method(name_init,value)
    end

    define_method(name) do
    if not self.instance_variables.include?(at) then
    initial_value = value
    if self.methods.include?(name_init) then
    initial_value = self.send(name_init)
    end
    self.instance_variable_set(sym,initial_value)
    end
    self.instance_variable_get(sym)
    end

    define_method("#{name}=") { |val| self.instance_variable_set(sym,val) }
    define_method("#{name}?") { not [false, nil].include?(self.instance_variable_get(sym)) }
    end

    def attribute(*args, &block)
    args.each do |arg|
    if arg.kind_of?(Hash) then
    arg.each_pair do |k,v|
    if block_given? then
    _make_attribute(k,block)
    else
    _make_attribute(k,v)
    end
    end
    else
    _make_attribute(arg,block)
    end
    end
    end
    end


    --huq684BweRXVnRxX--
    Jeremy Hinegardner, Feb 21, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andrew Francis
    Replies:
    0
    Views:
    401
    Andrew Francis
    Jun 28, 2006
  2. =?Utf-8?B?Y2FzaGRlc2ttYWM=?=

    Solution file not in the solution folder

    =?Utf-8?B?Y2FzaGRlc2ttYWM=?=, Sep 12, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    1,091
    Laurent Bugnion
    Sep 12, 2006
  3. , India
    Replies:
    17
    Views:
    1,026
    James Kanze
    Oct 1, 2007
  4. Luke Blanshard

    [/QUIZ] metakoans.rb (#67)

    Luke Blanshard, Feb 19, 2006, in forum: Ruby
    Replies:
    8
    Views:
    116
    George Ogata
    Feb 21, 2006
  5. Ari Brown

    [Solution][QUIZ] #67 metakoans.rb

    Ari Brown, Oct 6, 2007, in forum: Ruby
    Replies:
    0
    Views:
    69
    Ari Brown
    Oct 6, 2007
Loading...

Share This Page