Как я могу изменить Символ в Ruby без RuntimeError: Не можете изменить замороженный Символ? - PullRequest
0 голосов
/ 30 сентября 2018

Я пытаюсь изменить цвет шахматной фигуры, если позиция соответствует заданным критериям, однако продолжаю получать следующее сообщение об ошибке:

Position#move_str
Failure/Error: it {expect(Position[P: [e2, e3], p:[d3, d4]].move_str(e2,d3)).to eq "ed3"}

RuntimeError:
can't modify frozen Symbol
 # ./chess.rb:24:in `color'
 # ./chess.rb:122:in `block in move_str'
 # ./chess.rb:122:in `select!'
 # ./chess.rb:122:in `move_str'
 # ./chess_spec.rb:75:in `block (3 levels) in <top (required)>'

Я вызываю код из отдельного файла (который связалправильно, так как предыдущие тесты с другими разделами работают).Он проходит через следующие фрагменты кода

chess_spec.rb Файл:

75. it {expect(Position[P: e2, p:d3].move_str(e2,d3)).to eq "ed"}
76. it {expect(Position[P: [e2, e3], p:[d3, d4]].move_str(e2,d3)).to eq "ed3"}

chess.rb Цвет файла

21. class Symbol
22. def color
23. return @color unless @color.nil?
24. @color = :a < self ? :black : :white
25.
26. end

chess.rb Файл move_str

113. def move_str(from, to)
114.   piece = board[from]
115.   piece_str = piece.pawn? ? "" : piece
116.   list = find(piece, to)
117.   is_capture = board[to] || piece.pawn? && to == ep
118.   if piece.pawn? && is_capture then
119.
120.     possible_pawn_pos = [*0..7].select{|row|board[from%10+(row+2)*10] == piece}
121.     possible_pawn_pos.select! { |row| target = board[to%10 + (row+2+white(-1, 1))*10]; target && target.color != piece.color }
122.       if possible_pawn_pos == 1 then"#{from.to_sq[0]}#{to.to_sq[0]}"
123.       else
124.       "#{from.to_sq[0]}#{to.to_sq}"
125.        end
126.        else
127.            if list.size == 1 then
128.                "#{piece_str}#{to.to_sq}"
129.                elsif list.select { |idx| idx%10 == from%10}.size == 1
130.                    "#{piece_str}#{from.to_sq[0]}#{to.to_sq}"
131.                elsif list.select { |idx| idx/10 == from/10}.size == 1
132.                    "#{piece_str}#{from.to_sq[1]}#{to.to_sq}"
133.                else
134.                    "#{piece_str}#{from.to_sq}#{to.to_sq}"
135.                end
136.    end
137. end

chess.rb Файл белый

109. def white(w,b,t=turn)
110.    t == :white ? w : b
111. end

Я знаю, что ошибка исходит из строки 122, как указано в сообщении об ошибке, и полагаю, что она исходит из раздела (row+2+white(-1, 1))*10], хотя и недействительно так уверен, как новичок в Ruby.Поскольку это Символ, я знаю, что вы не можете dup его вообще.Как тогда я смогу изменить цвет символов?

Спасибо за любую помощь заранее и извините, если я сделал какие-либо ошибки в публикации этого, поскольку я новичок в Ruby и переполнении стека.

1 Ответ

0 голосов
/ 30 сентября 2018

В Ruby экземпляры Символ предназначены для использования в качестве констант или неизменных значений.По этой причине символы всегда заморожены.

:a.frozen? #=> true

В документации Object#freeze говорится о замороженных объектах следующее:

freeze → obj

Предотвращает дальнейшие модификации obj .RuntimeError будет поднят при попытке изменения.Нет возможности разморозить замороженный объект.См. Также Object#frozen?.

Этот метод возвращает self.

a = [ "a", "b", "c" ]
a.freeze
a << "z"

производит:

prog.rb:3:in `<<': can't modify frozen Array (FrozenError)
 from prog.rb:3

Объекты следующих классов всегдазаморожено: целое число , число с плавающей запятой , символ .

Это означает, что ошибка будет возникать в следующей строке:

class Symbol
  def color
    return @color unless @color.nil?
    @color = :a < self ? :black : :white
    #      ^ Instance variable can only be read, writing to it
    #        counts as modification, thus raising an exception.
  end
end
...