Associating data with a function

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?

The Situation/Requirements

···

--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

The Solution We'll Ignore
--------------------------
We *could* create a distinct instance variable for each needed variable.
I personally don't like the weird coupling this creates, though. So I'm
ignoring it.

class Foo
  def initialize
    @tmp1 = ExpensiveObject.new
    @tmp2 = ExpensiveObject.new
    @tmp3 = ExpensiveObject.new
    @tmp4 = ExpensiveObject.new
  end
  def c1
    tmp1, tmp2 = @tmp1, @tmp2
    #...
  end
  def c2
    tmp1, tmp2 = @tmp3, @tmp4
    #...
  end
end

The JavaScript Solution
-----------------------
The solution I used for JavaScript was that functions/methods are
first-class objects that can have arbitrary data assigned, and can get a
reference to themselves during execution. So:

Foo.prototype.c1 = function( ) {
  var tmp1 = arguments.callee.eo1;
  var tmp2 = arguments.callee.eo2;
  //...
}
Foo.prototype.c1.eo1 = new ExpensiveObject;
Foo.prototype.c1.eo2 = new ExpensiveObject;

There were a few potential solutions for Lua. I'll list the two best,
just to help give you ideas:

Lua Solution #1: Closures (would work for JS, too)
--------------------------------------------------
Foo.c1 = ( function( )
  local tmp1 = ExpensiveObject:new( )
  local tmp2 = ExpensiveObject:new( )
  return function( self )
    -- stuff using tmp1 and tmp2
  end
end)( )

Lua Solution #2: Changing the global environment for a function
---------------------------------------------------------------
function associateFunctionData( inF, inData )
  setfenv(inF, setmetatable(inData,{__index=getfenv(inF)}))
end

function Foo:c1( )
  -- stuff using tmp1 and tmp2
  -- as though they were globals
end

associateFunctionData( Foo.c1, {
  tmp1 = ExpensiveObject:new( ),
  tmp2 = ExpensiveObject:new( )
} )

Just two ideas, it's too late to actually think :wink:

you can change your 'ignored' vesion to something more acceptable:

...
def c1
  @c1_tmp1 ||= ExpensiveObject.new
  @c1_tmp2 ||= ExpensiveObject.new
  tmp1, tmp2 = @c1_tmp1, @c2.tmp2
  ...
end

I was thinking of some kind of delegation, but it got too messy so I
abandoned it.
Another possibility is to implement a pool of objects directly into
ExpensiveObject or to create a layer above it.

i.e. something like (not tested, not thread-safe, etc.):

class ExtensiveObjectPool
   class << self
     def initialize
         @idle, @busy = [], []
     end

     def with(how_many)
         objs = allocate(how_many)
         yield *objs
     ensure
         release(objs)
     end

     def allocate(num)
          ret = []
          while num > 0 and not @free.empty?
              num -= 1
              ret << @free.pop
              @busy << ret.last
          end
          while num > 0
              num -= 1
              ret << ExpensiveObject.new
              @busy << ret.last
          end
          ret
     end
     def release(objs)
         @busy.delete(*objs)
         @free += objs
     end
end

class Foo
   def c1
       ExtensiveObjectPool.with(2) do |tmp1, tmp2|
          result = tmp1 + tmp2 + c2
       end
   end

   def c2
       ExtensiveObjectPool.with(2) do |tmp1, tmp2|
          result = tmp1 + tmp2
       end
   end
end

Hi --

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?

The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
def c1
   tmp1 = ExpensiveObject.new
   tmp2 = ExpensiveObject.new
   # stuff involving tmp1/tmp2
   result = tmp1 + tmp2 + c2
end
def c2
   tmp1 = ExpensiveObject.new
   tmp2 = ExpensiveObject.new
   # stuff involving tmp1/tmp2
   result = tmp1 + tmp2
end
end

Lua Solution #1: Closures (would work for JS, too)
--------------------------------------------------
Foo.c1 = ( function( )
local tmp1 = ExpensiveObject:new( )
local tmp2 = ExpensiveObject:new( )
return function( self )
   -- stuff using tmp1 and tmp2
end
end)( )

You could do:

   class Foo
     def initialize
       tmp1, tmp2 = EO.new, EO.new
       define_method("c1") { do stuff with tmp1 etc. }
       tmp1, tmp2 = EO.new, EO.new
       define_method("c2") { do stuff with tmp1 etc. }
     end
   end

or something like that. I'd be inclined to revisit the instance
variable version, though. I'm at the bottom of the well of mental
energy right now or I'd try to come up with a twist on it that might
seem less coupled....

David

···

On Thu, 5 Oct 2006, Gavin Kistner wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?
The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

Use closures and class scopes:

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

   define_method :c1 do
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2 + c2
   end
end

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

   define_method :c2 do
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2
   end
end

···

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

Hi,
At Thu, 5 Oct 2006 08:18:24 +0900,
Gavin Kistner wrote in [ruby-talk:218056]:

The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

Like this?

$ ruby eo.rb 5
#<Foo::ExpensiveObject: 1>
#<Foo::ExpensiveObject: 2>
#<Foo::ExpensiveObject: 3>
#<Foo::ExpensiveObject: 4>
#<Foo::ExpensiveObject: 5>
[:c1,
#<Foo::ExpensiveObject: 1>,
#<Foo::ExpensiveObject: 2>,
[:c2,
  #<Foo::ExpensiveObject: 3>,
  #<Foo::ExpensiveObject: 4>,
  #<Foo::ExpensiveObject: 5>,
  [:c1,
   #<Foo::ExpensiveObject: 1>,
   #<Foo::ExpensiveObject: 2>,
   [:c2,
    #<Foo::ExpensiveObject: 3>,
    #<Foo::ExpensiveObject: 4>,
    #<Foo::ExpensiveObject: 5>,
    [:c1, #<Foo::ExpensiveObject: 1>, #<Foo::ExpensiveObject: 2>, ]]]]]

$ cat eo.rb
#!/usr/bin/ruby

module ScratchArgument
  def scratch_method(name)
    meth = instance_method(name)
    define_method(name) do |*args0|
      *eo = *yield
      imeth = meth.bind(self)
      (class << self; self; end).class_eval do
        define_method(name) do |*args|
          args.unshift(*eo)
          imeth.call(*args)
        end
      end
      args0.unshift(*eo)
      imeth.call(*args0)
    end
  end
end

class Foo
  extend ScratchArgument

  class ExpensiveObject
    @@count = 0
    def initialize
      @id = @@count += 1
      p self
    end
    def inspect
      "#<#{self.class.name}: #{@id}>"
    end
  end

  def c1(tmp1, tmp2, i)
    if i <= 0
      
    else
      [:c1, tmp1, tmp2, c2(i - 1)]
    end
  end
  scratch_method(:c1) do
    [ExpensiveObject.new, ExpensiveObject.new]
  end

  def c2(tmp1, tmp2, tmp3, i)
    if i <= 0
      
    else
      [:c2, tmp1, tmp2, tmp3, c1(i - 1)]
    end
  end
  scratch_method(:c2) do
    [ExpensiveObject.new, ExpensiveObject.new, ExpensiveObject.new]
  end
end

result = Foo.new.c1(ARGV.empty? ? 3 : ARGV.first.to_i)
require 'pp'
pp result

···

--
Nobu Nakada

what's wrong with the simple solution:

   class Foo
     METHOD_DATA = {
       'c1' => {
         'tmp1' => ExpensiveObject.new,
         'tmp2' => ExpensiveObject.new,
       },

       'c2' => {
         'tmp1' => ExpensiveObject.new,
         'tmp2' => ExpensiveObject.new,
       },
     }

    def mdata m, key
      METHOD_DATA[m.to_s][key.to_s]
    end

    def c1
      tmp1, tmp2 = mdata('c1', 'tmp1'), mdata('c1', 'tmp2')
      result = tmp1 + tmp2 + c2
    end

    def c2
      tmp1, tmp2 = mdata('c2', 'tmp1'), mdata('c2', 'tmp2')
      result = tmp1 + tmp2
    end
   end

you can make it lazy using lambda if you want...

??

cheers.

-a

···

On Thu, 5 Oct 2006, Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object instances
with methods on a per-method basis?

The Situation/Requirements
--------------------------
A class has 2 different methods. Each method needs a couple 'scratch'
objects to perform its calculations. The methods call each other; they must
not use the same scratch objects. It is expensive to instantiate a scratch
object. It's not expensive to initialize an existing scratch object with
data. We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
def c1
   tmp1 = ExpensiveObject.new
   tmp2 = ExpensiveObject.new
   # stuff involving tmp1/tmp2
   result = tmp1 + tmp2 + c2
end
def c2
   tmp1 = ExpensiveObject.new
   tmp2 = ExpensiveObject.new
   # stuff involving tmp1/tmp2
   result = tmp1 + tmp2
end
end

The Solution We'll Ignore
--------------------------
We *could* create a distinct instance variable for each needed variable.
I personally don't like the weird coupling this creates, though. So I'm
ignoring it.

class Foo
def initialize
   @tmp1 = ExpensiveObject.new
   @tmp2 = ExpensiveObject.new
   @tmp3 = ExpensiveObject.new
   @tmp4 = ExpensiveObject.new
end
def c1
   tmp1, tmp2 = @tmp1, @tmp2
   #...
end
def c2
   tmp1, tmp2 = @tmp3, @tmp4
   #...
end
end

--
in order to be effective truth must penetrate like an arrow - and that is
likely to hurt. -- wei wu wei

I can think of several solutions.

1. Use command pattern, i.e., distribute method c1 and c2 to different classes (i.e. a class per method), make your local variables instance variables and reuse instances of these command classes. If you have common behavior or state you can even use a common base class or a Module.

2. Use factory with a pool to create and release objects whose creation is expensive. The factory can reside at class level. Gotcha: if you do multithreading you have to make sure the factory deals properly with that.

Note, both approaches work with pretty much every OO language and do not need any kind of fancy environment changes or closures.

Kind regards

  robert

···

On 05.10.2006 01:18, Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?
The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?

The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

I look at this and think, "where the persistant locals?" Well, we don't
have em but they can be emulatated via instance vars.

class Foo
   def c1
     tmp1 = (@_tmp1 ||= ExpensiveObject.new)
     tmp2 = (@_tmp2 ||= ExpensiveObject.new)
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2 + c2
   end
   def c2
     tmp1 = (@_tmp1 ||= ExpensiveObject.new)
     tmp2 = (@_tmp2 ||= ExpensiveObject.new)
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2
   end
end

T.

Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?

The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Wasteful Example:
class Foo
  def c1
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2 + c2
  end
  def c2
    tmp1 = ExpensiveObject.new
    tmp2 = ExpensiveObject.new
    # stuff involving tmp1/tmp2
    result = tmp1 + tmp2
  end
end

Hmm then again....

  require 'facet/annotation'

  class Foo

    ann :c1, :tmp1 => ExpensiveObject.new,
                  :tmp2 => ExpensiveObject.new

    def c1
      result = ann.c1.tmp1 + ann.c1.tmp2 + c2
    end

    ann :c2, :tmp1 => ExpensiveObject.new,
                  :tmp2 => ExpensiveObject.new

    def c2
      result = ann.c2.tmp1 + ann.c2.tmp2
    end

  end

Works as long ExpensiveObject isn't dependent on instance context.
(Note: If anyone actually tries this it may need to use:
'self.class.ann.c1.tmp1' instead, although it ought to work as given.)

T.

Can't you do the same here?

class A
tmp1 = ExpensiveObject.new
tmp2 = ExpensiveObject.new
define_method(:c1) do # Look ma! a closure
   # stuff using tmp1 and tmp2
end
end

···

On Thu, Oct 05, 2006 at 08:18:24AM +0900, Gavin Kistner wrote:

Because I just had to solve this problem in both JavaScript and Lua, and
because I love Ruby more than either, I thought I'd ask people here how
they'd solve it in Ruby.

The general question is: how would do you associate a few object
instances with methods on a per-method basis?

The Situation/Requirements
--------------------------
A class has 2 different methods.
Each method needs a couple 'scratch' objects to perform its
calculations.
The methods call each other; they must not use the same scratch objects.
It is expensive to instantiate a scratch object.
It's not expensive to initialize an existing scratch object with data.
We like OOP coding, and want to call these as methods of a receiver.

Lua Solution #1: Closures (would work for JS, too)
--------------------------------------------------
Foo.c1 = ( function( )
  local tmp1 = ExpensiveObject:new( )
  local tmp2 = ExpensiveObject:new( )
  return function( self )
    -- stuff using tmp1 and tmp2
  end
end)( )

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.

···

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

Robert Klemme wrote:

I can think of several solutions.

1. Use command pattern, ...
...
2. Use factory with a pool ...

...

3. Flyweight design pattern

http://redcorundum.blogspot.com/2006/09/simple-flyweight-implementation_26.html

Cheers,
verno

···

On 05.10.2006 01:18, Gavin Kistner wrote:

--
Posted via http://www.ruby-forum.com/\.

Hi --

···

On Thu, 5 Oct 2006, dblack@wobblini.net wrote:

class Foo
   def initialize
     tmp1, tmp2 = EO.new, EO.new
     define_method("c1") { do stuff with tmp1 etc. }
     tmp1, tmp2 = EO.new, EO.new
     define_method("c2") { do stuff with tmp1 etc. }
   end
end

or something like that. I'd be inclined to revisit the instance
variable version, though. I'm at the bottom of the well of mental
energy right now or I'd try to come up with a twist on it that might
seem less coupled....

See Joel's response for how to do this correctly :slight_smile: (i.e., calling
define_method in top-level class definition scope, not in an instance
method where it won't have any meaning)

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

It's certainly effective, and slightly nicer than instance variables
since it clearly describes which methods the variables go with. I'm not
wild about it just because it means that when you edit the method you
need to remember to go edit a data structure somewhere else.

(This is one reason that makes a separately-managed pool much nicer
than closure or other solutions where you must instantiate the objects
outside of the method itself.)

A viable alternative nonetheless.

···

ara.t.howard@noaa.gov wrote:

what's wrong with the simple solution:

   class Foo
     METHOD_DATA = {
       'c1' => {
         'tmp1' => ExpensiveObject.new,
         'tmp2' => ExpensiveObject.new,
       },

       'c2' => {
         'tmp1' => ExpensiveObject.new,
         'tmp2' => ExpensiveObject.new,
       },
     }

Trans wrote:

I look at this and think, "where the persistant locals?" Well, we don't
have em but they can be emulatated via instance vars.

class Foo
   def c1
     tmp1 = (@_tmp1 ||= ExpensiveObject.new)
     tmp2 = (@_tmp2 ||= ExpensiveObject.new)
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2 + c2
   end
   def c2
     tmp1 = (@_tmp1 ||= ExpensiveObject.new)
     tmp2 = (@_tmp2 ||= ExpensiveObject.new)
     # stuff involving tmp1/tmp2
     result = tmp1 + tmp2
   end
end

Persistent locals is an interesting concept. Your specific example
fails, however, if I change c1's last line to:
    result = tmp1 * c2 + tmp2
because calculating c2 will change the value in @_tmp2, making the tmp2
in c1 invalid. You'd need to ensure that each instance variable had a
unique name in each function, which is just about the same as declaring
all the instance variables during initialization or class creation.

Nobuyoshi Nakada wrote:

module ScratchArgument
  def scratch_method(name)
    meth = instance_method(name)
    define_method(name) do |*args0|
      *eo = *yield
      imeth = meth.bind(self)
      (class << self; self; end).class_eval do
        define_method(name) do |*args|
          args.unshift(*eo)
          imeth.call(*args)
        end
      end
      args0.unshift(*eo)
      imeth.call(*args0)
    end
  end
end

Wow, that's pretty crazy, Nobu! Thanks for the brain bending. :slight_smile:

Logan Capaldo wrote:

···

On Thu, Oct 05, 2006 at 08:18:24AM +0900, Gavin Kistner wrote:
> Lua Solution #1: Closures (would work for JS, too)
Can't you do the same here?

[snip]

Yup - both David Black and Joel VanderWerf posted that same solution
yesterday :slight_smile:

Phrogz wrote:

Trans wrote:
> I look at this and think, "where the persistant locals?" Well, we don't
> have em but they can be emulatated via instance vars.
>
> class Foo
> def c1
> tmp1 = (@_tmp1 ||= ExpensiveObject.new)
> tmp2 = (@_tmp2 ||= ExpensiveObject.new)
> # stuff involving tmp1/tmp2
> result = tmp1 + tmp2 + c2
> end
> def c2
> tmp1 = (@_tmp1 ||= ExpensiveObject.new)
> tmp2 = (@_tmp2 ||= ExpensiveObject.new)
> # stuff involving tmp1/tmp2
> result = tmp1 + tmp2
> end
> end

Persistent locals is an interesting concept. Your specific example
fails, however, if I change c1's last line to:
    result = tmp1 * c2 + tmp2
because calculating c2 will change the value in @_tmp2, making the tmp2
in c1 invalid. You'd need to ensure that each instance variable had a
unique name in each function, which is just about the same as declaring
all the instance variables during initialization or class creation.

Right, they should have had differnt names.

T.