Bob Nystrom, a Google engineer and author of Crafting Interpreters, writes about programming languages, parsers, and game programming.
Commenters love his writing, calling out "What Color Is Your Function?" and the code formatter post, and note his compiler and interpreter expertise.
> I don't think good content necessarily needs to be paid for. Much of the best content on the web is created as a hobby, with no attempt to monetize, like dr-iguana.com (and countless others.)
I felt that way for a long time. I am basically living that philosophy. My blog[1] has always been free to read and free from ads. I wrote a book[2], and you can read the entire thing online for free, again with no ads. Almost all the code I write is open source.
I imagined a utopia where all kinds of creative people would have enough free time to pursue their hobbies and share the fruits of their labor. I am lucky enough to basically live that utopia now—I happen to love programming, which is a very lucrative field.
It's fine to dream of a world where my personal utopia is more widely available, but that world isn't here today. You can think of a culture or society as the aggregate sum of all of its shared creative works.
When creative works can only be done by those who can afford the leisure, it skews society towards the perspective of the rich. Think back to 19th century English literature and how few novels there are that show how regular working-class people lived. That's because regular working-class people back then were too busy working in the mines to write a book.
There are some counterexamples, sure, but even most of those were created by rich people observing the poor from a distance. As sympathetic as Dickens was towards the poor, the stories he tells are still…
1) zig's io is not a viral effect type, you can in principle declare a global io variable and use it everywhere that any library calls for it. Not best practice for a library writer, but if you're building an app, do what you want.
2) There are two things here, there is function coloring and the function coloring problem. The function coloring problem is five things:
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
1. Every function has a color.
2. The way you call a function depends on its color.
3. You can only call a red function from within another red function.
4. Red functions are more painful to call.
5. Some core library functions are red.
You'll have some convincing to do that zig's plan satisfies 4. It's almost certain that it won't satisfy 5.
It's open to debate if zig's plan will work at all, of course.
Is the goal to make good ORM queries easier or to prevent bad queries? It's not clear there's really a compiler solution to the latter. If you're inside a loop in which a database cursor is in scope, then further database queries are prohibited? It's hard to see how that could be enforced other than something like What Color Is Your Function (https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/) with some functions marked as making queries and others as not.
To solve this, maybe instead best practice would be to ensure the database connection is not in a global variable and must be passed down. That would make it more obvious when a database is improperly used within a loop.
The same problem exists for any expensive operation within a loop (say, a database query while parsing the results of an API call, or vice versa).
Bob Nystrom makes this argument best, I think, in his two-parter on loops and iteration[1,2]. Looping over data structures is of course only one example of how one can apply coroutines, but a very established one. The canonical problem requiring coroutines[3] is also essentially about doing that.
Or for those who want something different there’s the elevator (and elevator-userbase) simulation from TAoCP volume 1, also an essentially concurrent problem with little to no parallelism or I/O to it.
[1] https://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/
[2] https://journal.stuffwithstuff.com/2013/02/24/iteration-inside-and-out-part-2/
[3] https://wiki.c2.com/?SameFringeProblem
For context, this is the author of https://craftinginterpreters.com/ , and https://gameprogrammingpatterns.com/ , and https://journal.stuffwithstuff.com/2015/09/08/the-hardest-program-ive-ever-written/ .
I promise that he knows a thing or two about compilers and performance!
For what it's worth, I agree with him. A recent example is the porting of the TypeScript compiler to Go: it hasn't been fully released yet, but people are already going wild for its performance improvement over the original in-TS compiler.
Of course, it took them over a decade to reach the point where a port was necessary - so it's up to you to decide when that decision makes sense for your language.
I still think this is one area Rust missed the mark. Go concurrency is quite amazing. Its fast and easy to reason about. Every language can learn something by how goroutines work here. Most importantly, it feels like you're just interacting with synchronous code. There is no "what color is your function?"[0] problem.
The fundamental primitives Rust decided to adopt are just not ergonomic by comparison, and suffers from the aforementioned "What Color Is Your Function?" problem.
An otherwise great language decided to adopt an old hand grenade in regards to async primitives
[0]: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/