Confused by scope in ruby

Hello,

I’ve been writing in ruby for a bit, but ran into something while
working on a project that struck me as weird, and could not find a ready
explanation.

Sorry if this is something super basic…

Here is a simplified example.

My question is: Why is the hash not empty at the end?

class Hmmm
def why_not_empty?
hash = {}
puts “Start: hash = #{hash.to_s}”
[1, 2, 3, 4, 5].each do |num|
put_in_hash(num, hash)
end
puts “End hash:\n#{hash.to_s}” # i would expect this to be {}
end

def put_in_hash(num, hsh)
hsh[num.to_s] = “hello from hash index #{num}.\n”
return nil
end

def number
num = 2
puts “Start number: #{num}”
change_number?(num)
puts “End number: #{num}”
end

def change_number?(num)
num = 3
end
end

@a = Hmmm.new
@a.why_not_empty?
@a.number

Output:
Start: hash =
End hash:
1hello from hash index 1.
2hello from hash index 2.
3hello from hash index 3.
4hello from hash index 4.
5hello from hash index 5.
Start number: 2
End number: 2

The number, as I would expect, stays at two, but the hash is actually
changed by the method, as if I were passing it a pointer in C or
something…

Actually, it appears that I was googling wrong:

If anyone else is curious:

http://www.ruby-forum.com/topic/163970
http://www.ruby-forum.com/topic/57549
http://www.ruby-forum.com/topic/119188
http://www.ruby-forum.com/topic/95594
http://www.ruby-forum.com/topic/139257
http://al2o3-cr.blogspot.com/2008/08/object-arr.html

Mischa F. wrote:

The number, as I would expect, stays at two, but the hash is actually
changed by the method, as if I were passing it a pointer in C or
something…

Well, that’s exactly what’s happening at C level - in both cases. The
difference is that if you do foo[bar] = baz or
foo.method_that_changes_foo!
then you change the object that foo points to (so all other variables
that
point to the same object will also reflect those changes), but if you do
foo = bar, you’re just changing the pointer, i.e. foo now points to
wherever
bar points to and the object that it previously pointed to is unchanged.

HTH,
Sebastian

Mischa F. wrote:

Hello,

I’ve been writing in ruby for a bit, but ran into something while
working on a project that struck me as weird, and could not find a ready
explanation.

Assigning a value to a parameter simply assigns a new variable to the
letter, and adding something to a hash modifies the existing object,
referenced by the variable. Similarily if you pass a string to a method
def change(s) and inside the method do:
s=“abc” # does not change the original object
s+=“abc” # does not change the original object, because it is equivalent
to s=s+“abc”
s<<“abc” # does change the outside object because it is an in-place
modification
s.upcase! # does change
s=s.upcase # does not

Have a look: http://al2o3-cr.blogspot.com/2008/08/object-arr.html

TPR.

Yes, that is helpful. Thank you both.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs