2015-07-22 2 views
0

Я не понимаю, что происходит в строке
print buggy_logger << "\n" # <- This insertion is the bug. Почему переменная статус изменяется при выводе указанной выше строки? Я выполняю этот веб-сайт http://www.reactive.io/tips/2009/01/11/the-difference-between-ruby-symbols-and-strings/Неизменяемый vs mutable

status = "peace" 

buggy_logger = status 

print "Status: " 
print buggy_logger << "\n" # <- This insertion is the bug. 

def launch_nukes?(status) 
    unless status == 'peace' 
    return true 
    else 
return false 
end 
end 

print "Nukes Launched: #{launch_nukes?(status)}\n" 

ВЫХОД ЕСТЬ:

=> Статус: мир

=> Nukes Запущенный: истинный

+0

Потому что вы добавляете строку строки в строку? –

+0

['String # <<'] (http://ruby-doc.org/core-2.2.0/String.html#method-i-3C-3C) (aka concat) * мутирует * исходный объект строки (который был создан «миром»). Я рекомендую * not * использовать мутации для строк, но вместо этого используйте '+' вместо '<<' здесь. – user2864740

+0

Thanks user2864740. Я понял. – user3040171

ответ

2

Ваш вопрос «? Почему переменные изменения»

Ответ за то, что buggy_logger имеет ссылку на status. Легко проверяется путем проверки object_id.

irb(main):001:0> a = "hi" 
=> "hi" 
irb(main):002:0> a.object_id 
=> 24088560 
irb(main):003:0> b = a 
=> "hi" 
irb(main):004:0> b.object_id 
=> 24088560 
irb(main):005:0> 

Чтобы создать копию использование + или любой оператор, не мутирует. Не используйте <<.

irb(main):010:0> c = a + " guys" 
=> "hi guys" 
irb(main):011:0> c.object_id 
=> 26523040 
irb(main):012:0> 
+2

Или просто используйте правильный не мутирующий оператор (т. Е. Не '<<'). – user2864740

+0

@ user2864740 Вы можете это сделать, но опасно «угадывать», при котором операторы мутируют, а какие нет. Безопаснее просто создавать новый объект с самого начала. – Rots

+2

@Rots Что вы рекомендуете OP делать? Используйте 'String.new' и' << '? Я бы не смог это сделать в обзоре кода. –

1

Поскольку status = "peace" является строка, когда buggy_logger << "\n" побежал , он обновляет строку buggy_logger (а затем status) как «мир \ n»

Поэтому, когда метод запущен, он возвращает true, потому что status != "peace" больше.

Теперь, если в начале вы использовали символ status = :peace, он не сможет быть изменен с помощью дополнения «\ n». Таким образом, метод будет возвращать ложь, потому что status == :peace

Символа версия:

status = :peace 

buggy_logger = status 

print "Status: " 
#print buggy_logger << "\n" # This is no longer possible. It will cause an error 

def launch_nukes?(status) 
    unless status == :peace 
    return true 
    else 
return false 
end 
end 

print "Nukes Launched: #{launch_nukes?(status)}\n" # <- Returns FALSE 
+0

Нет «символьной версии», потому что символы не могут быть мутированы (и, кроме того, не имеют '# <<'). – user2864740

+0

Я думаю, что он рекомендует перечисление статусов, что является хорошей идеей. Это можно сделать как символы, перечисления ActiveRecord или пользовательский класс. –

+0

«Символьная версия» просто показывает тот же пример и как можно избежать (случайного) эффекта мутации с помощью символов. Статья, в которой используется этот пример, контрастирует с этими двумя. –

Смежные вопросы