Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 告诉可变对象_Ruby_Immutability_Mutable - Fatal编程技术网

Ruby 告诉可变对象

Ruby 告诉可变对象,ruby,immutability,mutable,Ruby,Immutability,Mutable,是否有一种方法可以判断对象是否是可变的,类似于下面的mutable??如果没有,最好的实施方法是什么 "abcde".mutable? # => true 0.mutable? # => false 为了回答mu太短和dbenhur的问题,我不喜欢enumerated.inject(initial){…}或enumerated.each_with_object(initial){…}的语法。我想要一个反转接收者和参数的方法,并且我希望它可以用于各种各样的类;因此,我: initi

是否有一种方法可以判断对象是否是可变的,类似于下面的
mutable?
?如果没有,最好的实施方法是什么

"abcde".mutable? # => true
0.mutable? # => false

为了回答mu太短和dbenhur的问题,我不喜欢
enumerated.inject(initial){…}
enumerated.each_with_object(initial){…}
的语法。我想要一个反转接收者和参数的方法,并且我希望它可以用于各种各样的类;因此,我:

initial.my_new_method(enumerated){...}

0.my_new_method(1..10){|sum, i| sum + i} # => 55
"a".my_new_method(b: 3, c: 4){|s, (k, v)| s + k.to_s * v} # => "abbbcccc"
这将使返回成为接收者的修改版本,并且在概念上更加自然。使用
我的新方法
,我希望它是非破坏性的。当接收器是可变的时,我还想定义一个破坏性的版本

initial.my_new_method!(enumerated){...}

"a".my_new_method!(b: 3, c: 4){|s, (k, v)| s << k.to_s * v} # => "abbbcccc"
initial.my\u新方法!(经点算){…}
我的新方法!(b:3,c:4){s,(k,v){s“abbbccc”

因此,检测接收器是否可变是必要的。它是否被冻结并不重要。如果我对冻结对象使用破坏性版本的方法,它只会引发错误。这没什么错。

您可以调用对象上的
.freezed?
,查看对象的实例是否不可变:

1.9.3p194 :001 > a = Array.new
 => [] 
1.9.3p194 :002 > a.frozen?
 => false 
1.9.3p194 :003 > a.freeze
 => [] 
1.9.3p194 :004 > a.frozen?
 => true 
调用
.freeze
后,将不允许对对象的该实例进行其他更改,如果有人试图更改冻结的对象,将抛出
运行时错误

编辑:

正如下面注释中提到的检查
0.freezed?
将正确返回
false
,因为0是
Fixnum
类的实例。

AFAIK所有(未冻结)对象都是可变的,除了nil、true、false以及所有整数和符号。

class Object
  def mutable?; !!(dup rescue false) end
end

有两个属性可以使对象在ruby中不可变

1) 对象可能被冻结,在这种情况下,您的不变性检查是

2) 该对象可能是一个。据我所知,没有内置方法可以判断对象是即时的,因此必须依赖即时性的副作用。即时值不允许在其上定义单例类,因此我可以尝试以下作为代理:

class Object
  def immediate_value?
    class <<self; end
    return false
  rescue TypeError
    return true
  end

  def mutable?
    !(frozen? || immediate_value?)
  end
end
类对象
def立即_值?

请注意,这将告诉您,
0
没有冻结。这不是一个错误-这是正确的答案。@Chuck谢谢您,我将把它添加到帖子中。根据您在帖子中的描述,
冻结?
正是您想要的。不,不是。您的代码无法区分(未冻结)数组和一个fixnum。我的问题清楚地表明,我期望得到不同的结果。@sawa:您试图在这里建立的区别是什么?如果不冻结fixnum,从技术上讲,它们的状态可能会发生变化。您期望fixnum是不可变的,这是错误的,因此正确回答了“如何检测不可变对象?”必须违反这一预期。如果Fixnum被视为冻结对象,即使它们不是,那么合乎逻辑的解决方案就是在实际检查冻结性之后添加
|a.is|a?Fixnum
。为什么需要这样的东西?@muistosort用于设计一个根据是否是mutab而表现不同的方法“是或不是”。@muistooshort我在我的答案中添加了为什么我想要它。为什么在一种情况下简单地提出错误是可以的,而在另一种情况下则不行?如果有人想滥用这种方法,那么欢迎他们随意多次开枪。这并不能告诉你某个东西是否可以以任何有意义的方式改变。它只是告诉你一个对象是否已经改变了一个不会引发错误的
dup
方法。冻结的对象将响应true,而具有大量可变状态的单例将返回false。+1,因为直到现在我才有了相同的想法。但是“立即”将是一个更好的名称。@steenslag Right。这就是我的意思。我不使用该方法
freeze
,所以我不需要考虑在第一种情况下。第二部分似乎接近我想要的,除了你提到的创建类的缺点。我不知道这个限制。知道这一点很好。@sawa,如果你要将一个方法#mutable?注入到一个内置类(对象)中你应该绝对地考虑冻结。状态的一部分检查你今天是否使用它。“总是像最终维护你的代码的人一样是一个知道你住在哪里的暴力精神病患者。”不管怎么说,这可能是个坏主意,你为什么想要它也不清楚。我在回答中添加了我想要它的原因。这个枚举的问题是它取决于ruby的一个特定实现。语言定义没有说这些类是立即值,这只是当前参考实现的一个细节。明天ruby core可能决定立即实施浮动,并且他们不会违反任何语言合同。