News for hackers. Stuff that matters.
Re:New Features in Java 14 by mateuszf on Tuesday March 03, 2020 @07:18PM (#22480079)
I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala:

  case class Person (
    firstName: String,
    lastName: String,
    age: Int
  )
you could create an instance like this:

  val emily1 = Person("Emily", "Maness", 25)
and then create a new instance by updating several parameters at once, like this:

  // emily is married, and a year older
  val emily2 = emily1.copy(lastName = "Wells", age = 26)
Re:New Features in Java 14 by Benjammer on Tuesday March 03, 2020 @09:31PM (#22480731)
You'd probably have to manually write a Builder in the Person record class. Then the callsite might look something like this:

    val emily2 = emily1.newBuilder()
                    .lastName("Wells")
                    .age(26)
                    .build()

I think the inner Builder pattern is common enough in immutable java object implementations that they might want to include that fully in the Record class generation at some point. Most immutable object libraries that I've seen include a lot more functionality than Records, like builders.
Re:New Features in Java 14 by jeswin on Tuesday March 03, 2020 @11:35PM (#22481232)
Why not do what JS does?

  val emily2 = { ...emily1, age: 30 };
This has many advantages, one being that it provably and declaratively creates a copy, which is not the case with the builder. In fact the obsession with methods (and hence the implied state) is what makes Java a terrible misfit for functional paradigms such as immutability.
Re:New Features in Java 14 by riquito on Wednesday March 04, 2020 @12:00AM (#22481329)
JS is not any better in that regard, that simple example is ignoring nested objects, where the outer one is copied and the inner are referenced (unless you use triple dots all the way down - tedious and error prone, or even simply inefficient if done by some recursive algorithm). The syntax is cool though
Re:New Features in Java 14 by sa46 on Wednesday March 04, 2020 @12:11AM (#22481368)
I don't understand what you mean by provably. The Java example does the exact same thing as the JS version: create a shallow clone with a different age. Do you mean the builder might do something different?

    // Java
    val emily2 = emily1.toBuilder().age(30).build()
As far as adding the spread operator to Java, I think you'd have to require a Spreadable interface to use it or limit usage of the spread operators to records. It's not clear to me that the expressive power is worth it over a builder.
Re:New Features in Java 14 by jeswin on Wednesday March 04, 2020 @03:33AM (#22482085)
If a tool analyzed the JS AST, it could conclude (with fairly trivial analysis) that emily2 is a shallow clone of emily1. No such guarantee is possible with the Java version.
Re:New Features in Java 14 by hedora on Wednesday March 04, 2020 @11:14AM (#22484968)
Builders are really only useful for small programs or classes that aren’t broadly used.

Otherwise, at some point you need to add a field to Person, and then the compiler can’t tell you about all the places where your code fails to initialize the field.

Worse, some people pass builders around.

At that point, the problem of checking that you’ve passed a legal set of arguments when constructing objects is as hard as the halting problem.

You can write tests to make sure your program is typesafe, but that takes time away from writing more useful tests.

Re:New Features in Java 14 by jfengel on Wednesday March 04, 2020 @12:01PM (#22485448)
I find Builders most useful when you've got a lot of optional arguments. For mandatory arguments (and most arguments should be mandatory), you should definitely use constructors instead, so that your tool kit can tell you when they change.

Optional arguments with reasonable defaults don't present a problem for refactoring. It does make it hard to spot the cases where the reasonable defaults don't work. One trick is to temporarily add it to the constructor, review all the errors, and then remove the constructor arg.

Re:New Features in Java 14 by tadfisher on Tuesday March 03, 2020 @07:23PM (#22480106)
Java lacks default arguments for functions, which makes that particular API infeasible without adding support for such. They could generate "withFoo" methods or even builder types, but that would butt up against developer preference, so it's probably best to leave it up to developers or a third-party library.

Kotlin has a very similar feature in its data classes, FWIW.

Re:New Features in Java 14 by skissane on Tuesday March 03, 2020 @07:52PM (#22480250)
> Java lacks default arguments for functions, which makes that particular API infeasible without adding support for such

I really wish Java would add both default arguments for functions, and also support for passing function arguments by name.

One of these days...

Re:New Features in Java 14 by nine_k on Tuesday March 03, 2020 @09:41PM (#22480766)
This goes against the very idea of method signatures in Java an overloads based on them. An attempt to add it will likely bring in way, way more backwards-compatibility pain than any benefits are worth.

Writing simple methods with few arguments helps.

Re:New Features in Java 14 by thu2111 on Wednesday March 04, 2020 @05:21AM (#22482588)
The JVM has all the machinery required to do this right, though: invokedynamic.

Kotlin provides named arguments and a copy method on data classes/records that uses them. You do indeed have binary compatibility issues with them, but it's not a fundamental problem. It's just that it sits at the intersection of:

- Problems that only affect library writers, rarely a high priority for language designers (Java being a exception)

- Obscure JVM knowledge and new techniques

- Poor Android JVM holding back the ecosystem by discouraging any bytecode techniques that post-date Java circa 2010.

Re:New Features in Java 14 by diegof79 on Tuesday March 03, 2020 @10:25PM (#22480953)
You can have named parameters and backward compatibility with method signatures, Groovy does that [1].

Ok, it cheats a little bit because named params are actually a syntax sugar for Maps. But other languages do the same (e.g. Python) and is very useful too. And if you can type check the map (as in Typescript) the functionality is equivalent to named params.

[1] http://docs.groovy-lang.org/latest/html/documentation/#_name...

Re:New Features in Java 14 by viraptor on Wednesday March 04, 2020 @02:12AM (#22481796)
Python has real keyword parameters, not just a syntax sugar. They're just presented as a dict when you want to see them all. And you can splat that dict when calling.

Ruby before 2.7 has a syntax sugar where keyword parameters are the same as a trailing hash. But that's changing as well.

Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @09:38PM (#22480753)
Does Kotlin have anything to let you treat data classes in a generic way like you can do with Shapeless in Scala? That's where the real power comes IME - e.g. look at Circe where you can derive JSON encoders/decoders for arbitrarily nested case classes at compile time, so you have zero boilerplate but still get compile-time type safety that stops you from accidentally trying to serialise a file handle or semaphore.
Re:New Features in Java 14 by nitrogen on Tuesday March 03, 2020 @10:23PM (#22480946)
There is the currently experimental kotlinx.serialization library that generates e.g. JSON codecs at compile time. Not sure if that fits the bill.
Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @11:50PM (#22481292)
Looks like it's doing annotation processing at compile time? The trouble with that is that you end up with "magic" code like calling methods that don't appear to exist, and in order to be able to work on the serialisation itself (e.g. to add a new format) you have to understand the "magic", because there isn't a good intermediate abstraction. The great advantage of Shapeless is that all the "magic" is in the library itself and it spits out a generic representation of your data classes in record form; you can implement a new serialisation format in 100% vanilla Scala without having to worry about any macros or annotations or anything.
Re:New Features in Java 14 by thu2111 on Wednesday March 04, 2020 @05:24AM (#22482602)
It's not annotation processing, it's a compiler plugin with IDE support. So pretty deeply integrated. It avoids some of those issues.

The kotlinx.serialisation design is pretty nice. It's basically what you describe. The compiler generates generic code that can call into a variety of "codecs" but they don't have to actually be serialisation specific. So there are codecs for JSON, protobufs, CBOR etc but you can also do arbitrary object graph transformations with the framework. A deep clone being a simple hello-world type example. I've never used Shapeless but it sounds pretty similar in some ways.

https://github.com/Kotlin/kotlinx.serialization

Re:New Features in Java 14 by lmm on Wednesday March 04, 2020 @08:38PM (#22490127)
> It's basically what you describe. The compiler generates generic code that can call into a variety of "codecs" but they don't have to actually be serialisation specific. So there are codecs for JSON, protobufs, CBOR etc but you can also do arbitrary object graph transformations with the framework. A deep clone being a simple hello-world type example.

So what does the value that gets passed into your codec look like? What makes Shapeless tick is that it can represent records generically at the type level; records will have a type like

    type Book = 'author ->> String :: 'title ->> String :: HNil
that you can actually break down and do meaningful operations on (e.g. you could run it through a function that counts the lengths of strings and get something of type 'author ->> Int :: 'title ->> Int :: HNil, in a fully type-safe way). I'd be impressed if someone managed to encode those kinds of types into Kotlin - e.g. I don't think Kotlin has singleton types, so being able to compare field names at the type level is probably impossible?
Re:New Features in Java 14 by on_and_off on Tuesday March 03, 2020 @10:41PM (#22481035)
kotlin has this too .. but java does not have named params. It would be a good addition imo (think Rect(left, top, ....) , especially associated with default params.

Alternatively, they could automatically generate a builder class for records.

As always in java, I guess that somebody will duct tape an annotation based solution on top of the language to solve this.

Re:New Features in Java 14 by namelosw on Wednesday March 04, 2020 @08:57AM (#22483747)
It is very cumbersome to not having the 'copy' or equivalence so that a lot of functional languages have similar things:

F#: let updated = { old with prop = newValue }

Elixir: update = %{ old | prop: newValue }

Even JavaScript have similar stuff: const update = { ...old, prop: newValue }

Re:New Features in Java 14 by capableweb on Tuesday March 17, 2020 @07:40PM (#22611895)
Clojure: (assoc old :key new-value)

just a fn in the end

Re:New Features in Java 14 by mrlala on Tuesday March 03, 2020 @09:16PM (#22480663)
>val emily1 = Person("Emily", "Maness", 25)

The assumption of inputs based on the order of the class items frightens me!

Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @09:33PM (#22480739)
You can use named parameters if you're worried:

  val emily1 = Person(firstName="Emily", lastName="Maness", age=25)
Scala's approach to constructors is a good example of convention over configuration; in Java 99.9% of classes have a constructor like:

    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
which is just ceremonial boilerplate that obscures the actual logic of what the class is doing (an IDE can generate the constructor for you, but the person maintaining your code still has to take the time to comprehend it). You can do the more complicated things in cases where you need to, but it's important to keep the simple case simple.
Re:New Features in Java 14 by nine_k on Tuesday March 03, 2020 @09:42PM (#22480771)
Lombok solves this for Java.
Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @11:42PM (#22481262)
Using Lombok ends up being just as much effort as using a different JVM language, and the rewards are smaller.
Re:New Features in Java 14 by nine_k on Wednesday March 04, 2020 @12:52AM (#22481509)
The learning curve is way less steep, and you can introduce it into an existing project with zero impedance mismatch.
Re:New Features in Java 14 by neuronic on Wednesday March 04, 2020 @04:14AM (#22482250)
Yes, but in teams where there is no hope of switching to another JVM language like Kotlin, Lombok can reduce boilerplate by enormous amounts.

It's a compromise.

Re:New Features in Java 14 by nickik on Wednesday March 04, 2020 @07:39AM (#22483206)
Lombok is really not that complex and it not close to using a different language.
Re:New Features in Java 14 by Vax45 on Tuesday March 03, 2020 @10:26PM (#22480958)
I would try out Immutables before Lombok. It generates code using the standard annotation processor instead of modifying OpenJDK's AST tree.