Why I still reach for Lisp and Scheme instead of Haskell

Lisp/Scheme vs Haskell: overall sentiment

  • Many commenters agree with preferring Scheme/Lisp for personal projects because it “fits how they think,” especially for exploratory or interactive work.
  • Others enjoy Haskell but relegate it to niche uses (e.g., window manager configs) or specific domains.
  • Some say language choice is mostly about “how you like to work,” not pure technical superiority.

Syntax, expressiveness, and aesthetics

  • Lisp’s uniform syntax and small set of “atoms” are praised for composability and conceptual simplicity.
  • Several argue Haskell syntax is dense, ambiguous “word salad” that slows reading; others strongly defend it as elegant, concise “executable math.”
  • There is extended debate over Haskell’s indentation rules and layout, especially let/in alignment, with some finding them confusing and others considering them simple or too lenient.
  • Factorial examples are used to argue that ML/Haskell can be as concise as, or more concise than, Scheme; others say discomfort with unfamiliar syntax is more about taste than ability.

Types, safety, and scale

  • A Schemer who built a large Gambit codebase came away wanting a static type system for catching bugs.
  • Alternatives suggested: Common Lisp’s optional typing, and multiple “typed Lisps” (Coalton, Carp, Crunch, Jank).
  • Some are wary of large Haskell codebases despite the type safety, suggesting tradeoffs between safety and complexity.

Macros, DSLs, and s-expressions

  • Opinions diverge on macros: some rarely need them in Racket due to rich libraries; others use them mainly for fun or to remove boilerplate.
  • syntax-rules is seen by some as too constrained; others note it was meant as a minimal common denominator, with more powerful systems like syntax-case or implementation-specific macro systems.
  • One thread contrasts Haskell’s Parsec-driven DSL proliferation with the Lisp approach of normalizing XML/JSON into s-expressions, then operating on them uniformly.
  • Kernel’s fexpr-based “operatives” are presented as an alternative to macros, blurring compile-time vs run-time and enabling multi-stage programming.

REPL, live systems, and debugging

  • Interactive development (REPL, SWANK/SLIME-style) is widely seen as a major Lisp advantage: edit running programs, inspect state, redefine functions, even in production.
  • This is reported in Common Lisp, Clojure (via nREPL/CIDER/Calva), and to some extent Scheme/Racket, though Racket’s story is described as less clear or weaker.
  • Several note similar but less integrated experiences in Python (pdb), Ruby consoles, Emacs Lisp, and Java with strong IDEs and tools like JRebel/DCEVM.
  • Hot-patching in production is described as powerful but risky and rarely appropriate in multi-instance, autoscaled, or security-sensitive systems.

Debugging, logging, and Haskell specifics

  • Haskell’s IO and purity make ad-hoc print debugging harder; commenters mention Debug.Trace.trace as a workaround but note laziness affects when prints run.
  • Some argue they rely less on prints due to small pure functions, property-based testing, and strong types; others note that in distributed systems, robust logging is still essential.
  • There is debate over whether Haskell’s constraints and abstractions help or hinder rapid prototyping and “caveman debugging.”

Other paradigms and languages

  • Prolog (and Erlang by extension) is cited as better than Lisps for expressing complex domains in relational terms; others say it depends on problem shape and layer Prolog, OCaml, CLOS, and Lisp together.
  • Some emphasize that language readability can be assessed with ideas from typography and cognitive load, but what counts as “beautiful” or “natural” remains highly subjective across commenters.