Skip to content

Document spreads in the syntax lookup #1009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 3, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions misc_docs/syntax/language_spreads.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
id: "spreads"
keywords: ["spread", "record", "variant", "polymorphic", "array", "list", "function", "partial"]
name: "..."
summary: "This is the `...` syntax."
category: "languageconstructs"
---

A `spread` is three dots in a row: `...`. Spreads have many different uses in ReScript depending on in which context it is used.
## Record definitions
> Available in v10+

Spreads can be used to copy fields from one record definition into another.

```res
type a = {
id: string,
name: string,
}

type b = {
age: int
}

type c = {
...a,
...b,
active: bool
}
```

Read more about [record type spreads here](record.md#record-type-spread).

## Record immutable update
Spreads can be used for immutable updates of records:

```res
let meNextYear = {...me, age: me.age + 1}
```

Read more about [record immutable updates here](record.md#immutable-update).

## Variant definitions
> Available in v11+

Spreads can be used to copy constructors from one variant definition to another.

```res
type a = One | Two | Three
type b = | ...a | Four | Five
// b is now One | Two | Three | Four | Five
```

Read more about [variant type spreads](variant.md#variant-type-spreads) here.

## Variant pattern matching
> Available in v12+

You can refine the type of a variant by spreading compatible a variant when pattern matching:
```res
type pets = Cat | Dog
type fish = Cod | Salmon
type animals = | ...pets | ...fish

let isPet = (animal: animals) => {
switch animal {
| ...dog => Console.log("A dog!")
| _ => Console.log("Not a dog...")
}
}

```

Read more about [variant type spreads in pattern matching](pattern-matching-destructuring.md#match-on-subtype-variants).

## Polymorphic variant pattern matching
You can refine compatible polymorphic variants when pattern matching:

```res
type red = [#Ruby | #Redwood | #Rust]
type blue = [#Sapphire | #Neon | #Navy]

// Contains all constructors of red and blue.
// Also adds #Papayawhip
type color = [red | blue | #Papayawhip]

let myColor: color = #Ruby

switch myColor {
| #...blue => Console.log("This blue-ish")
| #...red => Console.log("This red-ish")
| other => Console.log2("Other color than red and blue: ", other)
}
```

Read more about [pattern matching and polymorphic variants](polymorphic-variant.md#combine-types-and-pattern-match).

## List immutable update
Spreads can be used for immutable updates of lists:

```res
let prepended = list{1, ...someOtherList}

// You can spread several lists, but it's O(n) so avoid it if possible
let multiple = list{1, ...prepended, ...anotherList}
```

Read more about [immutable list updates](array-and-list.md#immutable-prepend) here.

## List pattern matching
Spreads can be used when pattern matching on lists:

```res
let rec printStudents = (students) => {
switch students {
| list{} => () // done
| list{student} => Console.log("Last student: " ++ student)
| list{student1, ...otherStudents} =>
Console.log(student1)
printStudents(otherStudents)
}
}
printStudents(list{"Jane", "Harvey", "Patrick"})
```

Read more about [pattern matching on lists](pattern-matching-destructuring.md#match-on-list).

## Array immutable update
> Available in v11+

You can use spreads to add the contents of one array to another, just like in JavaScript:

```res
let firstArray = [1, 2, 3]
let secondArray = [...firstArray, 4, 5]
```

Read more about [array spreads](array-and-list.md#array-spreads).

## Partial application of functions
> Available in v11+ (uncurried mode)

You can partially apply a function using the spread syntax. Partially applying a function will return a new function taking only the arguments that wasn't applied partially.

```res
let add = (a, b) => a + b
let addFive = add(5, ...)
```

Read more about [partial application of functions](function.md#partial-application).

### References

* [Record type spreads](record.md#record-type-spread)
* [Record immutable updates](record.md#immutable-update)
* [Variant type spreads](variant.md#variant-type-spreads)
* [Variant type spreads in pattern matching](pattern-matching-destructuring.md#match-on-subtype-variants)
* [Pattern matching and polymorphic variants](polymorphic-variant.md#combine-types-and-pattern-match)
* [List immutable updates](array-and-list.md#immutable-prepend)
* [List pattern matching](pattern-matching-destructuring.md#match-on-list)
* [Array spreads](array-and-list.md#array-spreads)
* [Partial application of functions](function.md#partial-application)