Skip to content
This repository was archived by the owner on May 31, 2022. It is now read-only.

Commit e854613

Browse files
author
Tomasz Gałkowski
authored
adds lens function (#61)
* adds lens function * use v0.42.0 std temporarily
1 parent 7cef4b1 commit e854613

File tree

8 files changed

+174
-2
lines changed

8 files changed

+174
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- adds lens function
12+
1013
## [0.3.0] - 2020-05-14
1114

1215
### Added
@@ -90,7 +93,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9093
- reverse function
9194
- tail function
9295

93-
[unreleased]: https://github.com/galkowskit/denofun/compare/0.3.0...HEAD
96+
[Unreleased]: https://github.com/galkowskit/denofun/compare/0.3.0...HEAD
9497
[0.3.0]: https://github.com/galkowskit/denofun/compare/v0.2.0...0.3.0
9598
[v0.2.0]: https://github.com/galkowskit/denofun/compare/v0.1.0...v0.2.0
9699
[v0.1.0]: https://github.com/galkowskit/denofun/releases/tag/v0.1.0

README.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,24 @@ last([1, "test", 3]); // => 3
441441
last("hello world!"); // => "!"
442442
```
443443

444+
### lens
445+
446+
**lens** lens returns a special lens object that can be used as a function setter/getter.
447+
448+
```typescript
449+
import lens from "https://deno.land/x/denofun/lens.ts";
450+
451+
const car = Object.freeze({
452+
make: "Toyota",
453+
model: "GT86",
454+
});
455+
456+
const getCarModel = (data: { make: string, model: string }) => data.model;
457+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
458+
459+
const carModelLens = lens(getCarModel, setCarModel); // => Lens<Car, string>
460+
```
461+
444462
### map
445463

446464
**map** applies a function to each element of the array, returns the array of results.
@@ -602,7 +620,29 @@ reverse([1, 2, 3, 4, 5]); // => [5, 4, 3, 2, 1]
602620
reverse("hello world!"); // => ["!dlrow olleh"]
603621
```
604622

605-
**slice** return a given slice of an array or string (wrapper over Array.prototype.slice)
623+
### set
624+
625+
**set** uses a provided lens, copies the provided object with a changed value.
626+
627+
```typescript
628+
import lens from "https://deno.land/x/denofun/lens.ts";
629+
import set from "https://deno.land/x/denofun/set.ts";
630+
631+
const car = Object.freeze({
632+
make: "Toyota",
633+
model: "GT86",
634+
});
635+
636+
const getCarModel = (data: { make: string, model: string }) => data.model;
637+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
638+
639+
const carModelLens = lens(getCarModel, setCarModel);
640+
set(carModelLens, car, "Mirai"); // => { make: "Toyota", model: "Mirai" }
641+
```
642+
643+
### slice
644+
645+
**slice** return a given slice of an array or string (wrapper over Array.prototype.slice).
606646

607647
```typescript
608648
import slice from "https://deno.land/x/denofun/slice.ts";
@@ -676,6 +716,26 @@ const car = { make: "Alfa Romeo", model: "Giulia" };
676716
values(car); // => ["make", "model"]
677717
```
678718

719+
### view
720+
721+
**view** uses a lens to get value from an object.
722+
723+
```typescript
724+
import lens from "https://deno.land/x/denofun/lens.ts";
725+
import view from "https://deno.land/x/denofun/view.ts";
726+
727+
const car = Object.freeze({
728+
make: "Toyota",
729+
model: "GT86",
730+
});
731+
732+
const getCarModel = (data: { make: string, model: string }) => data.model;
733+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
734+
735+
const carModelLens = lens(getCarModel, setCarModel);
736+
view(carModelLens, car); // => "GT86"
737+
```
738+
679739
## For Developers
680740

681741
If you want to contribute to Denofun:

lib/lens.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export type Lens<T, V> = {
2+
getter: (data: T) => V;
3+
setter: (data: T, value: V) => T;
4+
};
5+
6+
/**
7+
* **lens** lens returns a special lens object that can be used as a function setter/getter
8+
* @param getterFn
9+
* @param setterFn
10+
*/
11+
export default function lens<T, V>(
12+
getterFn: (data: T) => V,
13+
setterFn: (data: T, value: V) => T,
14+
): Lens<T, V> {
15+
return {
16+
getter: getterFn,
17+
setter: setterFn,
18+
};
19+
}

lib/set.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Lens } from "./lens.ts";
2+
3+
/**
4+
* **set** uses a provided lens, copies the provided object with a changed value
5+
* @param lens {Lens} the lens that will be used
6+
* @param obj the object to be copied with the changed data
7+
* @param value the value to be used by the lens
8+
*/
9+
export default function set<T, V>(lens: Lens<T,V>, obj: T, value: V): T {
10+
return lens.setter(obj, value);
11+
}

lib/view.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Lens } from "../lib/lens.ts";
2+
3+
/**
4+
* **view** uses a lens to get value from an object
5+
* @param lens {Lens} a lens created by _lens_ function
6+
* @param obj data from which to get the value
7+
*/
8+
export default function view<T, V>(lens: Lens<T, V>, obj: T): V {
9+
return lens.getter(obj);
10+
}

test/lens_test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { assertEquals } from "https://deno.land/std@v0.42.0/testing/asserts.ts";
2+
3+
import lens from "../lib/lens.ts";
4+
5+
const car = Object.freeze({
6+
make: "Toyota",
7+
model: "GT86",
8+
});
9+
10+
const getCarModel = (data: { make: string, model: string }) => data.model;
11+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
12+
13+
const carModelLens = lens(getCarModel, setCarModel);
14+
15+
Deno.test({
16+
name: "lens",
17+
fn(): void {
18+
assertEquals(typeof lens, "function");
19+
assertEquals(typeof carModelLens, "object");
20+
assertEquals(typeof carModelLens.getter, "function");
21+
assertEquals(typeof carModelLens.setter, "function");
22+
assertEquals(carModelLens.getter(car), "GT86");
23+
assertEquals(carModelLens.setter(car, "Mirai"), { make: "Toyota", model: "Mirai" });
24+
},
25+
});

test/set_test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { assertEquals } from "https://deno.land/std@v0.42.0/testing/asserts.ts";
2+
3+
import lens from "../lib/lens.ts";
4+
import set from "../lib/set.ts";
5+
6+
const car = Object.freeze({
7+
make: "Toyota",
8+
model: "GT86",
9+
});
10+
11+
const getCarModel = (data: { make: string, model: string }) => data.model;
12+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
13+
14+
const carModelLens = lens(getCarModel, setCarModel);
15+
16+
Deno.test({
17+
name: "set",
18+
fn(): void {
19+
assertEquals(typeof set, "function");
20+
assertEquals(set(carModelLens, car, "Mirai"), { make: "Toyota", model: "Mirai" });
21+
},
22+
});

test/view_test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { assertEquals } from "https://deno.land/std@v0.42.0/testing/asserts.ts";
2+
3+
import lens from "../lib/lens.ts";
4+
import view from "../lib/view.ts";
5+
6+
const car = Object.freeze({
7+
make: "Toyota",
8+
model: "GT86",
9+
});
10+
11+
const getCarModel = (data: { make: string, model: string }) => data.model;
12+
const setCarModel = (data: { make: string, model: string }, value: string) => ({ ...data, model: value });
13+
14+
const carModelLens = lens(getCarModel, setCarModel);
15+
16+
Deno.test({
17+
name: "view",
18+
fn(): void {
19+
assertEquals(typeof view, "function");
20+
assertEquals(view(carModelLens, car), "GT86");
21+
},
22+
});

0 commit comments

Comments
 (0)