718 karma · joined October 4, 2015
I was able to keep up some ad-hoc home bodyweight exercises with Habitica (gamified habits) + Forest (pomodoro-ish app) earlier in the year, but that fell apart a few months later when the depression got worse, and I haven't managed to pick it up again yet.
I don't normally post things like this out of the blue, but if anyone has small software things they might be willing to commission me for within the next few-to-several months where turnaround time isn't “right now”, that could help a lot, so don't hesitate to poke me at my profile email address, low-effort one-liners accepted. (I have a partial source of work lined up for once I can focus again, but it's fraught in its own ways.)
My most native domain is oldish/systemsish/Unixish (Go, C, shell scripting, Perl…) but I can be fairly polyvalent in environments overall. Have done some previous work on things like Tor and OpenVPN. Ideal is something like “this bug/feature-request has been nagging at us and could use a fresh set of eyes”. Specific strengths historically include informal-methods precision of modeling and ability to haul The Good Stuff out of semantic mud. Specific weak areas include PHP being too psychologically taxing, Node.js likely being the same (which, ah, er, ouch given current SV culture), and flakiness from the depression itself (expected to improve with medication, but not 100% and exact curve unknown).
Posting this as a separate comment so it's easier to delete on its own if it turns out to be inappropriate. Also, to avoid surprise: I don't make my legal name too immediately visible from profiles etc. presently, but anyone who's transacting with me will get a confirmation of it privately.
Out of money. I was trying to get my career back into play via Triplebyte + one or two contacts around the beginning of the year; I had some minor success, but my interviews promptly got cancelled as the pandemic ramped up. And I think my Résumé of Nothing is now even more of an infinite liability than it's been in any recent years. (I took enough of a hit at the end of 2018 to pretty much lose my ability to work, after some years of on-and-off self-underemployment, and spent 2019 trying to recover; what I managed to regain has mostly been undone again in 2020.) Oh, and video calls and screen sharing (things people want a lot of nowadays) are both tricky due to secondary effects.
I finally have a source of medication that requires less effort to keep going, and that might help stabilize. Wish me luck?
Which would be why my projects use the “GNUmakefile” file name explicitly, even though e.g. I tend to write to POSIX sh where I can rather than following the “bash scripting” trend. I also remember seeing a project in the wild that had a separate GNUmakefile and BSDmakefile, presumably for similar reasons.
If you use only POSIX make syntax, great for you, but there's definitely a barrier compared to what a lot of people are used to thinking of as Make nowadays.
(This is also ignoring the part where “higher probability” at a glance refers more to popularity than to standards compliance, and I don't read the parent as implying being in an environment where POSIX/SUS compliance is directly related to the set of target systems.)
The geek/MOP/sociopath triangle wouldn't be a terrible description of the “subculture takeover” that seems to have occurred.
To expand on their comment: if `throw` in Java or C++ is similar to `error` in CL (or `throw` in some special cases), a `catch` clause in Java or C++ is equivalent to a label, where the `try` binds a handler that exits to it immediately. There's no equivalent of putting code in the handler other than a single unwind-and-jump, and there's no equivalent of restarts.
In CL, a condition handler gets called on top of the existing stack and can inspect what's going on before choosing where to exit to. Other functions in the call stack can provide alternative exits (restarts), like “continue processing anyway” or “substitute a placeholder value”; these are dynamically named, rather than lexically bound like `catch` . So there's a lot more possible decoupling, at least in theory. The equivalent of `finally`/destructors is `unwind-protect`, which has to interoperate with the condition mechanism but doesn't deal with conditions itself.
In C++ or Java, you could implement the restarts with a (thread-local) stack of restart descriptions plus try/finally or constructor/destructor, and the same for handlers, and then do your nonlocal exits with specialized throwables. I did something similar in Lua, in fact, while trying to extend it into a fancier language. But a “normal” `throw` will bypass all of that. That's not dangerous if you do the unwind-protects properly, but none of your existing libraries will be built for it, and the results will be kind of anemic.
In the Java-style objects+throw/catch world, similar things can be achieved by toggling “what to do if X happens” state or plumbing callback pointers through the object graph beforehand, which is similar but more ad-hoc, and possibly harder to add to existing systems. That said, the CL style proper is very tied to the call stack, which can also make things tricky.
From another angle, if you look at the difference between version 1 and version 2 time+node UUIDs, they're actually quite similar except for version 2 having a UID/GID-like field replacing some of the least significant bits of the other data. So collisions between v1 and v2 would be much more possible without the version bits. And at that point there's no reason not to use similar flags to refer to other generation methods; even if in theory you could decide that they're unlikely to create collisions, that just feels like it leaves the door open for edge cases and having to remember which of those decisions were made. Why not be consistent?
From the opposite angle, in a case where you're using random UUIDs generated within a trust boundary as lookup keys, the knowledge that one of them is random doesn't tell an adversary on the outside anything useful about the others, because they're all random, so it's a few harmless “wasted” bits. Of course, since UUIDs didn't have “unguessable” as a selling point to start with, if that's something you're leaning on, then go ahead and use something else…
I installed the official Windows binaries for GNU Emacs pretty recently, copied my elisp directory over, and for the most part things worked out of the box, but with a few inconvenient exceptions: taskbar pinning didn't seem to work properly due to the awkward emacs/runemacs distinction, and some things related to directory layout and navigation were painful due to assumptions of a Unix-style home directory clashing with Windows's user-directory layout. No WSL involved.
I wouldn't want to try to directly deliver anything from such an environment that I would ask other people to run. Even my more-trusted development laptop feels scary at times, especially when I'm operating in environments where I have to do about the same thing as above with installing a dozen dependencies from who-knows-whom. I generally use separate build UIDs for some measure of separation in these cases, but we still have Linux and X being potential emmentaler attack surfaces, and I haven't yet arranged my workflow to the point that spinning up new virtual machines is trivial, especially because then you have a lot more friction with testing GUI software, sharing existing files, etc. etc.—most of the easier solutions to which seem to be very cloud-oriented and “when your Internet connection goes down, so does everything else”, which is something I insist on pushing back against in this context, including because “someone upstream did something unexpected and now everything is instantly broken in a way I have no real leverage over” is its own massive trust hazard.
My dedicated low-sensitivity machine isn't very powerful, so the cost wasn't as much of an issue as it could have been; it was a midrange laptop several years ago which I'm still using. If your workplace environment comes with its own hardware, then that's a thing too.
It would certainly be nice to have better, though, and the desire for less redundancy of costly hardware is legitimate. My desired setup from a while ago, which I never managed thus far, is to have more powerful hardware with multiple boot configurations, but not all of them persistently present like most multi-boot machines: instead, I would physically attach and detach system and user disks, assuming that firmware-level attack persistence is rare, and then rely on power-down flushing any lower-trust code before attaching a higher-trust disk. It'd be hard to ask most people to do this, though.
Aww, I can't type outside ASCII range? Drat, I wanted to see whether different languages (even in Latin script) were distinguishable by sound this way.
The rapidity of settlement of common knowledge in Internet time breaks a lot of the natural frictional mitigations, too.
“Oh, the path dependence is real” (said in the tone of a gaming commentator).
Further, there's different levels and causes of “coordination didn't happen”, such as “we tried, but got confused and didn't have time to understand each other properly” or “actively sabotaging everyone else's ability to deal with the aggregate system so that I can get ahead”… and somewhere in there is one that stands out to me as specifically interacting with technical complexity, along the lines of “I want my piece to not have to be the one that changes and/or takes on other costs”. Which is part of the social dynamic of moving externally-essential complexity around within the aggregate system and potentially creating ripples of accidental complexity along the way.
(Whether and how this also happens when the information systems in question are human minds rather than software components might be relevant but also an exercise for the reader…)
Either you're expecting the code from that repository to exist somewhere in the compilation-host system already, or you are vendoring the code by copying it into your own repository and taking on any potential maintenance, unportability, any necessary configuration integration to make sure, for instance, that you're compiling for the host rather than the target in a cross-compile setup (did you make sure?)—
Either way, if you use that code as part of your build process, you are taking a build-dep on that code. The fact that its only build-dep is a C compiler may play into making this a sensible choice as compared with something that has even more transitive dependencies, but it does not make it go away.
What's more of a problem I might run into soon is that my setup was already out of date for video calls; this seems increasingly like a hard expectation rather than an optional plus; and the pseudo-docking way I use my primary laptop at my desk doesn't currently allow me to orient the builtin camera so that it catches my expression at a reasonable angle while also letting me leave the monitor in front of me. Putting the laptop where my monitor currently is might be workable, but it could also get squint-inducing at that distance… I might have to play around with this.
It occurs to me that I don't know whether any of the major dynamic language implementations with maps/dicts/hashes as a central data structure use a similar approach for very small ones… huh.
I expect I'll run into more friction once I get to any point where I want to make more dynamically interlinked data structures, though that might also push my designs into directions that use fewer pointers and more indexes or other indirect references to start with (I'm not sure of that yet)—and I really like the idea that if I can pare some of it down to a working “core” data structure semantic that involves pointer juggling, I can put carefully constructed hard-packed blocks of the pointer juggling in their own unsafe zone and then not be able to accidentally break the invariants outside of that.
Which, again, is almost exactly the same thing I'd tend to do in C with inline wrapper functions and visibility stuff, and making sure I compute all the intermediary results in one phase and putting all the hard mutations in a second, unfailable (except possibly for hard crashes due to null pointers or such) phase so that if something goes wrong the data doesn't wind up crashing down to a persistent broken state from mid-flight!
Heck, I've even done the newtype pattern (single-element structs for safe reinterpretation/bounding of an underlying type) in C before!
I've described the way I write C as “as though I were hand-cranking the front end of a strict, low-level Haskell or Caml compiler in my head”. Rust is the closest I've seen thus far to moving a big chunk of that part of me into the digital part of the compiler. So I'm guessing my taste wasn't exactly uncommon.
The first paragraph in “Technical details” mixes (1) and (3) confusingly, and should have had a paragraph break before the sentence beginning “Verify” (or been rewritten).
A quick glance at the patchset suggests this is right (the verification code looks to have been made stricter in the verify endpoint, but added in the sync endpoint), but I didn't dig deeper than that.
[edited slightly for wording]