gpt4 book ai didi

ruby - 如何解冻 Ruby 中的对象?

转载 作者:数据小太阳 更新时间:2023-10-29 06:23:59 25 4
gpt4 key购买 nike

在 Ruby 中,有 Object#freeze ,这会阻止对对象的进一步修改:

class Kingdom
attr_accessor :weather_conditions
end

arendelle = Kingdom.new
arendelle.frozen? # => false
arendelle.weather_conditions = 'in deep, deep, deep, deep snow'
arendelle.freeze
arendelle.frozen? # => true
arendelle.weather_conditions = 'sun is shining'
# !> RuntimeError: can't modify frozen Kingdom

script = 'Do you want to build a snowman?'.freeze
script[/snowman/] = 'castle of ice'
# !> RuntimeError: can't modify frozen String

但是,没有Object#unfreeze。有办法解冻卡住的王国吗?

最佳答案

更新:从 Ruby 2.7 开始,这不再有效!


是和否。没有任何直接使用标准 API 的方法。但是,有了一些了解#freeze?确实如此,您可以解决它。注意:这里的所有内容都是 MRI 当前版本的实现细节,可能会有所更改。


CRuby 中的对象存储在结构 RVALUE 中.
方便的是,结构中的第一件事是 VALUE flags; .
全部Object#freeze确实设置了一个标志,称为FL_FREEZE ,实际上是 equal to RUBY_FL_FREEZE . RUBY_FL_FREEZE基本上是11th bit在旗帜中。
解冻对象所需要做的就是取消设置第 11 位。

为此,您可以使用 Fiddle ,它是标准库的一部分,可让您在 C 级别修改语言:

require 'fiddle'

class Object
def unfreeze
Fiddle::Pointer.new(object_id * 2)[1] &= ~(1 << 3)
end
end

immediate value objects in Ruby存储在 address = their object_id * 2 。请注意,进行区分很重要,这样您就会知道这不会让您解冻 Fixnum例如。

因为我们要改变第 11 位,所以我们必须处理第二个字节的第 3 位。因此我们访问第二个字节 [1] .

~(1 << 3)类次 1三个位置,然后反转结果。这样,掩码中唯一的 0 位将是第三位,所有其他位都是 ones

最后,我们只需使用 按位和 ( &= ) 应用掩码。


foo = 'A frozen string'.freeze
foo.frozen? # => true
foo.unfreeze
foo.frozen? # => false
foo[/ (?=frozen)/] = 'n un'
foo # => 'An unfrozen string'

关于ruby - 如何解冻 Ruby 中的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35633367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com