---
# System prepended metadata

title: Spread operator ideas

---

# Spread operator ideas

## Definition

This is taken from [javascript documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax).

Spread syntax looks exactly like rest syntax. In a way, spread syntax is the opposite of rest syntax. Spread syntax "expands" an array into its elements, while rest syntax collects multiple elements and "condenses" them into a single element.

## Possible operators:
- `...expr` - This is probably best because it mirrors the rest operator
  - e.g. `...$var` - Referencing a variable and spreading it (used in examples below)
- `*expr`
- `expr*`
- `..` - Because `match` uses `..`

## Places allowed:

- Making lists
- Making records
- Making tables
- ~~Pattern matching~~ - When matching on lists and records, it uses `..$rest` rather than `...$rest` to mirror parameters (I guess that's because that's what Rust does?)

## Possible problems

- If someone has a command called `...` or`*`, then something like `{ ... (expr) }` could be intended as a closure that calls `...` on `(expr)`.
  - One possible fix is to require not having spaces between the spread operator and the expression.
  - Another possible "fix" is to tell users to use `^...`
- Not really a problem, but `match` uses `..` to match the remaining elements of lists and records. The fact that it's different might confuse people.

## Syntax

- `...` only recognized before `$variables`, `[lists]`, and `(subexpressions)` (no whitespace in between)
- No error signalled (yet) for `...` outside lists

## Examples
These examples are just thought starters. Nothing is "in stone" yet.

#### Example 1
Spread the `$rest` of parameters to command line arguments for external applications.
```
def test [...rest] {
  ^external_cmd ...$rest
}
```

#### Example 2
Spread the list into a command (nushell already does this)
```
let numbers = [1 2 3]
$numbers | math sum
```

#### Example 3
Spread the list into variables (not sure if this destructuring is included)
```
let numbers = [1 2 3 4]
let (a b c d) = ...$numbers
$a = 1
$b = 2
$c = 3
$d = 4
```

#### Example 4
Spread the string into a record?

```
let s = ..."test"
{"0": "t", "1": "e", "2": "s", "3": "t"}
```

> Note: spreading strings not supported, at least temporarily, as ambiguity about how to split

#### Example 5
Spread list into another list?
```
let parts = ["shoulders", "knees"];
let lyrics = ["head", ...$parts, "and", "toes"];
//  ["head", "shoulders", "knees", "and", "toes"]
```

#### Example 6

Spread list of lists into a table?

```
let list2d = [[1 2] [3 4]];
let table = [[x y]; ...$list2d];
// [[x y]; [1 2] [3 4]]
```

Error at runtime if too many columns
```
let list2d = [[1 2] [3 4 5 6]];
let table = [[x y]; ...$list2d];
// Error: too many columns, expected 2 but got 4
```

Error at runtime if too few columns (alternative: put in nulls)
```
let list2d = [[1 2] [3 4 5 6]];
let table = [[w x y z]; ...$list2d];
// Error: too few columns, expected 4 but got 2
```

#### Example 7

Bare strings
```
[...echo foo]
// Either [{"0": "e", "1": "c", "2": "h", "3": "o"} "foo"]
// or [["e", "c", "h", "o"] "foo"]
// (see example 4)
```

> Note: spreading strings not supported, at least temporarily, as ambiguity about how to split

#### Example 8

Passing arguments to fill in rest parameters (like Example 1)
```
def foo [bar: string, ...baz: string] {}
foo "quux" "xyzzy" ...$args "last"
// $baz would contain "xyzzy", the items in $args, and "last"
```

