TMTOWTDI vs One Obvious Way: language design philosophy
Two opposing slogans — Perl's 'There's more than one way to do it' and Python's 'one obvious way' — and how Raku and Go inherit the argument.
TMTOWTDI vs One Obvious Way: language design philosophy
Every programming language carries a hidden answer to a single question: when there are several ways to write a thing, how many should the language bless? Two communities answered that question so loudly, and so opposingly, that their answers became bumper-sticker slogans. On one side is Perl's TMTOWTDI — "There's More Than One Way To Do It." On the other is Python's insistence that "there should be one obvious way." The argument between them is one of the clearest fault lines in language design, and tracing it through Perl, Raku, Python, and Go tells you more about the discipline than any feature list.
Perl: more than one way, on purpose
Larry Wall released Perl 1.0 to the comp.sources.misc Usenet newsgroup on
December 18, 1987, as a glue language for Unix text processing. From the
start Wall — who had trained as a linguist — designed Perl to behave less like
mathematics and more like a natural language. The slogan that crystallised this,
pronounced "Tim Toady," appears in his essay in Open Sources (1999):
"There's more than one way to do it."
Wall meant it literally and gleefully. In Perl you can sum a list with a for
loop, a foreach loop, or List::Util::sum; you can guard a statement with a
prefix if or a postfix if or a postfix unless; you can map-and-grep in a
single expression or spell it out:
my @x = (1..5);
# four idiomatic ways to do "one" thing
my $s = 0; $s += $_ for @x; # postfix for
my $t = 0; $t += $_ foreach @x; # foreach
use List::Util qw(sum); my $u = sum(@x);
print "double the evens: @{[ map { $_*2 } grep { $_%2==0 } @x ]}\n";
# => double the evens: 2 4
The design rationale is explicitly linguistic. As Wall put it, "Perl was designed to be a mess (though in the nicest of possible ways)," because "English is useful because it's a mess. Since English is a mess, it maps well onto the problem space, which is also a mess, which we call reality." Multiple ways are a feature: they let the programmer pick the phrasing that fits the moment, and they keep the language from "telling the programmer how to program." Wall's companion slogan — the three programmer virtues of "laziness, impatience, and hubris" — points the same direction: optimise for the human writing the code.
It is worth noting that even Wall hedged. In a 1990 Usenet post he wrote, "Although the Perl slogan is There's More Than One Way To Do It, I hesitate to make 10 ways to do something." TMTOWTDI was always more than one, not unboundedly many.
Python: one obvious way, as a rebuttal
Python's philosophy is preserved as a literal Easter egg. Type import this
into any Python interpreter and you get The Zen of Python, twenty aphorisms
written by Tim Peters around 1999 and later standardised as PEP 20 (2004).
The line that answers Perl directly:
>>> import this
...
There should be one-- and preferably only one --obvious way to do it.
This was a deliberate, tongue-in-cheek riposte to TMTOWTDI — the contrast was made explicit in the Python community around the time of OSCON 2000, where Perl and Python folk shared a stage. The next aphorism even winks at it: "Although that way may not be obvious at first unless you're Dutch" — a nod to Python's creator, Guido van Rossum.
In practice the Zen shapes real syntax. Python offers list comprehensions as the idiom for filter-and-transform, and gently discourages the alternatives:
nums = [1, 2, 3, 4, 5, 6]
print(sum(x*2 for x in nums if x % 2 == 0)) # 24
print([x*2 for x in nums if x % 2 == 0]) # [4, 8, 12]
There is technically more than one way to write that loop, but the community agrees on which one is "obvious," and tools, style guides, and PEPs all push you toward it. Python's bet is the inverse of Perl's: optimise for the human reading the code, especially a human reading code they didn't write.
Raku: keep TMTOWTDI, add guardrails
What happened to Perl's philosophy when the language was reimagined? The project that began in 2000 as "Perl 6" — and was formally renamed Raku in October 2019, with Larry Wall's blessing — kept TMTOWTDI as a stated value but added structure so that "many ways" did not mean "anything goes." Raku codifies the multiplicity: it ships with multi-dispatch, optional gradual typing, and several parallel idioms that are all first-class rather than accidental.
my @x = 1..5;
say [+] @x; # 15, reduction metaoperator
say @x.sum; # 15, method form
say @x.grep(* %% 2).map(* × 2); # (4 8), the chained pipeline
Raku's twist is that the multiple ways are engineered — [+] and .sum are
deliberately co-equal, with consistent semantics — rather than the organic
sprawl of Perl 5. It is TMTOWTDI with a type system and a grammar engine behind
it: more than one way, but each way is a designed citizen of the language.
Go: one way, enforced by tools
Go, designed at Google in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson,
and announced publicly in November 2009, sits at the opposite pole from
Perl — arguably further out than Python. Where Python encourages one obvious
way, Go enforces it with tooling. The canonical example is gofmt: there is
exactly one correct way to format Go source, and the formatter rewrites your
file to match it. The famous "tabs versus spaces" debate simply does not exist
in Go, because the tool settles it (tabs, by the way) before anyone can argue.
Rob Pike summarised the ethos in his 2012 talk "Less is exponentially more."
Go deliberately omits features — no ternary operator, no while keyword (just
for), no implicit conversions — so that there are fewer ways to express the
same idea. Comprehensibility, not expressiveness, is the goal: features are kept
orthogonal so they combine predictably.
nums := []int{1, 2, 3, 4, 5, 6}
sum := 0
for _, x := range nums {
if x%2 == 0 {
sum += x * 2
}
}
fmt.Println(sum) // 24
There is no comprehension, no reduce, no chaining — just the one loop. A Perl programmer sees a poverty of expression; a Go programmer sees a thousand codebases that all read the same way.
What the slogans are really arguing about
Strip away the punchlines and the four languages are arguing about where to put the cost of variety.
- Perl pays the cost when you read unfamiliar code, and buys, in return, maximum expressive fit for the writer. TMTOWTDI optimises the author's freedom.
- Raku keeps that freedom but pays down some of the reading cost by making the many ways consistent and typed, rather than ad hoc.
- Python moves the cost forward to the writer — learn the one obvious idiom — to make every later reader's life cheaper.
- Go removes the choice almost entirely and lets tooling enforce uniformity, trading expressive range for a codebase that scales across thousands of engineers.
None of these is wrong; they are different answers to "who pays, and when?" A small script written and discarded by one author rewards Perl's flexibility. A library read by millions rewards Python's and Go's uniformity. The same slogan that makes a language delightful at one scale can make it costly at another — which is why the TMTOWTDI-versus-one-way debate never really ends. It just moves to the next language that has to decide how many ways is the right number of ways.