thecodex.expert · The Codex Family of Knowledge
Language Comparison

Syntax Across 11 Languages

Same concept, 11 implementations — see how Python, JavaScript, Java, TypeScript, Go, Rust, C++, Kotlin, Swift, SQL, and C handle the fundamentals side by side.

11 languages 20 concepts Click a language to filter

Hello World

The minimum runnable program.

Python
print("Hello, World!")
JavaScript
console.log("Hello, World!");
Java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
TypeScript
console.log("Hello, World!");
Go
package main
import "fmt"
func main() {
    fmt.Println("Hello, World!")
}
Rust
fn main() {
    println!("Hello, World!");
}
C++
#include <iostream>
int main() {
    std::cout << "Hello, World!\n";
}
Kotlin
fun main() {
    println("Hello, World!")
}
Swift
print("Hello, World!")
C
#include <stdio.h>
int main(void) {
    printf("Hello, World!\n");
    return 0;
}

Variables and Constants

Declaring mutable variables and immutable constants.

Pythonno explicit const
x = 42           # variable (re-assignable)
name = "Alice"   # type inferred
PI = 3.14159     # convention: UPPER = constant
JavaScript
let x = 42;          // mutable
const name = "Alice"; // immutable binding
const PI = 3.14159;
Java
int x = 42;              // mutable
String name = "Alice";
final double PI = 3.14;  // immutable
TypeScript
let x: number = 42;   // explicit type
let name = "Alice";   // inferred: string
const PI = 3.14159;   // const — immutable
Go
var x int = 42      // explicit
x := 42             // shorthand (inferred)
name := "Alice"
const PI = 3.14159
Rustimmutable by default
let x = 42;          // immutable
let mut y = 42;      // mutable
let name = "Alice";
const PI: f64 = 3.14159;
C++
int x = 42;
auto name = std::string("Alice"); // inferred
constexpr double PI = 3.14159;   // compile-time const
Kotlin
var x = 42          // mutable (inferred Int)
val name = "Alice"  // immutable reference
const val PI = 3.14159  // compile-time const
Swift
var x = 42          // mutable (inferred Int)
let name = "Alice"  // immutable (let = constant)
let PI = 3.14159
C
int x = 42;
char name[] = "Alice";
const double PI = 3.14159; // const
#define MAX 100  // preprocessor constant

Functions

Defining and calling a function with parameters and return value.

Python
def add(a: int, b: int) -> int:
    return a + b

result = add(3, 4)  # 7
JavaScript
function add(a, b) { return a + b; }
const addArrow = (a, b) => a + b;

add(3, 4);       // 7
addArrow(3, 4);  // 7
Java
static int add(int a, int b) {
    return a + b;
}
int result = add(3, 4);  // 7
TypeScript
function add(a: number, b: number): number {
    return a + b;
}
const addArrow = (a: number, b: number): number => a + b;
Gomultiple returns
func add(a, b int) int { return a + b }

// Multiple return values (idiomatic)
func divide(a, b float64) (float64, error) {
    if b == 0 { return 0, errors.New("div/0") }
    return a / b, nil
}
Rust
fn add(a: i32, b: i32) -> i32 {
    a + b  // last expression = return value
}
let result = add(3, 4);  // 7
C++
int add(int a, int b) { return a + b; }
auto addLambda = [](int a, int b) { return a + b; };

add(3, 4);        // 7
addLambda(3, 4);  // 7
Kotlin
fun add(a: Int, b: Int): Int = a + b
// Single-expression shorthand ↑

fun divide(a: Double, b: Double): Double? =
    if (b == 0.0) null else a / b
Swift
func add(_ a: Int, _ b: Int) -> Int { a + b }
// _ suppresses argument label at call site

let result = add(3, 4)  // 7
C
int add(int a, int b) { return a + b; }

int result = add(3, 4);  /* 7 */

Classes and Data Structures

Defining a type that groups data and behaviour.

Python
from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    def distance(self) -> float:
        return (self.x**2 + self.y**2)**0.5

p = Point(3.0, 4.0)
print(p.distance())  # 5.0
JavaScript
class Point {
    #x; #y;  // private fields
    constructor(x, y) { this.#x = x; this.#y = y; }
    distance() { return Math.hypot(this.#x, this.#y); }
    get x() { return this.#x; }
}
const p = new Point(3, 4);
p.distance();  // 5
Java
record Point(double x, double y) {
    double distance() {
        return Math.hypot(x, y);
    }
}
var p = new Point(3, 4);
p.distance();  // 5.0
TypeScript
class Point {
    constructor(
        private readonly x: number,
        private readonly y: number
    ) {}
    distance() { return Math.hypot(this.x, this.y); }
}
const p = new Point(3, 4);
p.distance();  // 5
Gostruct + methods
type Point struct { X, Y float64 }

func (p Point) Distance() float64 {
    return math.Hypot(p.X, p.Y)
}
p := Point{3, 4}
p.Distance()  // 5.0
Rust
struct Point { x: f64, y: f64 }

impl Point {
    fn distance(&self) -> f64 {
        (self.x*self.x + self.y*self.y).sqrt()
    }
}
let p = Point { x: 3.0, y: 4.0 };
p.distance()  // 5.0
C++
struct Point {
    double x, y;
    double distance() const {
        return std::hypot(x, y);
    }
};
Point p{3.0, 4.0};
p.distance();  // 5.0
Kotlin
data class Point(val x: Double, val y: Double) {
    fun distance() = Math.hypot(x, y)
}
val p = Point(3.0, 4.0)
p.distance()  // 5.0
Swift
struct Point {
    let x: Double
    let y: Double
    func distance() -> Double { hypot(x, y) }
}
let p = Point(x: 3, y: 4)
p.distance()  // 5.0
Cno methods
typedef struct { double x, y; } Point;

double distance(const Point *p) {
    return sqrt(p->x*p->x + p->y*p->y);
}
Point p = {3.0, 4.0};
distance(&p);  /* 5.0 */

Null / Optional Values

How each language represents "no value" and forces you to handle it.

PythonNone — no compile check
name: str | None = None    # Optional type hint (Python 3.10+)
length = len(name) if name else 0
result = name or "default" # falsy check
JavaScript
let name = null;
// Optional chaining — no throw
const len = name?.length;       // undefined
const display = name ?? "anon"; // nullish coalescing
Java
Optional<String> name = Optional.empty();
name.map(String::length)         // Optional.empty
    .orElse(0);                   // 0
name.ifPresent(System.out::println);
TypeScript
let name: string | null = null;
const len = name?.length;         // undefined
const display = name ?? "anon";   // "anon"
Gonil + comma-ok idiom
var name *string = nil
// Check before use
if name != nil { fmt.Println(len(*name)) }

// Comma-ok for maps/channels
val, ok := myMap["key"]
if ok { use(val) }
RustOption<T> — no null
let name: Option<&str> = None;
let len = name.map(|s| s.len()).unwrap_or(0);
if let Some(n) = name { println!("{}", n); }
let display = name.unwrap_or("anon");
C++
std::optional<std::string> name = std::nullopt;
auto len = name.has_value() ? name->length() : 0;
auto display = name.value_or("anon");
Kotlincompile-time null safety
val name: String? = null
val len = name?.length ?: 0   // safe call + Elvis
val display = name ?: "anon"
name?.let { println(it) }     // only if non-null
Swift
let name: String? = nil
let len = name?.count ?? 0     // optional chaining + ??
let display = name ?? "anon"
if let n = name { print(n) }  // if let binding
CNULL pointer — no safety
char *name = NULL;
/* Must check manually — no compile enforcement */
if (name != NULL) { printf("%zu\n", strlen(name)); }
const char *display = name ? name : "anon";

Error Handling

How each language propagates and handles failures.

Pythonexceptions
try:
    result = int("bad")
except ValueError as e:
    print(f"Error: {e}")
else:
    print("Success:", result)  # no exception
finally:
    print("always runs")
JavaScript
try {
    const n = JSON.parse("bad");
} catch (e) {
    if (e instanceof SyntaxError) console.error(e.message);
    else throw e;  // re-throw unexpected errors
}
Java
try {
    int n = Integer.parseInt("bad");
} catch (NumberFormatException e) {
    System.err.println(e.getMessage());
} finally {
    System.out.println("cleanup");
}
TypeScript
function parse(s: string): Result<number, string> {
    const n = Number(s);
    return isNaN(n) ? { ok: false, error: "NaN" }
                    : { ok: true, value: n };
}
Goerrors as values
n, err := strconv.Atoi("bad")
if err != nil {
    fmt.Println("error:", err)
    return  // handle at call site
}
// n is valid here
RustResult<T,E> + ?
fn parse(s: &str) -> Result<i32, _> {
    let n = s.parse::<i32>()?;  // ? propagates error
    Ok(n)
}
match parse("42") {
    Ok(n)  => println!("{}", n),
    Err(e) => println!("{}", e),
}
C++
try {
    int n = std::stoi("bad");
} catch (const std::invalid_argument& e) {
    std::cerr << e.what();
} catch (const std::exception& e) {
    std::cerr << e.what();
}
Kotlin
val n = "bad".toIntOrNull()  // null on failure (idiomatic)
    ?: throw IllegalArgumentException("bad input")

// Or: runCatching wraps exceptions
val result = runCatching { "42".toInt() }
result.onSuccess { println(it) }
      .onFailure { println(it.message) }
Swift
do {
    let data = try JSONDecoder().decode(User.self, from: raw)
} catch let e as DecodingError {
    print("Decode failed: \(e)")
} catch {
    print("Unknown: \(error)")
}
Creturn codes + errno
FILE *f = fopen("file.txt", "r");
if (f == NULL) {
    perror("fopen");  /* prints errno message */
    return -1;
}
/* use f */
fclose(f);

Loops

Iterating over a range and over a collection.

Python
for i in range(10): print(i)

items = ["a", "b", "c"]
for item in items: print(item)
for i, item in enumerate(items): print(i, item)
JavaScript
for (let i = 0; i < 10; i++) console.log(i);
for (const item of items) console.log(item);
items.forEach((item, i) => console.log(i, item));
Java
for (int i = 0; i < 10; i++) System.out.println(i);
for (String item : items) System.out.println(item);
IntStream.range(0, items.size())
    .forEach(i -> System.out.println(i + " " + items.get(i)));
TypeScript
for (let i = 0; i < 10; i++) console.log(i);
for (const item of items) console.log(item);
items.forEach((item, i) => console.log(i, item));
Goonly for keyword
for i := 0; i < 10; i++ { fmt.Println(i) }
for _, item := range items { fmt.Println(item) }
for i, item := range items { fmt.Println(i, item) }
Rust
for i in 0..10 { println!("{}", i); }
for item in &items { println!("{}", item); }
for (i, item) in items.iter().enumerate() {
    println!("{} {}", i, item);
}
C++
for (int i = 0; i < 10; i++) std::cout << i << "\n";
for (const auto& item : items) std::cout << item << "\n";
for (size_t i = 0; i < items.size(); i++)
    std::cout << i << " " << items[i] << "\n";
Kotlin
for (i in 0..9) println(i)           // inclusive
for (i in 0 until 10) println(i)    // exclusive
for ((i, item) in items.withIndex()) println("$i $item")
Swift
for i in 0..<10 { print(i) }          // half-open
for item in items { print(item) }
for (i, item) in items.enumerated() { print(i, item) }
C
for (int i = 0; i < 10; i++) printf("%d\n", i);
/* Array iteration — must know size */
for (int i = 0; i < n; i++) printf("%s\n", items[i]);

Arrays and Lists

Dynamic arrays / lists — create, append, access, slice.

Python
nums = [1, 2, 3]
nums.append(4)        # [1, 2, 3, 4]
nums[0]               # 1
nums[-1]              # 4 (last)
nums[1:3]             # [2, 3] (slice)
len(nums)             # 4
JavaScript
const nums = [1, 2, 3];
nums.push(4);         // [1, 2, 3, 4]
nums[0];              // 1
nums.at(-1);          // 4 (last)
nums.slice(1, 3);     // [2, 3]
nums.length;          // 4
Java
var nums = new ArrayList<>(List.of(1, 2, 3));
nums.add(4);          // [1, 2, 3, 4]
nums.get(0);          // 1
nums.get(nums.size()-1); // 4
nums.subList(1, 3);   // [2, 3]
nums.size();          // 4
Goslice type
nums := []int{1, 2, 3}
nums = append(nums, 4)   // [1 2 3 4]
nums[0]                  // 1
nums[len(nums)-1]        // 4
nums[1:3]                // [2 3]
len(nums)                // 4
Rust
let mut nums = vec![1, 2, 3];
nums.push(4);          // [1, 2, 3, 4]
nums[0];               // 1
nums.last();           // Some(4)
&nums[1..3];           // &[2, 3] (slice)
nums.len();            // 4
C++
std::vector<int> nums{1, 2, 3};
nums.push_back(4);     // [1, 2, 3, 4]
nums[0];               // 1
nums.back();           // 4
// No direct slice — use iterators
nums.size();           // 4
Kotlin
val nums = mutableListOf(1, 2, 3)
nums.add(4)             // [1, 2, 3, 4]
nums[0]                 // 1
nums.last()             // 4
nums.subList(1, 3)      // [2, 3]
nums.size               // 4
Swift
var nums = [1, 2, 3]
nums.append(4)          // [1, 2, 3, 4]
nums[0]                 // 1
nums.last               // Optional(4)
nums[1...2]             // ArraySlice: [2, 3]
nums.count              // 4
Cfixed arrays only
int nums[] = {1, 2, 3};  /* fixed-size */
int n = 3;
/* No append — must realloc for dynamic */
nums[0];                 /* 1 */
nums[n-1];               /* 3 (last) */
sizeof(nums)/sizeof(nums[0]);  /* 3 */

Maps and Dictionaries

Key-value data structures — create, get, set, iterate.

Python
d = {"name": "Alice", "age": 30}
d["email"] = "a@b.c"   # set
d.get("name")          # "Alice"
d.get("x", "default")  # "default"
for k, v in d.items(): print(k, v)
JavaScript
const m = new Map([["name","Alice"],["age",30]]);
m.set("email", "a@b.c");
m.get("name");          // "Alice"
for (const [k, v] of m) console.log(k, v);
// Object literal: { name: "Alice", age: 30 }
Java
var m = new HashMap<>(Map.of("name","Alice","age",30));
m.put("email", "a@b.c");
m.get("name");              // "Alice"
m.getOrDefault("x", "def"); // "def"
m.forEach((k, v) -> System.out.println(k + ": " + v));
Go
m := map[string]any{"name": "Alice", "age": 30}
m["email"] = "a@b.c"
v, ok := m["name"]  // comma-ok: check existence
for k, v := range m { fmt.Println(k, v) }
Rust
use std::collections::HashMap;
let mut m = HashMap::from([("name","Alice")]);
m.insert("email", "a@b.c");
m.get("name");              // Some("Alice")
m.get("x").unwrap_or("def");
for (k, v) in &m { println!("{}: {}", k, v); }
C++
std::unordered_map<std::string,int> m;
m["age"] = 30;
m.at("age");          // 30 (throws if missing)
m.count("age");       // 1 if exists
for (auto& [k,v] : m) std::cout << k << ": " << v;
Kotlin
val m = mutableMapOf("name" to "Alice", "age" to 30)
m["email"] = "a@b.c"
m["name"]               // "Alice"
m.getOrDefault("x","def")
m.forEach { (k,v) -> println("$k: $v") }
Swift
var m: [String: Any] = ["name":"Alice","age":30]
m["email"] = "a@b.c"
m["name"]                    // Optional("Alice")
m["x", default: "def"]       // "def"
for (k, v) in m { print("\(k): \(v)") }
Cno built-in — use struct array
/* No built-in map — manual approach */
typedef struct { char key[64]; int value; } KV;
KV map[] = {{"name",0},{"age",30}};
/* Or use a hash table library like uthash */

Closures / Anonymous Functions

Functions that capture variables from their surrounding scope.

Python
def make_adder(n):
    return lambda x: x + n  # captures n

add5 = make_adder(5)
add5(3)  # 8
JavaScript
const makeAdder = (n) => (x) => x + n;
const add5 = makeAdder(5);
add5(3);  // 8
Java
Function<Integer,Integer> makeAdder(int n) {
    return x -> x + n;  // n must be effectively final
}
var add5 = makeAdder(5);
add5.apply(3);  // 8
TypeScript
const makeAdder = (n: number) => (x: number): number => x + n;
const add5 = makeAdder(5);
add5(3);  // 8
Go
func makeAdder(n int) func(int) int {
    return func(x int) int { return x + n }
}
add5 := makeAdder(5)
add5(3)  // 8
Rust
fn make_adder(n: i32) -> impl Fn(i32) -> i32 {
    move |x| x + n  // move: capture n by value
}
let add5 = make_adder(5);
add5(3);  // 8
C++
auto makeAdder = [](int n) {
    return [n](int x) { return x + n; };  // captures n by value
};
auto add5 = makeAdder(5);
add5(3);  // 8
Kotlin
fun makeAdder(n: Int): (Int) -> Int = { x -> x + n }
val add5 = makeAdder(5)
add5(3)  // 8
Swift
func makeAdder(_ n: Int) -> (Int) -> Int {
    return { x in x + n }  // n captured
}
let add5 = makeAdder(5)
add5(3)  // 8
Cno closures — use struct
/* No closures — simulate with function pointer + context */
typedef struct { int n; } Adder;
int add(Adder *ctx, int x) { return ctx->n + x; }
Adder ctx = {5};
add(&ctx, 3);  /* 8 */

Async / Concurrent Operations

Running non-blocking I/O and waiting for results.

Python
import asyncio

async def fetch(id: int) -> str:
    await asyncio.sleep(0.1)
    return f"data-{id}"

async def main():
    # Concurrent: both run at the same time
    a, b = await asyncio.gather(fetch(1), fetch(2))
    print(a, b)

asyncio.run(main())
JavaScript
async function fetch(id) {
    await new Promise(r => setTimeout(r, 100));
    return `data-${id}`;
}
const [a, b] = await Promise.all([fetch(1), fetch(2)]);
console.log(a, b);
Java
CompletableFuture<String> f1 = CompletableFuture
    .supplyAsync(() -> "data-1");
CompletableFuture<String> f2 = CompletableFuture
    .supplyAsync(() -> "data-2");
CompletableFuture.allOf(f1, f2).join();
System.out.println(f1.get() + " " + f2.get());
TypeScript
async function fetch(id: number): Promise<string> {
    await new Promise(r => setTimeout(r, 100));
    return `data-${id}`;
}
const [a, b] = await Promise.all([fetch(1), fetch(2)]);
Go
func fetch(id int) string {
    time.Sleep(100 * time.Millisecond)
    return fmt.Sprintf("data-%d", id)
}
// Concurrent with goroutines + channel
ch := make(chan string, 2)
go func() { ch <- fetch(1) }()
go func() { ch <- fetch(2) }()
a, b := <-ch, <-ch
Rustrequires tokio
async fn fetch(id: u32) -> String {
    tokio::time::sleep(Duration::from_millis(100)).await;
    format!("data-{}", id)
}
let (a, b) = tokio::join!(fetch(1), fetch(2));
println!("{} {}", a, b);
C++
auto f1 = std::async(std::launch::async,
    []{ return std::string("data-1"); });
auto f2 = std::async(std::launch::async,
    []{ return std::string("data-2"); });
std::cout << f1.get() << " " << f2.get();
Kotlin
suspend fun fetch(id: Int): String {
    delay(100)
    return "data-$id"
}
// Concurrent with async
val (a, b) = coroutineScope {
    async { fetch(1) } to async { fetch(2) }
}.let { (a, b) -> a.await() to b.await() }
Swift
func fetch(id: Int) async -> String {
    try? await Task.sleep(nanoseconds: 100_000_000)
    return "data-\(id)"
}
async let a = fetch(id: 1)   // concurrent
async let b = fetch(id: 2)   // concurrent
let (ra, rb) = await (a, b)
CPOSIX threads
#include <pthread.h>
void *worker(void *arg) {
    /* do work */
    return "result";
}
pthread_t t1, t2;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);

Generics / Type Parameters

Writing functions and types that work for any type.

Python
from typing import TypeVar
T = TypeVar("T")

def first(items: list[T]) -> T | None:
    return items[0] if items else None

first([1, 2, 3])   # 1 (int)
first(["a", "b"])  # "a" (str)
JavaScriptdynamic — no generics
// No generics — dynamic typing
function first(items) {
    return items.length > 0 ? items[0] : null;
}
first([1, 2, 3]);   // 1
first(["a", "b"]);  // "a"
Javatype erasure at runtime
<T> Optional<T> first(List<T> items) {
    return items.isEmpty() ? Optional.empty()
                           : Optional.of(items.get(0));
}
first(List.of(1, 2, 3));       // Optional[1]
first(List.of("a", "b"));      // Optional[a]
TypeScript
function first<T>(items: T[]): T | undefined {
    return items[0];
}
first([1, 2, 3]);   // 1 — inferred: number
first(["a", "b"]);  // "a" — inferred: string
GoGo 1.18+
func First[T any](items []T) (T, bool) {
    if len(items) == 0 {
        var zero T; return zero, false
    }
    return items[0], true
}
First([]int{1, 2, 3})       // 1, true
First([]string{"a", "b"})   // "a", true
Rust
fn first<T>(items: &[T]) -> Option<&T> {
    items.first()
}
first(&[1, 2, 3]);     // Some(1)
first(&["a", "b"]);    // Some("a")
C++reified at compile time
template<typename T>
std::optional<T> first(const std::vector<T>& v) {
    return v.empty() ? std::nullopt : std::optional(v[0]);
}
first(std::vector{1,2,3});       // 1
first(std::vector{"a"s,"b"s});   // "a"
Kotlin
fun <T> first(items: List<T>): T? = items.firstOrNull()

first(listOf(1, 2, 3))      // 1
first(listOf("a", "b"))     // "a"
Swift
func first<T>(_ items: [T]) -> T? { items.first }

first([1, 2, 3])    // Optional(1)
first(["a", "b"])   // Optional("a")
Cvoid* for generics
/* No generics — use void* with size parameter */
void* first(void *arr, size_t elem_size, size_t count) {
    return count > 0 ? arr : NULL;
}
int nums[] = {1,2,3};
int *f = first(nums, sizeof(int), 3);  /* 1 */

Pattern Matching

Branching on the shape or type of a value.

PythonPython 3.10+
match command:
    case "quit":          exit()
    case "help" | "?":    show_help()
    case ["go", dir]:     move(dir)
    case {"action": a}:   handle(a)
    case _:               print("unknown")
JavaScriptno native — use switch
switch (command) {
    case "quit": exit(); break;
    case "help": showHelp(); break;
    default: console.log("unknown");
}
// Or discriminated union pattern with if/typeof
JavaJava 21 + sealed
String result = switch (shape) {
    case Circle c    -> "circle r=" + c.radius();
    case Rectangle r -> "rect " + r.w() + "x" + r.h();
    case Triangle t  -> "triangle";
    // exhaustive — no default needed
};
TypeScript
// Discriminated union
function handle(msg: Message): string {
    switch (msg.kind) {
        case "quit":    return "bye";
        case "move":    return `move to ${msg.dir}`;
        case "write":   return msg.text;
    }
}
Go
switch v := i.(type) {
case int:    fmt.Println("int:", v)
case string: fmt.Println("string:", v)
case bool:   fmt.Println("bool:", v)
default:     fmt.Println("other")
}
Rustmost powerful matching
match value {
    0           => println!("zero"),
    1..=9       => println!("single digit"),
    n if n < 0  => println!("negative: {}", n),
    n           => println!("large: {}", n),
}
C++std::visit for variant
std::visit([](auto&& arg) {
    using T = std::decay_t<decltype(arg)>;
    if constexpr (std::is_same_v<T, int>)
        std::cout << "int: " << arg;
    else if constexpr (std::is_same_v<T, std::string>)
        std::cout << "string: " << arg;
}, myVariant);
Kotlin
when (value) {
    is Int    -> println("int: $value")
    is String -> println("string: $value")
    in 1..10  -> println("in range")
    null      -> println("null")
    else      -> println("other")
}
Swift
switch value {
case 0:           print("zero")
case 1..<10:      print("small")
case let n where n < 0: print("negative \(n)")
case is String:   print("it's a String")
default:          print("other")
}
Cswitch integers only
switch (value) {
    case 0:   printf("zero\n");   break;
    case 1:   printf("one\n");    break;
    default:  printf("other\n");
}
/* Strings: use if/strcmp chain */

String Interpolation

Embedding values inside string literals.

Python
name, age = "Alice", 30
f"Hello {name}, you are {age}!"
f"{'upper'.upper()}"  # expressions work
JavaScript
const name = "Alice", age = 30;
`Hello ${name}, you are ${age}!`
`${age >= 18 ? "adult" : "minor"}`  // expressions
Java
// Text block + formatted (Java 15+)
String.format("Hello %s, you are %d!", name, age);
// Java 21 string templates (preview):
// STR."Hello \{name}, you are \{age}!"
TypeScript
const name = "Alice", age = 30;
`Hello ${name}, you are ${age}!`
`${age >= 18 ? "adult" : "minor"}`
Go
name, age := "Alice", 30
fmt.Sprintf("Hello %s, you are %d!", name, age)
// No native interpolation — use fmt.Sprintf
Rust
let name = "Alice"; let age = 30;
format!("Hello {name}, you are {age}!")
// Named directly in {} since Rust 1.58
C++
auto name = "Alice"; int age = 30;
std::format("Hello {}, you are {}!", name, age)  // C++20
// Before C++20: ostringstream or snprintf
Kotlin
val name = "Alice"; val age = 30
"Hello $name, you are $age!"
"${name.uppercase()} — ${if (age>=18) "adult" else "minor"}"
Swift
let name = "Alice"; let age = 30
"Hello \(name), you are \(age)!"
"\(age >= 18 ? "adult" : "minor")"
C
char buf[128];
snprintf(buf, sizeof(buf), "Hello %s, age %d!", name, age);
/* snprintf — safe; never use sprintf */

Type System Snapshot

Key characteristics of each language's type system.

Python
Dynamic, duck-typed.
Types checked at runtime.
Type hints (PEP 484) are optional
annotations — enforced by mypy/pyright
not the interpreter.
No compile-time type checking.
JavaScript
Dynamic, weakly typed.
Coercions: "5" - 1 == 4
           "5" + 1 == "51"
typeof null === "object" (historical bug)
No compile-time checks.
Java
Static, nominal, strong.
Checked at compile time.
Type erasure: List<String> and List<Integer>
are the same at runtime.
Autoboxing: int ↔ Integer.
TypeScript
Static, structural typing.
Types erased at compile time.
string is a subtype of {} and any.
strict: true required for full safety.
any disables type checking entirely.
Go
Static, structural interfaces.
Interfaces satisfied implicitly.
No inheritance — only composition.
Generics added in 1.18 (2022).
Strong: no implicit coercion.
Rust
Static, nominal, affine types.
Ownership enforced at compile time.
No null — Option<T> instead.
No exceptions — Result<T,E>.
Lifetimes: references always valid.
C++
Static, nominal.
Templates: compile-time reification.
RTTI available but slow — often avoided.
Implicit conversions can cause bugs.
Concepts (C++20) constrain templates.
Kotlin
Static, nominal, null-safe.
Nullable types (T?) in the type system.
Smart casts after null/type checks.
Structural typing via interfaces.
Reified generics in inline functions.
Swift
Static, nominal, protocol-oriented.
Optional<T> (T?) is an enum, not null.
Value types (struct/enum) preferred.
Generics: compile-time specialisation.
Sendable: type-level concurrency safety.
C
Static, nominal, weakly typed.
Implicit conversions between numerics.
void*: type-unsafe generic pointer.
No generics — templates, macros instead.
Signed overflow: undefined behaviour.

Memory Management

How each language manages object lifetimes and memory.

PythonGC + refcount
Reference counting + cycle-detecting GC.
CPython: GIL limits true parallelism.
Memory freed when refcount hits 0.
del removes a reference, not the object.
Finalizers (__del__) are unreliable.
JavaScriptGC
Tracing GC (V8: generational).
Non-deterministic collection.
WeakRef / FinalizationRegistry for
  weak references (ES2021).
No manual control.
JavaGC
Generational GC (G1, ZGC, Shenandoah).
Stop-the-world pauses (minimised by ZGC).
Stack: primitives + references.
Heap: all objects.
try-with-resources for deterministic close.
GoGC
Tri-color mark-and-sweep GC.
Very low pause times (<1ms target).
Escape analysis: compiler moves to heap
  only what must escape the stack.
runtime.GC() for manual trigger.
Rustno GC
Ownership + borrow checker at compile time.
Freed when owner goes out of scope (Drop).
No GC pauses — deterministic deallocation.
Rc<T>: shared (single-threaded).
Arc<T>: shared (multi-threaded).
C++RAII / manual
RAII: resources freed when object destroyed.
unique_ptr: sole ownership (no overhead).
shared_ptr: shared via atomic refcount.
Stack objects: freed at scope exit.
new/delete: manual (avoid in modern C++).
KotlinJVM GC
JVM GC (same as Java).
use { } for AutoCloseable resources.
Primitive types (Int, Double) compiled
  to JVM primitives where possible.
No manual memory management.
SwiftARC
Automatic Reference Counting (ARC).
Deterministic — freed when refcount hits 0.
No GC pauses.
weak/unowned: break retain cycles.
Value types (struct): copied on assignment.
Cfully manual
Fully manual: malloc/free.
Stack: local variables, freed on return.
Heap: malloc/calloc — must free exactly once.
No GC, no RAII, no smart pointers.
Buffer overflow, UAF: undefined behaviour.

Modules and Imports

Organising code across files and importing from other modules.

Python
import os
import os.path
from pathlib import Path
from typing import Optional, List

# Relative import (inside package)
from .utils import helper
JavaScript
import { add } from "./math.mjs";    // named
import Calculator from "./calc.mjs"; // default
import * as math from "./math.mjs";  // namespace
const lazy = await import("./heavy.mjs"); // dynamic
Java
import java.util.List;
import java.util.Optional;
import java.util.*;          // wildcard
import static Math.PI;       // static import
TypeScript
import { add } from "./math";
import type { User } from "./types"; // type-only import
export { add, multiply };
export default class Calculator {}
Go
import (
    "fmt"
    "math"
    "github.com/user/pkg"  // external module
    m "mymodule/math"      // alias
    _ "mymodule/init"      // side-effect only
)
Rust
use std::collections::HashMap;
use std::io::{self, Read, Write};
// External: declare in Cargo.toml, then:
use serde::{Deserialize, Serialize};
pub mod utils;  // declare a module
C++
#include <vector>
#include <string>
#include "myheader.hpp"
// C++20 modules:
import std;
import mymodule;
Kotlin
import kotlin.math.*
import java.util.Optional
import com.example.MyClass
import com.example.MyClass as Alias
Swift
import Foundation
import UIKit
import SwiftUI
// Internal files: same module = visible
// No explicit import needed for same module
C
#include <stdio.h>    // system header
#include <stdlib.h>
#include "myheader.h" // local header
// No namespace — everything is global

Concurrency Model

How each language approaches concurrent and parallel execution.

Python
asyncio: single-thread cooperative (I/O).
threading: OS threads — GIL limits CPU.
multiprocessing: true parallelism (no GIL).
concurrent.futures: high-level thread/process pool.
GIL: Global Interpreter Lock (CPython only).
JavaScript
Single-threaded event loop.
async/await: cooperative, non-blocking I/O.
Promises: asynchronous values.
Web Workers / Worker Threads: separate threads.
No shared mutable state between workers.
Java
OS threads (1:1).
Virtual threads (Java 21): M:N — millions possible.
CompletableFuture: async composition.
synchronized / locks: mutual exclusion.
Structured concurrency (preview, Java 21).
Go
Goroutines: M:N (GMP scheduler).
~2KB stack each — millions possible.
Channels: communicate by sharing.
sync.Mutex / sync.RWMutex for shared state.
context: cancellation propagation.
Rust
OS threads (std::thread) — no data races.
Compile-time: Send + Sync enforce thread safety.
async/await: cooperative (Tokio/async-std).
Arc<Mutex<T>>: shared mutable across threads.
Rayon: data-parallel iterators.
C++
OS threads (std::thread).
std::mutex, std::atomic.
std::async / std::future: task-based.
Coroutines (C++20): stackless cooperative.
No compile-time data-race prevention.
Kotlin
Coroutines: M:N via CPS transformation.
Dispatchers: Main, IO, Default.
StateFlow / SharedFlow: reactive streams.
Structured concurrency: CoroutineScope.
Channel: coroutine communication.
Swift
async/await: cooperative (5.5+).
Actors: compile-time isolation.
@MainActor: main thread guarantee.
Sendable: type-level thread safety (Swift 6).
Cooperative thread pool: bounded size.
C
POSIX threads (pthreads).
pthread_mutex_t for locking.
No compile-time safety — races are UB.
_Atomic / stdatomic.h for atomic ops.
OpenMP for parallel computation.