HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
akkartik
wart
C++2011–2023
akkartik / wart · Archived

wart

An experimental, small, readable Lisp with thorough unit tests and extensible functions/macros.

2Distinct people
30Mentions
0Explicit recommenders
145GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

An experimental, small, readable Lisp with thorough unit tests and extensible functions/macros.

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 10:01:16 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year30 dated mentions

Observed mentions: 2011-02-20 04:09:41 UTC to 2023-08-07 01:24:55 UTC.

02468102011-01-01 00:00:00 UTC to 2012-01-01 00:00:00 UTC (exclusive): 10 mentions; 0 submissions, 10 comments20112012-01-01 00:00:00 UTC to 2013-01-01 00:00:00 UTC (exclusive): 8 mentions; 0 submissions, 8 comments2013-01-01 00:00:00 UTC to 2014-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments20172018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2023

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20112011-01-01 00:00:00 UTC2012-01-01 00:00:00 UTC10010
20122012-01-01 00:00:00 UTC2013-01-01 00:00:00 UTC808
20132013-01-01 00:00:00 UTC2014-01-01 00:00:00 UTC404
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC101
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC202
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC101
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC303
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC000
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC000
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC000
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC000
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC000
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC101

What Hacker News says

8 sources
I often run git blame to track down and reread old commit logs. But yeah the new codebase kinda dilutes the point because I'm changing so many things at once. It's an exercise in making a codebase as self-documenting and approachable to outsiders as possible in a variety of ways. The numbered filenames are one example. Each file is intended to be self-contained, and later files build on earlier ones. No need to hack on makefiles to add a new file. Just create it, number it right, and it'll get compiled, with access to everything in earlier files. Since this is a lisp interpreter the ethos translates to lisp functions as well. I can improve performance by deleting a lisp function, reimplementing it in a new .cc file, and restarting the interpreter. The interpreter will transparently run make, which will transparently compile the new file.
Read the rest
And tests on the lisp function will continue to pass if I did the translation right. There's a README (http://github.com/akkartik/wart#readme) that tries to convey my goals, but I haven't had too many people read it yet. I'd love to hear what isn't clear. You aren't supposed to know lisp to understand it.
In All the Ganglia. The Nerves. On leaving a programming project unfinished.
I use tests for documentation. They seem like more work at the start, but they're more flexible. You can self-document things with tests that you cannot with just types. For example, here are some tests from the lisp interpreter I've been working on: http://github.com/akkartik/wart/blob/8a8cf96816/030.test You're right that tests aren't close to code. But that can be good or bad. Since it's not next to the code it can be more verbose and thorough without adding a constant reading burden. And when I wonder, "why is this line here?" I can comment it out and run the tests to find out. I think of tests as records of the input space of my program. Most of the time we go to great lengths to make explicit what we do but not quite what aspects of its behavior we truly care about. Where are the dont-cares in this program? If I refactor it am I res
Read the rest
tricted to a bit-for-bit identical behavior? In practice that's impossible, and without tests we fudge random parts of the state space without rigorously knowing what is important and what isn't.
In Study of 49 programmers: static type system had no effect on development time
It's easier to understand five simpler patches if 'diff' is too stupid to render the more complex patch. "Here I renamed this variable, then I moved this hunk over there, then I made the change." Even aside from the artifact of diff, I don't think this situation is analogous to short functions at all. The big difference is that commit logs are much more serial in nature. If I break one commit down to a sequence of 5 simpler commits they will almost always be read in that order, with context preserved. I'm ambivalent about long functions, but am much more draconian about complex commits: http://github.com/akkartik/wart
In The Tyranny of the Diff
> You can implement a macro system in 30 lines of Lisp. All you need is read, and it’s easy. The linked pastebin isn't a macro system. It's merely a macroexpansion system, it needs to be evaluated. And it's not as simple as merely wrapping it in 'eval' because of subtleties in getting at the right lexical scope. More generally, no fair claiming macros are easy because you managed to build them atop a lisp. You're using all the things other comments here refer to; claiming it's all 'read' is disingenuous. I'm still[1] looking for a straightforward non-lisp implementation of real macros. The clearest I've been able to come up with is an fexpr-based interpreter: http://github.com/akkartik/wart [1] From nearly 2 years ago: http://news.ycombinator.com/item?id=1468345
In Lisp: It's Not About Macros, It's About Read
I agree with your premise: "..we route around the damage and encapsulate it away inside our own APIs. ..if a system API is good enough, then we don’t need a library." ..but don't see how it leads to your conclusion: "Since APIs are guaranteed to be flawed, let’s accept that and work on encapsulation. Let’s replace authority with merit." Instead, my reaction is to be anti-abstraction and anti-backwards-compatibility. "Don't get suckered by interface guarantees; debug code." Implications: a) As a library/platform builder, I tell my users I make ZERO guarantees of backwards compatibility. I release no version numbers, only commits that they can pull if they want. If you build on my code, write tests or God help you. b) As a library user, I am extremely conservative about introducing new dependencies. When I do I pull it in once, write lots o
Read the rest
f tests for my application that will warn me if something breaks, or they change their interface. Basically I never make assumptions of backwards compatibility. But I never wrap dependencies in my own layers either. I try to never upgrade a dependency blindly without understanding what changed, and I rely on my tests to tell me when things break, and then I fix them to use the new interface. This is all a work in progress. I'm still playing with these ideas and working through their consequences. http://github.com/akkartik/wart/tree/unstable is built in this spirit. But the goal is clear: to attack the cruft that accumulates (like weeds) in the interstices around abstraction boundaries.
In Every API is Flawed

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.