##
3 不変に自動変換するためのプロトコル

集合は変更不可能な要素だけを含むことできます。 都合上、変更可能な`Set`オブジェクトは、集合要素として加えられる前に、 自動的に`ImmutableSet`へコピーします。 そのメカニズムはハッシュ可能な要素を常に加えることですが、 もしハッシュ不可能な場合は、その要素は変更不可能な等価物を返す `__as_immutable__()`メソッドを持っているかどうかチェックされます。

`Set`オブジェクトは、`ImmutableSet`のインスタンスを返す `__as_immutable__()`メソッドを持っているので、集合の集合を構築 することが可能です。

集合内のメンバーであることをチェックするために、 要素をハッシュする必要がある`__contains__()`メソッドと `remove()`メソッドが、同様のメカニズムを必要としています。 これらのメソッドは要素がハッシュできるかチェックします。 もし出来なければ-`__hash__()`,`__eq__()`,`__ne__()` のための一時的なメソッドを備えたクラスによってラップされた要素を返すメソッド- `__as_temporarily_immutable__()`メソッドをチェックします。

代理メカニズムは、オリジナルの可変オブジェクトから分かれたコピーを 組み上げる手間を助けてくれます。

`Set`オブジェクトは、新しいクラス`_TemporarilyImmutableSet` によってラップされた`Set`オブジェクトを返す、 `__as_temporarily_immutable__()`メソッドを実装します。

ハッシュ可能を与えるための2つのメカニズムは通常ユーザーに見えません。 しかしながら、マルチスレッド環境下においては、 `_TemporarilyImmutableSet`によって一時的にラップされたものを 持っているスレッドがあるときに、もう一つのスレッドが集合を更新することで、 衝突を発生させることができます。 言いかえれば、変更可能な集合の集合はスレッドセーフではありません。