As soon as I met Forth, I felt I had to hack my own (https://github.com/ttsiodras/MiniForth/) - and did so over a single week, two years ago. I targeted the Blue Pill and the original Arduino, but developed via cross-compilers so that I could test my code in the host.
I became so obsessed with the project that I was looking forward to tinkering with it after coming back from work every day; so it was hacked in 5 evenings and a weekend.
It was that much fun, to build a Forth.
> I became so obsessed with the project that I was looking forward to tinkering with it after coming back from work every day; so it was hacked in 5 evenings and a weekend. It was that much fun, to build a Forth.
Yep. In my computer architecture class as a freshman, we were supposed to do a final project of our choosing for the LC-3 (a RISC instruction set with emulator). I had dabbled briefly in Forth (with the RedPower 2 Minecraft mod) and thought it'd be fun to implement one. It ate up essentially all of my free time that semester: There was one morning where I only realized I'd stayed up all night when the sun started to come up and I finally checked the clock.
I've never found a practical use for Forth in my "real" life, but building one from scratch was an experience almost best described in religious terms. It was a pure distillation of Fred Brooks's description of programming:
> The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures.
> Yet the program construct, unlike the poet's words, is real in the sense that in moves and works, producing visible outputs seperate from the construct itself. It prints results, draws pictures, produces sounds, moves arms. The magic of myth and legend has come true in our time. One types the correct incantation on the keyboard, and a display screen comes to life, showing things that never were nor could be.
Fully agree. About 40,000 eons ago I wrote a Forth compiler in ZX81 basic. It went from taking 19 seconds to print 1000 numbers on the screen to instantly. I also learned a great lesson: I looked at the machine code it generated (it had a pinhole optimizer because the output was PUSH HL, PUSH DE, POP DE, POP HL everywhere), and I thought it was perfection - impossible to improve. The day later I came back and made it much faster.
If you wonder: How does it write itself? Isn’t it just the ability to write functions?
In a way, yes, but it's a bit more than that. Many programming languages allow you to define functions or methods, but Forth takes this concept further by allowing you to define new "words" that can become part of the language itself. These words can be used just like built-in operations, and they can even change the way the language behaves.
Also, because Forth is an extensible language, you can create words that define new control structures or modify the language's syntax. This is a level of flexibility that's not commonly found in other languages. In this sense, Forth can be seen as a language that "writes itself" because it allows programmers to customize and extend the language in a very fundamental way.
The ability to extend Forth by defining new words is somewhat similar to the macro system in Lisp. Both provide a way to extend the language and customize it to suit your needs.
In Lisp, macros allow you to define new syntactic constructs in the language. They work by transforming your program at compile-time, essentially letting you create your own domain-specific language within Lisp. This is a powerful feature that makes Lisp highly flexible and adaptable.
Similarly, in Forth, you can define new words that become part of the language and can be used just like built-in words. This allows you to extend the language's syntax and functionality, making Forth highly extensible and customizable.
Neat, I suppose, but... In nearly 40 years as a professional programmer, the problem has never been the syntax. It's always the semantics. (I mean, yes, if you're doing something like matrix multiplication it's nicer to be able to say A = B + C * D; rather than having to explicitly spell out which functions you're calling. I have never actually hit that situation, though.)
Do I just lack imagination?
Is this domain-specific, and I've just never been in the domain where it was useful?
Is Forth so crippled in syntax that you need to be able to extend it to make it something more useful?
Do people just want to be able to customize their language, the way some people do their cars?
A lot of the focus on simplicity is about ease of implementation. A compiler/interpreter for a language without syntax (Forth) is much faster/easier/simpler to write than one with syntax. Originally Forth was an OS as much as a programming language, and the strength of the concatenative paradigm for command languages can be seen in the enduring popularity of pipes in *nix shell. The syntax is not considered a problem because it will be invented as you go along and write the words that implement your application.
Because most semantics manifest through syntax. Syntax is how the programmer communicates their intent and gets access to the semantics of the underlying system.
A contrived case is the construction and use of lists built of CONS cells in lisp style languages. You can certainly do this in most any language, but creating CONS cells readily without something like an S-expression would be tedious and awkward indeed, to the point that folks would drift to something else more naturally represented in their language than something based on CONS cells.
What makes computer languages odd is in having syntax persistently be "born" in tandem with a desire for a certain semantics, and the two being hard to separate upon close inspection. You have to know the domain and have the experience to see when and where it occurs, but a need for additional syntax always appears beyond a certain point.
The reason why this is the case is because the computer's ultimate use lies in automation of some task: to automate you have to define the problem domain, and to define the problem domain you have to configure something, and as you expand the amount of configuration taking place from a single-use app like your usual batch-processing shell script towards a more bespoken front-end for a certain kind of task, you end up with valid and invalid ways of configuration. If you define an input mechanism that automates a configuration with "good defaults and helpful rules", you haven't concretely changed the underlying semantics - and this sort of thing is in the realm of what a linter does - but you have changed the syntax by which the problem is approached, and pushed the train of thought onto a certain rail.
And most of the time we ultimately aim to shove that concern into a graphical front-end, a form of syntax that is easy to browse through and discover your configuration options with, and enables some unique semantics with data visualization and inputs. But it's a layered process with multiple entry points - sometimes you change a configuration not by clicking around, but by editing a text file, and sometimes you change it by writing a different program. You also rely on having an operating system, files, sockets, etc. The concepts are made within an ecosystem of software and dependencies are assumed. And this is a predictable outcome of Algol.
In Algol-derived languages you have one, general-purpose syntax(and maybe an extra one, like the C preprocessor), and it does a bunch of things that are hard to enforce just with programmer discipline, so it gives you your structured loops and function calls and class methods and such. And you get access to libraries and those all expose the same kind of syntax with new vocabulary.
But then when you have to extend an Algol, you often end up in a place where you have enough configuration taking place to want it to be parsed in some degree. Maybe you decide you will generate code during the build process, or you have a little interpreter that enforces business rules, or something of that sort. You access it by calling a function, but that doesn't describe how you talk to it. You've started using a different protocol, all of the sudden, and your language tools correspondingly change. The boundaries are pretty hard.
And the way in which both Lisps and Forths differ from the Algol approach is in making it really easy to grab the metaprogramming you want, when you need it, so if you need a little compiler for a thing, the barrier to it is a modest "set a toggle so the logic occurs when compiling this other function, instead of at runtime". This is a thing that newer Algol-likes have chipped away at, but in general the priority is "common things are easy, hard things are possible", vs "you have the expressive power to design ideal solutions".
Forth's approach is more low-level than Lisp in that what it gives you to start with is almost nothing except the raw tools to define that syntax in a dictionary, enter the compilation mode, access memory and manipulate some bits. No safety or anything - you build that yourself when and where you want it. It's a useful "bring-up" language for new hardware because it's very permissive in that sense: you have a REPL available from the get-go and it can let you start banging bits. But it lacks the kind of standardization and collaboration that would result in an ecosystem like a C or Java, and that's also by definition: Forth has the expressive power to monopolize the entire path between the final application and the hardware, and if you aim to make it exist in a standardized context like a "web app" or a "Windows app", it suddenly does little of interest - that means you are defining the problem in web terms or Windows terms, and not as a mapping of hardware to solution.
It's a very isolated way of working on software, and a "software company" is nearly allergic to it, since the human factors dictate that the software should be collaborative and often hegemonic.
One of the most interesting Forth projects to me currently is Dusk OS, a 32-bit operating system written in Forth that includes its own C compiler, with various porting efforts under way
I cannot speak to DuskOS, I don’t know anything about it.
While historically Forth has been “its own OS”, it’s a kind of crummy one. Especially for anything a modern reader might think of when they think of an OS.
I mean, for sure, what do you want from something that can run in 8K of RAM. But while it offers primitives, historically it doesn’t of any concept of things like drivers or most any other abstractions. Code is loaded from source code (which is slow). Linking is just loading blocks in the right order. Loading a new program you must first remove the current one.
Arguably not much better than CP/M, which routinely cold started the machine to exit a program, but at least it separated the BIOS from the BDOS.
I missed this one. Thanks for the link. I was just reading "Beyond the Collapse" and my Lisp and APL/J and C skills would not allow me to approach Forth's simplicity at the OS level. I'll definitely check this out by next weekend.
My first programming languages were x86 assembly and Forth. My Dad was into Forth, and I learned programming from him. I wrote several x86 Forth systems for DOS as a teenager, culminating in a somewhat-polished ANS compatible one I called "Third": https://github.com/benhoyt/third -- it's kind of amazing being able to have a fully bootstrapped Forth compiler (including an assembler) in a couple thousand lines of code.
Just the other day I transcribed an old article I had co-written for the Forth Dimensions magazine. I still like the ideas in Forth, but the stack manipulation quickly gets tedious and is very hard to read. Just look at the code examples in https://benhoyt.com/writings/forth-lookup-tables/ -- especially Search-Table. Yikes! Yes, naming things is hard, but apparently not naming them is even harder.
I'm pretty sure I wrote the first version of kernel.com in assembler.
Update: actually, more likely it was built using the meta compiler running on top of one of my previous Forths (I wrote a few). It's been too long to remember exact details, and I didn't use revision control back then. :-)
"GreenArrays is shipping its 144-core asynchronous chip that needs little energy (7 pJ/inst). Idle cores use no power (100 nW). Active ones (4 mW) run fast (666 Mips), then wait for communication (idle)."
"I always considered that size and speed were important for amateurs. But in the modern context, there's only three parameters that matter: power, power, and power."
To me GA144 looks less like a state-of-the-art CPU or DSP replacement and more like an FPGA replacement—and that would actually be lovely to see, given how inefficient and expensive FPGAs are nowadays compared to doing the same thing with a custom chip (if you only overlook the design cost for the latter). The “computer” marketing makes little sense to me.
Unfortunately, GA don’t seem to have gotten the memo about cheap entry-level dev tools that the microcontroller world has been circulating since 2010 or so. At the prices they charge for their devboards, you wouldn’t really get one just to play with, even if the chips themselves are actually somewhat cheap compared to getting the same amount of compute on an FPGA.
(It’s $500 per devboard and $20 per chip, with each chip capable of 2e9 16-bit multiplies/sec. Somebody[1] is selling a breakout board with only the chip for a much more reasonable price of $35, but you’ll need to figure out how to wire up the thing yourself.)
Charles Moore is known for aggressively patenting his hardware, though. (Well, he and every other modern chip designer.) So we might not get to see anybody else do this stuff for a long, long time. Adapteva’s Epiphany/Parallella design used a broadly similar idea with an explicit grid interconnect and also aimed for a piece of the FPGA/ASIC pie, but they had much beefier, synchronous cores with separate message routers attached to them.
https://thinking-forth.sourceforge.net/ <- A better source. The one you linked includes a number of typographical errors early on (OCR errors?) that were grating for me to try and read. None of the errors I noticed in your link were present in the copies I checked out here.
Long ago, when OS/2 came out, a friend relayed to me that "You can't write programs in assembler for OS/2, they have to be written in C".
In defiance of that statement, I built Forth/2.[1] It was a direct threaded, native code Forth Compiler for OS/2 written in assembler. Brian Matthewson wrote an amazing manual for it, and it found a few dozen users.
Tangent: I remember reading this in its original presentation-prototype form, which is basically this article with much less text and more plotholes. The reason I'm mentioning it is because it's also a beauty of minimalism in terms of underlying website technology.
It's interesting to note that even in Rust, there exists a Forth compiler, as depicted in these resources [1]. Its usage remains somewhat unclear to me [2], but its existence has been previously discussed here [3]. It boasts a robust implementation and, while it isn't a REPL Forth VM, it stands as an impressive VM implementation.
I've been contemplating - given that FORTH is a VM - if there's a need for a compact and efficient system capable of managing streaming data, it could be the optimal choice for exceptional performance, close to the bare metal. There's no need to contend with the operating system. Isn't this essentially what FPGA’s do, but on standard CPUs? I envision it as a specialized system, minus the requirement to create every driver for all the hardware you'd need to interface with.
The main difference is that in this Forth variant, the source text is completely translated into bytecode and there is no runtime in the sense of classic Forth. This makes it easy to translate the bytecode to C.
I use my own Forth to generate C code with it, which I then embed in other software.
That can be very productive and clever, but be - and stay - aware that such polyglot solutions tend to be maintenance headaches in the longer run.
There is a really nice open source project out there that allows you to train your hearing and your sightreading, but it's written in the authors own language which in turn compiles to JavaScript and the headache to set up their toolchain is such that I haven't bothered fixing any of the bugs that I'm aware of (and there are plenty).
It's a little strange to talk about moonscript as something obscure, luarocks the main package manager for lua is written in it, not to mention itch.io. It's a proven language that's at least easier to learn than lua. (well, its at least more programmer friendly)
Ah, what beautiful paradigms there are which we toil away without. Retro (a modern Forth) looks very interesting. The textbook Thinking Forth is near SICP in terms of opening your mind to a new paradigm.
Is anyone using Forth in production these days with stories to tell?
I only wrote some file munging and reporting programs in Factor, a batteries-included Forth. Nobody would need these tools, so I was free to make and use for myself. They had people scraping HTML and Excel reports to do their reporting before. I exported my results to HTML and Excel. Sneaky fun for myself!
Stack code can be mapped to register code trivially if you impose some restrictions (each word has a static effect and both branches of a conditional have the same effect). Then lowering to SSA form performs an “abstract interpretation” where evaluating a word pops SSA values from a “abstract stack”, creates an SSA node and pushes its output values on the stack.
... ok, fair enough: it probably is trivial for you, lol.
(For the uninitiated: Slava Pestov created Factor, a modern concatenatvie language which (IIRC) did a lot of innovative stuff regarding optimizations in that domain)
Whenever I work on compiling Joy code I have to fight the urge to just write Joy-in-Factor and lean on all that crunchy goodness.
(I wrote Joypy (mentioned in TFA), now Thun (someone took Joypy on PyPI so I renamed it) which includes interpreters in C, Nim, OCaml, and Prolog. I made a few feints at compiling Joy so far, but it's just kid's play compared to Factor. "I am but an egg.")
There's a bunch a vendors still alive, mainly the historic Forth, Inc. and MPE. Both publish complete systems and native compilers that apparently perform well enough.
If raw execution speed was all that matters, I can name a bunch of popular programming languages that wouldn't have survived long enough to be saved by JIT, or to become to big to fail (that is, their ecosystem).
FORTH is still used to bring up new silicon because of its tiny core, you only need a couple of working assembly instructions to bootstrap yourself into a working system, you could do this entirely in cache or a small static RAM if you don't have a working memory controller yet.
You won't see a lot of hype around it and repos tend to be old because they 'just work', typically a user of such a system would download it and customize it to the point that sharing it would be pointless, the whole idea is to extend the language to become the application.
You are probably using it yourself, right now. You just don't realize it because embedded stuff isn't sexy, won't make it to the blogosphere and just sits there doing it's job, year after year. Every vehicle, every boot of a larger machine probably uses FORTH at some stage.
Not everything is web based and not everybody is part of the hype cycle.
Since you're asking 'anyone' one example should be enough to satisfy you with proof: every IBM Power series system has Open Firmware on it which you can boot into: https://www.ibm.com/docs/en/power9/0009-ESS?topic=asmi-power... . Note that that doesn't even mention Forth by name.
Also note that the world is a lot larger than just the English speaking part of it, and that bringing up new systems is usually transitory: as soon as you can bootstrap yourself out of a FORTH environment you do so because it is a bit limiting.
My impression so far is Forth development usually "limited" around hardware/embedded development. And for whatever reasons, seems like there are no much effort (?) to bring Forth to greater audiences (like us web/mobile dev apps, for example :D ).
Yes I know some folks are trying to change this, e.g:
I learned Forth when it was the only language that had an interpreter than ran on PalmOS. So you could write and execute it on your PalmPilot while you were bored in class in the 90s.
Forth was created to control the aiming of a radio telescope. It was used in the original Star Wars movie to direct the complex motions of the model space ships.
I got the gist of it though, and I think you do have a point: FORTH showed the power of stack machines (and the HP calculators of course did too) in a way that not much else did and I'm pretty sure that the ease with which you can bring one up to bootstrap a new environment is part of the reason why they were (and still are) more popular than many people realize for embedded stuff and first silicon of new and experimental CPUs. You can bootstrap to an interactive system in an afternoon in FORTH and some of the JVM instructions are definitely reminiscent of FORTH.
So it isn't all that farfetched to see the link between the Bitcoin embedded scripting language and the FORTH language, especially the stack section of the opcodes. I'd say they're of the same family, not necessarily a subset, and the lack of Turing completeness is of course a purposefully limiting factor.
Stackmachines are fascinating, incredibly simple and yet quite powerful. There are a couple of such concepts in computing (NAND gates on the hardware side, the Lambda function on the software side and FORTH as well as for/if/jsr/load/store, and even brainfuck (and ook!)) which all allow you to build just about anything. Each of them warrants study.
The Apple II computers, for example, had only upper-case characters in ROM (and screens were 40 characters wide). Lower -case characters would have required a second ROM, which obviously increased costs. Eventually models with lower-case capabilities were added, as was 80-column output.
Not nearly enough cycles for that. Nor core memory. Nor even the possibility of colours or font styles. You were lucky if you got a timeslot for your program and didn't get preempted. You were even luckier if you got both uppercase and lowercase letters. (-:
Forth was influential, but it is somewhere between obsolete and niche. It is much more difficult to program in than even raw C, let alone C++ and offers no advantage in speed on modern hardware where memory access is the by far the highest priority.
Forth on a modern CPU is still going to be much faster than C on a Forth processor. It isn't even true that modern processors are "optimized for C code", they have stack instructions that are very fast and directly apply to forth.
DonHopkins 8 months ago | parent | context | favorite | on: Forth vs Lisp
Coco Conn and Paul Rother wrote this up about what they did with FORTH at HOMER & Assoc, who made some really classic music videos including Atomic Dog, and hired Charles Moore himself! Here's what Coco Conn posted about it, and some discussion and links about it that I'm including with her permission:
>First shown at the 1989 Siggraph Electronic Theater to a rave response, this 3 minute humourous film went on to win several top computer graphic awards that same year including Niccograph of Japan.
>Coco: This was a show favorite at the SIGGRAPH film show that year. The year before the conference committee decided that showing demos wasn't the way to go anymore. Peter wrote Flying Logos as a way to sneak our demo reel into the show by turning it into a story. It worked and we made it into the film show.
>Don: I truly believe that in some other alternate dimension, there is a Flying Logo Heaven where the souls of dead flying logos go, where they dramatically promenade and swoop and spin around each other in pomp and pageantry to bombastic theme music. It would make a great screen saver, at least! Somewhere the Sun Logo and the SGI Logo are still dancing together.
----
Peter Conn and I [Coco Conn] had a company called HOMER & Assoc. which was located at the Sunset Gower Studios from 1977 until we closed shop in 1997. We made music videos, commercials & computer graphics/special effects for feature films. One cool note, we worked with Paul Verhoven on both RoboCop in 1986 and the x-ray scene for Total Recall in '89.
HOMER was actually a real time visual mixing console that our in-house engineer spent 1978 - 1981 designing and building, from scratch. The name HOMER stood for "Hybrid Optical Montage Electronically Reproduced." I helped as well, soldering the LEDs on the console and running cables. Peter built his own optical printer and three years into the build we also bought an early computer paint system. Our engineer finished building the console and promptly decided to move to England. We hadn’t used it because we still hadn’t found the right software to run the system. Luckily that’s when Paul Rother joined the company.
The joy stick on our console would bump you to the next line of code (being a command or sequence of events: fade, cut, dissolve, etc.) The console had touch sensitive fader pads. There were no dials. I think they were made by Allison? Each channel (which controlled either a slide projector or a film projector) was touch sensitive. After recording a sequence we could then tweek the current version using additional effects the channels offered such as momentary, additive, on/off, etc. For instance if you wanted to crossfade two images, you could either program it or perform it. Of course everything you did was recorded and would play back on the next round. You literally performed a sequence of visual effects with your hands. Peter would do countless passes until everything was perfect. This performance would then be played back to IP film on the optical printer. Each slide tray or film real would be individually run, one by one, to IP film. Sometimes there would be 10-15 or more passes to get all the elements transferred. Once that was done we would then convert the IP film to video and do additional video editing and effects. A totally nuts analogue system. But it worked.
---------------
HOMER Explained by Paul Rother, in-house programmer, (1982):
The photo is Paul sitting in front of the Optical Printer 7-bit Paint system, Homer and Associates, circa 1982. Homer and Associates was really one of a kind kinda of company. Founded by Peter Conn, originally I got hired to program Homer II, a visual realtime mixing console. Homer I is another whole story, but before my time. Homer II consisted of 16 slide projectors, 4 movie projectors, a 4 track tape recorder, 24 visual channels (each with its own Z80) touch sensitive sliders, a master Z80 S100 bus system and featuring "the joy stick bumper " control, which looked liked the gear shift right out of a 1964 mustang convertible.
The idea was that you would program a visual sequence, then play the sequence in sync with the sound track on the joystick, including cascades, bumps, cuts, etc. The whole thing would be recorded, and if you wanted to, like an audio mixer, go back and do over dubs, making corrections. Then once you had the perfect "hero" recording, you take the 8" floppy disc with the hero recording and the trays of slides to the optical printer, and record it to IP motion picture film, making multiple passes, one tray at a time. Now that I think about it, it was a crazy idea. We actually got the whole thing to work. And it worked great!
Forth & Charles Moore
We hired Forth, Inc. and got Charles Moore, the inventor of FORTH to program the console host computer. I learned FORTH and worked with Charles. I programmed the 2K byte EPROM in each visual channel. On the Master Z80 system we ran PolyForth a multi tasking system in 32K bytes. We had an extra 16K RAM for buffers and things. If I remember right, the system ran four tasks, but that was 20 years ago, my memory may be hazy.
Anyway, I learn not only FORTH from Charles Moore, but also how to factor code in to small reusable routines, WORDs they're called in FORTH. I learned Object Oriented Programming without knowing it. Also a lot of use of vectors. Its a cool language. Charles Moore was a great inspiration to me, and really taught me a great deal that they never taught me in computer programming school.
CAT-700
After we got the basic Homer II working and were able to record on the optical printer, Peter had another idea. He wanted to be able to see the movement of the optical printer, and see a prior frame compared to the current frame. We already had a video assist on the Fries Mitchell 35mm. What we needed was a Frame Buffer. We heard of S100 video board called the CAT-100, which was 1-bit frame buffer, good enough for what we needed. Somehow we never found a 1-bit version, but we found 7-bit version in the recycler!
We flew to Reno, rented a car and drove to a log cabin up in the hills of Truckie California. We got a demo of the thing. The guys were super secret and didn't want us to see the controlling program. It worked, so we bought it, and then flew onto Palo-Alto and met the French guy who designed it. They checked it out and it was OK. This was the days before computer designed boards, and all the traces on the board were curvy, kinda like a Van Gogh painting. We learned that it was 7-bit (CAT-700) because it would have been an 8-bit, but they could not get the 8th bit to work. We spent the night in Palo Alto with a Stanford friend of Peters working on a crazy secret Apple project, the Lisa. 32KByte Paint System
So I got the CAT-700 frame buffer to work, programmed in FORTH. So in that 32K we had an optical printer control system, and a paint system, all in one. (Also the OS, compiler, debugger, etc.) We later hooked up a Summigraphic Bitpad (before the Watcom tablet) and were able to draw on top of digitized frames. It got to the point where we needed TWO optical printers, one to digitize from film, and the other to record to film. Rube Goldberg is not strong enough descriptive to describe the system, with the filter wheels and all on stepper motors, it made music. The first use of the system was effects for Steve Miller Music Video, Abracadabra. I also remember using it on the George Clinton Video, Atomic Dog.
This photo was taken right after we got the system to work. I had hooked up an analog slider box, which controlled things like color. There were 4 color maps we could switch between instantly We did a lot of work in planes, using 2 planes for the original image to be rotoscoped, and the other 5 planes to draw onto. This photo was taken for an article in Millimeter Magazine. The photo ended up being a two page color spread, and I think Peter was pissed, cause I got premier exposure.
TTL logic
At Homer and Assoc. I also learned TTL logic and designed a number of computer boards for the S100 bus. One that controlled stepper motors with a timer chip (Motorola 6840). Another to control the Slide Projectors also using the same Motorola timer chip to control the lamp triacs. My favorite thing, about the system, was the use of the cassette storage interface as a cheap timecode reader/writer.
I became so obsessed with the project that I was looking forward to tinkering with it after coming back from work every day; so it was hacked in 5 evenings and a weekend. It was that much fun, to build a Forth.
I highly recommend the process; I think the only other time I felt so enlightened was when I first met Lisp macros (https://www.thanassis.space/score4.html#lisp).