On Aug 3, 4:53 pm, Keith Rarick <k... / essembly.com> wrote:
> I've been using ruby for about 8 months now and I've come to appreciate
> its powerful features. But I misspython'sdecorators, so I made
> something similar.
>
> The code is attached; here are some examples. It's really easy to use a
> decorator:
>
> class C
>   memoized
>   def tak(x, y, z)
>     return z if x <= y
>     tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
>   end
> end
>
> And really easy to write one:
>
> class Module
>   decorator
>   def memoized(name, f)
>     lambda do |*args|
>       ((@__memo_cache ||= {})[[name, args]] ||=
> [f.bind(self).call(*args)])[0]
>     end
>   end
> end
>
> You can use this to do all of the usual decorator things, like
> memoization, method call tracing, synchronization, currying, type
> checking, basic profiling, print warnings for deprecated methods, or
> anything else you can think of.
>
> One important limitation of this implementation is that you cannot
> "stack" decorators like you can inpython. That's fixable, and hopefully
> I'll have time to make another version of this library with stackable
> decorators. But until then, maybe someone will find this useful.
>
> I'd love to hear feedback about this library! If you have any comments
> or questions, please let me know.
>
> kr
>
> Attachments:http://www.ruby-forum.com/attachment/52/deco.rb

This is quite interesting.

I'm not sure how I feel about the use of declarative style. I'm not a
big fan of public, private, protected to begin with b/c of this. It
also complicates the code dealing with method_added and wrapping
methods... I wonder how robust it is. (This is another good example of
where some built in AOP functionality could improve things.)

Though it's a bit less convenient, it might be better to just name the
method:

  class C
    def tak(x, y, z)
      return z if x <= y
      tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
    end
    memoized :tak
  end

Unfortunately, not as nice, but the underlying code would certainly
get simplified.

Dreaming a little. I wonder, if there were a callback for when a class/
module closes, then maybe you do do it lazily? Also, I wonder if this
corresponds to Matz' idea of ":"-notation he used for pre and post.
So,

  class C
    def tak:memoized(x, y, z)
      return z if x <= y
      tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
    end
  end

Of course we could always do:

  class C
    def_memoized :tak do |x, y, z|
      return z if x <= y
      tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
    end
  end

Though the lack of block support and closed scope make that not quite
the same.

Oh, one last thing. Could you give some other examples? Memoization
perhaps isn't the best, since most times it is as easy as:

  class C
    def initialize
      @_tak = {}
    end

    def tak(x,y,z)
      @_tak[x,y,z]] ||= (
        return z if x <= y
        tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
      )
    end
  end

T.