Skip to content

Commit b62b2a0

Browse files
committed
Adding Span
1 parent 68a20e0 commit b62b2a0

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1818
- `CheckedRunnable`, the `Runnable` counterpart to `CheckedSupplier` that can throw checked exceptions
1919
- `Unit`, the lambda analog to `Void`, except actually inhabited by a singleton instance
2020
- `Kleisli`, the abstract representation of a `Kleisli` arrow (`Monad#flatMap`) as an `Fn1`
21-
- `These`, a `CoProduct3` of `A`, `B`, or `Tuple2<A,B>`
21+
- `These`, a `CoProduct3` of `A`, `B`, or `Tuple2<A,B>`
22+
- `Span`, for splitting an `Iterable` into contiguous elements matching a predicate
2223

2324
### Deprecated
2425
- `Either#trying` in favor of `Try#trying`
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn2;
2+
3+
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
4+
import com.jnape.palatable.lambda.functions.Fn1;
5+
import com.jnape.palatable.lambda.functions.Fn2;
6+
7+
import java.util.function.Function;
8+
9+
import static com.jnape.palatable.lambda.functions.builtin.fn2.DropWhile.dropWhile;
10+
import static com.jnape.palatable.lambda.functions.builtin.fn2.TakeWhile.takeWhile;
11+
12+
/**
13+
* Given a predicate, return a {@link Tuple2} where the first slot is the front contiguous elements of an {@link
14+
* Iterable} matching the predicate and the second slot is all the remaining elements.
15+
*
16+
* @param <A> the {@link Iterable} element type
17+
*/
18+
public final class Span<A> implements Fn2<Function<? super A, Boolean>, Iterable<A>, Tuple2<Iterable<A>, Iterable<A>>> {
19+
20+
private static final Span INSTANCE = new Span();
21+
22+
private Span() {
23+
}
24+
25+
@Override
26+
public Tuple2<Iterable<A>, Iterable<A>> apply(Function<? super A, Boolean> predicate, Iterable<A> as) {
27+
return Tuple2.fill(as).biMap(takeWhile(predicate), dropWhile(predicate));
28+
}
29+
30+
@SuppressWarnings("unchecked")
31+
public static <A> Span<A> span() {
32+
return INSTANCE;
33+
}
34+
35+
public static <A> Fn1<Iterable<A>, Tuple2<Iterable<A>, Iterable<A>>> span(Function<? super A, Boolean> predicate) {
36+
return Span.<A>span().apply(predicate);
37+
}
38+
39+
public static <A> Tuple2<Iterable<A>, Iterable<A>> span(Function<? super A, Boolean> predicate,
40+
Iterable<A> as) {
41+
return Span.<A>span(predicate).apply(as);
42+
}
43+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn2;
2+
3+
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
4+
import com.jnape.palatable.lambda.functions.Fn1;
5+
import com.jnape.palatable.lambda.monoid.builtin.Concat;
6+
import com.jnape.palatable.traitor.annotations.TestTraits;
7+
import com.jnape.palatable.traitor.runners.Traits;
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
import testsupport.traits.EmptyIterableSupport;
11+
import testsupport.traits.FiniteIteration;
12+
import testsupport.traits.ImmutableIteration;
13+
import testsupport.traits.InfiniteIterableSupport;
14+
import testsupport.traits.Laziness;
15+
16+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Eq.eq;
17+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
18+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Span.span;
19+
import static java.util.Arrays.asList;
20+
import static org.junit.Assert.assertThat;
21+
import static testsupport.matchers.IterableMatcher.iterates;
22+
23+
@RunWith(Traits.class)
24+
public class SpanTest {
25+
26+
@TestTraits({EmptyIterableSupport.class, InfiniteIterableSupport.class, FiniteIteration.class, ImmutableIteration.class, Laziness.class})
27+
public Fn1<Iterable<Integer>, Iterable<Integer>> testSubject() {
28+
return span(eq(0)).fmap(into(Concat::concat));
29+
}
30+
31+
@Test
32+
public void splitsIterableAfterPredicateFailure() {
33+
Tuple2<Iterable<Integer>, Iterable<Integer>> spanned = span(eq(1), asList(1, 1, 1, 2, 3, 1));
34+
assertThat(spanned._1(), iterates(1, 1, 1));
35+
assertThat(spanned._2(), iterates(2, 3, 1));
36+
}
37+
}

0 commit comments

Comments
 (0)