2015-10-28 3 views
0

Я написал следующий код:Рубин взрыва странное поведение

print "Please enter a string" 
user_input = gets.chomp 
user_input.downcase! 
if user_input.include? "s" 
    print "Changing #{user_input} to #{user_input.gsub!(/s/,'th')}" 
else 
    print "No s in the string" 
end 

и я обнаружил, что user_input и user_input.gsub!(/s/,'th') содержат одинаковое значение. Это происходит из-за операции взрыва на gsub и потому, что они являются частью одной и той же строки.

Расщепление печать в две строки изменяет поведение:

print "Changing #{user_input} to " 
print "#{user_input.gsub!(/s/,'th')}" 

Интересно, если это ошибка.

+0

Pro Совет: если вы думаете, что вы нашли ошибку в компилятор/интерпретатор/любой другой, вы не делали. Ошибка в вашем коде. :) –

+0

Я действительно знаю, что я поставил вопрос «базовый», потому что я только начал изучать рубин, поскольку мой оригинальный вопрос был указан – Antonio

+0

Это была шутка, кстати. Не оскорбление или что-то в этом роде. –

ответ

3

Это особенность, а не ошибка.

Строчная интерполяция (оператор "#{}") работает, находя все динамические части, оценивая их, а затем склеивая статические и динамические части вместе в одну строку. Поскольку все динамические части оцениваются до конкатенации, gsub! мутирует объект, на который указывает user_input. Итак, первое появление inner_page в этой строке увидит обновленное значение.

Решение: не используйте опасные gsub!, используйте сейф gsub.

Здесь вы можете увидеть, как это действительно бывает (инструкции VM). На данный момент это будет китайский для вас, но через несколько лет вы поймете. :)

code = <<-RUBY 
    user_input = 'blah' 
    print "Changing \#{user_input} to \#{user_input.gsub!(/s/,'th')}" 
RUBY 

puts RubyVM::InstructionSequence.new(code).disasm 

disasm

+0

В любом случае отличается от кода Java int i = 0; System.out.print (String.format («тестирование% d% d», i, ++ i)); и имеет противоположное поведение System.out.print (String.format («тестирование% d% d», i, i ++)); – Antonio

+0

@ Антонио: эти примеры Java неактуальны. Попробуйте те, где вы мутируете строку на месте, вы увидите то же самое. (подсказка: примитивное значение и ссылка на объект) –

+0

String test = «вы уверены?»; System.out.println (String.format ("% s% s", test, test.substring (0,7))); Но не работает :( – Antonio

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