24 minutes is a better target, i have a few repos like this... and long before the internet made it easy, it was the kind of thing i would do in my lunchtime at an office job.
it was way more instructive than following the standard path.
I'm not sure what the intended utility of "I am better than the target audience of this article" is, but I assure you it does not paint you in a positive light to other readers.
I read it more like setting a low bar in terms of time, like a pomodoro in fact. So whatever you produce in 24 minutes is that language. Then try again later.
Some of us should start the meta-project of cleaning our house by just making our bed.
> and long before the internet made it easy, it was the kind of thing i would do in my lunchtime at an office job.
This gives me vibes of "I think I'm really impressive and I want people to know it." Maybe that's uncharitable though... Talking to people online has made me too cynical haha. I appreciate the alternative perspective.
I had a lunch time project for a couple of months, where I would spend about 30 minutes a day (I had to limit myself) implementing a scheme-like in an assembly-like language called Teraterm. It was fun trying to work within the constraints of the language. I finally quit when I hit TTs built in recursion limits. I know the solution would be implementing a call stack in TT, but I couldn't bring myself to do it.
There wasn't a setjmp()/longjmp() type functionality? That's how I cheated implementing a Lisp in C. When tail recursing I'd let the stack grow a while, nuke it with longjmp(), and keep going.
That was a long time ago and I didn't know nearly as much about PL design and implementation as I do now, but it set me on the path. Funny thing was I started that project just to prove to myself that I could still write C since I'd been doing a ton of Perl.
If you discovered that trick yourself, you're very clever. It was documented by Henry Baker and is implemented in Chicken Scheme.
The basic ideas are:
1. All allocations (e.g. consing) take from the stack.
2. Tail calls are stack calls, so we keep consuming stack.
3. No function ever returns; all calls are tail calls. The Lisp code is CPS-transformed. (Since functions in the compiled code don't actually return even when appearing to, the stack-allocated objects remain nicely valid.)
4. When the stack reaches a certain limit, we rewind it. At that point, all the data which we consed on that stack which is still reachable is relocated to the heap, so they remain valid while we clobber the original stack.
it was way more instructive than following the standard path.
interesting read though :)