""" Remove the first occurrence of a value from the vector. >>> v1 = v(1, 2, 3, 2, 1) >>> v2 = v1.remove(1) >>> v2 pvector([2, 3, 2, 1]) >>> v2.remove(1) pvector([2, 3, 2]) """ _EMPTY_PVECTOR = PythonPVector(0, SHIFT, [], []) PVector.register(PythonPVector) Sequence.register(PVector) Hashable.register(PVector) def python_pvector(iterable=()): """ Create a new persistent vector containing the elements in iterable. >>> v1 = pvector([1, 2, 3]) >>> v1 pvector([1, 2, 3]) """ return _EMPTY_PVECTOR.extend(iterable) try: # Use the C extension as underlying trie implementation if it is available
pmap({'b': 2, 'a': 1}) The changes are kept in the evolver. An updated pmap can be created using the persistent() function on the evolver. >>> m2 = e.persistent() >>> m2 pmap({'c': 3, 'b': 2}) The new pmap will share data with the original pmap in the same way that would have been done if only using operations on the pmap. """ return self._Evolver(self) Mapping.register(PMap) Hashable.register(PMap) def _turbo_mapping(initial, pre_size): if pre_size: size = pre_size else: try: size = 2 * len(initial) or 8 except Exception: # Guess we can't figure out the length. Give up on length hinting, # we can always reallocate later. size = 8 buckets = size * [None]
__and__ = Set.__and__ __or__ = Set.__or__ __sub__ = Set.__sub__ __xor__ = Set.__xor__ issubset = __le__ issuperset = __ge__ union = __or__ intersection = __and__ difference = __sub__ symmetric_difference = __xor__ isdisjoint = Set.isdisjoint Set.register(PSet) Hashable.register(PSet) _EMPTY_PSET = PSet(pmap()) def pset(iterable=(), pre_size=8): """ Creates a persistent set from iterable. Optionally takes a sizing parameter equivalent to that used for :py:func:`pmap`. >>> s1 = pset([1, 2, 3, 2]) >>> s1 pset([1, 2, 3]) """ if not iterable: return _EMPTY_PSET
type(index).__name__) if index >= 0: return self.popleft(index).left shifted = len(self) + index if shifted < 0: raise IndexError( "pdeque index {0} out of range {1}".format(index, len(self)), ) return self.popleft(shifted).left index = Sequence.index Sequence.register(PDeque) Hashable.register(PDeque) def pdeque(iterable=(), maxlen=None): """ Return deque containing the elements of iterable. If maxlen is specified then len(iterable) - maxlen elements are discarded from the left to if len(iterable) > maxlen. >>> pdeque([1, 2, 3]) pdeque([1, 2, 3]) >>> pdeque([1, 2, 3, 4], maxlen=2) pdeque([3, 4], maxlen=2) """ t = tuple(iterable) if maxlen is not None: t = t[-maxlen:]
__slots__ = ('first', 'rest') def __new__(cls, first, rest): instance = super(PList, cls).__new__(cls) instance.first = first instance.rest = rest return instance def __bool__(self): return True __nonzero__ = __bool__ Sequence.register(PList) Hashable.register(PList) class _EmptyPList(_PListBase): __slots__ = () def __bool__(self): return False __nonzero__ = __bool__ @property def first(self): raise AttributeError("Empty PList has no first") @property
""" Hash based on value of elements. >>> m = pmap({pbag([1, 2]): "it's here!"}) >>> m[pbag([2, 1])] "it's here!" >>> pbag([1, 1, 2]) in m False """ return hash(self._counts) Container.register(PBag) Iterable.register(PBag) Sized.register(PBag) Hashable.register(PBag) def b(*elements): """ Construct a persistent bag. Takes an arbitrary number of arguments to insert into the new persistent bag. >>> b(1, 2, 3, 2) pbag([1, 2, 2, 3]) """ return pbag(elements)
#@final def __eq__(ops, other_ops): if type(other_ops) is not type(ops): return NotImplemented return ops.get_args_for_eq_hash() == other_ops.get_args_for_eq_hash() return ops.__eq == other_ops.__eq #@final def __hash__(ops): return hash((type(ops), ops.get_args_for_eq_hash())) return hash((type(ops), ops.__eq)) @not_implemented def get_args_for_eq_hash(ops): ... ''' @not_implemented def __eq__(self, other): return self is other @not_implemented def __hash__(self): return id(self) ''' def __ne__(self, other): return not (self == other) Hashable.register(IOps) assert issubclass(IOps, Hashable)