By reference or by value? Or Fixnum assignment is different?

Hi,

I am new to Ruby, just start reading the pickaxe.

Here I have a question regarding passing parameters by value or
reference. Hence everything is an object and the book mentioned for
a="abc"; b=a just created a new reference to "abc", I guess it applies
to everything is an object (could I be wrong here?).

Seems it is not the case for Fixnum.

#sample code from pickaxe

def n_times(thing)

   lambda {|n| thing * n}

end

=> nil

#Fixnum and String

a=b=23

=> 23

c=d="abc"

=> "abc"

#c, d and 'thing' are reference to same thing, just as the book said

p2=n_times(c)

=> #<Proc:0x802b7980@(irb):18 (lambda)>

p2.call(3)

=> "abcabcabc"

c.insert(-1,'d'); d.insert(-1, 'e')

=> "abcde"

p2.call(3)

=> "abcdeabcdeabcde"

#not apply to Fixnum???

p1=n_times(a)

=> #<Proc:0x802c0bc0@(irb):18 (lambda)>

p1.call(3)

=> 69

a=a+1; b=b+1

=> 24

p1.call(3)

=> 69

At first, seems to me when pass Fixnum, Ruby makes a copy. But further
dig seems it was the assignment:

a=b=10

=> 10

p a.object_id; p b.object_id

21

21

=> 21

a+=1

=> 11

p a; p b

11

10

=> 10

# object_id changed after assignment!

p a.object_id; p b.object_id

23

21

=> 21

Why Fixnum behaves different from String? Is the number class (e.g.
Fixnum, Float) the only one in Ruby core that behave like this? A little
bit confusing here

a=b=10

=> 10

p a.object_id; p b.object_id

21

21

=> 21

a=a<<1

=> 20

# a was changed!

p a.object_id; p b.object_id

41

21

=> 21

c=d="abc"

=> "abc"

p c.object_id; p d.object_id

-1072646678

-1072646678

=> -1072646678

c=c << "d"

=> "abcd"

# same operator << (ok, different operation for Fixnum)

# didn't change the obj id for String

p c.object_id; p d.object_id

-1072646678

-1072646678

=> -1072646678

p d

"abcd"

Thanks for reading. I appreciate any help/comment.

J.T

Thanks Joel, Florian for the explaination.

Now I am clear for Fixnum, operators create new object instead of
operate on the current one (immutable J), and assignment changed the
reference. At least as of now I haven't found a method to change the
Fixnum object directly. For String, there are methods/operators operate
on the current object (mutable).

Thanks again.

J.T

···

From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of
Jason Tao
Sent: Thursday, December 19, 2013 11:42 AM
To: ruby-talk@ruby-lang.org
Subject: by reference or by value? Or Fixnum assignment is different?

Hi,

I am new to Ruby, just start reading the pickaxe.

Here I have a question regarding passing parameters by value or
reference. Hence everything is an object and the book mentioned for
a="abc"; b=a just created a new reference to "abc", I guess it applies
to everything is an object (could I be wrong here?).

Seems it is not the case for Fixnum.

#sample code from pickaxe

def n_times(thing)

   lambda {|n| thing * n}

end

=> nil

#Fixnum and String

a=b=23

=> 23

c=d="abc"

=> "abc"

#c, d and 'thing' are reference to same thing, just as the book said

p2=n_times(c)

=> #<Proc:0x802b7980@(irb):18 (lambda)>

p2.call(3)

=> "abcabcabc"

c.insert(-1,'d'); d.insert(-1, 'e')

=> "abcde"

p2.call(3)

=> "abcdeabcdeabcde"

#not apply to Fixnum???

p1=n_times(a)

=> #<Proc:0x802c0bc0@(irb):18 (lambda)>

p1.call(3)

=> 69

a=a+1; b=b+1

=> 24

p1.call(3)

=> 69

At first, seems to me when pass Fixnum, Ruby makes a copy. But further
dig seems it was the assignment:

a=b=10

=> 10

p a.object_id; p b.object_id

21

21

=> 21

a+=1

=> 11

p a; p b

11

10

=> 10

# object_id changed after assignment!

p a.object_id; p b.object_id

23

21

=> 21

Why Fixnum behaves different from String? Is the number class (e.g.
Fixnum, Float) the only one in Ruby core that behave like this? A little
bit confusing here

a=b=10

=> 10

p a.object_id; p b.object_id

21

21

=> 21

a=a<<1

=> 20

# a was changed!

p a.object_id; p b.object_id

41

21

=> 21

c=d="abc"

=> "abc"

p c.object_id; p d.object_id

-1072646678

-1072646678

=> -1072646678

c=c << "d"

=> "abcd"

# same operator << (ok, different operation for Fixnum)

# didn't change the obj id for String

p c.object_id; p d.object_id

-1072646678

-1072646678

=> -1072646678

p d

"abcd"

Thanks for reading. I appreciate any help/comment.

J.T

Fixnum is immutable. What happens when you add 1 to your Fixnum is that
it becomes a different Fixnum with a different object id.

String is mutable. When you modify a String, it retains its object id,
but each instance of a String has a different object id.

irb(main):006:0> a.object_id
=> 3
irb(main):007:0> b.object_id
=> 3
irb(main):008:0> a = "a"
=> "a"
irb(main):009:0> b = "a"
=> "a"
irb(main):010:0> a.object_id
=> 24142944
irb(main):011:0> b.object_id
=> 23626116

···

--
Posted via http://www.ruby-forum.com/.

If it helps: a += 1 is not rubys increment, it is shorthand for a = a + 1. So you are reassigning a.

···

Am 19.12.2013 um 20:41 schrieb "Jason Tao" <jtao@digital-dispatch.com>:

Hi,

I am new to Ruby, just start reading the pickaxe.

Here I have a question regarding passing parameters by value or reference. Hence everything is an object and the book mentioned for a=”abc”; b=a just created a new reference to “abc”, I guess it applies to everything is an object (could I be wrong here?).

Seems it is not the case for Fixnum.

#sample code from pickaxe
def n_times(thing)
   lambda {|n| thing * n}
end
=> nil

#Fixnum and String
a=b=23
=> 23
c=d="abc"
=> "abc"

#c, d and ‘thing’ are reference to same thing, just as the book said
p2=n_times(c)
=> #<Proc:0x802b7980@(irb):18 (lambda)>
p2.call(3)
=> "abcabcabc"
c.insert(-1,'d'); d.insert(-1, 'e')
=> "abcde"
p2.call(3)
=> "abcdeabcdeabcde"

#not apply to Fixnum???
p1=n_times(a)
=> #<Proc:0x802c0bc0@(irb):18 (lambda)>
p1.call(3)
=> 69
a=a+1; b=b+1
=> 24
p1.call(3)
=> 69

At first, seems to me when pass Fixnum, Ruby makes a copy. But further dig seems it was the assignment:

a=b=10
=> 10
p a.object_id; p b.object_id
21
21
=> 21
a+=1
=> 11
p a; p b
11
10
=> 10
# object_id changed after assignment!
p a.object_id; p b.object_id
23
21
=> 21

Why Fixnum behaves different from String? Is the number class (e.g. Fixnum, Float) the only one in Ruby core that behave like this? A little bit confusing here

a=b=10
=> 10
p a.object_id; p b.object_id
21
21
=> 21
a=a<<1
=> 20
# a was changed!
p a.object_id; p b.object_id
41
21
=> 21
c=d="abc"
=> "abc"
p c.object_id; p d.object_id
-1072646678
-1072646678
=> -1072646678
c=c << "d"
=> "abcd"
# same operator << (ok, different operation for Fixnum)
# didn’t change the obj id for String
p c.object_id; p d.object_id
-1072646678
-1072646678
=> -1072646678
p d
"abcd"

Thanks for reading. I appreciate any help/comment.

J.T

From a language user's point of view _all_ variables are references.
Technically (i.e. under the hood) there are some optimizations done -
but they do not affect usage. I'd say it's best to ignore the under
the hood part for now while you are learning the language. It may
cause unnecessary confusion. You can still look at this later.

To add a fun fact: you can actually attach state to a Fixnum:

irb(main):017:0> x=1
=> 1
irb(main):018:0> x.instance_variable_set '@foo', "bar"
=> "bar"
irb(main):019:0> x.instance_variable_get '@foo'
=> "bar"
irb(main):020:0> 1.instance_variable_get '@foo'
=> "bar"
irb(main):021:0> 1.freeze
=> 1
irb(main):022:0> x.instance_variable_set '@foo', "buz"
RuntimeError: can't modify frozen object
from (irb):22:in `instance_variable_set'
from (irb):22
from /usr/bin/irb:12:in `<main>'

That does not mean that you should do it or that it's a good idea. For
all practical purposes you should view all numeric types as immutable.
A bit more on numbers and operators in Ruby:

http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html

Kind regards

robert

···

On Thu, Dec 19, 2013 at 11:29 PM, Jason Tao <jtao@digital-dispatch.com> wrote:

Now I am clear for Fixnum, operators create new object instead of operate on
the current one (immutable J), and assignment changed the reference. At
least as of now I haven’t found a method to change the Fixnum object
directly. For String, there are methods/operators operate on the current
object (mutable).

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/