7 ms·
Manifold: Java typesafe metaprogramming with IDE support by abusing the compiler
- TrianguloY 5y agoSeems like Kotlin but using a preprocessor approach instead of a whole different compilation process. I wonder if that allows to use newer javac features and be better optimized than kotlin's equivalent.
- vips7L 5y agoYMMV but to me it seems like most Java features are better optimized than the Kotlin equivalent.
- hawk_ 5y agowhile this may seem "fun", it's not recommended for production https://www.reddit.com/r/java/comments/q97el0/comment/hguochg/ https://www.reddit.com/r/java/comments/q97el0/comment/hguoch...
- imtringued 5y agoAt first I thought it was cool but then starting with operator overloading it basically rolled down a very steep slippery slope...
- dtech 5y agoI never understand the hate operator overloading gets. Why is it collectively decided that date.plus(1, ChronoUnit.DAYS) is 100% fine and dandy, but date + ChronoUnit.day(1) would be like introducing longjmp.
- Koshkin 5y agoNot to mention that operator (and function) overloading is absolutely unavoidable when you are dealing with generics. A generic type may itself define an operator, which, of course, becomes overloaded due to its origin, or such a type may require that an operator on another, parameter type, exists and satisfies certain “axioms” (such as associativity).
- oweiler 5y agoMost devs probably know operator overloading from C++ and Scala, which both go way overboard with them. Operator overloading on a limited set on operators, like in Kotlin is fine.
- seanmcdirmid 5y agoC#’s limits are much more reasonable than Kotlin’s. The former allows overloading comparison operators with return values other than Booleans (eg if you want to return wrapped Boolean types), the latter does not (so Kotlin EDSLs rely on eq, lt style infix operators). C# on the other hand doesn’t (or didn’t?) allow for operators to be defined via extension-type overloading. Not that limitations are bad, Kotlin is just weird in them.
- matheusmoreira 5y agoI don't understand it either. It's just yet another Java limitation that better languages simply don't have and which must be constantly worked around. There's no reason why we can't have a method named + which adds the receiver to the argument. It's just a simple symbol. x + y x.+(y) The root cause of this is the distinction between primitive and object types. Simply put, not everything is an object in Java and this causes numberless problems. One of them is the need for special syntax cases for the mathematical operators of the primitive types.
- dtech 5y agoThis is exactly how scala does it
- matheusmoreira 5y agoYeah. It's also how Ruby and Smalltalk do it. Lisp also does similar things. In these languages it doesn't even make sense to talk about operators. They don't exist. There are only methods, functions. General ideas represented by a few universal concepts. No special cases. Of course they can be overridden... It would have been strange if they couldn't. They're just normal methods or functions.
- igouy 5y agoNo special cases; apart from the special cases ;-) Some Smalltalk methods are "compiled in-line" special — ifTrue: alternativeBlock "If the receiver is false (i.e., the condition is false), then the value is the false alternative, which is nil. Otherwise answer the result of evaluating the argument, alternativeBlock. Create an error notification if the receiver is nonBoolean. Execution does not actually reach here because the expression is compiled in-line." self subclassResponsibility
- matheusmoreira 5y agoThat's just the implementation though, isn't it? In the language proper, the method still exists. The implementation just compiles it away.
- ModernMech 5y agoOperator overloading is great for library authors, bad for basically everyone else. What operator overloading buys you is fewer keystrokes to express a concept. For someone intimately familiar with a codebase, like a library author, this is awesome. It is a great save if you can write a + b + c instead of a.concatenate(b).concatenate(c). However, as a regular old user, operator overloading can be a drag. Let's say you come across the expression a + b. Are a and b numbers and are you adding them? Are they strings and are you concatenating them? Are they vectors and are you appending them? As a programmer, you don't know, so when you see this expression you have to go on a fact-finding mission to figure out what's going on. For a typed language like C++ this is not so bad; you just need to look up the types of a and b. But that isn't always straightforward due to type inference. The fact is that the symbol + has a well-defined meaning in mathematics. Operator overloading takes a very clear and well-defined symbol and turns it into a fuzzy enigma. In my opinion, it's better to have N well-defined, clear, and unique semantics for N symbols in a PL rather than having a single symbol that is overloaded for N purposes. Writing the code may take longer, but code is read more than it's written, so that doesn't seem so bad to me.
- FractalHQ 5y agoIn Typescript with VSCode just hovering over a variable shows its type and any doc comments with click-to-def. In that case, I don’t really see this being a problem.
- pjmlp 5y agoJust the same with a.concatenate(b).concatenate(c), how can you be sure what concatenate() is actually doing? One has to go through the same analysis the function called +.
- oldsecondhand 5y agoWith proper cross referencing tool support it can be the same, but in the past most IDEs didn't help you finding which function would be called in case of operator overload.
- ImprobableTruth 5y ago
- pjmlp 5y agoSame here, specially since they exist since Lisp.
- bradrn 5y agoPersonally I like the approach of Haskell: no overloading of any functions whatsoever (except in a restricted way through typeclasses), but you can define new operators yourself. That allows the certainty which comes with the absence of overloading, but also the concision which comes with using operators rather than functions. (Not that concision is everything, mind you; code gets difficult to read if there are too many custom functions. But at least the option is there.)
- alserio 5y agoI believe the Java people have done that in reaction to what was being done in c++ land. IMO operator overloading is fine when the operator is well behaved (i.e. respects some kind of law, plus should be at least a monoid etc).
- Olreich 5y agoI love the “properties” bit. You can get the same functionality by just defaulting the fields on your classes to public. 99% of the time, the getters and setters aren’t doing anything, just proxying the variable.
- skocznymroczny 5y agoYes, 99% they don't do anything, but the 1% of cases in which you want to add something extra, you're glad you're using properties. For example if you want to convert the data to other format/unit before returning, or to log all usages of a variable.
- speed_spread 5y agoAs long as this is your code, refactoring to introduce getters and setters if ever needed would be a cinch.
- vips7L 5y agoI’d rather have functions as they work quite well with method references and streams. Additionally ORMs require methods to do dirty tracking. If your class isn’t a entity pojo just use a record and get the getters for free.
- recursivedoubts 5y agoManifold is an amazing piece of technology. It grew out of the "open type system" of Gosu: https://guidewiredevelopment.wordpress.com/2010/11/18/gosus-secret-sauce-the-open-type-system/ https://guidewiredevelopment.wordpress.com/2010/11/18/gosus-... The open type system was a simple API for adding new types to Gosu, allowing you to surface non-native types in a type safe way. A really nice way to do metaprogramming for a statically typed languge. Unfortunately Gosu never really went anywhere as an open source langauge, and Scott moved on to exploring javac plugins that let you accomplish the same thing in java. Amazing stuff.
- speed_spread 5y agoMost of what this offers can be replicated in Java with properly set up build-time code gen plugins and Lombok (or a bunch of standard annotation processors). The remaining operator overloading and naive C-style preprocessor are from the wish list of someone who never had to understand or maintain software using those. Finally, reliance on Javac's internals guarantees brittleness across JDK updates. This is much more than just a plugin, it should provide it's own compiler, even if 95% would be lifted from an existing Javac implementation. Hard pass.
- pshirshov 5y agoWhy anyone may need this? Don't we have Scala?..