On Sat, Oct 2, 2010 at 6:41 PM, Ralph Shnelvar <ralphs / dos32.com> wrote:

> I see
>  http://www.ruby-forum.com/topic/41160
>
> which has a fairly long explanation of passing stuff by reference and copy
> on write(cow).
>
>
> Let's say I have
>  def som_func(x,y)
>   x = 24
>   y = 42
>  end
>  .
>  .
>
>  a=1
>  b=2
>  .
>  .
>  .
>  some_func(a,b)
>
>
> and I want to have some_func change a to 24 and b to 42 ...
>
> How do I do it?
>
>
> Is there a good write-up on copy on write and how to change the values of
> parameters?



It kind of depends what you're looking for here. As you've shown it, what
you want is not possible, but its not exactly clear what you want, so there
might be different reasons for this.


First, in languages like C and C++, where a local variable is a memory
location on the stack, that you know and can manipulate, this is possible to
do. You can go to that location in memory, and change that value.

#include <iostream>
using namespace std;

void printab(string preface , int a , int b) {
  cout << preface << ", a=" << a << ", " << "b=" << b << endl;
  return;
}

void cpp_style( int &a , int &b ) {
  a = 24;
  b = 42;
}

void c_style_pointers( int *a , int *b ) {
  *a = 36;
  *b = 63;
}

int main (int argc, char const *argv[]) {
  int a=1 , b=2;
  printab( "initially" , a , b );

  cpp_style( a , b );
  printab( "c++ style ref" , a , b );

  c_style_pointers( &a , &b );
  printab( "c style macro" , a , b );
  return 0;
}

In both cases, the actual memory address of main's a and b are passed to the
function, which dereferences them every time it wants to do anything with a
and b. In fact, these two examples are identical under the covers, the
reference style just hides away some syntax and some of the capability.

In Ruby, you cannot do this, because you do not have access to variables,
only the objects they are referencing (though there are some ways you can
kind of get around this with metaprogramming, I don't think any of them will
be useful here, and they are probably generally frowned upon).



Alternatively, if you are not wanting to change which object a and b point
to, but rather the internals of that object, then you can do this generally.
Meaning that you can mutate the object that a and b are pointing to:

def change_value(a,b)
  a.replace "replaced a"
  b.replace "replaced b"
end

a = "initial a"
b = "initial b"
puts "initially: a=#{a.inspect}, b=#{b.inspect}"
puts "initial object ids: a=#{a.object_id}, b=#{b.object_id}"

change_value a , b

puts
puts "after: a=#{a.inspect}, b=#{b.inspect}"
puts "afterw object ids: a=#{a.object_id}, b=#{b.object_id}"


However, you can't do this in your example, because a and b are integers,
and integers are immutable. They have no mutating methods, anything that
might have mutated them will instead return a new integer. That is hwy I had
to use String to show you.

You could get around this by writing a wrapper class to allow them to be
mutable.

class MutableValue
  def initialize(initial_value)
    @value = initial_value
  end
  def to_s
    @value.to_s
  end
  def replace(new_value)
    @value = new_value
  end
  def inspect
    "#<Mutable #{to_s}>"
  end
end

def change_value(a,b)
  a.replace 24
  b.replace 42
end

a = MutableValue.new 1
b = MutableValue.new 2
puts "initially: a=#{a.inspect}, b=#{b.inspect}"
puts "initial object ids: a=#{a.object_id}, b=#{b.object_id}"

change_value a , b

puts
puts "after: a=#{a.inspect}, b=#{b.inspect}"
puts "afterw object ids: a=#{a.object_id}, b=#{b.object_id}"



Of course, you need to be careful with this, because it could behave in ways
that you are not anticipating.

-----

If you have a specific use case in mind, it might be best to show what you
are trying to do so that people can suggest an alternative approach.