简体   繁体   中英

Using string.next to assign hash values inside a loop. I can't explain the following output

Program:

letter = "a"
chars = Hash.new

for i in 1..5
    chars[i] = letter
    puts letter
    letter.next!
end

puts chars

=== Output:

a

b

c

d

e

{1=>"f", 2=>"f", 3=>"f", 4=>"f", 5=>"f"}

=== Question

I don't understand why I don't get {1=>"a" , 2=>"b" , 3=>"c", 4=>"d" , 5=>"e" }

I included the puts statement to check that at each stage of the iteration the letter is correct.

Thanks in advance.

chars[i] = letter doesn't assign a copy of letter to chars[i] . letter is a reference to string "a" and it assigns that reference to chars[i] . So after you assign char[1] = letter , then change letter with letter.next! , char[1] now refers to the same, new value of the string that letter does. See Ruby: how can I copy a variable without pointing to the same object? , and change your code to:

for i in 1..5
    chars[i] = letter.dup   # Assign a copy of `letter` to chars[i]
    puts letter
    letter.next!
end

The exclamation mark in letter.next! is there to indicate potential danger: next! changes the original string. All values in the hash are the same string and it changes every time.

(Almost ?) always, there is a non-exclamation mark version of the method - the "safe" version. In this case, it does not change the original string , it delivers a new string.

letter = "a"
chars = Hash.new

for i in 1..5
    chars[i] = letter
    puts letter
    letter = letter.next # new string !!
end

puts chars  # => {1=>"a", 2=>"b", 3=>"c", 4=>"d", 5=>"e"}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM