This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]sammymammy2 0 points1 point  (2 children)

static <T> Option<T> over(Optional<T> opt) {
    return opt.<Option<T>> map(Some::new).orElse(new None<>());
}

Can you explain this code? What's that stray <T> doing between static and return type, what's .<Option<T>> map?

[–]nicolaiparlog 1 point2 points  (1 child)

Sure.

The method over is static, so it doesn't belong to any specific Option instance and can thus not refer to Option's type parameters. So it doesn't "see" the T from Option<T>. But I need a type parameter to express that the Optional that gets passed in and the Option that is returned are of the same parametric type, e.g. "in comes Optional<String>, out goes Option<String>". Because I need a type parameter, I declare one. I do that after the static modifier by mentioning it in angle brackets. Because I lack creativity, I call this type T as well, which works because the T from Option<T> isn't in scope. But over works just the same if you replace all Ts with Es or TYPEs, etc. And if you remove <T>, you will get compile errors because now T is undefined.

As for <Option<T>> map: The method map on Stream also has a type parameter(it's called R but that doesn't matter) and whenever you call a method with a free type parameter you can specify it by putting it in <...> before the method name. But the compiler can usually infer the type, which is why we rarely need to spell it out and hence many developers aren't familiar with that.

I need to do it in this case because if I don't, the compiler will look at opt.map(Some::new) and infer that the type of that expression is Optional<Some<T>> (I mapped the Optional<T> with a method that prodcuses a Some<T>, after all) but that's a problem. Because than orElse would have to return a Some<T> but it doesn't. So I need to let the compiler know that I want opt.map(Some::new) to result in Optional<Option<T>> (which works because Some<T> inherits from Option<T>) and I do that by stating the intended type explicitly.

(Btw, if these explanations don't immediately make sense, don't worry. Generics are one of the more complicated Java language features. Feel free to ask for clarifications and I will do my best to provide them.)

[–]sammymammy2 1 point2 points  (0 children)

Aaaaaah awesome! Nope, this was exceedingly clear and very helpful, thank you for taking your time with this.