From fc91195a0bb4aa4f9f8fde3a919b7199ab2f36da Mon Sep 17 00:00:00 2001 From: Philip Blair Date: Thu, 10 Jun 2021 15:06:09 -0700 Subject: [PATCH 1/5] feat(stdlib): Add Array.slice function --- stdlib/array.gr | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/stdlib/array.gr b/stdlib/array.gr index d74c52471..d48a7daf9 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -414,3 +414,47 @@ export let join = (separator: String, items: Array) => { Some(s) => s, } } + +/** + * Slices an array given zero-based start and end indexes. The character + * at the end index will not be included in the result. + * + * If either index is a negative number, it will be treated as a reverse index from + * the end of the array. e.g. slice(1, -1, [> 'a', 'b', 'c']) === 'b']. + * + * @param startIndex: Number The index of the array where the slice will begin (inclusive) + * @param endIndex: Number The index of the array where the slice will end (exclusive) + * @param array: Array The array to be sliced + * @returns Array The subset of the array that was sliced + */ +export let slice = (startIndex, endIndex, array) => { + // Note(blaine): Implementation taken directly from the String.slice method + // I wrote in Reason for Grain_utils.String + let arrayLength = length(array) + + let wrapNegativeIndex = idx => { + if (idx >= 0) { + idx + } else { + arrayLength + idx + } + } + + let startIndex = wrapNegativeIndex(startIndex) + let endIndex = wrapNegativeIndex(endIndex) + // Ensure we aren't working with an `end` value that is too big + let endIndex = if (endIndex > arrayLength) { + arrayLength + } else { + endIndex + } + + let newLength = endIndex - startIndex; + if (newLength < 0) { + [>] + } else if (newLength > arrayLength) { + array + } else { + init(newLength, n => array[startIndex + n]) + } +} From 261f688a03847fd4bcae2c8996076ecf78ad97a4 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Thu, 10 Jun 2021 15:06:28 -0700 Subject: [PATCH 2/5] chore: add tests --- compiler/test/stdlib/array.test.gr | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compiler/test/stdlib/array.test.gr b/compiler/test/stdlib/array.test.gr index d80237ed3..28ef1b6b4 100644 --- a/compiler/test/stdlib/array.test.gr +++ b/compiler/test/stdlib/array.test.gr @@ -269,3 +269,20 @@ assert Array.unique([>]) == [>] // Array.join assert Array.join(", ", [> "a", "b", "c"]) == "a, b, c" assert Array.join(", ", [>]) == "" + +// Array.slice +let testChars = [> 'a', 'b', 'c'] + +assert Array.slice(0, 1, testChars) == [> 'a'] +assert Array.slice(1, Array.length(testChars), testChars) == [> 'b', 'c'] +assert Array.slice(0, 0, testChars) == [>] +// Purposefully huge number +assert Array.slice(1, 10000, testChars) == [> 'b', 'c'] +// Negative indexing +assert Array.slice(1, -1, testChars) == [> 'b'] +assert Array.slice(-2, -1, testChars) == [> 'b'] +// Bad order +assert Array.slice(2, 1, testChars) == [>] +assert Array.slice(-1, -2, testChars) == [>] +// Empty +assert Array.slice(1, 4, [>]) == [>] From 9a72668daf4140005a4fad6095654d074e07d7a6 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sun, 13 Jun 2021 10:43:33 -0700 Subject: [PATCH 3/5] Update stdlib/array.gr Co-authored-by: Oscar Spencer --- stdlib/array.gr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/array.gr b/stdlib/array.gr index d48a7daf9..472e601be 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -416,7 +416,7 @@ export let join = (separator: String, items: Array) => { } /** - * Slices an array given zero-based start and end indexes. The character + * Slices an array given zero-based start and end indexes. The value * at the end index will not be included in the result. * * If either index is a negative number, it will be treated as a reverse index from From bd40a55d8ace516060e0dc7faf6d146beea211cd Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sun, 13 Jun 2021 10:44:36 -0700 Subject: [PATCH 4/5] Update stdlib/array.gr Co-authored-by: Oscar Spencer --- stdlib/array.gr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/array.gr b/stdlib/array.gr index 472e601be..aebb9ccfa 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -420,7 +420,7 @@ export let join = (separator: String, items: Array) => { * at the end index will not be included in the result. * * If either index is a negative number, it will be treated as a reverse index from - * the end of the array. e.g. slice(1, -1, [> 'a', 'b', 'c']) === 'b']. + * the end of the array. e.g. slice(1, -1, [> 'a', 'b', 'c']) == [> 'b']. * * @param startIndex: Number The index of the array where the slice will begin (inclusive) * @param endIndex: Number The index of the array where the slice will end (exclusive) From 54b9a3519324bcf34efcf5036e69d03fb40c49d4 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Mon, 14 Jun 2021 09:27:50 -0700 Subject: [PATCH 5/5] Update stdlib/array.gr Co-authored-by: Oscar Spencer --- stdlib/array.gr | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/array.gr b/stdlib/array.gr index aebb9ccfa..faa857f25 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -428,8 +428,6 @@ export let join = (separator: String, items: Array) => { * @returns Array The subset of the array that was sliced */ export let slice = (startIndex, endIndex, array) => { - // Note(blaine): Implementation taken directly from the String.slice method - // I wrote in Reason for Grain_utils.String let arrayLength = length(array) let wrapNegativeIndex = idx => {