13 ms·
Java 21: What’s New?
- jph 3y agoThe matching syntax looks really good to me: // Java 21 if (obj instanceof Point(int x, int y)) { System.out.println(x+y); } // Older Java if (obj instanceof Point p) { int x = p.x(); int y = p.y(); System.out.println(x+y); }
- riku_iki 3y agoIts not substantial improvement, but another invariant which need to be learned and adds more brain load. I hope someone will design some jvm SimpleLang eventually, which will have very few syntactic constructions but cover all/most of use cases.
- nkh 3y agoIsn't that Clojure? (let [p obj] (if (instance? Point p) (let [x (.x p) y (.y p)] (println (+ x y))))
- riku_iki 3y agoI think Clojure is not statically typed? which is a big disadvantage, and also syntax is very different from current mainstream languages, so even more effort to learn is required.
- nkh 3y agoWhen type checking is needed, I find the Truss library* does the trick quite well. As for the syntax, there is very little, which can make it a harder lift but once you have the hang of it you won't deal with the issues identified in the parent comment. * https://github.com/taoensso/truss https://github.com/taoensso/truss
- The_Colonel 3y agoI don't know what Truss is, but I know that I inherited a few smaller Clojure projects / services, and it's untyped hell. Having optional typing means most people are not going to use it.
- cutler 3y agoJS and Python are not statically typed, or PHP for that matter, but it hasn't stopped JS and Python topping the popularity list year on year nor did PHP stop Facebook from world domination.
- riku_iki 3y agoI think in all cases it was realized that static types are adding significant benefits, so they were added to python, typescript and hack have been developed.
- cutler 3y agoJS and Python have gradual, not static typing. Same for PHP 8 but Hack is a different language.
- deleted 3y ago[deleted]
- Per_Bothner 3y agoOr Kawa: (if (? p::Point obj) (... p:x p:y)) This succeeds if obj matches the pattern p::Point, declaring p to be the value of obj coerced to a Point. This is integrated with Kawa's static type-checking/inference. https://www.gnu.org/software/kawa/Conditionals.html https://www.gnu.org/software/kawa/Conditionals.html
- cutler 3y agoClojure to the rescue ... again. Honestly, I can't fathom why Clojure isn't up there with the most popular languages. Paul Graham was right when he described it, well Lisp, as a secret weapon.
- chii 3y agoi would imagine the idiomatic clojure to do this is to convert the `p` into a bean using `clojure.core/bean` but if it is a java record class, then there's currently no standard library way, since it's not a bean (getter/setter naming of properties). You'd have to write custom code for it, which sucks.
- kazinator 3y agoTXR Lisp: Using quasiquote-style pattern: (if-match ^#S(point x ,x y ,y) obj (prinl (+ x y)) Or using @(struct ...) pattern operator: (if-match @(struct point x @x y @y) obj (prinl (+ x y)) All done with macros. Expansion, compilation, disassembly: 4> (flow '(if-match @(struct point x @x y @y) (new (point 1 2)) (prinl (+ x y))) expand prinl compile-toplevel disassemble) (let ((#:g0062 (struct-from-args 'point 1 2))) (let* (#:result-0065 x y) (if (if (subtypep (typeof #:g0062) 'point) (let ((#:x0063 (slot #:g0062 'x)) (#:y0064 (slot #:g0062 'y))) (sys:setq x #:x0063) (sys:setq y #:y0064) (sys:setq #:result-0065 (prinl (+ x y))) t)) #:result-0065 ()))) data: 0: point 1: 1 2: 2 3: x 4: y syms: 0: struct-from-args 1: subtypep 2: typeof 3: slot 4: prinl 5: sys:b+ code: 0: 2003000E gcall t14 0 d0 d1 d2 1: 04000000 2: 04020401 3: 20010005 gcall t5 2 t14 4: 000E0002 5: 20020002 gcall t2 1 t5 d0 6: 00050001 7: 00000400 8: 38000016 if t2 22 9: 00000002 10: 2002000A gcall t10 3 t14 d3 11: 000E0003 12: 00000403 13: 20020009 gcall t9 3 t14 d4 14: 000E0003 15: 00000404 16: 20020006 gcall t6 5 t10 t9 17: 000A0005 18: 00000009 19: 2001000D gcall t13 4 t6 20: 00060004 21: 1000000D end t13 22: 10000000 end nil instruction count: 10 #<sys:vm-desc: 9966330> I see this is doing something silly: (subtypep (typeof x) y) is just (typep x y), but costs an extra gcall instruction. Either the pattern matcher should do this, or the compiler should have that as an algebraic reduction, or both. Let's do the compiler for fun: $ git diff stdlib diff --git a/stdlib/compiler.tl b/stdlib/compiler.tl index 58685741..a837571e 100644 --- a/stdlib/compiler.tl +++ b/stdlib/compiler.tl @@ -1411,6 +1411,8 @@ (defmeth compiler comp-fun-form (me oreg env form) (set form (rlcp ^(,bin ,a ,b) form))) ((- @a) (set form (rlcp ^(neg ,a) form))) + ((subtypep (typeof @a) @b) + (set form (rlcp ^(typep ,a ,b) form))) ((@(or ignore nilf) . @args) (if (eql sym 'ignore) (each ((a args)) Note that we are using pattern matching here to recognize and rewrite this case. In return we will obtain better code from pattern matching: $ make TXR stdlib/compiler.tl -> stdlib/compiler.tlo $ ./txr This is the TXR Lisp interactive listener of TXR 291. Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet. TXR is not a toy, but should be kept within easy reach of children. 1> (flow '(if-match @(struct point x @x y @y) (new (point 1 2)) (prinl (+ x y))) expand prinl compile-toplevel disassemble) (let ((#:g0024 (struct-from-args 'point 1 2))) (let* (#:result-0028 x y) (if (if (subtypep (typeof #:g0024) ;; this hasn't changed, of course 'point) (let ((#:x0026 (slot #:g0024 'x)) (#:y0027 (slot #:g0024 'y))) (sys:setq x #:x0026) (sys:setq y #:y0027) (sys:setq #:result-0028 (prinl (+ x y))) t)) #:result-0028 ()))) ** expr-1:1: warning: if-match: no such struct type: point ** expr-1:1: warning: new: point does not name a struct type data: 0: point 1: 1 2: 2 3: x 4: y syms: 0: struct-from-args 1: typep ;;; no mention of subtypep here any more! 2: slot 3: prinl 4: sys:b+ code: 0: 2003000E gcall t14 0 d0 d1 d2 1: 04000000 2: 04020401 3: 20020002 gcall t2 1 t14 d0 4: 000E0001 5: 00000400 6: 38000014 if t2 20 7: 00000002 8: 2002000A gcall t10 2 t14 d3 9: 000E0002 10: 00000403 11: 20020009 gcall t9 2 t14 d4 12: 000E0002 13: 00000404 14: 20020006 gcall t6 4 t10 t9 15: 000A0004 16: 00000009 17: 2001000D gcall t13 3 t6 18: 00060003 19: 1000000D end t13 20: 10000000 end nil instruction count: 9 ;; down by one #<sys:vm-desc: 92c94d0> Ship it!
- eastbound 3y agoOh yes, without the .stream()….collect(toList()) cruft! Just lists with .map() on them! Also without the :: operator, it’s uglier than the arrow equivalent and it’s yet-another-construct to parse.
- appplication 3y agoI disagree. One of the major critiques of Java is how verbose and full of boilerplate it is. And sure, you can hand wave that as devs being picky, but this is a real reason people avoid picking up new projects in Java. The verbosity serves no purpose, and less code is generally better. As for there now being multiple ways to write the same thing, this seems like something that could be easily linted into consistency. So you would really only have to learn the less verbose way for any newer Java projects.
- riku_iki 3y ago> of Java is how verbose and full of boilerplate it is. yes, new SimpleLang can have lessons learned during last 20 years implemented, as in example from another commenter: https://news.ycombinator.com/item?id=37068380 https://news.ycombinator.com/item?id=37068380 Currently, for a given task, Java usually have 5 legacy deprecated ways to solve, and two more in newish Java versions, and dev needs to keep all of them in memory to be able to read and understand other's code. > As for there now being multiple ways to write the same thing, this seems like something that could be easily linted into consistency. that's if you don't work with any legacy systems and 3p libraries and never switch projects/jobs
- user432678 3y agoSounds like Kotlin is exactly such SimpleLang.
- seanmcdirmid 3y agoYa, I'm not sure why people would use Java anymore given that the SimpleLang is pretty good.
- lmm 3y agoKotlin is even worse; it's younger than Java but also has 5 legacy ways to solve the problem and two more in the newer version, it's just that the legacy ways have been removed so any examples you find online won't work any more.
- earthboundkid 3y agoSomeone (I think pg?) said that patterns are just insufficient language features, but the flip side applies too: you can apply a pattern in any language, but a feature is limited to what the language designers provide. Patterns you can learn once and write anywhere (for better or worse).
- Jtsummers 3y agoPeter Norvig: http://norvig.com/design-patterns/ http://norvig.com/design-patterns/ (slide 4)
- earthboundkid 3y agoPN, so I was half right. :-P
- maxfurman 3y agoSounds like Kotlin to me
- riku_iki 3y agoin my non-expert opinion, kotlin also added bunch of creative, unobvious and opinionated constructs to not be qualified as "simple lang"
- cutler 3y agoTheir implementation of closures is ass-backwards. Just a bare pair of braces with no arrow to disambiguate from block parens. Kotlin also added to Java's verbosity with extra modifiers like 'internal', 'open' and 'by lazy' which isn't even grammatical English. And don't get me started on multiple constructors.
- pizza234 3y agoDestructuring (/pattern matching) itself is supported by several languages (although more in general, its flexibility depends on the language). It makes sense to support it in modern languages, as it's practical and intuitive. IMO it's a significant syntactical improvement, as it considerably reduces boilerplate assignments.
- riku_iki 3y ago> It makes sense to support it in modern languages the problem is that Java not modern language, but carrying all legacy features from last 20 years, so having all legacy features + new modern creative ideas make Java very complex.
- unlikelytomato 3y agoWhat are some examples of these legacy features? Overwhelmingly, I see complaints that java has been too simple compared to virtually all other languages. I agree that cognitive load is important. However, it feels really strange to me to suggest that java has reached the complexity of other similar languages. What am I missing?
- riku_iki 3y agofor example Java went through several generations of IO evolution, so some simple task like reading text file line by line can be done in many different way in current standard library: - using DataInputStream - using Scanner - using Reader - using Files.readLines and they all suck.
- unlikelytomato 3y agoI see. Is it fair to say that most of the issues area related to jdk included libraries vs language features itself? I also find a lot of the included libraries to be cumbersome, but I see these syntax improvements to be a welcome change in contrast.
- Blackthorn 3y agoWe're programmers. It's our job to know these things. There really aren't that many to learn. It's a much simpler task than various engineering fields.
- riku_iki 3y agothe job is to produce software and make this process reliable and efficient. > There really aren't that many to learn. I think there are a lot to learn in java ecosystem.
- yazaddaruvala 3y agoThe job is to communicate effectively while producing software more reliably and with less time than someone else that might get hired. There are many of us who think Java has very little to learn - asking us to go slower - while probably good for society in general, is a losing strategy in a Capitalist economy. You can keep up, or be left behind. Meanwhile, fortunately the “communicate effectively” is 100x more valuable as “produce software more reliably and faster” ie learning all of these new languages and language improvements.
- sbjs 3y agoThat was literally the point of Java, to be syntactically and semantically simple, in contrast to the extreme complexity of C++. But just like with Lisp, that only moves necessary complexity to another layer. True wisdom in language design is understanding the line between necessary and unnecessary complexity, and perfectly incorporating necessary complexity into the language so users don't have to reinvent the wheel at the library or precompiler level.
- kaba0 3y agoJava is quite a lean language, especially considering its age, and the design team does consider every new feature for a long time before adding, being an exception among languages with regards to feature churn (with all its negatives and positives). Just look at C# or C++, both have at least an order of magnitude larger language “surface area”.
- nxobject 3y agoBeyond the other posts, I wonder whether some of the reactions are due to the fact that destructuring here is purely syntactic sugar – there's no "fear of missing out" on new semantics that offer a drastic new improvement in programming style, to the extent that they feel obligatory to incorporate in your mental model of Java (e.g the introduction of anonymous functions.)
- trondeh80 3y agoKotlin is pretty close to this?
- riku_iki 3y agothis was discussed here in comment several times, and opposite opinion is that kotlin added enough creatives and opinionated constructs which make it more innovative and less simple. I think the closest thing is if someone would create linter for java which would allow only essential structures and library API. Java has very good foundational core.
- brap 3y agoThanks I hate it
- the_af 3y agoYou hate that it takes 2 lines instead of 4 (excluding curly braces) to accomplish the same? The new syntax is not even convoluted, it's pretty intuitive destructuring syntax already available in many modern languages.
- morepork 3y agoThere's potential confusion whether the int x from the example comes from point.x (field), point.x() (method) or point.getX() (common getter pattern), just one more gotcha
- the_af 3y agoBy reading the proposal [1], I see it's meant for record types. Records seem to be value classes, i.e. the equivalent to Scala's case classes. In that case, there's absolutely no ambiguity: there's only one `x` you can be talking about. By the way, value/case classes are such a boon. Very easy to get used to, and once you have, you want to use them everywhere, I guarantee. ---- [1] https://openjdk.org/jeps/440 https://openjdk.org/jeps/440
- morepork 3y agoThanks that makes more sense, I had assumed it was for all types as Point used in the example has the same name as a class in the standard library
- trealira 3y agoAnd that "older Java" example itself is an alternative (added in Java 16, from looking it up) to what existed before. if (obj instanceof Point) { Point p = (Point) obj; int x = p.x(); int y = p.y(); System.out.println(x + y); }
- monksy 3y agoScala obj match { case Point(x,y)=> println(x+y) }
- diarrhea 3y agoVery similar in Python and Rust as well.
- switchbak 3y agoSadly no one wants to talk about Scala any more.
- throwaway5959 3y agoEven for Spark?
- monksy 3y agoWe don't talk about spark
- throwaway5959 3y agoWhat? Why?
- klysm 3y agoPretty much the same as C#
- coding123 3y agoWhat is it saying here. Is the (int x, int y) from getters or the constructor? It LOOKs like a constructor, but I can't possibly imagine it's doing anything with the constructor in this call.... Which probably explains the person saying "I hate it".
- valenterry 3y agoNo, I think this only works on Java Records where it's clear what the identifiers are.
- kaba0 3y agoYou are destructuring the object here, and since it is a record type that is nothing more than its typed, ordered fields listed in the constructor, you just use it as its reverse function here, basically. Destructuring for other kind of objects are planned with user-defined destructors. But it does have plenty prior art, e.g. in haskell you can deconstruct lists arbitrarily like _:secondElem:rest would bind secondElem logically.
- morepork 3y agoIt's a bit of an unkind example as most would write the latter as if (obj instanceof Point p) { System.out.println(p.x()+p.y()); } But I can maybe see the value if you need to use x/y more than once. However in Java it's common to have getX() style accessors, for which this syntax doesn't seem that helpful as your variable would end up being called getX
- valenterry 3y agoI think this syntax for accessing x and y only works for java records anyways and not for methods.
- whalesalad 3y agoFor those in the ecosystem these days - is there a compelling reason to choose Java over Kotlin? I am under the impression that Kotlin is a better Java without any sacrifices. Is this true?
- crickey 3y agoI mean what are your goals, its never as clear cut as X is objectively better in all use cases over Y
- mardifoufs 3y agoAt this point I think the more relevant question is: is there any point to using kotlin if you are not doing android dev?
- afavour 3y agoPersonally I find it more enjoyable to code in than Java. There’s also maybe an argument to be made around Kotlin Native, KotlinJS too.
- robertlagrant 3y agoAlso Kotlin Multiplatform.
- kaba0 3y agoGraalVM, TeaVM, Google’s Closure compiler. Java is an insanely big language, so if a tiny language has something, you can bet Java also has it in a much more ready form.
- xwowsersx 3y agoSure, assuming you are happy with most of the language constructs and it feels ergonomic to you, Kotlin can make sense for backend/APIs, while still having access to all the Java libs/packages. I'm starting several new largeish projects now and have decided on using Kotlin.
- mdaniel 3y ago
- whartung 3y agoYummy. Java's rocket sled continues to burn.
- ryanianian 3y agoWhat?
- spockz 3y agoIt remains a bit bitter sweet to see that so many features that we’ve had for 13+ years in Scala and longer in languages like Haskell and were ridiculed back then, now find their way to mainstream Java.
- zokier 3y agoRidiculed? Really?
- earthboundkid 3y agoThe only Haskell feature I can think of people ridiculing is laziness, which makes sense because it sucks and makes performance hard to reason about.
- earthboundkid 3y agoOh and burritos. Burritos are funny.
- the_af 3y agoThey only ridicule it because they don't use it or understand it. Laziness by default is my favorite Haskell feature.
- BaseballPhysics 3y agoSo you've never had a space leak? Be honest...
- the_af 3y agoI've seen lots of things and problems in languages both with and without lazy evaluation. On the whole, I like it in Haskell. In languages without lazy evaluation (by default) I tend to miss it. I've never seen it "ridiculed" by anyone proficient with the language or who used it for an actual project, either.
- LatticeAnimal 3y agoThe syntax for the string template surprised me. Are there other languages that use a `STR.` prefix to indicate string formatting?
- xwowsersx 3y agoI don't believe so.
- papercrane 3y agoIt kind of reminds me of JS tagged templates syntax. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- TrianguloY 3y agoPython requires a prefix too f"{x} + {y} = {x+y}". I guess you can now almost simulate it by using f."\{x}...". The new java way is strange, but maybe it was to avoid having to touch the language parser too much.
- mdaniel 3y agothe Java one is pluggable, whereas if one wanted to implement the cited PreparedStatement-strings in Python it'd be a parser bump since there is no `sql""` in the grammar
- TrianguloY 3y agoWhat I wanted to mention is that maybe (although probably not possible with the current grammar) an alternative would have been to remove the dot. STR"x=\{x}"
- mdaniel 3y agoPython does so via its "f-strings": https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals https://docs.python.org/3/reference/lexical_analysis.html#fo... although as the link implies, that's done at the grammar level, and not via a static field that is a StringTemplate.Processor as it is in Java https://openjdk.org/jeps/430#The-STR-template-processor https://openjdk.org/jeps/430#The-STR-template-processor
- theandrewbailey 3y ago> Java collections don’t have a type representing an ordered sequence of elements, Java 21 fills this gap by introducing the SequencedCollection, SequencedSet and SequencedMap interfaces. These interfaces provide methods for adding, modifying or deleting elements at the beginning or end of the collection, as well as for iterating over a collection in reverse order. That sounds like a deque, and it's been in Java for a long time. (No set or map implementations though.) https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/Deque.html https://docs.oracle.com/en/java/javase/18/docs/api/java.base...
- deleted 3y ago[deleted]
- joaonmatos 3y agoSome of the methods were explicitly lifted out of the Deque into this interface. Basically the aim of the new interface is to provide an unified experience and standard methods to all the collections that can feasibly support it.
- eastbound 3y agoAnyone knows when the Java 21 LTS certification book will be out (“OJP exam” or something like that)? I’m tempted to pass the exam with Java 17, since the wait for Java 21 will be too long, assuming it will be several months after the GA date, September 21st.
- hmottestad 3y agoYou'll probably be fine without it. If I'm interviewing someone and they have a Java 6 certification I'll just think that someone forced them to get it, but if they have 17 or newer it would be a big red flag unless they are straight out of uni and working at a consulting firm.
- Espionage724 3y agoFor a while I was only interested in newer Java releases just to see if Runescape ran on it :p The usefulness seemed to cut-off with Java 11 though and now the RS Java client is being deprecated.
- ajdoingnothing 3y agoI can't wait until major frameworks (such as Spring in version 6.1) support virtual threads. Reactive programming (e.g., Webflux) would become a niche (unless your use case truly requires streaming with a high number of TPS).
- softwaredoug 3y ago> JEP-448 – Vector API: sixth incubation of this feature. This new version includes bugfixes and performance improvements. Rant: JFC Java, its 2023 and people use Java to run actual databases and develop machine learning infrastructure. Yet the ability to do SIMD in the JVM is on its sixth incubation.
- the-smug-one 3y agoThat's because they want to get it right. The same with Valhalla. The same with Loom.
- marginalia_nu 3y agoI'd rather have a good API late than a bad API early in a language as committed to backward compatibility as Java.
- riku_iki 3y agoanother important feature is Arena api which is also in preview state
- dikei 3y agoWell, being a portable platform is hard. Even for native platform like C/C++ or Rust, SIMD intrinsic took a while to develop, and required multiple iterations to mature for each supported platform. Plus, with newer CPU instructions being introduced, the job is never fully done.
- kasperni 3y ago> Yet the ability to do SIMD in the JVM is on its sixth incubation. As noted in the JEP. The Vector API cannot be move to preview before value classes are available. Hence it is still in incubation and will be for quite some time.
- sohamgovande 3y agoJava 21 is great but every enterprise java system I've seen is still stuck on JDK 8
- xmcqdpt2 3y agoWe are rapidly moving millions of LOC onto Java 21 at $work so that we can take advantage of virtual threads. It's been relatively straightforward as we were already on Java 11 in most places (and on 13, 17 in other projects). The project is like the definition of "entreprise". The move from 8 to 11 was way harder than upgrading from 11 to anything else. In general Java compatibility between versions is very good.
- kernal 3y agoWith Application Servers (Oracle WebLogic, etc.) rapidly approaching EOL support companies are migrating their codebases to Java 11+. Additionally, Java 8 reached EOL on Mar 31, 2022. Any companies still using it must pay Oracle for extended support. This too is ending soon.
- lfmunoz4 3y ago[dead]
- sigzero 3y agoIs Java 21 the next LTS version?
- cutler 3y agoYes.
- deleted 3y ago[deleted]
- tedyoung 3y agoYes, but: https://twitter.com/nipafx/status/1676908785313492992 https://twitter.com/nipafx/status/1676908785313492992 "JDK21 is a version, for which many vendors offer support." tl;dr: the Java version is not what gets "long-term support", it's a specific runtime JDK released by some Java vendor, e.g., Oracle, Eclipse Adoptium, Azul, Microsoft, Amazon (Coretto), etc.
- renewiltord 3y agoWould be cool if there were an easy way to add primitives to Java. I would like a 128-bit integer that the JVM could handle with `add` + `adc` and friends. If I could extend my JVM trivially by linking in a `.so` that enabled it to handle the primitive it would be pretty sick. I imagine that's not really that easy to do, but a nice wide primitive that could be used for fixed point arithmetic would be nice to have.
- kasperni 3y agoThere is an ongoing project [1] to support use cases such as this. [1] https://openjdk.org/projects/valhalla/ https://openjdk.org/projects/valhalla/
- rictic 3y agoAre StringTemplates constant? i.e. for this method: StringTemplate foo() { return RAW.""; } is foo() == foo()? This is a very useful feature of JS tagged template functions, as it lets a template processor do expensive one-time processing of a StringTemplate and cache the result, then use that to quickly apply that to particular values. I don't see an answer here: https://cr.openjdk.org/~jlaskey/templates/docs/api/java.base/java/lang/StringTemplate.html https://cr.openjdk.org/~jlaskey/templates/docs/api/java.base...
- kamaal 3y agoDid tail call optimisation make it to the JVM so that we can have it in Clojure?
- kasperni 3y agoNo, still on the drawing board.
- amai 3y agoIs there something like pytorch or tensorflow for doing deep learning with Java nowadays? Can Java be used to create programs running on GPUs?