如何在没有RuntimeError的情况下在Ruby中修改符号:无法修改冻结的符号?

时间:2018-09-30 11:21:21

标签: ruby runtime-error symbols

如果位置与给定条件匹配,我试图更改棋子的颜色,但是不断收到以下错误消息:

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 :(得分:1)

Symbol 的Ruby实例中,旨在用作常量或不可变值。因此,符号始终被冻结。

:a.frozen? #=> true

Object#freeze documentation对冻结的对象说以下话:

  

冻结→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
     

以下类别的对象始终被冻结:IntegerFloatSymbol

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

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
相关问题