Transparent Lazy execution

I have often wanted to execute a bit of code only if the result of
that code is used later. For example in a Rails app I might load some
data in my controller but sometimes depending on some situations the
result is not actually used in the view.

So what I want is to be able to do:

@recent = lazy { Post.find_recent 5 }

But then if @recent is never used the actual search is not executed.
But because I don’t want to break compatibility once @recent is used I
want it to act and behave exactly like it is the return value of the
block. Even the core methods like class and respond_to? should return
the correct values.

So I took my first stab at it. You can see it at:

http://files.pixelwareinc.com/transparent_lazy.rb

My questions are:

  1. What trouble am I getting myself into by allowing this object to
    completely loose it’s identity?
  2. What holes are in the armor? Is there any way my proxy class does
    not act like the result of the block? If there are, do they matter?
  3. What are the performance and memory implications?

The only hole I can think of is that you see the proxy if you are
stepping through your code. This is no big deal to me.

There would be a slight memory increase as there is an extra object
but it should be insignificant. And everything should be garbage
collected when nothing is using the proxy object anymore so I don’t
forsee any memory leaks. Obviously every call to the lazy-loaded data
incurs an extra method call but I think I can live with that.

My next step will be to monkey-patch this into Rails so that
ActiveRecord::Base.find will use the lazy method by default. This will
allow everything to be lazy loaded without having to change a single
line of code in my application.

On Mar 14, 2:59 pm, Eric A. [email protected] wrote:

But because I don’t want to break compatibility once @recent is used I

  1. What trouble am I getting myself into by allowing this object to
    collected when nothing is using the proxy object anymore so I don’t
    forsee any memory leaks. Obviously every call to the lazy-loaded data
    incurs an extra method call but I think I can live with that.

My next step will be to monkey-patch this into Rails so that
ActiveRecord::Base.find will use the lazy method by default. This will
allow everything to be lazy loaded without having to change a single
line of code in my application.

Have you looked at lazy.rb?

T.

On Mar 14, 2008, at 12:59 PM, Eric A. wrote:

@recent = lazy { Post.find_recent 5 }

gem install fattr

fattr(:recent){ Post.find_recent 5 }

http://www.rubyquiz.com/quiz67.html

a @ http://codeforpeople.com/

On Mar 14, 6:23 pm, Trans [email protected] wrote:

Have you looked at lazy.rb?

Yes, I saw that but I didn’t notice until now that it had transparent
evaluation of the promised block. I’ll have to look at this closer as
it seems to have what I need and is probably much better tested. Plus
I like it’s idea of the futures it has.

Eric