By Pavan Kumar T V ·
English Is Not the New Programming Language, Part 2
Series: Part 1 made the case that English is too loose to command a machine. This is Part 2. Part 3 asks why we need a language at all.
The last post sparked a better argument than I expected.
I'd written that English is dangerous for instructing machines because a typo doesn't break; it quietly means something else. Push to remote becomes push to remove, one key, opposite intent, no error. My whole case was that real programming languages fight back and English doesn't.
The sharpest reply landed almost immediately, and it was aimed straight at my chest:
That's correct. Every word of it.
And I want to start Part 2 by conceding it completely, because the concession is where the real point lives.
Code is one keystroke from a lie too
a = 2 puts 2 into a and reports success. a == 2 asks whether a already holds 2. Drop one character and an assignment wears the costume of a comparison: the branch runs every time, no break, no error, a different valid program standing where you meant another. My push-to-remove disaster, in C.
So the argument I aimed at English lands on code too. Pack meaning tight enough and every language, human or machine, ends up with opposite meanings a keystroke apart. There's no syntax clever enough to escape it; the crowded neighborhood is just the price of being expressive.
But here's the line my critic walked right up to and didn't cross.
In code, something is standing at the door. Type if (a = 2) in a language with a half-decent compiler and you get a warning, or an error, or a linter screaming about an assignment inside a condition. Some languages banned the construct outright. The C world invented "Yoda conditions," writing if (2 == a), so that a slipped key produces if (2 = a), which is trying to assign to the number 2, which is nonsense, which won't compile. A whole coding style, evolved for one purpose: to convert a silent semantic flip into a loud syntactic crash.
That is the difference. Not that code can't be mistyped, but that when you mistype it, you are not alone with the mistake. The language has a second party in the room whose entire job is to read it back to you and ask whether you meant to compare.
English as a specification has no such party. You fire the sentence one-way at a probability engine that executes the most plausible reading and never looks up. The flip and the intent are indistinguishable to it, because to the model the flip is the message.
So the rebuttal doesn't rescue English. It sharpens the real question. If even code, dense and precise, needs a guard at the door, then the thing that matters about a language was never just its precision. It's whether the precision comes with someone to catch the slip.
Which sent me down a rabbit hole I didn't expect to enjoy this much.
Is there a human language built for this?
If English is loose, and the looseness is the bug, then somewhere out there must be a natural language that closed more of the holes. Not because its speakers were smarter, but because their grammar simply refuses to let you skip what English lets you leave vague.
There is. Several, actually. And lining them up tells you something English-only speakers never get to feel.
Finnish won't let you be vague about where. English has one exhausted little word, "on," doing the work of a dozen relationships. The book on the table. Depends on you. On Tuesday. On fire. The listener disambiguates from context, and that's a runtime guess. Finnish refuses the guess. It bakes the spatial relation into the noun itself:
talo = house
talossa → IN the house (inside)
talosta → OUT OF the house (from inside)
taloon → INTO the house (moving in)
talolla → AT the house (on the surface)
talolta → FROM the house (off the surface)
talolle → ONTO the house (onto the surface)
There's no overloaded "on" to misread. The relation is in the word, not in the air around it. Specification pushed to write-time instead of read-time.
Finnish also won't let you hide whether the job finished. This one should make every engineer sit up, because it grammaticalizes the thing every spec is secretly about: did the action complete, and did it cover the whole thing?
English: "I read the book." Did you finish it? Unknown. "Process the records." All of them? Some? Did it run to done? Silent. Finnish marks it in the object's case:
Luin kirjan → I read the book (the whole book, finished)
Luin kirjaa → I read / was reading (at the book, ongoing or partial)
Same verb. The ending carries completion and coverage. You cannot describe the action without committing to whether it ran to the end. For thought-to-structure-to-outcome, that is the outcome, and Finnish makes you state it or you can't form the sentence.
Sanskrit tags every role, so word order stops mattering. Take: "With an axe, in the forest, the man cut the tree for his friend." In English the meaning rides on word order and a scatter of prepositions, so scramble it and it breaks. Sanskrit gives each participant an explicit semantic role, the kāraka system, marked on the noun:
man → agent (kartṛ, nominative)
tree → patient (karman, accusative)
axe → instrument (karaṇa, instrumental)
friend → beneficiary (sampradāna, dative)
forest → location (adhikaraṇa, locative)
Once every noun wears its role, you can permute the five any way you like and who-did-what-to-whom-with-what-for-whom-where never degrades. A 1985 paper in AI Magazine (Briggs) argued Sanskrit's grammar already is a semantic net: the kāraka tags map almost one-to-one onto the thematic roles a knowledge system would assign by hand. English makes you reconstruct the roles from position and hope. Sanskrit ships them attached.
Sanskrit even types its compounds. English compounds are a notorious bug: two words sit together and the relationship between them is anybody's guess.
olive oil → oil made FROM olives
baby oil → oil made FOR babies
snake oil → oil that is a LIE about snakes
Same shape, three different logical relations, zero marking. Sanskrit classifies the compound: tatpuruṣa (one part governs the other), bahuvrīhi (it describes something outside itself), dvandva (coordination, "this and that"). The class tells you which relation binds the words before you reach for context. English throws the relationship away. Sanskrit keeps a type tag on the join.
Turkish won't let you state a fact without stating how you know it. English asserts everything flat: "He came." Did you see it, or were you told, or are you guessing from the coat by the door? No provenance. Turkish grammaticalizes it:
Geldi → he came (I witnessed it)
Gelmiş → he came (apparently / I was told / I infer it)
The suffix is an evidence field. You can't make the bare claim without choosing whether you're reporting first-hand knowledge or hearsay. Quechua does it with -mi versus -si; Tuyuca forces a choice among five evidential markers on every sentence. For converting thought into something you can act on, forced provenance is the difference between a verified value and a rumor, marked at the grammar level instead of dropped on the floor.
German keeps the roles straight even when word order lies. English subject-versus-object is positional, so move the words and meaning collapses. German marks it with case:
Der Mann beißt den Hund. → The man bites the dog.
Den Hund beißt der Mann. → The man bites the dog. (still!)
Object-first in the second, but den is accusative and der is nominative, so the man is still the biter wherever he sits. Case carries the role; order is free to carry emphasis. English asks position to do both jobs at once, and they fight.
Line them up and they form a ladder, each language closing one more hole than English. Direction. Completion. Role. The relation inside a compound. The source of a claim. English sits near the bottom of that ladder. It's the last language you'd pick to build a logic on, if you were choosing on the merits instead of inheriting it from whoever had the navy.
And then the examples got scary
A friend read that list and said the thing that turned this whole essay around:
Look again:
talossa → talosta one letter: IN → OUT OF
t-a-l-o-s-s-a vs t-a-l-o-s-t-a
^
Luin kirjan → Luin kirjaa one letter: finished → unfinished
She's right, and it's worse than she thinks. The typo doesn't produce an error. It produces another perfectly valid word with a different meaning. Nothing flags it. The sentence still parses. It's just now true about a different reality. The slip lands on another real word the way push to remote landed on push to remove.
So precision didn't escape the trap. It walked deeper in. The very thing that made Finnish exact, packing direction and completion into the characters, shrank the distance between distinct meanings down to a single letter. The more meaning you cram into fewer characters, the smaller the gap between "in the house" and "out of the house," and the more silently a slip crosses it.
This is the law the whole argument was circling:
precision wants → density (pack meaning into few characters)
error tolerance wants → redundancy (spread meaning across many characters)
These pull in opposite directions, and you cannot max both in a flat stream of characters. Spread meaning thin and you get ambiguity but forgiveness: that's English, where a typo usually lands in empty space and produces a non-word your eye catches. Concentrate it and you get precision but brittleness: that's Finnish, that's Sanskrit, that's code. Pick your failure mode. There is no setting of the dial that is both exact and safe.
Error correction is just redundancy with a job
Here's the part that finally made it click for me. Shannon settled this in 1948 and nobody has beaten it since: to send a message reliably over a noisy channel, you must add redundancy. There is no clever trick around it. Reliability costs repetition. The redundant bits are the error-correcting code.
There's even a hard threshold. Two valid messages one character apart can't be error-corrected at all; you can't even reliably detect the slip, because the corrupted message is itself a legal message. talossa and talosta are one letter apart. By definition, in isolation, that typo is undetectable.
So how does Finnish survive? Because a word is never actually alone. The grammar echoes the same information across the sentence: number, case, gender repeated on the noun, the adjective, sometimes the verb. That agreement is a checksum. "The houses is red" jars instantly because plural got marked twice and the two marks disagree. The redundancy I sneered at in English, all those agreeing endings, all that morphological "waste," is the error correction. The redundancy that makes a language ambiguous and the redundancy that makes it self-correcting are the same redundancy. You can't strip one without losing the other.
Which means every robust language is a negotiated settlement between density and repetition. English settled high on redundancy: ambiguous, but forgiving, and backed by the oldest error-correcting trick there is, a live human across the table who cuts in with "wait, you mean delete?" the instant something sounds off. Finnish and Sanskrit and Latin settled toward density for precision, then bought safety back with heavy agreement so a one-letter slip contradicts its echoes. And code settled at maximum density, which is exactly why a raw character of it is the most dangerous language we write.
Code didn't remove the noise. It moved the noise into you.
Natural language evolved over a noisy channel of distance, mishearing, and crosstalk, so it's stuffed with redundancy to survive the trip. Code runs over a clean one; the bytes don't get corrupted in transit. So code stripped the redundancy out. It looked safe to.
But the noise didn't leave. It moved from the channel to the author. The corruption isn't on the wire anymore. It's the typo, the off-by-one, the = you meant as ==, the pull you meant as push. You are the noise source now. And a language with no internal redundancy has no defense against a noisy author, so we rebuilt the error-correcting code on the outside, and every piece of it is just structured redundancy with a job:
types → restate the value's kind, so a mismatch is caught (parity bits)
tests → restate the behavior from a second angle, so drift shows (a checksum)
assertions → restate an invariant inline (a guard bit)
the compiler → the "wait, what?" you get before it's too late (the back-channel)
code review → a second human re-derives your intent (re-transmission)
Look at what tests and types actually are: deliberate repetition. We preach DRY, Don't Repeat Yourself, for maintainability, then turn around and repeat ourselves on purpose everywhere reliability matters, because error correction is physically impossible without repetition. A type is the value's kind, said twice, so the two can be checked against each other. A test is the behavior, said twice, so changing one without the other rings an alarm.
And the most human piece is code review, because the one thing code's clean channel deleted was the conversational back-channel, the listener who says "huh?" in real time. The compiler became the synthetic "huh?" you get at build time. Tests are the "huh?" before deploy. Review is the "huh?" from another person: the repair loop, reinserted by hand into a medium that had thrown it away.
That's what my critic's if (a = 2) was really pointing at, and they almost had it backwards. Code isn't safe because it's precise. Code is dangerous because it's precise, one keystroke from a lie, just like English, just like Finnish. What makes it survivable is everything bolted around it to catch the lie. The precision and the guard rails arrive together, or the precision is a loaded gun with no safety.
So, Part 2's whole point in one line
My first post said English is too loose to instruct a machine. The rebuttal said code is just as fragile. Both are true, and they resolve into the same conclusion from opposite sides.
Loosen a language and meaning blurs; you can't specify the outcome. Tighten it and one keystroke lies; you can specify it perfectly and be perfectly wrong. The only thing that ever fixed either failure was redundancy: agreement in speech, types and tests in code, and a second party, human or compiler, to read it back to you before it ships.
"Just describe it in English" doesn't escape that dial, and it doesn't escape that cost. It hands you a precise-feeling sentence with the error correction torn off, fired one-way at a machine with no back-channel, no checksum, no Yoda condition, no compiler clearing its throat at the door. Every other precise language we've ever trusted came with a guard. English-as-spec is the first one we're pretending doesn't need one.
That's not English failing to be a programming language. It's English being one, minus the immune system that made programming languages survivable in the first place. The error correction you'd be giving up isn't a nice-to-have bolted onto coding. It's half of what coding is. And nobody selling you the slogan ever mentioned that half was leaving.