Repository: dubzzz/fast-check
Pull request #1742 (2021-04-14 19:55:57)

♻️ Simplify internal implementation of `memo`
<!-- Why is this PR for? -->
<!-- Describe the reason why you opened this PR or give a link towards the associated issue. -->

## In a nutshell

❌ New feature
❌ Fix an issue
❌ Documentation improvement
✔️ Other: *refactor*

(✔️: yes, ❌: no)

## Potential impacts

Nothing expected


codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/1742/builds/119788) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit f0808ab18e84d77c671274dce6b47c5a80db00ef:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-x66sn)| Configuration |
|[fast-check-examples](https://codesandbox.io/s/fast-check-examples-2zh3g)| Configuration |

codecov[bot]: # [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) Report
> Merging [#1742](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (f0808ab) into [main](https://codecov.io/gh/dubzzz/fast-check/commit/57d5489fb625b3b9664bea7e28c0e31ea997e73d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (57d5489) will **decrease** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/dubzzz/fast-check/pull/1742/graphs/tree.svg?width=650&height=150&src=pr&token=fRi2fJN730&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)

```diff
@@            Coverage Diff             @@
##             main    #1742      +/-   ##
==========================================
- Coverage   97.08%   97.07%   -0.01%     
==========================================
  Files         111      111              
  Lines        3600     3589      -11     
  Branches      713      713              
==========================================
- Hits         3495     3484      -11     
  Misses        101      101              
  Partials        4        4              
```

| Flag | Coverage Δ | |
|---|---|---|
| unit-tests | `97.07% <100.00%> (-0.01%)` | :arrow_down: |
| unit-tests-10.x-Linux | `?` | |
| unit-tests-12.x-Linux | `97.07% <100.00%> (-0.01%)` | :arrow_down: |
| unit-tests-14.x-Linux | `97.07% <100.00%> (-0.01%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) | Coverage Δ | |
|---|---|---|
| [src/check/arbitrary/MemoArbitrary.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1742/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#diff-c3JjL2NoZWNrL2FyYml0cmFyeS9NZW1vQXJiaXRyYXJ5LnRz) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Last update [57d5489...f0808ab](https://codecov.io/gh/dubzzz/fast-check/pull/1742?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).


Patch:
diff --git a/src/check/arbitrary/MemoArbitrary.ts b/src/check/arbitrary/MemoArbitrary.ts
index 1abc83b9..547694d4 100644
--- a/src/check/arbitrary/MemoArbitrary.ts
+++ b/src/check/arbitrary/MemoArbitrary.ts
@@ -1,25 +1,4 @@
-import { Stream } from '../../fast-check-default';
-import { Random } from '../../random/generator/Random';
 import { Arbitrary } from './definition/Arbitrary';
-import { convertFromNext, convertToNext } from './definition/Converters';
-import { NextArbitrary } from './definition/NextArbitrary';
-import { NextValue } from './definition/NextValue';
-
-/** @internal */
-export class MemoArbitrary<T> extends NextArbitrary<T> {
-  constructor(readonly underlying: NextArbitrary<T>) {
-    super();
-  }
-  generate(mrng: Random, biasFactor: number | undefined): NextValue<T> {
-    return this.underlying.generate(mrng, biasFactor);
-  }
-  canGenerate(value: unknown): value is T {
-    return this.underlying.canGenerate(value);
-  }
-  shrink(value: T, context?: unknown): Stream<NextValue<T>> {
-    return this.underlying.shrink(value, context);
-  }
-}
 
 /**
  * Output type for {@link memo}
@@ -57,7 +36,7 @@ export function memo<T>(builder: (maxDepth: number) => Arbitrary<T>): Memo<T> {
     if (!Object.prototype.hasOwnProperty.call(previous, n)) {
       const prev = contextRemainingDepth;
       contextRemainingDepth = n - 1;
-      previous[n] = convertFromNext(new MemoArbitrary(convertToNext(builder(n))));
+      previous[n] = builder(n);
       contextRemainingDepth = prev;
     }
     return previous[n];


Test patch:
diff --git a/test/unit/check/arbitrary/MemoArbitrary.utest.spec.ts b/test/unit/check/arbitrary/MemoArbitrary.utest.spec.ts
index 315c3488..4a48db57 100644
--- a/test/unit/check/arbitrary/MemoArbitrary.utest.spec.ts
+++ b/test/unit/check/arbitrary/MemoArbitrary.utest.spec.ts
@@ -1,8 +1,6 @@
-import { MemoArbitrary, memo as memoOld } from '../../../../src/check/arbitrary/MemoArbitrary';
+import { memo as memoOld } from '../../../../src/check/arbitrary/MemoArbitrary';
 import { NextArbitrary } from '../../../../src/check/arbitrary/definition/NextArbitrary';
 import { convertFromNext, convertToNext } from '../../../../src/check/arbitrary/definition/Converters';
-import { NextValue } from '../../../../src/check/arbitrary/definition/NextValue';
-import { Stream } from '../../../../src/stream/Stream';
 
 import { fakeNextArbitrary } from './generic/NextArbitraryHelpers';
 import * as stubRng from '../../stubs/generators';
@@ -17,7 +15,7 @@ function memo<T>(builder: (maxDepth: number) => NextArbitrary<T>): NextMemo<T> {
 
 describe('memo', () => {
   describe('builder', () => {
-    it('should wrap the arbitrary into a MemoArbitrary', () => {
+    it('should return the produced instance of arbitrary', () => {
       // Arrange
       const { instance: expectedArb } = fakeNextArbitrary();
       const builder = memo(() => expectedArb);
@@ -26,14 +24,12 @@ describe('memo', () => {
       const arb = builder();
 
       // Assert
-      expect(arb).toBeInstanceOf(MemoArbitrary);
-      expect(((arb as any) as MemoArbitrary<any>).underlying).toBe(expectedArb);
+      expect(arb).toBe(expectedArb);
     });
 
     it('should cache arbitraries associated to each depth', () => {
       // Arrange
-      const { instance: expectedArb } = fakeNextArbitrary();
-      const builder = memo(() => expectedArb);
+      const builder = memo(() => fakeNextArbitrary().instance);
 
       // Act
       const arb = builder();
@@ -47,8 +43,7 @@ describe('memo', () => {
 
     it('should instantiate new arbitraries for each depth', () => {
       // Arrange
-      const { instance: expectedArb } = fakeNextArbitrary();
-      const builder = memo(() => expectedArb);
+      const builder = memo(() => fakeNextArbitrary().instance);
 
       // Act
       const b10 = builder(10);
@@ -60,8 +55,7 @@ describe('memo', () => {
 
     it('should consider no depth as depth 10', () => {
       // Arrange
-      const { instance: expectedArb } = fakeNextArbitrary();
-      const builder = memo(() => expectedArb);
+      const builder = memo(() => fakeNextArbitrary().instance);
 
       // Act
       const bDefault = builder();
@@ -136,62 +130,4 @@ describe('memo', () => {
       expect(generate).toHaveBeenCalledWith(mrngNoCall, expectedBiasedFactor);
     });
   });
-
-  describe('generate', () => {
-    it('should call generate method of underlying on generate', () => {
-      // Arrange
-      const expectedBiasedFactor = 2;
-      const expectedGen = Symbol();
-      const expectedNextValue = new NextValue(expectedGen);
-      const { instance: arb, generate } = fakeNextArbitrary();
-      generate.mockReturnValue(expectedNextValue);
-
-      // Act
-      const memoArb = new MemoArbitrary(arb);
-      const g = memoArb.generate(mrngNoCall, expectedBiasedFactor);
-
-      // Assert
-      expect(g).toBe(expectedNextValue);
-      expect(generate).toHaveBeenCalledTimes(1);
-      expect(generate).toHaveBeenCalledWith(mrngNoCall, expectedBiasedFactor);
-    });
-  });
-
-  describe('canGenerate', () => {
-    it('should call canGenerate method of underlying on canGenerate', () => {
-      // Arrange
-      const expectedValue = Symbol();
-      const { instance: arb, canGenerate } = fakeNextArbitrary();
-      canGenerate.mockReturnValue(true);
-
-      // Act
-      const memoArb = new MemoArbitrary(arb);
-      const out = memoArb.canGenerate(expectedValue);
-
-      // Assert
-      expect(out).toBe(true);
-      expect(canGenerate).toHaveBeenCalledTimes(1);
-      expect(canGenerate).toHaveBeenCalledWith(expectedValue);
-    });
-  });
-
-  describe('shrink', () => {
-    it('should call shrink method of underlying on shrink', () => {
-      // Arrange
-      const expectedValue = Symbol();
-      const expectedContext = Symbol();
-      const expectedShrinks = Stream.of(new NextValue(Symbol()));
-      const { instance: arb, shrink } = fakeNextArbitrary();
-      shrink.mockReturnValue(expectedShrinks);
-
-      // Act
-      const memoArb = new MemoArbitrary(arb);
-      const out = memoArb.shrink(expectedValue, expectedContext);
-
-      // Assert
-      expect(out).toBe(expectedShrinks);
-      expect(shrink).toHaveBeenCalledTimes(1);
-      expect(shrink).toHaveBeenCalledWith(expectedValue, expectedContext);
-    });
-  });
 });