Associating data with a function

Joel VanderWerf wrote:
> Use closures and class scopes:
>
> class Foo
> tmp1 = ExpensiveObject.new
> tmp2 = ExpensiveObject.new

Assuming you want to share the tmp1 and tmp2 among all instances of the
class, which probably you don't want. Sorry.

No, I very much do - each object is only needed as a 'scratch' pad for performing calculations within the method; before and after the method I don't care about the value. Your idea has interesting merit. I hadn't thought of closing and re-opening the class to 'reset' the closure scope. Or (for that matter) of using define_method to create a method as a closure as both you and David suggested.

Thanks, interesting ideas!

···

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]

Gavin Kistner wrote:

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]

Joel VanderWerf wrote:

Use closures and class scopes:

class Foo
  tmp1 = ExpensiveObject.new
  tmp2 = ExpensiveObject.new

Assuming you want to share the tmp1 and tmp2 among all instances of the class, which probably you don't want. Sorry.

No, I very much do - each object is only needed as a 'scratch' pad for performing calculations within the method; before and after the method I don't care about the value. Your idea has interesting merit. I hadn't thought of closing and re-opening the class to 'reset' the closure scope. Or (for that matter) of using define_method to create a method as a closure as both you and David suggested.

Watch out for threads, then. If your program can have multiple threads running these calculations, a mutex will keep them from fighting over the expensive objects.

···

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

This got me thinking about the idea of thread local instance variables.

Thread# and Thread#= give you 'global' thread locals, here's an
UNTESTED 'SKETCH' of a class which would let you do something like:

class Foo

   def meth1
        @tliv1 = ThreadLocalInstanceVariable.new {ExpensiveVariable1.new}
        @tiiv2 = ThreadLocalInstanceVariable.new {ExpensiveVariable2.new}
        .. do something with those expensive variables
   end
...
end

rick@frodo:/public/rubyscripts$ cat thread_local.rb
require 'delegator'
class ThreadLocalInstanceVariable < Delegator

  def initialize(&init_block)
    super
    @init_block = init_block
  end

  def __get_obj__
    # thread local instance variable proxies are kept in a hash
    # which is itself a thread local variable
    iv_hash = Thread.current[:tl_iv_hash] || = Hash.new
    local_iv = iv_hash[self.object_id]
    unless local_iv
      # store using object_id to avoid direct reference
      my_id = self.object_id
      # clean out when local iv gets GC'd, e.g. when the instance holding
      # it dies
     ObjectSpace.define_finalizer(self, lambda {iv_hash.delete(my_id)})
      local_iv = iv_hash[self.object_id] = init_block.call
    end
    local_iv
  end

end

···

On 10/5/06, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Watch out for threads, then. If your program can have multiple threads
running these calculations, a mutex will keep them from fighting over
the expensive objects.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/