PONY λ M2 Modula-2
for Dart programmers

You already know Dart.Now explore other languages.

Side-by-side, interactive cheatsheets for Dart programmers
comparing Dart to other languages. Every example runs live in your browser — no setup, no installation.

▶ Start with Ruby Browse comparisons ↓

Choose your own path by reordering languages

Ruby ⚡ Works Offline ⚡ Offline

Every static guarantee traded for expressiveness. No compiler, no type annotations, no null safety — and in return, a language where numbers are objects, blocks are everywhere, classes are never closed, and methods can be written while the program runs. Dart checks your work up front; Ruby hands you the keys.

  • Dynamic and duck-typed: no annotations, no compiler — a value works if it responds to the method, and a typo is a NoMethodError when that line finally runs
  • Everything is an object receiving messages — 3.times, nil.to_s, 1 + 2 is 1.+(2) — with no primitives and no non-method operators
  • nil is an object (not Dart's tracked null), only nil and false are falsy (so 0 and "" are truthy), and &./|| stand in for ?./??
  • Blocks are the whole language: each, map, and File.open { } are ordinary methods taking a block, and Enumerable is the richest collection library on this site
  • Keyword arguments map cleanly from Dart named params, but symbols (:name), ranges (1..5), and &:method shorthand are new
  • Classes are never closed (open classes / monkey patching replace scoped extensions), mixins come from modules, and send/define_method/method_missing rewrite the object model at run time
Go Pre-Alpha

Not a sibling — a deliberately small language that rejects most of what Dart is built on. No classes or inheritance, no exceptions, no sound null safety, no named or optional arguments, no ternary. What you get back is a language you can hold in your head, an instant compiler, and goroutines and channels: cheap threads over shared memory, a different bet than Dart's single thread plus copy-only isolates.

  • No exceptions: a fallible function returns (value, error) and you check if err != nil at every call site — explicit where Dart propagates a throw automatically
  • No classes or inheritance: structs hold data, methods have receivers, and behavior is shared by embedding and by interfaces satisfied implicitly (structurally, no implements)
  • No sound null safety: nil and zero values replace it, and a nil dereference compiles then panics — the bug class Dart eliminates
  • Value types and explicit pointers (*T, &x), where every Dart type is a reference; a method needs a pointer receiver to mutate
  • No named/optional/default arguments (use an options struct), no ternary, and for is the only loop
  • Goroutines share memory, so go func() plus a sync.Mutex or a channel replaces Dart's isolates — data races are possible and yours to guard
Kotlin Pre-Alpha

Dart's closest sibling — so close the danger is complacency. Null safety, C-family syntax, when/switch, named arguments, sealed classes, extension functions, string interpolation, and structured concurrency all rhyme. This page leads with where the rhyme misleads: real threads with shared memory, renamed null operators, and a JVM soundness hole Dart never has.

  • Kotlin runs on the JVM with real threads and shared memory — where Dart's isolates share nothing and copy messages, Dispatchers.Default runs coroutines in parallel over one heap, so data races and Mutex are back
  • The null operators rename: ?? is Elvis ?:, single-bang ! is double-bang !!, and late splits into lateinit and by lazy
  • A value from Java arrives as a platform type that the compiler waves through — an unchecked nullability hole Dart's sound null safety never has
  • data class is the gift Dart lacks: free equals/hashCode/toString/copy/destructuring — but it is a reference and copy() is shallow, just like a Dart class
  • Numbers are typed and sized (Int/Long/Double/Float) with no num supertype and no ~// on two Ints already truncates
  • Cascades (..) become scope functions (apply/also), named constructors become companion object factories, and mixins become interface delegation (by)
Rust Pre-Alpha

The sharpest contrast on the site: none of Dart's runtime conveniences, all replaced by compile-time guarantees. Ownership and borrowing replace the garbage collector, Option replaces null, Result and ? replace exceptions, let is immutable by default, and there are no classes — structs, traits, and exhaustive match instead.

  • Ownership & borrowing replace GC: each value has one owner, assignment moves it, and you lend access with & (shared) or &mut (exclusive) — "shared XOR mutable" makes data races a compile error
  • No null: Option<T> (Some/None) with match, if let, unwrap_or, and ? — a step beyond even Dart's sound null safety, since there is no null to dereference
  • No exceptions: Result<T, E> (Ok/Err) with the ? propagation operator; panic! is only for unrecoverable bugs
  • Immutable by defaultlet is fixed, let mut opts into mutation (the reverse of Dart's var)
  • No classes or inheritance: structs hold data, impl blocks add methods, traits are the interfaces and mixins (default methods), enums carry data, and #[derive] gives you Kotlin's data-class conveniences à la carte
  • Generics are monomorphized with trait bounds (<T: PartialOrd>) — no boxing, no run-time cost — and real threads share memory safely via Arc/Mutex rather than Dart's copy-only isolates
Swift Pre-Alpha

Dart's other close sibling — optionals, ??, force-unwrap !, protocols, extensions, trailing closures, async/await, and rich pattern matching all rhyme. So this page leads with the real gaps: Swift has value types (struct, and even arrays, copy on assignment), reference counting instead of a garbage collector, and enums that finally carry payloads.

  • Value types: a struct — and Array/Dictionary/Set/Stringcopies on assignment, where every Dart type is a reference; let freezes the whole value and mutating methods need mutating + a var
  • ARC, not GC: class instances are reference-counted with deterministic deinit, so retain cycles leak and you break them with weak/unowned — a discipline Dart's collector hides
  • Enums carry associated values, so a Dart sealed class becomes one enum with payloads — the exact feature Dart's enum cannot express
  • Optionals rhyme (?, ??, !, ?.) but unwrap via if let/guard let; late becomes lazy var or an implicitly-unwrapped !
  • Arguments are labeled by default (move(x: 3, y: 4)), / on two Ints truncates with no implicit numeric conversion, and interpolation is \(expr)
  • No cascade operator, mixins become protocol extensions, named constructors become extra inits, and top-level code runs with no main()
TypeScript Alpha ⚡ Works Offline ⚡ Offline

The same C-family, null-safe, async-first look — but the safety underneath is gradual, not sound. ?., ??, string interpolation, arrow bodies, and async/await all map almost 1:1 from Dart — until !, as, and any turn out to be compile-time lies the checker permits, where Dart's check at run time.

  • Null safety exists (strictNullChecks) but is not sound: ! and as are erased, unchecked assertions — a wrong one yields a quiet undefined, not the exception Dart throws
  • Two absences, not one: null AND undefined — an optional field is T | undefined, and == null is the check that catches both
  • Types are structural and erased: shape is identity (no implements needed), generics vanish at run time, and is List<int> has no equivalent
  • No cascades, no operator overloading, no named/factory constructors, no real mixins — replaced by fluent return this, static factories, and mixin functions
  • sealed + exhaustive pattern switch becomes a discriminated union with a never-based exhaustiveness check; Dart 3 record/list patterns have no analog
  • Mapped and conditional types (Partial, Pick, keyof, infer) compute types from types — the one corner where TypeScript out-expresses Dart's generics entirely
C# Pre-Alpha

Dart's closest cousin — same C-family syntax, static typing, GC, OOP, and async/await. (Anders Hejlsberg had a hand in both C# and TypeScript.) So this page is about where the rhyme diverges: value types, an unsound take on nullable references, records that mean something different, LINQ, delegates and events, and no mixins or cascade.

  • Value types: a struct (and record struct) copies on assignment, where every Dart type is a reference — class stays reference-typed like Dart
  • Nullable reference types look like Dart's null safety but are unsound: warnings not errors, switchable off, and ! is an unchecked forgiveness that can still throw NullReferenceException
  • A C# record is a class with generated value equality and with expressions (Kotlin's data class), not Dart's tuple-style record — a genuine false friend
  • Properties ({ get; set; init; }) are the everyday getters/setters, and primary constructors keep classes terse
  • LINQ (Where/Select/GroupBy, deferred) out-reaches Dart's Iterable API; delegates (Func/Action) and first-class events have no direct Dart analog
  • No mixins (interfaces with default methods + composition) and no cascade (object initializers instead); generics are reified like Dart's, with variance (out/in) on top
Drag cards to reorder · your order is saved locally