3.1.10 arrays
3.1.10.1 The Array Type
By default, Pyret users should use this library. If, however, you need a higher-performant but potentially less ergonomic array library, look at RawArray instead, which is primarily reserved for internal use and for building other libraries. However, do not use that library unless you really cannot get what you need out of this one.
Because arrays are mutable, equality is not straightforward. Learn more at equality.
3.1.10.2 Using Arrays in Programs
Some of the names provided for arrays inevitably overlap with those provided for other data. Therefore, using the include form is likely to cause name-clashes. It is wiser to import arrays using a prefix name and use the names below through that prefix.
import arrays as A check: a = A.array-of("a", 3) a is=~ [A.array: "a", "a", "a"] A.array-length(a) is 3 end
3.1.10.3 Constructing Arrays
Constructs an Array with the given elements. Note that Arrays are mutable, so comparisons using == (the operator for equal-always) will only return true on Arrays when they are also identical, regardless of their contents. To compare the elements use equal-now/=~, and test using is=~.
import arrays as A check: a = [A.array: 1, 2, 3] a is a a is== a [A.array: 1, 2, 3] is=~ [A.array: 1, 2, 3] [A.array: 1, 2, 3] is-not== [A.array: 1, 2, 3] [A.array: 1, 2, 3] is-not [A.array: 1, 2, 3] end
Constructs an Array of length count, where every element is the value given as value.
Note that value is not copied, so, the elements of Arrays created with array-of will always be identical.
To create an array of arrays where each sub-array is independent of the other, use build-array.
Similar to raw-array-of.
import arrays as A check: arr = A.array-of(true, 2) arr is=~ [A.array: true, true] arr is-not [A.array: true, true] A.array-get-now(arr, 0) is<=> A.array-get-now(arr, 1) A.array-set-now(arr, 1, false) arr is=~ [A.array: true, false] arr-of-arrs = A.array-of(arr, 3) arr-of-arrs is=~ [A.array: [A.array: true, false], [A.array: true, false], [A.array: true, false]] A.array-set-now(arr, 0, false) arr-of-arrs is=~ [A.array: [A.array: false, false], [A.array: false, false], [A.array: false, false]] end
Constructs an array of length size, and fills it with the result of calling the function f with each index from 0 to size - 1.
Similar to build-list and raw-array-build.
import arrays as A check: fun sq(x): x * x end A.build-array(sq, 4) is=~ [A.array: sq(0), sq(1), sq(2), sq(3)] end check: fun build(n :: Number) -> Array<String>: A.array-of("_", 3) end a = A.build-array(build, 3) a is=~ [A.array: [A.array: "_", "_", "_"], [A.array: "_", "_", "_"], [A.array: "_", "_", "_"]] a.get-now(0).set-now(0, "X") a.get-now(1).set-now(1, "O") a is=~ [A.array: [A.array: "X", "_", "_"], [A.array: "_", "O", "_"], [A.array: "_", "_", "_"]] end
Converts a List to an Array containing the same elements in the same order.
Similar to raw-array-from-list.
import arrays as A import lists as L check: A.array-from-list([L.list: 1, 2, 3]) is=~ [A.array: 1, 2, 3] end
3.1.10.4 Array Methods
Returns the value at the given index.
This method has a -now suffix because its answer can change from one call to the next if, for example, .set-now is used.
Using an index too large, negative, or not a whole number raises an error.
Similar to get and raw-array-get.
import arrays as A check: a = [A.array: "a", "b", "c"] a.get-now(0) is "a" a.get-now(1) is "b" a.get-now(4) raises "index" a.get-now(-1) raises "index" a.get-now(1.2) raises "index" end
Updates the value at the given index, returning Nothing.
The update is stateful, so all references to the array see the update. Hence the -now suffix; in the example below, calling a.get-now() at two different points in the program produces two different results.
Using an index too large, negative, or not a whole number raises an error.
Similar to raw-array-set.
import arrays as A check: a = [A.array: "a", "b", "c"] a.get-now(0) is "a" a.set-now(0, "d") a.get-now(0) is "d" b = a a.set-now(0, "f") a is=~ [A.array: "f", "b", "c"] b is=~ [A.array: "f", "b", "c"] c = b.set-now(0, 'z') c is nothing b.set-now(4, "hi") raises "index" end
Returns the length of the array. The length of an array is set when it is created and cannot be changed.
Similar to length and raw-array-length.
import arrays as A check: a = [A.array: "a", "b"] a.length() is 2 b = [A.array: ] b.length() is 0 end
Applies function f to each element of self from left to right, constructing a new Array out of the elements for which f returned true.
Similar to filter and raw-array-filter.
import arrays as A check: a = [A.array: "apple", "banana", "plum"] p-words = a.filter({(s): string-contains(s, "p")}) p-words is=~ [A.array: "apple", "plum"] end
Applies function f to each element of the arrays from left to right, and constructs a new Array out of the return values in the corresponding order. The original array remains unchanged.
a represents the type of the elements in the original Array, b is the type of the elements in the new Array.
Similar to map and raw-array-map.
import arrays as A check: a = [A.array: "apple", "banana", "plum"] lengths = a.map(string-length) lengths is=~ [A.array: 5, 6, 4] a is=~ [A.array: "apple", "banana", "plum"] end
Combines the elements in the array with a function that accumulates each element with an intermediate result. Has an argument order that works with for. The numeric argument to the accumulator is the index of the current element.
Similar to fold and raw-array-fold.
import arrays as A fun sum-even-minus-odd(a :: Array<Number>): fun is-even(n): (n / 2) == num-floor(n / 2) end fun sum-ith(sum-so-far :: Number, new-n :: Number, idx :: Number): if is-even(idx): sum-so-far + new-n else: sum-so-far - new-n end end a.fold(sum-ith, 0, 0) end check: sum-even-minus-odd([A.array: ]) is 0 sum-even-minus-odd([A.array: 1]) is 1 sum-even-minus-odd([A.array: 1, 2]) is -1 because (1 - 2) sum-even-minus-odd([A.array: 1, 2, 3]) is 2 because (1 + 3) - 2 sum-even-minus-odd([A.array: 1, 2, 3, 4]) is -2 because ((1 + 3) - (2 + 4)) end
Creates a new array with all the elements of the current array followed by all the elements of other.
Similar to append and raw-array-concat.
import arrays as A check: a = [A.array: "To", "be", "or"] a.concat([A.array: "not", "to", "be"]) is=~ [A.array: "To", "be", "or", "not", "to", "be"] a is=~ [A.array: "To", "be", "or"] a is-not=~ [A.array: "To", "be", "or", "not", "to", "be"] end
Returns a copy of the given array, such that corresponding elements in the result are Identical to those in the source array.
Similar to raw-array-duplicate.
import arrays as A data Person: p(ref name :: String, ref age :: Number) end check: ps1 = [A.array: p("Alice", 30), p("Bob", 40)] ps2 = ps1.duplicate() ps2.get-now(0) is ps1.get-now(0) ps2.get-now(1)!{age: 57} ps1.get-now(1)!age is 57 end
Sorts the given array in-place in ascending or descending order according to the asc parameter. Returns a reference to the original array, which will have its contents mutably updated.
Similar to raw-array-sort-nums.
import arrays as A check: a = [A.array: 3, 1, 4, 1, 5, 9, 2] asc = a.sort-nums(true) asc is<=> a a is=~ [A.array: 1, 1, 2, 3, 4, 5, 9] a.sort-nums(false) a is=~ [A.array: 9, 5, 4, 3, 2, 1, 1] end
Creates a new array containing the sorted contents of the given array. The sort order is determined by calling the key function on each element to get a number, and sorting the elements by their key value (in increasing key order if asc is true, decreasing if false). Ties are broken by the order in which the element is present in the initial array.
Similar to raw-array-sort-by.
import arrays as A check: a = [A.array: "let", "us", "go", "then", "you", "and", "i"] asc = a.sort-by(string-length, true) asc is=~ [A.array: "i", "us", "go", "let", "you", "and", "then"] asc is-not=~ a desc = a.sort-by(string-length, false) desc is=~ [A.array: "then", "let", "you", "and", "us", "go", "i"] a is=~ [A.array: "let", "us", "go", "then", "you", "and", "i"] end
Converts a Array to a List containing the same elements in the same order. This method has a -now suffix because its answer can change from one call to the next if, for example, .set-now is subsequently used.
Note that it does not recursively convert Arrays; only the top-level is converted.
Similar to raw-array-to-list.
import arrays as A import lists as L check: a = [A.array: 1, 2, 3] a.to-list-now() is [L.list: 1, 2, 3] a2 = array-of([A.array: ], 3) a2.to-list-now() is=~ [L.list: [A.array: ], [A.array: ], [A.array: ]] a2.to-list-now() is-not=~ [L.list: [L.list: ], [L.list: ], [L.list: ]] a.set-now(0, 5) a.to-list-now() is [L.list: 5, 2, 3] end
3.1.10.5 Array Functions
Equivalent to array.get-now(index).
import arrays as A check: a = [A.array: 0, 1, 2] A.array-get-now(a, 1) is 1 end
- array-set-now :: (
- array :: Array<a>,
- index :: Number,
- value :: a
- )
- -> Nothing
Equivalent to array.set-now(index, value).
import arrays as A check: a = A.array-of("a", 3) a is=~ [A.array: "a", "a", "a"] A.array-set-now(a, 1, "b") a is=~ [A.array: "a", "b", "a"] end
Equivalent to array.length().
import arrays as A check: a = A.array-of("a", 3) a is=~ [A.array: "a", "a", "a"] A.array-length(a) is 3 end
Equivalent to array.filter(f), with an argument order designed for for.
Equivalent to array.map(f), with an argument order designed for for.
- array-fold :: (
- f :: (b, a -> Number),
- init :: b,
- array :: Array<a>,
- start-index :: Number
- )
- -> b
Equivalent to array.fold(f, init, start-index), with an argument order designed for for.
Equivalent to array1.concat(array2).
Equivalent to array.duplicate().
Equivalent to array.sort-nums(asc).
import arrays as A check: a = [A.array: 3, 1, 4, 1, 5, 9, 2] asc = A.array-sort-nums(a, true) asc is<=> a a is=~ [A.array: 1, 1, 2, 3, 4, 5, 9] A.array-sort-nums(a, false) a is=~ [A.array: 9, 5, 4, 3, 2, 1, 1] end
- array-sort-by :: (
- array :: Array<a>,
- key :: (a -> Number),
- asc :: Boolean
- )
- -> Array<a>
Equivalent to array.sort-by(key, asc).
import arrays as A check: a = [A.array: "let", "us", "go", "then", "you", "and", "i"] asc = A.array-sort-by(a, string-length, true) asc is=~ [A.array: "i", "us", "go", "let", "you", "and", "then"] asc is-not=~ a desc = A.array-sort-by(a, string-length, false) desc is=~ [A.array: "then", "let", "you", "and", "us", "go", "i"] a is=~ [A.array: "let", "us", "go", "then", "you", "and", "i"] end
Equivalent to array.to-list-now().
import arrays as A import lists as L check: a = A.array-of("a", 3) a is=~ [A.array: "a", "a", "a"] A.array-set-now(a, 1, "b") a is=~ [A.array: "a", "b", "a"] l = A.array-to-list-now(a) l is [L.list: "a", "b", "a"] end