class Tes
  attr_reader :allSkills
  def initialize
    @allSkills = {«var» => «p_dodge»}
  end
  def addBuff(buff)
    if buff[«var»][0,2] == «p_» then
      buff[«var»].delete! «p_»
    end
  end
  def prefire
    c = @allSkills.clone
    addBuff(c)
  end
end
f = Tes.new
f.prefire
puts f.allSkills.inspect

выводит {«var»=>»dodge»}. как такое может быть?

если строку
buff[«var»].delete! «p_»
заменить на
buff[«var»] = buff[«var»].delete «p_»
то всё ок.
ruby 1.8.7

Tagged with →  

7 Responses to как такое может быть?

  1. Zwrruby:

    Суть в том, что Hash#clone тебе склонировал хеш, но ключи-значения ведут на старые объекты. Кроме того, String#delete! работает непосредственно с объектом, а не с его клоном. Так как в обоих хешах значение ссылается на один и тот же объект строки, модификация этого объекта отражается на обоих хешах.

    Кстати, код настолько ебанически-хуёвый и загадочный, что я даже не осмелюсь предложить правильный вариант, поскольку не понимаю, что ты вообще пытался сделать.

  2. HardAdmin:

    считал что buff[«var»].delete! «p_» — синоним buff[«var»] = buff[«var»].delete «p_»
    это кусок кода передел чтобы понять что происходит, предложи свой вариант, охотно посмотрю.

  3. Zwrruby:

    Не синоним.

    Для иллюстрации момента вот тебе простой код.

    а)

    a = b =’hello, ‘

    a << ‘ world!’

    a # ‘hello, world’
    b # ‘hello, world’

    б)

    a = b = ‘hello, ‘

    a = «#{a} world» # ну или a = a + ‘ world’ или a += ‘ world’

    a # ‘hello, world’
    b # ‘hello,’

  4. HardAdmin:

    можно без класса сделать — разумеется, но он там был изначально и я не стал его трогать, вроде и так понятно что происходит в коде.

  5. HardAdmin:

    я так понимаю в а) у переменных a и b адрес не меняется.
    в б) переменной «а» присваивается новый адрес.

  6. Zwrruby:

    В первом случае обе переменные указывают на один и тот же объект. String#<< модифицирует объект, в итоге обе переменные содержат все еще одну и ту же модифицированную строку.

    Во втором случае a = a + ‘ world’ создает новый объект строки. А старый как был, так и остается. Таким образом в переменной b — старая строка, в переменной a — новая.

    String#delete! работает как String#<< в первом случае.

  7. HardAdmin:

    да я понял уже, спасибо)

Добавить комментарий