---
title: "Functions"
image: "https://hem.run/social/hem.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://hem.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Functions

Arrows are the only function form. No `function` keyword means no hoisting surprises and no dynamic `this`.

```hem
let clamp = (n: number, lo = 0, hi = 1) => Math.min(hi, Math.max(lo, n))
let map = <A, B>(xs: A[], f: (a: A) => B): B[] => xs.map(f)
let fetchJson = async (url: string) => await (await fetch(url)).json()
```

Functions are uncurried TypeScript functions, without automatic currying or labelled arguments. Use an options object, the TS idiom. Recursion, `async`/`await`, and top-level `await` are supported directly in the core language.

**Type guards and assertions** use checked inference or typed imports. Let the checker infer a predicate from a checked condition: `let isString = (x: unknown) => typeof x == "string"`. Explicit Hem-authored `x is T`, `asserts x is T`, and `asserts cond` signatures are refused with HEM2029 because their annotation does not verify their implementation. Imported assertion functions remain usable foreign contracts. For example, Effect's Schema module can validate an unknown input:

```hem
import * as Schema from "effect/Schema"

let uppercase = (value: unknown): string => {
  Schema.asserts(Schema.String, value)
  value.toUpperCase()
}
```

After `Schema.asserts(Schema.String, value)`, the imported assertion contract narrows `value` to `string`. The validator accepts an empty string and throws for non-string inputs. For authored validation, prefer checked narrowing and result values rather than promising an unchecked assertion signature.

This ordinary typed import does not require Hem's Effect extension.

Use an explicit trailing options object for named options. Hem does not add labels to positional parameters.

Source: https://hem.run/tour/functions/index.mdx
