11package fj ;
22
3- import java .lang .ref .Reference ;
4- import java .lang .ref .SoftReference ;
5- import java .lang .ref .WeakReference ;
6-
73import fj .data .Array ;
8- import fj .data .List ;
9- import fj .data .Stream ;
104import fj .data .Either ;
5+ import fj .data .List ;
116import fj .data .Option ;
7+ import fj .data .Stream ;
128import fj .data .Validation ;
9+
10+ import java .lang .ref .Reference ;
11+ import java .lang .ref .SoftReference ;
12+ import java .lang .ref .WeakReference ;
13+
14+ import static fj .P .p ;
15+ import static fj .Unit .unit ;
1316//import fj.data.*;
1417
1518
@@ -138,7 +141,7 @@ public final <B, C> P1<C> liftM2(P1<B> pb, F2<A, B, C> f) {
138141 * @return A single P1 for the given List.
139142 */
140143 public static <A > P1 <List <A >> sequence (final List <P1 <A >> as ) {
141- return as .foldRight (liftM2 (List .cons ()), P . p (List .nil ()));
144+ return as .foldRight (liftM2 (List .cons ()), p (List .nil ()));
142145 }
143146
144147 /**
@@ -157,7 +160,7 @@ public static <A> F<List<P1<A>>, P1<List<A>>> sequenceList() {
157160 * @return A single P1 for the given stream.
158161 */
159162 public static <A > P1 <Stream <A >> sequence (final Stream <P1 <A >> as ) {
160- return as .foldRight (liftM2 (Stream .cons ()), P . p (Stream .nil ()));
163+ return as .foldRight (liftM2 (Stream .cons ()), p (Stream .nil ()));
161164 }
162165
163166 /**
@@ -238,7 +241,11 @@ public final <B> P1<B> map(final F<A, B> f) {
238241 return P .lazy (() -> f .f (self ._1 ()));
239242 }
240243
241- public P1 <A > memo () {
244+ /**
245+ * @deprecated since 4.7. Use {@link P1#weakMemo()} instead.
246+ */
247+ @ Deprecated
248+ public final P1 <A > memo () {
242249 return weakMemo ();
243250 }
244251
@@ -247,7 +254,7 @@ public P1<A> memo() {
247254 *
248255 * @return A P1 that calls this P1 once and remembers the value for subsequent calls.
249256 */
250- public final P1 <A > hardMemo () { return new Memo <>(this ); }
257+ public P1 <A > hardMemo () { return new Memo <>(this ); }
251258
252259 /**
253260 * Like <code>memo</code>, but the memoized value is wrapped into a <code>WeakReference</code>
@@ -259,73 +266,85 @@ public P1<A> memo() {
259266 */
260267 public P1 <A > softMemo () { return new SoftReferenceMemo <>(this ); }
261268
269+ /**
270+ * @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead.
271+ */
272+ @ Deprecated
262273 public static <A > P1 <A > memo (F <Unit , A > f ) {
263- return P .lazy ( f ). memo ( );
274+ return P .weakMemo (() -> f . f ( unit ()) );
264275 }
265276
266- public static <A > P1 <A > memo (F0 <A > f ) {
267- return P .lazy (f ).memo ();
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 );
268283 }
269284
270- static class Memo <A > extends P1 <A > {
271- private volatile P1 <A > self ;
285+ static final class Memo <A > extends P1 <A > {
286+ private volatile F0 <A > fa ;
272287 private A value ;
273288
274- Memo (P1 <A > self ) { this .self = self ; }
289+ Memo (F0 <A > fa ) { this .fa = fa ; }
275290
276291 @ Override public final A _1 () {
277- if (self != null ) {
278- synchronized (this ) {
279- if (self != null ) {
280- A a = self ._1 ();
281- value = a ;
282- self = null ;
283- return a ;
284- }
285- }
292+ return (fa == null ) ? value : computeValue ();
293+ }
294+
295+ private synchronized A computeValue () {
296+ F0 <A > fa = this .fa ;
297+ if (fa != null ) {
298+ value = fa .f ();
299+ this .fa = null ;
286300 }
287301 return value ;
288302 }
289303
290- @ Override public final P1 <A > memo () { return this ; }
304+ @ Override public P1 <A > hardMemo () { return this ; }
305+ @ Override public P1 <A > softMemo () { return this ; }
306+ @ Override public P1 <A > weakMemo () { return this ; }
291307 }
292308
293309 abstract static class ReferenceMemo <A > extends P1 <A > {
294- private final P1 <A > self ;
295- private final Object latch = new Object ();
296- private volatile Reference <Option <A >> v = null ;
310+ private final F0 <A > fa ;
311+ private volatile Reference <P1 <A >> v = null ;
297312
298- ReferenceMemo (final P1 <A > self ) { this .self = self ; }
313+ ReferenceMemo (final F0 <A > fa ) { this .fa = fa ; }
299314
300315 @ Override public final A _1 () {
301- Option <A > o = v != null ? v .get () : null ;
302- if (o == null ) {
303- synchronized (latch ) {
304- o = v != null ? v .get () : null ;
305- if (o == null ) {
306- o = Option .some (self ._1 ());
307- v = newReference (o );
308- }
309- }
316+ Reference <P1 <A >> v = this .v ;
317+ P1 <A > p1 = v != null ? v .get () : null ;
318+ return p1 != null ? p1 ._1 () : computeValue ();
319+ }
320+
321+ private synchronized A computeValue () {
322+ Reference <P1 <A >> v = this .v ;
323+ P1 <A > p1 = v != null ? v .get () : null ;
324+ if (p1 == null ) {
325+ A a = fa .f ();
326+ this .v = newReference (p (a ));
327+ return a ;
310328 }
311- return o . some ();
329+ return p1 . _1 ();
312330 }
313331
314- abstract Reference <Option < A >> newReference (Option < A > o );
332+ abstract < B > Reference <B > newReference (B ref );
315333 }
316334
317- static class WeakReferenceMemo <A > extends ReferenceMemo <A > {
318- WeakReferenceMemo (P1 <A > self ) { super (self ); }
335+ static final class WeakReferenceMemo <A > extends ReferenceMemo <A > {
336+ WeakReferenceMemo (F0 <A > fa ) { super (fa ); }
319337 @ Override
320- final Reference <Option < A >> newReference (final Option < A > o ) { return new WeakReference <>(o ); }
321- @ Override public final P1 <A > weakMemo () { return this ; }
338+ < B > Reference <B > newReference (final B ref ) { return new WeakReference <>(ref ); }
339+ @ Override public P1 <A > weakMemo () { return this ; }
322340 }
323341
324- static class SoftReferenceMemo <A > extends ReferenceMemo <A > {
325- SoftReferenceMemo (P1 <A > self ) { super (self ); }
342+ static final class SoftReferenceMemo <A > extends ReferenceMemo <A > {
343+ SoftReferenceMemo (F0 <A > self ) { super (self ); }
326344 @ Override
327- final Reference <Option <A >> newReference (final Option <A > o ) { return new SoftReference <>(o ); }
328- @ Override public final P1 <A > softMemo () { return this ; }
345+ <B > Reference <B > newReference (final B ref ) { return new SoftReference <>(ref ); }
346+ @ Override public P1 <A > softMemo () { return this ; }
347+ @ Override public P1 <A > weakMemo () { return this ; }
329348 }
330349
331350 /**
0 commit comments