From: Eric Mahurin Date: 2005-10-10T12:16:14+09:00 Subject: Re: using lambda/Proc can prevent a lot of garbage collection --- Logan Capaldo wrote: > > On Oct 9, 2005, at 5:31 PM, Joel VanderWerf wrote: > > > Eric Hodel wrote: > > > > > >> A closure should only enclose the variables needed for its > execution. > >> This is actually not very difficult but unfortunately > eval('a') > >> prevents > >> Ruby from excluding unbound variables in closures. > >> > >> This is a (unfortunate IMO) feature of Ruby. > >> > >> > > > > Aren't there some useful hacks that depend on being able to > get at > > vars > > in the caller's scope (which need not be referenced in the > block), > > using > > the > > > > eval str, some_proc > > > > construct? > > > > I use it in my observable lib to get the self of the > block's context, > > using something like this: > > > > def when_#{var} pattern=Object, &block > > observer_map = @#{var}__observer_map ||= > ObserverMap.new > > if block > > observer = eval "self", block > > > > to find out what object is observing a variable. But that's > not as > > objectionable as getting access to arbitrary local vars in > that > > context. > > > > Does anyone remember--is there is anything that uses the > latter > > kind of > > access (arb. local vars) that is more than just a cute > hack? Is there > > anything really useful we would lose without that behavior? > > > > -- > > vjoel : Joel VanderWerf : path berkeley edu : 510 665 > 3407 > > > > > > Speaking of eval, I've always wondered why ruby of all > languages > needed a string based eval. What can you do with a string > eval that > you can't do with something like: > > eval(some_binding) { code } I can't think immediately how giving a binding to this would be useful, but I would like to see the block verision of eval: class Kernel def eval(*args) if block_given? yield else super end end end Right now, blocks can be used to create local variables (as long as they don't have the same name as an existing variable). You could use this eval to do this easily. This could change with Ruby 2 though. Maybe there are other uses. > some_binding of course would be optional just like currently. > > with instance_variable_get() and instance_variable_get you > dynamically get at ivars. with send and/or instance eval you > can > dynamically send messages. define_method blah blah... works > just as > well as eval "def blah blah". This is something thats always > kind of > irked me. And in my brave new world of evalless ruby, worse > case > scenario you write a string to a temporary file and load it. > But I > really don't believe thats necessary. Can anyone come up with > a use > for an eval taking a string that CAN'T be acheieved by an > eval that > takes a block? (well, irb I suppose). If nothing else I would > > appreciate it greatly if eval could take a block in addition > to a > string. I think this may have come off kind of like, so if I > did I > apologize in advance ;-) I looked at this a while back and found that most cases eval is used, it is used to create a method on the fly. You could probably find a way to use define_method instead of eval("def ...") for most of those cases. But, you'd still have the problem of this thread - a Proc can prevent garbage collection. Using define_method with a block will give that block access to all of the variable in the defining context. And that block/Proc will stick around indefinitely in the method that you are defining. Assuming the issue of this thread is solved, you still have another reason why eval("def ...") may be used over define_method. def creates a completely local variable context. You don't have that with define_method. You still have to worry about the variables in the block not interacting with variables in its context. This brings us back to another thread where I was talking about adding some local variable facilities. Currently, I'm using eval("def ...") in a way that define_method can't compete. I'm using it to make macro-like methods - flattening many levels of method calls into one method. Granted this is a performance reason, but define_method can't do it. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com