Search code examples
pythonconscdr

Proper lists and recursive tail in Python


In various Lisps a proper list is either nil (a null value) or a cons cell, where the first (head, first, car) value points to a value and the second (tail, rest, cdr) points to another proper list. Various other functional programming languages implement this head and tail functionality, including Erlang and Scala. In Common Lisp and Emacs Lisp you can infinitely recursively find a tail of a list:

(rest (rest (rest (rest (rest (rest ()))))))

It will yield nil. I want to emulate that behavior in Python. Sure, for performance i'd better stick with native datatypes, which are heavily optimized, so this is only for exercise. My code is:

class MyList:
    def __init__(self, *xs):
        self._x = []
        self._x.extend(xs)
        self.is_empty = not xs
        self.head = xs[0] if xs else None
        self.tail = MyList(*xs[1:]) if xs[1:] else MyList([])

However calling tail now enters a recursion and results in maximum recursion depth error. How can i make expressions like below possible? In other words, how can i create functionality of a proper list in Python?

a = MyList(1,2)
my_list.tail.tail.tail.tail.tail.tail

Related question, but does not answer my question: LISP cons in python


Solution

  • I've tried rewriting your example a bit - this seems to work for me without blowing the stack.

    class MyList(object):
        def __init__(self, *xs):
            self._x = xs if all(xs) else tuple()
            self.head = xs[0] if xs else None
    
        @property
        def is_empty(self):
            return not self._x
    
        @property
        def tail(self):
            return MyList(self._x[1:]) if self._x[1:] else MyList([])
    
    s = MyList(1, 2)
    print s.tail.tail.tail.tail.tail.tail