How can I modify a Symbol in Ruby without a RuntimeError: Can't modify frozen Symbol?

How can I modify a Symbol in Ruby without a RuntimeError: Can't modify frozen Symbol?

如果位置符合给定条件,我正在尝试更改棋子的颜色,但不断收到以下错误消息:

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 和堆栈溢出的新手。

在 Ruby 中,Symbol 的实例旨在用作常量或不可变值。由于这个原因,符号总是被冻结。

:a.frozen? #=> true

Object#freeze documentation 关于冻结对象的说明如下:

freeze → obj

Prevents further modifications to obj. A RuntimeError will be raised if modification is attempted. There is no way to unfreeze a frozen object. See also Object#frozen?.

This method returns self.

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

produces:

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

Objects of the following classes are always frozen: Integer, Float, Symbol.

这意味着将在以下行中引发错误:

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