PONYΞ»M2Modula-2
CodeCompared
for PHP programmers

You already know PHP.Now explore other languages.

Side-by-side, interactive cheatsheets for PHP programmers
comparing PHP 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

The language a PHP developer already half-knows. Ruby shares PHP's dynamic typing, heredocs, and => hash syntax, but drops the $ sigils and global function soup for a model where everything is an object β€” the language behind Rails, and the inspiration for much of modern Laravel.

  • No $ sigils and no <?php tag β€” a file is Ruby from the first byte; bare names are variables
  • Everything is an object β€” call .upcase or .length on the value itself instead of reaching for global strtoupper()/strlen()
  • Blocks β€” array.map { ... } and each replace foreach and standalone array_map/array_filter
  • Only nil and false are falsy β€” 0 and "" are truthy, and == never juggles types the way PHP's loose == does
  • Real mixins β€” a module with include Comparable or Enumerable works like a trait but composes through the method-lookup chain
GoPre-Alpha

The web backend, recompiled. A PHP developer reaches for Go when a request handler needs to be a fast, concurrent, single static binary β€” trading dynamic typing and per-request scripts for a compiler, goroutines, and errors-as-values.

  • Goroutines and channels β€” built-in concurrency where PHP runs one synchronous script per request
  • Compiles to one static binary with no runtime to deploy, instead of shipping source plus an interpreter
  • Static typing with zero values β€” every variable is well-defined; no null surprises, no type juggling
  • Errors are returned values checked with if err != nil β€” there are no exceptions for ordinary failures
  • Structs, methods, and implicit interfaces instead of classes and implements; visibility is set by capitalization
JavaScriptAlpha⚑ Works Offline⚑ Offline

The other half of the web you already half-share. A PHP developer knows JavaScript exists in every browser; this is the leap to using it as a real language β€” one runtime, an event loop instead of per-request scripts, and an async model PHP has no equivalent for.

  • An event loop and async/await β€” non-blocking I/O and concurrent work, where PHP blocks and runs each request fresh
  • One number type and + overloaded for concat β€” 5 + "3" is "53", unlike PHP's separate . operator
  • Two empty values, null and undefined, where PHP has only null
  • === with coercion rules that differ from PHP's == β€” your juggling intuition does not transfer
  • Objects and arrays are references (no copy-on-assign), and this depends on how a method is called
PythonBeta⚑ Works Offline⚑ Offline

The other dominant dynamic language β€” and PHP's closest peer. Python keeps the gradual typing and quick-iteration feel you know, but trades $ sigils, semicolons, <?php tags, and one all-purpose array for significant whitespace, distinct list/dict/tuple/set types, and comprehensions.

  • No $ on variables, no semicolons, no <?php β€” significant whitespace defines blocks
  • Four collection types (list, dict, tuple, set) where PHP has one array
  • Comprehensions β€” [n*2 for n in items] β€” replace array_map / array_filter
  • One == with no type juggling and no ===; is only for identity
  • Method calls with . and an explicit self instead of -> and implicit $this
  • pip and virtual environments in place of Composer and vendor/
CPre-Alpha

The machine underneath the web. PHP itself is written in C β€” this is the leap from a garbage-collected, dynamically typed scripting language down to manual memory, raw pointers, and a compiler that checks every type before the program runs.

  • Pointers and manual memory β€” malloc/free with no garbage collector; what a PHP variable hides
  • Static typing and a compile step β€” type errors are caught before the program runs, not at request time
  • Strings are char arrays ending in \0 β€” no string object, no .length, size buffers yourself
  • No associative arrays, no exceptions β€” you scan structs and check return codes by hand
  • Fixed-width integers that overflow, integer division that truncates, and == that compares addresses
RustPre-Alpha

Modern C, made memory-safe. Rust is a compiled systems language with no garbage collector β€” but where C hands you raw pointers, Rust gives you ownership and borrowing, no null, no exceptions, exhaustive matching, and traits, all checked before the program runs.

  • Ownership & borrowing β€” deterministic memory with no GC and no manual malloc/free
  • No null: absence is Option<T>, and the compiler makes you handle it
  • No exceptions: fallible code returns Result<T, E> with the ? operator
  • Immutable bindings by default; let mut to opt into mutation
  • Two string types β€” String (owned) and &str (borrowed) β€” where PHP has one
  • Traits and real generics instead of classes, inheritance, and mixed
TypeScriptAlpha⚑ Works Offline⚑ Offline

Gradual typing, taken further. PHP 8 gave you type declarations, union types, ?->, and ?? β€” TypeScript is that same instinct made structural and checked by a real compiler, sitting on top of the JavaScript runtime (one number type, ===, an event loop).

  • Union types (number | string) and nullable types β€” the same idea as PHP 8's int|string and ?string
  • Structural typing: a value fits an interface by shape, not by an implements clause
  • Real generics (<T>) and typed collections, where PHP has only @template docblocks
  • Types are erased at runtime β€” no enforcement, unlike PHP's runtime-checked declarations
  • The JavaScript runtime underneath: one number type, both null and undefined, and built-in async/await
C#Pre-Alpha

The language modern PHP keeps borrowing from. Match expressions, backed enums, named arguments, nullable types, readonly, first-class callables, string interpolation, and #[Attributes] all came to PHP from C# β€” so much of C# will feel like coming home, now compiled and statically typed.

  • Named arguments, ??, ?., and #[Attributes] β€” features PHP 8 adopted straight from C#
  • Compiled and statically typed: a real type checker catches bugs before the program runs
  • LINQ β€” Where/Select/GroupBy chains that read left-to-right, replacing nested array_map/array_filter
  • Records and init-only properties β€” value equality and immutability beyond PHP's readonly
  • Real properties with get/set instead of __get/__set magic methods
  • Built-in async/await and Task.WhenAll β€” concurrency PHP needs Fibers or Swoole for
JavaPre-Alpha⚑ Works Offline⚑ Offline

The enterprise backend PHP is so often weighed against. Java is statically typed, compiled to JVM bytecode, and object-oriented to the core β€” no top-level code, a main class, explicit types everywhere β€” trading PHP's quick-script feel for generics, streams, records, sealed types, and a checked-exception contract.

  • Everything lives in a class β€” no top-level functions; a main method is the entry point
  • Static typing & generics where PHP has mixed and @template docblocks
  • Streams (filter/map/collect) in place of array_map/array_filter
  • Records & sealed types with switch pattern matching β€” exhaustive, deconstructing
  • Checked exceptions: the compiler forces callers to handle declared failures
  • The famous traps: == vs .equals(), Integer caching, and NullPointerException
ErlangPre-Alpha

The language you inherit rather than choose. A PHP shop rarely picks Erlang β€” it ends up on call for RabbitMQ, ejabberd, CouchDB or the deepest layer of an Elixir dependency, and has to read the source. This page is angled at exactly that: the punctuation, the module header, the raw OTP callbacks and the three kinds of string, in the order you meet them opening a .erl file.

  • The punctuation is the real obstacle and it is learnable in a minute: comma is "and then", semicolon is "or else", period ends the sentence
  • Capitalization is syntax β€” Uppercase is a variable, lowercase is an atom, and a bare word you do not recognize is almost certainly a value rather than a name
  • {ok, Value} and {error, Reason} are the convention behind every API you will read, and {ok, X} = call() is an assertion that deliberately crashes
  • A gen_server file is two halves: the public API on top that sends messages, the callbacks below that run inside the process β€” and the return tuples are the whole protocol
  • The supervision tree is the architecture document; reading the supervisor modules tells you what a system is made of
  • 🚨 list_to_atom on user input can take a node down β€” the atom table is fixed-size and never garbage collected
ElmPre-Alpha

Your front end, with the errors moved to build time. PHP 8 already taught you type declarations, enums, match and ?-> β€” Elm is those instincts taken to the end of the road. Every type is checked before the program exists rather than when the line runs, null is not a value the language has, and there is no throw anywhere: markup is a typed value, not a string you assembled and hoped was valid HTML.

  • A type declaration is checked by the compiler, not at the call β€” a bad argument is a build failure, not a TypeError on somebody's request
  • There is no null: Maybe is a different type from String, so the null check cannot be forgotten the way ?string lets it be
  • No throw, no try, no catch β€” failure is a Result in the signature, visible to every caller instead of unwinding to one that lost the context
  • No template language at all: div [ attributes ] [ children ] is a function call, so htmlspecialchars has nothing to protect and an unclosed tag cannot exist
  • json_decode trusts the payload; a decoder states what you expect and fails at the boundary, naming the field the server renamed
  • The package registry computes the version bump by diffing the public API β€” a patch release that breaks you is impossible, not merely rude
ElixirPre-Alpha

The language that keeps running between requests. PHP builds a whole world, serves one request with it, and throws it away β€” which is why every PHP application reaches for Redis or the database to remember anything at all. The BEAM starts once and stays up, so state lives in memory, in processes that are cheap enough to have millions of, and a failure restarts one of them instead of the request.

  • A process is the thing PHP could not keep: a few hundred bytes, started in microseconds, holding state that outlives the request β€” a cache, a rate limiter or a connection pool with no external service behind it
  • Nothing is shared and nothing is mutable, so a message send copies the value and the entire category of race condition PHP avoids by discarding the world is instead impossible by construction
  • = is pattern matching, not assignment, and it reshapes everything: case takes data apart while it chooses, and a function gets several heads instead of a branching body
  • {:ok, value} / {:error, reason} replaces the exception you throw and the null that json_decode returns β€” the failure is in the return value, so it cannot be ignored by accident
  • One array becomes four collections β€” list, map, tuple and keyword list β€” each with costs you can feel, and options-array style survives as report(rows, separator: " | ")
  • There is no return, no while and no elseif: with replaces the stack of guard clauses, recursion replaces the loop, and cond replaces the chain
Drag cards to reorder Β· your order is saved locally