It make sense to not allow links to external code hosting, so I restated my question. This is classical cons list in python using Abstract Base Class interface. Constructor is in fact out of the Cons class, but I didn't see the way to put recursive code inside init.
# immutable, cons list and few methods
class Nil:
"""class Nil, the empty list"""
def is_empty(self):
return True
def head(self):
return Exception("Empty")
def tail(self):
return Exception("Empty")
def get_next(self):
return None
def __str__(self):
return "()"
class Cons:
"""Class cons, the non empty list: (head, list)"""
def __init__(self, _head, _tail):
self.head = _head
self.tail = _tail
def is_empty(self):
return False
def get_next(self):
return self.tail
def __str__(self):
current = self.tail
out = "(" + str(self.head)
while current != Nil:
out += ' ' + str(current.head)
current = current.get_next()
return out +')'
class List(metaclass=ABCMeta):
"""Abstarct class List"""
@abstractmethod
def is_empty():
pass
def head():
pass
def tail():
pass
List.register(Nil);
List.register(Cons)
def nth(n , xs):
"""Returns nt-h (0 based indexing) elemt of the list,
throws an exception when out of range"""
if xs is Nil:
return Exception("Out Of Bound")
if n == 0:
return xs.head
else:
return nth(n - 1, xs.tail)
def length(xs):
"""Returns length of a list O(n)"""
if xs is Nil:
return 0
else:
return 1 + length(xs.tail)
def cons(elem ,xs):
"""Cons element elem to the list"""
return Cons(elem, xs)
def subs_in_expr(new, old, xs):
""" this helper function works put single
list element which maybe list itself"""
if xs is not Cons:
if xs == old:
return new
else:
return xs
else:
return subst(new, old, xs)
def subst(new, old, xs):
"""substitutes new as old in a list(possible nested) """
if xs is Nil:
return Nil
else:
return cons(subs_in_expr(new, old, xs.head) , subst(new ,old, xs.tail))
def Create_list(args):
"""Crates immutable list from an iterable"""
if len(args) == 0:
return Nil()
tmp = len(args) - 1
def helper(xs, cnt, limit):
if cnt > limit:
return Nil
else:
return cons(xs[cnt], helper(xs, cnt + 1, limit))
return helper(args, 0, tmp)
l1 = Create_list(range(10))
print(l1)
print(nth(3, l1))
print(length(l1))
l2 = subst("A CAT", 0, l1)
print(l2)
'''
output --->
(0 1 2 3 4 5 6 7 8 9)
3
10
(A CAT 1 2 3 4 5 6 7 8 9)
<---
'''
I wrote few methods, they work so far, I think it's OK?
Added after edit:
def remove_nth(n, xs):
"""Removes the n-th elem in the list, throw an Exception
if index out of bounds"""
if isinstance(xs, Nil):
return Exception("Out of Bounds")
else:
if n == 0:
if xs.tail is not Nil:
return cons(xs.tail.head, xs.tail.tail)
else:
return Nil
else:
return cons(xs.head, remove_nth(n - 1, xs.tail))