Scrabble Oracle

2026

Finds the best plays given a scrabble board and rack.

code demo
Gleam

Yellow Cake

2025

A novel RPN stack language with guaranteed termination

code demo
JS

Utf2

2025

utf2 spec + cli

code
Haskell

Legerdemain

2024

A witch must find her lost children in the forest.

code demo
JS HTML CSS SVG

Roman & Druid

2024

A roman and druid are friends

demo
JS HTML CSS

Sandfall

2024

Falling sand simulator

code demo
WASM WAT

Dicey Wizards

2024

Print-and-play board game. Recruit allies, collect artifacts, fight monsters!

demo
Gimp

Buggy Buggies

2023

Online multiplayer AI competition

code
Elixir Phoenix LiveView

Multi-threading JS

2023

POC javascript multi-threading promise api

code
JS Web Workers

Portcullis

2022-2023

A minimalist dataflow programming language

code
Haskell

Scrabble Oracle

2021

Webapp for calculating the best Scrabble plays

code
Haskell Elm-Lang Docker

YART

2021

Yet Another Ray Tracer

code
Haskell

Tic Tac Toe

2020

MiniMaxable typeclass that uses negamax algorithm to solve simple zero sum games

code
Haskell

mu

2018

CLI version control utility that syncs with Dropbox

code
NodeJs

Blockchain Buddies

2018

an ERC-721 inspired crypto collectibles Ethereum application

code
Solidity React Redux

Swift-Pig

2018

a quick-and-dirty static templating CLI

code
NodeJS

PauperJs

2018

A poor man's client-side templating engine

code demo
JS

Time Release Encryption Whitepaper

2018

a novel P2P approach to time release encryption

demo
Blockchain

Chat Doodle

2017

real-time collaborative doodles

code
NodeJS Express Socket.io

Causality Paradox

2017

3D 1st person puzzle game with novel time travel mechanics

code demo
Three.js Cannon.js

minimum edit distance

2017

diff strings and lists with levenshtein distance

code
JS

Waterfall Color Gradient

2016

color picker and discrete gradient generator

code demo
JS HTML CSS

Amoeba Edit

2016

a text editor in a petri dish

code demo
JS HTML CSS p5.js

Visual Thesaurus

2016

A draggable, navigable, interactive synonym web map

code demo
JS HTML CSS D3

Understanding the Mandelbrot Set

2015

a paper that describes the math behind popular iterative fractals such as the Mandelbrot Set

demo
LaTeX

$ whoami
jake.wood

$ cat about.txt
Programming appeals to my creativity better than any other medium. Being a software engineer is like being a regular engineer except the builders work at the speed of light and the materials are free.

And that thing you made is also alive.

With this Frankensteinian power I make

- apps
- tools
- games
- art

Some of this is perusable on the "code" page.

what programmers value 03/26

What Programmers Value

Imagine you’re using JavaScript in a technical interview and the interviewer asks you to implement fold. Acceptable response vary depending on the interviewer’s programming values. Let’s look at solutions that will most resonate with a few different personas:

The Pragmatist:

Values getting the job done economically

function fold(arr, alg, init) {
  return arr.reduce(alg, init)
}

Pros

  • shows knowledge of standard library
  • doesn’t reimplement available APIs
  • performant
  • correct

Cons

  • no algorithmic knowledge demonstrated
  • arguably too cute

The Mathematician:

Values academic correctness

function foldr(alg, acc, xs) {
  if (xs.length === 0) return acc
  return alg(xs.at(0), foldr(alg, acc, xs.slice(1)))
}

function foldl(alg, acc, xs) {
  if (xs.length === 0) return acc
  return foldl(alg, alg(xs.at(0), acc), xs.slice(1))
}

Pros

  • deep knowledge of folds’ definitions
  • shows familiarity with recursion

Cons

  • can stack overflow
  • copying tail on each call has performance overhead

The Optimizer:

Values performance

function fold(array, callback, init) {
  let acc = init
  for (let i = 0; i < array.length; i++) {
    acc = callback(acc, array[i])
  }
  return acc
}

Pros

  • basic knowledge of JS
  • basic knowldge of algorithms
  • performant
  • correct

Cons

  • while practically correct, not technically what a fold is

All 3 implementations have the potential to annoy 2 of the 3 interviewer personas and not because they’re not correct, but because they don’t align with what those interviewers think is important.

bike lane lang 07/25

BIKE LANE LANG

ok, so idea for interesting PL semantics.

concept: “lanes”

most programming languages are 1 laned in that they follow computation linearly. do this, then this, wait for this async to finish, do this, etc.

some programming languages have semantics for operating on 2 lanes. for instance a promise chain in JS operates in 2 lanes. you follow the then path until and error then you are shunted into the catch path. In fact, catch is a specialized railroad switch for shunting the results of lane 2 back to lane 1. what’s even worse, track shifts are necessarily written vertically b/c editors don’t handle writing different code horizontally.

anyway, here’s some syntax examples of what I’m thinking about.

So you’d write a bunch of functions (that cannot directly manage control flow) and you’d have a second syntax that describes the control flow, maybe something like:

func_a_lane1
func_b_lane1 | func_c_lane2
               func_d_lane2
func_e_lane1 |              | func_f_lane3
             | func_g_lane2

those are all functions in a pipeline which accept data from 1 lane and return data to 1 lane.

so func_a_lane1 accepts data from lane 1 and might return data to lane 3 which means it would pass result directly to func_f_lane3.

contrived example:

goodness_test(number) {
  if number == 4 return L1(number)
  if number < 0 return L2(number)
  else return L3(number)
}

this syntax is a superset of the famous Result aka Either type but is more agnostic. it might be overkill but also this isn’t really an explicit feature of any language I know so it might be unexpectedly useful.

novel multi tenancy 09/23

novel multi tenancy

contemplating novel multi-tenant auth strategy:

every table has a many-2-many table with

auth_table

  • action (CRUD)
  • table_name
  • user_id

now if you want to query all boxes you can do

SELECT * FROM boxes
INNER JOIN auth_table AS auth ON auth.table_name = 'box'
WHERE auth.action = 'READ' AND auth.user_id = ?;

this has the interesting property that anything you can query through auth_table you’re allowed to query.

One ramification of this is that you could expose your DB to direct SQL queries by any user and the results could be filtered by appropriate auth_tables. User queries would be dynamically modified to include the auth join. If you wanted to get really wild you could do row-level security by adding a column_id field to the auth_table. You would need to think about DOS mitigation etc but still an interesting idea IMHO.

how zig self hosts 01/23

How Zig Self Hosts

Initially I only had a fuzzy appreciation for Zig’s self-hosting problem/solution. After listening to the Software Unscripted podcast where they chatted with one of the Zig core team I feel like I have a better understanding of what’s going on which I will attempt to summarize here.

Zig is self hosted which means that if you have the latest zig compiler already you can compile any zig program (including the source code for zig compiler). If you don’t have the latest Zig compiler floating around you need a bootstrap compiler – i.e. a compiler not written in Zig that can compile the latest Zig compiler source code. The basic flow for adding features to Zig is as follows: Dev adds some new language feature X and compiles Zig with compiler U to produce compiler V. Zig compiler implementation is updated to use feature X via compiler V and compiled to produce compiler W. note: Compilers V and W are indistinguishable in which programs they can compile. compilers V and W can compile programs that U cannot. If someone else goes through these steps instead of you, then they have a copy of compiler V instead of you. If, after every step for every feature, the Zig team published a linux compatible version of Zig then anyone could stay up to date on Zig development. However, the Zig team doesn’t want to force people to use linux to bootstrap their Zig compiler (b/c developer experience is very important to Zig). This is the Zig self-hosting problem.

Well OK, why don’t they publish Zig on every OS after each step? The Zig team also doesn’t want to do that b/c it would take up a huge amount of storage (and $). Their solution is to basically do option 1, but instead of publishing an executable that runs on linux they publish a version of the Zig compiler that’s been transpiled to webassembly – the insight here is that every OS can run webassembly. The net result is that on a brand new machine, if you want the bleeding edge version of Zig (not an official release), you can download the webassembly bootstrap compiler (which is presumably updated frequently), download the Zig source code from github, compile that code with the webassembly compiler, and now you have the latest version of Zig without too much hassle.

(feel free to fact check me on anything)