No erl, no elixir, no mix. Not in MSYS2 either — pacman -Ss erlang returns nothing,
so the route that rescued the OCaml track was unavailable.
winget failed differently this time, and the difference is worth recording:
$ winget search elixir
Failed in attempting to update the source: winget
Failed when searching source; results will not be included: winget
No package found matching input criteria.
Previously winget search worked and only install hung. Here the source index itself would
not refresh. Two distinct winget failures across three tracks; it is not a reliable route from
this context in any form.
The official answer is good and nearly worked.
elixir-lang.org/install publishes an install.bat that
needs no administrator rights:
curl.exe -fsSO https://elixir-lang.org/install.bat
.\install.bat elixir@1.20.4 otp@28.4
Reading it before running it — 6,483 bytes, and worth the minute — it does four things: reads
the latest release via a HEAD redirect, curls two zips from github.com/erlang/otp and
github.com/elixir-lang/elixir, extracts them with Expand-Archive, and runs the bundled
vc_redist.exe only if vcruntime140.dll is missing from system32. No registry, no PATH
mutation, no elevation except that last conditional step.
It then died partway through the 170 MB OTP archive:
downloading https://github.com/erlang/otp/releases/download/OTP-28.4/otp_win64_28.4.zip...
curl: (23) client returned ERROR on write of 13780 bytes
curl exit 23 is a write failure, not a network failure — it could not put the bytes where it
wanted them. Rather than fight the script's choice of temp directory,
tools/install-elixir.ps1 does the same four steps with
Invoke-WebRequest, an explicit download directory, and the same destination layout so
elixir-lang.org's own documentation still describes what is on disk:
%USERPROFILE%\.elixir-install\installs\otp\28.4
%USERPROFILE%\.elixir-install\installs\elixir\1.20.4-otp-28
Erlang/OTP 28 [erts-16.3] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
Elixir 1.20.4 (compiled with Erlang/OTP 28)
The script does not touch PATH. Two Erlang installations on one PATH is a worse problem
than resolving the path at call time, so verify.py globs
~/.elixir-install/installs/{otp,elixir}/*/bin and prepends the newest of each for the
suite's lifetime only.
Side effect worth banking: this installed Erlang/OTP 28 as well, so track 50 no longer has a toolchain problem.
\A and \z, not ^ and $defp all_digits?(s), do: String.match?(s, ~r/\A[0-9]+\z/)
Elixir's ~r is PCRE, where ^ and $ match at line boundaries by default. So
~r/^[0-9]+$/ matches "200\nrm -rf /" — the first line satisfies it and the rest is along
for the ride. The anchors meaning start-and-end-of-string are \A and \z.
The fixture would not have caught this. No field in access.log contains a newline, so the
wrong regex passes the golden diff and is still wrong. Same class as the
C track's %-20.20s truncation: found by reading the spec, not by running
the tests.
Python's re has the same ^/$ behaviour under re.MULTILINE only, and Go's regexp the
same. Java's Matcher.matches() anchors implicitly, which is why the Java track's
^[0-9]{3}$ is belt-and-braces rather than load-bearing. Four tracks, four slightly different
default anchoring rules.
IO.binwrite, not IO.writeIO.write runs the term through the Unicode encoder and hands it to the device with line
handling applied. IO.binwrite writes bytes. On Windows that is the difference between \n
and \r\n and therefore the whole diff — sixth track, sixth spelling of the same fact — and
it is also faster, because the encoding step is skipped for data that is already a binary.
System.haltIO.binwrite(:stdio, render(Path.basename(path), acc))
:ok = :io.put_chars(:standard_io, [])
System.halt(if acc.malformed == [], do: 0, else: 4)
System.halt stops the VM immediately. Standard output on the BEAM goes through an
asynchronous port process, so bytes handed to IO.binwrite may still be in flight when
the VM dies, and the report truncates at whatever had made it out. The empty
:io.put_chars/2 is a synchronous round trip to that port — it returns only once the port has
processed everything queued ahead of it, which is the flush.
Neither C's exit() nor Go's os.Exit has this hazard, because their stdout is a file
descriptor rather than a process. This is the cost of the actor model reaching all the way
down to I/O, and it is the one place in the track where "everything is a process" is a
nuisance rather than a feature.
Every account of BEAM scheduling says a process gets 2000 reductions before preemption.
The BEAM Book's scheduling
chapter
records that CONTEXT_REDS was 2000 before OTP 20 and has been 4000 since. The commonly
repeated figure is nine years stale. Corrected in Q6.
The AXD301 99.9999999% uptime figure appears in every Erlang pitch. It is in Armstrong's thesis — and so is his statement that evidence for the system's long-term stability "had also not been collected in any systematic way", the number coming from a customer's slide deck by unclear means.
Repeating the figure without the caveat misrepresents the source. Q1 quotes both. This is the kind of number the deepening runbook means when it says to replace a hedged number with a cited one or cut the claim — here the citation is what adds the hedge.
--shard N (SPEC 6) with Task.async_stream/3 and a merge/2 fold. For this track it
is the actual content; the serial version demonstrates the syntax and none of the
reason to use the language.:observer while sharding, to see the process tree the Q6 diagram
describes. :observer needs wx, which the OTP Windows zip includes.logagg.exs. It compiled with no warnings,
which means it found no provable violations — not the same as "typed correctly", and
the distinction is Q3's whole point.mix.exs variant with ExUnit doctests, to show what the real project layout costs.
Deliberately out of scope for a no-dependency program, but it is the thing an Elixir
reader will expect to see.