Hi,

I think I’ve found a nice example that shows the power of Ruby

usually *not* making copies of objects. But while I was trying to

take it further, I just bumped into a limitation: as far as I know it’s

impossible to replace an object with any other and changing all

the references pointing to the new one at once. It is possible to do

it with #replace(other_obj) only if the type of the new object is still

an

Array, Hash or String. But what if I want to change the underlying

type?

Let me explain what I’m trying to do in a more details:

I’m dealing with an equation system in my Ruby code, and

references are very useful in my case. Suppose that we have an

equation system that always has a variable on the left hand side,

and an expression on the right hand side, and variables have maximum

one equations where they appear on the left hand side. So, it is

straightforward to represent this in a Hash, like this:

eq = {

“k”=>12,

“y”=>[“k”, :+, 1],

“a”=>“y”,

“x”=>[“y”, :*, [“a”, :+, “k”, :+, 1]]

}

This represents the equation system

k = 12

y = k + 1

a = y

x = y * (a + k + 1)

Variables are always Strings, operators are Symbols, and compound

statements

are represented by Arrays. Now suppose that I want to substitute values

in

one

equation from another. For instance let’s replace the variable “y” in

the

equation

x = y * (…) with k+1 from the second equation (y = k+1):

eq[‘x’][0] = eq[‘y’]

The equation system changes to this:

{

“k”=>12,

“y”=>[“k”, :+, 1],

“a”=>“y”,

“x”=>[[“k”, :+, 1], :*, [“a”, :+, “k”, :+, 1]]

}

The wonderful thing in this is that instead of having a copy of it the

expression of k+1

it’s now referenced by two equations. The befit of this is that if I do

further substitutions

on the y = k+1 equation, I’ll have the modifications in the x =…

equation

too. When we

replace “k” with it’s value from the first equation:

eq[‘y’][0] = eq[‘k’] # eq[‘k’] is 12

we’ll get this

{

“k”=>12,

“y”=>[12, :+, 1],

“a”=>“y”,

“x”=>[[12, :+, 1], :*, [“a”, :+, “k”, :+, 1]]

}

Can you see the number 12 appering in the last equation? Awesome!

It’s

exactly what I

wanted to get.

So far so good.

Now let’s do some simplifications here. Everybody knows that 12+1 is

13,

so let’s replace

eq[‘y’] with 13. Well, the problem is, that we can’t, because eq[‘y’] =

13

will break the

carefully built reference system between the equations. The new value

of

eq[‘y’] will be

13, of course, but the other references (the one from the last equation)

pointing to the

array [12, :+, 1] will still hold the old reference to the array.

There’s one ugly solution however. I can use Array#replace on eq[‘y’]

to

replace it with

another Array, for instance with the array [13]. ([13] is an array

with a

single element that is

the numbe 13) The array [13] is not exactly 13, but very similar, and I

don’t know any

better solution at the moment:

eq[‘y’].replace [13]

This will do the trick, but [13] is not very nice, it’s like the numbe

13

in totally unnecessary

brackets:

{“k”=>12, “y”=>[13], “a”=>“y”, “x”=>[[13], :*, [“a”, :+, “k”, :+, 1]]}

I don’t want to represent 13 as [13]. What I really would love to do it

to

replace an

object (in this case the array [12, :+, 1]) with any other object (in

this

case the Fixnum

13) in a way that changes all the references from the old object to the

new

one. Just

like #replace does if the new object has the same type as the old one

(String, Array or

Hash).

Array#replace does not work with non-Array arguments, but it would be

great

to force

it to work somehow. Is it somehow possible?

u.