0

Context: i argue that saying pass_by_reference when it's really pass_by_sharing is misleading
Here is the excerpt from the book "Effective Ruby" I'm arguing against

"Most objects are passed around as references and not as actual values. When these types of objects are inserted into a container the collection class is actually storing a reference to the object and not the object itself. (The notable exception to the rule is the Fixnum class whose objects are always passed by value and not by reference.)

The same is true when objects are passed as method arguments. The method will receive a reference to the object and not a new copy. This is great for efficiency but has a startling implication. "

Lewix
  • 924
  • 1
  • 9
  • 11
  • Don't cite the that long chunk of text. Extract the opposing points. – sawa Oct 27 '14 at 03:10
  • @sawa not that I care but this is ridiculous to give -1 for that.I wanted to make sure that i give everybody the proper context/in case there's something I missed. I will remove it if many deemed it unnecessary. – Lewix Oct 27 '14 at 03:42

2 Answers2

3

The 'call by value' and 'call by object sharing' terminology matches Ruby's behavior, and the terminology is consistent with other object orientated languages that have the same semantics.

'Call by value' and 'call by object sharing' basically mean the same thing in object orientated languages, so which one is used doesn't really matter. Someone just thought it would clarify the confusion in the terminology to add more terminology.

If 'call by reference' was implemented in Ruby though, it would be something like:

def f(byref x)
    x = "CHANGED"
end

x = ""
f(x)

# X is "CHANGED"

Here, the value of x is changed. The value being which object x refers to.

Using terms 'call by reference' just creates confusion though because they mean different things to different people. It's unnecessary in languages like Ruby because you don't have a choice. In languages with different calling mechanisms like C++ and C# it makes more sense to teach these terms because they have a real effect on programs and we can come up with non hypothetical examples of them.

When explaining parameters in Ruby, you don't need to use any of these terms though. They're meaningless to people that don't already know the language. Just describe the behavior itself without that terminology and avoid the baggage.

I would say if you insist on using these terms, then use 'call by value' because it's usually considered more correct. The 'Programming Ruby' book calls it 'call by value', as well as plenty of Ruby programmers. Using the term with a different meaning than its technical one isn't helpful.

fgb
  • 18,439
  • 2
  • 38
  • 52
  • 2
    C# is a very nice comparison, because it has passing value types by value, passing reference types by value, passing value types by reference and passing reference types by reference. Ruby's (and Python's and ECMAScript's and Smalltalk's and Java's and …) semantics match 100% those of C# when passing reference types by value. So, it simply doesn't make sense why the exact same semantics should by called pass-by-value in C# and something else in Ruby. – Jörg W Mittag Oct 26 '14 at 21:11
  • 1
    I actually posted a snippet of C# demonstrating those four semantics in one of my answers on SO. You can dig it up if you're bored. – Jörg W Mittag Oct 26 '14 at 21:15
1

You are right. Ruby is pass-by-value only. The semantics of passing and assigning in Ruby are exactly identical to those in Java. And Java is universally described (on Stack Overflow and the rest of the Internet) as pass-by-value only. Terms about languages such as pass-by-value and pass-by-reference must be consistently used across languages to be meaningful.

The thing that is often misunderstood by people who say Java, Ruby, etc. "pass objects by reference" is that "objects" are not values in these languages, and thus cannot be "passed". The value of every variable and result of every expression is a "reference", which is a pointer to an object. The expression for creating an object returns an object pointer; when you access an attribute through the dot notation, the left side takes an object pointer; when you assign one variable to another, you copy the pointer resulting in two pointers to the same object. You always deal with pointers to objects, never objects themselves.

This is made explicit in Java as the only types in Java are primitive types and reference types -- there are no "object types". So every value in Java that is not a primitive is a reference (a pointer to an object). Ruby is dynamically-typed, so variables don't have explicit types. But you can imagine a dynamically-typed language as just a statically-typed language having exactly one type; and for languages like Python and Ruby, if this type were described, it be a pointer-to-object type.

The issue ultimately boils down to a problem of definitions. People argue over things because there is no precise definition, or they each have slightly different definitions. Rather then argue over vaguely-defined things like what is the "value" of a variable, or whether named values are "variables" or "names", etc., we need to use a definition for pass-by-value and pass-by-reference that is based purely on semantics of a language structure. @fgb's answer provides a clear semantic test for pass-by-reference. In "true pass-by-reference", e.g. with & in C++ and PHP, or with ref or out in C#, simple assignment (i.e. =) to a parameter variable has the same effect as simple assignment to the passed variable in the original scope. In pass-by-value, simple assignment (i.e. =) to a parameter variable has no effect in the original scope. This is what we see in Java, Python, Ruby, and many other languages.

I dislike people coming up with new names like "pass by object sharing", when they don't understand that the semantics are covered by an existing term, pass-by-value. Adding a new term only adds more to the confusion rather than reduce it, because it does not resolve the definitions of existing terms, only adding a new term that also needs to be defined.

newacct
  • 119,665
  • 29
  • 163
  • 224