# 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" ```