Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #197551

an adventure: a Lisp-style linked list

From Ethan Carter <ec1828@somewhere.edu>
Newsgroups comp.lang.python
Subject an adventure: a Lisp-style linked list
Date 2025-09-03 20:12 -0300
Organization A noiseless patient Spider
Message-ID <87o6rrt9kq.fsf@somewhere.edu> (permalink)

Show all headers | View raw


# -*- mode: python; python-indent-offset: 2 -*-

## As an exercise, I decided to implement a Lisp-style linked list
## using a class List.  I'm a bit surprised by the result: it seems
## polymorphism forces me to write a recursive procedure in two
## halves: one half in the List class itself and the other half in the
## Empty class.  For example, I created a class called Empty as a
## singleton.  So when I wrote the __len__ procedure for a List, I
## cannot treat the base case in the List.__len__ procedure because
## the base case really belongs to another class---since an empty list
## is not really a List, but rather of type Empty.

## This is because the Lisp list is really a union of two types, so
## using classes produces this situation.  What do you think?  Can you
## suggest anything beyond the obvious of ``write Python when using
## Python''?  Perhaps you do know how to implement a union in a more
## elegant way?  I'd love to see if you can workaround this in a
## prettier way.  Thanks very much.

## Usage:
## 
## >>> ls = List(0, List(1, List(2, List.Empty())))
## >>> len(ls)
## 3
## >>> ls[1]
## 1
## >>> ls[2]
## 2
## >>> ls[3]
## Traceback (most recent call last):
## [...]
## Exception: no such element

class List:
  head = None
  tail = None

  def __init__(self, d, ls):
    self.head = d
    self.tail = ls

  def getitem(self, n):
    if n == 0:
      return self.first()
    return self.rest().getitem(n - 1)

  def __getitem__(self, n):
    return self.getitem(n)
  
  def empty(self):
    return self is List.Empty()
  
  def first(self):
    return self.head

  def rest(self):
    return self.tail

  def __repr__(self):
    return f"List({self.head}, {self.rest()})"

  def __len__(self):
    return 1 + len(self.rest())

  class Empty:
    instance = None

    def __new__(cls):
      if cls.instance is None:
        cls.instance = super().__new__(cls)
      return cls.instance

    def __repr__(self):
      return "List.Empty()"

    def __len__(self):
      return 0

    def getitem(self, n):
      raise Exception("no such element")

Back to comp.lang.python | Previous | NextNext in thread | Find similar


Thread

an adventure: a Lisp-style linked list Ethan Carter <ec1828@somewhere.edu> - 2025-09-03 20:12 -0300
  Re: an adventure: a Lisp-style linked list ram@zedat.fu-berlin.de (Stefan Ram) - 2025-09-04 00:47 +0000
  Re: an adventure: a Lisp-style linked list pa@see.signature.invalid (Pierre Asselin) - 2025-09-04 18:41 +0000
    Re: an adventure: a Lisp-style linked list Ethan Carter <ec1828@somewhere.edu> - 2025-09-05 13:06 -0300

csiph-web