No Let
- 6 Devlogs
- 28 Total hours
A JavaScript coding puzzle site where you aren't allowed to declare let variables or use anything with mutable state.
A JavaScript coding puzzle site where you aren't allowed to declare let variables or use anything with mutable state.
I wrote the README and also fixed a minor performance bug.
Because Prism code editor only initializes once Svelte finishes hydrating, there’s a delay of a few hundred milliseconds between when the page becomes visible and when the editor initializes. This caused a layout shift on each puzzle page, which was making Lighthouse take away a few points in the performance category. So I precalculated the height of each puzzle editor in advance and applied that minimum height to the placeholder text. This fixed the layout shift, so now Lighthouse gives the site perfect 100s in performance, best practices, and SEO, which is cool.
I just added some error handling for infinite loops and infinite recursion.
Before, if you wrote while (true) {} in the editor and pressed run, it would permanently lock up the UI and crash the browser tab. Now the logic test just interrupts the execution after 1000ms and fails your code for taking too long.
Likewise, if you wrote const r=()=>r();r(); and ran it, QuickJS would silently throw an uncaught error and the logic test would be stuck at “Waiting…” forever. Now it just instantly fails the code because it recurses too deeply and QuickJS can’t execute it.
I’m probably going to ship No Let soon, unless I have more puzzle ideas, find more bugs to patch, or think of more features to add.
I spent the last 3.5 hours making a single puzzle. It’s the hardest puzzle yet and took the most time to create, and by a lot.
The puzzle is called Headcount, and it involves extracting a total count from a deeply-nested data object. I considered using nested arrays instead, but that would have a pretty trivial solution: return input.flat(Infinity).length. JS has far fewer built-in utilities for manipulating objects than it does for arrays, so I figured that using objects would pose more of a challenge, which I think it does.
You can play the new puzzle here: https://ethmarks.github.io/nolet/headcount.
I added more puzzles and wrote a congrats page for users who finish the whole site.
The congrats page finally gave me the excuse to reference xkcd 1312, which I’d been dying to do since I started this project.
Next, I just need to make more puzzles. I have 4 so far, which I don’t think is nearly enough. Puzzle design is really hard though.
I’ve made a lot of progress since my last devlog. I’d say that No Let is basically feature-complete now. All that’s left to do is adding polish and creating a bunch more puzzles.
You can try No Let right now at https://ethmarks.github.io/nolet/.
Here are some of the highlights of the changes in this devlog.
Output.svelte component that runs the logic test and the linter and outputs their results into a human-readable HTML list. I also made it use Svelte’s slide transition, which required a lot of refactoring.But most of the work I did has been refactors, fixes, and creating new puzzles.
So my idea for this project is that it’s a JavaScript puzzle site which forces you to use pure functional programming, which means that you aren’t allowed to use let or anything else with mutable state.
Basically, pure functional programming says that you should never ever reassign variables after you declare them. Ever. Because you can’t reassign variables, you also can’t increment counters, which means that it’s impossible to use for loops. The same logic applies to while loops, and to a few other things. These extremely restrictive self-imposed limitations force you to do things the functional programming way, which involves lambda calculus, recursive functions, currying, etc.
I think that this project will have four main parts. I’ve been working on it for about 7 hours and I’ve made some good progress, but there’s still a lot to do.
Math.random() that are considered “impure” by functional programming because they’re non-deterministic.let. I can use acornjs to parse the code into an AST, then applying a bunch of custom rules to it.let and whatnot.Right now I have minimal versions of parts 1, 2, and 3. They do work (mostly), but they’re missing features and don’t integrate well with each other.