9 ms·
Richard Gabriel's "The Rise of Worse is Better," written around the same time period the Unix-HATERS Handbook was written, gives some clues. Unix was contraste
by linguae 4y ago
Richard Gabriel's "The Rise of Worse is Better," written around the same time period the Unix-HATERS Handbook was written, gives some clues. Unix was contrasted with environments such as Scheme (which is rather small, but because it's designed as a "crown jewel"), Common Lisp (the exemplar of a "big complex system" that is complete and correct, but large and complex), and the ITS operating system (https://en.wikipedia.org/wiki/Incompatible_Timesharing_System https://en.wikipedia.org/wiki/Incompatible_Timesharing_Syste...). Thankfully there are many open-source Scheme and Common Lisp implementations, and ITS is also available as open source (https://github.com/PDP-10/its https://github.com/PDP-10/its).
Of course, modern Unix-like systems these days are large and complex, though Plan 9 and Inferno are quite architecturally refined, reducing some of the complexities that you'll see in contemporary Unix-like systems.
- toolz 4y agoCorrect and complete systems are large and complex, sure, but they are almost always comprised of small and simple parts. Unix in the 90s was around 300k LOC, hardly a small and simple system, but if we're to believe the author, it must have been made of small and simple parts.
- skissane 4y ago> ITS is also available as open source (https://github.com/PDP-10/its https://github.com/PDP-10/its) Sometimes I wonder, if you wanted to create an operating system like ITS for more modern platforms, what it would look like? ITS is written in PDP-10 assembly, what if someone wrote a compiler which read in PDP-10 assembly language and spit out C code? Could that be a first step to porting it? It is surely a lot more complicated than that. It contains self-modifying code, which would obviously break that translation strategy. A lot of hardware-specific code would have to be rewritten. 6 character filenames without nested directories might have been acceptable in the 1970s, but few could endure it today. A multi-user system with a near-total absence of security was acceptable back then, obviously not in today's very different world. ITS does have some interesting features contemporary systems don't: A process can submit commands to be run by the shell that spawned it – actually MS-DOS COMMAND.COM also had that feature (INT 2E), but I haven't seen anything else with it. A Unix shell could implement this by creating a Unix domain socket, and passing its path to subprocesses via an environment variable–but I've never seen that done. Another was that a program being debugged could call an API to run commands in its own debugger – I've never seen that in any other debugger, although I suppose you could write a GDB plugin to implement it (have a magic do-nothing function, then a GDB Python script sets a breakpoint on that function, and interprets its argument as commands for GDB.) Actually, in ITS these two features were the exact same feature, since the debugger was used as the command shell. Another was that a program had named subprocesses (by default the subprocess name was the same as the executable name, but it didn't have to be.) Compare that to most Unix shells, where it is easy to forget what you are running as background jobs 1, 2 or 3.
- javert 4y agoI wish we had more of this kind of content on Hacker News.
- cycomanic 4y agoInteresting context thanks! > A process can submit commands to be run by the shell that spawned it – actually MS-DOS COMMAND.COM also had that feature (INT 2E), but I haven't seen anything else with it. A Unix shell could implement this by creating a Unix domain socket, and passing its path to subprocesses via an environment variable–but I've never seen that done. What would you use it for? How is that superior to simply spawning a new shell process?
- skissane 4y agoNorton Utilities for DOS came with a program called NCD (Norton Change Directory). It was a full-screen replacement for the CD command, you could browse through the filesystem to get to the directory you wanted, then it would exit and return you to COMMAND.COM's prompt, with you already in that directory. That worked because under DOS, the current directory was system-wide, [0] not per-process, so a subprocess could change the parent process' current directory. On Unix systems, and the Windows NT family, the current directory is per-process, so that doesn't work any more. Now, you can implement the same idea on Unix–but it is more complex. You need to define a shell function in your .profile/.bash_profile/.zprofile/whatever. That shell function then executes the external change-directory program, and passes the destination directory back to the shell function somehow. The shell function then actually changes the directory. What if shells had exposed some kind of standard API to their subprocesses? Maybe something as simple as an environment variable containing the path to a Unix domain socket which accepts a simple text-based protocol. You could then implement an NCD-style command, by having it send the shell which called it a request to change its directory. That way, you would not have to install such a command by modifying your profile and restarting your shell, the command would just work the first time you ran it. Similarly, there are a lot of tools out there for supporting multiple versions of development tools concurrently (Environment Modules, venv for Python, nvm for Node, conda, etc.) Most of these tools work by manipulating your shell environment. Since, on Unix, environment variables are per-process, and a process cannot modify the environment of its parent, you have to install some shell function in your profile and restart your shell before using one of them. Once again, if shells exported some kind of "get/set shell environment" API to their subprocesses, these kind of tools would work the first time you ran them, without any need to modify your shell profile. [0] Actually, in MS-DOS and Windows 3.x/9x/Me, there is both a system-wide current drive, and a separate system-wide current directory for each drive – Windows NT family's cmd.exe simulates this by using a hidden environment variable per a drive to store its current directory, but that is a convention which only cmd.exe supports, the rest of Windows knows nothing about it.
- kazinator 4y agoAt the time The Rise of Worse Is Better was written, Scheme had: - no error handling. The specification described that certain situations result in an error, without defining what that means, or how you can catch and recover from one programmatically. - no module system. The Scheme report didn't describe any feature for decomposing a Scheme program into multiple files. No rules governing how literal data goes into compiled files and what the rules are for recovering symbols. No evaluation controls (like don't evaluate this form when compiling, but only deposit it into a compiled file and such). Unix was a useful production system used for running businesses, with error handling in its API's and compilation of programs decomposed into multiple files. The "PC losering" problem was nicely resolved. Unixes developed sigaction, where you can specify it both ways: interrupts can bail the system call (which is sometimes what you want) or restart it (which is what you want at other times). Neither is inherently better. Sometimes you really don't want a long system call to go back to sleep as if nothing happened. A third solution is possible though: your signal can resume the system call when it returns normally, or else abandon it with a siglongjmp, which restores the signal mask to what it was at the sigsetjmp point. Then there is is various other signal paraphernalia. Basically the Unix people had the right intuitions in this area, and took an incremental approach whereby they gradually rolled in more correctness.
- ertian 4y agoThat's kinda the whole point of the essay: getting something up and running quick that is 'complete' (if not particularly elegant) is better than slowly and carefully working on a Good System. Unix ate Lisp's lunch because you could build things on it right now. That essay definitely was a bit of a complaint about the crudeness of Unix. But I read it primarily as a wake up call (not to say epitaph) for the Ivory Tower Lisp developers who were dreaming about the perfect system while Unix ate their lunch.
- kazinator 4y agoThe Lisp people absolutely got something up and running quickly, which is why Lisp is one of the earliest languages. Big, institutional Lisp systems were in a different state of maturity when Unix was coming up. Early Lisp didn't have defmacro with destructuring, backquote, lexical scope, condition handling, structures, hash tables, ... you wouldn't want to use it today.