From f0db198a15c605683da9b7c0ab773988fbf1808c Mon Sep 17 00:00:00 2001 From: Oscar Spencer Date: Sat, 17 Dec 2022 17:19:54 -0600 Subject: [PATCH 1/2] feat: Document arrays and loops --- docs_config.yml | 4 +- src/guide/arrays.md | 103 ++++++++++++++++++++++++++++++++++++++++++++ src/guide/loops.md | 69 +++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/guide/arrays.md create mode 100644 src/guide/loops.md diff --git a/docs_config.yml b/docs_config.yml index e6524713..06f82004 100644 --- a/docs_config.yml +++ b/docs_config.yml @@ -38,9 +38,11 @@ docs_groups: The Guide: - guide/hello_world - guide/basics + - guide/mutation - guide/functions - guide/lists - - guide/mutation + - guide/arrays + - guide/loops - guide/data_types - guide/pattern_matching - guide/imports_exports diff --git a/src/guide/arrays.md b/src/guide/arrays.md new file mode 100644 index 00000000..60ed3da9 --- /dev/null +++ b/src/guide/arrays.md @@ -0,0 +1,103 @@ +--- +title: Arrays +--- + +An alternative to lists, arrays are fixed-length containers for ordered data. Individual elements can be swapped out for other elements, and individual elements can be retrieved quickly. + +## Creating and Using Arrays + +Like lists, arrays always contain elements of the same type, and attempting to mix element types will result in a compilation error. + +```grain +let empty = [>] +let numbers = [> 1, 2, 3] +let strings = [> "foo", "bar", "baz"] +``` + +Unlike lists, we can easily access elements at any (zero-based) index: + +```grain +let strings = [> "foo", "bar", "baz"] + +print(strings[0]) // "foo" +print(strings[1]) // "bar" +print(strings[2]) // "baz" +``` + +We can also use negative indexes to access elements from the end of the array: + +```grain +let strings = [> "foo", "bar", "baz"] + +print(strings[-1]) // "baz" +print(strings[-2]) // "bar" +print(strings[-3]) // "foo" +``` + +If we try to access an element beyond the length of the array, we'll get an `IndexOutOfBounds` error. + +## Updaing Arrays + +One of the major benefits arrays have is the ability to change the values it contains. We can update an array's values like so: + +```grain +let strings = [> "foo", "bar", "baz"] + +print(strings) // [> "foo", "bar", "baz"] + +strings[1] = "qux" + +print(strings) // [> "foo", "qux", "baz"] +``` + +In some cases, this could allow us to write programs that are more efficient than if we used a list. + +However, the size of an array is fixed. To add additonal items to an array, we must append them together, which would create a brand new, third array: + +```grain +import Array from "array" + +let one = [> 1] +let twoThree = [> 2, 3] +let oneTwoThree = Array.append(one, twoThree) + +print(oneTwoThree) // [> 1, 2, 3] +``` + +Since `oneTwoThree` is a brand new array, updating values in `one` or `twoThree` doesn't affect the values in `oneTwoThree`. + +For long arrays, even when adding just one element, this could be a fairly expensive operation. For programs that need to do this kind of operation, lists may be a better choice. We discuss this in more detail in the section below. + +To learn more about what's available in the Array standard library, check out the [array standard library documentation](https://grain-lang.org/docs/stdlib/array). + +## Lists vs. Arrays + +Lists and arrays are similar constructs, but each has its own pros and cons. It's up to you to choose which is right for your use case! + +Lists are excellent because they're + +- immutable +- efficient at adding additional elements +- efficient at removing elements +- easy to work with +- less succeptible to bugs + +Lists might not be the right choice because they're + +- unable to be modified +- inefficient at accessing random elements +- inefficient at determining the number of elements + +Arrays are excellent because they're + +- able to be modified after creation +- efficient at accessing random elements +- efficient at determining the number of elements + +Arrays might not be the right choice because they're + +- inefficient at adding additonal elements +- inefficient at removing elements +- more succeptible to bugs + +As a rule of thumb, lists are the idiomatic choice in Grain! Lean towards using lists whenever possible and use arrays when it makes your code easier to understand. diff --git a/src/guide/loops.md b/src/guide/loops.md new file mode 100644 index 00000000..43583240 --- /dev/null +++ b/src/guide/loops.md @@ -0,0 +1,69 @@ +--- +title: Loops +--- + +Loops allow you to repeat an action over and over (and over). + +## While Loops + +The most basic loop is the `while` loop. The code within the loop repeats until the condition is `false`. + +```grain +let mut i = 0 + +while (i < 10) { + print("looping!") + i += 1 +} +``` + +Loops can skip to the next iteration using the `continue` keyword. For example, to print only the odd numbers from zero to ten: + +```grain +let mut i = 0 + +while (i < 10) { + if (i % 2 == 0) continue + print(i) + i += 1 +} +``` + +Use the `break` keyword to exit from a loop entirely: + +```grain +let mut i = 0 + +while (true) { + if (i < 10) { + print("forever?") + i += 1 + } else { + break + } +} +``` + +## For Loops + +`for` loops are just like `while` loops, just with more structure. `for` loops accept an optional initializer statement which runs before the loop, an optional condition statement which runs before each iteration, and an optional increment statement which runs after each iteration. + +`for` loops are commonly used to iterate arrays: + +```grain +import Array from "array" + +let strings = [> "foo", "bar", "baz"] + +for (let mut i = 0; i < Array.length(strings); i += 1) { + print(strings[i]) +} +``` + +As all of the loop parameters are optional, they can all be omitted (though the semicolons are still required). Omitting the condition results in an infinite loop: + +```grain +for (;;) { + print("forever!") +} +``` From a75ef84aff32b384a1f74e1a04a4dc0036404c23 Mon Sep 17 00:00:00 2001 From: Oscar Spencer Date: Sat, 17 Dec 2022 18:04:07 -0600 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Blaine Bublitz --- src/guide/arrays.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guide/arrays.md b/src/guide/arrays.md index 60ed3da9..d9e24d55 100644 --- a/src/guide/arrays.md +++ b/src/guide/arrays.md @@ -36,9 +36,9 @@ print(strings[-3]) // "foo" If we try to access an element beyond the length of the array, we'll get an `IndexOutOfBounds` error. -## Updaing Arrays +## Updating Arrays -One of the major benefits arrays have is the ability to change the values it contains. We can update an array's values like so: +One of the major benefits of an array is the ability to change the values it contains. We can update an array's values like so: ```grain let strings = [> "foo", "bar", "baz"] @@ -84,7 +84,7 @@ Lists are excellent because they're Lists might not be the right choice because they're -- unable to be modified +- unable to be modified in place - inefficient at accessing random elements - inefficient at determining the number of elements