-
Enhancement
-
Resolution: Unresolved
-
P4
-
repo-valhalla
-
None
Lost updates are a practical problem with primitives and will be a practical problem with value types, more so than with object types. Solutions to this problem for primitives need to be carefully cross-applied from primitives to value types, in order to fulfill the promise that value types "work like an int".
A value type constructor creates a new value. A value type reconstructor creates a new value derived by adjusting a previous value. A reconstructor may be a "wither" method analogous to a "setter" method on a stateful object.
Setter methods are usually void returning (sometimes they return 'this'). Wither methods *must* return the updated value, which is distinct from the original value.
Value types "code like a class but work like an int". Ints and other primitives also have constructs which update them, returning a new method.
It is a common programming error to update a value and forget to store the updated value back to the variable which is tracking it. Java prevents this from happening in the case of int and other primitives:
int x = 0
x + 1; // bad code
x = x + 1; // good code
Java does not prevent this from happening with object APIs:
Iterator i = l.iterator();
i.next(); // bad code
x = i.next(); // good code
Java should take care to avoid this class of errors with value types:
Cursor c = Cursor(array, 0, 10);
c.next(); // bad code
c = c.next(); // good code
One simple approach to this problem would be to create some warnings, where value-type reconstructors, if used as expression statements, were diagnosed to the user. We assume that the value returned from a reconstructor is unique, and should not be discarded (at least implicitly).
A stronger approach is to treat discards as errors. This is preferable, because it delivers more "like an int" user experience. We can do this with the first non-preview release of value types, but not later.
The gentler advisory approach could be applied to existing Java APIs and object APIs, using an annotation. Possible spellings: "@NoDiscard", "@Precious". Such proposals have been made before; they are more urgent with values.
This design relates to, but is distinct from, the need for syntax sugar to express updates. "Works like an int" makes us consider whether to abbreviate the value-type analogues of "i += 1" and "i++", which provide various concise combinations of reading a variable, operating on its value, writing an updated value, and returning a related value (either the new or the old value of the variable). See also "a[i++]" which produces two results: It reads, operates, and writes to "i" and also returns a derived value.
Class-like APIs for the int-like usage patterns should be expressible (syntax is just an example):
i=i+1 v+=.increment() OR v.=increment() OR ...
i++ v.increment()++ OR v++.increment() OR ...
a[i++] v.increment()++.get() OR v++.increment().get() OR ...
A value type constructor creates a new value. A value type reconstructor creates a new value derived by adjusting a previous value. A reconstructor may be a "wither" method analogous to a "setter" method on a stateful object.
Setter methods are usually void returning (sometimes they return 'this'). Wither methods *must* return the updated value, which is distinct from the original value.
Value types "code like a class but work like an int". Ints and other primitives also have constructs which update them, returning a new method.
It is a common programming error to update a value and forget to store the updated value back to the variable which is tracking it. Java prevents this from happening in the case of int and other primitives:
int x = 0
x + 1; // bad code
x = x + 1; // good code
Java does not prevent this from happening with object APIs:
Iterator i = l.iterator();
i.next(); // bad code
x = i.next(); // good code
Java should take care to avoid this class of errors with value types:
Cursor c = Cursor(array, 0, 10);
c.next(); // bad code
c = c.next(); // good code
One simple approach to this problem would be to create some warnings, where value-type reconstructors, if used as expression statements, were diagnosed to the user. We assume that the value returned from a reconstructor is unique, and should not be discarded (at least implicitly).
A stronger approach is to treat discards as errors. This is preferable, because it delivers more "like an int" user experience. We can do this with the first non-preview release of value types, but not later.
The gentler advisory approach could be applied to existing Java APIs and object APIs, using an annotation. Possible spellings: "@NoDiscard", "@Precious". Such proposals have been made before; they are more urgent with values.
This design relates to, but is distinct from, the need for syntax sugar to express updates. "Works like an int" makes us consider whether to abbreviate the value-type analogues of "i += 1" and "i++", which provide various concise combinations of reading a variable, operating on its value, writing an updated value, and returning a related value (either the new or the old value of the variable). See also "a[i++]" which produces two results: It reads, operates, and writes to "i" and also returns a derived value.
Class-like APIs for the int-like usage patterns should be expressible (syntax is just an example):
i=i+1 v+=.increment() OR v.=increment() OR ...
i++ v.increment()++ OR v++.increment() OR ...
a[i++] v.increment()++.get() OR v++.increment().get() OR ...
- links to
-
Review(lworld) openjdk/valhalla/1274