This was so far the most successful week for this blog, with tens of thousands of views, several new patrons and twitter followers.
Two new supporters on patreon. Thanks!
I've finally published translation of my more-than-a-year-old article Programmer's critique of missing structure of operating systems. It took me horrible amount of time to translate it and then I've waited something like two and half months for grammar corrections. But apparently, all the work has paid up:
Almost 28 thousand visits just in one day, not bad. It was also trending post on the hackernews and it got some twitter response. Discussion was fascinating, although I have to say that in Czech version, there was better.
Over all, I have to say that this article has made a nice wave on a somewhat stalled fabric of the info sphere, and generated a lot of feedback.
This reddit post explains whole "object OS" idea really nicely:
So what would be a better way to solve this?
We can reimagine the whole thing. Probably the most interesting take on this is the monad manifesto. The problem with monad is that it doesn't go far enough. But they do hit on a key thing: files and streams was a great metaphor to describe most compute work in the 60s, and for a while it was the best there was. But around the same time a more solid idea was forming, though it wouldn't evolve into it's full potential until the 70s: Objects (in the smalltalk sense, not simula).
So lets revisit the OS, and the file system. So the idea is simple: everything in the OS is an isolated, completely obtuse "thing" we call this objects. And everything is an object, from the CPU running your code, to the kernel, to its scheduler, to the data you transfer outside. Your program itself is an object, though it's hidden internally. Generally objects don't expose their internals, instead you pass a message to them. The message may itself contain an object, to which the receiving object may then send another message with its internals. Objects sending and receiving of messages are not guaranteed to be in series, though some may.
So thinking of reading a piece of data from, say your keyboard or another process in a pipe you'd send it an object which can handle receive a piece of data (the reading as a series of bytes), if you are thinking call-back you pretty much got it. Now you can send a separate thing, or you can send a continuation to yourself, so your program pauses until the bytes are available, at which point the callback writes them into a buffer and the jumps to the continuation letting your program proceed. It isn't that far from how OSes work now, but the model and metaphor fully describes it and makes it obvious this is the way to go, instead of it seemingly doing weird things. Async is inherent in the model.
The advantage is that objects may appear to be the same, but behind the scenes expose very different things. And some objects may expose various things. Say writing as a transnational operation. You send a message to a writable data object which returns to you a transaction generator, when you send a message it returns (through continuations again) a result of writing to the transaction (which itself should be committed separately). If you don't want transactions (for whatever reason) or they don't make sense (writing to an append only object, like audio out) you have a simpler interface where you simply send the write operations to the object directly, no transaction.
Now of course this leads to an interesting challenge. In Unix everything is a string, which allows things to interact. But objects aren't guaranteed to be uniform.
The whole point of using objects instead of streams is that objects are more flexible (and honest) on what they are! The solution is that you can always try to find which interfaces an object implements. Here we can have a lot of discussion, but the solution is mostly set really. You can define interfaces, which are simply promises of what kind of messages an object can receive and send, and what guarantees it has (or at least must have). Objects can implement interfaces themselves, having full access to their internal, external implementation of interfaces can be done (using the object only on its external form, through its defined interfaces) and you can do implicit interfaces which are duck typing. You can then tell an object to pass itself to one object (generally a continuation) if it fulfills an interface, or to another (generally an error handler) if it doesn't. This allows for most basic type systems. Again the shell may give you a nicer way of describing this, but to the OS this is basically what it is.
Resource management, dealing with open resources, etc. is handled by a GC, which works as you'd expect it.
When objects pass their own stuff to others, they pass the necessary permissions, so security is bound to this. Commands by a user generally start with the permissions the user gives that command (generally open enough to not be annoying) and they may limit what they pass to other objects. Basically instead of file permission, we have object permission (modify, read, send messages to other objects aka. execute, etc.) and they can limit the scope (though not enlarge it) as needed. Because objects are more flexible than files you get more power.
And now how to get specific objects. One is through resources, these are objects that are well defined and understood, and generally identified through a URI (or IRI if we're being modern). Basically files and the URI is the filepath. Again shells can do good conventions to make it faster (just like you don't need to specify http(s) or www in browsers). Of course some objects can build their own namespace (basically do the same thing as a folder) which allows them to access their resources, others can access those resources through them (so /bin/ed is our editor, but /bin/ed/conf.toml is the editor's default configuration). Resources are not specifically tied to any one thing, but may have multiple paths to it. Having path in the resource system to a resource generally keeps it alive. Not all objects can become resources (think a resource handle which makes no sense to access out of context) but generally they can.
The second is providers, which are commonly accessible objects (either as a resource, or maybe provided by providers) that give you access to objects that do certain specific functionality. Generally the most common provider would be the environment provider, which gives you whatever is true for your environment (access to file, resources and so forth). A container system would basically expose what resources you have through env. Another would be context, which is more like what the specific process knows about how it was run (like which directory it was called from, what permissions were passed on to the object, etc). Basically DI at OS level.
Then we revisit the whole pattern of how we code things. Generally instead of building a full program, we build a series of programs that work well together. The most fundamental program would be one that lets programs work together. So if I were doing vi, it would be a system that loads a view, and a key-press mapper (we don't use the standard ttl of course). The view shows a buffer, which is an object that lets me do arbitrary selections and actions. Most transformations would be done through a visitor-like pattern, it the visitor actually may output a transformation, and allows it to work more like recursive schemes. The viewer doesn't use a raw-buffer, but instead one wraps the data, but allows arbitrary style information added on a second layer. My loading script will actually add extra layers, realizing when it's code, or such allowing me further functionality and more rich view. The loading script also loads a bunch of keyboard bindings, which bind to specific objects/visitors/transformers which do actions. So I could start a select-search command, which selects all pieces of text that fullfill a regex, and then a replace command, which replaces those selections with whatever text I input. If it's code I could automatically load another searcher which uses the same command for all languages, the semantic searcher which lets me do things like select all directly named instances of this variable/function but ultimately just changes whatever the selection of the buffer is. I can then do the same replace or such.
Basically the Unix philosophy got to its limits because computers started doing all sorts of things that the original model never considered. It lost it's structure and philosophy as it adapted and exceptions became more common than the rule, and decisions that now weren't the best one had to be kept to not loose existing features. But nowadays we have a better system to solve it, one that has proven it self time and time again. I think it would be interesting to build an OS that was like this from the beginning. Unix-like scenarios could be allowed, as Unix is simply a special case of the model.
I am also preparing new node (sub-page) that should work as a directory to all articles about structured systems.
Object wiki update
Small progress was made on the object wiki, but I couldn't allocate much time to working on it. I think that I managed maybe something like four hours over last two weeks.
I've finished Blindsight, again, for the third time. This time in Czech language. This may very well be the best sci-fi book I've ever read.
I don't understand the art of choosing irrelevant and ugly image for the front cover of the book, which is so prevalent in the Czech book culture. We are very small country (only 10M citizens) and people here in the book business are doing great job translating a lot of books from other languages. Why are you then using this random generic shit, which has really nothing to do with the content of the book? Why is there a female robot? Why does it look like cheap sci-fi from the 80's?
Look at the covers in other languages:
Can you recognize the recurring theme? Starship and a planet and something spikey - Rorschach, the alien artifact;
Imagine a crown of thorns, twisted, dark and unreflective, grown too thickly tangled to ever rest on any human head. Put it in orbit around a failed star whose own reflected half-light does little more than throw its satellites into silhouette. Occasional bloody highlights glinted like dim embers from its twists and crannies; they only emphasized the darkness everywhere else.
Imagine an artifact that embodies the very notion of torture, something so wrenched and disfigured that even across uncounted light years and unimaginable differences in biology and outlook, you can't help but feel that somehow, the structure itself is in pain.
Now make it the size of a city.
This story literally has a most amazing alien artifact, most interesting and very specific starfish like aliens, awesome spaceship and actual, very distinctive "vampire" mixed from the DNA of autists and psychopaths. But sure. Let's just slap there some random (female!) robot head and just be done with it.
I've also finished Dreamland, which is an autobiography by Bob Lazar (controversial Area 51 figure).
It was at the same time more interesting and more boring than expected, and really, no answers were given.
I tend to not to have opinion about his claims, even tho my first reaction would be to ignore him as attention whore. I am toying with the idea to build a comprehensive wiki with all of his claims, from which anyone could make an opinion, but meh. Probably not worth my time.
I am also making steady progress through the book about bullet journal method, and some books about design patterns.
I am trying bullet journal, with an actual pen and paper. It seems to be effective, and I am not sure why.
It kinda creeps me out, that this leads to more fragmentation, because now I am keeping todo and notes in bullet journal, notion.so and CherryTree at the same time. I am trying to keep this only for work, but if it is going to be effective, I'll probably want to use it for the rest of my life at some point.
Hacker Makes $360,000 ETH From a Flash Loan Single Transaction Involving Fulcrum, Compound, DyDx and Uniswap makes an interesting read.
Just ask for good music and 🗒the Algorithm shall provide.