6 ms·
Java Functions: Every Java FunctionalInterface You Want
- ZitchDog 12y agoIt's so sad that this is necessary. Proper function types would have made lambdas so much more useful.
- BrandonM 12y agoI agree wholeheartedly with your first sentence, but I still find lambdas to be quite useful in spite of their limitations.
- ZitchDog 12y agoI find them useful as well. But their usefulness is just not on the level of closures in functional languages, and it makes me sad.
- electrum 12y agoThis talk explains why: https://www.youtube.com/watch?v=MLksirK9nnE https://www.youtube.com/watch?v=MLksirK9nnE
- revelation 12y agoRead "people wouldn't stop harassing us for lambdas after we decided to delay them again and again, and so we half-assed a solution that is easy for us and binds into all the overengineered class hierarchies you have lying around".
- BrandonM 12y agoI believe Hacker News calls this a Minimum Viable Product.
- mateuszf 12y agoMVP and 100% backward compatibility don't go with each other well.
- BrandonM 12y agoThe linked talk actually does a pretty good job describing how Java 8's Lambda is both backwards compatible and forward thinking. 1. The idea of @FunctionalInterface leveraged practices that were already in use--interfaces with a single method--for Comparator, Runnable, Callable, and external libraries. This meant that users could use lambdas to implement such interfaces immediately, with no changes to existing libraries. 2. The actual implementation of a lambda in bytecode is a single invokedynamic call. They went that route to avoid tying the bytecode representation to their initial implementation. A future change could add true function types, and have them automatically instantiate a target functional interface (provided that they have the same "shape"). That would require a language change (adding function types), but not a bytecode change. That would have the nice result that all the code that people are writing now could work with new function types, and new code could be written to accept the function types instead of functional interfaces. My library would become unnecessary at that point, and I would be pretty happy about that. That is, Java 8's lambda implementation does not preclude fully-backwards-compatible "real" lambdas in the future. Personally, I think the Lambda project was a well-reasoned, intelligent step forward. The video is really worth watching, because I wasn't aware of how flexible their future directions are until I watched it.
- mateuszf 12y agoThanks. But that is totally compatible with what I said. Java lambdas were well thought out, doing MVP style development would highly likely blow it.
- frowaway001 12y ago> That is, Java 8's lambda implementation does not preclude fully-backwards-compatible "real" lambdas in the future. No, it just made them a lot harder to achieve, because any decent "real" lambda implementation requires now the introduction of another language feature: type aliases.
- chvid 12y agoIt is not necessary - just use the "boxed" version of the primitive types.
- deleted 12y ago[deleted]
- maaaats 12y agoWhat is the use for this?
- dyadic 12y agoWith Java 8 you can create anonymous functions, but they have to conform to a pre-existing interface. This is a huge collection of those interfaces.
- deleted 12y ago[deleted]
- BrandonM 12y agoOur company has been slowly converting a medium-sized (~100K LOC) Java codebase to take advantage of some Java 8 features. One example is a utility method that accepts a String DB query and then executes a Consumer<ResultSet> for each resulting row. The utility method creates the connection, uses try-with-resources to ensure that it's properly closed, etc. This makes a lot of code a lot cleaner. But unfortunately, many ResultSet operations can throw SQLException. So we created a `ConsumerE<T, E extends Exception>` to use in such cases, so that we can allow some lambdas to throw exceptions where it is sensible (InterruptedException, SQLException, and IOException being the major culprits). Pretty soon we ended up with FunctionE, BiFunctionE, and so on. At the same time, we found a need for more interfaces, such as ObjIntFunction<T, R>, that are not provided by JDK 8. Rather than continuing to implement these on an as-needed basis, I decided to just solve the problem once-and-for-all by creating this library.
- nardi 12y agoOver 16,000 classes. Better increase your PermGen.
- pron 12y agoNo more PermGen in Java 8. Besides, you only pay for the classes you use.
- BrandonM 12y agoYes, that's a huge number. That's why I split it up the way I did (https://github.com/mintern-java/functions#sensible-packaging https://github.com/mintern-java/functions#sensible-packaging). If you don't care about `short`, that cuts out nearly 6,000 of the classes. If you don't need three-argument functions, that's another 9,000+ classes. That leaves 1,316 classes. That's still a lot of classes, unfortunately, but at least it's in the realm of being reasonable.
- miralabs 12y agonot all gets loaded, only the classes you use.
- norswap 12y agoDoes someone know of a good tree-shaking packager for Java? Something that builds a jar (or a directory) with only the needed .class files (or even better, versions of the .class files with the used functions)? Looks like it would perfectly complement this project.
- TacticalCoder 12y agoProguard exists since many years and does optimization, shrinking, unused classes and unused methods removal etc. Even obfuscation if you want. It's been a long time I haven't used it but back in the days I used it for years as part of the build chain and it was pretty flawless. As I understand it nowadays it's even used for Android builds.
- _lce0 12y agoIsn't possible to generate those like on-demand? That would make those 16k classes availables to use, but present only when you need them.
- BrandonM 12y agoIt may be! It would be pretty cool to do something like: import net.mintern.functions.auto.ObjCharToBool; and have the generate-classes stage be able to see that import and automatically generate the requisite interface. Of course, the IDE might not be happy until the first compile, but that seems tolerable. It seems like Project Lombok has some similar issues... I'll have to see how it handles them. That would also allow an arbitrary function signature, though I personally think it starts to be better to write your own @FunctionalInterface for readability reasons once you hit more than 3 arguments.
- chvid 12y agoI do hope I am wrong; but isn't this like creating a version of Map for every possible permutation of the primitive types? I.e. MapIntInt MapIntShort MapShortBool etc. because you cannot write Map<int, short> and somehow think that the overhead of boxing (Map<Integer, Short>) is unbearable.
- makeramen 12y agoYeah I'm confused here too, I understand there might be a need for some of these, but you should be able to just rely on autoboxing of primitives to Objects like what RxJava does: https://github.com/ReactiveX/RxJava/tree/1.x/src/main/java/rx/functions https://github.com/ReactiveX/RxJava/tree/1.x/src/main/java/r... I can maybe see an extra variation for exceptions, but that would be one more generic or a Set<? extends Exception> no?
- chvid 12y agoYes.
- BrandonM 12y agoIt's exactly like that. For some use cases, that cost matters. Trove is a popular project that does just what you describe for Set, List, and Map. For this library, if you stick to binary-core, you basically get what Java 8 provides out of the box, while also getting exception-throwing functional interfaces, static `unchecked` functions for concisely converting from checked to unchecked versions, and `bind` methods for providing currying operations. So the full type enumeration is one part of it, but there`s a little more to it than that. I probably could have done a better job touting the other benefits.
- TeeWEE 12y agoOmg. Java is getting crippled. The language was never designed with lambda's in mind. And now we have Java 8 with "not-really-lambdas" But some kind of interface magic. Its just ugly as hell.