1 // ♓🌟 Piscēs ∷ collection.js
2 // ====================================================================
4 // Copyright © 2020–2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
10 import { call
, createCallableFunction
} from "./function.js";
11 import { canonicalNumericIndexString
} from "./string.js";
20 const { prototype: arrayPrototype
} = Array
;
23 /** Returns an array of the provided values. */
26 /** Returns whether the provided value is an array. */
29 /** Returns an array created from the provided arraylike. */
34 * Returns the result of catenating the provided arraylikes into a new
35 * collection according to the algorithm of `Array::concat`.
37 export const catenate
= createCallableFunction(
38 arrayPrototype
.concat
,
43 * Copies the items in the provided object to a new location according
44 * to the algorithm of `Array::copyWithin`.
46 export const copyWithin
= createCallableFunction(
47 arrayPrototype
.copyWithin
,
51 * Fills the provided object with the provided value according to the
52 * algorithm of `Array::fill`.
54 export const fill
= createCallableFunction(arrayPrototype
.fill
);
57 * Returns the result of filtering the provided object with the
58 * provided callback, according to the algorithm of `Array::filter`.
60 export const filter
= createCallableFunction(arrayPrototype
.filter
);
63 * Returns the first index in the provided object whose value satisfies
64 * the provided callback according to the algorithm of
67 export const findIndex
= createCallableFunction(
68 arrayPrototype
.findIndex
,
72 * Returns the first indexed entry in the provided object whose value
73 * satisfies the provided callback.
75 * If a third argument is supplied, it will be used as the this value
78 export const findIndexedEntry
= (
83 let result
= undefined;
84 findItem($, (kValue
, k
, O
) => {
85 if (call(callback
, thisArg
, [kValue
, k
, O
])) {
86 // The callback succeeded.
90 // The callback failed.
98 * Returns the first indexed value in the provided object which
99 * satisfies the provided callback, according to the algorithm of
102 export const findItem
= createCallableFunction(
108 * Returns the result of flatmapping the provided value with the
109 * provided callback according to the algorithm of `Array::flatMap`.
111 export const flatmap
= createCallableFunction(
112 arrayPrototype
.flatMap
,
117 * Returns the result of flattening the provided object according to
118 * the algorithm of `Array::flat`.
120 export const flatten
= createCallableFunction(
126 * Returns the first index of the provided object with a value
127 * equivalent to the provided value according to the algorithm of
130 export const getFirstIndex
= createCallableFunction(
131 arrayPrototype
.indexOf
,
136 * Returns the item on the provided object at the provided index
137 * according to the algorithm of `Array::at`.
139 export const getItem
= createCallableFunction(
145 * Returns the last index of the provided object with a value
146 * equivalent to the provided value according to the algorithm of
147 * `Array::lastIndexOf`.
149 export const getLastIndex
= createCallableFunction(
150 arrayPrototype
.lastIndexOf
,
155 * Returns whether every indexed value in the provided object satisfies
156 * the provided function, according to the algorithm of `Array::every`.
158 export const hasEvery
= createCallableFunction(
159 arrayPrototype
.every
,
164 * Returns whether the provided object has an indexed value which
165 * satisfies the provided function, according to the algorithm of
168 export const hasSome
= createCallableFunction(
174 * Returns whether the provided object has an indexed value equivalent
175 * to the provided value according to the algorithm of
178 * ※ This algorithm treats missing values as `undefined` rather than
181 export const includes
= createCallableFunction(
182 arrayPrototype
.includes
,
186 * Returns an iterator over the indexed entries in the provided value
187 * according to the algorithm of `Array::entries`.
189 export const indexedEntries
= createCallableFunction(
190 arrayPrototype
.entries
,
195 * Returns an iterator over the indices in the provided value according
196 * to the algorithm of `Array::keys`.
198 export const indices
= createCallableFunction(
203 /** Returns whether the provided value is an array index string. */
204 export const isArrayIndexString
= ($) => {
205 const value
= canonicalNumericIndexString($);
206 if (value
!== undefined) {
207 // The provided value is a canonical numeric index string.
208 return sameValue(value
, 0) || value
> 0 && value
< -1 >>> 0 &&
209 value
=== toLength(value
);
211 // The provided value is not a canonical numeric index string.
216 /** Returns whether the provided value is arraylike. */
217 export const isArraylikeObject
= ($) => {
218 if (type($) !== "object") {
222 lengthOfArraylike($); // throws if not arraylike
231 * Returns whether the provided object is a collection.
233 * The definition of “collection” used by Piscēs is similar to
234 * Ecmascript’s definition of an arraylike object, but it differs in
237 * - It requires the provided value to be a proper object.
239 * - It requires the `length` property to be an integer index.
241 * - It requires the object to be concat‐spreadable, meaning it must
242 * either be an array or have `.[Symbol.isConcatSpreadable]` be true.
244 export const isCollection
= ($) => {
245 if (!(type($) === "object" && "length" in $)) {
246 // The provided value is not an object or does not have a `length`.
250 toIndex($.length
); // will throw if `length` is not an index
251 return isConcatSpreadable($);
259 * Returns whether the provided value is spreadable during array
262 * This is also used to determine which things should be treated as
265 export const isConcatSpreadable
= ($) => {
266 if (type($) !== "object") {
267 // The provided value is not an object.
270 // The provided value is an object.
271 const spreadable
= $[Symbol
.isConcatSpreadable
];
272 return spreadable
!== undefined ? !!spreadable
: isArray($);
277 * Returns an iterator over the items in the provided value according
278 * to the algorithm of `Array::values`.
280 export const items
= createCallableFunction(
281 arrayPrototype
.values
,
286 * Returns the result of mapping the provided value with the provided
287 * callback according to the algorithm of `Array::map`.
289 export const map
= createCallableFunction(arrayPrototype
.map
);
292 * Pops from the provided value according to the algorithm of
295 export const pop
= createCallableFunction(arrayPrototype
.pop
);
298 * Pushes onto the provided value according to the algorithm of
301 export const push
= createCallableFunction(arrayPrototype
.push
);
304 * Returns the result of reducing the provided value with the provided
305 * callback, according to the algorithm of `Array::reduce`.
307 export const reduce
= createCallableFunction(arrayPrototype
.reduce
);
310 * Reverses the provided value according to the algorithm of
313 export const reverse
= createCallableFunction(arrayPrototype
.reverse
);
316 * Shifts the provided value according to the algorithm of
319 export const shift
= createCallableFunction(arrayPrototype
.shift
);
322 * Returns a slice of the provided value according to the algorithm of
325 export const slice
= createCallableFunction(arrayPrototype
.slice
);
328 * Sorts the provided value in‐place according to the algorithm of
331 export const sort
= createCallableFunction(arrayPrototype
.sort
);
334 * Splices into and out of the provided value according to the
335 * algorithm of `Array::splice`.
337 export const splice
= createCallableFunction(arrayPrototype
.splice
);
340 * Unshifts the provided value according to the algorithm of
343 export const unshift
= createCallableFunction(arrayPrototype
.unshift
);