views:

153

answers:

2

Hello, as a way to spice up my C++ programming homework, I've decided to instead of typing the C++ from the book onto my computer, instead reforming it in Ruby. Yes it's a bit silly, but I'm bored.

Anyway, I'm having trouble converting this kind of function to Ruby

void swap(int &a,int &b){
  int c=b;
  b=a;
  a=c
}

What would be the equivalent ruby code inside a function ?

+1  A: 

In Ruby, arguments are passed by value. So the following method will never have any effect:

def doesnt_swap(a, b)
  c = a
  a = b
  b = c
end

On the other hand, mosts objects are references, for examples strings, so you could write

def swap_strings(a, b)
  c = a.dup
  a.replace(b)
  b.replace(c)
end

This would swap the string values of the two arguments.

Integers are immediates, so there is no equivalent to replace; you can't write swap_integers.

Anyways, in Ruby, you swap by writing a, b = b, a

Marc-André Lafortune
Is there no way of "boxing" integers or anything like that to force it to pass by reference?
Earlz
@Earlz: If the integers are members of some object, you can swap the values of the object's instance variables. You cannot access local variables in another scope.
Chuck
@Earlz: well, there is (using a SimpleDelegator), but you'll never ever see that in Ruby.
Marc-André Lafortune
I think the terminology you want to use is that strings are "mutable", hence its contents can be altered; whereas number types are "immutable"
newacct
@newacct: indeed, I rephrased my answer accordingly.
Marc-André Lafortune
Nothing stops one from passing integers in, e.g., an array; the array being mutable, the function could then replace that integer with a different value. This, however, is seldom optimal design, and it certainly isn't idiomatic Ruby. If a function needs to communicate several values to its caller, it can always return multiple values (`return [line, remaining_elements]`).
Wayne Conrad
+5  A: 

Ruby is strictly pass-by-value. Always. But sometimes those values are poointers.

Here's a couple of links:

Note that while all of these say "Java", they should really say "Smalltalk and its descendants", which includes Java, Ruby and a ton of other languages.

I think most of the confusion stems from two problems:

  1. Ruby passes references by value. But the word "reference" in that sentence is not the same as the word "reference" in "pass-by-reference". Maybe it is clearer when we disambiguate: let's replace "pass-by-reference" with "pass-by-variable" and "reference" with "pointer" (note that these are "good" well-behaved poointers, not the "bad" ones from C):
    • Fortran is pass-by-variable
    • Ruby is pass-by-value and the values it passes are mostly poointers
  2. The references (poointers) that Ruby passes point to mutable objects. Therefore, while you cannot change the reference, you can mutate the objects that the reference points to. The problem here is that Ruby (like most imperative object-oriented languages) confuses the concepts of identity, state and value. You can learn more about that problem and how to fix it here (Note that while they say "Clojure", the concepts that are presented are universal and could be applied equally well to OO):

BTW: I deliberately misspelt "poointers" with an OO for object-orientation to make it clear that I am not talking about raw memory addresses, I am talking about opaque references to objects (and for obvious reasons I do not want to use the word "reference"; if you know a better word that is neither "pointer" nor "reference", I'd love to hear it).

Jörg W Mittag
Apparently that is largely debatable http://www.ruby-forum.com/topic/41160
Earlz
It is true in, in the same way that Java and Javascript are pass by value.
Marc-André Lafortune
@Earlz: this is just a disagreement on terminology between different language communities. objects in Java behave the same way, and they call it pass-by-value
newacct
Seems to me it'd be better for everyone if we started saying "pass by sharing", or some other term of choice distinct from value and reference, since clearly it's neither. From wikipedia on "call by sharing" (http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing) "For example, in the Java community, they say that Java is pass-by-value, whereas in the Ruby community, they say that Ruby is pass-by-reference, even though the two languages exhibit the same semantics."
Jefromi