1

次のように、オブジェクトが可変かどうかを判断するメソッドはありmutable?ますか?そうでない場合、それを実装するための最良の方法は何ですか?

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

enumerated.inject(initial){...}muに答えるには短すぎて、dbenhurの質問ですが、またはの構文は好きではありません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"

これにより、レシーバーの修正バージョンが返され、概念的にはより自然になります。そして、でmy_new_method、私はそれが非破壊的であることを望みました。レシーバーが可変の場合、破壊的なバージョンをさらに定義したかった

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

"a".my_new_method!(b: 3, c: 4){|s, (k, v)| s << k.to_s * v} # => "abbbcccc"

したがって、受信機が可変であるかどうかを検出する必要があります。凍っていても構いません。破壊的なバージョンのメソッドをフリーズしたオブジェクトで使用すると、単にエラーが発生します。それは何も悪いことではありません。

4

4 に答える 4

2

AFAIKすべての(凍結されていない)オブジェクトは、nil、true、false、およびすべての整数と記号を除いて、変更可能です。

于 2012-10-11T23:05:10.443 に答える
1

オブジェクトを呼び出し.frozen?て、オブジェクトのそのインスタンスが不変であるかどうかを確認できます。

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、オブジェクトのそのインスタンスで他の変更は許可されませんRuntimeError。誰かがフリーズしたオブジェクトを変更しようとすると、がスローされます。

編集:

以下のチェックで言及されているように、 0はクラスのインスタンスであるため、コメントで0.frozen?正しく返されます。falseFixnum

于 2012-10-11T22:37:45.803 に答える
1

rubyでオブジェクトを不変にすることができる2つのプロパティがあります

1)オブジェクトはで凍結される可能性がありObject#freezeます。その場合、不変性チェックは次のようになります。Object#frozen?

2)オブジェクトは即値である可能性があります。オブジェクトが即時であると私が知っている組み込みのメソッドはないので、即時の性質の副作用に依存する必要があります。即時値にシングルトンクラスを定義することは許可されていないため、プロキシとして次のことを試してみてください。

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

  def mutable?
    !(frozen? || immediate_value?)
  end
end

これはおそらくかなり信頼できる検出器ですが(オブジェクトのシングルトンクラスを開くのを防ぐ別のメカニズムはわかりません)、クエリされたオブジェクトごとにシングルトンクラスを作成するという不幸な副作用があります。

于 2012-10-12T05:35:33.050 に答える
-2

私はこれを思いついた

class Object
  def mutable?; !!(dup rescue false) end
end
于 2012-10-11T23:33:48.693 に答える