{
 "meta": {
  "title": "Functions — The Crush Language Guide",
  "description": "Generated from crush/functions.md of The Crush Language Guide (https://docs.crushlang.org/crush/functions.html). Edit the guide, not this file: it is regenerated on every build.",
  "frontends": [
   "crush"
  ],
  "author": "The Crush Language Guide",
  "tags": {
   "source": "crush/functions.md",
   "guide_url": "https://docs.crushlang.org/crush/functions.html",
   "generator": "scripts/build-notebooks.py"
  }
 },
 "cells": [
  {
   "id": "crush-functions-md-1",
   "kind": {
    "type": "markdown"
   },
   "source": "# Functions\n\nThis chapter covers defining and calling functions. Crush functions are named,\ntop-level declarations. **Functions are not first-class values yet** — you can\ncall one by name, but you can't store it in a variable or pass it as an argument\n(see [Higher-order functions](#higher-order-functions-and-lambdas)).\n\n## Defining functions\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-1",
   "kind": {
    "type": "crush"
   },
   "source": "fn greet(name: String) {\n    print(\"Hello, \" + name + \"!\")\n}\n\nfn add(a: Int, b: Int) -> Int {\n    return a + b\n}\n\ngreet(\"Alice\")\nprint(add(5, 3))\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "runnable"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:10",
      "browser": "run",
      "expect_output": "Hello, Alice!\n8\n"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-3",
   "kind": {
    "type": "markdown"
   },
   "source": "- Parameter and return **type hints are optional**. When present they are checked\n  at compile time at call sites (`add(\"x\", 1)` is a compile error).\n- The number of arguments is checked at compile time: `add(1)` →\n  `Function 'add' expects 2 arguments, found 1`.\n- There are no default parameter values (`fn f(x = 1)` is a parse error) and no\n  variadic parameters.\n- A function may be called before its definition appears in the file.\n\n## Returning values\n\nReturn with `return`. A function that falls off the end — or uses a bare\n`return` — yields `null`. A final expression is **not** an implicit return:\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-2",
   "kind": {
    "type": "crush"
   },
   "source": "fn check_sign(x: Int) -> String {\n    if x > 0 {\n        return \"positive\"\n    } else if x < 0 {\n        return \"negative\"\n    }\n    return \"zero\"\n}\n\nfn log_message(msg: String) {\n    print(\"[LOG] \" + msg)\n}\n\nprint(check_sign(5))\nprint(check_sign(-2))\nprint(check_sign(0))\nlog_message(\"done\")\nprint(log_message(\"again\"))\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "runnable"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:42",
      "browser": "run",
      "expect_output": "positive\nnegative\nzero\n[LOG] done\n[LOG] again\nnull\n"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-5",
   "kind": {
    "type": "markdown"
   },
   "source": "The return-type hint is not checked against what the body actually returns\ntoday: `fn f() -> Int { return \"s\" }` compiles.\n\n## Recursion\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-3",
   "kind": {
    "type": "crush"
   },
   "source": "fn factorial(n: Int) -> Int {\n    if n <= 1 {\n        return 1\n    }\n    return n * factorial(n - 1)\n}\n\nfn fib(n) {\n    if n < 2 {\n        return n\n    }\n    return fib(n - 1) + fib(n - 2)\n}\n\nprint(factorial(5))\nprint(fib(15))\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "runnable"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:78",
      "browser": "run",
      "expect_output": "120\n610\n"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-7",
   "kind": {
    "type": "markdown"
   },
   "source": "Mutual recursion works too. Recursion depth is capped by the VM's call-depth\nquota — **256 frames by default** (`--max-call-depth N` on `crush-run`); exceeding\nit ends the program with `call depth quota exceeded`. The other default quotas are\n1,000,000 instructions (`--max-steps`), a 4096-slot stack (`--max-stack`), 1 MiB of\noutput (`--max-output`), and a 30-second wall-clock limit per polyglot block.\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-4",
   "kind": {
    "type": "crush"
   },
   "source": "fn d(n) {\n    return d(n - 1)\n}\n\nfn main() {\n    print(d(1))\n}\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "expected-failure"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:110",
      "browser": "fail",
      "why": "this example shows a run-time error",
      "expect_error": "call depth quota exceeded"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-9",
   "kind": {
    "type": "markdown"
   },
   "source": "## Higher-order functions and lambdas\n\n> **Not yet implemented.** Passing a function by name (`apply(double, 21)`),\n> storing one in a variable (`let f = double`), and anonymous functions\n> (`|x| { ... }`, `|x| => x * 2`) all fail to compile. The lexer reads a bare `|`\n> as an identifier, so the lambda parser is unreachable (crush-ast **CRUSH-75**,\n> open); closures that capture variables are a separate, larger gap. Until then,\n> write ordinary named functions and call them directly, or use the\n> pipeline operator (`x |> f`), which does accept a function **name**:\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-5",
   "kind": {
    "type": "crush"
   },
   "source": "fn double(n) {\n    return n * 2\n}\n\nfn main() {\n    let f = double\n    print(f(21))\n}\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "expected-failure"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:128",
      "browser": "fail",
      "why": "not implemented yet (CRUSH-75); Run shows what happens today"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-6",
   "kind": {
    "type": "crush"
   },
   "source": "fn main() {\n    let double = |x| { return x * 2 }\n    print(double(21))\n}\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "expected-failure"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:137",
      "browser": "fail",
      "why": "not implemented yet (CRUSH-75); Run shows what happens today"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-7",
   "kind": {
    "type": "crush"
   },
   "source": "fn double(n) {\n    return n * 2\n}\nfn inc(n) {\n    return n + 1\n}\nprint(5 |> double |> inc)\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "runnable"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:142",
      "browser": "run",
      "expect_output": "11\n"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-13",
   "kind": {
    "type": "markdown"
   },
   "source": "## Concurrency: `spawn`, `yield`, `async`, `await`\n\nThese keywords are in the grammar, but the end-to-end path is incomplete: a\nprogram that contains `spawn f()`, `async fn`, or `await` is rejected by the\nassembler (`SPAWN takes 1 operand(s), got 0`). The AI/concurrency opcodes are\ntracked under crush-ast **CRUSH-1** / **CRUSH-34**. A bare `yield` statement\ncompiles and runs (it is a no-op without a spawned task).\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  },
  {
   "id": "crush-functions-8",
   "kind": {
    "type": "crush"
   },
   "source": "fn worker() {\n    print(\"worker\")\n}\n\nfn main() {\n    spawn worker()\n    yield\n    print(\"main\")\n}\n",
   "state": {
    "status": "pending"
   },
   "meta": {
    "tags": [
     "guide",
     "expected-failure"
    ],
    "extra": {
     "guide": {
      "src": "crush/functions.md:166",
      "browser": "fail",
      "why": "not implemented yet (CRUSH-34); Run shows what happens today"
     }
    }
   },
   "outputs": []
  },
  {
   "id": "crush-functions-md-15",
   "kind": {
    "type": "markdown"
   },
   "source": "## Best practices\n\n- Keep functions small and give parameters type hints — they document the\n  interface and catch mistakes at compile time.\n- Pass data in as parameters: functions cannot see top-level variables\n  ([Variables](https://docs.crushlang.org/crush/variables.html#module-level-variables-are-not-visible-inside-functions)).\n- Prefer descriptive names (`calculate_total_price`, not `calc`).\n\n## Next Steps\n\n- **[Capability System](https://docs.crushlang.org/crush/capabilities.html)**\n- **[Polyglot Programming](https://docs.crushlang.org/crush/polyglot.html)**\n",
   "state": {
    "status": "done"
   },
   "meta": {},
   "outputs": []
  }
 ]
}
