8 ms·
Pattern Matching for Java
- guelo 9y agoReally great proposal. Is this conversation in relation to Java 10 or just pie in the sky?
- dasmoth 9y agoThis is an exploratory document only and does not constitute a plan for any specific feature in any specific version of the Java Language. I hope it does go forward, though. Really useful feature, and given the constraints of the existing language, the proposed syntax looks pretty liveable-with.
- flavor8 9y agoAny substantial differences from Scala's implementation? From what I remember of Odersky's book it seems very similar if not identical. (Which is fine - I'm all for Java incorporating the best parts of Scala.)
- kelnos 9y agoThe syntax looks similar, but there's no mention of an `unapply()`-type thing, which would limit the flexibility of this proposal greatly.
- edejong 9y agoFor me the best parts would include: - Type inference - Everything is an object (no more primitives) - no obligatory ';' as a statement separator - Type-classes - Scoped import statements At which point we're actually recreating Scala and we might as well switch :)
- pyrale 9y agoCaustic people may argue that Java already has the worst parts of Scala :p
- raspasov 9y agoPattern matching is possibly one of the most under-utilized approaches that can simplify a lot of ugly/complex logic.
- zerr 9y agoOn the other hand it "prettifies" bad code style - branching by dynamic casts / type comparisons.
- wffurr 9y agoHow is that bad code style? That's exactly what virtual method dispatch does. The authors in the article even address this point, stating that some operations might make sense as instance methods if they are instrinsic to the type hierarchy, but others, especially ad-hoc queries, are extrinsic to the types and best expressed as pattern matching. Simply calling this "bad code style" sounds a lot like a justification for only having a verbose way to use an alternative to virtual method dispatch.
- zerr 9y agoEnumerating and testing for type equality each derived classes in one place (i.e. manual type switch) is certainly a bad code practice in OO languages. Yes, the better way is to let virtual method dispatch mechanism decide.
- TeMPOraL 9y agoDepends. It's useful when you want to have all dispatch code in one place (as opposed to it being scattered across numerous files). Doubly so if your language (like most languages) lacks multimethods. Triply so, if you need to dispatch on built-in types you can't extend, which sometimes happens in e.g. Java.
- drdrey 9y agoPattern matching allows far more than just branching by type comparisons. And I disagree that this is bad code style, this is actually a very common pattern in compilers (e.g. when you iterate a list of instructions, which may be of different types)
- idsout 9y agoI would love to see this land in Java. Pattern matching is one of my favorite features of Rust.
- kodablah 9y ago"How we declare the destructuring pattern in the AddNode class, or declare AddNode so that it implicitly acquires one, will be covered in a separate document." Please use a Scala unapply() and not just constructor parameters. The former gives much more latitude to build patterns. I have a ton more to say about all of this having written in Scala and Kotlin extensively. I'll just say that it is useful they are already thinking about new variable assignment to parts of matches and NOT concerning themselves w/ "smart casts".
- nightmunnas 9y agoI really really like these suggestions. Especially the first parts where I have found myself writing a lot of instance-of-cast and just marvel at how much clutter it actually adds without adding more description to the code. I do also ponder if there is a limit to how much we should potentially shorten the expressions, not to make the expressions extremely dense it understanding. The last opinion is just taste though, admittedly.
- nikolay 9y agoReally?! exprswitch?! Unreadable and long!
- deleted 9y ago[deleted]
- peeters 9y agoThis isn't a spec, it's a thought experiment. There's no need to criticize syntax at this point.
- guelo 9y agoThat's just a placeholder. Several times in the doc they say that the operator name needs to be explored, specifically to see if overloading 'switch' is feasible.
- peeters 9y agoIMO this is the biggest thing available to modern languages that Java is missing. I would absolutely love to see this, particularly pattern decomposition. I wonder if you could do it without something analogous to Scala's sealed classes though--you really want your type checker to be able to assert every match has considered every branch (without having to specify a "default" everywhere). That means you need to be able to mark classes as not-dynamically-extendible, so the type checker has the full set of subtypes available. Edit: Just got to the bottom of the article. Looks like sealed hierarchies is exactly what they explore.
- mark242 9y agoI mean, reading this article is basically a giant advertisement for Scala and its powerful pattern matching. functionThatReturnsAnyVal match { case i: Int if i > 2 => System.out.println("Greater than 2") case i: Int => System.out.println("Less than or equal to 2") case s: String => System.out.println("Hello, " + s) case _ => }
- taeric 9y agoThis still seems a terrible example just to try and avoid naming an object. Isn't the comparison to: Object o = functionThatReturnsAnyVal(); if (o instanceof Integer) { Integer i = (Integer) o; if (i > 2) { System.out.println("Greater than 2."); } else { System.out.println("Less than or equal to 2."); } } else if (o instanceof String) { String s = (String) s; System.out.println("Hello, " + s); } I get that the case syntax is kinda nice, but this particular example just doesn't seem to get there for me. Roughly half the lines, which is good. None of them hard to reason about. Which makes it a wash. Or is the comparison to something else?
- nightmunnas 9y ago(String) o; :)
- 9y ago
- deleted 9y ago[deleted]
- tannhaeuser 9y agoIf you like pattern matching, you'll love it's generalization into Prolog unification as explained in eg. [1]. [1]: http://www.amzi.com/AdventureInProlog/a10unif.php http://www.amzi.com/AdventureInProlog/a10unif.php
- stickfigure 9y agoThe syntax still looks tedious compared to Ceylon: if (is String name) { // compiler knows 'name' is String in this block print(name); } else { print("some other text"); } Why declare a new variable? The Ceylon syntax works great with union types too.
- jdmichal 9y agoI had the same comment on C#'s implementation: https://news.ycombinator.com/item?id=12971841#12972691 https://news.ycombinator.com/item?id=12971841#12972691 In C#, the "wanting the supertype" answer makes some sense with explicit interface implementations [0]. Java doesn't have that, and AFAIK there's no way to declare something that's visible on a supertype but not a subtype. [0] I think it's a bad reason. But the possibility does at least exist.
- evdev 9y agoIMO the hierarchy of need for this goes: 1 - case classes / value classes / data classes, whatever you want to call them. 2 - match-and-bind syntax ... 11? - fancy pattern matching This maybe says more about how much I pay attention to what's upstream in Java, but I found the fact that this is just a hypothetical proposal, in April of 2017, strangely shocking. I guess I figured it had to be on the docket for a future java version already.
- aardvark179 9y agoThis is not just a hypothetical proposal, I believe there is a working prototype and a lot of thought has gone into this. More things are coming, but pattern matching is a low hanging fruit that doesn't have difficult interactions with the type system or VM. Value classes need a lot of language enhancement to be really useful, and those things are likely to land before value classes themselves.
- pdpi 9y agoProject Valhalla (featuring value classes) is scheduled for Java 10 — so it'll probably arrive in production around 2020.
- aardvark179 9y agoI cannot comment on the Java release schedule, but Project Valhalla will be done when it's done, and it is not a small task. Project Amber is intended for smaller changes that may have been investigated as part of Valhalla and can be released earlier.
- hasenj 9y agoI think some/most of the "needed" features for Java are already available in some other JVM languages. I'm not too familiar with the JVM ecosystem but Kotlin comes to mind.
- chairmanwow 9y agoMaybe I'm misunderstanding your comment, but aren't case classes a fundamental piece of pattern matching? Or are you rather just suggesting the importance of which kinds of pattern matching are the most important?
- lacampbell 9y agoWhy the fixation on pattern matching? Don't get me wrong, I enjoy the benefit it provides, but for OO code multiple dispatch is a more elegant and idiomatic way to solve the "I don't want to implement the visitor pattern" problem. FYI, I recently found out that C# can actually do multiple dispatch https://blogs.msdn.microsoft.com/shawnhar/2011/04/05/visitor-and-multiple-dispatch-via-c-dynamic/ https://blogs.msdn.microsoft.com/shawnhar/2011/04/05/visitor...
- holtalanm 9y agowow. I havent used C# for at least three years, but that is a really powerful feature.
- zamalek 9y agoWhat's even better is that the DLR consists of some pretty tight code. Historically I was using a ConcurrentDictionary containing Funcs compiled using Expression. I've found the DLR is just as fast (for things that you can express with it), with a much lower overhead. I've started using it in dynamic scenarios wherever possible. Basically, this is going to be about as fast as you can get with the statically-typed underlying runtime.
- zastrowm 9y ago> I've found the DLR is just as fast... with a much lower overhead Can you expand on this? I would not have expected that it would be faster than compiled expressions.
- duncans 9y agoDynamic calls gets compiled at runtime, so there's an initial hit (as there would be with Expr.Compile) but after that ...
- zamalek 9y agoThe codegen creates a cache of delegates (created using expression trees), but uses a structure more suited to the problem than a simple ConcurrentDictionary. [1]: http://geekswithblogs.net/simonc/archive/2012/07/20/inside-the-dlr---callsites.aspx http://geekswithblogs.net/simonc/archive/2012/07/20/inside-t...
- zastrowm 9y agoReading this reminded me of all the discussions that took/are taking place for pattern matching in C#[0]; reading this I had the same reactions that I did for C#: cool stuff. It's also nice to see the languages reach parity in features; I only hope the two language committees pay attention to the research/feedback that the other receives. [0]: https://github.com/dotnet/roslyn/issues/10153 https://github.com/dotnet/roslyn/issues/10153
- kahnjw 9y agoShameless plug: I recently wrote a similar piece exploring pattern matching in Javascript http://jarrodkahn.com/posts/6/slug/ http://jarrodkahn.com/posts/6/slug/
- cschep 9y agoLooks quite Swift-like. Seems like a big win all around for pattern matching to become more "main stream".
- rdnetto 9y agoWould be really great to see this make it's way into the language. Here are some ways I've found to work around its absence: * adding a match() function to a common base type. So if it could have subtypes Foo(x), Bar(y, z), then the signature would look like: <T> T match(Function<X, T> foo, BiFunction<Y, Z, T> bar); * in the cases where I don't have control over the common base type, I've written a builder pattern that constructs a sequence of predicate-function pairs and applies them appropriately. This looks like so: new PatternMatchingHelper() .append(Foo.class, foo -> doSomething(foo.x)) .append(Bar.class, bar -> doSomethingElse(bar.y, bar.z)) .otherwise(x -> fallbackValue()) .apply(objectOfUnknownType); The main disadvantage here is that it doesn't work well with generics, because the class objects have raw types. You could probably extend the second approach to get something close to the arbitrary predicates that pattern matching would provide, but the syntax wouldn't be nearly a clean as having it in the language.
- jnordwick 9y agoJust use another language if you want pattern matching so badly. Twisting Java to look like Scala doesn't do the language justice.
- RhodesianHunter 9y agoYou act as if what op described must be the entirety of their code base. What if pattern matching is just a small part of a larger problem better solved with Java?
- adrianmsmith 9y agoIt's not so easy to just choose another language; there might be hundreds of thousands of lines of Java already written. In that case it's better make the best of a bad situation by doing something like this, than not even trying.
- dkarl 9y agoI feel these new language features that get grafted onto Java end up awkward and unpleasant to use. Java is still Java, and it exacts a stiff awkwardness tax for writing code in a style different from how Java OO was envisioned 15-20 years ago. The examples in the linked article look fine, but the difference between pattern matching as "possible direction" and pattern matching as "new language feature" could easily end up like the difference between Orson Welles as Charles Foster Kane and Orson Welles as Falstaff. I wonder if Oracle could create some excitement around the platform by creating or adopting a new language as an official repla^D^D^D^D^D "new member of the family" to implicitly succeed Java just like C# replaced Visual Basic for most use cases. Java could be kept around as a sop to die-hards like VB.NET was. It's great that the JVM allows a thousand flowers to bloom, but it's not great that the only "official" choice on the JVM is a language that hasn't been able to evolve very far from its 1990s roots.
- jeremyjh 9y agoOracle's most profitable customers are still using Java 6. That wouldn't change if they were pushing Kotlin.
- dkarl 9y agoI don't know Kotlin, but judging by their "Kotlin for Scala Developers" article I don't know if it would be a big enough jump to get people excited, especially since a project like this would take years to come to fruition. I think Scala is a good first try at what the successor language could be, but it has two problems: its reputation as a hard language, and the fact that it partly deserves said reputation. (Maybe if Odersky succeeds in simplifying the concepts underlying Scala as he's trying to now with Dotty, the result will be a potential Java-killer.) Oracle would have to fund a research project to choose an existing candidate and spend years developing it to fit the role it would play in the market. Which sounds very unlike Oracle, so I'm not holding my breath. EDIT: And to your point, I think it's a bad sign if their most profitable customers think that none of the Java language updates they've released in the last ten years is worth upgrading for. The longer their customers stick with 2006-era Java, the longer they pass up Oracle's current offerings, the less attached they feel to the future of the platform, and the more likely they are to make a big change when they do make a change.
- rattray 9y agoI'm currently thinking through the design of a pattern-matching feature for JavaScript, through a superset I'm building called LightScript[0]. I liked that this article laid out the specific options and various shades of gray that can constitute parts of "pattern matching". I'm curious for thoughts on a syntax like this: x = match y: case > 3: () => "it's bigger than three" case 2: () => "it's strictly equal to two" case Integer: (x) => `some int smaller than two: ${x}` case String: (s) => `some string: ${s}` case Array: ([ first, ...rest ]) => `a list starting with ${first}` case Object: ({ a, b }) => `an object with property a: ${a}` This is somewhat more difficult given that even when using Flow or TypeScript, there's relatively little type granularity available at runtime. Any thoughts? [0] http://lightscript.org http://lightscript.org
- jiaweihli 9y agoIf you're interested in exploring pattern matching, I've created a Javascript/TypeScript library dedicated to it. [0] You can see it live! [1] [0] https://github.com/jiaweihli/rematch https://github.com/jiaweihli/rematch [1] https://runkit.com/jiaweihli/57db70d841de7f1400d64f73 https://runkit.com/jiaweihli/57db70d841de7f1400d64f73
- seanalltogether 9y ago"Finally, the above code is less optimizable; absent compiler heroics, it will have O(n) time complexity, even though the underlying problem is often O(1)." Is this addressed with pattern matching?
- loukrazy 9y agoITT at least 3 JavaScript libraries to do this. Also how the heck do you destructure Java objects with private fields without resorting to bean accessors?
- deleted 9y ago[deleted]
- cestith 9y agoHow about... instanceOf x is? { Int { System.out.println("It's an Int"); } String { System.out.println("Hello, " + x); } _default { System.out.println("This type is not explicitly named here."); } } And if you don't want the type, the value of any other method, function, or attribute could be checked by "is?" or whatever syntax token you want there. Further tests could be saved for within those blocks to save complexity. What's odd though is that in Java this particular example seems to want multi-method. Testing the type explicitly and acting on it is more akin to duck-typed language programming. You see this pattern pretty often in Perl for example. If I want to write in Perl, I typically reach for Perl.
- djhworld 9y agoIt's not just the types/instanceof operator though They're talking about making the Pattern matcher match more complex patterns.
- tybit 9y agoI was originally very happy to hear pattern matching was coming to C#, but I don't think it is actually that useful a feature without discriminated unions/sum types too.
- platz 9y agoWhat C# has now is better described as fancy form of Destructuring . Perhaps they'll add actual pattern matching in a later release. Actually the proposed java version is better than C#'s because it allows a form of exhaustiveness checking which C# doesn't even attempt to provide for. However they had to add the `sealed` keyword too, which does not currently exist in java
- chvid 9y agoI honestly don't need this feature. Am I really the only one? Or do you all just have buckets of source code filled with if instanceof then cast just screaming for this language feature?
- kazagistar 9y agoI have buckets of code that would be much shorter and more typesafe if it was that way at least.
- legulere 9y agoJava already has simple pattern matching with exceptions (try {throw ...} catch ...). It's surprisingly ergonomic, even though it's just a hack
- kpil 9y agoThis is nice. But I think my number one feature would be first-class relationships in object oriented languages.
- cromwellian 9y agoTo me the biggest missing features are not this but: * heredoc/multiline string/embedded interpolated strings * concise array, map, and object literal initializers. * structural/anonymous types Simple things like multivalue return become an exercise in boilerplate in Java. As much as I like Immutables.org or @AutoValue, I should be able to return a struct or use destructuring operations at the callsite. The hack in Java is to use annotation processors to provide nice fluent builder patterns, but really the language should have first class support for this.
- sgift 9y ago> concise array, map, and object literal initializers. http://openjdk.java.net/jeps/269 http://openjdk.java.net/jeps/269 Just a few more month. Still nothing for the other two, but 1/3 is better than nothing.
- cromwellian 9y agoThose aren't new language features though, mostly just standardizing Guava conventions into the JDK.
- sgift 9y agoFair enough, but they do the job. I understand the wish of the designers to not change the syntax if a standard library extension does the job for 99% of the cases. Changing the language syntax is a far more elaborate process.
- cromwellian 9y agoI think it gets real ugly once you need nested data structures, the readability goes down (maps of lists of maps). Also, using overloads means it's limited to small arity, e.g. 10. Not having first class multiline literals really makes it painful to write something like React or GraphQL in Java. One of the things I give props to MS for is having the courage to evolve C# and TypeScript at a breakneck pace. Each release of TS, they add features I've been wishing for. They seem to be listening to developer productivity issues and responding. I under Java's desire to preserve backwards compatibility, but they end up breaking it anyway, and make design decisions based on how they can shoehorn things into the older JVMs, but each new release ends up with some issues. Witness how long it has taken folks to migrate to Java8. If we're going to wait years for major releases, then let's make them well worth the trouble when they finally arrive.
- scadge 9y agoAlong with with Value Types [1] Java 10 could be an even more significant improvement than Java 8 was :) [1] http://cr.openjdk.java.net/~jrose/values/values-0.html http://cr.openjdk.java.net/~jrose/values/values-0.html
- rbjorklin 9y agoHow does Vavr's (formerly Javaslang) pattern matching hold up? http://www.vavr.io/ http://www.vavr.io/
- hepta 9y agoI already use vavr, sadly such pattern matching is not exhaustive, which is the most important feature for me.
- siddharthbhola 9y agogood approach taken from scala programming language. makes things simpler and shorter.
- ysleepy 9y agoIt is an old concept used in most functional languages, like ML, haskell or even Prolog via unification. So not an invention of scala, only that is also lives on the JVM. http://wiki.c2.com/?PatternMatching http://wiki.c2.com/?PatternMatching
- leifg 9y agoAm I missing something or can most of the examples just be achieved with method overloading?
- ysleepy 9y agoJava only has single dynamic dispatch. That means it will use the method of the most specific sub-class, but will not dispatch on the runtime type of the argument, only its compile time type. So something like: for(None n: expreTree.children()) { intMath.eval(n); } will not work as expected if eval is overloaded.
- megawatthours 9y agoYou can do this in Java using derive4j: https://github.com/derive4j/derive4j https://github.com/derive4j/derive4j. It generates code for algebraic data types which offer a typesafe interface similar to the `case` statements in languages that natively support pattern matching.
- Latty 9y agoIn the same way you could "do" lambdas with single method interfaces in Java pre-8. It was possible, but it was still a pain to do.
- jbgi 9y agoIt depends. Bare minimum, in scala you have to do: sealed trait Either[A, B] final case class Left[A, B](a: A) extends Either[A, B] final case class Right[A, B](b: B) extends Either[A, B] and it is still not a real sum type due to exposing subtyping (cf. https://github.com/quasar-analytics/quasar/wiki/Faking-Sum-Types https://github.com/quasar-analytics/quasar/wiki/Faking-Sum-T...) with derive4j: @Data interface Either<A, B> { <X> X match(Function<A, X> left, Function<B, X> right); } or, at your preference: @Data interface Either<A, B> { interface Cases<X> { X left(A leftValue); X right(B rightValue); } <X> X match(Cases<X> cases); } So it is actually not much boilerplate. The real drawback of (any) java implementation is lack of TCO.
- gjmacd 9y agoJeez, seems like overkill when you get that free in more modern of stacks. Move to Elixir. Pattern matching is done right and it's brilliantly designed. I understand that if you're having to maintain Java applications, but why anybody would stomach a NEW project on that behemoth is beyond me. I'm not just talking about performance, I'm talking about object topology BS, complicated libraries, etc. Java (for me now) seems like it's bolted on to the Web and simply doesn't have it's place as a Web stack. My opinion of course but with the great amount of stacks out there -- I don't get the fascination.
- thinkmoore 9y agoThere is some very cool language design work from Chinawat Isradisaikul and Andrew C. Myers at Cornell on adding very powerful matching constructs to a Java-like language. Paper: http://www.cs.cornell.edu/~chinawat/papers/pldi13-p343-isradisaikul.pdf http://www.cs.cornell.edu/~chinawat/papers/pldi13-p343-israd... Slides: http://www.cs.cornell.edu/~chinawat/papers/chin-pldi13-slides.pdf http://www.cs.cornell.edu/~chinawat/papers/chin-pldi13-slide...