Concept Count
How much do you need to learn to read arbitrary code in this language?
Two views: the language's total surface area (everything a developer might encounter), and how many concepts a typical solution actually uses.
Surface Area — Total Concepts
The full inventory of distinct ideas a developer must learn. Curated across 8 categories: types, control flow, functions, OOP/data, memory, concurrency, metaprogramming, and error handling. Each concept warrants its own section in a language tutorial.
| Language ↕ | Concepts ↑ | Keywords ↕ | Keyword Ratio ↕ |
|---|---|---|---|
| Objective-C | ★48▼ | ★57▼ | ★1.19▼ |
| Milo | ★49▼ | ★30▼ | ★0.61▼ |
| Erlang | ★55▼ | ★28▼ | ★0.51▼ |
| Go | ★58▼ | ★25▼ | ★0.43▼ |
| C | ★60▼ | ★44▼ | ★0.73▼ |
| Elixir | ★62▼ | ★15▼ | ★0.24▼ |
| Clojure | ★65▼ | ★16▼ | ★0.25▼ |
| JavaScript | ★65▼ | ★46▼ | ★0.71▼ |
| Ruby | ★65▼ | ★41▼ | ★0.63▼ |
| Zig | ★65▼ | ★49▼ | ★0.75▼ |
| Haskell | ★75▼ | ★24▼ | ★0.32▼ |
| Python | ★75▼ | ★39▼ | ★0.52▼ |
| Java | ★80▼ | ★68▼ | ★0.85▼ |
| Kotlin | ★85▼ | ★78▼ | ★0.92▼ |
| TypeScript | ★100▼ | ★67▼ | ★0.67▼ |
| Rust | ★110▼ | ★58▼ | ★0.53▼ |
| Swift | ★110▼ | ★98▼ | ★0.89▼ |
| C# | ★120▼ | ★118▼ | ★0.98▼ |
| C++ | ★135▼ | ★92▼ | ★0.68▼ |
Keyword ratio = keywords / concepts. High ratio (Zig 0.75) means most concepts have dedicated syntax. Low ratio (Haskell 0.32) means concepts live in the type system, not reserved words.
Concept Distribution
Same total can mean very different things. Where do each language's concepts live?
| Language | Types | Control | Functions | OOP/Data | Memory | Concurrency | Metaprog | Errors |
|---|---|---|---|---|---|---|---|---|
| Objective-C | 8 | 6 | 4 | 10 | 8 | 4 | 5 | 3 |
| Milo | 8 | 6 | 5 | 4 | 8 | 10 | 4 | 4 |
| Erlang | 6 | 8 | 8 | 4 | 2 | 15 | 6 | 6 |
| Go | 10 | 8 | 6 | 8 | 5 | 10 | 3 | 8 |
| C | 12 | 8 | 6 | 4 | 15 | 5 | 6 | 4 |
| Elixir | 8 | 8 | 10 | 4 | 2 | 14 | 10 | 6 |
| Clojure | 8 | 6 | 14 | 6 | 2 | 12 | 12 | 5 |
| JavaScript | 6 | 8 | 12 | 10 | 2 | 10 | 10 | 7 |
| Ruby | 6 | 10 | 10 | 14 | 2 | 5 | 12 | 6 |
| Zig | 12 | 10 | 6 | 5 | 15 | 5 | 5 | 7 |
| Haskell | 22 | 8 | 15 | 3 | 2 | 8 | 5 | 12 |
| Python | 8 | 10 | 10 | 18 | 2 | 10 | 12 | 5 |
| Java | 14 | 10 | 8 | 18 | 4 | 10 | 8 | 8 |
| Kotlin | 16 | 10 | 12 | 14 | 3 | 10 | 8 | 12 |
| TypeScript | 22 | 10 | 12 | 14 | 2 | 10 | 14 | 16 |
| Rust | 22 | 12 | 12 | 12 | 22 | 10 | 10 | 10 |
| Swift | 20 | 12 | 12 | 16 | 12 | 12 | 14 | 12 |
| C# | 20 | 12 | 12 | 20 | 6 | 12 | 22 | 16 |
| C++ | 25 | 12 | 15 | 22 | 20 | 12 | 18 | 11 |
Concepts Used Per Solution
How many concepts does a typical program actually exercise? Averaged across 7 benchmark problems. This measures what you need to write code, not what you need to read arbitrary code (that's surface area above).
| Language ↕ | Concepts Used ↑ | Keywords Used ↕ | Syntax Patterns ↕ |
|---|---|---|---|
| Clojure | ★5▼ | ★4▼ | ★1▼ |
| Erlang | ★5▼ | ★2▼ | ★3▼ |
| Objective-C | ★6▼ | ★5▼ | ★1▼ |
| Ruby | ★6.4▼ | ★3.4▼ | ★3▼ |
| Elixir | ★7.3▼ | ★4▼ | ★3.3▼ |
| C# | ★8▼ | ★7▼ | ★1▼ |
| JavaScript | ★8.9▼ | ★7▼ | ★1.9▼ |
| Python | ★9.3▼ | ★7.3▼ | ★2▼ |
| C++ | ★9.4▼ | ★6.6▼ | ★2.9▼ |
| TypeScript | ★10.1▼ | ★7.4▼ | ★2.7▼ |
| Kotlin | ★10.3▼ | ★7▼ | ★3.3▼ |
| C | ★11.1▼ | ★7.1▼ | ★4▼ |
| Go | ★11.6▼ | ★8.9▼ | ★2.7▼ |
| Swift | ★11.7▼ | ★9▼ | ★2.7▼ |
| Haskell | ★12.1▼ | ★8▼ | ★4.1▼ |
| Rust | ★14.1▼ | ★9.9▼ | ★4.3▼ |
| Java | ★14.7▼ | ★10.3▼ | ★4.4▼ |
| Milo | ★16.4▼ | ★12.1▼ | ★4.3▼ |
| Zig | ★20▼ | ★15.9▼ | ★4.1▼ |
What drives the differences?
C++ (135) is the outlier — templates, SFINAE, move semantics, rule of five, coroutines, modules, concepts, ranges. The full surface area that makes C++ notoriously difficult to master.
Haskell (75) vs Python (75) — same total, opposite shapes. Python's concepts live in OOP & metaprogramming (classes, decorators, metaclasses). Haskell's live in types & functions (typeclasses, monads, higher-kinded types).
Go (58) — deliberately minimal. 25 keywords, no generics until recently, no exceptions, no inheritance. The language bets that a small surface area makes codebases more readable across large teams.
Zig (65) — similar to C's size but adds comptime, optional types, and safety checks. The low concept count is intentional — Zig's design philosophy rejects hidden control flow and implicit behavior.
Elixir (62) vs Erlang (55) — Elixir adds macros, protocols, and comprehensions on top of Erlang's model, trading a larger surface area for more expressiveness.
What counts as a concept?
A concept is a distinct mental model the programmer must hold — not syntax, but semantics:
if/else= 1 concept (conditional flow)- Ownership + borrowing = 2 concepts (they interact but are distinct)
- Generics = 1 concept (regardless of instantiation count)
async/await= 1 concept, but async + lifetimes = a compound interaction
Keywords are reserved words from the language spec. Syntax patterns are structural features detected in code (closures, pattern matching, generics, channels, etc.). Concept count per solution = keywords used + syntax patterns detected.
Surface area is a static language property — curated by analyzing each language's specification, standard library, and common idioms. See methodology for full details and per-language notes.