-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(v2): reduceLazy -> purryFromLazy, +takeLast, lazy zip, built-in …
…flat, and more... (#672) Following re-reading the codebase before releasing v2, I went over a few more things I wanted to change: * `take` and `drop` shouldn't use reduceLazy. * `drop` can optimize the trivial lazy case * `flat` uses the built-in flat. * `zipWith` was funky, now less funky, and lazy. * lazy `zip` * optimize lazy `first`. * Add takeLast * Don't use copy-and-splice where slice makes sense (`takeLast`, `dropLast`, `splitAt`). * don't use internal versions where a simple JS check is enough (`isEmpty`) * Update migration docs for `mapToObj` * bump ts minimum version. * Remove `reduceLazy`. It was reimplementing parts of `pipe`'s logic; instead, now, we rely on the way pipe handles lazy and build the rest of the APIs (dataFirst, dataLast) from it.
- Loading branch information
1 parent
2446135
commit ac35885
Showing
48 changed files
with
717 additions
and
477 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Typing | ||
|
||
The `indexed` variant was removed; the base implementation takes the same | ||
parameters. If you are using `indexed` you can simply remove it without any | ||
other changes. | ||
|
||
# Runtime | ||
|
||
The mapper now takes 2 additional parameters: `index` - The index of the current | ||
element being processed in array, and `data` - the array the function was called | ||
upon (the same signature the callbacks the built-in `Array.prototype` functions | ||
have). | ||
|
||
If you are using a function reference for the mapper (and not an inline arrow | ||
function), and that function accepts more than one param you might run into | ||
compile-time (or run-time!) issues because of the extra params being sent on | ||
each invocation of the function. We highly recommend using [unicorn/no-array-callback-reference](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-callback-reference.md) | ||
to warn against these issues. | ||
|
||
## Examples | ||
|
||
### Indexed variant removed | ||
|
||
```ts | ||
// Was | ||
mapToObj.indexed(array, mapper); | ||
|
||
// Now | ||
mapToObj(array, mapper); | ||
``` | ||
|
||
### Potential bug | ||
|
||
```ts | ||
function callback(key: string, index = 0) { | ||
return [key, index]; | ||
} | ||
|
||
// Bug | ||
mapToObj(["a", "b", "c"], callback); // => { a: 0, b: 1, c: 2 }, Was: { a: 0, b: 0, c: 0 } | ||
|
||
// Fix | ||
mapToObj(["a", "b", "c"], (item) => callback(item)); // => { a: 0, b: 0, c: 0 } | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,56 @@ | ||
import { createLazyInvocationCounter } from "../test/lazyInvocationCounter"; | ||
import { drop } from "./drop"; | ||
import { identity } from "./identity"; | ||
import { map } from "./map"; | ||
import { pipe } from "./pipe"; | ||
import { take } from "./take"; | ||
|
||
const array = [1, 2, 3, 4, 5] as const; | ||
const expected = [3, 4, 5]; | ||
describe("runtime", () => { | ||
describe("data first", () => { | ||
it("works on regular inputs", () => { | ||
expect(drop([1, 2, 3, 4, 5], 2)).toStrictEqual([3, 4, 5]); | ||
}); | ||
|
||
describe("data first", () => { | ||
test("should drop", () => { | ||
expect(drop(array, 2)).toEqual(expected); | ||
}); | ||
it("works trivially on empty arrays", () => { | ||
expect(drop([], 2)).toStrictEqual([]); | ||
}); | ||
|
||
test("should not drop", () => { | ||
expect(drop(array, 0)).toEqual(array); | ||
expect(drop(array, -0)).toEqual(array); | ||
expect(drop(array, -1)).toEqual(array); | ||
expect(drop(array, Number.NaN)).toEqual(array); | ||
}); | ||
it("works trivially with negative numbers", () => { | ||
expect(drop([1, 2, 3, 4, 5], -1)).toStrictEqual([1, 2, 3, 4, 5]); | ||
}); | ||
|
||
test("should return a new array even if there was no drop", () => { | ||
expect(drop(array, 0)).not.toBe(array); | ||
}); | ||
}); | ||
it("works when dropping more than the length of the array", () => { | ||
expect(drop([1, 2, 3, 4, 5], 10)).toStrictEqual([]); | ||
}); | ||
|
||
describe("data last", () => { | ||
test("drop", () => { | ||
const result = pipe(array, drop(2)); | ||
expect(result).toEqual(expected); | ||
test("returns a shallow clone when no items are dropped", () => { | ||
const data = [1, 2, 3, 4, 5]; | ||
const result = drop(data, 0); | ||
expect(result).toStrictEqual([1, 2, 3, 4, 5]); | ||
expect(result).not.toBe(data); | ||
}); | ||
}); | ||
test("drop with take", () => { | ||
const counter = createLazyInvocationCounter(); | ||
const result = pipe(array, counter.fn(), drop(2), take(2)); | ||
expect(counter.count).toHaveBeenCalledTimes(4); | ||
expect(result).toEqual([3, 4]); | ||
|
||
describe("data last", () => { | ||
it("works on regular inputs", () => { | ||
expect(pipe([1, 2, 3, 4, 5], drop(2))).toStrictEqual([3, 4, 5]); | ||
}); | ||
|
||
it("works trivially on empty arrays", () => { | ||
expect(pipe([], drop(2))).toStrictEqual([]); | ||
}); | ||
|
||
it("works trivially with negative numbers", () => { | ||
expect(pipe([1, 2, 3, 4, 5], drop(-1))).toStrictEqual([1, 2, 3, 4, 5]); | ||
}); | ||
|
||
it("works when dropping more than the length of the array", () => { | ||
expect(pipe([1, 2, 3, 4, 5], drop(10))).toStrictEqual([]); | ||
}); | ||
|
||
test("lazy impl", () => { | ||
const mockFunc = vi.fn(identity()); | ||
pipe([1, 2, 3, 4, 5], map(mockFunc), drop(2), take(2)); | ||
expect(mockFunc).toHaveBeenCalledTimes(4); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.