Skip to content

Commit 6fed9c6

Browse files
pivovaritEgor Tsinko
andauthored
lazily-evaluated Iterator.unfoldRight (#3112)
Co-authored-by: Egor Tsinko <egort@innova-power.com>
1 parent 77e411e commit 6fed9c6

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

vavr/src/main/java/io/vavr/collection/Iterator.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,17 +1326,18 @@ static <T, U> Iterator<U> unfoldLeft(T seed, Function<? super T, Option<Tuple2<?
13261326
static <T, U> Iterator<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f) {
13271327
Objects.requireNonNull(f, "the unfold iterating function is null");
13281328
return new AbstractIterator<U>() {
1329-
private Option<Tuple2<? extends U, ? extends T>> nextVal = f.apply(seed);
1329+
private Lazy<Option<Tuple2<? extends U, ? extends T>>> nextVal = Lazy.of(() -> f.apply(seed));
13301330

13311331
@Override
13321332
public boolean hasNext() {
1333-
return nextVal.isDefined();
1333+
return nextVal.get().isDefined();
13341334
}
13351335

13361336
@Override
13371337
public U getNext() {
1338-
final U result = nextVal.get()._1;
1339-
nextVal = f.apply(nextVal.get()._2);
1338+
Tuple2<? extends U, ? extends T> tuple = nextVal.get().get();
1339+
final U result = tuple._1;
1340+
nextVal = Lazy.of(() -> f.apply(tuple._2));
13401341
return result;
13411342
}
13421343
};
@@ -1865,11 +1866,10 @@ public boolean hasNext() {
18651866
public U getNext() {
18661867
if (isFirst) {
18671868
isFirst = false;
1868-
return acc;
18691869
} else {
18701870
acc = operation.apply(acc, that.next());
1871-
return acc;
18721871
}
1872+
return acc;
18731873
}
18741874
};
18751875
}
@@ -2014,7 +2014,7 @@ public boolean hasNext() {
20142014
queue = queue.dequeue()._2;
20152015
}
20162016
}
2017-
return queue.length() > 0;
2017+
return !queue.isEmpty();
20182018
}
20192019

20202020
@Override

vavr/src/test/java/io/vavr/collection/IteratorTest.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Spliterator;
3131
import java.util.concurrent.ExecutorService;
3232
import java.util.concurrent.Executors;
33+
import java.util.concurrent.atomic.AtomicInteger;
3334
import java.util.function.Function;
3435
import java.util.function.Supplier;
3536
import java.util.stream.Collector;
@@ -39,7 +40,13 @@
3940
import org.junit.jupiter.api.Disabled;
4041
import org.junit.jupiter.api.Test;
4142

42-
import static io.vavr.collection.Iterator.*;
43+
import static io.vavr.collection.Iterator.concat;
44+
import static io.vavr.collection.Iterator.continually;
45+
import static io.vavr.collection.Iterator.from;
46+
import static io.vavr.collection.Iterator.iterate;
47+
import static io.vavr.collection.Iterator.narrow;
48+
import static io.vavr.collection.Iterator.rangeBy;
49+
import static io.vavr.collection.Iterator.rangeClosedBy;
4350
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4451
import static org.junit.jupiter.api.Assertions.assertThrows;
4552
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
@@ -716,6 +723,39 @@ public void shouldPartitionLazily() {
716723

717724
// -- unfoldRight()
718725

726+
@Test
727+
void shouldUnfoldRightLazily() {
728+
AtomicInteger calls = new AtomicInteger();
729+
730+
Iterator<Integer> it = Iterator.unfoldRight(1, i -> {
731+
calls.incrementAndGet();
732+
return i <= 3 ? Option.some(Tuple.of(i, i + 1)) : Option.none();
733+
});
734+
735+
assertThat(calls.get()).isZero();
736+
737+
assertThat(it.hasNext()).isTrue();
738+
assertThat(calls.get()).isEqualTo(1);
739+
740+
assertThat(it.next()).isEqualTo(1);
741+
assertThat(calls.get()).isEqualTo(1);
742+
743+
assertThat(it.hasNext()).isTrue();
744+
assertThat(calls.get()).isEqualTo(2);
745+
746+
assertThat(it.next()).isEqualTo(2);
747+
assertThat(calls.get()).isEqualTo(2);
748+
749+
assertThat(it.hasNext()).isTrue();
750+
assertThat(calls.get()).isEqualTo(3);
751+
752+
assertThat(it.next()).isEqualTo(3);
753+
assertThat(calls.get()).isEqualTo(3);
754+
755+
assertThat(it.hasNext()).isFalse();
756+
assertThat(calls.get()).isEqualTo(4);
757+
}
758+
719759
@Test
720760
public void shouldUnfoldRightToEmpty() {
721761
assertThat(Iterator.unfoldRight(0, x -> Option.none())).isEqualTo(empty());

0 commit comments

Comments
 (0)