Sets can only contain immutable elements. For convenience,
mutable Set objects are automatically copied to an ImmutableSet
before being added as a set element. The mechanism is to always
add a hashable element, or if it is not hashable, the element is
checked to see if it has an __as_immutable__() method which
returns an immutable equivalent. Since Set objects have a
__as_immutable__() method returning an instance of ImmutableSet,
it is possible to construct sets of sets. A similar mechanism is
needed by the __contains__() and remove() methods which need to
hash an element to check for membership in a set. Those methods
check an element for hashability and, if not, check for a
__as_temporarily_immutable__() method which returns the element
wrapped by a class that provides temporary methods for
__hash__(), __eq__(), and __ne__(). The alternate mechanism
spares the need to build a separate copy of the original mutable
object. Set objects implement the __as_temporarily_immutable__()
method which returns the Set