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


Groups > comp.lang.python > #197552

Re: an adventure: a Lisp-style linked list

From ram@zedat.fu-berlin.de (Stefan Ram)
Newsgroups comp.lang.python
Subject Re: an adventure: a Lisp-style linked list
Date 2025-09-04 00:47 +0000
Organization Stefan Ram
Message-ID <lists-20250904013639@ram.dialup.fu-berlin.de> (permalink)
References <87o6rrt9kq.fsf@somewhere.edu>

Show all headers | View raw


Ethan Carter <ec1828@somewhere.edu> wrote or quoted:
>## 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:

  I think this lies in the nature of lists, as the rest can
  have at least two types: it might be another list or empty.

>##                                                             Can you
>## suggest anything beyond the obvious of ``write Python when using
>## Python''? 

  I'd use a two-layered approach:

  - CONS (dotted pairs), CAR, CDR, NIL and NULL as the lower layer

  - lists on top of that.

from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any

# Layer 0: CONS, CAR, CDR, and NIL

class Object( ABC ): # common interface for CONS and NIL

    @abstractmethod
    def null( self ) -> bool: ...

@dataclass( frozen=True )
class Cons( Object ): # dotted pairs

    car: Any
    cdr: Any

    def null( self ) -> bool:
        return False

@dataclass( frozen=True )
class Nil( Object ):

    def null( self )-> bool:
        return True

nil: Nil = Nil() # singleton

def null( x: Object ) -> bool:
    return x.null()

# Layer 1: lists

def make_list( *args: Any )-> Object:
    result: Object = nil
    for arg in reversed( args ):
        result = Cons( arg, result )
    return result

def print_list( lst: Object )-> None:
    print( end="(" )
    current = lst
    first = True
    while not null( current ):
        assert isinstance( current, Cons )
        if not first: print( end=" " )
        print( end=str( current.car ))
        current = current.cdr
        first = False
    print( end=")" )

# A perfect LISP imitation would also have special LISP-like int 
# objects, but for brevity's sake, here, I just use Python's ints.

l = make_list( 1, 2, 3 )
print_list( l )

  prints:

(1 2 3)

Back to comp.lang.python | Previous | NextPrevious in thread | Next 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