On Thu, 9 Mar 2006, Geert Fannes wrote:

> One thing that hinders the usability of Ruby for the things I want to
> do, is the fact that certain objects cannot be modified "in place" and
> always return NEW objects (like Fixnum, Bignum or Float), making it hard
> to do parameter passing by reference or similar things. Things get
> easily out of sync and both memory and cpu time (and programming
> overhead) has to be wasted to keep things going as should.

Fixnum involves no memory allocation whatsoever, so the concept of 
in-place couldn't even possibly apply. I see two kinds of solutions:

1. you can use delegation as in your Reference example; however, you won't
   be able to use += (and such) transparently, because those are
   completely non-overridable in Ruby. The best you'll be able to do is
   myVar[] += 1; that is, Ruby has a limited concept of lvalue which is
   limited to a few canned syntactic forms and you can't override any of
   them.

2. It's also possible to construct things that are pointers to variables
   instead of to objects, if you make them a pair of a holding object
   together with the name of the variable in it. For example, every local
   context has a Binding object that is associated to it (but is created
   only on-demand, as there is a faster internal form for it). It could
   look like:

class VarPtr
  def initialize(b,s) @b=b; @s=s.to_s end
  def []() @b.eval(@s) end
  def []=(v) @v=v; @b.eval(@s+"=@v"); @v=nil end
end

where the arguments of VarPtr.new are a Binding and a String that has to 
be a valid local variable identifier.

Here, @v is just a temporary buffer because the assignment can't run in 
two different sets of locals at once, so I put it in the object itself 
although it has the purpose of a local.

Applied to vectors, the second solution is more efficient. E.g. 
instead of having one indirector per vector cell, use ordinary 
numbers inside of the matrix, and then use a variant of VarPtr (a less 
esoteric one: no bindings, just easy stuff!) like this:

class VecElemPtr
  def initialize(vec,i) @vec=vec; @i=i end
  def []() @vec[@i] end
  def []=(v) @vec[@i]=v end
end

and this can be extended to elements in matrices, rows in matrices,
columns in matrices, etc. (makes sense?) and you can add #method_missing
and #coerce and make it subclass Numeric if you want.

The advantage of this approach is that it doesn't create VecElemPtr 
objects where you don't need them.

> This seems a bit drastic, if someone knows an easier solution to this
> problem, please let me know. If not, are there people willing to help me
> with introducing a Reference object in Ruby or have suggestions how this
> can be done? I cannot imagine no one encountered the same problems
> before.

If you were to implement references in the core of ruby, how would you 
deal with fixnums?

 _ _ __ ___ _____ ________ _____________ _____________________ ...
| Mathieu Bouchard - t˝═:+1.514.383.3801 - http://artengine.ca/matju
| Freelance Digital Arts Engineer, Montr˝┬l QC Canada