---
title: "Loops"
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.

# Loops

```hem
for user in users { notify(user) }     // for..of semantics — values, not keys
for [k, v] in headers { log(k, v) }
for i in 0..batches { flush(i) }       // → for (let i = 0; i < batches; i++)
for i in 1..=retries { }               // inclusive
while queue.size > 0 { drain() }
while let Some(line) = input.next() { handle(line) }   // refutable head, re-tested each iteration
```

JS's key-iterating `for..in` is removed (use `Object.keys`), C-style `for` is replaced by ranges (which exist only in loop heads), and `break`/`continue` work as expected. Loops are statements-shaped: they yield no value.

**`while let`** binds the `let`-`else` refutable pattern set (§6) and re-evaluates the scrutinee each iteration, ending the loop the first time the pattern fails. It is the loop analogue of `let`-`else`, with `break` standing in for the diverging `else`. `Some`, constructor, literal, record, array, and `as`-alias patterns all work, the payload is body-scoped, and there is no `else` and no value. The pattern must be **refutable**: an always-matching head (a bare binding, `_`, or a record/array of only bindings) would spin forever and is refused; write a plain `while <condition>` instead.

```hem
let printLines = async (lines: AsyncIterable<string>) => {
  for await line in lines { console.log(line) }
}
```

```ts emitted
const printLines = async (lines: AsyncIterable<string>) => {
  for await (const line of lines) { console.log(line); }
};
```

`for await` iterates asynchronous values inside `async` arrows or at module top level, with the same patterns and `break`/`continue` as `for`. Ranges are synchronous (HEM3007); inside effect blocks it is refused (HEM4119), so use a `Stream`, `Effect.forEach` over an array, or an async helper defined outside the block and lift its Promise with `await`.

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