Homoiconic Python
What this project actually is
- Multiple commenters note the project is essentially “Lisp in Python,” not “homoiconic Python.”
- Some expected Python’s native syntax/AST to be directly manipulable; instead, it’s an interpreter for a Lisp-like language written in Python.
- Debate on homoiconicity:
- One view: it means the language is implemented in itself.
- Another: it means code is a first-class data structure that can be constructed, inspected, and evaluated at runtime, regardless of implementation language.
- Some doubt that truly homoiconic Python is possible without Python syntax being composed of native data structures evaluated directly.
Related languages and tools
- Suggestions for “Python-like scripting Lisps” or Lisp-on-Python:
- Hy, Basilisp (Clojure-style lisps targeting Python).
- Janet (fast, embeddable, Lua-style VM).
- Ciel (batteries-included Common Lisp “scripting” setup).
- Rhombus (Python-ish surface syntax with Racket-style macros).
- Other experiments: js-lisp (Lisp in JS), fakelisp (Lisp-like tuples in Python), yamlscript (“program in YAML”), Binary Lambda Calculus in Python, and a “homoiconic Java” DSL.
Lisp REPL, debugging, and error handling vs Python
- Several comments praise Common Lisp’s REPL-driven workflow and debugging:
- Ability to recompile and patch live code, inspect and modify stack frames, and resume execution via restarts.
- Conditions/restarts separate error detection, handler choice, and recovery strategy, often allowing interactive continuation.
- In contrast, Python typically unwinds the stack on exceptions; state at the throw site is lost after unwinding.
- Some point out Python can still break into debuggers at exceptions and inspect locals; tools like
py-spy,pystack,cpython-lldb, and periodic checkpointing (e.g., Joblib) are suggested. - Consensus: long-running Python jobs should persist intermediate state; relying on live introspection alone is risky.
Expressiveness, macros, and readability
- Many admire Lisps’ expressiveness, macros, and historical influence; others argue that this freedom often leads to unreadable “abominations.”
- One view: languages like Go or Python intentionally restrict expressiveness (no rich macros, clunky lambdas) to limit how “clever” or non-idiomatic code can become.
- Counterpoints:
- Any language can host terrible code; organization and developers matter more.
- Lisp style guides explicitly caution against overusing macros; they are powerful but should be written sparingly.
- Macros can improve readability by creating concise domain-specific layers (e.g., object systems) that hide lower-level complexity.
Types and “taming” Lisp
- For those worried about large Lisp codebases becoming hard to reason about:
- Typed Racket and Shen are offered as strongly-typed Lisps.
- Dylan and Common Lisp (with compiler type declarations and warnings, especially in SBCL) are mentioned as Lisps with useful type systems or type checking support.