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:

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

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