Bug in b88: Stack Overflow when changing a Supplier to a lambda using LazySeq
Samir Talwar
samir at noodlesandwich.com
Sun May 26 11:58:30 PDT 2013
The attachments were stripped, so here they are inline. (Thanks to
Brian for pointing that out.)
Crashing with a stack overflow:
// START
import com.blogspot.nurkiewicz.lazyseq.LazySeq;
class MergeSortCrashing {
public static <T extends Comparable<T>> LazySeq<T>
mergeSorted(LazySeq<T> a, LazySeq<T> b) {
if (a.isEmpty()) {
return b;
}
if (b.isEmpty()) {
return a;
}
if (a.head().compareTo(b.head()) <= 0) {
return LazySeq.cons(a.head(), () -> mergeSorted(a.tail(), b));
} else {
return LazySeq.cons(b.head(), () -> mergeSorted(a, b.tail()));
}
}
}
// END
Compiles fine without lambdas:
// START
import java.util.function.Supplier;
import com.blogspot.nurkiewicz.lazyseq.LazySeq;
class MergeSortWithoutLambdas {
public static <T extends Comparable<T>> LazySeq<T>
mergeSorted(LazySeq<T> a, LazySeq<T> b) {
if (a.isEmpty()) {
return b;
}
if (b.isEmpty()) {
return a;
}
if (a.head().compareTo(b.head()) <= 0) {
return LazySeq.cons(a.head(), new Supplier<LazySeq<T>>() {
@Override public LazySeq<T> get() {
return mergeSorted(a.tail(), b);
}
});
} else {
return LazySeq.cons(a.head(), new Supplier<LazySeq<T>>() {
@Override public LazySeq<T> get() {
return mergeSorted(a, b.tail());
}
});
}
}
}
// END
Compiles fine with an explicit comparator instead and the <T extends
Comparable<T>> business changed to <T>:
(If you change the type parameter back to <T extends Comparable<T>>,
it crashes, even with this version.)
// START
import java.util.Comparator;
import com.blogspot.nurkiewicz.lazyseq.LazySeq;
class MergeSortSafe {
public static <T> LazySeq<T> mergeSorted(LazySeq<T> a, LazySeq<T>
b, Comparator<T> comparator) {
if (a.isEmpty()) {
return b;
}
if (b.isEmpty()) {
return a;
}
if (comparator.compare(a.head(), b.head()) <= 0) {
return LazySeq.cons(a.head(), () -> mergeSorted(a.tail(),
b, comparator));
} else {
return LazySeq.cons(b.head(), () -> mergeSorted(a,
b.tail(), comparator));
}
}
}
// END
— Samir.
On Sun, May 26, 2013 at 6:29 PM, Samir Talwar <samir at noodlesandwich.com> wrote:
> I wrote some code using the LazySeq library (
> https://github.com/nurkiewicz/LazySeq ) which implements merge sort
> given two already-sorted lists. It crashes with a stack overflow.
>
> That works well. If I try and use lambdas, javac crashes with a stack overflow.
>
> Lambdas code (MergeSortCrashing.java):
>
> public static <T extends Comparable<T>> LazySeq<T>
> mergeSorted(LazySeq<T> a, LazySeq<T> b) {
> if (a.isEmpty()) {
> return b;
> }
>
> if (b.isEmpty()) {
> return a;
> }
>
> if (a.head().compareTo(b.head()) <= 0) {
> return LazySeq.cons(a.head(), () -> mergeSorted(a.tail(), b));
> } else {
> return LazySeq.cons(b.head(), () -> mergeSorted(a, b.tail()));
> }
> }
>
> This is attempting to build against b88. Crashes in both IntelliJ and Maven.
>
> Two things: if an explicit comparator is passed in rather than having
> T be Comparable, it works. (See attachment: MergeSortSafe.java). It
> also works if I replace the lambdas with explicit instantiations of
> Supplier<LazySeq<T>> (see MergeSortWithoutLambdas.java).
>
> I'm pretty sure this is a bug. I hope this is the right place to
> report it. Cheers for all your hard work, guys. I hope this one gets
> fixed soon.
>
> — Samir.
More information about the lambda-dev
mailing list