[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Everything's an object, right?

Nathan

2/24/2006 3:57:00 AM

I was talking to a coworker today about the Ruby, and we were
discussing how in Ruby everything is an object. He wondered if
everything was call-by-reference, and my knee jerk reaction was yes.

Then I ran the following irb session....

------------------- START IRB -------------------------

def foo(x)
x = 'k' + x[1..x.size]
x
end

def bar(x)
x[0] = 'k'
x
end

k = 'crazy'
=> "crazy"

foo(k)
=> "krazy"

k
=> "crazy" # !?!?!?!?!

bar(k)
=> "krazy"

k
=> "krazy" # As expected.

------------------- END IRB -------------------------

Can someone explain to me why the method foo() doesn't modify k while
bar() does? I suppose it has something to do with the fact that I'm
using an asignment statement in foo() but modifiying the parameter
"in-place" for bar(). Still, I'm a bit confused.

[author's note: Yes, I know my example isn't very "Rubyish". I just
want to get a better handle on the language.]

Thanks!

-Nathan

6 Answers

Marcel Molina Jr.

2/24/2006 4:07:00 AM

0

On Fri, Feb 24, 2006 at 12:58:38PM +0900, Nathan Morse wrote:
> def foo(x)
> x = 'k' + x[1..x.size]
> x
> end
>
> def bar(x)
> x[0] = 'k'
> x
> end

String#+ creates a new object. String#[] edits the object in place.

def foo(x)
x = 'k' + x[1..x.size]
[x, x.object_id]
end

def bar(x)
x[0] = 'k'
[x, x.object_id]
end

>> k = 'crazy'
=> "crazy"
>> k.object_id
=> 2584064
>> foo k
=> ["krazy", 2580574]
>> bar k
=> ["krazy", 2584064]
>> foo k
=> ["krazy", 2577004]
>> bar k
=> ["krazy", 2584064]

marcel
--
Marcel Molina Jr. <marcel@vernix.org>


Nathan

2/24/2006 4:36:00 AM

0

What about when I don't use String#+ ?

------------------------------------------------------------

> def foo(x)
> x = "krazy"
> x
> end
=> nil

> def bar(x)
> x[0] = 'k'
> x
> end
=> nil

> k = 'crazy'
=> "crazy"

> foo(k)
=> "krazy"

> k
=> "crazy"

> bar(k)
=> "krazy"

> k
=> "krazy"

Hal E. Fulton

2/24/2006 5:09:00 AM

0

Nathan Morse wrote:
> What about when I don't use String#+ ?

Look at it this way. You're not "passing by reference." You're
passing references by value. :)

Learn to distinguish between variables and objects. The former
are merely "labels" if you will.

a = b = c = "hello" # three variables, one object

Then remember that assignment always "wipes out" the old reference.
Assignment doesn't change the old object at all.

a = b = "hi" # a and b both refer to "hi"
a = "bye" # but now a refers to "bye"

So assigning a variable is different from changing an object.
Look at this:

a = b = "hi"
b[0] = "f"
p a # "fi"

We're changing the *object* referred to by b (which is the same
one referred to by a). We're not making b refer to a different
object.

Or check this out. Both result in the value "foobar" -- but there
is a difference.

a = "foo"
b = "foo"
p a.object_id # -542440758
p b.object_id # -542444578

a << "bar"
b += "bar"
p a.object_id # -542440758
p b.object_id # -542466128 (a new object!)

Does this help any?


Hal



Nathan

2/24/2006 6:07:00 AM

0

<< ... remember that assignment always "wipes out" the old reference.
Assignment doesn't change the old object at all. >>

Ah ha! I get it now.

Thanks!

Huw Collingbourne

2/24/2006 10:24:00 AM

0

To the best of my knowledge everything (apart from integers) is passed by
reference. However, 99% of the time this doesn't matter. In 'pure OOP'
programming, 'messages' are sent to 'methods' and they respond with new
data. If you only ever use return values you won't see inconsistent
behaviour and you won't break encapsulation (which, in effect, using ByRef
arguments to obtain new values does).

To clarify. There are a few string methods which alter the original string
object. This is also the case if you index into a string to change a char.

However, when you evaluate an expression, this yields a new object so that
in the following:

x = x + 1

The expression on the right yields a value which is assigned to a new
object, x, on the left. In other words, the x on the right is a different
object from the x on the left. Since methods which alter data usually do so
in the process of evaluation and assignment, most of the time any object
(such as x) which "goes in" is assigned to a new object (with the same name)
by the time the method ends. This explains why many people believe that
arguments are sent 'by value' - because, in most cases, the value of any
argument that goes into a method is not changed. Rather, a new object is
created during the process of evaluation and assignment.

If this is confusing, just stick to the 'pure OOP' way of doing things and
always use return values; never try to use the values of ingoing arguments
as 'ByRef' parameters. Life is much simpler that way ;-)

best wishes
Huw Collingbourne
================================
Bitwise Magazine
www.bitwisemag.com
Dark Neon Ltd.
================================


dblack

2/24/2006 1:23:00 PM

0