Can't make simple Streams over indirect projects work
Srikanth
srikanth.adayapalam at oracle.com
Wed Aug 14 14:33:46 UTC 2019
Thanks Ben, I will study this and get back soon (tomorrow is a holiday
in my location, so by Friday)
Srikanth
On 14/08/19 7:43 PM, Ben Evans wrote:
> 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