While on the subject of defaults: we've been treating B2 as the default kind of non-identity class, on the theory that it is the smallest hop away from identity classes, and also that it covers a broader range (all the existing value-based classes.)  Is that still the default we want?

Flipping that default might make framing the B2/B3 distinction easier: rather than "tolerant of zero", what we'd opt into is "ref only".

<bikeshed>

Pulling farther, there's a bucket-inversion we might be able to pull here, just by moving some terminology around:

    class B1 { }                 // ref only
    value class B3 { }           // ref and val projections
    value-based class B2 { }     // ref only

And then we can apply non-atomic / fragile (or whatever we call it) to either B2 or B3.

This has a few positive properties:

 - Connection to the existing term "value-based", which means "follows the value constraints, but is a ref type", and has the connotation of "approximation of a value class"
 - .val makes sense in the context of a "value class"
 - We get the orthogonality we are seeking, but avoid piling up lots of modifiers (non-atomic zero-happy value class) as well as not having to invent crazy words like "zero-happy"
 - Practical difference between .val and .ref is just about nullity now
 - We get the "must opt into non-atomicity" that Brian has been ranting about

This basically leaves the bucket model intact, with some flipped terminology, but importantly, factors atomicity out of being an implicit bucket property, and instead an explicit global choice.  This is by far the most important aspect of the restack I am pushing.

It is an orthogonal choice as to whether .val or .ref gets the "good" name for value classes.

On the negative side, there is an extra syntactic burden to get to B2 compared to B3 (value-based instead of value) which might cause some developers to reach for it when they might prefer VBC. But if the default for B3 is .ref, it might not matter as much (they're both ref types and you still get integrity), so the only risk is accidental exposure of the zero value.

</bikeshed>

On 5/4/2022 2:27 PM, Kevin Bourrillion wrote:
My favorite kind of thread...

At the risk of inducing groans, a reminder that much of my own terminology backstory is found in Data in Java Programs <https://urldefense.com/v3/__https://docs.google.com/document/d/1J-a_K87P-R3TscD4uW2Qsbt5BlBR_7uX_BekwJ5BLSE/preview__;!!ACWV5N9M2RV99hQ!NPBDak8nHT2gphJA0fD58S9nj9V1-O5xUyBd2nxtpk2hxoVd-9j08O_pZ8jje-dwBjEwf_GjQis3lrdF$>, and that when there are places we disagree below, the disagreement is probably highlighted by something in *that* document first.

Since for all we know it might be out of step with how typical Java devs really think, I'll just mention that it's at least been well-received by reddit <https://urldefense.com/v3/__https://www.reddit.com/r/java/search/?q=*22data*20in*20java*20programs*22__;JSUlJSU!!ACWV5N9M2RV99hQ!NPBDak8nHT2gphJA0fD58S9nj9V1-O5xUyBd2nxtpk2hxoVd-9j08O_pZ8jje-dwBjEwf_GjQo7MMfgr$> twice (if reddit can find something to complain about, they usually do!).


On Wed, May 4, 2022 at 8:05 AM Brian Goetz <brian.go...@oracle.com> wrote:

    Currently, we have primitives and classes/references, where
    primitives have box/wrapper reference companions.  The original
    goal of Bucket 3 was to model primitive/box pairs.  We have
    tentatively been calling these "primitives", but there are good
    arguments why we should not overload this term.

    We have tentatively assigned the phrase "value class" to all
    identity-free classes, but it is also possible we can use value to
    describe what we've been calling primitives, and use something
    else (identity-free, non-identity) to describe the bigger family.

    So, in our search for how to stack the user model, we should bear
    in mind that names that have been tentatively assigned to one
    thing might be a better fit for something else (e.g., the "new
    primitives").  We are looking for:

     - A term for all non-identity classes. (Previously, all classes
    had identity.)


The term applies to the objects first and foremost. The object either has identity or does not.

What *is* identity? I'll claim it's exactly like an ordinary immutable field-based property, with one special provision: it is *always* auto-assigned to be unique, and thus can never be copied. That feels to me like it tells the whole story. So the difference between these kinds of objects is exactly a "with identity" / "without identity" distinction, and as we know from interface naming ("HasFoo"), it is often impossible to turn that into adjective form.

The second complication here is the backward default. *Having* identity is actually the special property! I do think we should lean into that. Part of upgrading your code to be "Java 21-modern" (or whatever) really should be marking all your classes that you really *want* to have identity and letting the rest lose it. The terms that feel right are "identity object" and "class that produces identity objects" shortened to "identity class".

For the most part I think we'll end up talking about "identity classes" and "classes in general", and more rarely needing to refer to "classes without identity" or "non-identity classes". So I think it's okay to let them use "A \ B"-style terminology as I've done here. (I furthermore still think it's okay to have an IdentityObject interface but no ValueObject interface, as the latter doesn't really embody additional client-facing capabilities.)

This is one of at least four examples of backward defaults in the language. We are either stuck with painful/awkward terminology choices in all of them, or we could pursue the idea of letting source files declare their language level, upon which the problem vanishes.

    - A term for what we've been calling atomicity: that instances
    cannot appear to be torn, even when published under race.
    (Previously, all classes had this property.)


I think this term we really need is this one's negation. You never need to (or can) mention it with identity classes; with the rest you can use it to opt into more risk. The English words that come to mind are https://www.thesaurus.com/browse/fragile <https://urldefense.com/v3/__https://www.thesaurus.com/browse/fragile__;!!ACWV5N9M2RV99hQ!NPBDak8nHT2gphJA0fD58S9nj9V1-O5xUyBd2nxtpk2hxoVd-9j08O_pZ8jje-dwBjEwf_GjQjVeQvGq$>.

     - A term for those non-identity classes which do not _require_ a
    reference.  These must have a valid zero, and give rise to two
    types, what we've been calling the "ref" and "val" projections.


I think we need to name the *type* first before the class. Today we have

1. primitive types (the values are the instances)
2. reference types (the values are references to the instances)

But this isn't the *heart* of what it means to be "primitive"; it just happens to be true of primitives so far. And sure, we'll certainly explain all of this *partly* by saying these types are "primitive-LIKE". But what is the quality that they and true primitive types have in common? It's "the values are the instances", so this can either lead to "value type" or go back to "inline/direct/immediate type".

At this moment I like both "value type" and "inline type" well enough. Value *is* overloaded, to be sure, because of "value semantics" (aka why AutoValue is called AutoValue). But the connection is strong enough imho. I can delve deep into this topic if desired.

Then, back to your question, what is the name for a *class* that *also* gives rise to a value type -- a "valuable class"?

     - A term for what we've been calling the "ref" and "val"
    projections.


Note I think we should only invoke the concept of "projection" once we get into type variables. Otherwise we simply have two types for one class. (And the reason for that is very solid / easy to defend, just by appealing to how we'd've preferred int and Integer had worked.) I would just call them the reference type and the (name debated just above) type, simple as that.

    Let's start with _terms_, not _declaration syntax_.


Yes, and even the term we like 2nd best for a thing can still be useful in the documentation of that thing.

--
Kevin Bourrillion | Java Librarian | Google, Inc. |kev...@google.com

Reply via email to