A release timeline of the field, the same program shown side by side, a feature matrix, and an honest accounting of where each language wins.
No language is wrong; each one chose a different thing to never compromise on. Knowing the prime directive explains nearly every design decision downstream of it.
## T hintsA 3-D Point with a constructor, read-only fields, a distance method, and a call — the everyday unit of object-shaped code. Watch the ceremony-to-algorithm ratio.
✓ first-class · ~ partial, library-grade, or in flux · — absent by design or omission. Preview-status Tungsten features are footnoted, not hidden.
| Feature | Tungsten | C | Rust | Python | Ruby | Go | Zig | Odin | Swift | Clojure | JS | Haskell | C# | Scala | Kotlin | Julia | Fortran | C++ | Java |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Blocks close by dedent | ✓ | — | — | ✓ | — | — | — | — | — | — | — | ~layout rule | — | ~Scala 3 indent | — | — | — | — | — |
| Exact decimals by default1 | ✓3.14 is Decimal; ~3.14 floats | — | — | ~decimal module | ~BigDecimal | — | — | — | ~Decimal lib | ~0.1M; ratios | — | ~Scientific lib | ~decimal type | ~BigDecimal | ~BigDecimal | ~Rational, BigFloat | — | — | ~BigDecimal |
| Unit-of-measure literals2 | ✓299_792_458 m/s | — | ~uom crate | ~pint lib | — | — | — | — | ~Measurement API | — | — | ~units pkg | — | ~squants lib | — | ~Unitful.jl | — | ~user-defined literals | ~units lib |
| Currency literals2 | ✓$3.50 − 25¢ | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
| Unicode math notation | ✓√ Δ · ² Σ ∫ | — | — | — | — | — | — | — | ~identifiers only | — | — | ~custom ops | — | ~custom ops | — | ✓√ ÷ ⋅ × | — | — | — |
| Classes | ✓ | — | ~struct+impl | ✓ | ✓ | ~struct+method | ~struct+fn | —by design | ✓ | ~defrecord | ✓ES6 class | —data + typeclasses | ✓ | ✓ | ✓ | —structs + dispatch | ~derived types | ✓ | ✓ |
| Traits / protocols | ✓trait + is | — | ✓traits | ~ABCs | ✓modules | ✓interfaces | ~comptime duck | — | ✓protocols | ✓protocols | — | ✓typeclasses | ✓interfaces | ✓traits | ✓interfaces | ~Holy traits | ~abstract interfaces | ~concepts (C++20) | ✓interfaces |
| Generics, monomorphized | ✓Complex<f64> | —macros | ✓ | —hints only | — | ~GC-shaped | ✓comptime | ✓parapoly | ~+ witness tables | — | — | ~dictionaries | ~reified, JIT | ~erased + @specialized | ~reified inline | ✓JIT-specialized | — | ✓templates | ~erased |
| Complex & quaternion numbers | ✓Complex→Sedenion, per scalar | — | ~num crates | ~cmath / numpy | ~Complex only | ~complex128 | ~std Complex | ~complex+quat | ~Numerics pkg | ~ratio/bignum | — | ~Data.Complex | ~System.Numerics | ~Spire lib | ~library | ✓Complex built-in | ✓COMPLEX native | ~std::complex | ~libraries |
| Pattern matching3 | ~case/when + recase | ~switch | ✓match | ✓match (3.10) | ✓case/in | ~switch | ~switch | ~switch | ✓switch | ~core.match | ~destructuring | ✓native | ✓patterns (C# 8+) | ✓match | ~when | ~Match.jl | ~select case | ~switch | ~switch (21) |
Case re-dispatch (recase) |
✓ | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
| Operator overloading | ✓typed dispatch | — | ✓traits | ✓dunders | ✓ | — | —by design | —by design | ✓ | — | — | ✓Num instances | ✓ | ✓ | ✓operator fun | ✓ | ~interface ops | ✓ | — |
| GPU kernels in-language | ✓@gpu fn → MSL | —CUDA dialect | —wgpu/WGSL strings | —Triton DSL | — | — | — | — | ~separate .metal | — | —WebGPU strings | —Accelerate DSL | —ILGPU lib | — | — | ✓CUDA.jl kernels | ~CUDA Fortran | —CUDA C++ | —TornadoVM |
| Zero-copy GPU tensors | ✓Metal 4, bf16 attention | — | — | ~PyTorch / MLX | — | — | — | — | ~MPSGraph / MLX | — | ~TF.js | — | ~TorchSharp | — | — | ✓CuArray | — | ~libtorch / Eigen | ~DJL |
| FP math modes, scoped | ✓@strictmath/@fastmath blocks | ~per-file flags | —intrinsics only | — | — | — | ✓@setFloatMode | — | — | — | — | — | — | — | — | ✓@fastmath | ~compiler flags | ~pragmas | ✓strictfp |
| Memory management | compile-time free | manual | ownership | refcount+GC | GC | GC | manual+allocators | manual+context | ARC | GC (JVM) | GC | GC | GC (CLR) | GC (JVM) | GC (JVM) | GC | manual/allocatable | manual + RAII | GC (JVM) |
| Compiles to native | ✓LLVM | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | ~GraalVM | — | ✓GHC | ~Native AOT | ~Scala Native | ~Kotlin/Native | ~JIT (LLVM) | ✓ | ✓ | ~GraalVM |
| Self-hosted compiler | ✓stage1 ≡ stage2 .ll | ✓ | ✓ | —CPython is C | —CRuby is C | ✓ | ✓ | —C++ | ~C++ core | ~ClojureScript | —V8 is C++ | ✓GHC in Haskell | ✓Roslyn in C# | ✓scalac in Scala | ~kotlinc | ~Julia + C++ | —gfortran is C | ✓GCC/Clang in C++ | ✓javac in Java |
| REPL | ✓plots, live scrub | — | — | ✓ | ✓ | — | — | — | ✓ | ✓nREPL | ✓node | ✓GHCi | ✓csi | ✓scala | ✓kotlinc | ✓ | ~LFortran | ~cling | ✓jshell |
| String interpolation | ✓"[x]" + unit conversion | — | ~format! macro | ✓f"" | ✓#{} | — | — | — | ✓\(x) | —str concat | ✓${…} | — | ✓$"{x}" | ✓s"$x" | ✓"$x" | ✓"$x" | — | —std::format | —String.format |
| Structured concurrency4 | ~goroutines | ~pthreads | ✓async + threads | ~asyncio, GIL | ~threads/ractors | ✓goroutines | ~in flux | ~threads | ✓actors | ✓core.async, STM | ~async, 1 thread | ✓STM, green threads | ✓async/Task | ✓Future, Akka | ✓coroutines | ✓Tasks, @spawn | ✓coarrays | ✓std::thread | ✓threads, virtual |
| Package manager | ~bit + registry, preview | — | ✓cargo | ✓pip | ✓gem | ✓modules | ~build.zig.zon | —vendored | ✓SPM | ✓deps.edn | ✓npm | ✓cabal | ✓NuGet | ✓sbt | ✓Gradle | ✓Pkg | ✓fpm | ~Conan / vcpkg | ✓Maven |
| Windows support | —macOS + Linux | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
1 Exact-decimal semantics are the language definition and the reference interpreter's behavior; the native compiler's decimal path is being hardened for the preview. 2 Units, currency, and percentage literals currently run on the reference interpreter; native-compiler support is on the preview roadmap. 3 Tungsten's destructuring patterns (=> arms with binding and guards) are specified but not yet implemented — today's compiler ships case/when plus the recase re-dispatch, which no other surveyed language has. 4 Tungsten ships goroutines; the fuller task/channel/supervisor model is still being built out. We mark it honestly.
IP addresses, dates, money, rationals, colours — values the lexer reads as first-class tokens, where other languages reach for a string and a constructor. Every result below is real compiler output.
/ gives an exact fraction — not 0, not 0.75
uuid.parse("…")
# is normally a comment; a hex colour is the exception
₹50/- notation — plus £, ¥, ₩, €, and $. The sign picks the currency.
0.30000000000000004
1...10 excludes the end
~
Ask the others and binary floating point answers back. In Python, JavaScript, Ruby, Julia, Go, and most of the field, 0.1 + 0.2 surfaces as 0.30000000000000004; C and C++ print a tidy 0.3 only because their default precision rounds the error out of sight — it is still there. Either way, exactness is a library you must remember to import (Python's decimal, Ruby's BigDecimal, Rust's rust_decimal crate).
Tungsten inverts the default: 3.14 is an exact decimal, and binary floats are the opt-in, spelled ~3.14. The approximate thing carries the visual warning label, not the exact thing. Money, percentages, and measurements build on that foundation — they're literals, not libraries.
When you do want hardware floats, you get real control: three compile-time math modes and scoped @strictmath/@fastmath blocks, with FMA contraction rules precise enough to keep a determinant of equal products exactly zero.
Rust, Zig, and Odin monomorphize — every instantiation becomes specialized machine code, and abstraction costs nothing at runtime. Python and Ruby erase — types are hints or absent, and every operation pays dynamic dispatch. Go and Swift sit between (dictionary-passing and witness tables, with specialization when the optimizer feels like it).
Tungsten joins the monomorphizing camp — unusual for a dynamically-flavored language. Complex<f64>.new(…) stamps out a real Complex$f64 class with native f64 arithmetic, recursively specializing parent classes, validated against with T in (…) constraints.
One consequence worth bragging about: Complex, Quaternion, Octonion, Sedenion, and larger algebras up to 256 dimensions are all ordinary library code, specialized per scalar type, with typed operator-overload dispatch choosing the right * per operand pair.
This is the sharpest divide in the survey. In every mainstream language, GPU programming means leaving the language: CUDA C++ is a separate dialect with its own compiler; Python's Triton is an embedded DSL compiling traced Python; Rust passes WGSL shader strings to wgpu; Swift keeps kernels in separate .metal files behind ~40 lines of pipeline boilerplate.
In Tungsten, @gpu fn is a function annotation. The compiler lowers that function to Metal Shading Language while the rest of the file lowers to LLVM — one syntax, one file, no FFI, no string-embedded shaders. Simdgroup 8×8 cooperative matrices are available for tiled matmuls, and the Tensor class drives Metal 4 cooperative tensors for bf16 linear layers.
The honest caveat: today it targets Metal only — Apple GPUs. The dialect stack is designed for CUDA/WebGPU backends to attach later, but they don't exist yet. If you need NVIDIA today, Tungsten's GPU story isn't yours yet.
Memory: C and Zig hand you the allocator; Odin adds context-scoped allocators; Rust proves safety at compile time and charges you the borrow checker; Swift refcounts; Python, Ruby, and Go collect garbage. Tungsten frees at build time instead: its model is compile-time free insertion — escape analysis frees non-escaping heap values deterministically at compile time, so hot paths don't churn the heap in the first place.
Errors: Rust and Zig encode failure in return types (Result, error unions) — rigorous, and viral through every signature. Go spells it out longhand (if err != nil, a quarter of many functions). Python, Ruby, Swift, and Tungsten use exceptions (raise/rescue with conditional modifiers like raise X if y), keeping the happy path unindented.
Tungsten's choices here are deliberately conventional — the innovation budget went to notation, numerics, and the GPU, not to a novel memory or error model.
Not really competitors — Tungsten's runtime is C, and its binaries link a C runtime. C wins on ubiquity, ABI, and a 50-year toolchain. Tungsten exists because "trust the programmer" doesn't scale to notation-heavy domains.
Tungsten: expressiveness, safety, GPU · C: ubiquity, ABI, zero runtime
Rust owns the systems niche: no GC, provable memory safety, fearless concurrency, cargo. Tungsten doesn't contest it — it offers monomorphized generics and native binaries without the borrow checker's learning curve, freeing memory at compile time instead, for domains where notation matters more than lifetime annotations.
Tungsten: ceremony, math notation, REPL · Rust: no-GC safety, ecosystem, concurrency
Python's ecosystem is insurmountable in the short term — that's just true. Tungsten's counters: native binaries (ship a standalone executable, not a runtime), exact decimals by default, units in the language, GPU kernels without leaving the file, and dramatically fewer tokens per algorithm — which now also means cheaper LLM generation.
Tungsten: native speed, numerics, GPU, tokens · Python: every library ever written
Tungsten is recognizably Ruby-descended — blocks, message passing, happiness-first. The pitch to a Rubyist is direct: keep the expressiveness, drop the ends, gain native binaries, real generics, complex & quaternion numbers, and a GPU. Rails has no Tungsten equivalent yet; Carbide is embryonic.
Tungsten: native compile, numerics, GPU · Ruby: Rails, gems, 30 years of maturity
Go's goroutines, std library, and one-binary deploys make it the boring-in-a-good-way server language. Tungsten compiles to one binary too, and it has working goroutines — but Go's scheduler, tooling, and ecosystem are far more mature, so Go still wins the concurrent-server matchup. Tungsten wins when the problem is mathematical.
Tungsten: notation, numerics, GPU · Go: concurrency, deploys, stdlib, team scale
Opposite poles of one axis: Zig makes everything visible (allocators, control flow, errors); Tungsten makes everything disappear (ceremony, memory, dispatch). Zig's comptime and cross-compilation are genuinely brilliant. They share a virtue: both compilers explain exactly what they did.
Tungsten: brevity, notation, no manual frees · Zig: explicitness, comptime, cross-compile
The other language here that believes linear algebra belongs in the language — Odin has built-in matrix types and array programming, aimed at games and tools. Odin rejects OO entirely; Tungsten is OO to the bone. Kindred spirits about math, opposite conclusions about objects.
Tungsten: OO, no manual memory, GPU codegen · Odin: determinism, simplicity, SOA-friendly data
The nearest neighbor: LLVM-compiled, Apple-platform-strong, ergonomics-obsessed, Metal-capable. Swift has Xcode, ABI stability, and a decade of production. Tungsten's differences: GPU kernels in-language (not separate .metal files), exact decimals, units, dedent blocks, and a REPL that plots. If you live outside Apple's world, Swift's edge shrinks and Tungsten's Linux story matters.
Tungsten: in-language GPU, numerics, brevity · Swift: tooling, maturity, iOS/macOS APIs