HN Debrief

Why Janet? (2023)

The post is a 2023 essay arguing for Janet, a small Lisp-like language released in 2019 that aims to be simple, embeddable, portable, and pleasant for scripting. It sells Janet on a few concrete traits: a tiny runtime, easy binary generation, compile-time evaluation that can bake data into executables, built-in parsing tools based on parsing expression grammars, and Lisp-style macros without some of the old Lisp naming baggage. For readers who have never touched it, the rough comparison people kept reaching for was “Lua or Tcl for embedding and scripts, but with a modern Lisp shape and stronger macro story.”

For teams evaluating niche runtimes, Janet looks less like a general-purpose platform bet and more like a sharp tool for embedded scripting, compact deployables, and developer-centric DSL work where startup time and control matter more than ecosystem breadth.

Discussion mood

Mostly positive and curious. People liked Janet’s small runtime, embeddability, fast startup, shell scripting ergonomics, and macro-friendly design. The hesitation centered on thin libraries, immature package management, weak namespace and immutability stories compared with Clojure, and a few technical design choices that make it a poor fit for some embedding scenarios.

Key insights

  1. 01 Janet’s biggest tradeoff against Babashka and Clojure is not syntax.
    It is data structure semantics. Commenters argued that Clojure’s persistent collections and standard library make data-heavy scripting much more capable because immutable updates use structural sharing instead of flat copies, and the built-ins already assume you are transforming maps, vectors, and sets at scale. That reframes Janet as stronger for subprocess-heavy scripts, tiny runtimes, and embedding, but weaker once the job turns into serious data wrangling.

    If your script spends more time shaping large datasets than launching tools, Clojure-style runtimes still have a real edge. Janet wins when deployment footprint and shell adjacency matter more.
      Attribution:
    • iLemming #1 #2
  2. 02 Janet’s embedding story is good until you need multiple fully isolated interpreters in one process.
    The key criticism was that thread-local global state is still a real constraint for plugin-style hosts like VST3, AU, AAX, and CLAP, where many instances run inside one address space and the host controls callback threads. That is a materially different bar from “can be embedded in C,” and it puts Janet behind Lua and newer Python subinterpreters for some commercial embedding use cases.

    “Embeddable” is not one thing. If you need host-controlled, multi-instance, same-process isolation, Janet’s runtime model can disqualify it.
  3. 03 The PEG discussion exposed an important mismatch between language-design elegance and day-to-day parser work.
    Supporters liked PEGs because ordered choice makes ambiguity explicit and often easier to control than conventional grammars. Critics pushed back that this only feels simple if you already internalize PEG’s non-obvious constraints like no left recursion and careful rule ordering. For real-world grammars, that can turn into hidden rewrite work and poor developer experience. The useful conclusion was that PEGs are powerful, but not a drop-in replacement for regexes or general parser generators.

    Janet’s PEG tooling is a feature for the right user, not a universal simplification. Teams should treat it as a specific parsing model with real constraints.
      Attribution:
    • xigoi #1 #2
    • bmn__ #1
    • jsmith45 #1
  4. 04 Janet’s compile-time execution model is more practical than the blog post made obvious.
    A detailed example showed loading a TSV at build time, materializing it into a hashmap inside the binary, and turning runtime lookups into plain in-memory access. The commenter claimed this beat an equivalent Go approach that needed code generation and a giant literal data file to get similar performance. Even if you discount the benchmark, the architectural point stands: Janet makes partial evaluation and data baking feel native instead of bolted on.

    Janet’s strongest trick is not just macros. It is how cheaply it lets you move work out of runtime and ship the result.
      Attribution:
    • veqq #1 #2

Against the grain

  1. 01 The reflexive fear of DSLs is overstated.
    One commenter cut through the usual “only you will understand this later” complaint by pointing out that every codebase already has a DSL, whether it is explicit in syntax or implicit in APIs and patterns. In a macro-capable language, making that domain language visible can actually reduce accidental complexity instead of hiding it behind framework conventions.

    A well-made DSL is not automatically a maintenance smell. It can be clearer than the unofficial DSLs teams build by accident.
      Attribution:
    • ifidishshbsba #1
    • frwrfwrfeefwf #1
  2. 02 Not everyone who understands Lisp wants to work in Lisp.
    Several comments pushed back on the quasi-religious tone around parentheses, REPLs, and macros by saying the tradeoff is real, not ignorance. Static typing, mainstream tooling, and visual readability remain decisive for many experienced developers who have already tried Racket, Clojure, and Babashka and still chose Python, Go, or Rust.

    Janet’s ceiling is limited as much by taste and team ergonomics as by missing features. “You just don’t get it” is not a serious rebuttal.
      Attribution:
    • layer8 #1
    • maleldil #1 #2
  3. 03 Tcl remains a live alternative for much of what Janet claims as its niche.
    The comparison that landed was simple: Tcl is still compelling if you care about UI tooling and its distinctive command model, while Janet is the better fit if you want a cleaner embedded scripting language and stronger macro capabilities. That weakens the idea that Janet owns this territory outright.

    Janet is not the only small embeddable language worth considering. Tcl is old, but it still solves adjacent problems differently and sometimes better.
      Attribution:
    • ux266478 #1
    • embedding-shape #1
    • adrian_b #1
    • sph #1

Reference links

Janet docs and ecosystem

  • Janet sandbox API docs
    Referenced as a standout security feature for disabling system capabilities in embedded or untrusted code scenarios.
  • Janet community tutorials
    Suggested as a gentler starting point than the better-known book.
  • janet.guide
    Shared as a helpful guide for learning Janet.
  • Janet embedding docs
    Used to clarify the thread-local runtime model during the embedding debate.
  • sh-dsl in Janet Spork
    Pointed to as the standard library shell DSL that makes Janet attractive for scripting.

Janet libraries and projects

  • jeep
    Offered as a workaround for Janet’s package management limitations by vendoring dependencies and installing bundles without JPM.
  • Joy web framework
    Repeatedly cited as the main example of serious Janet web development and HTTP support.
  • jurl
    Recommended as a working Janet HTTP and TLS client wrapper.
  • churlish
    Mentioned as another Janet HTTP client option.
  • small-peg-tracer
    Suggested as a debugging aid for understanding PEG behavior.

Related languages and implementations

  • Fennel
    Raised as the closest sibling project from the same creator, useful for comparing Janet with a Lisp that targets Lua.
  • LuaJIT issue #1457 on VM instrumentation
    Shared to show ongoing work that could improve debugging and tooling for Fennel and other LuaJIT-hosted languages.
  • Hy language
    Brought up as another Lisp-flavored language, this time riding on Python.

Performance and compile-time examples

  • Verse Reader performance notes
    Used to support claims about Janet’s speed and about compile-time data baking beating a comparable Go approach in one case.
  • jnj
    Referenced as a way to use J from Janet and as part of a broader argument for Janet-powered DSLs and array programming ideas.

Lisp workflow and background

  • Calva Paredit
    Given as a concrete example of structural editing tooling that makes Lisp workflows click for some developers.
  • Peter Norvig’s Lispy
    Suggested as an accessible way to understand Lisp by implementing a tiny interpreter.
  • Peter Norvig’s Lispy 2
    Follow-up resource for learning Lisp internals by building an interpreter.