Skip to content

Why Can't We Use English as a Programming Language? The Ambiguity Problem Explained

Problem

When I talk to non-programmers about what I do, they sometimes ask: “Why do we need programming languages? Why can’t we just write code in English?”

I used to give a vague answer about “computers need precise instructions.” But the real answer is deeper and more interesting than that.

The core problem: English makes a terrible programming language because it inherently lacks the precision, unambiguous syntax, and formal structure that computers require.

What happened?

The conversation usually goes like this:

“If I can write a detailed specification in English that describes exactly what the software should do, isn’t that basically code? Why can’t the computer just run that?”

At first glance, this seems reasonable. A well-written specification can be incredibly detailed. It describes inputs, outputs, edge cases, error handling. It almost reads like pseudocode.

But here’s where it breaks down. A Reddit commenter put it perfectly:

“The spec-is-code thing breaks down pretty fast when the spec itself is ambiguous, which like… that’s why you have specs.”

This hit me. The whole point of natural language specifications is that they’re written in natural language—ambiguous by design. If specs were perfectly precise, we wouldn’t need specs at all. We’d just write code.

The Three Types of Ambiguity

Let me show you why English fails as a programming language.

1. Lexical Ambiguity

Words have multiple meanings. Consider this instruction:

English instruction
Set the value to null if it's empty

What does “empty” mean? What does “null” mean? Here are the possible interpretations:

Multiple interpretations of 'empty'
if (value === null) { ... } // null means null?
if (value === undefined) { ... } // null means undefined?
if (value === '') { ... } // empty string?
if (value.length === 0) { ... } // empty array?
if (Object.keys(value).length === 0) { ... } // empty object?

In English, context fills these gaps. In programming, the computer can’t guess.

2. Syntactic Ambiguity

Sentence structure can be interpreted multiple ways. Classic example:

Syntactic ambiguity in English
I saw the man with the telescope.

Who has the telescope? The speaker? Or the man being seen?

Now a programming example:

Ambiguous instruction
Sort the users by age and return the first ten.

Here are three valid interpretations:

Three possible implementations
# Interpretation 1: Sort all, then take first 10
users.sort(key=lambda u: u.age)[:10]
# Interpretation 2: Take first 10, then sort those
users[:10].sort(key=lambda u: u.age)
# Interpretation 3: Get first 10 youngest (streaming)
sorted(users, key=lambda u: u.age)[:10]

All three produce different results. English doesn’t specify which one.

3. Pragmatic Ambiguity

Even perfectly parsed sentences can mean different things based on intent:

Pragmatic ambiguity
Calculate the average and display it.

What is “it”? The number? A formatted string? A chart?

Multiple display options
const average = sum / count;
console.log(average); // raw number
console.log(average.toFixed(2)); // "3.14"
console.log(`Average: ${average}`); // "Average: 3.14159..."

And what happens if count is 0? English doesn’t specify error handling.

Why Programming Languages Work

Programming languages solve these problems through four key mechanisms:

How programming languages solve ambiguity
┌─────────────────────┐
│ Natural Language │ → Ambiguous, contextual
└─────────────────────┘
┌─────────────────────┐
│ Programming Language│ → Precise, formal
└─────────────────────┘
├─── Formal Grammar: One parse tree per program
├─── Type System: Variables have defined types
├─── Explicit Semantics: Every operation defined
└─── Deterministic: Same input → same output

Type Safety

Programming languages have type systems. English doesn’t.

Type safety comparison
English: "Add five to the result"
Result could be: number, string, list, object?
Computer: "I don't know what type this is"
TypeScript: function addFive(n: number): number {
return n + 5;
}
Compiler: "I guarantee n is a number"
Computer: "Clear instructions, no ambiguity"

A Reddit commenter noted:

“My spec doesn’t have syntax errors or hit weird language and runtime quirks. It doesn’t typecheck though, I miss typechecking.”

This is the trade-off. Natural language is flexible. Programming languages are verifiable.

Explicit Semantics

Every operation in a programming language has precisely defined behavior:

Explicit vs implicit semantics
English instruction:
"Process each item in the list and return the results. Handle errors gracefully."
Programming specification:
function processItems<T, R>(
items: T[],
processor: (item: T) => Result<R, Error>
): Result<R[], Error>
This specifies:
- Input type: Array of T
- Output type: Result containing Array of R or Error
- Error handling: Explicit in the type signature

The programming version removes all ambiguity. It also removes all flexibility.

The Historical Parallel

One Reddit comment caught my attention:

“Darwin had to use very precise language to make his points because there were practically no biology terms yet. Language like that is difficult to parse and it’s much less efficient than our scientific jargon of today.”

This reveals something important. Natural language evolves toward precision over time. Scientific fields develop jargon because ambiguity is expensive.

Programming languages skipped this evolution. They started precise by design.

Common Misconceptions

”English-like languages are easier to learn”

SQL uses English keywords. COBOL reads like documentation. But they still have rigid syntax rules:

SQL looks English but has strict rules
SELECT name FROM users WHERE age > 18;

Looks like English. But miss a semicolon, forget the FROM clause, or use the wrong JOIN type—and the computer rejects it. The keywords are English. The grammar is not.

”Detailed specs are code”

Specs describe what. Code specifies how. Even detailed specs leave implementation decisions to programmers:

Spec vs code distinction
Specification:
"The system should authenticate users before granting access to
protected resources. Invalid credentials should result in an
error message."
Implementation decisions left to programmer:
- What authentication method? (JWT, session, OAuth?)
- How to store passwords? (bcrypt, argon2, scrypt?)
- What error message? What status code?
- How to handle rate limiting?
- Session timeout duration?

The spec is useful because it’s high-level. But that usefulness comes from the ambiguity it allows.

”LLMs will solve this”

LLMs translate between English and code. But they cannot make English itself precise enough for direct execution.

An LLM might interpret “sort the users” correctly 99% of the time. But that 1% where it guesses wrong is why we still need programming languages.

Why This Matters

Understanding the difference between natural and programming languages helps explain:

  1. Why LLMs struggle with precise tasks - They’re trained on ambiguous natural language, then asked to produce unambiguous code.

  2. Why we need both specs and code - Specs capture intent (with some flexibility). Code captures execution (with no flexibility).

  3. Why “English programming” keeps failing - Every attempt to make English precise enough for computers ends up creating a verbose programming language.

  4. Why ambiguity in natural language is a feature, not a bug - Poetry, humor, and efficient communication all depend on it. Removing ambiguity makes language worse for humans, not better.

Summary

In this post, I explained why English makes a poor programming language. The key point is that English and programming languages have fundamentally different design goals. English prioritizes flexibility, expressiveness, and efficient human communication. Programming languages prioritize precision, determinism, and formal verification.

These goals are in direct conflict. The moment you make English precise enough for computers to execute, you’ve reinvented a verbose programming language—not natural language.

The next time someone suggests “just write specs in English,” remember: specs are written in English precisely because English allows ambiguity. If specs were code, we wouldn’t need specs at all.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments