1. 25

    Nice article. I must admin that I am a systemd fan. I much prefer it to the soup of raw text in rc.d folders. Finally, an init system system for the 1990s.

    1. 13

      I’ve never had a problem doing anything with systemd myself - I think a lot of the hate towards it stems from the attitude of the project owners, and how they don’t make any effort to cooperate with other projects (most notably, IMO, the Linux kernel folks). Here’s a couple of interesting mailing list messages that demonstrate that:

      1. 11


        I was initially skeptical about the debug ability of a systemd unit, but the documentation covers things to great depth, and I’m a convert to the technical merits. Declarative service files, particularly when you use a ‘drop-in’, are a definite step up from the shell scripts of sysvinit.

        The way the project tries to gobble up /everything/ is a concern though, given their interactions (or lack thereof) with other parts of the community.


          Declarative service files, particularly when you use a ‘drop-in’, are a definite step up from the shell scripts of sysvinit.

          I’ve never found “systemd vs sysvinit shell scripts” to be a particularly compelling argument. “Don’t use sysvinit shell scripts” is a perfectly fine argument, but doesn’t say much about systemd. There are loads of init systems out there, and it seemed to me that systemd was never in competition with sysvinit scripts, it was in competition with other new-fangled init systems, especially upstart which was widely deployed by Ubuntu.


            In the case of Debian, it’s basically sysvinit or systemd.


              That’s still not much of an argument for systemd; it’s just passing the buck to the Debian developers, and going with whichever they chose. That’s an excellent thing for users, sysadmins, etc. to do, but doesn’t address the actual question (i.e. why did the Debian devs make that choice?).

              According to Wikipedia, the initial release of systemd was in 2010, at which point Ubuntu (a very widely-deployed Debian derivative) had been using upstart by default for 4 years.

              Debian’s choice wasn’t so much between sysvinit or systemd, it was which non-sysvinit system to use; with the highest-profile contenders being systemd (backed by RedHat) and upstart (backed by Canonical). Sticking with sysvinit would have been an abstain, i.e. “we know it’s bad, but the alternatives aren’t better enough to justify a switch at the moment”. In other words sysvinit’s only “feature” is the fact that it is already in widespread use, with all of the benefits that brings (pre-existing code snippets, documentation, blogposts, troubleshooting forums, etc.).

              These days systemd has that “feature” too, since it’s used by so many distros (including Debian, as you say), which was the last nail in sysvinit’s coffin: at this point sysvinit is mostly hanging on as a legacy option (Debian in particular cares very deeply about stability and compatibility). Choosing between Debian sysvinit and Debian systemd isn’t so much a choice of init system, it’s a choice of whether or not to agree with the Debian developers’ choice to switch init system. And that choice was between systemd, upstart, initng, runit, daemontools, dmd, etc. They abstained (stuck with sysvinit) for many years, until around 2015 when the systemd vs upstart competition was resoundingly won by systemd, with Ubuntu switching away from upstart and Debian switching away from sysvinit.

              As I saw all of this going on, my interpretation was:

              • Around 2005 every popular distro was using sysvinit because of its entrenched base, a few users advocated for alternatives like initng but the distros didn’t find the improvements to be worth the cost.
              • Ubuntu switched to upstart, making init systems a hot topic: sysvinit became viewed as legacy, upstart was being looked at closely by other distros and it seemed like, once it got enough real-world usage, many might switch over.
              • Systemd appeared, inspired by Apple’s launchd, and gradually gained users. At this point sysvinit was already seen as legacy and the question was what systemd offered that upstart didn’t.
              • Debian debated switching init system, and with input from Ubuntu developers they both agreed that systemd was the better option (from my understanding, systemd’s “lazy” approach was a fundamentally better fit to the init problem than upstart’s “eager” approach). Upstart basically died at this point.
              • All subsequent debates about systemd focus on how it’s better than sysvinit, which was never really in question.

              To me, comparing systemd to sysvinit is like those shampoo adverts which claim their product gives an X% improvement, but the fine-print says that’s compared to not washing ;)


                OpenRC is drop-in and works perfectly fine. I dropped it in and I’m using it on all my installs with no issues.


                  I think maybe you’ve misunderstood me.

                  I don’t mean you can install systemd and it will continue to work with sysvinit scripts.

                  I’m referring to systemd’s “drop-in” unit configurations. You can override specific parameters of a unit without having to replace the whole thing.



              My impression is that the resistance to systemd stems from it not being unixy. Not being Debiany, even.

              I use for i in ..., sed, grep, awk, find, kill -SIGHUP, lsof, inotify, tee, and tr all damned day to mange my system, and systemd has left me blind and toothless.

              I’m still working on my LFS-based replacement for my various Debian desktops, vms, and laptop.

        1. 2

          The hash example seems to go entirely against duck typing without ever mentioning it. Does that mean I shouldn’t do duck typing? Or I should? Based on this I should probably just be using a static language…

          1. 1

            I too think that it’s unreasonably strict. I’m not familiar with Ruby, but is_a is frowned upon in most class-based OOP: the usual alternative is to ask the object if it can do something (i.e. call one of its methods), rather than the language (via is_a).

            A simplistic version might use a method like canHash, returning a boolean. This moves the responsibility away from the language and into the objects, where we can choose how it’s implemented. The problem with doing this is that we’ll probably have to change/wrap the objects that we’re using to give them this new method.

            A nicer approach would use what’s already there. For example, in Python the foo[bar] notation is implemented by calling a __getitem__ method. Hence we could have the constructor check whether the given object has a __getitem__ method, rather than what class it is/inherits from. One problem with this is that the object might use a “magic method” to handle those calls, which may cause our check to fail despite giving a valid object. Whether we want to allow that or not depends on the language culture.

            The equivalent with static typing is an interface, e.g. KeyValueMap. The nice thing about interfaces is that we don’t care what the actual type is, how it is structured, if it’s a subtype of something, etc. we only care about “can we use it like a hash map?”. This is like doing a canHash check, but doing it statically at compile time rather than at run time; like canHash, we would have to ensure that the types we care about provide an implementation of the interface. Some languages, like Haskell, allow us to provide such implementations ourselves in an ad-hoc way (although there can be conflicts, see “orphan instances”); in languages like Java we can only implement interfaces from within the type (actually class) definition, we can’t “plug in” an implementation later (we’d have to provide a wrapper).

          1. 1

            I’ve run across similar issues too, which I wrote a blog post about.

            To me, the main “camps” seem to be domain-based vs. implementation-based. For example, the implementation-based perspective maps testing terminology on to programming language features: a “unit” is a method, a “dependency” is a class, etc. The domain perspective is based on semantically meaningful divisions, e.g. a “unit” might be “logging in”, since we can’t “half log in” regardless of how much code is involved in the process.

            Cross-talk between those using different definitions ends up taking a reasonable practices according to one definition and applying it in places where’s it’s less appropriate (e.g. that all “dependencies” should be mocked, which gets ridiculous if we take “dependency” to mean “any class”).

            1. 1

              Hmm. Not really happy about this.

              Let’s take a step back.

              I often liken testing to building a ship in a bottle.

              You have to explore and manipulate the entire contents of the bottle, only through the interface, the mouth of the bottle.

              The larger and more complex the inside of the bottle, the harder your task is.

              The more constrained your interface (narrower the mouth), the harder your task is.

              Yet to verify your code will work for all valid uses, you have to explore the entire inside of the bottle.

              Now if your function calls another function….. it’s like building a ship in a bottle, that is inside another bottle.

              Orders of magnitude harder problem.

              If you have a really simple bottle with a wide mouth…. it’s all easy.

              But for anything even slightly more complex, the only way to achieve the goal of verifying the correctness of the code, is to go for the smallest possible unit.

              What is the smallest possible unit?

              The smallest thing you can throw at your toolchain and produce a runnable executable test.

              Why are you running a whole web server?”

              No. I won’t chide you for…

              not doing real unit testing, for failing to use the correct magic formula

              I will do worse.

              I will merely ask you how did you explore the whole state space of your code? Are you sure you have verified your code will work when it is invoked with any parameters and any internal state that it is contracted to work for?

              If you answer Yes, and you can explain how… I’m happy.

              If you mumble and look at your feet and mutter about the number of atoms in the known universe, I’m less happy.

              If your tests take longer than the average rate of commits to the repo so you cannot cleanly decide whose commit broke the tests….. I’m getting quite disgruntled.

              If your tests break sporadically so it seems as if my commit broke the build…. I’m actually getting quite pissed off.

              1. 1

                Now if your function calls another function….. it’s like building a ship in a bottle, that is inside another bottle.

                Orders of magnitude harder problem.

                I disagree: calling other functions make our life easier, since we can delegate responsibilities and compartmentalise the problem. The ‘interface’ of our functions (parameters, calling convention, side-effects, error conditions, etc.) should be all we need to use them effectively. Checking that the interface is adhered to isn’t the caller’s responsibility, that’s the responsibility of that function’s own tests (although calling a function in a test does check some of its implementation, but that’s just a bonus).

                In other words, don’t build ships-in-bottles-in-bottles: build ships-in-bottles, then push one inside another (and take it back out for changes/fixes).

                1. 2

                  Certainly the path to building defect free systems is to assemble them out of defect free components.

                  However, to verify a function you need to be able to explore it’s state space. ie. Global, static and instance variables only via the parameters of the methods that manipulate that state space.

                  This is why functional programming folks hate hidden mutable state.

                  Your program needs to work for values of internal state the user has access to from the initial state.

                  But verifying that is hard.

                  As an extreme example, I have a gadget on my desk with a couple of buttons and an RF interface.

                  It’s internal state is in the multimegabytes. ie. No matter how much or how long you tested via those couple of buttons… you still have only explored an absolutely negligible fraction of the states that the user may legitimately access.

                  Or to go back to the bottle analogy….

                  It all depends on the shape of the bottle.

                  If you have a wide mouth, shallow bottle (ie. The interface is as broad or broader than the state space inside the function), yes you are right.

                  If you have a narrow mouthed deep bottle, and your inner bottle is narrow mouthed and deep… a substantial part of the state of your outer bottle resides inside the inner.

                  Thus to verify your outer bottle, you have to also explore all parts of the inner bottle that may be reached via the mouth of the outer.

                  And that is very hard.

                  An alternate approach is use contract tests to verify that the outer and inner functions agree on their interface. I typically use this approach for services like I/O, timers, threading primitives etc.

                  Of course, the best approach is to minimize the amount of mutable hidden state….

              1. 2

                Some good, comprehensive information there. My own projects are too small to need mailing lists, although I did once receive a patch via email :)

                A couple of points about the content:

                • The article recommends using git’s --mirror option but I seem to recall some bad experience trying that in the past, so I always use --bare instead.
                • The article also mentions BugsEverywhere, which I tried to use some years ago but it seemed to be dead (submodules weren’t resolving, etc.). I considered forking, but it seemed dauntingly overengineered for what I needed. Instead I use artemis which is very simple.

                My own setup has been evolving over the years, but it would be nice to have a command to make a “skeleton” project, with a mailing list, repo URL, CI setup, etc. There’s probably too much variation among those things for people to agree; so far I use a script which can take a local git repo and set up a bare clone on my Web server, set up some hooks for rendering static pages, etc.

                1. 13

                  There’s two really nice things here:

                  1. The “number of versions” is a fantastic metric and Microsoft Research observed something similar spending a little more time on this point. If you’re changing a module many times, perhaps you (the programmer) don’t know what it is supposed to do?
                  2. The “size” is another good metric, but I think the authors don’t go far enough: Lines of code and number of statements are nowhere near as good as “source code bytes”. Arthur is supposed to have said only a short program has any chance of being correct, but really it’s scrolling that is getting you into trouble: When data is produced and consumed out of view of each other you literally cannot see the opportunity for the bug.

                  But maybe something not so nice: testing has a negative correlation with defects, but not very much. This is consistent with a lot of other empirical examinations on the subject that had a lot less data, but it still sounds bonkers. People who swear by test driven development know it’s helping them write better code, but the numbers don’t lie, so what is it?

                  My theory is that when you tell someone they need to write tests, they write crappy tests, but if they want to write tests even when they’re not required, then it’s because they want a second way to look at their problem and understand it better. And that’s what we’re striving for.

                  1. 4

                    when you tell someone they need to write tests, they write crappy tests, but if they want to write tests even when they’re not required, then it’s because they want a second way to look at their problem and understand it better.

                    This rings very true to me, for what it’s worth.

                    1. 2

                      Yes, I wrote something similar on Stack Exchange a while back:

                      Testing follows a common pattern in software engineering: testing is claimed to make software better/more “agile”/less buggy/etc., but it’s not really the testing which does this. Rather, good developers make software better/more “agile”/less buggy/etc. and testing is something that good developers tend to do.

                      In other words, performing some ritual like unit testing for its own sake will not make your code better. Yet understanding why many people do unit testing will make you a better developer, and being a better developer will make your code better, whether it has unit tests or not.

                    2. 3

                      If you’re changing a module many times, perhaps you (the programmer) don’t know what it is supposed to do?

                      That or the people asking for the change don’t know what they’re doing and keep changing the requirements. >.<

                      1. 1

                        That can generate new modules rather than changes to existing ones.

                    1. 3

                      To me testing (automated/manual, unit/integration, etc.), type systems, verification, assertions, linting, etc. all affect the confidence I have in a system/program. That’s why I cringe whenever I see claims like “types make testing obsolete”, or “I have enough tests so I don’t need types”, etc. In fact, I even take issue with phrasing like whether/how much testing is “needed”; since there’s usually no actual requirement to do any (or, if there is such a requirement for certain domains, then checking the relevant regulations will be more prudent and informative than going with the opinions of some random internet stranger ;) ).

                      It all lives on a spectrum: there are no well-defined lines telling us how much testing is “enough”, and of course the qualities of a test suite are important (e.g. whether they cover the important/tricky parts, etc.). If I don’t feel confident enough about some code, I’ll happily use whichever method increases my confidence in the most efficient way. Usually that means adding some tests, since test suites are often too small rather than too large. Yet any method gives diminishing returns: we can’t gain much confidence by adding tests to a heavily tested program (especially if we’ve prioritised high-impact areas like end-to-end tests, regression tests, etc.). We might gain more by focusing on, say, types instead, e.g. to ensure user IDs are distinct from order IDs, that SQL is distinct from user input, that invalid states can’t be represented, etc.

                      The same can happen the other way too: whilst types tell us about all cases, rather than just testing individual ones, there’s only a certain amount of type-level computational trickery we can indulge in before it’s more informative to just run the darned thing and make sure our assumptions hold up.

                      Other factors can affect what counts as “enough”, e.g. if something has little chance to cause damage then it might be fine to just run and see what happens; if we’re designing something for specialist/technical users to interact with, we might greatly increase our confidence by guarding certain actions with assertions, so that we crash with an informative message rather than doing the wrong thing; if something’s meant to last for a long time, we might code more defensively and test more of our assumptions; etc.

                      Experience has taught me to always be pessimistic when it comes to estimating confidence, and to keep the path to testing/typing/proving clear of obstacles (e.g. separating calculations from I/O, having small clearly-defined functions/methods, having well-defined data structures rather than piles of key/value nestings, etc.), even if I don’t yet plan to use those things. Even if I don’t think I need them, this can make them cheaper options if I need more confidence further down the line (e.g. pulling some piece of functionality out of a bash script and writing it in Haskell).

                      1. 33

                        hopefully this will get a bunch of FOSS projects off github. they should never have been on there in the first place.

                        1. 7

                          Where should they have been?

                          1. 1

                            I used to host everything on Gitorious. It was around since slightly before GitHub, but then got aquired by GitLab and shut down. It looks like everything was migrated over to GitLab some time later, but by then I was happily self-hosting bare clones with a static file server.

                            1. 1

                              a computer running a vcs

                            2. 10

                              Who are you to tell open source maintainers where they “should” be?

                              If you believe it’s important that open source projects need to use open source tools, you need to start by making the open source tools great, not by lecturing people for using effective tooling to advance their projects.

                              1. 4

                                maintainers of free software should use free tools to support the free software ecosystem, and so that others don’t have to give away their freedom in order to participate. you seem to be implying that the only valid criterion for using a tool is how “effective” it is in the short term; i don’t agree with that.

                                1. 3


                              1. 4

                                I can’t see an “about” page or something to give more info. Is this manually curated, user generated or automatically pulled (from where?).

                                It reminds me of a handful of “match making” sites for devs looking for projects/issues to work on, e.g. https://openhatch.org/search

                                PS: I notice that these links seem to point at github.com. I personally try to avoid getting locked in to such proprietary services; I mostly track issues directly in their repos using http://mrzv.org/software/artemis

                                1. 2

                                  It always bugs me why we need a shell like syntax? For all those shell clones in lisp, we already have an REPL. What those shell clones do is some kind of parsing the shell syntax and calling lisp functions anyway. You are not going to get a posix compatible shell anyway, then why do it?

                                  Is it because unix shell has a superior syntax geared toward CLI? Is it mostly because we can save a few keystrokes?

                                  1. 1

                                    It is an interesting point. The pipe and redirect syntax is very succinct and powerful though.

                                    I really like the idea that of something like this that is mostly the same for simple cases (which probably make up 90%+ of my shell usage), but allows you to dip down to the more powerful syntax very easily when the need arises.

                                    1. 1

                                      The reason I write a lot of shell scripts is the simplicity of invoking commands, reading and writing files, stdio, pipes, branching on exit codes, command substitution, etc.

                                      Doing this with things like Python’s subprocess module is a pain, and often requires highly non-obvious things like spawning extra threads to avoid deadlocks, etc. Helper libraries make life much easier, although I agree that altering the syntax to match sh is usually unneccessary.

                                    1. 8

                                      Pretty ironic that this is on YouTube.

                                        1. 4

                                          See also https://d.tube/, hosted on IPFS.

                                          1. 1

                                            Hosted on github… ;)

                                        1. 2

                                          I want to go through the whole thing later, when I have time, but right off the bat I notice it doesn’t grant trademark licenses. Doesn’t that already automatically disqualify it from being an FSF-approved license? I’m thinking of the Firefox example, though maybe that was DFSG?

                                          (That being said I’ve never had a problem with people protecting trademarks since they basically never have a real effect on the ability to use/modify/etc. the software. It might not fit the letter of the law in terms of the four freedoms but it fits the spirit.)

                                          1. 2

                                            This is the first I’ve heard of the FSF disqualifying licenses for not granting trademarks. Is that a recent decision (e.g. to reduce license proliferation)? I would have thought that’s a separate issue to copyright license approval, since so few FSF-approved licenses grant trademark licenses (MPL, MIT, BSD, …).

                                            When you say “FSF-approved” are you referring specifically to GPL compatibility?

                                            1. 1

                                              Sorry, I was completely wrong! I was thinking of https://en.m.wikipedia.org/wiki/Mozilla_software_rebranded_by_Debian and thought the FSF was involved, but it was just Debian.

                                              1. 3

                                                And Debian never considered Firefox non-DFSG. Mozilla considered Debian to be misusing the trademark (because they alter the source and build from source instead of using upstream binaries) and asked that they stop using the trademarks (for awhile, Debian ships officially-branded Mozilla products again)

                                                1. 3

                                                  Debian was kind of the initial objector in the saga, but they only objected to one specific thing, the Firefox logo. In 2004, they replaced the logo with a freely licensed one in the version they shipped, because Mozilla wouldn’t relicense the logo PNGs/SVGs under a free license. But the browser was still called Firefox. That was the reason for a ‘-dfsg’ suffix in the package’s version number. Those kinds of minor changes are common though. Debian even does it to some GNU packages, because they don’t consider the GNU Free Documentation License with invariant sections to be DFSG-free, so they strip out a few offending info files & tack on a -dfsg suffix.

                                                  You’re right that the name change came from Mozilla though, in 2006, when someone doing a review of the Firefox trademark seems to have objected to everything about Debian’s package: they didn’t like something with an alternate logo shipping under the “Firefox” trademark and for the first time they raised an objection to the patched source (which was patched for non-license reasons) shipping under that name. Which at that point pretty much required a rename, since even people who had thought the logo-copyright issue was petty/unimportant couldn’t accept a “no source patches allowed” condition in a free-software distribution.

                                                2. 2

                                                  Yeah, “Iceweasel” was a Debian thing; IIRC Debian wanted to backport security fixes to stable released, but avoid including any new features. Mozilla didn’t want their “brand” on the less-featureful versions (even though it was all their software…), so trademark shenanigans ensued.

                                                  The FSF do actually push their own Firefox rebrand called GNU Icecat (really imaginative naming all round!). It mostly seems to be about not “promoting” proprietary addons, etc. That doesn’t mean FSF don’t “approve” (in a technical/legal sense) the MPL as a Free Software copyright license, etc. It just means they might not advocate using certain software (Firefox), in favour of something else (Icecat).

                                            1. 5

                                              Very nice descriptions and clear examples. Row polymorphism is brought up a lot when discussing e.g. the deficiencies of Haskell’s built-in records, or algebraic effect systems, but these examples have more of an OO flavour than a functional one.

                                              I’ve not actually used OCaml (although I have used StandardML), but I often hear that its users tend to avoid its OO-style features. Are those examples indicative of how real OCaml users would write code, or would they tend to use some other approach (e.g. modules)?

                                              1. 2

                                                Yeah almost no one uses objects in OCaml nowadays. They use dynamic dispatch for method calls and so tend to be slower than non-object-oriented OCaml code.

                                              1. 6

                                                There seems to be some confusion here around the R in FRP. I’ve usually seen it expand to Functional Reactive Programming, a formulation which I believe dates back to work by Conal Elliot and Paul Hudak in 1997, and whose influence I believe is explicitly acknowledged by frameworks like, um, React. The OotTP paper is the first I’ve seen to use the term Functional Relational Programming, and of course they cite Elliot and Hudak.

                                                There are lots of possible reasons why the OotTP work wasn’t especially influential. Acronym shadowing might be a minor one.

                                                1. 4

                                                  The “what does FRP mean” problem is even worse than that: Elliot’s FRP idea was about “behaviours”, which are values/functions parameterised by time. To ‘run’ these programs we sample them for different time parameters, e.g. game(0), game(1/60), game(2/60), game(3/60), etc. for the frames of a 60 frame per second game. We can even use different sample rates for different parts, e.g. if a game’s physics engine is expensive we might wrap it in a behaviour which never samples the actual engine faster than 10 times per second, and just linearly interpolates between those at other times.

                                                  The problem is, the continuous/parameterised nature of FRP got mostly ignored, so FRP has instead come to mean discrete-time event handling (e.g. Elm, React, …). Elliot’s even distanced himself from the term these days.

                                                  PS: One reason continuous-time FRP didn’t originally catch on was it allows past behaviours to be queried, which prevented implementations from ever garbage-collecting old results, just in case they ever got queried at some point. Newer approaches, like FRP Now fix this issue.

                                                1. 4

                                                  I did some searching after OotTP was posted, and came across this among other things (mostly related to miniKanren, Clojure and project-m36). Yet I don’t think I’ve actually seen the FRelP idea manifest in any of these systems.

                                                  For example, these slides talk about architectures like Elm, which certainly has the feeder/observer part, but (AFAIK) isn’t particularly relational: it’s state is a big, hierarchical sums-of-products datastructure, with functions operating on sub-trees.

                                                  To be honest the feeder/observer part of OotTP was my least favourite: a hack to satisfy the “awkward squad”.

                                                  One of the key aspects of relational (logic) programming is that we don’t have “input” and “output” slots like a function: we can provide whatever data/constraints we have, and read off consistent values from any of the others (it might require a slow search, but OotTP tries not to care about efficiency). Applying this “direction agnostic” idea to I/O reminds me of the “propagators” discussed by Sussman. There, a program is like a circuit or network, where the components maintain some invariant on their connectors: specify some values, the others get adjusted to match. Whilst equivalent to the feeder/observer idea in principle, propagators feel more like an interface and less like a black-box oracle. I can imagine two standalone FRelP systems being connected with propagators, performing some best-effort to impedence match. In contrast, connecting systems with feeders/observers make me think of deep, dark rabbit holes of ontological mismatches, semantic gaps, invariant violation, …

                                                  1. 3

                                                    My intuition for this stuff (also upsampling, style transfer, and many other image to image applications) is that the AI is basically a domain-specific decompression program. With any decompression program, we feed in a small amount of data (e.g. a runlength encoded bitmap image) and get out more data (e.g. a normal bitmap image), but crucially the amount of information doesn’t increase: everything we see in the output was either already present in the input (perhaps in some encoded form), or is an artefact (e.g. the “blockyness” seen in JPEGs). The analogy to decompression isn’t so apparent when we’re turning x-by-y pixels into x-by-y pixels, since the amount of data stays the same, but the idea that we’re “decoding” the input, and that we can’t gain any information (since there’s nowhere for it to come from) is what I’m getting at.

                                                    What worries me with these learned systems is that they’re so specific to the domain that their artefacts are indistinguishable from real content. This is especially true for generative adversarial networks, where the generated data is “100% artefact”, and trained specifically to be indistinguishable from real inputs.

                                                    The failure modes of these systems won’t be things that we’re used to with generic image processing, like “this bush looks blurry” or “the street sign has incorrect colours”, etc. Instead we’ll get very plausible looking images, which turn out to have quite important problems like “image includes a human figure, but it should actually be a trash can”, “streets signs are missing several intersections”, etc. This is very important to keep in mind when thinking of applications for this technology: when the information is sparse or ambiguous, the system will just make something up, and that will be indistinguishable from a real input. One obvious application of this “night vision” in particular is on attack drones, but that may be a very bad idea if it “hallucinates” targets.

                                                    An example of this which comes to mind is the “character substitution” problem on some scanners/faxes/copiers. The idea is to perform OCR on scanned documents, so they can be compressed more easily (e.g. storing “123” instead of all the scanned pixel values of those digits). However, when there’s ambiguity, like a “7” which looks like a “1”, the OCR will pick whichever it thinks is correct (say “1”) and store it just like any other character; losing the information that it could have been something else. When the document gets printed out, a perfect, crisp “1” will appear, which is indistinguishable from all of the correct characters.

                                                    1. 3

                                                      As a general rule of thumb, I try to always store the confidence level or accuracy estimate of anything processed by machine. For example, working in this domain of computer vision, I might process images to denoise and find contours then use SVM to classify what’s in the image and only store tags that have, say, 0.9 confidence (out of 1.0). The important step is to store metadata, including the list of tags, with their confidence score and anything else that pertains to accuracy, such as the exact kernel or model that was used. This doesn’t solve the problem, but provides insight as to what happened, how to recreate it, and what other output is now suspect.

                                                    1. 7

                                                      I can’t speak for his personality, but I’m certainly a big fan of Schmidhuber’s work. It’s refreshing to see the stream of small, concrete results in AI (e.g. machine translation, traffic sign identification, etc.) scattered with the occasional big, abstract idea (goedel machines, speed prior, etc.). I don’t necessarily agree with some of the more philosophical musings, but I can respect his willingness to take extrapolations seriously.

                                                      One thing lacking in this article is giving credit to the laundry list of students and collaborators that have worked with Schmidhuber, e.g. Sepp Hochreiter in the case of LSTM. In research it’s rarely clear from the outside how much each co-author contributed to a result, but when I see Schmidhuber’s name on all these impressive papers I’d sooner assume that he’s an effective facilitator, coordinator, “ideas man”, sounding board, etc. rather than a singular genius who’s swept up unwitting co-authors in his wake ;)

                                                      1. 18

                                                        As a counterpoint to the author’s sweeping generalisation, I don’t think I’ve ever used an application based on Electron. I’ve certainly never used Slack, Hyper, VSCode, etc. which the author says they spend most of their time in.

                                                        My most used programs are probably Emacs, st, Conkeror, Firefox, Pidgin, VLC, cmus, Basket, KBibTeX, …

                                                        I know I’m certainly not “typical”, but I doubt the author is either.

                                                        1. 2

                                                          Thing is that many people out there are using these apps, and this creates network effects. This is especially so for any communication apps like Slack. While you might be able to avoid these apps personally, it’s becoming increasingly difficult to do for the vast majority of people out there. Another aspect to consider is that many apps simply wouldn’t exist on smaller platforms like Linux without Electron. So one very positive aspect of using the web stack is that it helps avoid platform lock in.

                                                          1. 1

                                                            I don’t disagree with what you’re saying in general, although I just want to make clear w.r.t. my anecodote above that I’m not actively avoiding such programs; I’ve just never encountered them, faced a problem that they would help solve, etc.

                                                            Whilst I know it’s pithy, those particular examples do seem a little silly to me: there’s no shortage of terminals (Hyper) or text editors (VSCode). Messaging silos (Slack) are certainly a problem; although I think that’s more societal than technological at this point.

                                                            1. 1

                                                              I think the interesting part with stuff like VSCode is that you have a canvas right in the editor. This allows you to start doing stuff like this very easily. With proto-repl-charts, you could query your database via the REPL, get some data back, and chart it to see trends as an example.

                                                        1. 3

                                                          I didn’t realise that third-party clients were still usable for Twitter, since they seemed to disable most API functionality around 2010 (i.e. once they’d become popular, due in no small part to their “openness” for integrations/clients/bots/etc.). In other words, Embrace/Extend/Extinguish.

                                                          1. 1

                                                            I believe existing clients were grandfathered in.

                                                            The client I use is a fork of ttytter and it’s possible to install and use the streaming API from it (I’m not sure if that’s an API that will be shut off).

                                                            1. 1

                                                              Yes, this is primary measure against alternative clients (if it’s still applies): new oauth tokens are just denied once client gets some number of logged in users.

                                                              Push notifications are far from being an essential feature. It’s more facebookish thing for “slot machine-like” behavior everyone is talking about now, intended to use with official client. I think users of alternative clients are usually against flood of notifications.

                                                            1. 3

                                                              Guix is a very cool project. I’m rather zealous when it comes to FOSS, I’m a big fan of Scheme and I’m already a NixOS user. I should switch over to GuixSD at some point, but the only “spare” machines I have to try it on are RaspberryPis, where GuixSD isn’t supported and Guix give segmentation faults (wrong ARM variant, I suppose).

                                                              Still, it’s great to see efforts like this; especially those which bridge the gap with ‘traditional’ systems. There’s a temptation for projects to build up elaborate “ecosystems”, where the approach to compatibility is to replace or cannabalise rather than work with existing solutions. SystemD is one example, but it’s also true of Nix (NixOS distro, deployed with NixOps, built with Hydra, etc.).