PONYΞ»M2Modula-2
CodeCompared
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 RubyBrowse comparisons ↓Explore the language map β†—

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
GoPre-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
KotlinPre-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)
RustPre-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 default β€” let 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
SwiftPre-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/String β€” copies 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()
TypeScriptAlpha⚑ 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
JavaPre-Alpha

🚨 This one runs the other way: you are giving up the safer language. Dart has SOUND null safety β€” the compiler proves a non-nullable reference is never null β€” and Java has null underneath every reference with NullPointerException as its most common production failure. The page says so plainly, and then spends its second half on the two places Java is genuinely ahead: real shared-memory threads, and thirty years of server ecosystem.

  • 🚨 Sound null safety is gone. String? and String stop being different types; Optional, requireNonNull and annotations are partial recoveries, not the guarantee
  • 🚨 Isolates cannot share and threads can. Dart makes data races impossible and copying expensive; Java makes sharing free and correctness your problem β€” decide which thread owns each mutable field
  • No named arguments and no default values, which is the biggest day-to-day loss for a Flutter developer β€” the builder pattern exists to work around exactly what you have for free
  • 🚨 Generics are ERASED here, where yours are reified: no instanceof List<String>, no new T[10], and List<Integer> boxes every element
  • Checked exceptions have no Dart counterpart β€” throws is part of the signature and every caller must catch or declare
  • Java did not add await; it made blocking cheap instead. Virtual threads mean ordinary sequential code scales, which is the opposite strategy from Dart's
  • The method channel is a string, a string and a codec, with nothing checked β€” keep the Java side small, handle notImplemented, and remember its handler runs on the Android main thread
RocPre-Alpha

A fast, friendly, purely functional language from Richard Feldman β€” no garbage collector, no lifetimes, no nulls: memory is managed by compile-time reference counting, and all I/O is delegated to a host "platform" written in another language.

  • Purely functional with managed effects β€” effectful functions are marked with a ! suffix (main!, echo!), so purity is visible in every signature
  • Compile-time reference counting instead of a garbage collector or ownership annotations β€” memory safety with zero programmer bookkeeping
  • Tag unions with exhaustive match β€” the compiler catches every unhandled case
  • The Try type replaces both nil and exceptions β€” every fallible operation returns Ok or Err
  • The platform model β€” a Roc program cannot perform I/O on its own; a host written in Rust, Zig, or another language provides every effect
Drag cards to reorder Β· your order is saved locally