[SOLUTION] metakoans.rb (#67)

F

Florian Groß

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

Ruby said:
# 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--
 
J

James Edward Gray II

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
 
R

Ryan Leavengood

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
 
M

Michael Ulm

Christian said:
=20
=20
=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: (e-mail address removed)
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.
---------------------------------------------------------------
 
M

Michael Ulm

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: (e-mail address removed)
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.
---------------------------------------------------------------
 
J

James Edward Gray II

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
 
M

Michael Ulm

James said:
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: (e-mail address removed)
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.
---------------------------------------------------------------
 
J

Jeremy Hinegardner

--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 (e-mail address removed)


--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--
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top