Skip to content

Commit f56fa23

Browse files
committed
P1.*memo: avoid uncessary wrapping of F0 value into a P1.lazy when possible. Expose static factories in P for this.
Deprecated redondant API.
1 parent e723d71 commit f56fa23

12 files changed

Lines changed: 119 additions & 66 deletions

File tree

core/src/main/java/fj/P.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,45 @@ public static <A> P1<A> p(final A a) {
3838
};
3939
}
4040

41+
/**
42+
* Convert a F0 into a P1, using call-by-need semantic:
43+
* function f is evaluated at most once, at first to {@link P1#_1()}.
44+
*/
45+
public static <A> P1<A> hardMemo(F0<A> f) {
46+
return new P1.Memo<>(f);
47+
}
4148

42-
public static <A> P1<A> lazy(final P1<A> pa) {
43-
return pa;
44-
}
49+
/**
50+
* Convert a F0 into a P1, using weak call-by-need semantic:
51+
* function f is evaluated at first call to {@link P1#_1()}
52+
* and at each subsequent call if and only if the reference have been garbage collected.
53+
*/
54+
public static <A> P1<A> weakMemo(F0<A> f) {
55+
return new P1.WeakReferenceMemo<>(f);
56+
}
57+
58+
/**
59+
* Convert a F0 into a P1, using soft call-by-need semantic:
60+
* function f is evaluated at first call to {@link P1#_1()}
61+
* and at each subsequent call if and only if the reference have been garbage collected
62+
* due of shortage of memory (ie. to avoid OutOfMemoryErrors).
63+
*/
64+
public static <A> P1<A> sofMemo(F0<A> f) {
65+
return new P1.SoftReferenceMemo<>(f);
66+
}
67+
68+
/**
69+
* Convert a F0 into a P1, using call-by-name semantic:
70+
* function f is evaluated at each call to {@link P1#_1()}.
71+
*/
72+
public static <A> P1<A> lazy(F0<A> f) {
73+
return new P1<A>() {
74+
@Override
75+
public A _1() {
76+
return f.f();
77+
}
78+
};
79+
}
4580

4681
public static <A, B> P2<A, B> lazy(final F0<A> pa, final F0<B> pb) {
4782
return new P2<A, B>() {
@@ -538,15 +573,6 @@ public H _8() {
538573
};
539574
}
540575

541-
public static <A> P1<A> lazy(F0<A> f) {
542-
return new P1<A>() {
543-
@Override
544-
public A _1() {
545-
return f.f();
546-
}
547-
};
548-
}
549-
550576
public static <A> P1<A> lazy(F<Unit, A> f) {
551577
return lazy(() -> f.f(unit()));
552578
}

core/src/main/java/fj/P1.java

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.lang.ref.WeakReference;
1313

1414
import static fj.P.p;
15+
import static fj.Unit.unit;
1516
//import fj.data.*;
1617

1718

@@ -240,6 +241,10 @@ public final <B> P1<B> map(final F<A, B> f) {
240241
return P.lazy(() -> f.f(self._1()));
241242
}
242243

244+
/**
245+
* @deprecated since 4.7. Use {@link P1#weakMemo()} instead.
246+
*/
247+
@Deprecated
243248
public final P1<A> memo() {
244249
return weakMemo();
245250
}
@@ -261,29 +266,37 @@ public final P1<A> memo() {
261266
*/
262267
public P1<A> softMemo() { return new SoftReferenceMemo<>(this); }
263268

269+
/**
270+
* @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead.
271+
*/
272+
@Deprecated
264273
public static <A> P1<A> memo(F<Unit, A> f) {
265-
return P.lazy(f).weakMemo();
274+
return P.weakMemo(() -> f.f(unit()));
266275
}
267276

268-
public static <A> P1<A> memo(F0<A> f) {
269-
return P.lazy(f).weakMemo();
277+
/**
278+
* @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead.
279+
*/
280+
@Deprecated
281+
public static <A> P1<A> memo(F0<A> f) {
282+
return P.weakMemo(f);
270283
}
271284

272285
static final class Memo<A> extends P1<A> {
273-
private volatile P1<A> self;
286+
private volatile F0<A> fa;
274287
private A value;
275288

276-
Memo(P1<A> self) { this.self = self; }
289+
Memo(F0<A> fa) { this.fa = fa; }
277290

278291
@Override public final A _1() {
279-
return (self == null) ? value : computeValue();
292+
return (fa == null) ? value : computeValue();
280293
}
281294

282295
private synchronized A computeValue() {
283-
P1<A> self = this.self;
284-
if (self != null) {
285-
value = self._1();
286-
this.self = null;
296+
F0<A> fa = this.fa;
297+
if (fa != null) {
298+
value = fa.f();
299+
this.fa = null;
287300
}
288301
return value;
289302
}
@@ -294,10 +307,10 @@ private synchronized A computeValue() {
294307
}
295308

296309
abstract static class ReferenceMemo<A> extends P1<A> {
297-
private final P1<A> self;
310+
private final F0<A> fa;
298311
private volatile Reference<P1<A>> v = null;
299312

300-
ReferenceMemo(final P1<A> self) { this.self = self; }
313+
ReferenceMemo(final F0<A> fa) { this.fa = fa; }
301314

302315
@Override public final A _1() {
303316
Reference<P1<A>> v = this.v;
@@ -309,7 +322,7 @@ private synchronized A computeValue() {
309322
Reference<P1<A>> v = this.v;
310323
P1<A> p1 = v != null ? v.get() : null;
311324
if (p1 == null) {
312-
A a = self._1();
325+
A a = fa.f();
313326
this.v = newReference(p(a));
314327
return a;
315328
}
@@ -320,14 +333,14 @@ private synchronized A computeValue() {
320333
}
321334

322335
static final class WeakReferenceMemo<A> extends ReferenceMemo<A> {
323-
WeakReferenceMemo(P1<A> self) { super(self); }
336+
WeakReferenceMemo(F0<A> fa) { super(fa); }
324337
@Override
325338
<B> Reference<B> newReference(final B ref) { return new WeakReference<>(ref); }
326339
@Override public P1<A> weakMemo() { return this; }
327340
}
328341

329342
static final class SoftReferenceMemo<A> extends ReferenceMemo<A> {
330-
SoftReferenceMemo(P1<A> self) { super(self); }
343+
SoftReferenceMemo(F0<A> self) { super(self); }
331344
@Override
332345
<B> Reference<B> newReference(final B ref) { return new SoftReference<>(ref); }
333346
@Override public P1<A> softMemo() { return this; }

core/src/main/java/fj/P2.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fj;
22

33
import static fj.Function.*;
4+
import static fj.P.weakMemo;
45
import static fj.data.optic.PLens.pLens;
56
import fj.data.*;
67
import fj.data.optic.Lens;
@@ -185,8 +186,8 @@ public final P1<B> _2_() {
185186
public final P2<A, B> memo() {
186187
P2<A, B> self = this;
187188
return new P2<A, B>() {
188-
private final P1<A> a = P1.memo(u -> self._1());
189-
private final P1<B> b = P1.memo(u -> self._2());
189+
private final P1<A> a = weakMemo(self::_1);
190+
private final P1<B> b = weakMemo(self::_2);
190191

191192
public A _1() {
192193
return a._1();

core/src/main/java/fj/P3.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-3.
57
*
@@ -128,9 +130,9 @@ public final P1<C> _3_() {
128130
public final P3<A, B, C> memo() {
129131
P3<A, B, C> self = this;
130132
return new P3<A, B, C>() {
131-
private final P1<A> a = P1.memo(u -> self._1());
132-
private final P1<B> b = P1.memo(u -> self._2());
133-
private final P1<C> c = P1.memo(u -> self._3());
133+
private final P1<A> a = weakMemo(self::_1);
134+
private final P1<B> b = weakMemo(self::_2);
135+
private final P1<C> c = weakMemo(self::_3);
134136

135137
public A _1() {
136138
return a._1();

core/src/main/java/fj/P4.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-4.
57
*
@@ -182,10 +184,10 @@ public final P1<D> _4_() {
182184
public final P4<A, B, C, D> memo() {
183185
P4<A, B, C, D> self = this;
184186
return new P4<A, B, C, D>() {
185-
private final P1<A> a = P1.memo(u -> self._1());
186-
private final P1<B> b = P1.memo(u -> self._2());
187-
private final P1<C> c = P1.memo(u -> self._3());
188-
private final P1<D> d = P1.memo(u -> self._4());
187+
private final P1<A> a = weakMemo(self::_1);
188+
private final P1<B> b = weakMemo(self::_2);
189+
private final P1<C> c = weakMemo(self::_3);
190+
private final P1<D> d = weakMemo(self::_4);
189191

190192
public A _1() {
191193
return a._1();

core/src/main/java/fj/P5.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-5.
57
*
@@ -244,11 +246,11 @@ public final P1<E> _5_() {
244246
public final P5<A, B, C, D, E> memo() {
245247
P5<A, B, C, D, E> self = this;
246248
return new P5<A, B, C, D, E>() {
247-
private final P1<A> a = P1.memo(u -> self._1());
248-
private final P1<B> b = P1.memo(u -> self._2());
249-
private final P1<C> c = P1.memo(u -> self._3());
250-
private final P1<D> d = P1.memo(u -> self._4());
251-
private final P1<E> e = P1.memo(u -> self._5());
249+
private final P1<A> a = weakMemo(self::_1);
250+
private final P1<B> b = weakMemo(self::_2);
251+
private final P1<C> c = weakMemo(self::_3);
252+
private final P1<D> d = weakMemo(self::_4);
253+
private final P1<E> e = weakMemo(self::_5);
252254

253255
public A _1() {
254256
return a._1();

core/src/main/java/fj/P6.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-6.
57
*
@@ -315,12 +317,12 @@ public final P1<F> _6_() {
315317
public final P6<A, B, C, D, E, F> memo() {
316318
P6<A, B, C, D, E, F> self = this;
317319
return new P6<A, B, C, D, E, F>() {
318-
private final P1<A> a = P1.memo(u -> self._1());
319-
private final P1<B> b = P1.memo(u -> self._2());
320-
private final P1<C> c = P1.memo(u -> self._3());
321-
private final P1<D> d = P1.memo(u -> self._4());
322-
private final P1<E> e = P1.memo(u -> self._5());
323-
private final P1<F> f = P1.memo(u -> self._6());
320+
private final P1<A> a = weakMemo(self::_1);
321+
private final P1<B> b = weakMemo(self::_2);
322+
private final P1<C> c = weakMemo(self::_3);
323+
private final P1<D> d = weakMemo(self::_4);
324+
private final P1<E> e = weakMemo(self::_5);
325+
private final P1<F> f = weakMemo(self::_6);
324326

325327
public A _1() {
326328
return a._1();

core/src/main/java/fj/P7.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-7.
57
*
@@ -393,13 +395,13 @@ public final P1<G> _7_() {
393395
public final P7<A, B, C, D, E, F, G> memo() {
394396
P7<A, B, C, D, E, F, G> self = this;
395397
return new P7<A, B, C, D, E, F, G>() {
396-
private final P1<A> a = P1.memo(u -> self._1());
397-
private final P1<B> b = P1.memo(u -> self._2());
398-
private final P1<C> c = P1.memo(u -> self._3());
399-
private final P1<D> d = P1.memo(u -> self._4());
400-
private final P1<E> e = P1.memo(u -> self._5());
401-
private final P1<F> f = P1.memo(u -> self._6());
402-
private final P1<G> g = P1.memo(u -> self._7());
398+
private final P1<A> a = weakMemo(self::_1);
399+
private final P1<B> b = weakMemo(self::_2);
400+
private final P1<C> c = weakMemo(self::_3);
401+
private final P1<D> d = weakMemo(self::_4);
402+
private final P1<E> e = weakMemo(self::_5);
403+
private final P1<F> f = weakMemo(self::_6);
404+
private final P1<G> g = weakMemo(self::_7);
403405

404406
public A _1() {
405407
return a._1();

core/src/main/java/fj/P8.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fj;
22

3+
import static fj.P.weakMemo;
4+
35
/**
46
* A product-8.
57
*
@@ -480,14 +482,14 @@ public final P1<H> _8_() {
480482
public final P8<A, B, C, D, E, F, G, H> memo() {
481483
P8<A, B, C, D, E, F, G, H> self = this;
482484
return new P8<A, B, C, D, E, F, G, H>() {
483-
private final P1<A> a = P1.memo(u -> self._1());
484-
private final P1<B> b = P1.memo(u -> self._2());
485-
private final P1<C> c = P1.memo(u -> self._3());
486-
private final P1<D> d = P1.memo(u -> self._4());
487-
private final P1<E> e = P1.memo(u -> self._5());
488-
private final P1<F> f = P1.memo(u -> self._6());
489-
private final P1<G> g = P1.memo(u -> self._7());
490-
private final P1<H> h = P1.memo(u -> self._8());
485+
private final P1<A> a = weakMemo(self::_1);
486+
private final P1<B> b = weakMemo(self::_2);
487+
private final P1<C> c = weakMemo(self::_3);
488+
private final P1<D> d = weakMemo(self::_4);
489+
private final P1<E> e = weakMemo(self::_5);
490+
private final P1<F> f = weakMemo(self::_6);
491+
private final P1<G> g = weakMemo(self::_7);
492+
private final P1<H> h = weakMemo(self::_8);
491493

492494
public A _1() {
493495
return a._1();

core/src/main/java/fj/data/Stream.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static fj.Function.*;
2626
import static fj.P.p;
2727
import static fj.P.p2;
28+
import static fj.P.weakMemo;
2829
import static fj.Unit.unit;
2930
import static fj.control.parallel.Promise.promise;
3031
import static fj.data.Array.mkArray;
@@ -1442,7 +1443,7 @@ private static final class Cons<A> extends Stream<A> {
14421443

14431444
Cons(final A head, final F0<Stream<A>> tail) {
14441445
this.head = head;
1445-
this.tail = P1.memo(tail);
1446+
this.tail = weakMemo(tail);
14461447
}
14471448

14481449
public A head() {

0 commit comments

Comments
 (0)