7 ms·
Ah, Java adding yet another C# feature 15 years later.
by neonsunset 3y ago
Ah, Java adding yet another C# feature 15 years later.
- marginalia_nu 3y agoWell yes. This is Java's stated development strategy. Let other languages evaluate new features, and implement them once they're demonstrated to be good.
- mrkeen 3y agoThe unstated part is implementing them poorly. Optionals that throw NPEs, Streams that operate on more than 1 item when called with .limit(1). Futures that don't cancel. Lambdas that don't play nicely with exceptions. Non-extendable streams.
- DarkNova6 3y agoOptionals only throw NPE if you’re using them wrong. You are not wrong about cancelabel futures, though.
- marginalia_nu 3y agoEither way it feels like optionals are going to be deprecated real quick now we have sealed interfaces and record matching. They let you get rid of so much of the unpleasantness in dealing with this API. Instead you can public sealed interface Maybe<T> { <T2> Maybe<T2> map(Function<T, T2> mapper); <T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper); T elseGet(T fallback); record Just<T>(T value) implements Maybe<T> { public <T2> Maybe<T2> map(Function<T, T2> mapper) { return new Just<T2>(mapper.apply(value)); } public <T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper) { return mapper.apply(value); } public T elseGet(T fallback) { return value; } } record Empty<T>() implements Maybe<T> { public <T2> Maybe<T2> map(Function<T, T2> mapper) { return new Empty<>(); } public <T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper) { return new Empty<>(); } public T elseGet(T fallback) { return fallback; } } } public void demo() { Maybe<String> foo = new Maybe.Empty<String>(); System.out.println( switch (foo) { case Maybe.Just(String val) -> "Hello " + val; case Maybe.Empty() -> "Fine, leave me hanging"; } ); };
- pron 3y agoYou're assuming that deconstructing and exhaustive patterns will continue to be restricted to ADTs only. That may or may not be the case.
- marginalia_nu 3y agoNot really, I'm just highlighting that this is possible with records today. .
- lkitching 3y agoSince this defines an interface, does this solve the null problem? e.g. Maybe<String> foo = null; foo.map(s -> "bar"); explicit pattern matching is usually discouraged anyway though, and you can do this now with Optional Optional<String> foo = Optional.empty(); String message = foo.map(s -> "Hello " + s).orElse("Fine, leave me hanging"); Other languages like Scala also have an Option.fold method for this specific case.
- kaba0 3y agoThe more likely scenario is that Optional will get made into a value type.
- imtringued 3y agoShowing an error on broken code will cost you backwards compatibility. The best you will get is a warning and the JVM will deoptimize Optional back to a regular object, because somewhere someone set an Optional to null somewhere in a library. It doesn't even have to be as obvious as Optional<String> o = null; Any cast to Optional can let a null pointer slip from an Object reference. List<Optional<String>> is allowed to contain null pointers and you are allowed to assign o = list.get(0) which generates an implicit cast. There is no good solution for this. Due to the way generics are implemented.
- kaba0 3y agoAh, you mean the Optional itself being null. That’s not any bigger an issue than anything else being Optional. Also, value types might come combined with nullability — so you might have Optional<String>!, which can’t be null, and will efficiently be stored in-place.
- pron 3y ago"Poorly" is very subjective. Yes, some aspects require fixing (e.g. the interaction of lambdas with checked exceptions; there's much we can do there, but we need to design this carefully), but others are tradeoffs; e.g. they require complicating the language in a way that hurts in other areas. It's not a coincidence that many languages that PL fans think do things "right" end up being far less popular than languages that PL fans think do things "wrong". Developers have different and conflicting preferences, and they are not distributed evenly. For example, the sweet spot for mainstream, super-popular languages over more/less compile-time checking in some areas vs. language complexity is probably not the sweet spot preferred by most developers. It's a little like the VHS vs. Betamax debate. Improving a super-popular language in some small way that doesn't harm its popularity can have a far bigger impact on software quality than features that complicate the language to a point where it will not be taught as a first language in a lot of schools and will thus never be super-popular. Designing language features for industry to maximise their impact requires far more complex considerations than just PL theory.
- Quekid5 3y ago> Yes, some aspects require fixing (e.g. the interaction of lambdas with checked exceptions; there's much we can do there, but we need to design this carefully) I do like the Java platform in general, but this sort of argument from hypothetical future Java fixes strikes my as incredibly disingenuous. People aren't programming in a hypothetical future Java. I can literally pose no argument against your imagined solution to this problem without very specific details. (Implication being, it's a straw man at best.) And saying saying stuff like (in an adjacent thread): > You're assuming that deconstructing and exhaustive patterns will continue to be restricted to ADTs only. That may or may not be the case. Is just complete fiction. (EDIT: Are you going to solve the halting problem, or are you going to provide details before just promising "it'll be ok"? I assume the Halting Problem is out of the question, but what's the plan, then? Details, pls) Either point to extant JEPs or explain in detail what the exact plan is, please.
- pron 3y agoFirst of all, you completely misunderstand my point. I neither ask people to judge Java based on some hypothetical future, nor ask for feedback on future designs. I acknowledged there's a real problem and mentioned we're exploring solutions, but even with the problem Java is the world's most popular typed programming language in 2023. Not every problem is big, and PL fans tend to grossly overestimate the cost of some cumbersomeness in a language and grossly underestimate the cost of language complexity because their preferences are often in the minority. Having said that, we have a few experiments with type-safe "checked exception transparency" for lambdas (and methods in general), but as always we like to sit on them for a few years because the cost of a bad feature may be much higher than the cost of a missing one. We only publicly discuss specific solutions once there's something to be gained by such a discussion and once we've decided that the problem merits a solution in the short term. > Is just complete fiction. I was responding to a statement about deprecating Optional in favour of an ADT, and hinted at this design, which is under exploration (https://openjdk.org/projects/amber/design-notes/patterns/pattern-match-object-model https://openjdk.org/projects/amber/design-notes/patterns/pat...): case Optional.empty() -> ... case Optional.of(var x) -> ... It's not complete fiction, this is actual stuff we're working on, but not everything we explore will end up in the language.
- Tainnor 3y agoLISP has had higher order functions from day 1. Even Java's big rival at the time, Smalltalk, had them. Yet, they were only added to Java in 2014. I think that Java suffers from NIH syndrome. Nothing that other languages do is good enough for Java until it has been debated for years and reimplemented using new patterns and unknown terminology.
- Dudester230602 3y agoIt's like desktop Windows, server Linux or Android of programming languages. So big it does not need to be good or innovative.
- marginalia_nu 3y agoThe slow rate of change is arguably the biggest selling point for Java. You don't need to waste time on language churn, can spend the entire time building stuff instead.
- cesarb 3y ago> The slow rate of change is arguably the biggest selling point for Java. Unfortunately, since Java 9 the rate of change seems to have increased a lot. > You don't need to waste time on language churn, can spend the entire time building stuff instead. In my experience, every time you upgrade to a new Java LTS, either something breaks or a library you depend on is incompatible with that Java LTS, and you have to waste some time fixing the breakage (the most recent one I saw: latest Mockito is incompatible with Java 21, unless you set a magic system property).
- lbalazscs 3y agoThe latest Mockito works with Java 21; you'll just see a warning about the usage of the bytebuddy agent. In the future, you'll need to explicitly approve the loading of agents (you can call it "magic"), which will improve the security of your programs.
- cesarb 3y ago> The latest Mockito works with Java 21 That was not the case a couple of days ago when I last looked; I see now that they released Mockito 5.7.0 two days ago, which probably fixes this issue. But that still shows my point: for every new Java LTS, you have to either fix some breakage, or update some library you depend on to a new version (which might then require further changes to your code, or even dropping compatibility with some older Java LTS). Edit: I just tried with the latest Mockito (5.7.0), and it still gave me the same "Java 21 (65) is not supported by the current version" error, when run without the magic system property. It seems something else earlier in the dependencies had a dependency on an older release of byte-buddy, so I will have to manually upgrade byte-buddy, and hope that it doesn't break that earlier dependency.