]> Lady’s Gitweb - Pisces/blob - collection.js
69c0beefabf16bd9d64fe57f17f82d8ab11dd3e7
[Pisces] / collection.js
1 // ♓🌟 Piscēs ∷ collection.js
2 // ====================================================================
3 //
4 // Copyright © 2020–2023 Lady [@ Lady’s Computer].
5 //
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/>.
9
10 import { call, createCallableFunction } from "./function.js";
11 import { lengthOfArraylike, toIndex, type } from "./value.js";
12
13 const { prototype: arrayPrototype } = Array;
14
15 export const {
16 /** Returns an array of the provided values. */
17 of: array,
18
19 /** Returns whether the provided value is an array. */
20 isArray,
21
22 /** Returns an array created from the provided arraylike. */
23 from: toArray,
24 } = Array;
25
26 /**
27 * Returns the result of catenating the provided arraylikes into a new
28 * collection according to the algorithm of `Array::concat`.
29 */
30 export const catenate = createCallableFunction(
31 arrayPrototype.concat,
32 "catenate",
33 );
34
35 /**
36 * Copies the items in the provided object to a new location according
37 * to the algorithm of `Array::copyWithin`.
38 */
39 export const copyWithin = createCallableFunction(
40 arrayPrototype.copyWithin,
41 );
42
43 /**
44 * Fills the provided object with the provided value according to the
45 * algorithm of `Array::fill`.
46 */
47 export const fill = createCallableFunction(arrayPrototype.fill);
48
49 /**
50 * Returns the result of filtering the provided object with the
51 * provided callback, according to the algorithm of `Array::filter`.
52 */
53 export const filter = createCallableFunction(arrayPrototype.filter);
54
55 /**
56 * Returns the first index in the provided object whose value satisfies
57 * the provided callback according to the algorithm of
58 * `Array::findIndex`.
59 */
60 export const findIndex = createCallableFunction(
61 arrayPrototype.findIndex,
62 );
63
64 /**
65 * Returns the first indexed entry in the provided object whose value
66 * satisfies the provided callback.
67 *
68 * If a third argument is supplied, it will be used as the this value
69 * of the callback.
70 */
71 export const findIndexedEntry = (
72 $,
73 callback,
74 thisArg = undefined,
75 ) => {
76 let result = undefined;
77 findItem($, (kValue, k, O) => {
78 if (call(callback, thisArg, [kValue, k, O])) {
79 // The callback succeeded.
80 result = [k, kValue];
81 return true;
82 } else {
83 // The callback failed.
84 return false;
85 }
86 });
87 return result;
88 };
89
90 /**
91 * Returns the first indexed value in the provided object which
92 * satisfies the provided callback, according to the algorithm of
93 * `Array::find`.
94 */
95 export const findItem = createCallableFunction(
96 arrayPrototype.find,
97 "findItem",
98 );
99
100 /**
101 * Returns the result of flatmapping the provided value with the
102 * provided callback according to the algorithm of `Array::flatMap`.
103 */
104 export const flatmap = createCallableFunction(
105 arrayPrototype.flatMap,
106 "flatmap",
107 );
108
109 /**
110 * Returns the result of flattening the provided object according to
111 * the algorithm of `Array::flat`.
112 */
113 export const flatten = createCallableFunction(
114 arrayPrototype.flat,
115 "flatten",
116 );
117
118 /**
119 * Returns the first index of the provided object with a value
120 * equivalent to the provided value according to the algorithm of
121 * `Array::indexOf`.
122 */
123 export const getFirstIndex = createCallableFunction(
124 arrayPrototype.indexOf,
125 "getFirstIndex",
126 );
127
128 /**
129 * Returns the item on the provided object at the provided index
130 * according to the algorithm of `Array::at`.
131 */
132 export const getItem = createCallableFunction(
133 arrayPrototype.at,
134 "getItem",
135 );
136
137 /**
138 * Returns the last index of the provided object with a value
139 * equivalent to the provided value according to the algorithm of
140 * `Array::lastIndexOf`.
141 */
142 export const getLastIndex = createCallableFunction(
143 arrayPrototype.lastIndexOf,
144 "getLastIndex",
145 );
146
147 /**
148 * Returns whether every indexed value in the provided object satisfies
149 * the provided function, according to the algorithm of `Array::every`.
150 */
151 export const hasEvery = createCallableFunction(
152 arrayPrototype.every,
153 "hasEvery",
154 );
155
156 /**
157 * Returns whether the provided object has an indexed value which
158 * satisfies the provided function, according to the algorithm of
159 * `Array::some`.
160 */
161 export const hasSome = createCallableFunction(
162 arrayPrototype.some,
163 "hasSome",
164 );
165
166 /**
167 * Returns whether the provided object has an indexed value equivalent
168 * to the provided value according to the algorithm of
169 * `Array::includes`.
170 *
171 * ※ This algorithm treats missing values as `undefined` rather than
172 * skipping them.
173 */
174 export const includes = createCallableFunction(
175 arrayPrototype.includes,
176 );
177
178 /**
179 * Returns an iterator over the indexed entries in the provided value
180 * according to the algorithm of `Array::entries`.
181 */
182 export const indexedEntries = createCallableFunction(
183 arrayPrototype.entries,
184 "indexedEntries",
185 );
186
187 /**
188 * Returns an iterator over the indices in the provided value according
189 * to the algorithm of `Array::keys`.
190 */
191 export const indices = createCallableFunction(
192 arrayPrototype.keys,
193 "indices",
194 );
195
196 /** Returns whether the provided value is arraylike. */
197 export const isArraylikeObject = ($) => {
198 if (type($) !== "object") {
199 return false;
200 } else {
201 try {
202 lengthOfArraylike($); // throws if not arraylike
203 return true;
204 } catch {
205 return false;
206 }
207 }
208 };
209
210 /**
211 * Returns whether the provided object is a collection.
212 *
213 * The definition of “collection” used by Piscēs is similar to
214 * Ecmascript’s definition of an arraylike object, but it differs in
215 * a few ways :—
216 *
217 * - It requires the provided value to be a proper object.
218 *
219 * - It requires the `length` property to be an integer index.
220 *
221 * - It requires the object to be concat‐spreadable, meaning it must
222 * either be an array or have `.[Symbol.isConcatSpreadable]` be true.
223 */
224 export const isCollection = ($) => {
225 if (!(type($) === "object" && "length" in $)) {
226 // The provided value is not an object or does not have a `length`.
227 return false;
228 } else {
229 try {
230 toIndex($.length); // will throw if `length` is not an index
231 return isConcatSpreadable($);
232 } catch {
233 return false;
234 }
235 }
236 };
237
238 /**
239 * Returns whether the provided value is spreadable during array
240 * concatenation.
241 *
242 * This is also used to determine which things should be treated as
243 * collections.
244 */
245 export const isConcatSpreadable = ($) => {
246 if (type($) !== "object") {
247 // The provided value is not an object.
248 return false;
249 } else {
250 // The provided value is an object.
251 const spreadable = $[Symbol.isConcatSpreadable];
252 return spreadable !== undefined ? !!spreadable : isArray($);
253 }
254 };
255
256 /**
257 * Returns an iterator over the items in the provided value according
258 * to the algorithm of `Array::values`.
259 */
260 export const items = createCallableFunction(
261 arrayPrototype.values,
262 "items",
263 );
264
265 /**
266 * Returns the result of mapping the provided value with the provided
267 * callback according to the algorithm of `Array::map`.
268 */
269 export const map = createCallableFunction(arrayPrototype.map);
270
271 /**
272 * Pops from the provided value according to the algorithm of
273 * `Array::pop`.
274 */
275 export const pop = createCallableFunction(arrayPrototype.pop);
276
277 /**
278 * Pushes onto the provided value according to the algorithm of
279 * `Array::push`.
280 */
281 export const push = createCallableFunction(arrayPrototype.push);
282
283 /**
284 * Returns the result of reducing the provided value with the provided
285 * callback, according to the algorithm of `Array::reduce`.
286 */
287 export const reduce = createCallableFunction(arrayPrototype.reduce);
288
289 /**
290 * Reverses the provided value according to the algorithm of
291 * `Array::reverse`.
292 */
293 export const reverse = createCallableFunction(arrayPrototype.reverse);
294
295 /**
296 * Shifts the provided value according to the algorithm of
297 * `Array::shift`.
298 */
299 export const shift = createCallableFunction(arrayPrototype.shift);
300
301 /**
302 * Returns a slice of the provided value according to the algorithm of
303 * `Array::slice`.
304 */
305 export const slice = createCallableFunction(arrayPrototype.slice);
306
307 /**
308 * Sorts the provided value in‐place according to the algorithm of
309 * `Array::sort`.
310 */
311 export const sort = createCallableFunction(arrayPrototype.sort);
312
313 /**
314 * Splices into and out of the provided value according to the
315 * algorithm of `Array::splice`.
316 */
317 export const splice = createCallableFunction(arrayPrototype.splice);
318
319 /**
320 * Unshifts the provided value according to the algorithm of
321 * `Array::unshift`.
322 */
323 export const unshift = createCallableFunction(arrayPrototype.unshift);
This page took 0.126909 seconds and 3 git commands to generate.