Saturday, August 3, 2019

Project Valhalla Eclairs

Éclairs offer several appealing characteristics and have been described as a "trifecta" that "encompass[es] the trinity of pastry, a light and crispy shell, a silky creamy filling and intense chocolate glaze." In the OpenJDK valhalla-spec-experts mailing list, Brian Goetz's post "Collapsing the requirements" proposes the concept of Valhalla "Eclairs" and discusses how use of these "eclairs" in Valhalla can provide their own trifecta of removing the need for LV in the VM ("LPoint/QPoint distinction" or boxed projection versus unboxed projection or "LV is the null-adjunction of QV"), removing the need for V? in the language, and removing the need for null default values.

Goetz's "Summary" in the "Collapsing the requirements" summarizes the value of the proposed Valhalla eclairs and succinctly states what the proposed "eclairs" concept is (I have added the emphasis), "In one swoop, we can banish LV from the VM, V? from the language, and null-default values, by making a simple requirement: every value type is paired with an interface or abstract class 'box'. For most values, this can be automatically generated by the compiler and denoted via a well-known name (e.g., V.Box); for some values, such as those that are migrated from reference types, we can explicitly declare the box type and pick explicit names for both types."

Goetz provides more details and examples in the "Collapsing the requirements" post of "requiring that every value type have a companion interface (or abstract class) supertype." He also provides a more formal definition:

Define an envelope-class pair ("eclair") as a pair (V, I) such that:
  • V is an inline class
  • I is a sealed type
  • I permits V (and only V)
  • V <: I

Several other Goetz statements in the "Collapsing the requirements" post highlight desirable features of these proposed Valhalla eclairs and here is a sample:

  • "If every value type be a member of an eclair, we can use V when we want the flattenable, non-nullable, specializable type; and we use I when we want the non-flattenable, nullable, erased 'box'. We don’t need to denote `V?`; we can just use I, which is an ordinary, nominal type."
  • "Now, the type formerly known as `V?` is an ordinary, nominal interface (or abstract class) type. The user can say what they mean, and no magic is needed by either the language or the VM."
  • "Using the eclair wrapper also kicks the problem of erased generics down the road; if we use `Foo<I>` for erased generics, and temporarily ban `Foo<V>`, when we get to specialized generics, it will be obvious what `Foo<V>` means (their common super type will be `Foo<? extends I>`). This is a less confusing world, as then 'List of erased V' and 'List of specialized V' don’t coexist; there’s only 'List of V' and 'List of V’s Box'."

One last aspect of the "Collapsing the requirements" post that I want to highlight here is the proposal to "define a new public value class `Opt<T>` which is the value half of the eclair, and the existing Optional is the interface/abstract class half." Goetz explains that the new value class Opt is needed as a compromise (rather than adapting existing reference class Optional to be the inside of the eclair) because "existing variables of type Optional are not flattened" when today's Optional is migrated to an eclair.

Although it is a bit of a compromise to have to know, use, and differentiate another type Opt from Optional, one of the advantages of having Opt be the value portion of the eclair and having Optional be the interface/supertype portion of the eclair (and the support of boxing conversion between them) is that there is a relatively straightforward migration path between today's use of Optional and tomorrow's use of Opt. As Goetz puts it, "existing fields / arrays can migrate gradually to Opt, as they want the benefit of flattening; existing APIs can continue to truck in Optional." Goetz summarizes the migration benefit and cost of the Opt approach: "Users can migrate their fields gradually. The cost: the good name gets burned. But there is a compatible migration path from ref to value."

It's a bit disappointing to need to use "Opt" instead of "Optional", but I think most Java developers could quickly become used to applying Opt when it's available and its advantages are identified. Today's powerful Java IDEs could also identify places where existing Optional usage can be changed to Opt and warn the developer when he or she tried to introduce an Optional reference class when an Opt value class could be used.

Eclairs are tasty, tempting treats and the proposed Valhalla "eclairs" have some tempting characteristics of their own.

No comments: