Locklin on science

Woo for its own sake

Posted in Design, tools by Scott Locklin on January 8, 2021

Software development is a funny profession. It covers people who do stuff ranging from register twiddling in device drivers and OS guts, to people who serve web content, to “big data” statisticians, to devops infrastructure, to people who write javascript and html front ends on electron apps. To a certain extent, software engineering is grossly underpaid. If software engineers were allowed to capture more of the value they create, we’d have vastly fewer billionaires and more software engineers with normal upper middle class lifestyles, such as houses owned in the clear and successful reproductive lifecycles. The underpaid are often compensated in self esteem.

By “compensated in self esteem” I don’t mean they have high self esteem; I mean the manager saying “dude yer so fookin smart brah” kind. This is the same brainlet payment system in place in the present day “hard sciences” with people writing bullshit papers nobody cares about, or, like, journalists and other “twitter activists” who believe themselves to be intellectual workers rather than the snitches and witch hunters they actually are. Basically, nerd gets a pat on the head instead of a paycheck.

Once in a while, independent minded programmers demand more. They may or may not be “so fookin smart,” but they think they are. Their day jobs consist of unpleasant plumbing tasks, keeping various Rube Goldberg contraptions functioning and generally eating soylent and larva-burgers and claiming to like it. As such, most programmers long to do something fancy, like develop a web server based on Category Theory, or write a stack of really cool lisp macros for generating ad server callbacks, or add some weird new programming language of dubious utility to an already complex and fragile stack.

Allowing your unicycle-riding silver pants mentat to write the prototype in Haskell to keep him from getting a job at the Hedge Fund may make some HR sense. But if you’re going to rewrite the thing in Java so a bunch of offshore midwits can keep it running, maybe the “adulting” thing to do is just write it in Java in the first place.

I’m not shitting on Haskell in particular, though there is an argument to be made for looking askance at using it in production. Haskell is mostly a researchy/academicy language. I don’t know, but I strongly suspect its run of the mill libraries dealing with stuff like network and storage is weak and not fully debugged. Why do I suspect this? In part from casual observation, but also from sociology. Haskell is a fancy language with people doing fancy things in it. One of the valuable things about popular but boring languages is that the code has been traversed many times, and routine stuff you’re likely to use in production is probably well debugged. This isn’t always true, but it’s mostly true. The other benefit to boring languages is people concentrate on the problem, rather than the interesting complexities of the language itself.

You see it in smaller ways too; people who feel like every line of code has to be innovative: new elliptic curves, new network protocols, new block ciphers, new ZNP systems; to a crucial money oriented application that would have been really cool and have a much smaller attack surface if you had bestowed only one innovation on it. I guess this sort of thing is like bike-shedding or Yak-shaving, but it’s really something more perverse. If you have a job doing shit with computers, you are presumably solving real world problems which someone pays for. Maybe, you know, you should solve the problem instead of being a unicycle riding silver pants juggling chainsaws.

You see a lot of it in the cryptocurrency community, in part because there is enough money floating around, the lunatics are often running the asylum, in part for its undeserved reputation as being complicated (it’s just a shared database with rules and checksums; Bram more or less did the hard part in the summer of 2000 while my buddy Gerald was sleeping on his couch). For example: this atrocity by Gnosis. Gnosis is an interesting project which I hope is around for a long time. They’re doing a ton of very difficult things. Recently they decided to offer multi-token batch auctions. Why? I have no freaking idea. It’s about as necessary and in demand as riding to work in silver pants on a unicycle. Worse though: from an engineering perspective, it involves mixed integer programming, which is, as every sane person knows, NP-hard.

This is a danger in putting software developers or programmers in charge. These guys are often child-like in their enthusiasm for new and shiny things. Engineers are different: they’re trying to solve a problem. Engineers understand it’s OK to solve the problem with ephemeral, trashy, but fast-to-market solutions if the product manager is going to change it all next week. Engineers also plan for the future when the software is critical infrastructure that lives and fortunes may depend on. Engineers don’t build things that require mixed integer programming unless it’s absolutely necessary to solve a real world problem. If they juggle on unicycles, they do it on their own time; not at work.

Consider an engineering solution for critical infrastructure from a previous era; that of providing motive power for small fishing boats. Motors were vastly superior to sail for this task. In the early days of motorized fishing, in some cases until fairly recently, there was no radio to call for help if something goes wrong. You’re out there in the vastness on your own; possibly by yourself, with nothing but your wits and your vessel. There’s probably not much in the way of supply lines when you’re at shore either. So the motors of the early days were extremely reliable. Few, robust moving parts, simple two stroke semi diesel operation, runs on any fuel, requires no electricity to start; just an old fashioned vaporizing torch which runs on your fuel; in a pinch you could start a fire of log books. You glance at such a thing and you know it is designed for robust operation. Indeed the same engines have been used more or less continuously for decades; they only turn at 500 rpm, and drive the propeller directly rather than through a gearbox.

Such engines are useful enough they remain in use to this day; new ones of roughly this design are still sold by the Sabb company in Norway. They’re not as environmentally friendly or fuel efficient as modern ones (though close in the latter measure), but they’re definitely more reliable where it counts. When you look at this in the engine room, you are filled with confidence Mr. Scott will keep the warp drives running. If you find some jackass on a unicycle back there (who will probably try to stick a solar powered Sterling engine in the thing), maybe not so much.

I don’t think long term software engineering looks much different from this. Stuff you can trust looks like a giant one-piston semidiesel. You make it out of well known, well traversed and well tested parts. There are a couple of well regarded essays on the boringness yet awesomeness of golang. Despite abundant disagreement I think there is a lot to that. Nobody writes code in golang because of its extreme beauty or interesting abstractions. It is a boring garbage collected thing that looks like C for grownups, or Java not designed by 90s era object oriented nanotech fearing imbeciles. I think it bothers a lot of people that it’s not complicated enough. I’m not shilling for it, but I think anyone who overlooks it for network oriented coding because it’s boring or they think it’s “slow” because it doesn’t use functors or borrow checkers or whatever is a unicycle riding idiot though. Again looking at blockchain land; Geth (written in golang) has mostly been a rock, where the (Rust) Parity team struggles to maintain parity with feature roll outs and eventually exploded into multiple code bases the last time I checked. There’s zero perceptible performance difference between them.

There’s a Joel Spolsky on (Peter Seibel interview with) JWZ which I always related to on complexification of the software process:

One principle duct tape programmers understand well is that any kind of coding technique that’s even slightly complicated is going to doom your project. Duct tape programmers tend to avoid C++, templates, multiple inheritance, multithreading, COM, CORBA, and a host of other technologies that are all totally reasonable, when you think long and hard about them, but are, honestly, just a little bit too hard for the human brain.

Sure, there’s nothing officially wrong with trying to write multithreaded code in C++ on Windows using COM. But it’s prone to disastrous bugs, the kind of bugs that only happen under very specific timing scenarios, because our brains are not, honestly, good enough to write this kind of code. Mediocre programmers are, frankly, defensive about this, and they don’t want to admit that they’re not able to write this super-complicated code, so they let the bullies on their team plow away with some godforsaken template architecture in C++ because otherwise they’d have to admit that they just don’t feel smart enough to use what would otherwise be a perfectly good programming technique FOR SPOCK. Duct tape programmers don’t give a shit what you think about them. They stick to simple basic and easy to use tools and use the extra brainpower that these tools leave them to write more useful features for their customers.

I don’t think this captures the perverseness and destructiveness of people who try to get fancy for no reason, nor do I think JWZ was a “duct tape programmer” -he was an engineer, and that’s why his products actually shipped.

I say this as an aficionado of a couple of fancy and specialized languages I use on a regular basis. I know that it is possible to increase programmer productivity through language choice, and often times, runtime performance really doesn’t suffer. Languages like OCaML, APL and Lisp have demonstrated that small teams can deliver complex high performance software that works reliably. Delphi and Labview are other examples of high productivity languages; the former for its amazing IDE, and the latter for representing state machines as flow charts and providing useful modules for hardware. The problem is that large teams probably can’t deliver complex high performance software that works reliably using these tools. One also must pay a high price up front in learning to deal with them at all, depending on where you come from (not so much with Labview). From a hiring manager or engineer’s perspective, the choice to develop in a weird high productivity language is fraught. What happens if the thing crashes at 4 in the morning? Do you have enough spare people someone can be raised on the telephone to fix it? What if it’s something up the dependency tree written by an eccentric who is usually mountaineering in the Alps? For mission critical production code, the human machine that keeps it running can’t be ignored. If your mentat gets hit by a bus or joins the circus as a unicycle juggler and the code breaks in production you’re in deep sheeyit. The idea that it won’t ever break because muh technology is retarded and the towers of jelly that are modern OS/language/framework stacks are almost without exception going to break when you update things.

 

The “don’t get fancy” maxim applies in spades to something like data science. There are abundant reasons to just use Naive Bayes in production code for something like sentiment analysis. They’re easy to debug and they have a trivial semi-supervised mode using the EM algorithm if you’re short of data. For unsupervised clustering or decomposition it’s hard to beat geometric approaches like single-linkage/dbscan or PCA. For regression or classification models, linear regression is pretty good, or gradient boost/random forest/KNN. Most of the time, your real problem is shitty data, so using the most accurate  tool is completely useless.

Using the latest tool is even worse. 99 times out of 100, the latest woo in machine learning is not an actual improvement over existing techniques. 100% of the time it is touted as a great revolution because it beat some other technique … on a carefully curated data set. Such results are trumpeted by the researcher because …. WTF else do you expect them to do? They just spent a year or two developing a new technique; the professor is trying to get tenure or be a big kahuna, and the student is trying to get a job by being expert in the new technique. What are they going to tell you? That their new technique was kind of dumb and worthless?

I’ve fallen for this a number of times now; I will admit my sins. I fooled around a bit with t-SNE while I was at Ayasdi, and I could never get it to do anything sane. I just assumed I was a moron who couldn’t use this advanced piece of technology. No, actually, t-SNE is kind of bullshit; a glorified random number generator that once in a while randomly finds an interesting embedding. SAX looked cool because it embodied some ideas I had been fooling around with for almost a decade, but even the author admits it is horse shit. At this point when some new thing comes along, especially if people are talking about it in weeb-land forums, I pretty much ignore it, unless it is being touted to me by a person who has actually used it on a substantive problem with unambiguously excellent results. Matrix profiles looks like one of these; SAX dude dreamed it up, and like SAX, it appears to be an arbitrary collection of vaguely common sense things to do that’s pretty equivalent to any number of similar techniques dating back over the last 40 years.

There are innovations in data science tools. But most of them since boosting are pretty marginal in their returns, or only apply to corner cases you’re unlikely to encounter.  Some make it easier to see what’s going on, some find problems with statistical estimators, but mostly you’re going to get better payoff by getting better at the basics. Everyone is so in love with woo, the guy who can actually do a solid estimate of mean differences is going to provide a lot more value than the guy who knows about the latest PR release from UC Riverside.

Good old numerical linear algebra, which everyone roundly ignores, is a more interesting subject than machine learning in current year.  How many of you know about using CUR decompositions in your PCA calculations? Ever look at some sloppy PCA and wonder which rows/columns produced most of the variance? Well, that’s what a CUR decomposition is. Obviously looking at the top 3 most important of each isn’t going to be as accurate as looking at the regular PCA, but it sure can be helpful. Nuclear Norm and non-negative matrix factorizations all look like they do useful things. They don’t get shilled; just quietly used by engineering types who find them helpful.


I’m tooling up a small machine shop again, and it makes me wonder what shops for the creation of physical mechanisms would look like if this mindset were pervasive. The archetypical small shop has always had a lathe in it. Probably the first thing after you get tired of hacksawing up material; a bandsaw or powered hacksaw. Small endmill, rotary sharpener, and you’re off to the races; generally building up more tooling for whatever steam engines, clocks or automatons you feel like building. I’m imagining the archetypical unicycle-juggler buying a shop full of solid printers and weird CNC machines and forgetting to buy cutters, hacksaws, files and machinist squares. As if files and machinist squares are beneath them in current year.

34 Responses

Subscribe to comments with RSS.

  1. Mischa said, on January 8, 2021 at 6:35 pm

    Yeah we just stick with boring shit https://blog.jetbridge.com/framework/

  2. Ben Gimpert said, on January 8, 2021 at 7:18 pm

    If only there was a norm for skilled workers collectively demanding non-headpat pay… Or maybe bargaining for it. Yeah.

    Anyway! I think the original transparent, simple, maintainable, well-trodden engineering solution is the shell script right? Tiny unixen tools that do one thing right strung together with the deadsimple pipe metaphor.

    • Scott Locklin said, on January 9, 2021 at 12:25 pm

      I dunno man, that sounds kinda racist somehow. Maybe you should rephrase that as “can I have another larvaburger?”

      I remember when A9’s recommendation engine was basically a shell script that ran on someone’s desktop. For all I know it still is.

    • Anonymous said, on January 9, 2021 at 2:49 pm

      >I think the original transparent, simple, maintainable, well-trodden engineering solution is the shell script right?

      Is that irony or post-irony, I can’t tell:) Actual Unix-way coding is quirks all the way down. Dataflow programming though, which it aspires to be, is Actually Good.

  3. asciilifeform said, on January 8, 2021 at 8:03 pm

    I’m an Ada aficionado. For those unfamiliar, this is arguably the archaetypical “boring” language, where standards actually exist on dead tree, after ratification by committees where members sport metre-long beards. The interesting thing is that — unlike e.g. CPP — one in fact can usefully program entirely in the language described in the standard.

    And so from my perspective e.g. Google’s “Go” language is, if not exactly the same kind of “unicycle” as Haskell, then simply not distinguishable with the naked eye in “unicyclicity”.

    Haskell is a concoction of academics, whose objective is to “look clever”; while Go is an attempt (AFAIK quite successful) to manacle Google’s programmers to their workplace. (Later copied by Apple in “Swift”; and I expect we will see more pseudo-“open” saltmine-proprietary languages in the future.)

    • Scott Locklin said, on January 9, 2021 at 1:05 pm

      I had considered attempting to take SPARK for a spin, but I have too many hobbies. Your FFA thing is a masterpiece of literate coding. Of course it will probably be roundly ignored.

      Golang isn’t so bad; it’s dumb and you can write the rules on an index card; goroutines also seems to work for people. I don’t think Google actually uses it much, which is typical of current year google. There’s nothing about it you can point to as being special; any midwit should be able to contribute to a project written in it.

      • asciilifeform said, on January 9, 2021 at 6:51 pm

        > will probably be roundly ignored

        Indeed I doubt that more than a dozen people, to date, have read any substantial portion of FFA. And perhaps two dozen more could be turned up somewhere, who in principle could be persuaded to.

        IMHO, FFA however continues to work just fine as a practical demonstration — for anyone who gives a damn (or merely curious) — of what computer programs would look like if the field were to be taken forcibly back from poseurs and deskillers and made to resemble something like bridge-building.

    • Anonymous said, on January 9, 2021 at 3:21 pm

      >I’m an Ada aficionado. For those unfamiliar, this is arguably the archaetypical “boring” language, where standards actually exist on dead tree, after ratification by committees where members sport metre-long beards.

      I use Ada for system programming, for any serious programming basically, and all the good things I can say about it begin with ‘compared to other languages’. On its own though… it’s a bureaucratic designed-by-committee waterfall-era monstrosity. My main problem with it is that it poses as an advanced language (has generics, contracts, can actually eval things at compile time) but if you treat it as such you’re up for some pain. I wish it was promoted more honestly as a better C. C is dumb and so are all the ‘advanced’ features of Ada. The standard is not that helpful because written in the best traditions of legalese and man pages. For an actively maintained language, I think Ada has no excuse to be as bad as it is, but oh well. At least it’s not one of those LLVM-based languages with horrid compile times. Regular breaks for improved mental health are still necessary though.

      • asciilifeform said, on January 9, 2021 at 5:30 pm

        > it poses as an advanced language (has generics, contracts, can actually eval things at compile time) but if you treat it as such you’re up for some pain

        I might be in the minority in this respect, but I have found that Ada — including the more “exotic” features such as generics — in fact works as advertised. And that the Ada standard, while tricky for novices to read, in fact describes the semantics of the language usefully and without ambiguity.

        > I think Ada has no excuse to be as bad as it is

        It is unclear to me just where it is supposedly “so bad”. Though the “frightening” reputation of the language is useful, IMHO, in that it seems to work well in repelling “hipsters”, who managed to poison every ecosystem which could not keep them away — including e.g. Common Lisp’s.

        • Anonymous said, on January 10, 2021 at 1:03 am

          >I might be in the minority in this respect, but I have found that Ada – including the more “exotic” features such as generics – in fact works as advertised.

          type Pixel_Array is array (Positive range ) of Unsigned_32;
          
          type Framebuffer (Width, Height: Positive) is record
          
            Pixels: Pixel_Array( 1 .. Width * Height );
            --Error: discriminant in constraint must appear alone. This works though:
            --Pixels: Pixel_Array( 1 .. Width );
          
          end record;
          

          The problem with Ada is that you can’t develop intuition for when it’s advanced features stop working. I was actually surprised how much it allows to do at compiletime but then the above happened and I was like… u wot m8? I mean, a language that has `case` expressions and array slices somehow can’t multiply two numbers? Or consider variant records: the `case` statement works much like in regular code except you can’t have fields after it. I have a variant record representing different kinds of graphical widgets. They all have the same header fields like `Kind`, `Position`, etc. followed by a body, followed by a label (string). The body part is variant and depends on the kind and for memory layout reasons the label follows the body. I had to resort to address arithmetic to deal with the label and it’s hard to imagine, based on the rest of the language, why Ada can’t handle this. Maybe there’s a valid reason, I haven’t thought about it much, but it sure is not conveyed through the syntax. There’s a bunch of similar surprises so if you start out like “I’m gonna encode all my invariants in my types!!!11” …well, no, you’re not. Which is extremely weird given that the language has actual type invariants.

          >And that the Ada standard, while tricky for novices to read, in fact describes the semantics of the language usefully and without ambiguity.

          Wait, why should it be tricky for novices to read? There’s nothing fundamentally difficult about like, arrays, right?

          >An array is characterized by the number of indices (the dimensionality of the array), the type and position of each index, the lower and upper bounds for each index, and the subtype of the components. The order of the indices is significant.

          >A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; this range of values is called the index range. The bounds of an array are the bounds of its index ranges. The length of a dimension of an array is the number of values of the index range of the dimension (zero for a null range). The length of a one-dimensional array is the length of its only dimension.

          Much of the trickiness comes from empty blabbling like above which can be either thrown away or reduced to a couple of sentences. The only reason for its existence, I imagine, is to please some bureaucrats, much like ‘objects in the mirror are behind you’. Actually important information, like in a typical man page, can be hidden somewhere inbetween and not visually emphasized. How should a standard be structured? First you say succinctly and informally what you’re describing then build up intuition with examples then solidify that with formal definitions then add more examples to ensure retention, if needed. How does the standard read? Like a typical ToS that starts with ‘Company is … User is … ‘ and by the time you get to what you came for your brain falls out. In actually complex cases it’s much easier to just try things out or google than to comb through the standard.

          >It is unclear to me just where it is supposedly “so bad”.

          The general code structure, for example. How should code read? First you show the meat, then you list the dependencies. Like in math, `f = x + z where x …` This way you’re not burying the lead and when you get to the dependencies they are contextualized by the meat. What Ada code reads like? First you skip a wall of meaningless definitions to get to the meat, then jump aaaall the way back to the start of that wall, then aaall the way back again. I’m sure every bureaucrat and waterfall-lover that reads such code feels very satisfied. A real example: I have a record representing a node in a p2p network. There’s a pair of handlers (pointers) in the record, one for handling input data and the other for generating output data. Now, each instance of the program listens on some port and tries to connect to known nodes. So the node record is actually variant and can be used to represent both a (local) server and a (remote) client. From a code reuse perspective this makes much sense but there’s a catch. Because a server can effectively only read (not real data but sockets via accept(2)) it also make sense to tighten up the signature of the output handler such that it only accepts client nodes, which… doesn’t seem feasible. Or at least requires levels of fuckery I’m not sure I have mental health to endure. The root cause of the problem is that I can’t define the node record (in full) before the handler types. The moral of the story, just as above, is that you can be doing something seemingly normal but then suddenly hit a wall. Maybe some guy at AdaCore knows the answer and it’s actually simple, but I don’t work at AdaCore, I’m just trying to get shit done.

          I’m not gonna bang on ‘Max_Size_In_Storage_Elements or how child packages work or how printf debugging works or a million other papercuts. (Btw, why is it storage elements in some places and storage units in others?) Ada is an old language with a ton of cruft, designed in full before the first implementation, influenced by a highly bureaucratic organization. I quite agree with the following: “the kindest thing that has been said about it is that there is probably a good small language screaming to get out from inside its vast, elephantine bulk.” But hey, at least it’s not Rust, right?

          >Though the “frightening” reputation of the language is useful, IMHO, in that it seems to work well in repelling “hipsters, who managed to poison every ecosystem which could not keep them away – including e.g. Common Lisp’s.

          A better solution is to actually have balls. IIRC there was some community-driven bullying of the Clojure team to make Clojure more community-driven to which Hickey said “no” and the bullies gave up.

          • Scott Locklin said, on January 10, 2021 at 12:18 pm

            > Pixel_Array( 1 .. Width * Height );

            I mean, wouldn’t this blow up because you can’t tell if Width*Height overflows at runtime? Go easy on me, I’ve never really looked at it.

            The cruftiness of Ada in the large made me more interested in the SPARK subset. But again, I don’t need more hobbies especially involving computers. High integrity stuff is interesting (especially with SPARK as you seem to get high performance for free), but thoroughly outside my present professional interests.

            • asciilifeform said, on January 10, 2021 at 5:16 pm

              > The cruftiness of Ada in the large made me more interested in the SPARK subset.

              FWIW, FFA is written in an even more restricted subset of Ada. (Presently I do not use SPARKism, preferring human-readable proofs — made practical by the branch-free reformulation of all of the necessary moving parts — and maximally-compact programmatic implementation instead.)

            • Anonymous said, on January 12, 2021 at 7:38 am

              >I mean, wouldn’t this blow up because you can’t tell if Width*Height overflows at runtime?

              I’ve never run into this myself but Ada is supposed to catch that. Only so called modular types are allowed to overflow, it’s part of their semantics and modulo reduction is applied to overflowing values.

          • asciilifeform said, on January 10, 2021 at 5:01 pm

            What Ada actually “wants” you to do, is, e.g.:

            Pixel_Count : constant Positive := Width * Height;
            Pixels : Pixel_Array( 1 .. Pixel_Count );

            … and I can’t think of any reason to object — it makes the code palpably more readable. I delight in all the various ways in which Ada clips the wings of “idiomatic C” aficionados. (E.g., it has no equivalent of preprocessor macros; no ifdefs; and the curator of a project can even permaban almost arbitrary subsets of the language, including all pointerism.)

            > Wait, why should it be tricky for novices to read?

            It’s a standard — meant to be read by compiler-writers (and occasional power users who walk the razor’s edge of the permissible.) For noobs there is e.g. Barnes “Ada 2012”.

            > There’s nothing fundamentally difficult about like, arrays, right?

            With all respect, this is untrue. Ada (as I suspect you know) has civilized (as opposed to “C-style”, “let it crash and burn”) arrays, where the bounds can be any integers (e.g. 4 .. 11) , slices may be assigned to one another (including overlapping, and does The Right Thing) and an appropriate exception is raised if the assignment cannot be carried out as-written at runtime for whatever reason. AFAIK the only other standardized programming language which has these, is Common Lisp. Ergo, something, evidently, “is difficult about arrays.”

            > Much of the trickiness comes from empty blabbling like above which can be either thrown away or reduced to a couple of sentences. The only reason for its existence, I imagine, is to please some bureaucrats, much like ‘objects in the mirror are behind you’.

            Can you shorten the given passage in a way which preserves 100% of the meaning? Or do you believe that this is somehow optional? Why not then simply use a programming language “defined by manpages” and napkin scribbles of a “benevolent dictator” ? There are so many to choose from. How did you end up with Ada?

            > What Ada code reads like? First you skip a wall of meaningless definitions to get to the meat, then jump aaaall the way back to the start of that wall

            Why are there “meaningless” definitions in your program? How is it the fault of Ada? (And I cannot resist to ask: are e.g. C headers, somehow, “meaningful” ?)

            > Because a server can effectively only read (not real data but sockets via accept(2)) it also make sense to tighten up the signature of the output handler such that it only accepts client nodes, which… doesn’t seem feasible. Or at least requires levels of fuckery I’m not sure I have mental health to endure. The root cause of the problem is that I can’t define the node record (in full) before the handler types.

            This is what “with private” is for (see an example of mine re: usage.)

            > …a ton of cruft… …there is probably a good small language screaming to get out from inside its vast, elephantine bulk.

            Admittedly not a scientific measure, but Ada (including Barnes, and the complete manuals for 2012 and earlier) takes up scarcely 1/3 of a shelf in my office. While C++ occupies the other 2/3 of that shelf.

            And I wonder what a complete dead tree spec for all of e.g. Python and its libraries would look like. Why is it that no one complains of the “elephant” there ?

            How much would a total description of JS, HTML5, etc. as-implemented in e.g. Chrome, weigh? Would it fit in your house?

            There is gnarl in Ada, like everywhere else. But I have found that most of what novices complain about, actually consists of justifiable “cold-turkey tremors of the recovering C addict”.

            > A better solution is to actually have balls. IIRC there was some community-driven bullying of the Clojure team to make Clojure more community-driven to which Hickey said “no” and the bullies gave up.

            IMHO Hickey himself is part of the problem. Clojure itself amounts to an embrace-and-extinguish attack against the Common Lisp community.

            • Anonymous said, on January 12, 2021 at 11:44 am

              >I can’t think of any reason to object — it makes the code palpably more readable.

              I can think of one: obscuring verbosity. Giving a name to every little detail makes the essence harder to see. In general I feel like Ada designers were like we heard you like verbosity so we put verbosity into your verbosity. Printing anything involving more than a couple variables easily turns what would be a one-liner into a multiline monstrosity that you need to carefully align to reduce the noise.

              Speaking of the example, using a two-dimensional array would also solve my problem, however I didn’t know at the time what memory layout Ada uses for those. The standard wasn’t forthcoming, unsurprisingly, and I couldn’t find much on the web. Later I did find the relevant info in the standard, by grepping the HTML. Turns out it’s tucked away inside an ‘Implementation Advice’ section of one of the pages. Not only its location can’t be guessed from the TOC, it’s also not discoverable though the index, which is absurd. But anyway, for this important, from a system programming perspective, characteristic I’m relying on implementers heeding some… implementation advice. Such standard, much wow.

              >I delight in all the various ways in which Ada clips the wings of “idiomatic C” aficionados.

              Of course you do. Look, I have no problem with BDSM folks just because I personally don’t like getting gagged and whipped but I do have a problem with those who say that this is somehow ‘normal’ and everybody should like it. There are defenses against mediocre programmers like forbidding pointers/pointer arithmetic but professionals need these tools anyway and the more cumbersome it is to write unsafe code the less mental power remains available for checking its correctness. And if you somehow think that 99.99999% of such cases can be resolved within the typesystem, go do some osdev. Part of the reason C remains popular despite being a minefield is that when you’re doing something dangerous it (mostly) doesn’t get in your way. Give me a warning every time I do something like that but keep your hands away as you definitely lack the clairvoyance to know what a system programmer might actually need. Ada gets this (almost) right btw as all the lowlevel stuff like ‘Address, ‘Position, etc. is readily available.

              >it has no equivalent of preprocessor macros; no ifdefs; and the curator of a project can even permaban almost arbitrary subsets of the language

              Those are actually good things.

              >It’s a standard — meant to be read by compiler-writers

              …and compiler-writers are humans and as such don’t benefit from trickiness. All good texts that are supposed to communicate complex ideas precisely make use of informal language and care about building intuition. This is true for everything from technical standards to math papers. There’s however a culture (which, as I understand, you represent) of people who consider human squishiness to be below them. Talk to any Git aficionado, Unix aficionado, C aficionado, they will all say that you just need to git gud and for noobs there are various (despicable) training wheels.

              >Can you shorten the given passage in a way which preserves 100% of the meaning?

              “An array is characterized by the number of indices […], the type and position of each index, the lower and upper bounds for each index, and the subtype of the components.” This just lumps a bunch of info into one big list for the sole (bureaucratic) purpose of having such a list. How is one gonna read about arrays and be like “I wonder if arrays are characterized by the lower and upper bounds of their indices? What if they aren’t?”
              “The order of the indices is significant.” Duh.
              “A one-dimensional array has a distinct component for each possible index value.” What is it with “distinct”? Does the concept of an array suggest they can be somehow not distinct? “A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order).” Yuck! Then there’s redundant terminology, “range” vs “bounds”, which leads to a hole unnecessary sentence “The bounds of an array are the bounds of its index ranges.” While technically these concepts are distinct, only one is necessary here. This is how the standard grinds your will to read it into dust:) A sentence here, a couple of terms there, and by the end of the page your brain is chuckfull of this word salad.

              >Why are there “meaningless” definitions in your program?

              They are meaningless until contextualized by the meat. It’s more pronounced in package bodies than in specs. Also, a language that can’t resolve forward references within the same compilation unit clearly does not belong in the 21st century, yet here we are.

              >This is what “with private” is for (see an example of mine re: usage.)

              Will have a look later.

              >Ada (including Barnes, and the complete manuals for 2012 and earlier) takes up scarcely 1/3 of a shelf in my office. While C++ occupies the other 2/3 of that shelf.

              Does that exonerate Ada somehow? Or go against my initial statement that all the good things I can say about it begin with ‘compared to other languages’?

              >Why is it that no one complains of the “elephant” there ?

              You sure? There’s plenty of Python critique out there.

              >But I have found that most of what novices complain about, actually consists of justifiable “cold-turkey tremors of the recovering C addict”.

              FWIIW as an Ada novice I mostly complained about its UX, not about “why can’t shoot myself in the foot like in C?” Its inconsistency (e.g. ‘Size is in bits but ‘Position is in bytes), its implicitness. I mean, you actually need to decipher the below:

              generic 
                type A is private;            --'private' doesn't say 'any'
                type B is ();               --doesn't quite say 'discrete', does it?
              ...
              

              This trick is of the same nature. Using an Import pragma (an FFI mechanism) to disable an overlay’s default initialization is incongruent with the semantics of overlays. With all these you need to stop and think. Tricks.

              >IMHO Hickey himself is part of the problem.

              Hickey runs Clojure as his personal project, like he should. I dunno much about the attack you mentioned but if true the problem is with how Common Lisp is run, not so much with Hickey.

  4. Walt said, on January 8, 2021 at 10:44 pm

    The term “data science” is somewhat enraging because all scientists and engineers deal with data.

    Your critique seems to apply to computer architectures as well.

    • CS said, on January 11, 2021 at 8:18 pm

      ASIC design is rife with new tool woo-ism. The fact of the matter is the vast majority of computer architecture is pretty straightforward, but that doesn’t keep a lot of people employed.

      RISC-V will continue to grow in popularity as companies realize this.

      • Walt said, on January 12, 2021 at 12:27 am

        I wonder if fabless semiconductor companies feed into this. Their only reason for existence is design and they only real IP they own are the design tools. US tech companies also only want to invest in software.

        • CS said, on January 12, 2021 at 5:58 pm

          I don’t think so. In fact I think some fabless companies are doing some of the most exciting work.

          As for software, that’s true, but computing is moving into a pretty exciting place for the first time in a decade or two. General purpose is reaching its end. This is why I think RISC-V is likely to result in some neat stuff. Simplify the general purpose portion, go HAM on acceleration protocols.

          I’m halfway through that lecture you posted. It’s quite good. But also a really scary endeavor to do an SoC-level ISA!

          • Walt said, on January 13, 2021 at 8:32 pm

            RISC-V looks pretty interesting. Thanks. It should help when California undergoes its green revolution energy storage and I have far less power everyday.

  5. Anonymous said, on January 9, 2021 at 6:25 am

    Hacker shits never get that technology is about people and get really annoyed when somebody points that out. First computers were built to solve problems of physical nature so even when hackers were involved they were still grounded by that nature. But once computers became powerful enough that virtual worlds could be constructed and once the influx of hackers and money people became unstoppable hackers got really unhinged. The stuff they like about technology — all the complexity that makes even a conceptually simple system an intricate maze, all the quirks one must know to use such a system efficiently, the emergent nature of it all — that’s exactly what makes an interesting game. Somebody compared Linux to an MMO, I think that’s actually correct. The foreword to Hacker’s Delight really captures that spirit. Getting lost in bits and bytes for the sheer pleasure of it. I mean I’m autistic, I do understand. Fuck that noise though: if a regularly used high-level operation needs some bit-fuckery to be implemented efficiently then the hardware architecture is not well-designed. Also saw this recently:
    >My day job is to speak in an arcane snake language to a crystal vibrating at 3,000,000,000 cycles per second sitting in a cloud so that it can alter probabilities in the real world. If that isn’t magic what is.
    If that isn’t tragic, then what is. Also learned some basic bookbinding recently #hackersdontunderstand

    • Scott Locklin said, on January 9, 2021 at 1:14 pm

      Bookbinding :thumbsup:

      I’ve used linux on the desktop on and off since 1999, FWIIW. KDE at least has been significantly better than osx for usability for about 8 years now, which is kind of miraculous.

  6. Igor Bukanov said, on January 9, 2021 at 12:49 pm

    Go as a language also suffers from academic things. In a book from 1982 I read a warning that the thing that would be called channels in Go 25 years later and that the language would embrace for communication between threads lead to thread explosion and hard to maintain and inflexible code. This is often what happens in practice in Go code that I looked at.

    Fortunately Go provide enough hatches in terms of good old semaphores and signals that one can ignore the channels when it matters. At best they can be used to implement an *untyped* work queue per thread to post messages to the thread, a successful design that is used in Erlang and sane C/C++ libraries, but even than the moment one needs messages with priorities, one better just forget about channels and just implement the queue using ideas from sixties.

    • Scott Locklin said, on January 9, 2021 at 1:21 pm

      I’ve only fiddled with golang for a few weeks; just pointing out a high level observation that, taken as a whole, it seems to work better than implementations in fancier languages.

      • Igor Bukanov said, on January 9, 2021 at 9:40 pm

        Go works well for network-oriented services and so far its track record of the backward compatibility is OK (I cannot say good since they changed their build system in a way that broke older setups). And its build times are excellent. For simple code it can be faster to compile Go source and start it than to start a Python script. On the other hand as a C replacement for low-level system libraries and services it should not be used as it abstracts too much and the abstractions leak.

        • Scott Locklin said, on January 10, 2021 at 12:22 pm

          I guess people have tried to build OS bits out of golang, but the track record of GCed OS being used for anything noteworthy is pretty nonexistent.

          But most people are just serving up some service on a network: seems pretty reasonable for that. Considering where it originated, that’s probably what it’s supposed to be for.

  7. dotkaye said, on January 9, 2021 at 7:30 pm

    that fine old two-stroke engine thumping along, is a thing of beauty..

    I spent a significant fraction of my early career rewriting unicyclists’ code so it could be maintained. As an answer to ‘what do you do ?’ ‘software engineer’ works because people know roughly what it means, but always thought that was so much nonsense. Software has pretensions and aspirations to be an engineering discipline, but it’s a long long way to there from the current state of programming. My brother the civil engineer just laughs at us..

  8. kyn said, on January 9, 2021 at 7:50 pm

    A cathartic read as always.The ML community as a whole is a big ball of shit, but if I had a ball of shit that dollar bills magically started sticking to I’d probably be tempted to act like a dung beetle.

    That being said, I am glad you mention Keogh. I will always give a technique coming out of Keogh’s group the benefit of the doubt (which for me just means giving it the old college try on a small problem, maybe one we’ve already solved at work), because he strikes me as a particularly honest researcher. He is deeply honest about the failures of certain techniques (even his own), and regularly offers good criticism to the community at large (cherrypicking datasets, faulty benchmarking, etc.)

    His papers are often lightly humorous and very well constructed. He pays great attention to application. I am always impressed to come away from his papers not only with a (possible) new technique but with a thought of how to better communicate data to or receive data from customers and coworkers (the time series bitmaps paper and the efficient and effective labelling of time series archives papers are two nice examples).

    How many of the current ML set would focus on something like entomology to solve someone’s problem rather than take the the usual approach of inventing a problem or riding on prepackaged datasets? How many of the current ML set would deign to offer Matlab implementations simply because it is what 90% of academia uses? See here: https://www.reddit.com/r/MachineLearning/comments/5jzb0a/r_an_incredibly_useful_new_tool_for_time_series/

    The UCR group does engage in a fair bit of PR (and hey, here I am doing it for them), but all wackademics do, and of all the papers I slog through as a simple wageslave, theirs often have some of the highest value-to-time-spent ratios.

    And the man loves to turn engines, is a high school dropout, and worked his way through college. I’m probably contributing to a big problem in the research space here by waxing about this guy, but I have a soft spot here. He comes from a background much more familiar to me and my family than the usual children of professors and analysts. If I’m going to have to hear about ML researchers until the money runs out, put more of this guy in my face and less of these fucking masturbators.

  9. David said, on January 9, 2021 at 9:24 pm

    was in town and I saw an old subaru with a turbo diesel
    badge, and asked the guy who headed for it what that was all about, he had converted it over to 1.9 diesel and ran it on strait fryer oil, he then pointed out the curious axel stubs ,which he had made up to attach a second set of wheels ,so that he could drive out on the bay of fundy mud flats and get clams,he is also the inventor of
    the “lunicycle”,which is two unicycles conected by a shaft and universal joints.

  10. svilen dobrev said, on January 10, 2021 at 12:19 am

    Long time ago one had to be engineer in order to be able to program stuff. So engineering came before programming. One knew the engine from pistons/transistors up (or failed miserably). But, one day, Maybe about 1995 (was it visual basic?) the tide/tables turned, and anyone and hir dog could be programmer. Engineers be gone. Now, in order to fix a shaking table, replace the legs with screwable ones (instead of fitting some folded used paper ticket underneath) . Or better, Have luck

  11. Michael said, on January 11, 2021 at 7:35 pm

    From Michael Abrash’s Graphics Programming Black Book:

    “In the early 1970s, as the first hand-held calculators were hitting the market, I knew a fellow named Irwin. He was a good student, and was planning to be an engineer. Being an engineer back then meant knowing how to use a slide rule, and Irwin could jockey a slipstick with the best of them. In fact, he was so good that he challenged a fellow with a calculator to a duel—and won, becoming a local legend in the process.

    When you get right down to it, though, Irwin was spitting into the wind. In a few short years his hard-earned slipstick skills would be worthless, and the entire discipline would be essentially wiped from the face of the earth. What’s more, anyone with half a brain could see that changeover coming. Irwin had basically wasted the considerable effort and time he had spent optimizing his soon-to-be-obsolete skills.
    What does all this have to do with programming? Plenty. When you spend time optimizing poorly-designed assembly code, or when you count on an optimizing compiler to make your code fast, you’re wasting the optimization, much as Irwin did. Particularly in assembly, you’ll find that without proper up- front design and everything else that goes into high-performance design, you’ll waste considerable effort and time on making an inherently slow program as fast as possible—which is still slow—when you could easily have improved performance a great deal more with just a little thought. As we’ll see, handcrafted assembly language and optimizing compilers matter, but less than you might think, in the grand scheme of things—and they scarcely matter at all unless they’re used in the context of a good design and a thorough understanding of both the task at hand and the PC.”

    Your last paragraphs on Machine Shops make me think of this quote. Sure, you might want a file, but a lot of prototyping work can be done on a 3-d printer, and these days I’d put one in before a lathe or end mill. Of course, if I’m buying a bandsaw, I might as well get an end mill and lathe, but machining for rough prototyping is a skill of diminishing returns. Machining things accurately by hand just isn’t as important for everyone to master as it was 30 years ago.

    • Scott Locklin said, on January 11, 2021 at 8:18 pm

      LBNL didn’t even bother with CNC, because with one-offs, it’s a total waste of time. The bridgeport had a DRO, that was about it. Making plastic pixels using a solid printer is also pretty unhelpful in constructing little clocks and steam engines or parts for vacuum chambers. Not even the 100k metal sintering ones.

      FWIIW I actually use a slide rule (a Pickett N-525). Mostly in calculating bills, but anyone involved with matter should understand how logarithms work.


Leave a comment