Can't make simple Streams over indirect projects work
Ben Evans
benjamin.john.evans at gmail.com
Wed Aug 14 14:13:24 UTC 2019
Thanks Srikanth.
I can confirm that this does indeed fix my examples.
However, when I try to generalise this to deal with optional values of
reference type, then while this compiles:
public inline class Optional<T> {
private T value;
@SuppressWarnings("unchecked")
public static<T> Optional<T> empty() {
return (Optional<T>) Optional.default;
}
private Optional(T value) {
this.value = value;
}
public static <T> Optional<T> of(T value) {
if (value == null)
return empty();
return new Optional<T>(value);
}
public T get() {
if (value == null)
throw new NoSuchElementException("No value present");
return value;
}
public boolean isPresent() {
return value != null;
}
public T orElse(T other) {
return value != null ? value : other;
}
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else
return Optional.of(mapper.apply(value));
}
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}
all my attempts to use it, eg. via code like this:
List<Optional?<Integer>> opts = new ArrayList<>();
for (int i=0; i < 5; i++) {
Optional<Integer> oi = Optional.of(i);
opts.add((Optional?<Integer>)oi);
Optional<Integer> oe = Optional.empty();
opts.add((Optional?<Integer>)oe);
}
Integer total = opts.stream()
.map((Optional?<Integer> o) -> {
Optional<Integer> op = (Optional<Integer>)o;
return op.orElse(0);
})
.reduce(0, (x, y) -> x + y);
System.out.println("Total: "+ total);
fail to compile.
Have I misunderstood something here? Is Optional?<Integer> a valid
type, and should it be possible to project the inline type
Optional<Integer> to it?
Thanks,
Ben
On Wed, 14 Aug 2019 at 10:46, Srikanth <srikanth.adayapalam at oracle.com> wrote:
>
> Hello Ben,
>
> With this push:
> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d for
> https://bugs.openjdk.java.net/browse/JDK-8229537, I believe the code
> snippet below
> compiles fine (once suitable imports are typed in)
>
> However, this program fails at runtime with "Exception in thread "main"
> java.lang.ClassCircularityError: OptionalInt" - this circularity error
> is a bogus error that is being addressed as we speak by the good folks
> at the VM team.
>
> See
> https://mail.openjdk.java.net/pipermail/valhalla-dev/2019-August/006229.html
> which initiates a review of a fix for
> https://bugs.openjdk.java.net/browse/JDK-8229372.
>
> In the meantime, you can easily workaround the circularity problem by
> manually constant propagating OptionalInt.default into the only place
> OptionalInt.EMPTY is used.
>
> You may want to peruse the tests I have added here,
> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d
>
> Thanks!
> Srikanth
>
> On 28/07/19 6:44 PM, Ben Evans wrote:
> > Hi,
> >
> > I'm probably missing something really obvious, but I've been playing
> > with this code for several days and can't find my bug.
> >
> > Given an inline class defined like this:
> >
> > public inline class OptionalInt {
> > private static final OptionalInt EMPTY = OptionalInt.default;
> >
> > private boolean isPresent = false;
> > private int v = 0;
> >
> > public static OptionalInt empty() {
> > return EMPTY;
> > }
> >
> > public static OptionalInt of(int val) {
> > OptionalInt self = OptionalInt.default;
> > self = __WithField(self.v, val);
> > self = __WithField(self.isPresent, true);
> > return self;
> > }
> >
> > public int getAsInt() {
> > if (!isPresent)
> > throw new NoSuchElementException("No value present");
> >
> > return v;
> > }
> >
> > public boolean isPresent() {
> > return isPresent;
> > }
> >
> > public void ifPresent(IntConsumer consumer) {
> > if (isPresent)
> > consumer.accept(v);
> > }
> >
> > public int orElse(int other) {
> > return isPresent ? v : other;
> > }
> > }
> >
> > and some code that attempts to use it like this:
> >
> > public final class Main4 {
> > public static void main(String[] args) {
> > List<OptionalInt?> opts = new ArrayList<>();
> > for (int i=0; i < 5; i++) {
> > opts.add(OptionalInt.of(i));
> > opts.add(OptionalInt.empty());
> > opts.add(null);
> > }
> >
> > Integer total = opts.stream()
> > .map((OptionalInt? o) -> {
> > if (o == null)
> > return 0;
> >
> > OptionalInt op = (OptionalInt)o;
> > return op.orElse(0);
> > })
> > .reduce(0, (x, y) -> x + y);
> >
> > System.out.println("Total: "+ total);
> > }
> > }
> >
> > Then javac barfs like this:
> >
> > bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues
> > javamag/Main4.java
> >
> > javamag/Main4.java:15: error: ')' expected
> > .map((OptionalInt? o) -> {
> > ^
> > javamag/Main4.java:15: error: : expected
> > .map((OptionalInt? o) -> {
> > ^
> > javamag/Main4.java:15: error: ';' expected
> > .map((OptionalInt? o) -> {
> > ^
> > javamag/Main4.java:20: error: illegal start of expression\
> > })
> > ^
> > 4 errors
> >
> > Could some kind person put me out of my misery and tell me what I'm
> > doing wrong here, and what the proper way to express this should be?
> >
> > Thanks,
> >
> > Ben
>
More information about the valhalla-dev
mailing list