Skip to content

Commit 0643bc4

Browse files
committed
Fn1#withSelf for writing self-referencing Fn1s
1 parent fec66aa commit 0643bc4

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
77

88
### Added
99
- `$`, function application represented as a higher-order `Fn2`
10+
- `Fn1#withSelf`, a static method for constructing a self-referencing `Fn1`
1011

1112
## [5.2.0] - 2020-02-12
1213

src/main/java/com/jnape/palatable/lambda/functions/Fn1.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ default <C, D> Fn2<A, C, D> andThen(Fn2<? super B, ? super C, ? extends D> after
302302
return (a, c) -> after.apply(apply(a), c);
303303
}
304304

305+
default Fn1<A, B> self() {
306+
return this;
307+
}
308+
305309
/**
306310
* Static factory method for avoid explicit casting when using method references as {@link Fn1}s.
307311
*
@@ -335,4 +339,17 @@ static <A, B> Fn1<A, B> fromFunction(Function<? super A, ? extends B> function)
335339
static <A> Pure<Fn1<A, ?>> pureFn1() {
336340
return Constantly::constantly;
337341
}
342+
343+
/**
344+
* Construct an {@link Fn1} that has a reference to itself in scope at the time it is executed (presumably for
345+
* recursive invocations).
346+
*
347+
* @param fn the body of the function, with access to itself
348+
* @param <A> the input type
349+
* @param <B> the output type
350+
* @return the {@link Fn1}
351+
*/
352+
static <A, B> Fn1<A, B> withSelf(Fn2<? super Fn1<? super A, ? extends B>, ? super A, ? extends B> fn) {
353+
return a -> fn.apply(withSelf(fn), a);
354+
}
338355
}

src/test/java/com/jnape/palatable/lambda/functions/Fn1Test.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import testsupport.traits.Equivalence;
99
import testsupport.traits.FunctorLaws;
1010
import testsupport.traits.MonadLaws;
11-
import testsupport.traits.MonadRecLaws;
1211
import testsupport.traits.MonadReaderLaws;
12+
import testsupport.traits.MonadRecLaws;
1313
import testsupport.traits.MonadWriterLaws;
1414

1515
import java.util.function.Function;
@@ -105,4 +105,9 @@ public void staticPure() {
105105
Fn1<String, Integer> fn1 = Fn1.<String>pureFn1().apply(1);
106106
assertEquals((Integer) 1, fn1.apply("anything"));
107107
}
108+
109+
@Test
110+
public void withSelf() {
111+
assertEquals((Integer) 15, Fn1.<Integer, Integer>withSelf((f, x) -> x > 1 ? x + f.apply(x - 1) : x).apply(5));
112+
}
108113
}

0 commit comments

Comments
 (0)