diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 873d5ac83..296a02977 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -1,6 +1,8 @@
name: Java CI
-on: [push]
+on:
+ push:
+ pull_request:
jobs:
build-java-1_8:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 39074daea..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-dist: trusty
-language: java
-jdk:
- - oraclejdk8
- - openjdk11
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d56ef532..3aecf9b88 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
## [Unreleased]
-There are currently no unreleased changes
+### Added
+- `ReaderT#ask`, a static factory method for returning an identity `ReaderT`
+
+### Fixed
+- nested `DropWhile`s no longer incorrectly deforest using disjunction
## [5.4.0] - 2021-09-17
diff --git a/README.md b/README.md
index 850dcfb8f..7d84c6295 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,8 @@
λ
======
-[](https://travis-ci.com/palatable/lambda)
[](https://github.com/palatable/lambda/actions)
[](http://search.maven.org/#search%7Cga%7C1%7Ccom.jnape.palatable.lambda)
-[](https://gitter.im/palatable/lambda?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[
](https://discord.gg/wR7k8RAKM5)
[](https://floobits.com/jnape/lambda/redirect)
Functional patterns for Java
diff --git a/pom.xml b/pom.xml
index 6f7735144..bae03b1e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
lambda
- 5.4.1-SNAPSHOT
+ 5.5.1-SNAPSHOT
jar
Lambda
@@ -103,6 +103,13 @@
org.apache.maven.plugins
maven-jar-plugin
${maven-jar-plugin.version}
+
+
+
+ com.jnape.palatable.lambda
+
+
+
diff --git a/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterable.java b/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterable.java
index d87cf0e09..ea7b68bc7 100644
--- a/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterable.java
+++ b/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterable.java
@@ -1,24 +1,20 @@
package com.jnape.palatable.lambda.internal.iteration;
import com.jnape.palatable.lambda.functions.Fn1;
+import com.jnape.palatable.lambda.internal.ImmutableQueue;
-import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
-
-import static com.jnape.palatable.lambda.functions.builtin.fn2.Any.any;
-import static java.util.Collections.singletonList;
public final class PredicatedDroppingIterable implements Iterable {
- private final List> predicates;
- private final Iterable as;
+ private final ImmutableQueue> predicates;
+ private final Iterable as;
public PredicatedDroppingIterable(Fn1 super A, ? extends Boolean> predicate, Iterable as) {
- List> predicates = new ArrayList<>(singletonList(predicate));
+ ImmutableQueue> predicates = ImmutableQueue.singleton(predicate);
while (as instanceof PredicatedDroppingIterable) {
PredicatedDroppingIterable nested = (PredicatedDroppingIterable) as;
as = nested.as;
- predicates.addAll(0, nested.predicates);
+ predicates = nested.predicates.concat(predicates);
}
this.predicates = predicates;
this.as = as;
@@ -26,7 +22,6 @@ public PredicatedDroppingIterable(Fn1 super A, ? extends Boolean> predicate, I
@Override
public Iterator iterator() {
- Fn1 super A, ? extends Boolean> metaPredicate = a -> any(p -> p.apply(a), predicates);
- return new PredicatedDroppingIterator<>(metaPredicate, as.iterator());
+ return new PredicatedDroppingIterator<>(predicates, as.iterator());
}
}
diff --git a/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterator.java b/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterator.java
index 7add62a45..a97b513ac 100644
--- a/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterator.java
+++ b/src/main/java/com/jnape/palatable/lambda/internal/iteration/PredicatedDroppingIterator.java
@@ -1,19 +1,18 @@
package com.jnape.palatable.lambda.internal.iteration;
import com.jnape.palatable.lambda.functions.Fn1;
+import com.jnape.palatable.lambda.internal.ImmutableQueue;
import java.util.Iterator;
import java.util.NoSuchElementException;
public final class PredicatedDroppingIterator extends ImmutableIterator {
- private final Fn1 super A, ? extends Boolean> predicate;
- private final RewindableIterator rewindableIterator;
- private boolean finishedDropping;
+ private final Iterator> predicates;
+ private final RewindableIterator rewindableIterator;
- public PredicatedDroppingIterator(Fn1 super A, ? extends Boolean> predicate, Iterator asIterator) {
- this.predicate = predicate;
+ public PredicatedDroppingIterator(ImmutableQueue> predicates, Iterator asIterator) {
+ this.predicates = predicates.iterator();
rewindableIterator = new RewindableIterator<>(asIterator);
- finishedDropping = false;
}
@Override
@@ -31,11 +30,17 @@ public A next() {
}
private void dropElementsIfNecessary() {
- while (rewindableIterator.hasNext() && !finishedDropping) {
- if (!predicate.apply(rewindableIterator.next())) {
- rewindableIterator.rewind();
- finishedDropping = true;
+ while (predicates.hasNext() && rewindableIterator.hasNext()) {
+ Fn1 super A, ? extends Boolean> predicate = predicates.next();
+ boolean predicateDone = false;
+
+ while (rewindableIterator.hasNext() && !predicateDone) {
+ if (!predicate.apply(rewindableIterator.next())) {
+ rewindableIterator.rewind();
+ predicateDone = true;
+ }
}
+
}
}
}
diff --git a/src/main/java/com/jnape/palatable/lambda/internal/iteration/RewindableIterator.java b/src/main/java/com/jnape/palatable/lambda/internal/iteration/RewindableIterator.java
index 5bdde4312..092e7e98b 100644
--- a/src/main/java/com/jnape/palatable/lambda/internal/iteration/RewindableIterator.java
+++ b/src/main/java/com/jnape/palatable/lambda/internal/iteration/RewindableIterator.java
@@ -54,9 +54,7 @@ public A retrieve() {
if (cache == null)
throw new NoSuchElementException("Cache is empty.");
- A cache = this.cache;
- this.cache = null;
- return cache;
+ return this.cache;
}
public boolean isEmpty() {
diff --git a/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderT.java b/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderT.java
index e7f93a168..e4c8ec5f0 100644
--- a/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderT.java
+++ b/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderT.java
@@ -204,6 +204,19 @@ public ReaderT> carry() {
return (ReaderT>) Cartesian.super.carry();
}
+ /**
+ * Given a {@link Pure} ask will give you access to the input within the monadic embedding
+ *
+ * @param pureM the {@link Pure} instance for the given {@link Monad}
+ * @param the input and output type of the returned ReaderT
+ * @param the returned {@link Monad}
+ * @return the {@link ReaderT}
+ */
+ public static > ReaderT ask(Pure pureM) {
+ //noinspection Convert2MethodRef
+ return readerT(a -> pureM.apply(a));
+ }
+
/**
* Lift a {@link Fn1 function} (R -> {@link Monad}<A, M>
) into a {@link ReaderT} instance.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java b/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java
index 8ecf83775..59f4ce1c7 100644
--- a/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java
+++ b/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java
@@ -82,7 +82,7 @@ default A foldLeft(A a, Iterable as) {
*/
@Override
default Lazy foldRight(A a, Iterable as) {
- return lazy(() -> flip().foldMap(id(), reverse(cons(a, as))));
+ return lazy(() -> flip().foldMap(id(), cons(a, reverse(as))));
}
/**
diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/Semigroup.java b/src/main/java/com/jnape/palatable/lambda/semigroup/Semigroup.java
index a061328ce..d4cc1e6b4 100644
--- a/src/main/java/com/jnape/palatable/lambda/semigroup/Semigroup.java
+++ b/src/main/java/com/jnape/palatable/lambda/semigroup/Semigroup.java
@@ -39,7 +39,7 @@ default A foldLeft(A a, Iterable as) {
* @see FoldRight
*/
default Lazy foldRight(A a, Iterable as) {
- return FoldRight.foldRight((y, lazyX) -> lazyX.fmap(x -> apply(x, y)), lazy(a), as);
+ return FoldRight.foldRight((y, lazyX) -> lazyX.fmap(x -> apply(y, x)), lazy(a), as);
}
/**
diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java
index 68162ad74..222a5e7dc 100644
--- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java
+++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java
@@ -72,7 +72,7 @@ public Maybe checkedApply(Maybe maybeX, Maybe maybeY) {
@Override
public Maybe foldLeft(Maybe acc, Iterable> maybes) {
return trampoline(
- into((res, it) -> res.equals(nothing())
+ into((res, it) -> res.equals(nothing()) || !it.hasNext()
? terminate(res)
: recurse(tuple(liftA2(aSemigroup, res, it.next()), it))),
tuple(acc, maybes.iterator()));
diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhileTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhileTest.java
index 83903f451..ff4551a11 100644
--- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhileTest.java
+++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhileTest.java
@@ -56,7 +56,13 @@ public void deforestingExecutesPredicatesInOrder() {
innerInvocations.add(x);
return x > 2;
}, asList(1, 2, 3))).forEach(__ -> {});
- assertThat(innerInvocations, iterates(1, 2, 3));
- assertThat(outerInvocations, iterates(1, 2));
+ assertThat(innerInvocations, iterates(1));
+ assertThat(outerInvocations, iterates(1, 2, 3));
+ }
+
+ @Test
+ public void eachLayerIsAppliedOnce() {
+ assertThat(dropWhile(i -> i % 2 == 0, dropWhile(i -> i % 2 == 1, asList(1, 2, 3))),
+ iterates(3));
}
}
diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/FoldRightTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/FoldRightTest.java
index 912ee9b4a..62f6d43c9 100644
--- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/FoldRightTest.java
+++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/FoldRightTest.java
@@ -29,7 +29,7 @@ public Fn1, Iterable