[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Re: [SOLUTION] metakoans.rb (#67

Ilmari Heikkinen

2/19/2006 7:37:00 PM

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=nilclass 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)][] }
5 Answers

Adam Shelly

2/19/2006 8:18:00 PM

0

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


hitesh.jasani@gmail.com

2/19/2006 9:47:00 PM

0

Here's my solution. It ends up at 13 lines, as long as you don't mind
one line going past 80 chars. Kudos to Ara for such an interesting
quiz.

class Module
def attribute sym, &blk
name, dval = sym, false
name, dval = sym.keys.first, sym.values.first if Hash === sym
if blk
dval = "def_value_#{sym}".to_sym
define_method(dval, blk)
end
module_eval %( def #{name}; @#{name} ||= #{dval}; end )
module_eval %( def #{name}=(val); if NilClass === val then @#{name}
= lambda{nil}.call; else @#{name} = val; end; end )
module_eval %( def #{name}?; @#{name} ? true : false ; end)
end
end

- Hitesh
http://www.j...

James Gray

2/20/2006 12:44:00 AM

0

On Feb 19, 2006, at 1:36 PM, Ilmari Heikkinen 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 Gray II


Adam Shelly

2/21/2006 6:23:00 PM

0

On 2/19/06, Adam Shelly <adam.shelly@gmail.com> wrote:
> The only part I don't really like is the a_init_
> sentinel I had to add to pass Koan9.

Ok, after looking at some of the other solutions, I've refined my solution.
It now handles multiple attributes with initializers.
I think I disagree with Ara about what to do when provided with both a
block and a hash. With multiple attributes, it makes more sense to me
if the block acts as a default, rather than an override, so that you
get the following:
t = Class.new {attribute(:a,:b=>4,:c=>2){10*b+c} }.new
[t.a, t.b, t.c] => [42, 4, 2]
To get Ara's preferred behaviour, just add `,&block` before the `and`
on the 4th line.

I notice that most people extended Module, while I extended Object.
Is there a reason to prefer one over the other?

-Adam

#-------Knowledge.rb
#
class Object
def attribute *names, &block
names.each do |name|
attribute *name.map{|k,v|[k,v]} and next if name.kind_of? Hash
name,v = name
class_eval "def #{name};"+
"@#{name}=(defined?(@#{name}) ? @#{name} : #{name}_init_); end"
class_eval "def #{name}?; !(self.#{name}.nil?); end"
class_eval "def #{name}=(v); @#{name}=v; end"
private; define_method("#{name}_init_", block || proc {v})
end
end
end


Adam Shelly

2/21/2006 9:22:00 PM

0

On 2/21/06, Ross Bamford <rossrt@roscopeco.co.uk> wrote:
> Well, you're extending Object with a method that relies on methods
> defined in Module (class_eval), and your method is available in places
> where it really didn't ought to be.

aha.
I am not yet sufficiently enlightened about metaclasses.
I need more koans.