Default value for date/time
John Rose
john.r.rose at oracle.com
Wed May 9 00:13:55 UTC 2018
On May 8, 2018, at 4:54 PM, Stephen Colebourne <scolebourne at joda.org> wrote:
>
> On 8 May 2018 at 00:55, John Rose <john.r.rose at oracle.com> wrote:
>> - make all-zero LD return "LocalDate.default" for toString
>> - make all-zero LD throw DefaultValueException for all other access methods
>
> Isn't this just null under a different name? (Adding a second kind of
> null is deeply unappealing.)
No, defaults are type-specific values. What I'm showing you is
how you can make your primitive-like type (value LD) work
more backward-compatibly with your old type (VBC LD).
> If so, then saying that LocalDate.default (all zeros) == null doesn't
> seem terrible. ie. value types could opt in to letting the all zero
> bits be called null.
Allowing some value types to pretend to be null and others not
is also terrible. The least terrible thing is to make a clean break
with null, and not let any value type be confused with null, ever.
Then, if you want, you build as much null-like behavior, or as little,
as your type needs.
> BTW, a tangential question. Is the JVM going to guarantee that there
> never exists an invalid set of bits for a value type? For example,
> LocalDate would want to prevent the month field being 13, but I've
> seen no discussion of a validateBits() method for value types.
"codes like a class, works like an int"
Coding like a class means that it has a constructor which is in
control of all field values. So, yes, the JVM guarantees this.
The trade-off is the JVM specifies a no-args constructor for
you with all-default field values. Your class needs to accept
this and assign and document the behavior as needed.
For numeric and algebraic types, the default value is likely
to be some kind of zero or null or monoid identity, if you
play your cards right. You don't get to *not* play your cards.
> On 8 May 2018 at 00:47, John Rose <john.r.rose at oracle.com> wrote:
>> Nope, null is a reference, and is not any kind of value.
>> Our key principle is "codes like a class, works like an int."
>
> From my perspective, the key point here is that LocalDate isn't like
> int. Its not numeric, it doesn't have a sensible default.
Then you want DefaultValueExceptions for access methods.
> I worry that while the key principle has got the project a long way,
> it is too hard line when it comes to some potential value types -
> Currency or Money being other examples where a default is silly, but
> they are otherwise fully value-like.
Any value type measuring a scaled amount is going to have a
zero right? That's the default, probably. It's affine amounts
like times that don't have a good default.
>
>>> throws an exception? (ie. the default can't be observed)
>>
>> "Works like an int" means there is always an observable
>> default. Making defaults unobservable is not "like an int",
>> and is not a project we want to undertake either.
>
> Maybe this could be at the javac level, not the JVM level? (Just
> exploring ideas) ie. javac could arrange itself such that if code
> tried to observe a default a DefaultValueObservationException is
> thrown. This need for this guard should be rare.
Nope. Java arrays and Java object fields come pre-filled with
the default of their type. That's why we force you, the value type
writer, to assign a meaning (even if it is exceptional) to the
unique default value of your type.
In most cases, this will be more useful than the null pointer
default value you get for an object reference. You can run
methods on it immediately.
>
>> Also, the default value of Optional very cleanly boils down to empty,
>> since the reference is null (and/or any extra boolean would be false).
>> In the case of Optional we'd want the default value to play a very
>> definite role in the API.
>
> Is there a list of situations where the default can be observed? This
> comment suggests an intention that use of Optional could observe the
> default value (I don't see how myself as the API methods shouldn't
> allow it).
class ObserveTheDefault {
LocalDateValue x;
LocalDateValue[] a = new LocalDateValue[1];
void test() {
System.out.println(x);
assert(LocalDateValue.default.equals(x));
System.out.println(a[0]);
assert(LocalDateValue.default.equals(a[0]));
}
public static void main(String… av) { new ObserveTheDefault().test(); }
}
One thing that "working like an int" means is you can
create a variable in the heap (field or array element).
What will the value of this field or element be? The default.
That's why you've gotta play that part of the game when
you code a value type.
There are ways to try to wiggle out of this trap, but they all
lead to worse places. If you try to say, "uninitialized variables
cannot be read", then you are signing up for a read barrier
on all value type reads, with a ValueNotVisibleException.
That's not "like an int", is it? Part of the contract of being
an int or any value type is designating a default value.
Moreover, the JVM designates for you the field values
of this default.
— John
More information about the valhalla-dev
mailing list