I just tried it. :X asks you to enter an encryption key, then asks you to enter it again, and only continues if the keys match. And then you're still in vim and need to save your file to overwrite anything. Seems hard to do by mistake.
> I am not sure ARMv1 (and v2) even had supervisor vs user mode, etc.? (It may have, Google isn't helping me here)
v2 at least had 4 modes: user mode, supervisor, IRQ and FIQ. They were encoded in the low 2 bits of r15 (which weren't otherwise needed, since the PC was always word-aligned).
The original Archimedes was intended to run a "preemptively multi tasking, multi-threaded, multi-user, written in Acorn-extended Modula2+" system called ARX. But when that wasn't ready in time, they ended up just porting the 8-bit BBC Micro MOS to the new 32-bit machines!
I usually notice if my blog gets on Hacker News fairly soon, so I'll see any comments posted here.
I prefer not to use email for most things because then the reply only benefits one person, whereas replies in a public forum can be read by others and get indexed by search engines.
I've been thinking about creating a Matrix room for each blog post as a discussion forum, but so far most posts have ended up on other discussion sites anyway.
- domainslib schedules all tasks across all cores (like Go).
- eio keeps tasks on the same core (and you can use a shared job queue to distribute work between cores if you want).
Eio can certainly do async IO on multiple cores.
Moving tasks freely between cores has some major downsides - for example every time a Go program wants to access a shared value, it needs to take a mutex (and be careful to avoid deadlocks). Such races can be very hard to debug.
I suspect that the extra reliability is often worth the cost of sometimes having unbalanced workloads between cores. We're still investigating how big this effect is. When I worked at Docker, we spent a lot of time dealing with races in the Go code, even though almost nothing in Docker is CPU intensive!
For a group of tasks on a single core, you can be sure that e.g. incrementing a counter or scanning an array is an atomic operation. Only blocking operations (such as reading from a file or socket) can allow something else to run. And eio schedules tasks deterministically, so if you test with (deterministic) mocks then the trace of your tests is deterministic too. Eio's own unit-tests are mostly expect-based tests where the test just checks that the trace output matches the recorded trace, for example.
By default, opam installs everything into the current "switch". Typically you have switch one per compiler, but you can create one per project. You can also create a "local" switch directly inside your project directory: https://opam.ocaml.org/blog/opam-local-switches/
Another option is to use the duniverse tool (https://github.com/ocamllabs/duniverse). That downloads all dependencies to the project directory, and then builds them all together as one giant project. That makes it very easy to make changes across multiple libraries at once, while keeping fast incremental builds.
And a final option is to build projects with Docker, which allows you to have separate versions of non-OCaml packages too.
> the recommended tools never seem to work together on anything but the latest version
Whenever a package is added to the repository, the CI tests (the latest compatible version of) every package that depends on it to check everything still works. However, non-current packages may break if they're missing upper bounds (it doesn't check all previous releases).
However, since opam-repository is just a Git repo, you can clone a known snapshot of it at some point in time and keep using that. That allows you to continue using old versions of packages without the risk of new software causing unwanted upgrades.
> My impression is that INRIA is too eager to add features and tweak the language.
That's strange. I've always had the opposite impression - that they maintain compatibility at all costs, including leaving sub-optimal APIs in the standard library.
> Next, everything builds so slowly, and just trying to set up Core, utop, and ocp_indent is a trial in patience, watching the same dep build again and again
The Core alternative standard library is pretty huge, indeed (I don't use it). I just tried installing all the tools you mention in a fresh container:
$ time docker run ocaml/opam:debian-9_ocaml-4.05.0 opam install core utop ocp-indent
6:03.75elapsed
So, 6 min to set up a dev environment with those tools. That installed 67 packages, so compilation took about 5 seconds/package on average. I'm not sure why it would build the same dep twice - I haven't seen it do that.
Yes, doing this would make it easier to use services like GitHub. For example, DataKit's GitHub bridge service uses webhooks to track changes in GitHub metadata (e.g. the status of branches, tags and PRs) and stores the state in another Git branch. The DataKitCI monitors this branch to know when to build things (and writes the status back there):
I use a Qubes Debian VM for dev work. Works fine, except that it runs gnome-keyring by default, which breaks ssh, and restores this config everytime I upgrade (but easy to fix when it happens).
Here's a common example. Some systems provide blocking operations: e.g. read_line waits for a line of text and then returns it as a string. Others use promises: read_line returns a promise of a string.
What if you want to write a library that works with either blocking calls or asynchronous promises?
The cohttp HTTP library is written that way. For example, the Transfer_io module[1] (supporting both chunking and non-chunking HTTP transfers) takes as an argument another module, IO[2], that provides a read_line function of type "ic -> string option t", where the type t is abstract and higher-kinded (and "ic" = input channel). You can instantiate the module with a blocking IO module (where a "string t" is just the same as a "string" and read_line blocks) or with a non-blocking one (where a "string t" is a promise for a "t" and read_line returns a promise).
It depends on which lightweight OS and which unikernel. But e.g. a stripped down Linux will still have a huge amount of C. If you're going to write your kernel in something safer, then you might as well make a unikernel, rather than creating a kernel/userspace split.
Like most OCaml libraries, Irmin can be used in the browser by compiling your program with js_of_ocaml.
My `irmin-js` experiment provides a Javascript API to Irmin, so you can write your application in Javascript too, rather than OCaml. My JS isn't very good though; here's what my example code ended up looking like: