Every time I’ve spoken with someone about programming in the last month or so, machine learning or artificial intelligence has come up. Let me tell you the reasons why I don’t care a whole lot about it.

1. It’s not going to put me out of a job

At least 75% of the actual job of programming is figuring out what a person means when they ask for something. This is not a problem that a machine can solve for you, for the same reason that it’s harder to build a robot that builds other robots than to just build a robot. Have you had words with Siri lately? Do you think Siri is in a good position to understand your intent, or it’s maybe just searching for command words in a limited lexicon? Do you really think it could find Henry’s stool? Or does it seem more likely that it would get confused and require a human… trained to translate… high-level human-language… into language suitable for… the machine?

2. Machine learning is not creative

Machine learning is great at solving problems where you start with a thousand test cases and have no idea how to write the function to distinguish them. A great deal of the work of software 2.0” will be a sort of data docent work involving curating data sets of different character. This isn’t going to be an effective or efficient way of solving general-purpose problems any more than it was when Lisp and Prolog claimed they could do it in the 1980s.

By the way, Lisp and Prolog are still fun and cool, and playing with them are a great way to wash the bullshit out of your eyes about AI.

3. More random failure is not a feature

When I ask Siri to set a timer for my tea, it works about 90% of the time. For reference, this means that about once a week, it fails to understand me, and I always say exactly the same thing. This failure rate is completely acceptable for toys like Siri. It’s really not acceptable for most applications we like to use computers for. Is a transfer of money involved? It seems unlikely to me that anyone who works for a living will accept a 10% chance that the money either doesn’t get sent or doesn’t arrive. It seems more likely to me you want the most straightforward code path you can imagine. A big detour through an opaque neural network for grins feels like a bad idea.

The majority of software is actually in this situation. You don’t want a 10% chance your web service does not get called. You don’t want a 10% chance that your log message does not get written or reported. You don’t want a 10% chance that the email to the user does not get sent.

When are you content with a high probability of nothing happening? When you’re making something that is essentially a toy, or perhaps, doing a task where no one can really tell if you’re doing anything at all, which brings us to…

4. ML is painstakingly squeezing the last drop of profit out of a failing business model

The nice thing about advertising is that someone can pay you $500 to do it, and then if nothing happens, you can just shrug and say try again.” Google wants you to believe that you’re accomplishing something, but how many people out there actually know that the money they spend on Google is giving them a positive return?

Let’s play a game: if people who believe they need your product stop buying your product, and you’re left only with the customers who actually do need your product, how does your future look? I think if your primary product is advertising, you’re probably a lot more fucked than someone else who does something more tangible. To be blunt, if all fads were cancelled tomorrow, Facebook and Google would be done for, but Wolfram would get maybe a little blip. You want to work for the blip companies.

5. ML squeezes the last drop from the lemon

ML is a great tool for handling that last fuzzy piece of an interesting application. As an ingredient, it’s more like truffles than flour, potatoes or onions. It’s an expensive, complex tool that solves very specific problems in very specific circumstances.

Unfortunately, there are a few large companies that stand to make significantly more money if either A) machine learning makes significant advances in the failing advertising market, or (more likely) B) machine learning specialists glut the market and suddenly earn more like what normal programmers earn.

Does that change your understanding of why Google and Facebook might be trying to make sure this technology is as widely available and understood as possible? Bear in mind that unless you have massive data sets, machine learning is basically useless. A startup with a proprietary machine learning algorithm that beat the socks off anything Facebook or Google has would be greatly hampered by lack of data—and Facebook and Google are definitely able to compensate for any algorithmic shortcoming either by throwing a ton of compute at the problem or by throwing a ton of computational manual labor” hacks at the problem.

6. Something else is going to end the profession of programming first

Of the 25% of my job that actually requires programming, probably about 90% of it is in the service of things users simply can’t detect. Code quality. Testing. Following the latest UI fads. Worry about the maintenance programmer. Design.

Here’s a frightening question for any programmer. How much of your job disappears if users don’t mind if the app is ugly and are able to do basic programming on their own? I’m not being facetious. If we were really honest, I think we would admit that A) most of what we do is done for reasons that ultimately amount to fashion, and B) a more computationally-literate, less faddish user base requires dramatically less effort to support.

Let’s recall Fred Brook’s program-system-product grid:

Fred Brooks program-system-product gridFred Brooks program-system-product grid

What you’re seeing there is the admission of our industry that solving a problem costs 1/10th of what you’re paying, because you want a nice UI.

All it would take to decimate the population of programmers would be for people to get computer literate and not be so picky about the colors. This sounds to me like something that happens when crafts get industrialized: the faddish handcraftedness is replaced by easier-to-scale, lower quality work.

I think the emphasis on machine learning is looking at Fabergé eggs and saying all handcrafts are going to be like this” simply because it’s very lucrative for Fabergé.

Nope.

Your software is not going to be that cool. It’s going to come in beige and all the ports are going to be standardized. But, it will actually do real work that real people need done, and that is way better than making useless decorative eggs for the new Tsars.

Conclusion

Machine learning is boring.

November 14, 2017






Here’s some Unix tools everybody should know about. They’re third-party and not especially well-known.

fish

fish - the friendly interactive shell

Finally, a shell for the 90s” is a great tag line. For a long time we have sort of had to decide if we wanted a better programming experience or a better interactive experience with the shell. Fish has a very nice programming language, but the ooh-ahh factor is definitely the command line. Check it out.

pv

pv - pipe viewer

A utility that works like cat, except shows progress bars. This thing makes a huge improvement on the UI of your shell scripts. I highly recommend it.

parallel

parallel - xargs for multiple cores

It has a number of nice modes, but basically it does what it says on the tin: run a bunch of stuff concurrently. By default it will figure out how many cores you are and make your machine busy, but not create a bunch of contention. I use this in file conversion scripts now to good effect.

entr

entr - watch the filesystem

This is a great little utility for tying behavior to filesystem changes.

cronic

cronic - a cure for cron’s email problem

Useful for making it so you only get mail from cron when something happens you should know about.

November 8, 2017






Who is your hero? Mine is Cook Ting.

Cook Ting laid down his knife and [said], What I care about is the Way, which goes beyond skill. When I first began cutting up oxen, all I could see was the ox itself. After three years I no longer saw the whole ox. And now—now I go at it by spirit and don’t look with my eyes. Perception and understanding have come to a stop and spirit moves where it wants. I go along with the natural makeup, strike in the big hollows, guide the knife through the big openings, and follow things as they are. So I never touch the smallest ligament or tendon, much less a main joint.”

— Chuang Tzu, ch. 3: The Secret of Caring For Life”

Cook Ting is my hero. He doesn’t care about fame. He just wants to do the thing he does, well. And in doing it, he has become so good at it, it almost defies explanation. He’s a cook, but not a chef.

November 8, 2017






If I had to average a list of numbers, I would probably do it like this:

averagelist(List, Avg) :- 
  length(List, N), sumlist(List, Sum), 
  Avg is Sum / N.

This resembles the actual mathematical definition. Then you could just make a list of numbers and average that. @lurker is right, this is a terrible way to go, but it would work:

average(N, Avg) :- 
  findall(I, between(1, N, I), Is),
  averagelist(Is, Avg).

This is building up abstraction. But of course, this is for a class and the important thing is to not use Prolog or learn declarative programming or solve actual problems but rather to perform meaningless inductive calisthenics to prove you understand recursion. So a better” (i.e. worse but likelier to be accepted by a clueless professor) solution is to take the procedural code:

average(list) ::= 
  sum := 0
  count := 0
  repeat with i ∈ list
    sum := sum + i
    count := count + 1
  return sum / count

and convert it into equivalent Prolog code:

average(List, Result) :- average(List, 0, 0, Result).

average([], Sum, Count, Result) :- Result is Sum / Count.
average([X|Xs], Sum, Count, Result) :- 
  Sum1 is Sum + X,
  succ(Count, Count1),
  average(Xs, Sum1, Count1, Result).

The list result of my findall/3 must be delicately hand-assembled using only tools available in the 18th century lest anyone develop a sense that Prolog can be used effectively in fewer than 40 lines of code:

iota(N, Result)        :- iota(1, N, Result).
iota(X, Y, [X|Result]) :- X < Y, succ(X,X1), iota(X1, Y, Result).
iota(X, X, [X]).

Then you could build averagelist/2 without the taint of library code (of course, you’ll have to write length/2 and sumlist/2, and probably member/2 even though it isn’t used, but just because it’s clever and useful and it sort of seems like it should be in the source file next to all this other stuff we might need), but it would look generally like this:

average(N, Avg) :-
  iota(N, List),
  averagelist(List, Avg).

Now, of course, it will be pointed out that the introduction of additional predicates that are not directly answers to the take home assignment are illegitimate and will be penalized as doing such leads to readability, maintainability, breaking problems down into manageable pieces and other things that are not directly related to the goal of the assignment (to make Prolog appear tedious yet opaque) so we could now look at this and realize that if we want to flatten these two predicates together we ought to be able to by just smushing together their state variables and doing all the work of both, like this:

average(N, Avg) :- average(1, N, 0, 0, Avg).

average(X, Y, Sum, Count, Avg) :-
    X < Y,
    Sum1 is Sum + X,
    succ(Count, Count1),
    succ(X, X1),
    average(X1, Y, Sum1, Count1, Avg).
average(X, X, Sum, Count, Avg) :-
    Sum1 is Sum + X,
    succ(Count, Count1),
    Avg is Sum1 / Count1.

Now this is starting to look like Professor of Programming Languages code! We went from basically four little readable lines to 9 or 10 repetitive lines and a lot of book-keeping and state! I think we’re on the right track now, let’s review how it works:

  1. average/2 is just a call to average/5 with our state initialized (no sum, no count, starting value = 1).
  2. average/5 has two cases: a base case where the count-up-to value and the current-count value are equal, and an inductive case where the current-count is less.
  3. add up the blah blah blah you get the point

The key takeaways here are: 1) Prolog has a terse, high-level, readable and comprehensible standard library, which you are prohibited from using in school, and 2) any procedural loop can be made working Prolog by creating a recursive helper predicate and moving the code around.

June 9, 2017 prolog






Update 2025-05-09: There is now a page on this topic on sona pona! Read that instead, the below is very incomplete and out of date!

Natural Semantic Metalanguage is a theory that claims there is a common set of semantics underlying all natural languages. This is a descriptive theory, but we can also use it to evaluate constructed languages and perhaps use it prescriptively to help us create effective constructed languages (or at least let us restrict them consciously rather than accidentally).

I’ve taken the chart of NSM semantic primes from 2016 and written the Toki Pona equivalent of each prime in it, and crossed it off a list of Toki Pona words. The result is a mapping of NSM to Toki Pona, but it also tells me a few other things:

  • There are some primes in NSM that have no direct representation in Toki Pona. This highlights areas of Toki Pona that contribute to the sense that there are things you can’t say in it.
  • There are several overloaded words in Toki Pona that function as more than one NSM prime. This helps explain the fuzziness” you feel using Toki Pona.
  • The non-primes in Toki Pona’s lexicon form a useful minimal vocabulary for people interested in language construction.

Interestingly, there are only a few primes that appear to be handled grammatically in Toki Pona. Almost all the primes in NSM are realized as independent Toki Pona words. This suggests to me that Toki Pona is extremely well-constructed.

Now, onto the chart:

NSM Prime Toki Pona
I-ME mi
YOU sina
SOMEONE jan
SOMETHING-THING ijo
BODY sijelo
PEOPLE jan mute
KIND <none>
PART wan

In the first section, we see a pretty good mapping from NSM prime to Toki Pona. KIND has no mapping, which makes sense, because Toki Pona is in general very bad at making distinctions between type (by design). I’ve marked wan in bold to draw attention to the fact that it represents multiple NSM primes. In fact, wan means one, unit, element, part, piece, or make one—in other words, as a noun, it means a single thing or one of many things, but as a verb it means to unify them into a wholeness, so it is a kind of auto-antonym, which is surprising in a constructed language but occurs not uncommonly in natural languages.

NSM Prime Toki Pona
WORDS nimi
THIS ni
THE SAME sama
OTHER-ELSE ante
ONE wan
TWO tu
MUCH-MANY mute
ALL ali
SOME <none>
LITTLE-FEW lili

mute and lili are both pretty polyvalent; mute winds up covering a lot of scenarios.

NSM Prime Toki Pona
TIME-WHEN tenpo
NOW tenpo ni
MOMENT tenpo
(FOR) SOME TIME <none>
A LONG TIME tenpo mute
A SHORT TIME tenpo lili
BEFORE tenpo pini
AFTER tenpo kama

As you can see, Toki Pona is fairly weak at time. tenpo pini and tenpo kama mean finished time” and time to-come” and that’s about all you get. There’s definitely no distinction between points and intervals. The ambiguity here is probably intentional—intended to focus your attention on the here-and-now rather than placing sentences into arbitrary points in time and space (unlike Lojban).

NSM Prime Toki Pona
WANT wile
DON’T WANT wile ala
FEEL pilin
DO pali
SAY toki
KNOW sona
SEE lukin
HEAR kute
THINK pilin

Toki Pona has a full set of the mental predicates, the only ambiguity is the merging of think” and feel”, which was definitely an intentional choice by the inventor to steer discourse in a certain direction.

NSM Prime Toki Pona
HAPPEN kama
BE (SOMEWHERE) lon
LIVE ali
DIE moli
THERE IS <none>
BE SOMEONE/SOMETHING <none>
(IS) MINE pi mi
MOVE tawa

Here we see lon used to place things and people as well as define them. It doesn’t seem like a perfect fit for any of these primes but it is closer than nothing. Toki Pona probably relies more on the null copula to say things like this is a cat” (ni li soweli). I’ve underlined ali because life” is an oblique meaning. Toki Pona doesn’t seem to have a word for live.”

NSM Prime Toki Pona
TOUCH pilin
INSIDE insa
PLACE-WHERE-SOMEWHERE tomo
HERE lon
ABOVE sewi
BELOW anpa
ON ONE SIDE poka
NEAR <none>
FAR weka

I’ve underlined tomo because the sense a general place” is definitely secondary to the sense a room (indoors)” so it is an oblique association with the NSM prime. Also weka means away” in a sort of vague way that might mean far but isn’t the main sense. And once again we have pilin for something sensory. That there are no real words for near and far is probably intentional—again, Toki Pona emphasizes the here-and-now—the surprise is that there is not really a word for here at all. It’s apparently just always implied; soweli mute li lon means both there are cats here” and lots of cats exist” and no distinction between them is possible.

NSM Prime Toki Pona
NOT-DON’T ala
CAN ken
BECAUSE tan
IF la
MAYBE ken la
LIKE-AS-WAY nasin

la functions as a strange bit of grammar in Toki Pona, separating an adverb” or context” from the rest of the sentence. Conditionals are handled this way, as are temporal constructions. I think it’s likely that this area was intended to be simple and weak but grew more complex as the community expanded. Anyway, all the primes are available here, but not all as single words.

NSM Prime Toki Pona
VERY kin
MORE-ANYMORE mute
SMALL lili
BIG suli
BAD ike
GOOD pona
TRUE lon

Once again, mute and lili reappear as common adjectives. lon in the sense of true” is probably oblique. There’s no explicit way of saying false; you would simply negate the statement somehow.

So, what does that leave? Quite a bit:

  • a (ah, ha, uh, oh, ooh, aw, well)
  • akesi (non-cute animal, reptile, amphibian)
  • anu (or)
  • awen (stay, wait, remain)
  • en (and)
  • esun (market, shop)
  • ilo (tool, device, machine)
  • jaki (dirty, gross, filthy)
  • jelo (yellow)
  • jo (have, contain)
  • kala (fish, sea creature)
  • kalama (sound, noise, voice)
  • kasi (plant, leaf, herb, tree, wood)
  • kepeken (use)
  • kili (fruit, pulpy vegetable, mushroom)
  • kiwen (hard thing, rock, stone, metal, mineral, clay)
  • ko (semi-solid or squishy substance)
  • kon (air, wind, smell, soul)
  • kule (color, paint)
  • kulupu (group, community, society, company, people)
  • lape (sleep, rest)
  • laso (blue, blue-green)
  • lawa (head, mind)
  • len (clothing, cloth, fabric)
  • lete (cold)
  • linja (long, very thin, floppy thing)
  • lipu (flat and bendable thing)
  • loje (red)
  • luka (hand, arm)
  • lupa (hole, orifice, window, door)
  • ma (land, earth, country)
  • mama (parent, mother, father)
  • mani (money, material wealth, currency, dollar)
  • meli (woman, female, girl, wife, girlfriend)
  • mije (man, male, boy, husband, boyfriend)
  • moku (food, meal, eat, drink)
  • monsi (back, rear end, butt, behind)
  • mu (cute animal noise)
  • mun (moon)
  • musi (fun, playing, game, recreation, art)
  • nanpa (number)
  • nasa (silly, crazy, foolish, drunk, strange, stupid, weird)
  • nena (bump, nose, hill, mountain, button)
  • noka (leg, foot)
  • o (vocative)
  • oko (eye)
  • olin (love)
  • ona (she, he, it, they)
  • open (open, turn on)
  • pakala (blunder, accident, mistake)
  • palisa (long, mostly hard object)
  • pan (grain, cereal)
  • pana (give, put, send, place, release, emit, cause)
  • pimeja (black, dark)
  • pini (end, tip)
  • pipi (bug, insect, spider)
  • poki (container, box, bowl, cup, glass)
  • seli (fire, warmth, heat)
  • selo (outside, surface, skin, shell, bark, shape, peel)
  • seme (what, which)
  • sike (circle, wheel, sphere, ball, cycle)
  • sin (new, fresh, another, more)
  • sinpin (front, chest, torso, face, wall)
  • sitelen (picture, image, draw, write)
  • soweli (animal, especially land mammal, lovable animal)
  • suno (sun, light)
  • supa (horizontal surface, e.g furniture, table, chair, pillow, floor)
  • suwi (candy, sweet food)
  • taso (only, sole, but)
  • telo (water, liquid, juice, sauce)
  • unpa (sex, sexuality)
  • uta (mouth)

More details on the Toki Pona vocabulary can be found at the semi-official wordlist, by consulting pu, the official Toki Pona Book or perhaps by reading a tutorial.

Ideas for further work:

  • Create an NSM-complete Toki Pona by filling in the missing primes and disambiguating multi-valent words
  • Create an inflected Toki Pona by converting NSM primes into bound morphemes on the remaining TP lexicon

April 27, 2017 language






I want you to close your eyes for a second and picture your biggest hero. Here’s mine.

hint: it’s buckaroo banzaihint: it’s buckaroo banzai

The man you see pictured here is Buckaroo Banzai. According to the highly informative documentary The Adventures of Buckaroo Banzai Across the 8th Dimension, Buckaroo is both a physicist and neurosurgeon while heading a rock band as well as running the fan club. One gets the sense these are just a few of the salient features of a fairly rich backstory.

Importantly, early in the film during what appears to be the informal job interview of Sidney, another neuroscientist, Buckaroo asks if he can dance. The implication is that he’s not interested in bringing a neurosurgeon onto his team if he can’t perform in the band.

Obviously, we can’t run our own workplaces like Buckaroo does. But, there’s a cue in here about how to live. I see programmers talking about how to be better programmers by learning, learning, learning about programming. Acquire new languages, try new frameworks, have side projects, be constantly writing code. I see other programmers talking about how to be better programmers by meditating, by working out, hiking the wilderness and getting to 4% body fat, by getting better sleep and eating healthier foods. And I think they’re both missing the point.

The way to be a better programmer is to be a better, bigger human. Indulge your interests. Call your mom. Care about yourself, your family, your friends, strangers. Buckaroo Banzai didn’t have his band to be a better physicist. His being a physicist wasn’t there to improve his being a neuroscientist or vice versa. They were simply expressions of his being. Sidney doesn’t have to dance to be a good neurosurgeon, he has to dance because he’s human and Buckaroo wants to be around humans. (Sidney can’t dance for shit, by the way.) Dr. Sidney Zweibel wants to cure rodeo clownism

So quit trying to be a better programmer so you can write more code faster and better and be more powerful at it so you can be a better cog and get more head pats. Be a better programmer to help save the planet from red lectroids from the 8th dimension. That’s a much better reason than to get a job at Google or Facebook, of all fucking places. And give her your coat.

Because you’re perfect.

March 1, 2017