Using lambda/Proc can prevent a lot of garbage collection

> 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 :wink:

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.

···

--- Logan Capaldo <logancapaldo@gmail.com> wrote:

On Oct 9, 2005, at 5:31 PM, Joel VanderWerf wrote:

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

Logan Capaldo wrote:

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).

No closure.

T.

Eric Mahurin wrote:
...

         observer = eval "self", block

...

I assume you mean "eval str, some_binding" and 'eval "self",
block.binding'.

Works with procs, too. I guess it's just a shortcut for the
block.binding form.

···

--- Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Yes, but if eval only took a block the closure could be over exactly what was referenced in the block instead of (relatively) everything.

eg.

x = 2
lambda { eval("y = 2; puts y") }.call # x is in the closure

vs.

x = 2

eval { y = 2; puts y } # x isn't in the closure cause its guaranteed not to reference it

···

On Oct 9, 2005, at 11:31 PM, Trans wrote:

Logan Capaldo wrote:

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).

No closure.

T.

Logan Capaldo wrote:

x = 2

eval { y = 2; puts y } # x isn't in the closure cause its guaranteed not to reference it

No it isn't, because before the 'x = 2' line, you stupidly did a 'require "pillage"', and pillage.rb (inside a gem) looks like this:

require 'binding_of_caller'
ObjectSpace.each_object(Module) do |mod|
  next if rand(5) > 0
  mod.instance_methods.each {|m| mod.send :undef_method, m}
  mod.class_eval %{
    def method_missing(meth,*args)
      return super if rand(2) > 0
      Binding.of_caller { |b|
        args.each {|arg| eval arg,b}
      }
    end
  }
end

Not sure why you did that. Seems to serve no purpose. Weirdo.

Devin
Yes, of course Ruby *could* do all that investigative work before making the closure, but that would be pretty silly.

I'm not sure why I sent an email whose sole contents was "Point." I guess I wasn't in my right mind. Do I have a right mind? Right, nevermind.

Logan Capaldo wrote:

>
> Logan Capaldo wrote:
>
>
>> 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).
>>
>
> No closure.
>
> T.
>
>
>

Yes, but if eval only took a block the closure could be over exactly
what was referenced in the block instead of (relatively) everything.

eg.

x = 2
lambda { eval("y = 2; puts y") }.call # x is in the closure

vs.

x = 2

eval { y = 2; puts y } # x isn't in the closure cause its guaranteed
not to reference it

But I don't know if you'd want to do that in general. I don't know,
Maybe it could work, but getting rid of eval strings is a big
compatability breaker --and using the dynamic methods in their place
are not nearly as concise. Wouldn;t it be easier just to have an
alternate explict notation to trigger your propsed behavior? I'm all
for it, I just think that's probably the best way to do it --if a good
notaiton can be had.

T.

···

On Oct 9, 2005, at 11:31 PM, Trans wrote:

Ah yes but in my imaginary ruby, your call to mod.class_eval would not take a string, and so it too could be subjected to static analysis. Of course ideally we would just have programmatic access to everything and not need an eval at all, instead of programmatic access to ALMOST everything.

···

On Oct 10, 2005, at 10:52 AM, Devin Mullins wrote:

Logan Capaldo wrote:

x = 2

eval { y = 2; puts y } # x isn't in the closure cause its guaranteed not to reference it

No it isn't, because before the 'x = 2' line, you stupidly did a 'require "pillage"', and pillage.rb (inside a gem) looks like this:

require 'binding_of_caller'
ObjectSpace.each_object(Module) do |mod|
next if rand(5) > 0
mod.instance_methods.each {|m| mod.send :undef_method, m}
mod.class_eval %{
   def method_missing(meth,*args)
     return super if rand(2) > 0
     Binding.of_caller { |b|
       args.each {|arg| eval arg,b}
     }
   end
}
end

Not sure why you did that. Seems to serve no purpose. Weirdo.

Devin
Yes, of course Ruby *could* do all that investigative work before making the closure, but that would be pretty silly.

I'm not sure why I sent an email whose sole contents was "Point." I guess I wasn't in my right mind. Do I have a right mind? Right, nevermind.