From c9d4ab0865ade18c8db3b8a030d0edbd85aba957 Mon Sep 17 00:00:00 2001 From: Alex Snezhko Date: Fri, 10 Feb 2023 23:34:30 -0500 Subject: [PATCH 1/3] feat: Document arbitrary-position list spreads --- src/guide/lists.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/guide/lists.md b/src/guide/lists.md index 3e91f71d..45449e07 100644 --- a/src/guide/lists.md +++ b/src/guide/lists.md @@ -14,7 +14,7 @@ let numbers = [1, 2, 3] let strings = ["foo", "bar", "baz"] ``` -Lists in Grain are linked lists, so if we'd like to add a new item to a list, we add it to the front: +Lists in Grain are linked lists, so if we'd like to add a new item to a list, the preferred way is to add it to the front, which we can do with the spread syntax (`...`): ```grain let twoThree = [2, 3] @@ -23,6 +23,18 @@ let oneTwoThree = [1, ...twoThree] print(oneTwoThree) // [1, 2, 3] ``` +For convenience, it is also possible to use the spread syntax at any position in a list: + +```grain +let oneTwo = [1, 2] +let threeFour = [3, 4] +let result = [...oneTwo, ...threeFour, 5] + +print(result) // [1, 2, 3, 4, 5] +``` + +However, it is important to be aware of the **performance implications of arbitrary-position spreads**: in general, including a single spread at the end of a list expression is much more efficient than including a spread anywhere else as the latter requires copying the entire list(s) being spread. + We can also write functions that process data in lists, but we'll save that fun for the section on Pattern Matching. ## The List Standard Library From aef7fc967caa0bdf615dbd4463192d268c8e2f69 Mon Sep 17 00:00:00 2001 From: Alex Snezhko Date: Sat, 11 Feb 2023 12:40:26 -0500 Subject: [PATCH 2/3] update wording --- src/guide/lists.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/guide/lists.md b/src/guide/lists.md index 45449e07..c663470d 100644 --- a/src/guide/lists.md +++ b/src/guide/lists.md @@ -14,7 +14,7 @@ let numbers = [1, 2, 3] let strings = ["foo", "bar", "baz"] ``` -Lists in Grain are linked lists, so if we'd like to add a new item to a list, the preferred way is to add it to the front, which we can do with the spread syntax (`...`): +Lists in Grain are linked lists, so if we'd like to add a new item to a list, we add it to the front: ```grain let twoThree = [2, 3] @@ -23,7 +23,9 @@ let oneTwoThree = [1, ...twoThree] print(oneTwoThree) // [1, 2, 3] ``` -For convenience, it is also possible to use the spread syntax at any position in a list: +## More On Spreads (`...`) + +Although spreads are recommended to only be put at the end of a list, for convenience it is also possible to use the spread syntax at any position in a list: ```grain let oneTwo = [1, 2] @@ -33,7 +35,7 @@ let result = [...oneTwo, ...threeFour, 5] print(result) // [1, 2, 3, 4, 5] ``` -However, it is important to be aware of the **performance implications of arbitrary-position spreads**: in general, including a single spread at the end of a list expression is much more efficient than including a spread anywhere else as the latter requires copying the entire list(s) being spread. +However, it is important to be aware of the **performance implications of arbitrary-position spreads**. Grain lists are implemented as singly-linked lists, and therefore prepending new elements to the beginning of one is a very efficient operation (the last new element could then simply point to the list being extended). On the other hand, we do not get this same benefit if a spread appears somewhere other than at the end of a list expression. In this case, the entire list being spread will have to be copied one element at a time in order to create the new list while also not mutating the old list. We can also write functions that process data in lists, but we'll save that fun for the section on Pattern Matching. From ead99e182e2b13848d1f9adf9cde29c22ba1a3b1 Mon Sep 17 00:00:00 2001 From: Alex Snezhko Date: Sat, 11 Feb 2023 13:19:57 -0500 Subject: [PATCH 3/3] update wording pt 2 --- src/guide/lists.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/guide/lists.md b/src/guide/lists.md index c663470d..279b47fa 100644 --- a/src/guide/lists.md +++ b/src/guide/lists.md @@ -23,6 +23,8 @@ let oneTwoThree = [1, ...twoThree] print(oneTwoThree) // [1, 2, 3] ``` +We can also write functions that process data in lists, but we'll save that fun for the section on Pattern Matching. + ## More On Spreads (`...`) Although spreads are recommended to only be put at the end of a list, for convenience it is also possible to use the spread syntax at any position in a list: @@ -35,9 +37,9 @@ let result = [...oneTwo, ...threeFour, 5] print(result) // [1, 2, 3, 4, 5] ``` -However, it is important to be aware of the **performance implications of arbitrary-position spreads**. Grain lists are implemented as singly-linked lists, and therefore prepending new elements to the beginning of one is a very efficient operation (the last new element could then simply point to the list being extended). On the other hand, we do not get this same benefit if a spread appears somewhere other than at the end of a list expression. In this case, the entire list being spread will have to be copied one element at a time in order to create the new list while also not mutating the old list. +However, it is important to be aware of the **performance implications of arbitrary-position spreads**. Grain lists are immutable linked lists, and therefore prepending new elements to the beginning of one is a very efficient operation—the new element simply points to the list being extended! On the other hand, we do not get this same benefit if a spread appears somewhere other than at the end of a list expression. In this case, a brand new list must be created, copying one element at a time, pointing each one at the next, to point to the new elements at the end. -We can also write functions that process data in lists, but we'll save that fun for the section on Pattern Matching. +Use arbitrary-position spreads sparingly, only when they make your code more expressive and where performance isn't a major concern. ## The List Standard Library