(Written by Thaura Work. I haven’t checked it. I’ve been learning Elm, so there might be some bias it picked up somewhere in my files.)
A quick-reference list of language features and conventions that make one-shot code generation more reliable. The common thread: predictability. Features that appear frequently in training data, parse unambiguously, and leave few implicit choices produce fewer hallucinations and fewer subtle bugs.
Type System & Static Structure
- Explicit type annotations. Languages with strong static typing (TypeScript, Rust, Go, Java) constrain the solution space dramatically. An annotation like
fn process(input: Vec<u8>) -> Result<String, Error>tells the model exactly what goes in and comes out, eliminating an entire class of guessing. - Algebraic / sum types. Enums, tagged unions, sealed classes, and
Result<T, E>force exhaustive handling. The model can’t silently forget a case the way it can with a bare integer or string status code. - Optionality made explicit.
Option<T>, nullable markers, or required-field syntax prevent “did I check for null?” ambiguity from leaking into generated logic.
Naming & Conventions
- Descriptive, conventional identifiers. Names that follow community norms (
getUserName, notgn()) match high-frequency patterns in training data. The model essentially autocomplete-s from convention. - Standard library names used as-is. Reaching for
collections.defaultdictinstead of inventing a helper keeps the output verifiable and familiar.
Syntax Predictability
- Uniform function/method call syntax. Consistent
f(x)across the language means the model rarely fumbles call shapes. Languages mixing macro invocations, operator overloading, and special dispatch forms are harder to get right blind. - No hidden mutation or side effects baked into syntax. Properties, getters/setters, and overloaded operators introduce behavior the model must infer. Plain functions and plain fields are safer bets.
- Single, obvious control-flow forms. One canonical
for x in items:loop beats five dialects. When a language has many ways to express the same thing, the model picks whichever was most frequent in its slice of training data β which may not be your house style.
Module & Import Clarity
- Explicit imports. Languages where every symbol must be imported (Go, ES modules, Rust
use) give the model a clear contract. Implicit global namespaces increase the chance of name collisions and wrong-symbol guesses. - Flat, predictable module paths. Deep dynamic import chains are harder for the model to resolve correctly than shallow, named ones.
Error Handling
- Structured errors over exceptions-as-control-flow. Returning error values or using typed result types is easier for the model to wire up correctly than try/catch ladders with implicit propagation.
- One idiomatic recovery path. If the ecosystem has a single accepted pattern (e.g., Rust’s
?operator), the model converges on it reliably.
Immutability & Data Flow
- Default-immutability languages (Rust ownership, immutable-by-default JS bindings via
constdiscipline, Clojure values) reduce the state-space the model must track. Fewer aliasing surprises mean fewer off-by-one-mutation bugs. - Pure-function-friendly design. Functions whose output depends only on inputs are trivially composable and easy for the model to reason about step by step.
Formatting & Tokenization Friendliness
- Consistent whitespace-based structure (Python indentation, standard 4-space blocks) maps cleanly onto token boundaries. Irregular formatting or mixed-indentation legacy code increases noise.
- Common delimiters and punctuation. Braces, parentheses, semicolons used uniformly tokenize predictably; exotic delimiter schemes add risk.
Testability Surface
- Small, independently callable units. A language/ecosystem where you can unit-test a function without bootstrapping a framework gives the model a natural stopping point and makes verification cheap.
- Deterministic behavior by default. No hidden randomness, no wall-clock dependence inside core logic β the model can reason about outputs concretely.
Practical Takeaways
| Prefer | Over | Why |
|---|---|---|
| Typed signatures | Untyped / duck-typed params | Constrains output shape |
| Sum types / enums | Magic integers or strings | Exhaustiveness enforced |
| Explicit imports | Global namespace | Clear dependency graph |
| Returned errors | Broad exception swallowing | Localized failure handling |
| Immutable data flow | Shared mutable state | Less aliasing to track |
| Standard library calls | Invented helpers | Matches training frequency |
| One canonical idiom | Five competing styles | Reduces variance in output |
Rule of thumb: when choosing a language or refactoring a prompt for better one-shot results, pick the option that leaves the fewest implicit decisions to the model. Every explicit choice you encode in the language itself is a decision the model doesn’t have to guess.
Language Competition
Comparing these languages: JavaScript, TypeScript, Lua, Go, Rust, C++, C, ObjC, Haskell, Elm, Python3, Perl, Perl6, PHP8, Vala, Java, Kotlin, Swift, C#, F#.
| Language Feature | Languages that have it | Languages that lack it |
|---|---|---|
| Typed signatures | TypeScript, Go, Rust, C++, C, ObjC, Haskell, Elm, Perl6, PHP8, Vala, Java, Kotlin, Swift, C#, F# | JavaScript, Lua, Python3, Perl |
| Sum types / enums | Go, Rust, Haskell, Elm, PHP8, Vala, Java, Kotlin, Swift, C#, F# | JavaScript, TypeScript, Lua, C++, C, ObjC, Python3, Perl, Perl6, C++ |
| Optionality made explicit | Rust (Option<T>), Kotlin (?), Swift (Optional), TypeScript (strict null checks), Java (annotations) | JavaScript, Lua, C, C++, Python3, Perl, Perl6, PHP8, Go, ObjC |
| Uniform function call syntax | C, C++, Java, Kotlin, Swift, C#, F#, Go, Rust, Haskell, Elm, PHP8, Vala | JavaScript (optional chaining, spread, template literals), Perl (many sigils), Lua (mixed : and .) |
| No hidden mutation in syntax | Rust (ownership), Haskell (lazy purity), Elm (no side effects), Go (minimal), C (explicit) | JavaScript (proxies, getters/setters), C++ (operator overloading), Java (properties via beans), PHP8 (magic methods), Swift (computed properties), Kotlin (delegates) |
| Single obvious control-flow form | Go, Rust, C, C++, Java, C#, F#, Kotlin, Swift, Elm, Haskell | JavaScript (for-of, for-in, forEach, map/filter/reduce), Ruby-like sugar in PHP8, Perl (postfix if/unless) |
| Explicit imports | Go, Rust, ES modules (TS/JS), Java, C#, F#, Kotlin, Swift | C/C++ (#include is explicit but no module system), Perl (use), Python3 (implicit init), PHP8 (autoload), Lua (require), ObjC (@import) |
| Flat predictable module paths | Go, Rust, C, C++ | Java (deep packages), C#/F# (namespaces), Kotlin (packages), Swift (modules + @objc), TS/JS (node_modules resolution) |
| Structured errors over exceptions | Go (error values), Rust (Result<T,E>), C (errno/return codes), Elm (typed Result) | Java (checked exceptions everywhere), C# (exceptions), Kotlin (exceptions), Swift (throws), C++ (exceptions optional), PHP8 (throw/catch), JS (try/catch only), Python3 (raise/except), Perl (die/warn), Perl6 (exception), ObjC (NSException) |
| One idiomatic recovery path | Rust (? operator), Go (bare error return), C (check errno) | Java (nested try/catch), C# (multiple catch filters), JS (no standard propagation), Python3 (broad except patterns) |
| Default immutability | Rust (borrow checker), Haskell (values immutable by default), Elm (immutable data) | JavaScript, TypeScript, Python3, Java, C#, C++, C, Go, PHP8, Perl, Perl6, Lua, Swift (var default), Kotlin (val default helps but var exists), Vala, ObjC |
| Pure-function-friendly design | Haskell, Elm, Rust (functional style encouraged), F# | C, C++, Java, C#, Objective-C, PHP8, Perl, Perl6, JavaScript, Python3 (mutable defaults common), Go, Kotlin, Swift, Vala, Lua |
| Consistent whitespace structure | Python3 (indentation-based), Go (gofmt enforces), Rust (rustfmt enforces), C (K&R or LLVM style) | C++ (no enforced formatter), Java (no enforced formatter), C#/F# (formatter varies), Kotlin/Swift (flexible), JS/TS (prettier optional), PHP8 (PSR optional), Perl/Perl6 (freeform), Lua (freeform), ObjC (freeform) |
| Common delimiters & punctuation | C, C++, Java, C#, F#, Kotlin, Swift, Go, Rust, PHP8, Vala | Python3 (whitespace-delimited, no braces/semicolons), Perl (sigils $@%&*, flexible quoting), Lua (no semicolons, mixed end keywords), Haskell (layout rule, do notation), Elm (indentation-sensitive like Python) |
| Small independently callable units | Go, Rust, C, C++, Python3, Haskell, Elm, Java, C#, F#, Kotlin, Swift | Perl (monolithic scripts common), PHP8 (procedural legacy), Lua (small ecosystem), ObjC (framework-bound), C++ (template metaprogramming complexity) |
| Deterministic behavior by default | Rust, Haskell, Elm, Go, C, C++ | JavaScript (event-loop timing, floating-point variance), Python3 (dict ordering pre-3.7, hash randomization), PHP8 (locale-dependent sorting), Perl (hash ordering), Java (HashMap iteration order), C# (dictionary enumeration), Kotlin (collection impl choices), Swift (Set unordered), Vala (GLib dict ordering) |