]> Lady’s Gitweb - Pisces/blob - collection.js
03326a6cd0de048259206c4310cec6f73d8d2d9e
[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 { 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
197 /**
198 * Returns whether the provided object is a collection.
199 *
200 * The definition of “collection” used by Piscēs is similar to
201 * Ecmascript’s definition of an arraylike object, but it differs in
202 * a few ways :—
203 *
204 * - It requires the provided value to be a proper object.
205 *
206 * - It requires the `length` property to be an integer index.
207 *
208 * - It requires the object to be concat‐spreadable, meaning it must
209 * either be an array or have `.[Symbol.isConcatSpreadable]` be true.
210 */
211 export const isCollection = ($) => {
212 if (!(type($) === "object" && "length" in $)) {
213 // The provided value is not an object or does not have a `length`.
214 return false;
215 } else {
216 try {
217 toIndex($.length); // will throw if `length` is not an index
218 return isConcatSpreadable($);
219 } catch {
220 return false;
221 }
222 }
223 };
224
225 /**
226 * Returns whether the provided value is spreadable during array
227 * concatenation.
228 *
229 * This is also used to determine which things should be treated as
230 * collections.
231 */
232 export const isConcatSpreadable = ($) => {
233 if (type($) !== "object") {
234 // The provided value is not an object.
235 return false;
236 } else {
237 // The provided value is an object.
238 const spreadable = $[Symbol.isConcatSpreadable];
239 return spreadable !== undefined ? !!spreadable : isArray($);
240 }
241 };
242
243 /**
244 * Returns an iterator over the items in the provided value according
245 * to the algorithm of `Array::values`.
246 */
247 export const items = createCallableFunction(
248 arrayPrototype.values,
249 "items",
250 );
251
252 /**
253 * Returns the result of mapping the provided value with the provided
254 * callback according to the algorithm of `Array::map`.
255 */
256 export const map = createCallableFunction(arrayPrototype.map);
257
258 /**
259 * Pops from the provided value according to the algorithm of
260 * `Array::pop`.
261 */
262 export const pop = createCallableFunction(arrayPrototype.pop);
263
264 /**
265 * Pushes onto the provided value according to the algorithm of
266 * `Array::push`.
267 */
268 export const push = createCallableFunction(arrayPrototype.push);
269
270 /**
271 * Returns the result of reducing the provided value with the provided
272 * callback, according to the algorithm of `Array::reduce`.
273 */
274 export const reduce = createCallableFunction(arrayPrototype.reduce);
275
276 /**
277 * Reverses the provided value according to the algorithm of
278 * `Array::reverse`.
279 */
280 export const reverse = createCallableFunction(arrayPrototype.reverse);
281
282 /**
283 * Shifts the provided value according to the algorithm of
284 * `Array::shift`.
285 */
286 export const shift = createCallableFunction(arrayPrototype.shift);
287
288 /**
289 * Returns a slice of the provided value according to the algorithm of
290 * `Array::slice`.
291 */
292 export const slice = createCallableFunction(arrayPrototype.slice);
293
294 /**
295 * Sorts the provided value in‐place according to the algorithm of
296 * `Array::sort`.
297 */
298 export const sort = createCallableFunction(arrayPrototype.sort);
299
300 /**
301 * Splices into and out of the provided value according to the
302 * algorithm of `Array::splice`.
303 */
304 export const splice = createCallableFunction(arrayPrototype.splice);
305
306 /**
307 * Unshifts the provided value according to the algorithm of
308 * `Array::unshift`.
309 */
310 export const unshift = createCallableFunction(arrayPrototype.unshift);
This page took 0.058559 seconds and 3 git commands to generate.