Joshua Tree NP <3
HN user
eliben
http://eli.thegreenplace.net
You're welcome :)
The harnesses are documented here: https://github.com/eliben/watgo/tree/main/tests
Note that I had to switch the harness from wazero to Node (unfortunately!) when it turned out wazero doesn't support gc and other new proposals (e.g. your comment here https://github.com/wazero/wazero/issues/2483)
Thank you very much for maintaining wazero - I love that project, and am looking forward to being able to use it for this in the future.
watgo (https://github.com/eliben/watgo) -- a WebAssembly toolkit for Go. Think something like wasm-tools or wabt, just in pure (0 dependency) Go.
According to the official tracker (https://www.energy.ca.gov/data-reports/clean-energy-serving-... and elsewhere) there were 279 days in 2025 where California was on 100% renewable for _some_ time during the day (could be hours, could be minutes at mid-day).
In total hours equivalent of 77.3 full days over 2025.
California is a great example; highest electricity prices in the US (not counting Hawaii, which makes sense) despite significant hydro and fantastic solar capacity. In the last few years California runs 100% renewable on many days (and growing) every year.
Economics 101: prices are not set by what goods cost to create + markup. Prices are set by how much people are willing to pay.
Thank you for the feedback. The idea was to first define what we want the basis functions to be (a pretty abstract definition) and then develop how to actually get that from _normal_, continuous functions.
Fixed, thank you! (it's actually r(x)=p(x)-q(x))
(proof-reading through HN is a mildly embarrassing process, sorry about that! I do go over these posts and proof-read them several times myself before publishing)
Thanks for noticing, I'll fix it shortly
Right, standalone binaries for CLI tools is great. And if one has Go installed, they can just `go run ...` any tool from its GitHub path, all installation/build/caching happens automagically (meaning the execution is immediate after the first run).
But I can definitely see how someone with `uv` muscle memory wants everything in the same command.
`uv` is the best thing that happened to the Python ecosystem since... I don't know... maybe Numpy.
Very interesting! I encountered the problems these tools are trying to tackle just recently while trying to guide an agent into creating an in-browser tool for me. Closing the loop on a web interface isn't as simple as CLI-only tools. I should give this a try.
It's also interesting that you've shifted to Go for your agent-coded CLI tools, Simon.
The underlying issue here is that the Nobel Peace Prize is a useless, politicized joke. It appears to be almost designed to give newspapers something to write about.
It's a shame it gets tied with scientific prizes which represent actual merit.
Nice, I'm proud I managed to nerd-snipe you :-) Thanks for taking the time.
Seriously, though, I think this solves a nicely framed simpler problem. I was thinking about a more general tool, but that's genuinely hard (you'll need heavy CV algorithms or a special ML model to detect what is background what what isn't).
To be honest, what you built here is probably sufficient anyway, because the models are better at obeying "create a white background" or "create a 0xffffff background" than "transparent", so this tool can post-process to what's needed.
When asked for "transparent", I've had a model generate a fake checkerboard pattern of gray colors to imitate how viewers render transparent areas :-) For this kind of nonsense, the transparent-png tool wouldn't do!
Great work, Simon -- thanks for sharing!
One tool I'd really like to see in this format is a simple "turn the background of this PNG to transparent". Models still refuse to follow the instruction to create transparent backgrounds for logos they create, and I often have to look for other tools doing this as post-processing.
It's possible that this is too complicated for the "few hundred lines of js" code envelope, though.
I also enjoyed working with BF for toy compiler projects; here's a series of JIT compilers for BF in increasing level of sophistication: https://eli.thegreenplace.net/2017/adventures-in-jit-compila...
Thanks for spotting this, what a silly typo :)
... Fixed
Thanks for the kind words!
Regarding ring size, yes I'd say 2^64 is good. Since the representation is sparse, it seems safe but I'd be interested in hearing other views.
Thanks for posting this!
Just a quick note that this post is the first in a series: see https://eli.thegreenplace.net/tag/multiple-dispatch for the full series
The Y combinator in Python: https://eli.thegreenplace.net/2016/some-notes-on-the-y-combi...
(scroll down, after the concept is explained using Clojure)
A bit crazier, in Go with generics: https://eli.thegreenplace.net/2022/the-y-combinator-in-go-wi...
A quick plug for https://www.goatcounter.com/ - a super lightweight visitor counter. Very much privacy oriented (https://www.goatcounter.com/help/gdpr).
I've set it up on my blog a while ago (https://eli.thegreenplace.net/2023/using-goatcounter-for-blo...) and it's been working really well.
Yes, Factor is mentioned in the first paragraph of the post!
Thanks for the feedback! What do you feel is not finished?
Thanks for the note. Much of the blog post is dealing with this - how the approach I took for the Go implementation is not sufficient for the hacker level - because the code isn't stored anywhere but remains as text. This isn't a Go issue, it's a result of the specific design decision of how to implement it.
The second implementation - in C - does it the "right way", with both code and data living in the same memory, and thus allows all the usual Forth shenanigans. Again, this has all to do with the design approach and not the implementation language. Nothing precludes one from writing such an implementation in Go :-)
Indeed, generating functions are mentioned in a footnote :) Very interesting topic
Plain text in git. Eternal, searchable, compact.
Updated the result to 80ns - thanks for flagging this. This grows with the size of the data (because more cache misses), and running the benchmark on the full billion takes a while.
[That said, on a hot production bloom filter, much can be loaded into caches anyway so it's not an entirely un-realistic scenario that some of these are cache hits]
This is very impressive, amazing work!
One question: how do you manage large code bases in scratch? Is it easy to find a piece of code? Something like grepping for specific things seems difficult.
I've recently been really warming up to Scratch since one of my kids picked it up and really enjoys it. I love the built-in concurrency model - it's a bit like CSP. Gets kids to think concurrently from day 1.
It is authoritatively debunked in Sid Meier's (excellent) memoir - there was no such integer underflow bug in Civ I, it was all a rumor that went viral. The franchise did embrace the meme, though.
Sorry, the intention was just to show a cool use of complex numbers, not claim this is the simplest method to generate 12 which is pretty simple, as you demonstrate.
Really? But why? All of 2+2, 2*2 2^2 are trivially 4, and sqrt(4)=2 so why is the + more odd than others?
JIT is something different people sometimes define in different ways.
In this sample, when the function itself is called (not when it's decorated), analysis runs followed by LLVM codegen and execution. The examples in the blog post are minimal, but can be trivially extended to cache the JIT step when needed, specialize on runtime argument types or values, etc.
If this isn't JIT, I'm curious to hear what you consider to be JIT?