Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc (collections): Add contribtution guide, some principles and extend README #1110

Merged
merged 6 commits into from
Aug 10, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Formatting
  • Loading branch information
LionC committed Aug 8, 2021
commit 854b227fc4712d66ee0cd9af2e842dd7d1b01949
39 changes: 24 additions & 15 deletions collections/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
# Contribution Guide

First, thank you for being interested in contributing! We hope this page helps as a guide. When in doubt, look at the files
in this folder, read through issues and PRs regarding the `collections` module or visit the
First, thank you for being interested in contributing! We hope this page helps
as a guide. When in doubt, look at the files in this folder, read through issues
and PRs regarding the `collections` module or visit the
[#deno-std channel on our Discord](https://discord.gg/Ub9bRxHv) and ask.

## Philosophy

Currently, those are the general ideas behind how the module is implemented:

- Provide a clear, specific toolbox and vocabulary for common tasks with `Array`s and `Record`s
- Provide a clear, specific toolbox and vocabulary for common tasks with
`Array`s and `Record`s
- Optimize each specific tasks for maximum runtime and memory efficiency
- Offer only pure functions, never mutate given arguments, always return a new value
- Accept and return `Array`s and `Record`s - we are optimizing for the most common use cases and
leave more general approaches to the [ES iterator helpers proposal](https://github.com/tc39/proposal-iterator-helpers)
for now
- Some implementations for common tasks are pretty trivial - this is fine. It still provides a readable vocabulary to
express a common task, is as optimized as possible and helps newcomers. Be aware that it might not be everyones style
to use small functions and we do not want to change that, just offer a way to do so if desired
- Offer only pure functions, never mutate given arguments, always return a new
value
- Accept and return `Array`s and `Record`s - we are optimizing for the most
common use cases and leave more general approaches to the
[ES iterator helpers proposal](https://github.com/tc39/proposal-iterator-helpers)
for now
- Some implementations for common tasks are pretty trivial - this is fine. It
still provides a readable vocabulary to express a common task, is as optimized
as possible and helps newcomers. Be aware that it might not be everyones style
to use small functions and we do not want to change that, just offer a way to
do so if desired
- All functions can be imported in isolation to reduce bundle size if important
- All functions are implemented in Typescript

## Contribution Checklist

If you want to post a PR, this checklis might help you to speed up the process by solving most common review comments upfront.
If you want to post a PR, this checklis might help you to speed up the process
by solving most common review comments upfront.

- Did you support importing from `mod.ts` as well as your functions file?
- Have you made sure to allocate as little memory and do as little steps in your algorithm as possible?
- Did you add/adapt JSDoc comments, add/adapt an example, made sure that the example uses the `ts` markdown tag and `assertEquals` to show the result?
- Have you made sure to allocate as little memory and do as little steps in your
algorithm as possible?
- Did you add/adapt JSDoc comments, add/adapt an example, made sure that the
example uses the `ts` markdown tag and `assertEquals` to show the result?
- Did you add/adapt your functions documentation in `README.md`?
- Did you make sure **not** to mutate the arguments passe to your function?
- Did you add tests ensuring no mutation, empty input and corner cases?
- Are your types flat, meaning there is no unnecessary alias in them that makes your users "go to type definition" twice
to understand what to pass?
- Are your types flat, meaning there is no unnecessary alias in them that makes
your users "go to type definition" twice to understand what to pass?
110 changes: 59 additions & 51 deletions collections/README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
# std/collections

This module includes pure functions for specific common tasks around collection types
like `Array` and `Record`. This module is heavily inspired by `kotlin`s stdlib.
This module includes pure functions for specific common tasks around collection
types like `Array` and `Record`. This module is heavily inspired by `kotlin`s
stdlib.

- All provided functions are **pure**, which also means that hey do **not mutate** your inputs,
**returning a new value** instead.
- All functions are importable on their own by referencing their snake_case named file (e.g. `collections/sort_by.ts`)
- All provided functions are **pure**, which also means that hey do **not
mutate** your inputs, **returning a new value** instead.
- All functions are importable on their own by referencing their snake_case
named file (e.g. `collections/sort_by.ts`)

If you want to contribute or undestand why this is done the way it is, see the [contribution guide](CONTRIBUTING.md).
If you want to contribute or undestand why this is done the way it is, see the
[contribution guide](CONTRIBUTING.md).

## Usage

### associateBy

Transforms the given array into a Record, extracting the key of each element using the given selector.
If the selector produces the same key for multiple elements, the latest one will be used (overriding the
ones before it).
Transforms the given array into a Record, extracting the key of each element
using the given selector. If the selector produces the same key for multiple
elements, the latest one will be used (overriding the ones before it).

```ts
const users = [
{ id: 'a2e', userName: 'Anna' },
{ id: '5f8', userName: 'Arnold' },
{ id: 'd2c', userName: 'Kim' },
{ id: "a2e", userName: "Anna" },
{ id: "5f8", userName: "Arnold" },
{ id: "d2c", userName: "Kim" },
];
const usersById = associateBy(users, (it) => it.id);

assertEquals(usersById, {
'a2e': { id: 'a2e', userName: 'Anna' },
'5f8': { id: '5f8', userName: 'Arnold' },
'd2c': { id: 'd2c', userName: 'Kim' },
"a2e": { id: "a2e", userName: "Anna" },
"5f8": { id: "5f8", userName: "Arnold" },
"d2c": { id: "d2c", userName: "Kim" },
});
```


### chunked

Splits the given array into chunks of the given size and returns them.
Expand Down Expand Up @@ -267,19 +269,20 @@ console.assert(

### mapNotNullish

Returns a new array, containing all elements in the given array transformed using the given transformer, except the ones
that were transformed to `null` or `undefined`.
Returns a new array, containing all elements in the given array transformed
using the given transformer, except the ones that were transformed to `null` or
`undefined`.

```typescript
const people = [
{ middleName: null },
{ middleName: 'William' },
{ middleName: undefined },
{ middleName: 'Martha' },
{ middleName: null },
{ middleName: "William" },
{ middleName: undefined },
{ middleName: "Martha" },
];
const foundMiddleNames = mapNotNullish(people, (it) => it.middleName);

assertEquals(foundMiddleNames, [ 'William', 'Martha' ]);
assertEquals(foundMiddleNames, ["William", "Martha"]);
```

### mapValues
Expand Down Expand Up @@ -337,20 +340,21 @@ console.assert(

### sortBy

Returns all elements in the given collection, sorted by their result using the given selector

Returns all elements in the given collection, sorted by their result using the
given selector

```ts
const people = [
{ name: 'Anna', age: 34 },
{ name: 'Kim', age: 42 },
{ name: 'John', age: 23 },
{ name: "Anna", age: 34 },
{ name: "Kim", age: 42 },
{ name: "John", age: 23 },
];
const sortedByAge = sortBy(people, (it) => it.age);

assertEquals(sortedByAge, [
{ name: 'John', age: 23 },
{ name: 'Anna', age: 34 },
{ name: 'Kim', age: 42 },
{ name: "John", age: 23 },
{ name: "Anna", age: 34 },
{ name: "Kim", age: 42 },
]);
```

Expand All @@ -359,44 +363,48 @@ assertEquals(sortedByAge, [
Returns all distinct elements that appear in any of the given arrays

```ts
const soupIngredients = [ 'Pepper', 'Carrots', 'Leek' ];
const saladIngredients = [ 'Carrots', 'Radicchio', 'Pepper' ];
const soupIngredients = ["Pepper", "Carrots", "Leek"];
const saladIngredients = ["Carrots", "Radicchio", "Pepper"];
const shoppingList = union(soupIngredients, saladIngredients);

assertEquals(shoppingList, [ 'Pepper', 'Carrots', 'Leek', 'Radicchio' ]);
assertEquals(shoppingList, ["Pepper", "Carrots", "Leek", "Radicchio"]);
```

### unzip

Builds two separate arrays from the given array of 2-tuples, with the first returned array holding all first
tuple elements and the second one holding all the second elements
Builds two separate arrays from the given array of 2-tuples, with the first
returned array holding all first tuple elements and the second one holding all
the second elements

```ts
const parents = [
[ 'Maria', 'Jeff' ],
[ 'Anna', 'Kim' ],
[ 'John', 'Leroy' ],
["Maria", "Jeff"],
["Anna", "Kim"],
["John", "Leroy"],
] as [string, string][];

const [ moms, dads ] = unzip(parents);
const [moms, dads] = unzip(parents);

assertEquals(moms, [ 'Maria', 'Anna', 'John' ]);
assertEquals(moms, [ 'Jeff', 'Kim', 'Leroy' ]);
assertEquals(moms, ["Maria", "Anna", "John"]);
assertEquals(moms, ["Jeff", "Kim", "Leroy"]);
```

### zip

Builds 2-tuples of elements from the given array with matching indices, stopping when the smaller array's end is reached
Builds 2-tuples of elements from the given array with matching indices, stopping
when the smaller array's end is reached

```ts
const numbers = [ 1, 2, 3, 4 ];
const letters = [ 'a', 'b', 'c', 'd' ];
const numbers = [1, 2, 3, 4];
const letters = ["a", "b", "c", "d"];
const pairs = zip(numbers, letters);

console.assert(pairs === [
[ 1, 'a' ],
[ 2, 'b' ],
[ 3, 'c' ],
[ 4, 'd' ],
]);
console.assert(
pairs === [
[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"],
],
);
```