Metakoans.rb (#67)

Quoting Wilson B. [email protected]:

Just got mine down to 30. I’m really looking forward to seeing
the shortest solution, because I have a feeling it’s going to
humiliate that.

23, with copious whitespace.

It’s like Taoist golf. Strive without striving.

-mental

Quoting [email protected]:

per-object - where object may be a class (singleton method).

Hmm, would semantics like Hash’s default block be acceptable?

-mental

On Sat, 18 Feb 2006, Wilson B. wrote:

(Final result, 42 lines, with whitespace)

Just got mine down to 30. I’m really looking forward to seeing the
shortest solution, because I have a feeling it’s going to humiliate
that.

42 is the clear winner - regardless of who goes shorter :wink:

-a

Mine’s also 42 non-blank, non-comment lines. I can see many ways to
reduce that, but all would uglify the code or slow it down. By moving
some logic inside a define I could cut that to 35, but I prefer to do
as much of the logic out of define_methods as possible.

On 2/17/06, [email protected] [email protected] wrote:

Jacob F.

(Final result, 42 lines, with whitespace)

Just got mine down to 30. I’m really looking forward to seeing the
shortest solution, because I have a feeling it’s going to humiliate
that.

42 is the clear winner - regardless of who goes shorter :wink:

I got it down to 15, but I can pad it to 42 with some haiku. Heh.

I’m at 13

[email protected] writes:

Quoting Wilson B. [email protected]:

Just got mine down to 30. I’m really looking forward to seeing
the shortest solution, because I have a feeling it’s going to
humiliate that.

23, with copious whitespace.

It’s like Taoist golf. Strive without striving.

23 here too, I could go <20 easily, but this way it’s nice to read.

14 lines here, with no really long lines.
could reduce it to 8, but it’s much easier to read this way.

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…

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.

-mental

Geez. Seeing all these tiny line counts tells me that I’m missing
something fundamental, and that I’m not likely to “get it” if I’ve
never done this type of programming before. How depressing. Why bother?

My current attribute method is just 8 lines, but the whole solution is
16 (normal length lines).
But I’m not completely happy with my implementation so I’m looking
forward to seeing what other people did.

It has been said already, but it bears repeating: Great quiz - both the
idea and the execution.
It motivated me so much that this is the first quiz I actually
completed!

  • Peter

In article [email protected],
Christian N. [email protected] wrote:

It’s like Taoist golf. Strive without striving.

23 here too, I could go <20 easily, but this way it’s nice to read.

I’ve got a very readable 18 lines.

I really enjoyed this quiz.

Phil

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.

Dunno about golfing, been snowboarding the whole week.

I’m near koan 8 with 28 lines, and I need sleep (failed at 7, while
wondering why the program knew I did [need sleep]; Then I solved 7 while
puzzling about 8, or actually ironing out an inconsistency in my
program;
maybe I am already asleep)

Anyway, what I wanted to post about: in the description/code there are a
few
asserts like this:
assert{ (o.a = nil) == nil }
which will always be asserted, since Ruby evaluates ‘a = b’ to b, no
matter
what a is; specifically, it does not evaluate to the result of #a= in
code
like ‘o.a = b’; imho, this makes perfect sense for statements like ‘a =
b = c’

Code to show:

class X
attr_reader :ha
def ha=(val)
@ha = “not what you expect”
end
end
x = X.new
p x.ha = nil # => nil
p x.ha # => “not what you expect”
p (x.ha = nil) == nil # => true

Bye,
Kero.

PS: fun quiz!

On 2/18/06, Timothy G. [email protected] wrote:

              user     system      total        real

attr 3.720000 0.000000 3.720000 ( 3.724316)
attribute 25.750000 0.000000 25.750000 ( 25.790665)

It isn’t that efficient, but I’d like to see how it compares.

That’s interesting. I didn’t expect the difference to be quite this
big. attr is impressively fast.
user system total real
attr 7.250000 0.000000 7.250000 ( 7.250000)
attribute 30.110000 0.000000 30.110000 ( 30.172000)

I’m looking forward to seeing some of the other solutions, for sure.
I had my hands halfway around a faster way, but couldn’t quite make it
work.

To take the focus off number of lines, let’s take a look at bechmarks.
This was my benchmark script:

Benchmark::bm(12) do |x|
x.report(‘attr’) {100000.times {c = Class.new {attr :foo, :bar}}}
x.report(‘attribute’) {100000.times {c = Class.new {attribute :foo,
:bar}}}
end

And my results were:

              user     system      total        real

attr 3.720000 0.000000 3.720000 ( 3.724316)
attribute 25.750000 0.000000 25.750000 ( 25.790665)

It isn’t that efficient, but I’d like to see how it compares.

On 2006.02.19 10:30, Wilson B. wrote:

And my results were:
user system total real
attr 7.250000 0.000000 7.250000 ( 7.250000)
attribute 30.110000 0.000000 30.110000 ( 30.172000)

I’m looking forward to seeing some of the other solutions, for sure.
I had my hands halfway around a faster way, but couldn’t quite make it
work.

Yours actually looks very good. My first attempt is quite a bit off:

                user     system      total        real

attr 7.117188 0.000000 7.117188 ( 7.381454)
attribute 38.835938 0.031250 38.867188 ( 41.244430)

To factor out some machine differential, mine works out to be about
5.46 times slower, yours is 4.15 and Timothy is at 7.45. Another
interesting tidbit is that attr_accessor is about 1.5 to 2 times
slower than attr.

From another standpoint, it might be interesting to look at
access and update speeds. Here is the script:

require ‘benchmark’
require ‘knowledge’

Benchmark.bm {|b|
b.report(‘attr_accessor’) {c = Class.new {attr_accessor :foo}.new;
c.foo = 2; 100_000.times {c.foo}}
b.report(‘attribute-plain’) {c = Class.new {attribute :foo}.new;
c.foo = 2; 100_000.times {c.foo}}
b.report(‘attribute-default’) {c = Class.new {attribute(:foo)
{2}}.new; 100_000.times {c.foo}}
}

                     user     system      total        real

attr_accessor 0.046875 0.000000 0.046875 ( 0.052311)
attribute-plain 0.343750 0.000000 0.343750 ( 0.364738)
attribute-default 0.460938 0.000000 0.460938 ( 0.474879)

So there is clear order-of-magnitude difference there.

E

attr_* are written in c if I’m not mistaken. That might explain (at
least some of) the difference.

+1 on this being an excellent quiz. Thanks again Ara

-Harold

I wasn’t going to get into benchmarking this one, but …

On Sun, 2006-02-19 at 12:45 +0900, Eero S. wrote:

big. attr is impressively fast.
user system total real
attr 7.117188 0.000000 7.117188 ( 7.381454)
attribute 38.835938 0.031250 38.867188 ( 41.244430)

To factor out some machine differential, mine works out to be about
5.46 times slower, yours is 4.15 and Timothy is at 7.45. Another
interesting tidbit is that attr_accessor is about 1.5 to 2 times
slower than attr.

I think maybe there is some confusion over the operation of ‘attr’ here,
the test above defines a single attribute, :foo. The second argument to
‘attr’ is evaluated as boolean, and determines whether a writer is
created also. So the test will make foo and foo= but not bar or bar= .
Consider the following IRB:

class C
  attr :one, :two
end
# => nil

c = C.new
# => #<C:0xb7e34534>

c.one
# => nil
c.one = 'one'
# => "one"
c.two
NoMethodError: undefined method `two' for #<C:0xb7e34534>
        from (irb):11

}

                     user     system      total        real

attr_accessor 0.046875 0.000000 0.046875 ( 0.052311)
attribute-plain 0.343750 0.000000 0.343750 ( 0.364738)
attribute-default 0.460938 0.000000 0.460938 ( 0.474879)

So there is clear order-of-magnitude difference there.

After modifying the original benchmark to use attr_accessor (for
completeness really, they’re all implemented in C AFAIK so comparison is
pretty futile from the start ;)) and adding in the code above, I get:

Creation

                      user     system      total        real

attr 4.930000 0.040000 4.970000 ( 5.066622)
attribute 16.080000 0.130000 16.210000 ( 16.429639)

Use

                      user     system      total        real

attr_accessor 0.080000 0.010000 0.090000 ( 0.123403)
attribute-plain 0.730000 0.000000 0.730000 ( 0.777927)
attribute-default 0.700000 0.010000 0.710000 ( 0.755691)

MenTaLguY wrote:

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.

-mental

Yea, I don’t usually golf, so I’m torn as to what’s reasonable and
what’s golfing, in terms of line count. Right now I’m at 17, and I got
it down to 13 or 14 before changing it back cause I found the new code
aesthetically displeasing.