| 1 | import { assert, describe, it } from "@effect/vitest" |
| 2 | import { assertNone, assertSome, deepStrictEqual, strictEqual, throws } from "@effect/vitest/utils" |
| 3 | import { |
| 4 | Array as Arr, |
| 5 | Equal, |
| 6 | Equivalence, |
| 7 | Hash, |
| 8 | Number as Num, |
| 9 | Option, |
| 10 | Order, |
| 11 | type Predicate, |
| 12 | Result, |
| 13 | String as Str |
| 14 | } from "effect" |
| 15 | import { identity, pipe } from "effect/Function" |
| 16 | import * as fc from "fast-check" |
| 17 | |
| 18 | const symA = Symbol.for("a") |
| 19 | const symB = Symbol.for("b") |
| 20 | const symC = Symbol.for("c") |
| 21 | |
| 22 | const double = (n: number) => n * 2 |
| 23 | |
| 24 | class HashCollision implements Equal.Equal { |
| 25 | constructor(readonly value: number) {} |
| 26 | [Hash.symbol](): number { |
| 27 | return 0 |
| 28 | } |
| 29 | [Equal.symbol](that: Equal.Equal): boolean { |
| 30 | return that instanceof HashCollision && this.value === that.value |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | describe("Array", () => { |
| 35 | it("isCanonicalArrayIndex", () => { |
| 36 | assert.isTrue(Arr.isCanonicalArrayIndex("0")) |
| 37 | assert.isTrue(Arr.isCanonicalArrayIndex("4294967294")) |
| 38 | assert.isFalse(Arr.isCanonicalArrayIndex("01")) |
| 39 | assert.isFalse(Arr.isCanonicalArrayIndex("4294967295")) |
| 40 | }) |
| 41 | |
| 42 | it("of", () => { |
| 43 | deepStrictEqual(Arr.of(1), [1]) |
| 44 | }) |
| 45 | |
| 46 | it("fromIterable/Array should return the same reference if the iterable is an Array", () => { |
| 47 | const i = [1, 2, 3] |
| 48 | strictEqual(Arr.fromIterable(i), i) |
| 49 | }) |
| 50 | |
| 51 | it("fromIterable/Iterable", () => { |
| 52 | deepStrictEqual(Arr.fromIterable(new Set([1, 2, 3])), [1, 2, 3]) |
| 53 | }) |
| 54 | |
| 55 | it("ensure", () => { |
| 56 | deepStrictEqual(Arr.ensure(1), [1]) |
| 57 | deepStrictEqual(Arr.ensure(null), [null]) |
| 58 | deepStrictEqual(Arr.ensure([1]), [1]) |
| 59 | deepStrictEqual(Arr.ensure([1, 2]), [1, 2]) |
| 60 | deepStrictEqual(Arr.ensure(new Set([1, 2])), [new Set([1, 2])]) |
| 61 | }) |
| 62 | |
| 63 | describe("iterable inputs", () => { |
| 64 | it("prepend", () => { |
| 65 | deepStrictEqual(pipe([1, 2, 3], Arr.prepend(0)), [0, 1, 2, 3]) |
| 66 | deepStrictEqual(pipe([[2]], Arr.prepend([1])), [[1], [2]]) |
| 67 | |
| 68 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.prepend(0)), [0, 1, 2, 3]) |
| 69 | deepStrictEqual(pipe(new Set([[2]]), Arr.prepend([1])), [[1], [2]]) |
| 70 | }) |
| 71 | |
| 72 | it("prependAll", () => { |
| 73 | deepStrictEqual(pipe([3, 4], Arr.prependAll([1, 2])), [1, 2, 3, 4]) |
| 74 | |
| 75 | deepStrictEqual(pipe([3, 4], Arr.prependAll(new Set([1, 2]))), [1, 2, 3, 4]) |
| 76 | deepStrictEqual(pipe(new Set([3, 4]), Arr.prependAll([1, 2])), [1, 2, 3, 4]) |
| 77 | }) |
| 78 | |
| 79 | it("append", () => { |
| 80 | deepStrictEqual(pipe([1, 2, 3], Arr.append(4)), [1, 2, 3, 4]) |
| 81 | deepStrictEqual(pipe([[1]], Arr.append([2])), [[1], [2]]) |
| 82 | |
| 83 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.append(4)), [1, 2, 3, 4]) |
| 84 | deepStrictEqual(pipe(new Set([[1]]), Arr.append([2])), [[1], [2]]) |
| 85 | }) |
| 86 | |
| 87 | it("appendAll", () => { |
| 88 | deepStrictEqual(pipe([1, 2], Arr.appendAll([3, 4])), [1, 2, 3, 4]) |
| 89 | |
| 90 | deepStrictEqual(pipe([1, 2], Arr.appendAll(new Set([3, 4]))), [1, 2, 3, 4]) |
| 91 | deepStrictEqual(pipe(new Set([1, 2]), Arr.appendAll([3, 4])), [1, 2, 3, 4]) |
| 92 | }) |
| 93 | |
| 94 | it("scan", () => { |
| 95 | const f = (b: number, a: number) => b - a |
| 96 | deepStrictEqual(pipe([1, 2, 3], Arr.scan(10, f)), [10, 9, 7, 4]) |
| 97 | deepStrictEqual(pipe([0], Arr.scan(10, f)), [10, 10]) |
| 98 | deepStrictEqual(pipe([], Arr.scan(10, f)), [10]) |
| 99 | |
| 100 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.scan(10, f)), [10, 9, 7, 4]) |
| 101 | deepStrictEqual(pipe(new Set([0]), Arr.scan(10, f)), [10, 10]) |
| 102 | deepStrictEqual(pipe(new Set([]), Arr.scan(10, f)), [10]) |
| 103 | }) |
| 104 | |
| 105 | it("scanRight", () => { |
| 106 | const f = (b: number, a: number) => a - b |
| 107 | deepStrictEqual(pipe([1, 2, 3], Arr.scanRight(10, f)), [-8, 9, -7, 10]) |
| 108 | deepStrictEqual(pipe([0], Arr.scanRight(10, f)), [-10, 10]) |
| 109 | deepStrictEqual(pipe([], Arr.scanRight(10, f)), [10]) |
| 110 | |
| 111 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.scanRight(10, f)), [-8, 9, -7, 10]) |
| 112 | deepStrictEqual(pipe(new Set([0]), Arr.scanRight(10, f)), [-10, 10]) |
| 113 | deepStrictEqual(pipe(new Set([]), Arr.scanRight(10, f)), [10]) |
| 114 | }) |
| 115 | |
| 116 | it("tail", () => { |
| 117 | assertSome(Arr.tail([1, 2, 3]), [2, 3]) |
| 118 | assertNone(Arr.tail([])) |
| 119 | |
| 120 | assertSome(Arr.tail(new Set([1, 2, 3])), [2, 3]) |
| 121 | assertNone(Arr.tail(new Set([]))) |
| 122 | }) |
| 123 | |
| 124 | it("init", () => { |
| 125 | assertSome(Arr.init([1, 2, 3]), [1, 2]) |
| 126 | assertNone(Arr.init([])) |
| 127 | |
| 128 | assertSome(Arr.init(new Set([1, 2, 3])), [1, 2]) |
| 129 | assertNone(Arr.init(new Set([]))) |
| 130 | }) |
| 131 | |
| 132 | it("take", () => { |
| 133 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.take(2)), [1, 2]) |
| 134 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.take(0)), []) |
| 135 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.take(Number.NaN)), []) |
| 136 | // out of bounds |
| 137 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.take(-10)), []) |
| 138 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.take(10)), [1, 2, 3, 4]) |
| 139 | |
| 140 | deepStrictEqual(pipe(new Set([1, 2, 3, 4]), Arr.take(2)), [1, 2]) |
| 141 | deepStrictEqual(pipe(new Set([1, 2, 3, 4]), Arr.take(0)), []) |
| 142 | // out of bounds |
| 143 | deepStrictEqual(pipe(new Set([1, 2, 3, 4]), Arr.take(-10)), []) |
| 144 | deepStrictEqual(pipe(new Set([1, 2, 3, 4]), Arr.take(10)), [1, 2, 3, 4]) |
| 145 | }) |
| 146 | |
| 147 | it("takeRight", () => { |
| 148 | deepStrictEqual(pipe(Arr.empty(), Arr.takeRight(0)), []) |
| 149 | deepStrictEqual(pipe([1, 2], Arr.takeRight(0)), []) |
| 150 | deepStrictEqual(pipe([1, 2], Arr.takeRight(Number.NaN)), []) |
| 151 | deepStrictEqual(pipe([1, 2], Arr.takeRight(1)), [2]) |
| 152 | deepStrictEqual(pipe([1, 2], Arr.takeRight(2)), [1, 2]) |
| 153 | // out of bound |
| 154 | deepStrictEqual(pipe(Arr.empty(), Arr.takeRight(1)), []) |
| 155 | deepStrictEqual(pipe(Arr.empty(), Arr.takeRight(-1)), []) |
| 156 | deepStrictEqual(pipe([1, 2], Arr.takeRight(3)), [1, 2]) |
| 157 | deepStrictEqual(pipe([1, 2], Arr.takeRight(-1)), []) |
| 158 | |
| 159 | deepStrictEqual(pipe(new Set(), Arr.takeRight(0)), []) |
| 160 | deepStrictEqual(pipe(new Set([1, 2]), Arr.takeRight(0)), []) |
| 161 | deepStrictEqual(pipe(new Set([1, 2]), Arr.takeRight(1)), [2]) |
| 162 | deepStrictEqual(pipe(new Set([1, 2]), Arr.takeRight(2)), [1, 2]) |
| 163 | // out of bound |
| 164 | deepStrictEqual(pipe(new Set(), Arr.takeRight(1)), []) |
| 165 | deepStrictEqual(pipe(new Set(), Arr.takeRight(-1)), []) |
| 166 | deepStrictEqual(pipe(new Set([1, 2]), Arr.takeRight(3)), [1, 2]) |
| 167 | deepStrictEqual(pipe(new Set([1, 2]), Arr.takeRight(-1)), []) |
| 168 | }) |
| 169 | |
| 170 | it("takeWhile", () => { |
| 171 | const f = (n: number) => n % 2 === 0 |
| 172 | deepStrictEqual(pipe([2, 4, 3, 6], Arr.takeWhile(f)), [2, 4]) |
| 173 | deepStrictEqual(pipe(Arr.empty(), Arr.takeWhile(f)), []) |
| 174 | deepStrictEqual(pipe([1, 2, 4], Arr.takeWhile(f)), []) |
| 175 | deepStrictEqual(pipe([2, 4], Arr.takeWhile(f)), [2, 4]) |
| 176 | |
| 177 | deepStrictEqual(pipe(new Set([2, 4, 3, 6]), Arr.takeWhile(f)), [2, 4]) |
| 178 | deepStrictEqual(pipe(new Set<number>(), Arr.takeWhile(f)), []) |
| 179 | deepStrictEqual(pipe(new Set([1, 2, 4]), Arr.takeWhile(f)), []) |
| 180 | deepStrictEqual(pipe(new Set([2, 4]), Arr.takeWhile(f)), [2, 4]) |
| 181 | }) |
| 182 | |
| 183 | it("takeWhileFilter", () => { |
| 184 | const f: (n: number, i: number) => Result.Result<number, string> = (n, i) => |
| 185 | n + i < 5 ? Result.succeed(n * 10) : Result.fail(`stop: ${n}`) |
| 186 | |
| 187 | deepStrictEqual(Arr.takeWhileFilter([], f), []) |
| 188 | deepStrictEqual(Arr.takeWhileFilter([1, 2, 3], f), [10, 20]) |
| 189 | deepStrictEqual(pipe([1, 2, 3], Arr.takeWhileFilter(f)), [10, 20]) |
| 190 | |
| 191 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.takeWhileFilter(f)), [10, 20]) |
| 192 | deepStrictEqual(pipe([][Symbol.iterator](), Arr.takeWhileFilter(f)), []) |
| 193 | }) |
| 194 | |
| 195 | it("span", () => { |
| 196 | const f = Arr.span<number>((n) => n % 2 === 1) |
| 197 | const assertSpan = ( |
| 198 | input: Iterable<number>, |
| 199 | expectedInit: ReadonlyArray<number>, |
| 200 | expectedRest: ReadonlyArray<number> |
| 201 | ) => { |
| 202 | const [init, rest] = f(input) |
| 203 | deepStrictEqual(init, expectedInit) |
| 204 | deepStrictEqual(rest, expectedRest) |
| 205 | } |
| 206 | assertSpan([1, 3, 2, 4, 5], [1, 3], [2, 4, 5]) |
| 207 | assertSpan(Arr.empty(), Arr.empty(), Arr.empty()) |
| 208 | assertSpan([1, 3], [1, 3], Arr.empty()) |
| 209 | assertSpan([2, 4], Arr.empty(), [2, 4]) |
| 210 | |
| 211 | assertSpan(new Set([1, 3, 2, 4, 5]), [1, 3], [2, 4, 5]) |
| 212 | assertSpan(new Set(), Arr.empty(), Arr.empty()) |
| 213 | assertSpan(new Set([1, 3]), [1, 3], Arr.empty()) |
| 214 | assertSpan(new Set([2, 4]), Arr.empty(), [2, 4]) |
| 215 | |
| 216 | // iterator input |
| 217 | assertSpan([1, 3, 2, 4, 5][Symbol.iterator](), [1, 3], [2, 4, 5]) |
| 218 | assertSpan([][Symbol.iterator](), Arr.empty(), Arr.empty()) |
| 219 | }) |
| 220 | |
| 221 | it("splitWhere", () => { |
| 222 | const f = Arr.splitWhere<number>((n) => n % 2 !== 1) |
| 223 | const assertSplitWhere = ( |
| 224 | input: Iterable<number>, |
| 225 | expectedInit: ReadonlyArray<number>, |
| 226 | expectedRest: ReadonlyArray<number> |
| 227 | ) => { |
| 228 | const [init, rest] = f(input) |
| 229 | deepStrictEqual(init, expectedInit) |
| 230 | deepStrictEqual(rest, expectedRest) |
| 231 | } |
| 232 | assertSplitWhere([1, 3, 2, 4, 5], [1, 3], [2, 4, 5]) |
| 233 | assertSplitWhere(Arr.empty(), Arr.empty(), Arr.empty()) |
| 234 | assertSplitWhere([1, 3], [1, 3], Arr.empty()) |
| 235 | assertSplitWhere([2, 4], Arr.empty(), [2, 4]) |
| 236 | |
| 237 | assertSplitWhere(new Set([1, 3, 2, 4, 5]), [1, 3], [2, 4, 5]) |
| 238 | assertSplitWhere(new Set(), Arr.empty(), Arr.empty()) |
| 239 | assertSplitWhere(new Set([1, 3]), [1, 3], Arr.empty()) |
| 240 | assertSplitWhere(new Set([2, 4]), Arr.empty(), [2, 4]) |
| 241 | }) |
| 242 | |
| 243 | it("split", () => { |
| 244 | deepStrictEqual(pipe(Arr.empty(), Arr.split(2)), Arr.empty()) |
| 245 | deepStrictEqual(pipe(Arr.make(1), Arr.split(2)), Arr.make(Arr.make(1))) |
| 246 | deepStrictEqual(pipe(Arr.make(1, 2, 3), Arr.split(Number.NaN)), Arr.make(Arr.make(1, 2, 3))) |
| 247 | deepStrictEqual(pipe(Arr.make(1, 2), Arr.split(2)), Arr.make(Arr.make(1), Arr.make(2))) |
| 248 | deepStrictEqual(pipe(Arr.make(1, 2, 3, 4, 5), Arr.split(2)), Arr.make(Arr.make(1, 2, 3), Arr.make(4, 5))) |
| 249 | deepStrictEqual( |
| 250 | pipe(Arr.make(1, 2, 3, 4, 5), Arr.split(3)), |
| 251 | Arr.make(Arr.make(1, 2), Arr.make(3, 4), Arr.make(5)) |
| 252 | ) |
| 253 | }) |
| 254 | |
| 255 | it("drop", () => { |
| 256 | deepStrictEqual(pipe(Arr.empty(), Arr.drop(0)), []) |
| 257 | deepStrictEqual(pipe([1, 2], Arr.drop(0)), [1, 2]) |
| 258 | deepStrictEqual(pipe([1, 2], Arr.drop(Number.NaN)), [1, 2]) |
| 259 | deepStrictEqual(pipe([1, 2], Arr.drop(1)), [2]) |
| 260 | deepStrictEqual(pipe([1, 2], Arr.drop(2)), []) |
| 261 | // out of bound |
| 262 | deepStrictEqual(pipe(Arr.empty(), Arr.drop(1)), []) |
| 263 | deepStrictEqual(pipe(Arr.empty(), Arr.drop(-1)), []) |
| 264 | deepStrictEqual(pipe([1, 2], Arr.drop(3)), []) |
| 265 | deepStrictEqual(pipe([1, 2], Arr.drop(-1)), [1, 2]) |
| 266 | |
| 267 | deepStrictEqual(pipe(new Set(), Arr.drop(0)), []) |
| 268 | deepStrictEqual(pipe(new Set([1, 2]), Arr.drop(0)), [1, 2]) |
| 269 | deepStrictEqual(pipe(new Set([1, 2]), Arr.drop(1)), [2]) |
| 270 | deepStrictEqual(pipe(new Set([1, 2]), Arr.drop(2)), []) |
| 271 | // out of bound |
| 272 | deepStrictEqual(pipe(new Set(), Arr.drop(1)), []) |
| 273 | deepStrictEqual(pipe(new Set(), Arr.drop(-1)), []) |
| 274 | deepStrictEqual(pipe(new Set([1, 2]), Arr.drop(3)), []) |
| 275 | deepStrictEqual(pipe(new Set([1, 2]), Arr.drop(-1)), [1, 2]) |
| 276 | }) |
| 277 | |
| 278 | it("dropRight", () => { |
| 279 | deepStrictEqual(pipe([], Arr.dropRight(0)), []) |
| 280 | deepStrictEqual(pipe([1, 2], Arr.dropRight(0)), [1, 2]) |
| 281 | deepStrictEqual(pipe([1, 2], Arr.dropRight(Number.NaN)), [1, 2]) |
| 282 | deepStrictEqual(pipe([1, 2], Arr.dropRight(1)), [1]) |
| 283 | deepStrictEqual(pipe([1, 2], Arr.dropRight(2)), []) |
| 284 | // out of bound |
| 285 | deepStrictEqual(pipe([], Arr.dropRight(1)), []) |
| 286 | deepStrictEqual(pipe([1, 2], Arr.dropRight(3)), []) |
| 287 | deepStrictEqual(pipe([], Arr.dropRight(-1)), []) |
| 288 | deepStrictEqual(pipe([1, 2], Arr.dropRight(-1)), [1, 2]) |
| 289 | |
| 290 | deepStrictEqual(pipe(new Set(), Arr.dropRight(0)), []) |
| 291 | deepStrictEqual(pipe(new Set([1, 2]), Arr.dropRight(0)), [1, 2]) |
| 292 | deepStrictEqual(pipe(new Set([1, 2]), Arr.dropRight(1)), [1]) |
| 293 | deepStrictEqual(pipe(new Set([1, 2]), Arr.dropRight(2)), []) |
| 294 | // out of bound |
| 295 | deepStrictEqual(pipe(new Set(), Arr.dropRight(1)), []) |
| 296 | deepStrictEqual(pipe(new Set([1, 2]), Arr.dropRight(3)), []) |
| 297 | deepStrictEqual(pipe(new Set(), Arr.dropRight(-1)), []) |
| 298 | deepStrictEqual(pipe(new Set([1, 2]), Arr.dropRight(-1)), [1, 2]) |
| 299 | }) |
| 300 | |
| 301 | it("dropWhile", () => { |
| 302 | const f = Arr.dropWhile<number>((n) => n > 0) |
| 303 | |
| 304 | deepStrictEqual(f([]), []) |
| 305 | deepStrictEqual(f([1, 2]), Arr.empty()) |
| 306 | deepStrictEqual(f([-1, -2]), [-1, -2]) |
| 307 | deepStrictEqual(f([-1, 2]), [-1, 2]) |
| 308 | deepStrictEqual(f([1, -2, 3]), [-2, 3]) |
| 309 | |
| 310 | deepStrictEqual(f(new Set<number>()), []) |
| 311 | deepStrictEqual(f(new Set([1, 2])), Arr.empty()) |
| 312 | deepStrictEqual(f(new Set([-1, -2])), [-1, -2]) |
| 313 | deepStrictEqual(f(new Set([-1, 2])), [-1, 2]) |
| 314 | deepStrictEqual(f(new Set([1, -2, 3])), [-2, 3]) |
| 315 | |
| 316 | // iterator input |
| 317 | deepStrictEqual(f([1, -2, 3][Symbol.iterator]()), [-2, 3]) |
| 318 | deepStrictEqual(f([][Symbol.iterator]()), []) |
| 319 | }) |
| 320 | |
| 321 | it("dropWhileFilter", () => { |
| 322 | const f: (n: number, i: number) => Result.Result<number, string> = (n, i) => |
| 323 | n + i < 5 ? Result.succeed(n * 10) : Result.fail(`stop: ${n}`) |
| 324 | |
| 325 | deepStrictEqual(Arr.dropWhileFilter([], f), []) |
| 326 | deepStrictEqual(Arr.dropWhileFilter([1, 2, 3], f), [3]) |
| 327 | deepStrictEqual(pipe([1, 2, 3], Arr.dropWhileFilter(f)), [3]) |
| 328 | |
| 329 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.dropWhileFilter(f)), [3]) |
| 330 | deepStrictEqual(pipe([][Symbol.iterator](), Arr.dropWhileFilter(f)), []) |
| 331 | }) |
| 332 | |
| 333 | it("findFirstIndex", () => { |
| 334 | assertNone(pipe([], Arr.findFirstIndex((n) => n % 2 === 0))) |
| 335 | assertSome(pipe([1, 2, 3], Arr.findFirstIndex((n) => n % 2 === 0)), 1) |
| 336 | assertSome(pipe([1, 2, 3, 1], Arr.findFirstIndex((n) => n % 2 === 0)), 1) |
| 337 | |
| 338 | assertNone(pipe(new Set<number>(), Arr.findFirstIndex((n) => n % 2 === 0))) |
| 339 | assertSome(pipe(new Set([1, 2, 3]), Arr.findFirstIndex((n) => n % 2 === 0)), 1) |
| 340 | assertSome(pipe(new Set([1, 2, 3, 4]), Arr.findFirstIndex((n) => n % 2 === 0)), 1) |
| 341 | }) |
| 342 | |
| 343 | it("findLastIndex", () => { |
| 344 | assertNone(pipe([], Arr.findLastIndex((n) => n % 2 === 0))) |
| 345 | assertSome(pipe([1, 2, 3], Arr.findLastIndex((n) => n % 2 === 0)), 1) |
| 346 | assertSome(pipe([1, 2, 3, 4], Arr.findLastIndex((n) => n % 2 === 0)), 3) |
| 347 | |
| 348 | assertNone(pipe(new Set<number>(), Arr.findLastIndex((n) => n % 2 === 0))) |
| 349 | assertSome(pipe(new Set([1, 2, 3]), Arr.findLastIndex((n) => n % 2 === 0)), 1) |
| 350 | assertSome(pipe(new Set([1, 2, 3, 4]), Arr.findLastIndex((n) => n % 2 === 0)), 3) |
| 351 | }) |
| 352 | |
| 353 | describe("findFirst", () => { |
| 354 | it("boolean-returning overloads", () => { |
| 355 | assertNone(pipe([], Arr.findFirst((n) => n % 2 === 0))) |
| 356 | assertSome(pipe([1, 2, 3], Arr.findFirst((n) => n % 2 === 0)), 2) |
| 357 | assertSome(pipe([1, 2, 3, 4], Arr.findFirst((n) => n % 2 === 0)), 2) |
| 358 | |
| 359 | assertNone(pipe(new Set<number>(), Arr.findFirst((n) => n % 2 === 0))) |
| 360 | assertSome(pipe(new Set([1, 2, 3]), Arr.findFirst((n) => n % 2 === 0)), 2) |
| 361 | assertSome(pipe(new Set([1, 2, 3, 4]), Arr.findFirst((n) => n % 2 === 0)), 2) |
| 362 | }) |
| 363 | |
| 364 | it("Option-returning overloads", () => { |
| 365 | assertNone( |
| 366 | pipe([], Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())) |
| 367 | ) |
| 368 | assertSome( |
| 369 | pipe([1, 2, 3], Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 370 | [2, 1] |
| 371 | ) |
| 372 | assertSome( |
| 373 | pipe([1, 2, 3, 4], Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 374 | [2, 1] |
| 375 | ) |
| 376 | |
| 377 | assertNone( |
| 378 | pipe(new Set<number>(), Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())) |
| 379 | ) |
| 380 | assertSome( |
| 381 | pipe(new Set([1, 2, 3]), Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 382 | [2, 1] |
| 383 | ) |
| 384 | assertSome( |
| 385 | pipe(new Set([1, 2, 3, 4]), Arr.findFirst((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 386 | [2, 1] |
| 387 | ) |
| 388 | }) |
| 389 | }) |
| 390 | |
| 391 | describe("findFirstWithIndex", () => { |
| 392 | it("boolean-returning overloads", () => { |
| 393 | assertNone(pipe([], Arr.findFirstWithIndex((n) => n % 2 === 0))) |
| 394 | assertSome(pipe([1, 2, 3], Arr.findFirstWithIndex((n) => n % 2 === 0)), [2, 1]) |
| 395 | assertSome(pipe([1, 2, 3, 4], Arr.findFirstWithIndex((n) => n % 2 === 0)), [2, 1]) |
| 396 | |
| 397 | assertNone(pipe(new Set<number>(), Arr.findFirstWithIndex((n) => n % 2 === 0))) |
| 398 | assertSome(pipe(new Set([1, 2, 3]), Arr.findFirstWithIndex((n) => n % 2 === 0)), [2, 1]) |
| 399 | assertSome(pipe(new Set([1, 2, 3, 4]), Arr.findFirstWithIndex((n) => n % 2 === 0)), [2, 1]) |
| 400 | }) |
| 401 | |
| 402 | it("Option-returning overloads", () => { |
| 403 | assertNone( |
| 404 | pipe([], Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())) |
| 405 | ) |
| 406 | assertSome( |
| 407 | pipe([1, 2, 3], Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())), |
| 408 | [3, 1] |
| 409 | ) |
| 410 | assertSome( |
| 411 | pipe([1, 2, 3, 4], Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())), |
| 412 | [3, 1] |
| 413 | ) |
| 414 | |
| 415 | assertNone( |
| 416 | pipe(new Set<number>(), Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())) |
| 417 | ) |
| 418 | assertSome( |
| 419 | pipe(new Set([1, 2, 3]), Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())), |
| 420 | [3, 1] |
| 421 | ) |
| 422 | assertSome( |
| 423 | pipe(new Set([1, 2, 3, 4]), Arr.findFirstWithIndex((n) => n % 2 === 0 ? Option.some(n + 1) : Option.none())), |
| 424 | [3, 1] |
| 425 | ) |
| 426 | }) |
| 427 | }) |
| 428 | |
| 429 | describe("findLast", () => { |
| 430 | it("boolean-returning overloads", () => { |
| 431 | assertNone(pipe([], Arr.findLast((n) => n % 2 === 0))) |
| 432 | assertSome(pipe([1, 2, 3], Arr.findLast((n) => n % 2 === 0)), 2) |
| 433 | assertSome(pipe([1, 2, 3, 4], Arr.findLast((n) => n % 2 === 0)), 4) |
| 434 | |
| 435 | assertNone(pipe(new Set<number>(), Arr.findLast((n) => n % 2 === 0))) |
| 436 | assertSome(pipe(new Set([1, 2, 3]), Arr.findLast((n) => n % 2 === 0)), 2) |
| 437 | assertSome(pipe(new Set([1, 2, 3, 4]), Arr.findLast((n) => n % 2 === 0)), 4) |
| 438 | }) |
| 439 | |
| 440 | it("Option-returning overloads", () => { |
| 441 | assertNone( |
| 442 | pipe([], Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())) |
| 443 | ) |
| 444 | assertSome( |
| 445 | pipe([1, 2, 3], Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 446 | [2, 1] |
| 447 | ) |
| 448 | assertSome( |
| 449 | pipe([1, 2, 3, 4], Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 450 | [4, 3] |
| 451 | ) |
| 452 | |
| 453 | assertNone( |
| 454 | pipe(new Set<number>(), Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())) |
| 455 | ) |
| 456 | assertSome( |
| 457 | pipe(new Set([1, 2, 3]), Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 458 | [2, 1] |
| 459 | ) |
| 460 | assertSome( |
| 461 | pipe(new Set([1, 2, 3, 4]), Arr.findLast((n, i) => n % 2 === 0 ? Option.some([n, i]) : Option.none())), |
| 462 | [4, 3] |
| 463 | ) |
| 464 | }) |
| 465 | }) |
| 466 | |
| 467 | it("insertAt", () => { |
| 468 | assertNone(Arr.insertAt(1, 1)([])) |
| 469 | assertSome(Arr.insertAt(0, 1)([]), [1]) |
| 470 | assertSome(Arr.insertAt(2, 5)([1, 2, 3, 4]), [1, 2, 5, 3, 4]) |
| 471 | // out of bound |
| 472 | assertNone(Arr.insertAt(-1, 5)([1, 2, 3, 4])) |
| 473 | assertNone(Arr.insertAt(10, 5)([1, 2, 3, 4])) |
| 474 | |
| 475 | assertNone(Arr.insertAt(1, 1)(new Set([]))) |
| 476 | assertSome(Arr.insertAt(0, 1)(new Set([])), [1]) |
| 477 | assertSome(Arr.insertAt(2, 5)(new Set([1, 2, 3, 4])), [1, 2, 5, 3, 4]) |
| 478 | // out of bound |
| 479 | assertNone(Arr.insertAt(-1, 5)(new Set([1, 2, 3, 4]))) |
| 480 | assertNone(Arr.insertAt(10, 5)(new Set([1, 2, 3, 4]))) |
| 481 | }) |
| 482 | |
| 483 | it("replace", () => { |
| 484 | assertSome(pipe([1, 2, 3], Arr.replace(1, "a")), [1, "a", 3]) |
| 485 | // out of bound |
| 486 | assertNone(pipe([], Arr.replace(1, "a"))) |
| 487 | assertNone(pipe([1, 2, 3], Arr.replace(-1, "a"))) |
| 488 | assertNone(pipe([1, 2, 3], Arr.replace(10, "a"))) |
| 489 | |
| 490 | assertSome(pipe(new Set([1, 2, 3]), Arr.replace(1, "a")), [1, "a", 3]) |
| 491 | // out of bound |
| 492 | assertNone(pipe(new Set([]), Arr.replace(1, "a"))) |
| 493 | assertNone(pipe(new Set([1, 2, 3]), Arr.replace(-1, "a"))) |
| 494 | assertNone(pipe(new Set([1, 2, 3]), Arr.replace(10, "a"))) |
| 495 | }) |
| 496 | |
| 497 | it("modify", () => { |
| 498 | assertSome(pipe([1, 2, 3], Arr.modify(1, double)), [1, 4, 3]) |
| 499 | // out of bound |
| 500 | assertNone(pipe([], Arr.modify(1, double))) |
| 501 | assertNone(pipe([1, 2, 3], Arr.modify(10, double))) |
| 502 | |
| 503 | assertSome(pipe(new Set([1, 2, 3]), Arr.modify(1, double)), [1, 4, 3]) |
| 504 | // out of bound |
| 505 | assertNone(pipe(new Set([]), Arr.modify(1, double))) |
| 506 | assertNone(pipe(new Set([1, 2, 3]), Arr.modify(10, double))) |
| 507 | }) |
| 508 | |
| 509 | it("remove", () => { |
| 510 | deepStrictEqual(pipe([1, 2, 3], Arr.remove(0)), [2, 3]) |
| 511 | // out of bound |
| 512 | deepStrictEqual(pipe([], Arr.remove(0)), []) |
| 513 | deepStrictEqual(pipe([1, 2, 3], Arr.remove(-1)), [1, 2, 3]) |
| 514 | deepStrictEqual(pipe([1, 2, 3], Arr.remove(10)), [1, 2, 3]) |
| 515 | |
| 516 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.remove(0)), [2, 3]) |
| 517 | // out of bound |
| 518 | deepStrictEqual(pipe(new Set([]), Arr.remove(0)), []) |
| 519 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.remove(-1)), [1, 2, 3]) |
| 520 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.remove(10)), [1, 2, 3]) |
| 521 | }) |
| 522 | |
| 523 | it("reverse", () => { |
| 524 | deepStrictEqual(Arr.reverse([]), []) |
| 525 | deepStrictEqual(Arr.reverse([1]), [1]) |
| 526 | deepStrictEqual(Arr.reverse([1, 2, 3]), [3, 2, 1]) |
| 527 | |
| 528 | deepStrictEqual(Arr.reverse(new Set([])), []) |
| 529 | deepStrictEqual(Arr.reverse(new Set([1])), [1]) |
| 530 | deepStrictEqual(Arr.reverse(new Set([1, 2, 3])), [3, 2, 1]) |
| 531 | }) |
| 532 | |
| 533 | it("sort", () => { |
| 534 | deepStrictEqual(Arr.sort(Num.Order)([]), []) |
| 535 | deepStrictEqual(Arr.sort(Num.Order)([1, 3, 2]), [1, 2, 3]) |
| 536 | |
| 537 | deepStrictEqual(Arr.sort(Num.Order)(new Set<number>()), []) |
| 538 | deepStrictEqual(Arr.sort(Num.Order)(new Set([1, 3, 2])), [1, 2, 3]) |
| 539 | }) |
| 540 | |
| 541 | it("zip", () => { |
| 542 | deepStrictEqual(pipe(new Set([]), Arr.zip(new Set(["a", "b", "c", "d"]))), []) |
| 543 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.zip(new Set([]))), []) |
| 544 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.zip(new Set(["a", "b", "c", "d"]))), [ |
| 545 | [1, "a"], |
| 546 | [2, "b"], |
| 547 | [3, "c"] |
| 548 | ]) |
| 549 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.zip(new Set(["a", "b", "c", "d"]))), [ |
| 550 | [1, "a"], |
| 551 | [2, "b"], |
| 552 | [3, "c"] |
| 553 | ]) |
| 554 | }) |
| 555 | |
| 556 | it("zipWith", () => { |
| 557 | deepStrictEqual( |
| 558 | pipe(new Set([1, 2, 3]), Arr.zipWith(new Set([]), (n, s) => s + n)), |
| 559 | [] |
| 560 | ) |
| 561 | deepStrictEqual( |
| 562 | pipe(new Set([]), Arr.zipWith(new Set(["a", "b", "c", "d"]), (n, s) => s + n)), |
| 563 | [] |
| 564 | ) |
| 565 | deepStrictEqual( |
| 566 | pipe(new Set([]), Arr.zipWith(new Set([]), (n, s) => s + n)), |
| 567 | [] |
| 568 | ) |
| 569 | deepStrictEqual( |
| 570 | pipe(new Set([1, 2, 3]), Arr.zipWith(new Set(["a", "b", "c", "d"]), (n, s) => s + n)), |
| 571 | ["a1", "b2", "c3"] |
| 572 | ) |
| 573 | }) |
| 574 | |
| 575 | it("unzip", () => { |
| 576 | deepStrictEqual(Arr.unzip(new Set([])), [[], []]) |
| 577 | deepStrictEqual( |
| 578 | Arr.unzip( |
| 579 | new Set( |
| 580 | [ |
| 581 | [1, "a"], |
| 582 | [2, "b"], |
| 583 | [3, "c"] |
| 584 | ] as const |
| 585 | ) |
| 586 | ), |
| 587 | [ |
| 588 | [1, 2, 3], |
| 589 | ["a", "b", "c"] |
| 590 | ] |
| 591 | ) |
| 592 | }) |
| 593 | |
| 594 | it("intersperse", () => { |
| 595 | deepStrictEqual(pipe([], Arr.intersperse(0)), []) |
| 596 | deepStrictEqual(pipe([1], Arr.intersperse(0)), [1]) |
| 597 | deepStrictEqual(pipe([1, 2, 3], Arr.intersperse(0)), [1, 0, 2, 0, 3]) |
| 598 | deepStrictEqual(pipe([1, 2], Arr.intersperse(0)), [1, 0, 2]) |
| 599 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.intersperse(0)), [1, 0, 2, 0, 3, 0, 4]) |
| 600 | |
| 601 | deepStrictEqual(pipe(new Set([]), Arr.intersperse(0)), []) |
| 602 | deepStrictEqual(pipe(new Set([1]), Arr.intersperse(0)), [1]) |
| 603 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.intersperse(0)), [1, 0, 2, 0, 3]) |
| 604 | deepStrictEqual(pipe(new Set([1, 2]), Arr.intersperse(0)), [1, 0, 2]) |
| 605 | deepStrictEqual(pipe(new Set([1, 2, 3, 4]), Arr.intersperse(0)), [1, 0, 2, 0, 3, 0, 4]) |
| 606 | }) |
| 607 | |
| 608 | it("rotate", () => { |
| 609 | deepStrictEqual(Arr.rotate(0)(Arr.empty()), Arr.empty()) |
| 610 | deepStrictEqual(Arr.rotate(1)(Arr.empty()), Arr.empty()) |
| 611 | deepStrictEqual(Arr.rotate(1)([1]), [1]) |
| 612 | deepStrictEqual(Arr.rotate(2)([1]), [1]) |
| 613 | deepStrictEqual(Arr.rotate(-1)([1]), [1]) |
| 614 | deepStrictEqual(Arr.rotate(-2)([1]), [1]) |
| 615 | deepStrictEqual(Arr.rotate(2)([1, 2]), [1, 2]) |
| 616 | deepStrictEqual(Arr.rotate(0)([1, 2]), [1, 2]) |
| 617 | deepStrictEqual(Arr.rotate(-2)([1, 2]), [1, 2]) |
| 618 | deepStrictEqual(Arr.rotate(1)([1, 2]), [2, 1]) |
| 619 | deepStrictEqual(Arr.rotate(1)(new Set([1, 2, 3, 4, 5])), [5, 1, 2, 3, 4]) |
| 620 | deepStrictEqual(Arr.rotate(2)(new Set([1, 2, 3, 4, 5])), [4, 5, 1, 2, 3]) |
| 621 | deepStrictEqual(Arr.rotate(-1)(new Set([1, 2, 3, 4, 5])), [2, 3, 4, 5, 1]) |
| 622 | deepStrictEqual(Arr.rotate(-2)(new Set([1, 2, 3, 4, 5])), [3, 4, 5, 1, 2]) |
| 623 | deepStrictEqual( |
| 624 | Arr.rotate(1)((function*() { |
| 625 | yield* [1, 2, 3] |
| 626 | })()), |
| 627 | [3, 1, 2] |
| 628 | ) |
| 629 | // out of bounds |
| 630 | deepStrictEqual(Arr.rotate(7)([1, 2, 3, 4, 5]), [4, 5, 1, 2, 3]) |
| 631 | deepStrictEqual(Arr.rotate(-7)([1, 2, 3, 4, 5]), [3, 4, 5, 1, 2]) |
| 632 | deepStrictEqual(Arr.rotate(2.2)([1, 2, 3, 4, 5]), [4, 5, 1, 2, 3]) |
| 633 | deepStrictEqual(Arr.rotate(-2.2)([1, 2, 3, 4, 5]), [3, 4, 5, 1, 2]) |
| 634 | }) |
| 635 | |
| 636 | it("containsWith", () => { |
| 637 | const contains = Arr.containsWith(Equivalence.strictEqual<number>()) |
| 638 | deepStrictEqual(pipe([1, 2, 3], contains(2)), true) |
| 639 | deepStrictEqual(pipe([1, 2, 3], contains(0)), false) |
| 640 | |
| 641 | deepStrictEqual(pipe(new Set([1, 2, 3]), contains(2)), true) |
| 642 | deepStrictEqual(pipe(new Set([1, 2, 3]), contains(0)), false) |
| 643 | }) |
| 644 | |
| 645 | it("contains", () => { |
| 646 | const contains = Arr.contains |
| 647 | deepStrictEqual(pipe([1, 2, 3], contains(2)), true) |
| 648 | deepStrictEqual(pipe([1, 2, 3], contains(0)), false) |
| 649 | |
| 650 | deepStrictEqual(pipe(new Set([1, 2, 3]), contains(2)), true) |
| 651 | deepStrictEqual(pipe(new Set([1, 2, 3]), contains(0)), false) |
| 652 | }) |
| 653 | |
| 654 | it("dedupeWith", () => { |
| 655 | const dedupe = Arr.dedupeWith(Equivalence.strictEqual<number>()) |
| 656 | deepStrictEqual(dedupe([]), []) |
| 657 | deepStrictEqual(dedupe([-0, -0]), [-0]) |
| 658 | deepStrictEqual(dedupe([0, -0]), [0]) |
| 659 | deepStrictEqual(dedupe([1]), [1]) |
| 660 | deepStrictEqual(dedupe([2, 1, 2]), [2, 1]) |
| 661 | deepStrictEqual(dedupe([1, 2, 1]), [1, 2]) |
| 662 | deepStrictEqual(dedupe([1, 2, 3, 4, 5]), [1, 2, 3, 4, 5]) |
| 663 | deepStrictEqual(dedupe([1, 1, 2, 2, 3, 3, 4, 4, 5, 5]), [1, 2, 3, 4, 5]) |
| 664 | deepStrictEqual(dedupe([1, 2, 3, 4, 5, 1, 2, 3, 4, 5]), [1, 2, 3, 4, 5]) |
| 665 | }) |
| 666 | |
| 667 | it("dedupeAdjacentWith", () => { |
| 668 | const dedupeAdjacent = Arr.dedupeAdjacentWith(Equivalence.strictEqual<number>()) |
| 669 | deepStrictEqual(dedupeAdjacent([]), []) |
| 670 | deepStrictEqual(dedupeAdjacent([1, 2, 3]), [1, 2, 3]) |
| 671 | deepStrictEqual(dedupeAdjacent([1, 2, 2, 3, 3]), [1, 2, 3]) |
| 672 | }) |
| 673 | |
| 674 | it("splitAt", () => { |
| 675 | const assertSplitAt = ( |
| 676 | input: ReadonlyArray<number>, |
| 677 | index: number, |
| 678 | expectedInit: ReadonlyArray<number>, |
| 679 | expectedRest: ReadonlyArray<number> |
| 680 | ) => { |
| 681 | const [init, rest] = Arr.splitAt(index)(input) |
| 682 | deepStrictEqual(init, expectedInit) |
| 683 | deepStrictEqual(rest, expectedRest) |
| 684 | } |
| 685 | deepStrictEqual(Arr.splitAt(1)([1, 2]), [[1], [2]]) |
| 686 | assertSplitAt([1, 2], 2, [1, 2], []) |
| 687 | deepStrictEqual(Arr.splitAt(2)([1, 2, 3, 4, 5]), [ |
| 688 | [1, 2], |
| 689 | [3, 4, 5] |
| 690 | ]) |
| 691 | deepStrictEqual(Arr.splitAt(2)(new Set([1, 2, 3, 4, 5])), [ |
| 692 | [1, 2], |
| 693 | [3, 4, 5] |
| 694 | ]) |
| 695 | assertSplitAt([], 0, [], []) |
| 696 | assertSplitAt([1, 2], 0, [], [1, 2]) |
| 697 | assertSplitAt([1, 2], Number.NaN, [], [1, 2]) |
| 698 | |
| 699 | // out of bounds |
| 700 | assertSplitAt([], -1, [], []) |
| 701 | assertSplitAt([1, 2], -1, [], [1, 2]) |
| 702 | assertSplitAt([1, 2], 3, [1, 2], []) |
| 703 | assertSplitAt([], 3, [], []) |
| 704 | }) |
| 705 | }) |
| 706 | |
| 707 | it("splitAtNonEmpty", () => { |
| 708 | deepStrictEqual(pipe(Arr.make(1, 2, 3, 4), Arr.splitAtNonEmpty(2)), [[1, 2], [3, 4]]) |
| 709 | deepStrictEqual(pipe(Arr.make(1, 2, 3, 4), Arr.splitAtNonEmpty(10)), [[1, 2, 3, 4], []]) |
| 710 | deepStrictEqual(pipe(Arr.make(1, 2, 3, 4), Arr.splitAtNonEmpty(Number.NaN)), [[1], [2, 3, 4]]) |
| 711 | }) |
| 712 | |
| 713 | describe("getUnsafe", () => { |
| 714 | it("should throw on index out of bound", () => { |
| 715 | throws(() => pipe([], Arr.getUnsafe(100)), new Error("Index out of bounds: 100")) |
| 716 | }) |
| 717 | }) |
| 718 | |
| 719 | it("fromNullishOr", () => { |
| 720 | deepStrictEqual(Arr.fromNullishOr(undefined), []) |
| 721 | deepStrictEqual(Arr.fromNullishOr(null), []) |
| 722 | deepStrictEqual(Arr.fromNullishOr(1), [1]) |
| 723 | }) |
| 724 | |
| 725 | it("liftNullishOr", () => { |
| 726 | const f = Arr.liftNullishOr((n: number) => (n > 0 ? n : null)) |
| 727 | deepStrictEqual(f(1), [1]) |
| 728 | deepStrictEqual(f(-1), []) |
| 729 | }) |
| 730 | |
| 731 | it("flatMapNullishOr", () => { |
| 732 | const f = Arr.flatMapNullishOr((n: number) => (n > 0 ? n : null)) |
| 733 | deepStrictEqual(pipe([], f), []) |
| 734 | deepStrictEqual(pipe([1], f), [1]) |
| 735 | deepStrictEqual(pipe([1, 2], f), [1, 2]) |
| 736 | deepStrictEqual(pipe([-1], f), []) |
| 737 | deepStrictEqual(pipe([-1, 2], f), [2]) |
| 738 | }) |
| 739 | |
| 740 | it("liftPredicate", () => { |
| 741 | const p = (n: number): boolean => n > 2 |
| 742 | const f = Arr.liftPredicate(p) |
| 743 | deepStrictEqual(f(1), []) |
| 744 | deepStrictEqual(f(3), [3]) |
| 745 | }) |
| 746 | |
| 747 | it("liftOption", () => { |
| 748 | const f = Arr.liftOption((n: number) => (n > 0 ? Option.some(n) : Option.none())) |
| 749 | deepStrictEqual(f(1), [1]) |
| 750 | deepStrictEqual(f(-1), []) |
| 751 | }) |
| 752 | |
| 753 | it("unprepend", () => { |
| 754 | deepStrictEqual(Arr.unprepend([0]), [0, []]) |
| 755 | deepStrictEqual(Arr.unprepend([1, 2, 3, 4]), [1, [2, 3, 4]]) |
| 756 | }) |
| 757 | |
| 758 | it("unappend", () => { |
| 759 | deepStrictEqual(Arr.unappend([0]), [[], 0]) |
| 760 | deepStrictEqual(Arr.unappend([1, 2, 3, 4]), [ |
| 761 | Arr.make(1, 2, 3), |
| 762 | 4 |
| 763 | ]) |
| 764 | deepStrictEqual(Arr.unappend([0]), [[], 0]) |
| 765 | deepStrictEqual(Arr.unappend([1, 2, 3, 4]), [ |
| 766 | Arr.make(1, 2, 3), |
| 767 | 4 |
| 768 | ]) |
| 769 | }) |
| 770 | |
| 771 | it("modifyHeadNonEmpty", () => { |
| 772 | const f = (s: string) => s + "!" |
| 773 | deepStrictEqual(pipe(["a"], Arr.modifyHeadNonEmpty(f)), ["a!"]) |
| 774 | deepStrictEqual(pipe(["a", "b"], Arr.modifyHeadNonEmpty(f)), ["a!", "b"]) |
| 775 | deepStrictEqual(pipe(["a", "b", "c"], Arr.modifyHeadNonEmpty(f)), ["a!", "b", "c"]) |
| 776 | }) |
| 777 | |
| 778 | it("modifyLastNonEmpty", () => { |
| 779 | const f = (s: string) => s + "!" |
| 780 | deepStrictEqual(pipe(["a"], Arr.modifyLastNonEmpty(f)), ["a!"]) |
| 781 | deepStrictEqual(pipe(["a", "b"], Arr.modifyLastNonEmpty(f)), ["a", "b!"]) |
| 782 | deepStrictEqual(pipe(["a", "b", "c"], Arr.modifyLastNonEmpty(f)), ["a", "b", "c!"]) |
| 783 | }) |
| 784 | |
| 785 | it("setHeadNonEmpty", () => { |
| 786 | deepStrictEqual(pipe(Arr.make("a"), Arr.setHeadNonEmpty("d")), ["d"]) |
| 787 | deepStrictEqual(pipe(Arr.make("a", "b"), Arr.setHeadNonEmpty("d")), ["d", "b"]) |
| 788 | deepStrictEqual(pipe(Arr.make("a", "b", "c"), Arr.setHeadNonEmpty("d")), ["d", "b", "c"]) |
| 789 | }) |
| 790 | |
| 791 | it("setLastNonEmpty", () => { |
| 792 | deepStrictEqual(pipe(Arr.make("a"), Arr.setLastNonEmpty("d")), ["d"]) |
| 793 | deepStrictEqual(pipe(Arr.make("a", "b"), Arr.setLastNonEmpty("d")), ["a", "d"]) |
| 794 | deepStrictEqual(pipe(Arr.make("a", "b", "c"), Arr.setLastNonEmpty("d")), ["a", "b", "d"]) |
| 795 | }) |
| 796 | |
| 797 | it("liftResult", () => { |
| 798 | const f = Arr.liftResult((s: string) => s.length > 2 ? Result.succeed(s.length) : Result.fail("e")) |
| 799 | deepStrictEqual(f("a"), []) |
| 800 | deepStrictEqual(f("aaa"), [3]) |
| 801 | }) |
| 802 | |
| 803 | it("headNonEmpty", () => { |
| 804 | deepStrictEqual(Arr.headNonEmpty(Arr.make(1, 2)), 1) |
| 805 | }) |
| 806 | |
| 807 | it("tailNonEmpty", () => { |
| 808 | deepStrictEqual(Arr.tailNonEmpty(Arr.make(1, 2)), [2]) |
| 809 | }) |
| 810 | |
| 811 | it("lastNonEmpty", () => { |
| 812 | deepStrictEqual(Arr.lastNonEmpty(Arr.make(1, 2, 3)), 3) |
| 813 | deepStrictEqual(Arr.lastNonEmpty([1]), 1) |
| 814 | }) |
| 815 | |
| 816 | it("initNonEmpty", () => { |
| 817 | deepStrictEqual( |
| 818 | Arr.initNonEmpty(Arr.make(1, 2, 3)), |
| 819 | Arr.make(1, 2) |
| 820 | ) |
| 821 | deepStrictEqual(Arr.initNonEmpty([1]), []) |
| 822 | }) |
| 823 | |
| 824 | it("get", () => { |
| 825 | assertSome(pipe([1, 2, 3], Arr.get(0)), 1) |
| 826 | assertNone(pipe([1, 2, 3], Arr.get(3))) |
| 827 | }) |
| 828 | |
| 829 | it("unfold", () => { |
| 830 | const as = Arr.unfold(5, (n) => (n > 0 ? Option.some([n, n - 1]) : Option.none())) |
| 831 | deepStrictEqual(as, [5, 4, 3, 2, 1]) |
| 832 | }) |
| 833 | |
| 834 | it("map", () => { |
| 835 | deepStrictEqual( |
| 836 | pipe([1, 2, 3], Arr.map((n) => n * 2)), |
| 837 | [2, 4, 6] |
| 838 | ) |
| 839 | deepStrictEqual( |
| 840 | pipe(["a", "b"], Arr.map((s, i) => s + i)), |
| 841 | ["a0", "b1"] |
| 842 | ) |
| 843 | }) |
| 844 | |
| 845 | it("flatMap", () => { |
| 846 | deepStrictEqual( |
| 847 | pipe([1, 2, 3], Arr.flatMap((n) => [n, n + 1])), |
| 848 | [1, 2, 2, 3, 3, 4] |
| 849 | ) |
| 850 | const f = Arr.flatMap((n: number, i) => [n + i]) |
| 851 | deepStrictEqual(pipe([], f), []) |
| 852 | deepStrictEqual(pipe([1, 2, 3], f), [1, 3, 5]) |
| 853 | }) |
| 854 | |
| 855 | it("extend", () => { |
| 856 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.extend(Num.sumAll)), [10, 9, 7, 4]) |
| 857 | deepStrictEqual(pipe([1, 2, 3, 4], Arr.extend(identity)), [ |
| 858 | [1, 2, 3, 4], |
| 859 | [2, 3, 4], |
| 860 | [3, 4], |
| 861 | [4] |
| 862 | ]) |
| 863 | }) |
| 864 | |
| 865 | it("compact", () => { |
| 866 | deepStrictEqual(Arr.getSomes([]), []) |
| 867 | deepStrictEqual(Arr.getSomes([Option.some(1), Option.some(2), Option.some(3)]), [ |
| 868 | 1, |
| 869 | 2, |
| 870 | 3 |
| 871 | ]) |
| 872 | deepStrictEqual(Arr.getSomes([Option.some(1), Option.none(), Option.some(3)]), [ |
| 873 | 1, |
| 874 | 3 |
| 875 | ]) |
| 876 | }) |
| 877 | |
| 878 | it("separate", () => { |
| 879 | deepStrictEqual(Arr.separate([]), [[], []]) |
| 880 | deepStrictEqual(Arr.separate([Result.succeed(1), Result.fail("e"), Result.fail(2), Result.succeed(2)]), [ |
| 881 | [1, 2], |
| 882 | ["e", 2] |
| 883 | ]) |
| 884 | }) |
| 885 | |
| 886 | it("filter", () => { |
| 887 | deepStrictEqual(Arr.filter([1, 2, 3], (n) => n % 2 === 1), [1, 3]) |
| 888 | deepStrictEqual(Arr.filter([Option.some(3), Option.some(2), Option.some(1)], Option.isSome), [ |
| 889 | Option.some(3), |
| 890 | Option.some(2), |
| 891 | Option.some(1) |
| 892 | ]) |
| 893 | deepStrictEqual(Arr.filter([Option.some(3), Option.none(), Option.some(1)], Option.isSome), [ |
| 894 | Option.some(3), |
| 895 | Option.some(1) |
| 896 | ]) |
| 897 | deepStrictEqual(Arr.filter(["a", "b", "c"], (_, i) => i % 2 === 0), ["a", "c"]) |
| 898 | }) |
| 899 | |
| 900 | it("filterMap", () => { |
| 901 | const f: (n: number, i: number) => Result.Result<number, string> = (n, i) => |
| 902 | n + i < 4 ? Result.succeed(n * 2) : Result.fail(`skip: ${n}`) |
| 903 | |
| 904 | deepStrictEqual(Arr.filterMap([], f), []) |
| 905 | deepStrictEqual(Arr.filterMap([1, 2, 3], f), [2, 4]) |
| 906 | deepStrictEqual(pipe([1, 2, 3], Arr.filterMap(f)), [2, 4]) |
| 907 | deepStrictEqual(pipe(new Set([1, 2, 3]), Arr.filterMap(f)), [2, 4]) |
| 908 | deepStrictEqual(pipe([1, 2, 3][Symbol.iterator](), Arr.filterMap(f)), [2, 4]) |
| 909 | }) |
| 910 | |
| 911 | it("partition (identity)", () => { |
| 912 | deepStrictEqual(Arr.partition([], identity), [[], []]) |
| 913 | deepStrictEqual(Arr.partition([Result.succeed(1), Result.fail("a"), Result.succeed(2)], identity), [[1, 2], ["a"]]) |
| 914 | }) |
| 915 | |
| 916 | it("partition - transformed outputs", () => { |
| 917 | deepStrictEqual(Arr.partition([], (n) => n > 2 ? Result.succeed(n) : Result.fail(n)), [[], []]) |
| 918 | deepStrictEqual(Arr.partition([1, 3], (n) => n > 2 ? Result.succeed(n) : Result.fail(n)), [[3], [1]]) |
| 919 | |
| 920 | deepStrictEqual(Arr.partition([], (n, i) => n + i > 2 ? Result.succeed(n) : Result.fail(n)), [[], []]) |
| 921 | deepStrictEqual(Arr.partition([1, 2], (n, i) => n + i > 2 ? Result.succeed(n) : Result.fail(n)), [[2], [1]]) |
| 922 | }) |
| 923 | |
| 924 | it("reduce", () => { |
| 925 | deepStrictEqual(pipe(["a", "b", "c"], Arr.reduce("", (b, a) => b + a)), "abc") |
| 926 | deepStrictEqual( |
| 927 | pipe( |
| 928 | ["a", "b"], |
| 929 | Arr.reduce("", (b, a, i) => b + i + a) |
| 930 | ), |
| 931 | "0a1b" |
| 932 | ) |
| 933 | }) |
| 934 | |
| 935 | it("reduceRight", () => { |
| 936 | const f = (b: string, a: string) => b + a |
| 937 | deepStrictEqual(pipe(["a", "b", "c"], Arr.reduceRight("", f)), "cba") |
| 938 | deepStrictEqual(pipe([], Arr.reduceRight("", f)), "") |
| 939 | deepStrictEqual( |
| 940 | pipe( |
| 941 | ["a", "b"], |
| 942 | Arr.reduceRight("", (b, a, i) => b + i + a) |
| 943 | ), |
| 944 | "1b0a" |
| 945 | ) |
| 946 | }) |
| 947 | |
| 948 | it("makeOrder", () => { |
| 949 | const O = Arr.makeOrder(Str.Order) |
| 950 | deepStrictEqual(O([], []), 0) |
| 951 | deepStrictEqual(O(["a"], ["a"]), 0) |
| 952 | |
| 953 | deepStrictEqual(O(["a"], ["b"]), -1) |
| 954 | deepStrictEqual(O(["b"], ["a"]), 1) |
| 955 | |
| 956 | deepStrictEqual(O([], ["a"]), -1) |
| 957 | deepStrictEqual(O(["a"], []), 1) |
| 958 | deepStrictEqual(O(["a"], ["a", "a"]), -1) |
| 959 | deepStrictEqual(O(["b"], ["a", "a"]), 1) |
| 960 | |
| 961 | deepStrictEqual(O(["a", "a"], ["a", "a"]), 0) |
| 962 | deepStrictEqual(O(["a", "b"], ["a", "b"]), 0) |
| 963 | |
| 964 | deepStrictEqual(O(["a", "b"], ["a", "a"]), 1) |
| 965 | deepStrictEqual(O(["a", "a"], ["a", "b"]), -1) |
| 966 | |
| 967 | deepStrictEqual(O(["b", "a"], ["a", "b"]), 1) |
| 968 | deepStrictEqual(O(["a", "a"], ["b", "a"]), -1) |
| 969 | deepStrictEqual(O(["a", "b"], ["b", "a"]), -1) |
| 970 | deepStrictEqual(O(["b", "a"], ["b", "b"]), -1) |
| 971 | deepStrictEqual(O(["b", "b"], ["b", "a"]), 1) |
| 972 | }) |
| 973 | |
| 974 | it("isReadonlyArrayEmpty", () => { |
| 975 | deepStrictEqual(Arr.isReadonlyArrayEmpty([1, 2, 3]), false) |
| 976 | deepStrictEqual(Arr.isReadonlyArrayEmpty([]), true) |
| 977 | }) |
| 978 | |
| 979 | it("isArrayEmpty", () => { |
| 980 | deepStrictEqual(Arr.isArrayEmpty([1, 2, 3]), false) |
| 981 | deepStrictEqual(Arr.isArrayEmpty([]), true) |
| 982 | }) |
| 983 | |
| 984 | it("isReadonlyArrayNonEmpty", () => { |
| 985 | deepStrictEqual(Arr.isReadonlyArrayNonEmpty([1, 2, 3]), true) |
| 986 | deepStrictEqual(Arr.isReadonlyArrayNonEmpty([]), false) |
| 987 | }) |
| 988 | |
| 989 | it("isArrayNonEmpty", () => { |
| 990 | deepStrictEqual(Arr.isArrayNonEmpty([1, 2, 3]), true) |
| 991 | deepStrictEqual(Arr.isArrayNonEmpty([]), false) |
| 992 | }) |
| 993 | |
| 994 | it("head", () => { |
| 995 | const as: ReadonlyArray<number> = [1, 2, 3] |
| 996 | assertSome(Arr.head(as), 1) |
| 997 | assertNone(Arr.head([])) |
| 998 | }) |
| 999 | |
| 1000 | it("last", () => { |
| 1001 | const as: ReadonlyArray<number> = [1, 2, 3] |
| 1002 | assertSome(Arr.last(as), 3) |
| 1003 | assertNone(Arr.last([])) |
| 1004 | }) |
| 1005 | |
| 1006 | it("chunksOf", () => { |
| 1007 | deepStrictEqual(Arr.chunksOf(2)([1, 2, 3, 4, 5]), [ |
| 1008 | Arr.make(1, 2), |
| 1009 | [3, 4], |
| 1010 | [5] |
| 1011 | ]) |
| 1012 | deepStrictEqual(Arr.chunksOf(2)([1, 2, 3, 4, 5, 6]), [ |
| 1013 | Arr.make(1, 2), |
| 1014 | [3, 4], |
| 1015 | [5, 6] |
| 1016 | ]) |
| 1017 | deepStrictEqual(Arr.chunksOf(1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1018 | deepStrictEqual(Arr.chunksOf(5)([1, 2, 3, 4, 5]), [[1, 2, 3, 4, 5]]) |
| 1019 | // out of bounds |
| 1020 | deepStrictEqual(Arr.chunksOf(0)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1021 | deepStrictEqual(Arr.chunksOf(-1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1022 | deepStrictEqual(Arr.chunksOf(Number.NaN)([1, 2, 3]), [[1], [2], [3]]) |
| 1023 | |
| 1024 | const assertSingleChunk = ( |
| 1025 | input: Arr.NonEmptyReadonlyArray<number>, |
| 1026 | n: number |
| 1027 | ) => { |
| 1028 | const chunks = Arr.chunksOf(n)(input) |
| 1029 | strictEqual(chunks.length, 1) |
| 1030 | deepStrictEqual(Arr.headNonEmpty(chunks), input) |
| 1031 | } |
| 1032 | // n = length |
| 1033 | assertSingleChunk(Arr.make(1, 2), 2) |
| 1034 | // n out of bounds |
| 1035 | assertSingleChunk(Arr.make(1, 2), 3) |
| 1036 | }) |
| 1037 | |
| 1038 | it("window", () => { |
| 1039 | deepStrictEqual(Arr.window([], 0), []) |
| 1040 | deepStrictEqual(Arr.window([], 2), []) |
| 1041 | deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 2), [[1, 2], [2, 3], [3, 4], [4, 5]]) |
| 1042 | deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 3), [[1, 2, 3], [2, 3, 4], [3, 4, 5]]) |
| 1043 | deepStrictEqual(Arr.window([1, 2, 3], 1.5), [[1], [2], [3]]) |
| 1044 | deepStrictEqual(Arr.window([1, 2, 3], Number.NaN), []) |
| 1045 | |
| 1046 | // n out of bounds |
| 1047 | deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 6), []) |
| 1048 | deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 0), []) |
| 1049 | deepStrictEqual(Arr.window([1, 2, 3, 4, 5], -1), []) |
| 1050 | }) |
| 1051 | |
| 1052 | it("min", () => { |
| 1053 | deepStrictEqual(Arr.min(Num.Order)([2, 1, 3]), 1) |
| 1054 | deepStrictEqual(Arr.min(Num.Order)([3]), 3) |
| 1055 | }) |
| 1056 | |
| 1057 | it("max", () => { |
| 1058 | deepStrictEqual( |
| 1059 | Arr.max(Num.Order)(Arr.make(1, 2, 3)), |
| 1060 | 3 |
| 1061 | ) |
| 1062 | deepStrictEqual(Arr.max(Num.Order)([1]), 1) |
| 1063 | }) |
| 1064 | |
| 1065 | it("flatten", () => { |
| 1066 | deepStrictEqual(Arr.flatten([[1], [2], [3]]), [1, 2, 3]) |
| 1067 | }) |
| 1068 | |
| 1069 | it("groupWith", () => { |
| 1070 | const groupWith = Arr.groupWith(Equivalence.strictEqual<number>()) |
| 1071 | deepStrictEqual(groupWith([1, 2, 1, 1]), [[1], [2], [1, 1]]) |
| 1072 | deepStrictEqual(groupWith([1, 2, 1, 1, 3]), [[1], [2], [1, 1], [3]]) |
| 1073 | }) |
| 1074 | |
| 1075 | it("groupBy", () => { |
| 1076 | deepStrictEqual(Arr.groupBy((_) => "")([]), {}) |
| 1077 | deepStrictEqual(Arr.groupBy((a) => `${a}`)([1]), { "1": [1] }) |
| 1078 | deepStrictEqual( |
| 1079 | Arr.groupBy((s: string) => `${s.length}`)(["foo", "bar", "foobar"]), |
| 1080 | { |
| 1081 | "3": ["foo", "bar"], |
| 1082 | "6": ["foobar"] |
| 1083 | } |
| 1084 | ) |
| 1085 | deepStrictEqual(Arr.groupBy(["a", "b"], (s) => s === "a" ? symA : s === "b" ? symB : symC), { |
| 1086 | [symA]: ["a"], |
| 1087 | [symB]: ["b"] |
| 1088 | }) |
| 1089 | deepStrictEqual(Arr.groupBy(["a", "b", "c", "d"], (s) => s === "a" ? symA : s === "b" ? symB : symC), { |
| 1090 | [symA]: ["a"], |
| 1091 | [symB]: ["b"], |
| 1092 | [symC]: ["c", "d"] |
| 1093 | }) |
| 1094 | }) |
| 1095 | |
| 1096 | it("match", () => { |
| 1097 | const len: <A>(as: ReadonlyArray<A>) => number = Arr.match({ |
| 1098 | onEmpty: () => 0, |
| 1099 | onNonEmpty: (as) => 1 + len(as.slice(1)) |
| 1100 | }) |
| 1101 | deepStrictEqual(len([1, 2, 3]), 3) |
| 1102 | }) |
| 1103 | |
| 1104 | it("matchLeft", () => { |
| 1105 | const len: <A>(as: ReadonlyArray<A>) => number = Arr.matchLeft({ |
| 1106 | onEmpty: () => 0, |
| 1107 | onNonEmpty: (_, tail) => 1 + len(tail) |
| 1108 | }) |
| 1109 | deepStrictEqual(len([1, 2, 3]), 3) |
| 1110 | }) |
| 1111 | |
| 1112 | it("matchRight", () => { |
| 1113 | const len: <A>(as: ReadonlyArray<A>) => number = Arr.matchRight({ |
| 1114 | onEmpty: () => 0, |
| 1115 | onNonEmpty: (init, _) => 1 + len(init) |
| 1116 | }) |
| 1117 | deepStrictEqual(len([1, 2, 3]), 3) |
| 1118 | }) |
| 1119 | |
| 1120 | it("sortBy", () => { |
| 1121 | interface X { |
| 1122 | readonly a: string |
| 1123 | readonly b: number |
| 1124 | readonly c: boolean |
| 1125 | } |
| 1126 | |
| 1127 | const byName = pipe( |
| 1128 | Str.Order, |
| 1129 | Order.mapInput((p: { readonly a: string; readonly b: number }) => p.a) |
| 1130 | ) |
| 1131 | |
| 1132 | const byAge = pipe( |
| 1133 | Num.Order, |
| 1134 | Order.mapInput((p: { readonly a: string; readonly b: number }) => p.b) |
| 1135 | ) |
| 1136 | |
| 1137 | const sortByNameByAge = Arr.sortBy(byName, byAge) |
| 1138 | |
| 1139 | const xs: Arr.NonEmptyArray<X> = [ |
| 1140 | { a: "a", b: 1, c: true }, |
| 1141 | { a: "b", b: 3, c: true }, |
| 1142 | { a: "c", b: 2, c: true }, |
| 1143 | { a: "b", b: 2, c: true } |
| 1144 | ] |
| 1145 | |
| 1146 | deepStrictEqual(Arr.sortBy()(xs), xs) |
| 1147 | deepStrictEqual(sortByNameByAge([]), []) |
| 1148 | deepStrictEqual(sortByNameByAge(xs), [ |
| 1149 | { a: "a", b: 1, c: true }, |
| 1150 | { a: "b", b: 2, c: true }, |
| 1151 | { a: "b", b: 3, c: true }, |
| 1152 | { a: "c", b: 2, c: true } |
| 1153 | ]) |
| 1154 | |
| 1155 | deepStrictEqual(Arr.sortBy()(new Set(xs)), xs) |
| 1156 | deepStrictEqual(sortByNameByAge(new Set([])), []) |
| 1157 | deepStrictEqual(sortByNameByAge(new Set(xs)), [ |
| 1158 | { a: "a", b: 1, c: true }, |
| 1159 | { a: "b", b: 2, c: true }, |
| 1160 | { a: "b", b: 3, c: true }, |
| 1161 | { a: "c", b: 2, c: true } |
| 1162 | ]) |
| 1163 | |
| 1164 | const sortByAgeByName = Arr.sortBy(byAge, byName) |
| 1165 | deepStrictEqual(sortByAgeByName(xs), [ |
| 1166 | { a: "a", b: 1, c: true }, |
| 1167 | { a: "b", b: 2, c: true }, |
| 1168 | { a: "c", b: 2, c: true }, |
| 1169 | { a: "b", b: 3, c: true } |
| 1170 | ]) |
| 1171 | }) |
| 1172 | |
| 1173 | it("copy", () => { |
| 1174 | deepStrictEqual(pipe([], Arr.copy), []) |
| 1175 | deepStrictEqual(pipe([1, 2, 3], Arr.copy), [1, 2, 3]) |
| 1176 | }) |
| 1177 | |
| 1178 | it("chop", () => { |
| 1179 | deepStrictEqual(pipe([], Arr.chop((as) => [as[0] * 2, as.slice(1)])), []) |
| 1180 | deepStrictEqual(pipe([1, 2, 3], Arr.chop((as) => [as[0] * 2, as.slice(1)])), [2, 4, 6]) |
| 1181 | }) |
| 1182 | |
| 1183 | it("pad", () => { |
| 1184 | deepStrictEqual(pipe([], Arr.pad(0, 0)), []) |
| 1185 | deepStrictEqual(pipe([1, 2, 3], Arr.pad(0, 0)), []) |
| 1186 | deepStrictEqual(pipe([1, 2, 3], Arr.pad(2, 0)), [1, 2]) |
| 1187 | deepStrictEqual(pipe([1], Arr.pad(1.5, 0)), [1]) |
| 1188 | deepStrictEqual(pipe([1, 2, 3], Arr.pad(6, 0)), [1, 2, 3, 0, 0, 0]) |
| 1189 | deepStrictEqual(pipe([1, 2, 3], Arr.pad(-2, 0)), []) |
| 1190 | deepStrictEqual(pipe([1, 2, 3], Arr.pad(Number.NaN, 0)), []) |
| 1191 | }) |
| 1192 | |
| 1193 | describe("chunksOf", () => { |
| 1194 | it("should split a `ReadonlyArray` into length-n pieces", () => { |
| 1195 | deepStrictEqual(Arr.chunksOf(2)([1, 2, 3, 4, 5]), [[1, 2], [3, 4], [5]]) |
| 1196 | deepStrictEqual(Arr.chunksOf(2)([1, 2, 3, 4, 5, 6]), [ |
| 1197 | [1, 2], |
| 1198 | [3, 4], |
| 1199 | [5, 6] |
| 1200 | ]) |
| 1201 | deepStrictEqual(Arr.chunksOf(1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1202 | deepStrictEqual(Arr.chunksOf(5)([1, 2, 3, 4, 5]), [[1, 2, 3, 4, 5]]) |
| 1203 | // out of bounds |
| 1204 | deepStrictEqual(Arr.chunksOf(0)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1205 | deepStrictEqual(Arr.chunksOf(-1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) |
| 1206 | |
| 1207 | const assertSingleChunk = (input: ReadonlyArray<number>, n: number) => { |
| 1208 | const chunks = Arr.chunksOf(n)(input) |
| 1209 | deepStrictEqual(chunks.length, 1) |
| 1210 | deepStrictEqual(chunks[0], input) |
| 1211 | } |
| 1212 | // n = length |
| 1213 | assertSingleChunk([1, 2], 2) |
| 1214 | // n out of bounds |
| 1215 | assertSingleChunk([1, 2], 3) |
| 1216 | }) |
| 1217 | |
| 1218 | it("returns an empty array if provided an empty array", () => { |
| 1219 | const empty: ReadonlyArray<number> = [] |
| 1220 | deepStrictEqual(Arr.chunksOf(0)(empty), Arr.empty()) |
| 1221 | deepStrictEqual(Arr.chunksOf(0)(Arr.empty()), Arr.empty()) |
| 1222 | deepStrictEqual(Arr.chunksOf(1)(empty), Arr.empty()) |
| 1223 | deepStrictEqual(Arr.chunksOf(1)(Arr.empty()), Arr.empty()) |
| 1224 | deepStrictEqual(Arr.chunksOf(2)(empty), Arr.empty()) |
| 1225 | deepStrictEqual(Arr.chunksOf(2)(Arr.empty()), Arr.empty()) |
| 1226 | }) |
| 1227 | |
| 1228 | it("should respect the law: chunksOf(n)(xs).concat(chunksOf(n)(ys)) == chunksOf(n)(xs.concat(ys)))", () => { |
| 1229 | const xs: ReadonlyArray<number> = [] |
| 1230 | const ys: ReadonlyArray<number> = [1, 2] |
| 1231 | deepStrictEqual( |
| 1232 | Arr.chunksOf(2)(xs).concat(Arr.chunksOf(2)(ys)), |
| 1233 | Arr.chunksOf(2)(xs.concat(ys)) |
| 1234 | ) |
| 1235 | fc.assert( |
| 1236 | fc.property( |
| 1237 | fc.array(fc.integer()).filter((xs) => xs.length % 2 === 0), // Ensures `xs.length` is even |
| 1238 | fc.array(fc.integer()), |
| 1239 | fc.integer({ min: 1, max: 1 }).map((x) => x * 2), // Generates `n` to be even so that it evenly divides `xs` |
| 1240 | (xs, ys, n) => { |
| 1241 | const as = Arr.chunksOf(n)(xs).concat(Arr.chunksOf(n)(ys)) |
| 1242 | const bs = Arr.chunksOf(n)(xs.concat(ys)) |
| 1243 | deepStrictEqual(as, bs) |
| 1244 | } |
| 1245 | ) |
| 1246 | ) |
| 1247 | }) |
| 1248 | }) |
| 1249 | |
| 1250 | it("makeBy", () => { |
| 1251 | deepStrictEqual(Arr.makeBy(5, (n) => n * 2), [0, 2, 4, 6, 8]) |
| 1252 | deepStrictEqual(Arr.makeBy((n) => n * 2)(5), [0, 2, 4, 6, 8]) |
| 1253 | deepStrictEqual(Arr.makeBy(2.2, (n) => n * 2), [0, 2]) |
| 1254 | deepStrictEqual(Arr.makeBy((n) => n * 2)(2.2), [0, 2]) |
| 1255 | deepStrictEqual(Arr.makeBy(Number.NaN, (n) => n), [0]) |
| 1256 | }) |
| 1257 | |
| 1258 | it("replicate", () => { |
| 1259 | deepStrictEqual(Arr.replicate("a", 0), ["a"]) |
| 1260 | deepStrictEqual(Arr.replicate("a", -1), ["a"]) |
| 1261 | deepStrictEqual(Arr.replicate("a", Number.NaN), ["a"]) |
| 1262 | deepStrictEqual(Arr.replicate("a", 3), ["a", "a", "a"]) |
| 1263 | deepStrictEqual(Arr.replicate("a", 2.2), ["a", "a"]) |
| 1264 | }) |
| 1265 | |
| 1266 | it("range", () => { |
| 1267 | deepStrictEqual(Arr.range(0, 0), [0]) |
| 1268 | deepStrictEqual(Arr.range(0, 1), [0, 1]) |
| 1269 | deepStrictEqual(Arr.range(1, 5), [1, 2, 3, 4, 5]) |
| 1270 | deepStrictEqual(Arr.range(10, 15), [10, 11, 12, 13, 14, 15]) |
| 1271 | deepStrictEqual(Arr.range(-1, 0), [-1, 0]) |
| 1272 | deepStrictEqual(Arr.range(-5, -1), [-5, -4, -3, -2, -1]) |
| 1273 | // out of bound |
| 1274 | deepStrictEqual(Arr.range(2, 1), [2]) |
| 1275 | deepStrictEqual(Arr.range(-1, -2), [-1]) |
| 1276 | }) |
| 1277 | |
| 1278 | it("unionWith", () => { |
| 1279 | const two: ReadonlyArray<number> = [1, 2] |
| 1280 | deepStrictEqual(pipe(two, Arr.unionWith([3, 4], Equivalence.strictEqual<number>())), [1, 2, 3, 4]) |
| 1281 | deepStrictEqual(pipe(two, Arr.unionWith([2, 3], Equivalence.strictEqual<number>())), [1, 2, 3]) |
| 1282 | deepStrictEqual(pipe(two, Arr.unionWith([1, 2], Equivalence.strictEqual<number>())), [1, 2]) |
| 1283 | deepStrictEqual(pipe(two, Arr.unionWith(Arr.empty(), Equivalence.strictEqual<number>())), two) |
| 1284 | deepStrictEqual(pipe(Arr.empty(), Arr.unionWith(two, Equivalence.strictEqual<number>())), two) |
| 1285 | deepStrictEqual( |
| 1286 | pipe(Arr.empty(), Arr.unionWith(Arr.empty(), Equivalence.strictEqual<number>())), |
| 1287 | Arr.empty() |
| 1288 | ) |
| 1289 | }) |
| 1290 | |
| 1291 | it("intersectionWith", () => { |
| 1292 | const intersectionWith = Arr.intersectionWith(Equivalence.strictEqual<number>()) |
| 1293 | deepStrictEqual(pipe([1, 2], intersectionWith([3, 4])), []) |
| 1294 | deepStrictEqual(pipe([1, 2], intersectionWith([2, 3])), [2]) |
| 1295 | deepStrictEqual(pipe([1, 2], intersectionWith([1, 2])), [1, 2]) |
| 1296 | // iterator input |
| 1297 | deepStrictEqual(pipe([1, 2], intersectionWith([3, 4][Symbol.iterator]())), []) |
| 1298 | deepStrictEqual(pipe([1, 2], intersectionWith([2, 3][Symbol.iterator]())), [2]) |
| 1299 | deepStrictEqual(pipe([1, 2], intersectionWith([1, 2][Symbol.iterator]())), [1, 2]) |
| 1300 | }) |
| 1301 | |
| 1302 | it("differenceWith", () => { |
| 1303 | const differenceWith = Arr.differenceWith(Equivalence.strictEqual<number>()) |
| 1304 | deepStrictEqual(pipe([1, 2], differenceWith([3, 4])), [1, 2]) |
| 1305 | deepStrictEqual(pipe([1, 2], differenceWith([2, 3])), [1]) |
| 1306 | deepStrictEqual(pipe([1, 2], differenceWith([1, 2])), []) |
| 1307 | // iterator input |
| 1308 | deepStrictEqual(pipe([1, 2], differenceWith([3, 4][Symbol.iterator]())), [1, 2]) |
| 1309 | deepStrictEqual(pipe([1, 2], differenceWith([2, 3][Symbol.iterator]())), [1]) |
| 1310 | deepStrictEqual(pipe([1, 2], differenceWith([1, 2][Symbol.iterator]())), []) |
| 1311 | }) |
| 1312 | |
| 1313 | it("empty", () => { |
| 1314 | deepStrictEqual(Arr.empty.length, 0) |
| 1315 | }) |
| 1316 | |
| 1317 | it("every", () => { |
| 1318 | const isPositive: Predicate.Predicate<number> = (n) => n > 0 |
| 1319 | deepStrictEqual(Arr.every([1, 2, 3], isPositive), true) |
| 1320 | deepStrictEqual(Arr.every([1, 2, -3], isPositive), false) |
| 1321 | }) |
| 1322 | |
| 1323 | it("some", () => { |
| 1324 | const isPositive: Predicate.Predicate<number> = (n) => n > 0 |
| 1325 | deepStrictEqual(Arr.some([-1, -2, 3], isPositive), true) |
| 1326 | deepStrictEqual(Arr.some([-1, -2, -3], isPositive), false) |
| 1327 | }) |
| 1328 | |
| 1329 | it("length", () => { |
| 1330 | deepStrictEqual(Arr.length(Arr.empty()), 0) |
| 1331 | deepStrictEqual(Arr.length([]), 0) |
| 1332 | deepStrictEqual(Arr.length(["a"]), 1) |
| 1333 | }) |
| 1334 | |
| 1335 | it("fromOption", () => { |
| 1336 | deepStrictEqual(Arr.fromOption(Option.some("hello")), ["hello"]) |
| 1337 | deepStrictEqual(Arr.fromOption(Option.none()), []) |
| 1338 | }) |
| 1339 | |
| 1340 | it("forEach", () => { |
| 1341 | const log: Array<string> = [] |
| 1342 | Arr.forEach(["a", "b", "c"], (a, i) => log.push(`${a}-${i}`)) |
| 1343 | deepStrictEqual(log, ["a-0", "b-1", "c-2"]) |
| 1344 | }) |
| 1345 | |
| 1346 | it("sortWith", () => { |
| 1347 | type X = { |
| 1348 | a: string |
| 1349 | b: number |
| 1350 | } |
| 1351 | const arr: ReadonlyArray<X> = [{ a: "a", b: 2 }, { a: "b", b: 1 }] |
| 1352 | deepStrictEqual(Arr.sortWith(arr, (x) => x.b, Order.Number), [{ a: "b", b: 1 }, { a: "a", b: 2 }]) |
| 1353 | }) |
| 1354 | |
| 1355 | it("countBy", () => { |
| 1356 | deepStrictEqual(Arr.countBy([1, 2, 3, 4, 5], (n) => n % 2 === 0), 2) |
| 1357 | deepStrictEqual(pipe([1, 2, 3, 4, 5], Arr.countBy((n) => n % 2 === 0)), 2) |
| 1358 | }) |
| 1359 | |
| 1360 | it("isArray", () => { |
| 1361 | strictEqual(Arr.isArray([]), true) |
| 1362 | strictEqual(Arr.isArray([1, 2, 3]), true) |
| 1363 | strictEqual(Arr.isArray("hello"), false) |
| 1364 | strictEqual(Arr.isArray(123), false) |
| 1365 | strictEqual(Arr.isArray(null), false) |
| 1366 | strictEqual(Arr.isArray(undefined), false) |
| 1367 | strictEqual(Arr.isArray({}), false) |
| 1368 | strictEqual(Arr.isArray(new Set([1, 2])), false) |
| 1369 | }) |
| 1370 | |
| 1371 | it("fromRecord", () => { |
| 1372 | deepStrictEqual(Arr.fromRecord({}), []) |
| 1373 | const entries = Arr.fromRecord({ a: 1, b: 2 }) |
| 1374 | deepStrictEqual(entries.length, 2) |
| 1375 | deepStrictEqual(entries.sort(([a], [b]) => a.localeCompare(b)), [["a", 1], ["b", 2]]) |
| 1376 | }) |
| 1377 | |
| 1378 | it("join", () => { |
| 1379 | deepStrictEqual(Arr.join([], ","), "") |
| 1380 | deepStrictEqual(Arr.join(["a"], ","), "a") |
| 1381 | deepStrictEqual(Arr.join(["a", "b", "c"], ", "), "a, b, c") |
| 1382 | deepStrictEqual(Arr.join(["a", "b", "c"], ""), "abc") |
| 1383 | deepStrictEqual(pipe(["x", "y"], Arr.join("-")), "x-y") |
| 1384 | }) |
| 1385 | |
| 1386 | it("mapAccum", () => { |
| 1387 | deepStrictEqual(Arr.mapAccum([1, 2, 3], 0, (acc, n) => [acc + n, acc + n]), [6, [1, 3, 6]]) |
| 1388 | deepStrictEqual(Arr.mapAccum([], 10, (acc, n: number) => [acc + n, n]), [10, []]) |
| 1389 | deepStrictEqual( |
| 1390 | pipe([1, 2, 3], Arr.mapAccum(0, (acc, n) => [acc + n, n * 2])), |
| 1391 | [6, [2, 4, 6]] |
| 1392 | ) |
| 1393 | deepStrictEqual( |
| 1394 | Arr.mapAccum(["a", "b", "c"], "", (acc, s, i) => [acc + s, `${s}${i}`]), |
| 1395 | ["abc", ["a0", "b1", "c2"]] |
| 1396 | ) |
| 1397 | }) |
| 1398 | |
| 1399 | it("partition", () => { |
| 1400 | const f: (n: number, i: number) => Result.Result<number, string> = (n, i) => |
| 1401 | n > 0 ? Result.succeed(n + i) : Result.fail(`negative: ${n}:${i}`) |
| 1402 | deepStrictEqual(Arr.partition([], f), [[], []]) |
| 1403 | deepStrictEqual(Arr.partition([1, -2, 3, -4], f), [[1, 5], ["negative: -2:1", "negative: -4:3"]]) |
| 1404 | deepStrictEqual(pipe([5, 10], Arr.partition(f)), [[5, 11], []]) |
| 1405 | deepStrictEqual(pipe([-1, -2], Arr.partition(f)), [[], ["negative: -1:0", "negative: -2:1"]]) |
| 1406 | deepStrictEqual( |
| 1407 | pipe(new Set([1, -2, 3, -4]), Arr.partition(f)), |
| 1408 | [[1, 5], ["negative: -2:1", "negative: -4:3"]] |
| 1409 | ) |
| 1410 | deepStrictEqual(pipe([1, -2, 3][Symbol.iterator](), Arr.partition(f)), [[1, 5], ["negative: -2:1"]]) |
| 1411 | }) |
| 1412 | |
| 1413 | it("partition with typed pass/fail outputs", () => { |
| 1414 | const items: Array<string | number> = [1, "a", 2, "b"] |
| 1415 | deepStrictEqual( |
| 1416 | Arr.partition(items, (x) => typeof x === "number" ? Result.succeed(x) : Result.fail(x)), |
| 1417 | [[1, 2], ["a", "b"]] |
| 1418 | ) |
| 1419 | }) |
| 1420 | |
| 1421 | it("getFailures", () => { |
| 1422 | deepStrictEqual(Arr.getFailures([]), []) |
| 1423 | deepStrictEqual( |
| 1424 | Arr.getFailures([Result.succeed(1), Result.fail("err"), Result.succeed(2)]), |
| 1425 | ["err"] |
| 1426 | ) |
| 1427 | deepStrictEqual( |
| 1428 | Arr.getFailures([Result.fail("a"), Result.fail("b")]), |
| 1429 | ["a", "b"] |
| 1430 | ) |
| 1431 | deepStrictEqual( |
| 1432 | Arr.getFailures([Result.succeed(1), Result.succeed(2)]), |
| 1433 | [] |
| 1434 | ) |
| 1435 | }) |
| 1436 | |
| 1437 | it("getSuccesses", () => { |
| 1438 | deepStrictEqual(Arr.getSuccesses([]), []) |
| 1439 | deepStrictEqual( |
| 1440 | Arr.getSuccesses([Result.succeed(1), Result.fail("err"), Result.succeed(2)]), |
| 1441 | [1, 2] |
| 1442 | ) |
| 1443 | deepStrictEqual( |
| 1444 | Arr.getSuccesses([Result.fail("a"), Result.fail("b")]), |
| 1445 | [] |
| 1446 | ) |
| 1447 | deepStrictEqual( |
| 1448 | Arr.getSuccesses([Result.succeed(1), Result.succeed(2)]), |
| 1449 | [1, 2] |
| 1450 | ) |
| 1451 | }) |
| 1452 | |
| 1453 | it("dedupe", () => { |
| 1454 | deepStrictEqual(Arr.dedupe([]), []) |
| 1455 | deepStrictEqual(Arr.dedupe([1, 2, 1, 3, 2, 4]), [1, 2, 3, 4]) |
| 1456 | deepStrictEqual(Arr.dedupe([1, 2, 3]), [1, 2, 3]) |
| 1457 | deepStrictEqual(Arr.dedupe([1, 1, 1]), [1]) |
| 1458 | deepStrictEqual(Arr.dedupe(["a", "b", "a"]), ["a", "b"]) |
| 1459 | deepStrictEqual(Arr.dedupe([NaN, NaN]), [NaN]) |
| 1460 | deepStrictEqual(Arr.dedupe([0, -0]), [0]) |
| 1461 | deepStrictEqual( |
| 1462 | Arr.dedupe([new HashCollision(1), new HashCollision(2), new HashCollision(1)]).map((value) => value.value), |
| 1463 | [1, 2] |
| 1464 | ) |
| 1465 | const sparse = globalThis.Array<number>(2) |
| 1466 | sparse[1] = 1 |
| 1467 | deepStrictEqual(Arr.dedupe(sparse), [undefined, 1]) |
| 1468 | deepStrictEqual(Arr.dedupe(globalThis.Array(1)), [undefined]) |
| 1469 | }) |
| 1470 | |
| 1471 | it("dedupe does not hash a single value", () => { |
| 1472 | let value: unknown = null |
| 1473 | for (let index = 0; index < 25_000; index++) { |
| 1474 | value = { value } |
| 1475 | } |
| 1476 | const result = Arr.dedupe([value]) |
| 1477 | strictEqual(result.length, 1) |
| 1478 | strictEqual(result[0], value) |
| 1479 | }) |
| 1480 | |
| 1481 | it("dedupeAdjacent", () => { |
| 1482 | deepStrictEqual(Arr.dedupeAdjacent([]), []) |
| 1483 | deepStrictEqual(Arr.dedupeAdjacent([1, 2, 3]), [1, 2, 3]) |
| 1484 | deepStrictEqual(Arr.dedupeAdjacent([1, 1, 2, 2, 3, 3]), [1, 2, 3]) |
| 1485 | deepStrictEqual(Arr.dedupeAdjacent([1, 2, 1]), [1, 2, 1]) |
| 1486 | deepStrictEqual(Arr.dedupeAdjacent([1, 1, 1]), [1]) |
| 1487 | }) |
| 1488 | |
| 1489 | it("group", () => { |
| 1490 | deepStrictEqual(Arr.group([1, 1, 2, 2, 2, 3, 1]), [[1, 1], [2, 2, 2], [3], [1]]) |
| 1491 | deepStrictEqual(Arr.group([1]), [[1]]) |
| 1492 | deepStrictEqual(Arr.group(["a", "a", "b"]), [["a", "a"], ["b"]]) |
| 1493 | }) |
| 1494 | |
| 1495 | it("union", () => { |
| 1496 | deepStrictEqual(Arr.union([1, 2], [2, 3]), [1, 2, 3]) |
| 1497 | deepStrictEqual(Arr.union([], [1, 2]), [1, 2]) |
| 1498 | deepStrictEqual(Arr.union([1, 2], []), [1, 2]) |
| 1499 | deepStrictEqual(Arr.union([], []), []) |
| 1500 | deepStrictEqual(Arr.union([1, 2], [1, 2]), [1, 2]) |
| 1501 | deepStrictEqual(pipe([1, 2], Arr.union([3, 4])), [1, 2, 3, 4]) |
| 1502 | deepStrictEqual( |
| 1503 | Arr.union( |
| 1504 | [new HashCollision(1), new HashCollision(2)], |
| 1505 | [new HashCollision(1), new HashCollision(3)] |
| 1506 | ).map((value) => value.value), |
| 1507 | [1, 2, 3] |
| 1508 | ) |
| 1509 | }) |
| 1510 | |
| 1511 | it("intersection", () => { |
| 1512 | deepStrictEqual(Arr.intersection([1, 2, 3], [3, 4, 1]), [1, 3]) |
| 1513 | deepStrictEqual(Arr.intersection([1, 2], [3, 4]), []) |
| 1514 | deepStrictEqual(Arr.intersection([1, 2], [1, 2]), [1, 2]) |
| 1515 | deepStrictEqual(Arr.intersection([], [1, 2]), []) |
| 1516 | deepStrictEqual(Arr.intersection([1, 2], []), []) |
| 1517 | deepStrictEqual(pipe([1, 2, 3], Arr.intersection([2, 3, 4])), [2, 3]) |
| 1518 | deepStrictEqual(Arr.intersection([1, 1, 2], [1]), [1, 1]) |
| 1519 | deepStrictEqual( |
| 1520 | Arr.intersection( |
| 1521 | [new HashCollision(1), new HashCollision(2)], |
| 1522 | [new HashCollision(1)] |
| 1523 | ).map((value) => value.value), |
| 1524 | [1] |
| 1525 | ) |
| 1526 | }) |
| 1527 | |
| 1528 | it("difference", () => { |
| 1529 | deepStrictEqual(Arr.difference([1, 2, 3], [2, 3, 4]), [1]) |
| 1530 | deepStrictEqual(Arr.difference([1, 2], [1, 2]), []) |
| 1531 | deepStrictEqual(Arr.difference([1, 2], []), [1, 2]) |
| 1532 | deepStrictEqual(Arr.difference([], [1, 2]), []) |
| 1533 | deepStrictEqual(pipe([1, 2, 3], Arr.difference([3])), [1, 2]) |
| 1534 | const sparse = globalThis.Array<number>(2) |
| 1535 | sparse[1] = 1 |
| 1536 | deepStrictEqual(Arr.difference(sparse, []), [1]) |
| 1537 | deepStrictEqual( |
| 1538 | Arr.difference( |
| 1539 | [new HashCollision(1), new HashCollision(2)], |
| 1540 | [new HashCollision(1)] |
| 1541 | ).map((value) => value.value), |
| 1542 | [2] |
| 1543 | ) |
| 1544 | }) |
| 1545 | |
| 1546 | it("cartesianWith", () => { |
| 1547 | deepStrictEqual( |
| 1548 | Arr.cartesianWith([1, 2], ["a", "b"], (n, s) => `${n}-${s}`), |
| 1549 | ["1-a", "1-b", "2-a", "2-b"] |
| 1550 | ) |
| 1551 | deepStrictEqual(Arr.cartesianWith([], ["a", "b"], (n: number, s) => `${n}-${s}`), []) |
| 1552 | deepStrictEqual(Arr.cartesianWith([1, 2], [], (n, s: string) => `${n}-${s}`), []) |
| 1553 | deepStrictEqual( |
| 1554 | pipe([1], Arr.cartesianWith(["x"], (n, s) => `${n}${s}`)), |
| 1555 | ["1x"] |
| 1556 | ) |
| 1557 | }) |
| 1558 | |
| 1559 | it("cartesian", () => { |
| 1560 | deepStrictEqual(Arr.cartesian([1, 2], ["a", "b"]), [ |
| 1561 | [1, "a"], |
| 1562 | [1, "b"], |
| 1563 | [2, "a"], |
| 1564 | [2, "b"] |
| 1565 | ]) |
| 1566 | deepStrictEqual(Arr.cartesian([], ["a"]), []) |
| 1567 | deepStrictEqual(Arr.cartesian([1], []), []) |
| 1568 | deepStrictEqual(Arr.cartesian([1], ["a"]), [[1, "a"]]) |
| 1569 | deepStrictEqual(pipe([1, 2], Arr.cartesian(["x"])), [[1, "x"], [2, "x"]]) |
| 1570 | }) |
| 1571 | |
| 1572 | it("makeEquivalence", () => { |
| 1573 | const eq = Arr.makeEquivalence(Equivalence.strictEqual<number>()) |
| 1574 | strictEqual(eq([], []), true) |
| 1575 | strictEqual(eq([1, 2, 3], [1, 2, 3]), true) |
| 1576 | strictEqual(eq([1, 2], [1, 2, 3]), false) |
| 1577 | strictEqual(eq([1, 2, 3], [1, 2]), false) |
| 1578 | strictEqual(eq([1, 2, 3], [1, 3, 2]), false) |
| 1579 | strictEqual(eq([1], [2]), false) |
| 1580 | }) |
| 1581 | |
| 1582 | it("getReadonlyReducerConcat", () => { |
| 1583 | const reducer = Arr.getReadonlyReducerConcat<number>() |
| 1584 | deepStrictEqual(reducer.combine([1, 2], [3, 4]), [1, 2, 3, 4]) |
| 1585 | deepStrictEqual(reducer.combine([], [1, 2]), [1, 2]) |
| 1586 | deepStrictEqual(reducer.combine([1, 2], []), [1, 2]) |
| 1587 | deepStrictEqual(reducer.initialValue, []) |
| 1588 | }) |
| 1589 | |
| 1590 | it("makeReducerConcat", () => { |
| 1591 | const reducer = Arr.makeReducerConcat<string>() |
| 1592 | deepStrictEqual(reducer.combine(["a"], ["b"]), ["a", "b"]) |
| 1593 | deepStrictEqual(reducer.initialValue, []) |
| 1594 | }) |
| 1595 | |
| 1596 | it("allocate", () => { |
| 1597 | deepStrictEqual(Arr.allocate(0).length, 0) |
| 1598 | deepStrictEqual(Arr.allocate(Number.NaN).length, 0) |
| 1599 | deepStrictEqual(Arr.allocate(-1).length, 0) |
| 1600 | deepStrictEqual(Arr.allocate(1.5).length, 1) |
| 1601 | deepStrictEqual(Arr.allocate(3).length, 3) |
| 1602 | }) |
| 1603 | |
| 1604 | describe("every - edge cases", () => { |
| 1605 | it("returns true for empty array", () => { |
| 1606 | strictEqual(Arr.every([], (_n: number) => false), true) |
| 1607 | }) |
| 1608 | it("with index", () => { |
| 1609 | strictEqual(Arr.every([0, 1, 2], (n, i) => n === i), true) |
| 1610 | strictEqual(Arr.every([0, 1, 3], (n, i) => n === i), false) |
| 1611 | }) |
| 1612 | }) |
| 1613 | |
| 1614 | describe("some - edge cases", () => { |
| 1615 | it("returns false for empty array", () => { |
| 1616 | strictEqual(Arr.some([], (_n: number) => true), false) |
| 1617 | }) |
| 1618 | it("with index", () => { |
| 1619 | strictEqual(Arr.some([10, 20, 2], (n, i) => n === i), true) |
| 1620 | strictEqual(Arr.some([10, 20, 30], (n, i) => n === i), false) |
| 1621 | }) |
| 1622 | }) |
| 1623 | |
| 1624 | describe("copy - edge cases", () => { |
| 1625 | it("returns a new reference", () => { |
| 1626 | const original = [1, 2, 3] |
| 1627 | const copied = Arr.copy(original) |
| 1628 | deepStrictEqual(copied, original) |
| 1629 | strictEqual(copied !== original, true) |
| 1630 | }) |
| 1631 | }) |
| 1632 | |
| 1633 | describe("unfold - edge cases", () => { |
| 1634 | it("returns empty when seed produces Option.none", () => { |
| 1635 | deepStrictEqual(Arr.unfold(0, () => Option.none()), []) |
| 1636 | }) |
| 1637 | }) |
| 1638 | |
| 1639 | it("bindTo", () => { |
| 1640 | deepStrictEqual(pipe([1, 2, 3], Arr.bindTo("a")), [{ a: 1 }, { a: 2 }, { a: 3 }]) |
| 1641 | deepStrictEqual(pipe([], Arr.bindTo("a")), []) |
| 1642 | deepStrictEqual(Arr.bindTo([1], "x"), [{ x: 1 }]) |
| 1643 | }) |
| 1644 | |
| 1645 | it("Do notation", () => { |
| 1646 | const _do = Arr.Do |
| 1647 | deepStrictEqual(_do, Arr.of({})) |
| 1648 | |
| 1649 | const doA = Arr.bind(_do, "a", () => ["a"]) |
| 1650 | deepStrictEqual(doA, Arr.of({ a: "a" })) |
| 1651 | |
| 1652 | const doAB = Arr.bind(doA, "b", (x) => ["b", x.a + "b"]) |
| 1653 | deepStrictEqual(doAB, [ |
| 1654 | { a: "a", b: "b" }, |
| 1655 | { a: "a", b: "ab" } |
| 1656 | ]) |
| 1657 | const doABC = Arr.let(doAB, "c", (x) => [x.a, x.b, x.a + x.b]) |
| 1658 | deepStrictEqual(doABC, [ |
| 1659 | { a: "a", b: "b", c: ["a", "b", "ab"] }, |
| 1660 | { a: "a", b: "ab", c: ["a", "ab", "aab"] } |
| 1661 | ]) |
| 1662 | |
| 1663 | const doABCD = Arr.bind(doABC, "d", () => Arr.empty()) |
| 1664 | deepStrictEqual(doABCD, []) |
| 1665 | |
| 1666 | const doAB__proto__C = pipe( |
| 1667 | Arr.let(doAB, "__proto__", (x) => [x.a, x.b, x.a + x.b]), |
| 1668 | Arr.let("c", (x) => [x.a, x.b, x.a + x.b]) |
| 1669 | ) |
| 1670 | deepStrictEqual(doAB__proto__C, [ |
| 1671 | { a: "a", b: "b", c: ["a", "b", "ab"], ["__proto__"]: ["a", "b", "ab"] }, |
| 1672 | { a: "a", b: "ab", c: ["a", "ab", "aab"], ["__proto__"]: ["a", "ab", "aab"] } |
| 1673 | ]) |
| 1674 | }) |
| 1675 | }) |