当前位置: 动力学知识库 > 问答 > 编程问答 >

Ruby array changes by changing a 'copy' of one of its elements

问题描述:

I'm trying to confirm whether my understanding is correct of these six lines of code:

string="this is a sentence"

words=string.split

first_word=words[0]

first_word[0]=first_word[0].upcase

out=words.join(" ")

puts(out)

which prints "This is a sentence" (with the first letter capitalized).

It would appear that changing the "first_word" string, which is defined as the first element of the "words" array, also changes the original "words" array. Is this indeed Ruby's default behavior? Does it not make it more difficult to track where in the code changes to the array take place?

网友答案:

You just need need to distinguish between a variable and an object. Your string is an object. first_word is a variable.

Look for example

a = "hello"
b = a
c = b

now all variables contain the same object, a string with the value "hello". We say they reference the object. No copy is made.

a[0] = 'H'

This changes the first character of the object, a string which now has the value "Hello". Both b and c contain the same, now changed object.

a = "different"

This assigns a new object to the variable a. b and c still hold the original object.

Is this Rubys default behaviour? yes. And it also works like this in many other programming languages.

Does it make it difficult to track changes? Sometimes.

If you takes an element from an array (like your first_word), you need to know:

If you change the object itself, no matter how you access it, all variables will still hold your object, which just happened to be changed.

But if you replace the object in the array, like words[0] = "That", then all your other variables will still hold the original object.

网友答案:

This behavior is caused by how ruby does pass-by-value and pass-by-reference.

This is probably one of the more confusing parts of Ruby. It is well accepted that Ruby is a pass-by-value, high level programming language. Unfortunately, this is slightly incorrect, and you have found yourself a perfect example. Ruby does pass-by-value, however, most values in ruby are references. When Ruby does an assignment of a simple datatypes, integers, floats, strings, it will create a new object. However, when assigning objects such as arrays and hashes, you are creating references.

original_hash = {name: "schylar"}
reference_hash = original_hash
reference_hash[:name] = "!schylar"
original_hash #=> "!schylar"

original_array = [1,2]
reference_array = original_array
reference_array[0] = 3
reference_array #=> [3,2]

original_fixnum = 1
new_object_fixnum = original_fixnum
new_object_fixnum = 2
original_fixnum #=> 1

original_string = "Schylar"
new_object_string = original_string
new_object_string = "!Schylar"
original_string #=> "Schylar'

If you find yourself needing to copy by value, you may re-think the design. A common way to pass-by-value complex datatypes is using the Marshal methods.

a = {name: "Schylar"}
b = Marshal.load(Marshal.dump(a))
b[:name] = "!!!Schylar"
a #=> {:name => "Schylar"}
分享给朋友:
您可能感兴趣的文章:
随机阅读: