Use of dup to remove references

Hello

I am new to ruby and looking for a brief explanation on why a code sample
works in an unexpected way.

# Beginning of code

def wipe_from( sentence )
  sentence_new = sentence
  while sentence_new.include? '('
    open = sentence_new.index( '(' )
    close = sentence_new.index( ')', open )
    sentence_new[open..close] = '' if close
  end
sentence_new
end

spoken = "I'm not happy with (nonsense) this moon."
test = wipe_from( spoken )

puts spoken
puts test

# End of code

I'd expect that the variable spoken would be unchanged because it's
sentence_new that's being modified. It works as expected if I use dup or
clone, but why is spoken being modified at all? Shouldn't it just be
returning the value of sentence_new?

Brian

Ruby treats all variables as references to an object.
ie. if i say:
sentence = "my string"

you can think of it like this:
"my string" is stored as data somewhere in memory( let's say memory slot
13)
then <sentence> will hold the value 13. (the memory location that
contains it's data)

so if you say:
sentence_new = sentence

then it will assign the value 13 to <sentence_new>

so now both <sentence_new> and <sentence> refers to whatever is at
memory slot 13.

so now it doesn't matter if you say:
sentence_new[open..close] = '' OR
sentence[open..close] = ''

they're both modifying the data at memory slot 13.

Hope that helps clear things up.
  -Patrick

···

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

# def wipe_from( sentence )
# sentence_new = sentence

if in doubt, insert

    p sentence.object_id
    p sentence_new.object_id

# while sentence_new.include? '('
# open = sentence_new.index( '(' )
# close = sentence_new.index( ')', open )
# sentence_new[open..close] = '' if close
# end
# sentence_new
# end
# spoken = "I'm not happy with (nonsense) this moon."
# test = wipe_from( spoken )
# puts spoken
# puts test

if in doubt, insert

    p spoken.object_id
    p test.object_id

# # End of code

···

From: Brian Ross [mailto:p.brian.ross@gmail.com]
#
# I'd expect that the variable spoken would be unchanged because it's
# sentence_new that's being modified. It works as expected if I

variables are just references to objects. when you do

   y = "test"
   x = y

x and y now references to the original string object "test"

# use dup or clone, but why is spoken being modified at all?
# Shouldn't it just be returning the value of sentence_new?

not ruby. use dup or clone to taste :slight_smile:

anyway, in ruby nothing is impossible. In fact, there are many better ways :wink:

in your case eg, you can use string#gsub

sample,

irb(main):001:0> spoken = "I'm not happy with (nonsense) this moon."
=> "I'm not happy with (nonsense) this moon."

irb(main):002:0> spoken_new = spoken.gsub(/\(.*\)/,"")
=> "I'm not happy with this moon."

irb(main):003:0> spoken_new
=> "I'm not happy with this moon."

irb(main):004:0> spoken
=> "I'm not happy with (nonsense) this moon."

hth.
kind regards -botp

# def wipe_from( sentence )
# sentence_new = sentence

if in doubt, insert

    p sentence.object_id
    p sentence_new.object_id

# while sentence_new.include? '('
# open = sentence_new.index( '(' )
# close = sentence_new.index( ')', open )
# sentence_new[open..close] = '' if close
# end
# sentence_new
# end
# spoken = "I'm not happy with (nonsense) this moon."
# test = wipe_from( spoken )
# puts spoken
# puts test

if in doubt, insert

    p spoken.object_id
    p test.object_id

# # End of code

···

From: Brian Ross [mailto:p.brian.ross@gmail.com]
#
# I'd expect that the variable spoken would be unchanged because it's
# sentence_new that's being modified. It works as expected if I

variables are just references to objects. when you do

   y = "test"
   x = y

x and y now references to the original string object "test"

# use dup or clone, but why is spoken being modified at all?
# Shouldn't it just be returning the value of sentence_new?

not ruby. use dup or clone to taste :slight_smile:

anyway, in ruby nothing is impossible. In fact, there are many better ways :wink:

in your case eg, you can use string#gsub

sample,

irb(main):001:0> spoken = "I'm not happy with (nonsense) this moon."
=> "I'm not happy with (nonsense) this moon."

irb(main):002:0> spoken_new = spoken.gsub(/\(.*\)/,"")
=> "I'm not happy with this moon."

irb(main):003:0> spoken_new
=> "I'm not happy with this moon."

irb(main):004:0> spoken
=> "I'm not happy with (nonsense) this moon."

hth.
kind regards -botp

Thanks so much for the help. What has been confusing is that the object
changes in this next bit of test code so that both variables reference
different objects:

# Start of code that changes object

sentence = "first"
p sentence.object_id
sentence_new = sentence
p sentence_new.object_id
sentence = "second"
p sentence.object_id
p sentence_new.object_id

# End of code

and I think that I figured out that the method doesn't change the object
referenced, but just the value of the object, while using = to assign a new
value assigns a new object as well. Is that correct? Is there a way to use =
without changing the object in the example above?

# Start of code that preserves object

sentence = "test"
p sentence.object_id
sentence_new = sentence
p sentence_new.object_id
sentence['t'] = 'p'
p sentence.object_id
puts sentence_new
puts sentence

# End of code

Thanks again
Brian

···

On Thu, Aug 14, 2008 at 10:20 PM, botp <botpena@gmail.com> wrote:

variables are just references to objects. when you do

  y = "test"
  x = y

x and y now references to the original string object "test"

Mmm, there's only two types of operations in Ruby. Assignment, and
method calls.

sentence = "variable" is an assignment. The object_id of "variable" is
put inside a variable named <sentence>

sentence[3] = 't' is a method call. The method's name is "[]=", so
sentence does whatever the method is defined as:

sentence[3] = 't' does the same thing as:
sentence.[]=('t')

Assignment ALWAYS assigns a new object.
Method calls ALWAYS operates directly on the receiving object.

···

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