Example

This is a example file simular to odins demo file.

/**
 * Kotlin Language Demo
 *
 * Kotlin is a modern, statically typed programming language that runs on the JVM,
 * can be compiled to JavaScript, and supports native compilation via Kotlin/Native.
 * It is fully interoperable with Java and is the preferred language for Android development.
 *
 * # Learning Kotlin
 * Official Docs       - https://kotlinlang.org/docs/home.html
 * Kotlin Playground   - https://play.kotlinlang.org/
 * Kotlin by Example   - https://play.kotlinlang.org/byExample/overview
 * Standard Library    - https://kotlinlang.org/api/latest/jvm/stdlib/
 * Kotlin Koans        - https://kotlinlang.org/docs/koans.html
 */

// ─────────────────────────────────────────────────────────────────────────────
// Top-level declarations: functions, properties, and constants can live outside
// any class at the file level.
// ─────────────────────────────────────────────────────────────────────────────

const val APP_NAME = "KotlinDemo"  // compile-time constant (must be primitive or String)
val BUILD_YEAR = 2024              // top-level read-only property (val)
var runCount = 0                   // top-level mutable property (var)

// =============================================================================
// THE BASICS
// =============================================================================

fun theBasics() {
    println("\n# The Basics")

    // -- Variables ------------------------------------------------------------
    // `val` is immutable; `var` is mutable.
    val immutable: Int = 42
    var mutable: Int = 10
    mutable += 5

    // Type inference: the compiler deduces the type from the initializer.
    val inferred = "Hello, Kotlin"   // String
    val pi       = 3.14159           // Double
    val flag     = true              // Boolean

    // Explicit numeric types
    val byteVal:   Byte   = 127
    val shortVal:  Short  = 32_000        // underscores improve readability
    val intVal:    Int    = 1_000_000
    val longVal:   Long   = 9_000_000_000L
    val floatVal:  Float  = 2.718f        // 'f' suffix required for Float literals
    val doubleVal: Double = 1.0e9

    // Characters and strings
    val ch    = 'A'
    val nl    = '\n'
    val path  = "C:\\Windows\\notepad.exe"

    // Raw (multi-line) strings use triple quotes; no escape sequences needed.
    val rawPath = """C:\Windows\notepad.exe"""
    val poem = """
        Roses are red,
        Violets are blue,
        Kotlin is great,
        And so are you.
    """.trimIndent()

    // String templates: embed expressions directly with $ or ${...}
    val name = "World"
    println("Hello, $name!")
    println("2 + 2 = ${2 + 2}")
    println("PI ~ $pi, length of poem: ${poem.length} chars")

    // -- Null Safety ----------------------------------------------------------
    // Types are non-null by default. Append '?' to allow null.
    var nonNull: String  = "always here"
    var nullable: String? = null

    // Safe-call operator: returns null instead of throwing NPE
    println(nullable?.length)   // null

    // Elvis operator: provide a default when left side is null
    val len = nullable?.length ?: 0
    println("Length or default: $len")

    // Non-null assertion: throws if null (use sparingly)
    nullable = "now non-null"
    println(nullable!!.length)

    // -- Type Checks and Casts ------------------------------------------------
    val any: Any = "I am a String"
    if (any is String) {
        // Smart cast: compiler knows `any` is String inside this block
        println("Smart-cast length: ${any.length}")
    }

    val num: Number = 3.14
    val asDouble = num as Double           // unsafe cast (throws on failure)
    val asInt    = num as? Int             // safe cast (returns null on failure)
    println("asDouble=$asDouble, asInt=$asInt")

    @Suppress("UNUSED_VARIABLE")
    val unused = listOf(immutable, mutable, inferred, flag, byteVal, shortVal,
        intVal, longVal, floatVal, doubleVal, ch, nl, path, rawPath, nonNull)
}

// =============================================================================
// CONTROL FLOW
// =============================================================================

fun controlFlow() {
    println("\n# Control Flow")

    // -- if / else as an expression -------------------------------------------
    val x = 7
    val label = if (x % 2 == 0) "even" else "odd"
    println("$x is $label")

    val clamped = if (x < 0) 0 else if (x > 10) 10 else x
    println("clamped: $clamped")

    // -- when (like a supercharged switch) ------------------------------------
    // `when` is both a statement and an expression.
    val score = 85
    val grade = when {
        score >= 90 -> "A"
        score >= 80 -> "B"
        score >= 70 -> "C"
        score >= 60 -> "D"
        else        -> "F"
    }
    println("Score $score => Grade $grade")

    // Match against a value
    val day = 3
    when (day) {
        1       -> println("Monday")
        2       -> println("Tuesday")
        3, 4    -> println("Mid-week")        // multiple values per branch
        in 5..7 -> println("End of week")     // range check
        else    -> println("Unknown day")
    }

    // `when` with type checks (replaces long if-is chains)
    fun describe(obj: Any): String = when (obj) {
        is Int     -> "Integer: $obj"
        is String  -> "String of length ${obj.length}"
        is List<*> -> "List with ${obj.size} elements"
        else       -> "Unknown: $obj"
    }
    println(describe(42))
    println(describe("hi"))
    println(describe(listOf(1, 2, 3)))

    // -- for loops ------------------------------------------------------------
    for (i in 1..5)      print("$i ")   ; println()   // inclusive range
    for (i in 1 until 5) print("$i ")   ; println()   // exclusive upper bound
    for (i in 5 downTo 1 step 2) print("$i ") ; println()  // 5 3 1

    val fruits = listOf("apple", "banana", "cherry")
    for (fruit in fruits) print("$fruit ")
    println()

    // withIndex gives both index and value
    for ((index, fruit) in fruits.withIndex()) {
        println("  [$index] $fruit")
    }

    // -- while / do-while -----------------------------------------------------
    var count = 0
    while (count < 3) { print("${count++} ") } ; println()

    var n = 3
    do { print("${n--} ") } while (n > 0) ; println()

    // -- break and continue with labels ---------------------------------------
    outer@ for (i in 1..3) {
        for (j in 1..3) {
            if (j == 2) continue@outer  // skip to next outer iteration
            print("($i,$j) ")
        }
    }
    println()

    outer2@ for (i in 1..3) {
        for (j in 1..3) {
            if (i == 2 && j == 2) break@outer2
            print("($i,$j) ")
        }
    }
    println()
}

// =============================================================================
// FUNCTIONS
// =============================================================================

fun functionsDemo() {
    println("\n# Functions")

    // -- Default and named parameters -----------------------------------------
    fun greet(name: String, greeting: String = "Hello") = println("$greeting, $name!")
    greet("Alice")
    greet("Bob", greeting = "Hi")
    greet(greeting = "Hey", name = "Carol")

    // -- Vararg ---------------------------------------------------------------
    fun sum(vararg nums: Int, initial: Int = 0): Int {
        var result = initial
        for (n in nums) result += n
        return result
    }
    println("sum() = ${sum()}")
    println("sum(1,2,3) = ${sum(1, 2, 3)}")
    println("sum(initial=10, 1,2,3) = ${sum(1, 2, 3, initial = 10)}")

    // Spread operator (*) unpacks an array into a vararg parameter
    val odds = intArrayOf(1, 3, 5)
    println("sum(*odds) = ${sum(*odds)}")

    // -- Single-expression functions ------------------------------------------
    fun square(x: Int) = x * x
    fun max(a: Int, b: Int) = if (a > b) a else b
    println("square(7) = ${square(7)}, max(3,9) = ${max(3, 9)}")

    // -- Local functions ------------------------------------------------------
    fun factorial(n: Int): Long {
        fun go(acc: Long, remaining: Int): Long =
            if (remaining <= 1) acc else go(acc * remaining, remaining - 1)
        return go(1L, n)
    }
    println("10! = ${factorial(10)}")

    // -- Higher-order functions -----------------------------------------------
    fun applyTwice(x: Int, f: (Int) -> Int) = f(f(x))
    println("applyTwice(3, ::square) = ${applyTwice(3, ::square)}")

    fun compose(f: (Int) -> Int, g: (Int) -> Int): (Int) -> Int = { x -> f(g(x)) }
    val squareThenDouble = compose({ it * 2 }, ::square)
    println("squareThenDouble(4) = ${squareThenDouble(4)}")

    // -- Extension functions --------------------------------------------------
    // Add methods to existing types without subclassing.
    fun String.isPalindrome() = this == this.reversed()
    fun Int.isPrime(): Boolean {
        if (this < 2) return false
        for (i in 2..Math.sqrt(this.toDouble()).toInt()) {
            if (this % i == 0) return false
        }
        return true
    }

    println("\"racecar\".isPalindrome() = ${"racecar".isPalindrome()}")
    println("\"kotlin\".isPalindrome()  = ${"kotlin".isPalindrome()}")
    println("17.isPrime() = ${17.isPrime()}, 18.isPrime() = ${18.isPrime()}")

    // -- Infix functions ------------------------------------------------------
    infix fun Int.pow(exp: Int): Int {
        var result = 1
        repeat(exp) { result *= this }
        return result
    }
    println("2 pow 10 = ${2 pow 10}")

    // -- Tail-recursive functions ---------------------------------------------
    // `tailrec` asks the compiler to optimize the tail call into a loop.
    tailrec fun fibTail(n: Int, a: Long = 0L, b: Long = 1L): Long =
        if (n == 0) a else fibTail(n - 1, b, a + b)
    println("fib(50) = ${fibTail(50)}")
}

// =============================================================================
// LAMBDAS AND FUNCTIONAL PROGRAMMING
// =============================================================================

fun lambdasAndFP() {
    println("\n# Lambdas and Functional Programming")

    // -- Lambda syntax --------------------------------------------------------
    val double: (Int) -> Int = { x -> x * 2 }
    val add: (Int, Int) -> Int = { a, b -> a + b }
    println("double(5) = ${double(5)}, add(3,4) = ${add(3, 4)}")

    // Single-parameter lambdas can use `it`
    val triple: (Int) -> Int = { it * 3 }
    println("triple(4) = ${triple(4)}")

    // -- Collection transformations -------------------------------------------
    val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val evens   = numbers.filter { it % 2 == 0 }
    val squares = numbers.map { it * it }
    val total   = numbers.reduce { acc, n -> acc + n }
    val product = numbers.fold(1L) { acc, n -> acc * n }

    println("evens:   $evens")
    println("squares: $squares")
    println("sum:     $total")
    println("product: $product")

    val (evens2, odds) = numbers.partition { it % 2 == 0 }
    println("partition -> evens: $evens2, odds: $odds")

    val flattened = listOf(listOf(1, 2), listOf(3, 4), listOf(5)).flatten()
    println("flattened: $flattened")

    val words = listOf("hello world", "kotlin is great")
    val allWords = words.flatMap { it.split(" ") }
    println("flatMap words: $allWords")

    // groupBy, associateWith
    val byParity = numbers.groupBy { if (it % 2 == 0) "even" else "odd" }
    println("groupBy parity: $byParity")

    val squared = numbers.associateWith { it * it }
    println("associateWith square: $squared")

    // -- Sequences (lazy evaluation, like Java Streams) -----------------------
    // Sequences defer each step until the terminal operation, avoiding
    // the creation of intermediate lists for large data.
    val result = generateSequence(1) { it + 1 }  // infinite sequence
        .filter { it % 2 != 0 }                   // odd numbers
        .map { it * it }                           // squared
        .take(5)                                   // first 5
        .toList()
    println("First 5 odd squares (lazy): $result")

    // -- Closures -------------------------------------------------------------
    fun makeCounter(start: Int = 0): () -> Int {
        var count = start
        return { count++ }
    }
    val counter = makeCounter(10)
    println("counter: ${counter()}, ${counter()}, ${counter()}")  // 10, 11, 12
}

// =============================================================================
// CLASSES AND OBJECTS
// =============================================================================

// -- Primary constructor with property declarations ---------------------------
class Person(
    val name: String,
    var age: Int,
    private val email: String = ""
) {
    // Properties with custom getters/setters
    val isAdult: Boolean
        get() = age >= 18

    var nickname: String = name
        set(value) {
            field = value.trim()   // `field` refers to the backing field
        }

    // Secondary constructor must delegate to primary via `this(...)`
    constructor(name: String) : this(name, 0)

    // init block runs as part of the primary constructor
    init {
        require(age >= 0) { "Age must be non-negative" }
    }

    fun greet() = println("Hi, I'm $name (${if (isAdult) "adult" else "minor"})")

    // operator overloading
    operator fun compareTo(other: Person): Int = this.age.compareTo(other.age)

    override fun toString() = "Person(name=$name, age=$age)"
}

// -- Data classes -------------------------------------------------------------
// Automatically generates: equals, hashCode, toString, copy, componentN
data class Point(val x: Double, val y: Double) {
    fun distanceTo(other: Point) =
        Math.sqrt((x - other.x).let { it * it } + (y - other.y).let { it * it })
}

// -- Inheritance --------------------------------------------------------------
// Classes are `final` by default; `open` allows subclassing.
open class Shape(val color: String = "black") {
    open fun area(): Double = 0.0
    open fun describe() = println("Shape: color=$color, area=${area()}")
}

class Circle(val radius: Double, color: String = "red") : Shape(color) {
    override fun area() = Math.PI * radius * radius
    override fun describe() = println("Circle: r=$radius, area=${"%.2f".format(area())}, color=$color")
}

class Rectangle(val width: Double, val height: Double, color: String = "blue") : Shape(color) {
    override fun area() = width * height
    override fun describe() = println("Rectangle: ${width}x${height}, area=${area()}, color=$color")
}

// -- Abstract classes ---------------------------------------------------------
abstract class Animal(val name: String) {
    abstract fun sound(): String
    fun introduce() = println("I am $name and I go '${sound()}'")
}

class Dog(name: String) : Animal(name) {
    override fun sound() = "Woof"
}

class Cat(name: String) : Animal(name) {
    override fun sound() = "Meow"
}

fun classesAndObjects() {
    println("\n# Classes and Objects")

    val alice = Person("Alice", 30, "alice@example.com")
    alice.greet()
    alice.nickname = "  Ali  "
    println("nickname: '${alice.nickname}'")

    val p1 = Point(0.0, 0.0)
    val p2 = Point(3.0, 4.0)
    println("distance p1->p2: ${p1.distanceTo(p2)}")

    // `copy` with modified fields — data class feature
    val p3 = p2.copy(x = 6.0)
    println("p3 (copy of p2, x=6): $p3")

    // Destructuring via componentN functions
    val (x, y) = p2
    println("destructured: x=$x, y=$y")

    val shapes: List<Shape> = listOf(Circle(5.0), Rectangle(3.0, 4.0), Circle(1.0, "green"))
    shapes.forEach { it.describe() }
    println("Largest area: ${shapes.maxOf { it.area() }}")

    val animals = listOf(Dog("Rex"), Cat("Whiskers"), Dog("Buddy"))
    animals.forEach { it.introduce() }
}

// =============================================================================
// INTERFACES
// =============================================================================

interface Drawable {
    val strokeWidth: Int get() = 1       // property with default
    fun draw()                            // abstract
    fun drawWithBorder() {                // default implementation
        println("--- border ---")
        draw()
        println("--- border ---")
    }
}

interface Resizable {
    fun resize(factor: Double)
}

// A class can implement multiple interfaces
class Canvas(private val label: String) : Drawable, Resizable {
    private var scale = 1.0

    override fun draw() = println("Drawing '$label' at scale $scale")
    override fun resize(factor: Double) { scale *= factor }
}

fun interfacesDemo() {
    println("\n# Interfaces")
    val c = Canvas("Mona Lisa")
    c.draw()
    c.resize(2.0)
    c.drawWithBorder()
}

// =============================================================================
// SEALED CLASSES (closed type hierarchies — conceptually like Odin unions)
// =============================================================================

sealed class Result<out T> {
    data class Success<T>(val value: T)   : Result<T>()
    data class Failure(val error: String) : Result<Nothing>()
    object Loading                        : Result<Nothing>()
}

fun fetchUser(id: Int): Result<String> = when (id) {
    1    -> Result.Success("Alice")
    2    -> Result.Success("Bob")
    -1   -> Result.Loading
    else -> Result.Failure("User $id not found")
}

// Sealed classes make `when` exhaustive — the compiler warns if a branch is missing.
fun handleResult(result: Result<String>) = when (result) {
    is Result.Success -> println("Got user: ${result.value}")
    is Result.Failure -> println("Error: ${result.error}")
    Result.Loading    -> println("Loading...")
}

fun sealedClassesDemo() {
    println("\n# Sealed Classes")
    listOf(1, 2, 99, -1).map(::fetchUser).forEach(::handleResult)
}

// =============================================================================
// ENUM CLASSES
// =============================================================================

enum class Direction(val degrees: Int) {
    NORTH(0), EAST(90), SOUTH(180), WEST(270);

    fun opposite(): Direction = when (this) {
        NORTH -> SOUTH
        SOUTH -> NORTH
        EAST  -> WEST
        WEST  -> EAST
    }

    fun turnRight(): Direction = entries[(ordinal + 1) % entries.size]
}

fun enumClassesDemo() {
    println("\n# Enum Classes")
    Direction.entries.forEach { println("${it.name}: ${it.degrees} degrees") }

    val dir = Direction.NORTH
    println("Opposite of $dir: ${dir.opposite()}")
    println("Turn right from $dir: ${dir.turnRight()}")

    val d = Direction.valueOf("EAST")
    println("valueOf(\"EAST\") = $d")
}

// =============================================================================
// OBJECT DECLARATIONS AND COMPANION OBJECTS
// =============================================================================

// `object` is a singleton — instantiated lazily on first access.
object Registry {
    private val entries = mutableMapOf<String, String>()

    fun register(key: String, value: String) { entries[key] = value }
    fun lookup(key: String) = entries[key]
    override fun toString() = "Registry($entries)"
}

class Counter private constructor(initial: Int = 0) {
    var count = initial
        private set

    fun increment() { count++ }
    fun reset() { count = 0 }

    // Companion objects replace `static` members from Java.
    // They can implement interfaces and have extension functions.
    companion object Factory {
        private var instanceCount = 0

        fun create(start: Int = 0): Counter {
            instanceCount++
            return Counter(start)
        }

        fun totalCreated() = instanceCount
    }
}

fun objectsDemo() {
    println("\n# Objects and Companion Objects")

    Registry.register("lang", "Kotlin")
    Registry.register("version", "2.0")
    println(Registry)

    val c1 = Counter.create()
    val c2 = Counter.create(10)
    repeat(5) { c1.increment() }
    println("c1.count=${c1.count}, c2.count=${c2.count}")
    println("Counters created: ${Counter.totalCreated()}")

    // Object expressions create anonymous objects / ad-hoc implementations
    val clickHandler = object : Drawable {
        override fun draw() = println("Anonymous drawable drawn")
    }
    clickHandler.draw()
}

// =============================================================================
// GENERICS
// =============================================================================

// Generic class with an upper bound constraint
class Box<T : Comparable<T>>(val value: T) {
    fun isGreaterThan(other: Box<T>) = this.value > other.value
    override fun toString() = "Box($value)"
}

// Generic extension function
fun <T> List<T>.second(): T? = if (size >= 2) this[1] else null

// Reified generics: access type information at runtime (only in inline functions)
inline fun <reified T> List<*>.filterIsType(): List<T> =
    filterIsInstance<T>()

// Variance: `out` = covariant (producer), `in` = contravariant (consumer)
class Cage<out T : Animal>(private val animal: T) {
    fun getAnimal(): T = animal
}

fun genericsDemo() {
    println("\n# Generics")

    val boxA = Box(42)
    val boxB = Box(17)
    println("$boxA > $boxB ? ${boxA.isGreaterThan(boxB)}")

    val mixed: List<Any> = listOf(1, "two", 3.0, "four", 5)
    val strings = mixed.filterIsType<String>()
    println("strings from mixed list: $strings")

    // Covariance: Cage<Dog> can be assigned to Cage<Animal> because of `out`
    val dogCage: Cage<Dog> = Cage(Dog("Fido"))
    val animalCage: Cage<Animal> = dogCage
    println("animal in cage: ${animalCage.getAnimal().name}")
}

// =============================================================================
// DELEGATION
// =============================================================================

interface Logger {
    fun log(msg: String)
}

class ConsoleLogger : Logger {
    override fun log(msg: String) = println("[LOG] $msg")
}

// `by` delegates all Logger calls to the provided instance — eliminates boilerplate
class Service(logger: Logger = ConsoleLogger()) : Logger by logger {
    fun doWork() {
        log("Starting work")
        log("Work done")
    }
}

// -- Property delegation ------------------------------------------------------
class Config {
    // `lazy` initializes the value on first access (thread-safe by default)
    val heavyResource: String by lazy {
        println("  [lazy] Computing heavyResource...")
        "I was computed lazily"
    }

    // `observable` fires a callback on every assignment
    var status: String by kotlin.properties.Delegates.observable("idle") { _, old, new ->
        println("  [observable] status: $old -> $new")
    }

    // `vetoable` can reject an assignment by returning false
    var positiveOnly: Int by kotlin.properties.Delegates.vetoable(0) { _, _, new ->
        new >= 0
    }
}

fun delegationDemo() {
    println("\n# Delegation")

    val svc = Service()
    svc.doWork()

    val cfg = Config()
    println(cfg.heavyResource)   // triggers lazy init
    println(cfg.heavyResource)   // returns cached value

    cfg.status = "running"
    cfg.status = "stopped"

    cfg.positiveOnly = 5
    println("positiveOnly = ${cfg.positiveOnly}")   // 5
    cfg.positiveOnly = -1
    println("positiveOnly = ${cfg.positiveOnly}")   // still 5 — vetoed
}

// =============================================================================
// COROUTINES (structured concurrency)
// =============================================================================
// NOTE: Requires the `kotlinx-coroutines-core` dependency.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun coroutinesDemo() {
    println("\n# Coroutines")

    // -- Basic launch / async -------------------------------------------------
    runBlocking {
        // launch: fire-and-forget coroutine (returns Job)
        val job = launch {
            delay(100)
            println("Coroutine done")
        }

        // async: returns a Deferred<T> (like a Future/Promise)
        val deferred: Deferred<Int> = async {
            delay(50)
            42
        }

        println("Awaited: ${deferred.await()}")
        job.join()
    }

    // -- Flows (cold async streams, like Rx Observables) ----------------------
    fun countDown(): Flow<Int> = flow {
        for (i in 3 downTo 1) {
            delay(100)
            emit(i)
        }
    }

    runBlocking {
        countDown()
            .map { "T-$it" }
            .collect { println(it) }
    }

    // -- Channel (hot stream / CSP-style producer-consumer) -------------------
    runBlocking {
        val channel = Channel<Int>()
        launch { for (i in 1..5) { channel.send(i * i) } ; channel.close() }
        for (v in channel) print("$v ")
        println()
    }
}


// =============================================================================
// SCOPE FUNCTIONS: let, run, with, apply, also
// =============================================================================

fun scopeFunctionsDemo() {
    println("\n# Scope Functions")

    data class ServerConfig(
        var host: String = "localhost",
        var port: Int = 8080,
        var secure: Boolean = false
    )

    // `apply`: configures an object and returns the receiver itself
    val config = ServerConfig().apply {
        host   = "example.com"
        port   = 443
        secure = true
    }
    println("apply -> $config")

    // `also`: used for side-effects; returns the receiver
    val list = mutableListOf(1, 2, 3)
        .also { println("also: created list $it") }
        .also { it.add(4) }
    println("after also: $list")

    // `let`: transforms the receiver; the lambda result is returned
    val length = "Hello, Kotlin".let {
        println("let: processing '$it'")
        it.length
    }
    println("let result: $length")

    // `run`: like `let` but receiver becomes `this` inside the lambda
    val summary = config.run {
        "${if (secure) "https" else "http"}://$host:$port"
    }
    println("run -> $summary")

    // `with`: non-extension version of `run`; pass the receiver as an argument
    val info = with(config) {
        "Host=$host, Port=$port, Secure=$secure"
    }
    println("with -> $info")

    // Common idiom: null-safe block with `let`
    val maybeNull: String? = "present"
    maybeNull?.let { println("non-null value: '$it'") }
}

// =============================================================================
// COLLECTIONS IN DEPTH
// =============================================================================

fun collectionsDemo() {
    println("\n# Collections")

    // -- Immutable vs mutable -------------------------------------------------
    val immutableList = listOf(3, 1, 4, 1, 5, 9, 2, 6)
    val mutableList   = mutableListOf(3, 1, 4, 1, 5, 9, 2, 6)
    mutableList.add(5) ; mutableList.removeAt(0)

    val immutableMap  = mapOf("one" to 1, "two" to 2, "three" to 3)
    val mutableMap    = mutableMapOf("one" to 1, "two" to 2)
    mutableMap["four"] = 4

    val immutableSet  = setOf(1, 2, 2, 3, 3, 4)   // duplicates automatically removed
    val mutableSet    = mutableSetOf(1, 2, 3)
    mutableSet += 4

    println("list: $immutableList")
    println("map:  $immutableMap")
    println("set:  $immutableSet")

    // -- Sorting --------------------------------------------------------------
    println("sorted:     ${immutableList.sorted()}")
    println("sortedDesc: ${immutableList.sortedDescending()}")

    data class Employee(val name: String, val dept: String, val salary: Int)
    val employees = listOf(
        Employee("Zara", "Eng",  90_000),
        Employee("Alex", "HR",   60_000),
        Employee("Mia",  "Eng", 110_000),
        Employee("Ben",  "HR",   55_000),
    )

    // Sort by department ascending, then salary descending
    val sorted = employees.sortedWith(compareBy({ it.dept }, { -it.salary }))
    sorted.forEach { println("  ${it.dept} | ${it.name} | ${it.salary}") }

    // -- Windowing / chunking -------------------------------------------------
    val nums = (1..10).toList()
    println("chunked(3):    ${nums.chunked(3)}")
    println("windowed(4,2): ${nums.windowed(4, step = 2)}")

    // -- zip / unzip ----------------------------------------------------------
    val keys   = listOf("a", "b", "c")
    val values = listOf(1, 2, 3)
    val zipped = keys.zip(values)
    println("zipped: $zipped")
    val (ks, vs) = zipped.unzip()
    println("unzipped: $ks, $vs")
}

// =============================================================================
// DESTRUCTURING
// =============================================================================

fun destructuringDemo() {
    println("\n# Destructuring")

    // Data classes provide componentN functions automatically
    data class RGB(val r: Int, val g: Int, val b: Int)
    val (r, g, b) = RGB(255, 128, 0)
    println("r=$r, g=$g, b=$b")

    // Map entries destructure into key/value pairs
    val map = mapOf("x" to 10, "y" to 20, "z" to 30)
    for ((key, value) in map) println("  $key -> $value")

    // Lambda parameter destructuring
    val points = listOf(Point(1.0, 2.0), Point(3.0, 4.0))
    points.forEach { (x, y) -> println("  ($x, $y)") }

    // Use underscore to skip unused components
    data class Triple3(val a: Int, val b: Int, val c: Int)
    val (first, _, third) = Triple3(1, 2, 3)
    println("first=$first, third=$third")
}

// =============================================================================
// TYPE ALIASES AND INLINE VALUE CLASSES
// =============================================================================

typealias StringMap = Map<String, String>
typealias Predicate<T> = (T) -> Boolean

// Value classes wrap a single value with (usually) zero runtime overhead.
// The JVM represents them as the underlying type wherever possible.
@JvmInline
value class Metres(val amount: Double) {
    operator fun plus(other: Metres) = Metres(amount + other.amount)
    override fun toString() = "${amount}m"
}

@JvmInline
value class Seconds(val amount: Double) {
    override fun toString() = "${amount}s"
}

fun typeSystemDemo() {
    println("\n# Type Aliases and Inline Value Classes")

    val headers: StringMap = mapOf("Content-Type" to "application/json")
    println("headers: $headers")

    val isEven: Predicate<Int> = { it % 2 == 0 }
    println("isEven(4)=${isEven(4)}, isEven(5)=${isEven(5)}")

    val a = Metres(100.0)
    val b = Metres(42.5)
    println("$a + $b = ${a + b}")

    // Type safety: you cannot accidentally pass Seconds where Metres is expected
    val duration = Seconds(9.58)
    println("duration: $duration")
}

// =============================================================================
// OPERATOR OVERLOADING
// =============================================================================

data class Vector2(val x: Double, val y: Double) {
    operator fun plus(other: Vector2)  = Vector2(x + other.x, y + other.y)
    operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y)
    operator fun times(scalar: Double) = Vector2(x * scalar, y * scalar)
    operator fun unaryMinus()          = Vector2(-x, -y)
    operator fun get(index: Int) = when (index) {
        0    -> x
        1    -> y
        else -> throw IndexOutOfBoundsException("Index $index")
    }

    val magnitude get() = Math.sqrt(x * x + y * y)
    override fun toString() = "($x, $y)"
}

// Extension operators can be defined outside the class
operator fun Double.times(v: Vector2) = v * this

fun operatorOverloadingDemo() {
    println("\n# Operator Overloading")
    val a = Vector2(1.0, 2.0)
    val b = Vector2(3.0, 4.0)

    println("a=$a, b=$b")
    println("a + b = ${a + b}")
    println("a - b = ${a - b}")
    println("a * 3.0 = ${a * 3.0}")
    println("2.0 * b = ${2.0 * b}")
    println("-a = ${-a}")
    println("b[0]=${b[0]}, b[1]=${b[1]}")
    println("|b| = ${b.magnitude}")
}

// =============================================================================
// REFLECTION AND ANNOTATIONS
// =============================================================================

annotation class JsonField(val name: String = "")
annotation class Required

data class User(
    @JsonField("user_name") @Required val username: String,
    @JsonField("user_age")            val age: Int,
    val email: String     // no annotation
)

fun reflectionDemo() {
    println("\n# Reflection and Annotations")

    val kClass = User::class
    println("Class: ${kClass.simpleName}")
    println("Is data class: ${kClass.isData}")

    for (prop in kClass.memberProperties) {
        val jsonField = prop.annotations.filterIsInstance<JsonField>().firstOrNull()
        val required  = prop.annotations.filterIsInstance<Required>().firstOrNull()
        val jsonName  = if (jsonField != null && jsonField.name.isNotEmpty()) jsonField.name else prop.name
        println("  ${prop.name} -> json='$jsonName', required=${required != null}")
    }

    // Calling a constructor by reference via reflection
    val constructor = kClass.constructors.first()
    val user = constructor.call("alice", 30, "alice@example.com")
    println("Created via reflection: $user")
}

// =============================================================================
// DSL BUILDING (type-safe builders)
// =============================================================================

@DslMarker annotation class HtmlDsl

@HtmlDsl
class Tag(val name: String) {
    private val children = mutableListOf<Any>()
    private val attrs    = mutableMapOf<String, String>()

    fun attr(key: String, value: String) { attrs[key] = value }

    fun tag(name: String, block: Tag.() -> Unit): Tag {
        val child = Tag(name).also(block)
        children.add(child)
        return child
    }

    // `unaryPlus` on String allows `+"text"` syntax inside a builder block
    operator fun String.unaryPlus() { children.add(this) }

    override fun toString(): String {
        val attrStr = if (attrs.isEmpty()) "" else " " + attrs.entries.joinToString(" ") {
            "${it.key}=\"${it.value}\""
        }
        val body = children.joinToString("")
        return "<$name$attrStr>$body</$name>"
    }
}

fun html(block: Tag.() -> Unit) = Tag("html").also(block)

fun dslDemo() {
    println("\n# DSL Building (Type-Safe Builders)")

    val page = html {
        tag("head") {
            tag("title") { +"Kotlin DSL Demo" }
        }
        tag("body") {
            attr("class", "container")
            tag("h1") { +"Hello from Kotlin DSL" }
            tag("p")  { +"Type-safe HTML builders are a Kotlin superpower." }
        }
    }
    println(page)
}

// =============================================================================
// MAIN ENTRY POINT
// =============================================================================

fun main() {
    /*
     * For more Kotlin examples:
     *   Kotlin by Example   - https://play.kotlinlang.org/byExample/overview
     *   Kotlin GitHub       - https://github.com/JetBrains/kotlin
     *   Kotlin Koans        - https://kotlinlang.org/docs/koans.html
     *   Awesome Kotlin      - https://kotlin.link/
     */

    theBasics()
    controlFlow()
    functionsDemo()
    lambdasAndFP()
    classesAndObjects()
    interfacesDemo()
    sealedClassesDemo()
    enumClassesDemo()
    objectsDemo()
    genericsDemo()
    delegationDemo()
    scopeFunctionsDemo()
    collectionsDemo()
    destructuringDemo()
    typeSystemDemo()
    operatorOverloadingDemo()
    reflectionDemo()
    dslDemo()
    // coroutinesDemo()  // Uncomment if kotlinx-coroutines is on the classpath
}