<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7" -->

---
title: Lisp in 99 Lines of C and How to Write One Yourself
description: A compact implementation of Lisp written in just 99 lines of C, covering 21 Lisp primitives, garbage collection, and a REPL. Also includes tail-call optimized...
canonical: https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Lisp in 99 Lines of C and How to Write One Yourself | daily.dev
og:description: A compact implementation of Lisp written in just 99 lines of C, covering 21 Lisp primitives, garbage collection, and a REPL. Also includes tail-call optimized...
og:url: https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7
og:image: https://api.daily.dev/og/posts/W2EEmvLF7.png
og:image:alt: Lisp in 99 Lines of C and How to Write One Yourself
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Lisp in 99 Lines of C and How to Write One Yourself

**[Lobsters](https://daily.dev/sources/lobsters)** · 1 min read · 0 upvotes · 0 comments

## Summary

A compact implementation of Lisp written in just 99 lines of C, covering 21 Lisp primitives, garbage collection, and a REPL. Also includes tail-call optimized versions for improved speed and reduced memory usage, along with a guide on how to write one yourself.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://github.com/Robert-van-Engelen/tinylisp/blob/main/tinylisp.pdf>

## Community take

How the wider developer community reacted, aggregated from 2 discussions and 139 comments across lobsters, hackernews (as of 2026-08-05).

**TL;DR:** The community is broadly enthusiastic about this compact Lisp implementation, praising the NaN boxing technique and the pedagogical value, while some critique the code style (single-letter macros, line-packing) and note that continuations are a missing feature.

**Sentiment:** 55% positive · 30% mixed · 15% skeptical

**The case for**

- NaN boxing is highlighted as a clever and elegant technique for packing type information into a double.
- The implementation is praised for being well-documented and easier to read than comparable minimal Lisps like sectorlisp.
- Commenters found it genuinely clarifying for understanding Lisp internals compared to other papers and resources.
- The tail-call optimization and garbage collection in so few lines impressed several readers.

**The pushback**

- The '99 lines' claim is seen as misleading since multiple statements are packed onto single lines (119 semicolons noted).
- Single-letter macro aliases like `#define L double` are considered poor C style and an abuse of the preprocessor.
- Continuations are not implemented, which is noted as a significant omission for a 'serious' Lisp.
- Some feel the project lacks practical value without built-in networking or concurrency support for real-world use.

**By community**

- lobsters (positive): Commenters appreciated the 'lispy' C style reminiscent of array-language implementations, and one learned about NaN boxing from the project.
- hackernews (mixed): Broadly positive reception for the pedagogical value and NaN boxing technique, but with notable criticism of the code style, the line-count gimmick, and missing features like continuations.

**Hottest debate:** Whether packing multiple statements per line to hit '99 lines' is a meaningful or misleading measure of implementation complexity.

**Open questions**

- How would one efficiently implement stackful continuations (call/cc) in a C-based Lisp interpreter?
- Is it worth adding networking and concurrency primitives to small Lisp implementations, or should they rely on FFI/bindings?
- Do modern JavaScript engines still use NaN boxing?

**Highlights**

> The [code](https://github.com/Robert-van-Engelen/tinylisp) is quite lispy, similar to how modern array languages are implemented in Arthur Whitney style C, resembling an array language: ```c #define L double L cons(L x,L y) { cell[--sp] = x; cell[--sp] = y; if (hp > sp<<3) abort(); return box(CONS,sp); } L car(L p) { return (T(p)&~(CONS^CLOS)) == CONS ? cell[ord(p)+1] : err; } L cdr(L p) { return (T(p)&~(CONS^CLOS)) == CONS ? cell[ord(p)] : err; } L bind(L v,L t,L e) { return not(v) ? e : T(v) == CONS ? bind(cdr(v),cdr(t),pair(car(v),car(t),e)) : pair(v,t,e); L reduce(L f,L t,L e) { return eval(cdr(car(f)),bind(car(car(f)),evlis(t,e),not(cdr(f)) ? env : cdr(f))); } ```
> — [veqq on lobsters · 5 points](https://lobste.rs/s/sj5ml2/lisp_99_lines_c_how_write_one_yourself#c_zjxzre)

> It says 99 lines, and it theoretically is, but is it really 99 lines if it has 119 semicolons? In the main function,    nil = box(NIL,0); err = atom("ERR"); tru = atom("#t"); env = pair(tru,tru,nil); This should probably be 4 lines of code, but it all appears on one line in the source code. '99 lines' of code is technically true, but using number of lines as a measure of code complexity becomes less useful once you start packing multiple distinct things into one line like this.
> — [dontcontactme on hackernews · 1 comments](https://news.ycombinator.com/item?id=32104696)

> When I did something similar the hard part was implementing continuations efficiently, a feature that a lot of these small lisp interpreters lack.
> — [latenightcoding on hackernews · 1 comments](https://news.ycombinator.com/item?id=32101293)

> > #define I unsigned #define L double Gross.  I appreciate the overall idea of the article, but have some taste, and learn to touch type so you aren't tempted into such atrocities. Maybe this is how a lisp programmer writes C, but as a C programmer, this is offensively disgusting.  Jesus, at least use a typedef rather than abusing the preprocessor. Not that single-letter Fortran-esque synonyms of existing types are any sort of approximation of a good idea.
> — [smcameron on hackernews](https://news.ycombinator.com/item?id=32104850)

> It annoys me when people talk about what McCarthy did, and credit to him features that only appeared later and were borrowed from elsewhere. For example this article brings up static typing as one of Lisp's innovations.  In fact that first appeared in ALGOL-60 and didn't make its way into Lisp until 1962. And, more egregiously, the article lists closures.  In fact the first Lisp with closures was Scheme in the 1970s.  And it didn't invent them - the idea appeared in Pascal first.  (Though because it lacked true garbage collection, Pascal only allowed you to pass closures into functions, and not return them.  this greatly limited their utility.) To demonstrate how much those features are not core to Lisp, one of the most widely used Lisp applications is emacs.  But it did not get support lexical scope or closures until 2012!
> — [btilly on hackernews · 3 comments](https://news.ycombinator.com/item?id=32103762)

**Source threads**

- [lobsters](https://lobste.rs/s/sj5ml2/lisp_99_lines_c_how_write_one_yourself) · 18 points · 3 comments
- [hackernews](https://news.ycombinator.com/item?id=32100035) · 289 points · 136 comments

## Similar posts on daily.dev

- [JeffBezanson/femtolisp: a lightweight, robust, scheme-like lisp implementation](https://daily.dev/posts/jeffbezanson-femtolisp-a-lightweight-robust-scheme-like-lisp-implementation-05mm9mqj8) · Hacker News · 0 upvotes · 0 comments
- [Lisp: Common Lisp, Racket, Clojure, Emacs Lisp](https://daily.dev/posts/lisp-common-lisp-racket-clojure-emacs-lisp-jz1gvo1dc) · Lobsters · 0 upvotes · 0 comments
- [Lil' Fun Langs](https://daily.dev/posts/lil-fun-langs-0ekzoi6my) · Hacker News · 0 upvotes · 0 comments

---

Tags: [#c](https://daily.dev/tags/c), [#lisp](https://daily.dev/tags/lisp)

[View this post on daily.dev](https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Lisp in 99 Lines of C and How to Write One Yourself","url":"https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7"},"datePublished":"2026-08-05T03:39:52.049Z","dateModified":"2026-08-05T03:40:22.127Z","description":"A compact implementation of Lisp written in just 99 lines of C, covering 21 Lisp primitives, garbage collection, and a REPL. Also includes tail-call optimized...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/1536ba8f5b6d0c95c18ddd14986b7b86?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/1536ba8f5b6d0c95c18ddd14986b7b86?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Lobsters","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Lobsters","logo":"https://media.daily.dev/image/upload/s--tl8v_Fku--/f_auto,t_logo/v1698841318/logos/lobste.jpg","url":"https://daily.dev/sources/lobsters"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/lisp-in-99-lines-of-c-and-how-to-write-one-yourself-w2eemvlf7","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"c,lisp","timeRequired":"PT1M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Lobsters","item":"https://daily.dev/sources/lobsters"},{"@type":"ListItem","position":3,"name":"Lisp in 99 Lines of C and How to Write One Yourself"}]}
```

