Queries regarding value classes

Julian Waters tanksherman27 at gmail.com
Fri Mar 18 12:01:35 UTC 2022


Hi Remi,

I'm not sure I follow what you're trying to say, my suggestion for records
was to make them value based by default, and ref modifier can then be used
when one wants them to be identity based (While the exact opposite is true
for regular classes, which are always identity by default).

Regarding the change for value classes, my current query is whether

X x = new X(1);
x = new X(3);

can be replaced with

X x = new X(1);
x.a = 3;

when x is not* marked* as final (or const). I do feel that it would be much
less tedious than calling new X() all the time, but this was before I was
aware of Amber's draft for with expressions until someone pointed it out
earlier. I suspect the misunderstanding in the thread is caused by my
confusion of what value classes actually *are*, I'm still having a hard
time figuring out how a reference object cannot be mutated, since to me
it does appear that you can modify the local copy you have, the change just
won't be reflected across other areas with another reference to the object
(Unlike identity objects). Maybe I'm thinking a little too much in the C++
model of classes? Sorry if this is causing anyone any trouble :(

best regards,
Julian

On Fri, Mar 18, 2022 at 5:11 PM Remi Forax <forax at univ-mlv.fr> wrote:

> ----- Original Message -----
> > From: "Julian Waters" <tanksherman27 at gmail.com>
> > To: "Pedro Lamarão" <pedro.lamarao at prodist.com.br>
> > Cc: "valhalla-dev" <valhalla-dev at openjdk.java.net>
> > Sent: Friday, March 18, 2022 3:11:59 AM
> > Subject: Re: Queries regarding value classes
>
> > Hi Pedro,
> >
> > I think you misunderstood me, what I was proposing was for value class X,
> > x.a = 3; would be equivalent to new X(3); internally (*A la* syntactic
> > sugar that could be disabled by being marked final), but it seems Amber
> > already has something related to this, so I'll move the discussion there
> > (Keeping the value by default records and the mark values at site of
> usage
> > here though)
>
> That's interesting !
>
> Let's use "const" instead of "final", because "final" has another meaning.
>
> You are proposing that if a local variable is tagged with const, then the
> compiler will rewrite
>   const Point point = new Point();
>   point.x = 3;
>
> to
>    Point point = new Point();
>    point = new Point(3, point.y);
>
> This is a transformation is similar to the one done by the compiler inside
> a constructor of a value class
>   class Point {
>     Point(int x, int y) {
>       this.x = x;
>       this.y = y;
>     }
>   }
>
> is rewritten to
>   class Point {
>     static Point <new>(int x, int y) {
>       Point point = Point.default;
>       point = _with_field_x(point, x);
>       point = _with_field_y(point, y);
>       return point;
>     }
>   }
>
> As you can see, the transformation not only rewrite the field assignments
> to use with_field but it also changes the signature of the containing
> method,
> a constructor returns void while a <new> factory method returns the type
> of the object.
>
> So either your proposal is only about the content of a method, but in my
> opinion it's like adding syntactic sugar for the sake of adding syntactic
> sugar or you also want to do cross method rewriting but it means
> introducing a new kind of methods which lead us right into the colored
> function problem [1] (and the magic will also break when using reflection).
>
> When we have introduced records, we have debated on the different ways to
> introduce a "with" operator, something like
>   point = Point.__with__ { x = 3; }   // this is more or less the C#
> syntax, not a syntax proposal!
>
> Sooner this month i've done a presentation of Loom and at the end two
> different persons ask me about either having a with syntax for records or
> having withers (setter that create a new object) added to the record class).
>
> Julian, correct me if i'm wrong but is it not what you want ? a "with"
> syntax (whatever it's form) on a record (and value record) ?
>
> >
> > best regards,
> > Julian
>
> regards,
> Rémi
>
> [1]
> https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
>
> >
> > On Fri, Mar 18, 2022 at 2:07 AM Pedro Lamarão <
> pedro.lamarao at prodist.com.br>
> > wrote:
> >
> >> My two cents.
> >> It may seem at first that doing something like this:
> >>
> >> X x = new X(1)
> >> x.a = 3
> >>
> >> is very useful, but, that is an artifact of the implementation.
> >> Because creating a new object in the heap has a cost, we would rather
> set
> >> its fields directly to avoid this cost.
> >> But if X is a value class, doing the below should have no such cost (in
> >> favourable circumstances):
> >>
> >> X x = new X(1)
> >> x = new X(3)
> >>
> >> Atte.
> >> Pedro.
> >>
> >> Em qua., 16 de mar. de 2022 às 23:05, Julian Waters <
> >> tanksherman27 at gmail.com> escreveu:
> >>
> >>> Alternatively, something like
> >>>
> >>> X x = new X(1);
> >>> x.a = 3;
> >>>
> >>> could be valid while
> >>>
> >>> final X x = new X(1);
> >>> x.a = 3;
> >>>
> >>> would not?
> >>>
> >>> best regards,
> >>> Julian
> >>>
> >>> On Tue, Mar 15, 2022 at 11:12 AM Julian Waters <
> tanksherman27 at gmail.com>
> >>> wrote:
> >>>
> >>> > So if I understand correctly, value objects are essentially the same
> as
> >>> > JEP-401's primitives but with nullability, and according to JEP-401,
> >>> > guarantee of atomic modification?
> >>> >
> >>> > "you are saying "change the a field of the object referred to by x to
> >>> 3.""
> >>> >
> >>> > Regarding this earlier x.a = 3 example, if X was a good ol' identity
> >>> > object, x would then be a reference to the actual instance, and we'd
> >>> simply
> >>> > follow the reference to where the actual object is stored and set a
> to
> >>> 3.
> >>> > But if it was a value object, my understanding from your previous
> post
> >>> is
> >>> > that it would be stored directly on the abstract (Ignoring HotSpot's
> >>> actual
> >>> > complex implementation) stack to be operated on as a bunch of fields
> >>> with
> >>> > no additional metadata other than the check for null. What's
> stopping us
> >>> > from then changing those fields directly? Like Quân Anh mentioned
> >>> earlier,
> >>> > we would've effectively created a new object if we did do that,
> since a
> >>> > value object has no identity, but wouldn't we have technically
> changed
> >>> the
> >>> > value of a after initialization? At the very least, I'd say it would
> be
> >>> > useful syntactic sugar to be able to do x.a on a value object
> instead of
> >>> > having to do new X(3); every time we wanted to change it, unless a is
> >>> > explicitly marked as final, without affecting == or related checks in
> >>> any
> >>> > way, since (from what I know) value objects are compared by field
> with
> >>> ==.
> >>> >
> >>> > Apologies for my lack of knowledge in this area, it still feels like
> I
> >>> > haven't really gotten a correct idea of what value types really are,
> >>> > especially compared to the true primitives of 401
> >>> >
> >>> > Thanks for the reply and have a great day!
> >>> >
> >>> > best regards,
> >>> > Julian
> >>> >
> >>> > On Tue, Mar 15, 2022 at 5:59 AM Brian Goetz <brian.goetz at oracle.com>
> >>> > wrote:
> >>> >
> >>> >> You are (understandably) conflating the properties of identity with
> the
> >>> >> properties of reference-ness.
> >>> >>
> >>> >> If you say
> >>> >>
> >>> >>     x.a = 3
> >>> >>
> >>> >> you are saying "change the a field of the object referred to by x to
> >>> 3."
> >>> >> The key to this sentence is *the object*; in order for assignment to
> >>> make
> >>> >> sense, you have to know exactly which variable you are talking
> about.
> >>> And
> >>> >> if that variable is an instance field, then you have to know exactly
> >>> which
> >>> >> object it lives in.  This is where identity comes in; if x is a
> >>> reference
> >>> >> to an identity object, we then know how to find it.  Which means,
> you
> >>> need
> >>> >> an identity in order to be able to talk about mutability in a
> >>> well-defined
> >>> >> way.
> >>> >>
> >>> >> So if that's true, what is a *reference* to a value?  This is the
> >>> >> confusing part.  If you think in terms of implementation, you'll
> >>> probably
> >>> >> think "reference means pointer", which puts you into a C frame of
> mind,
> >>> >> because pointers always point at things.  But that's not what
> reference
> >>> >> means in Java; its a more abstract kind of indirection.
> >>> >>
> >>> >> The distinction between int and Integer may be helpful.  At one
> level,
> >>> >> int and Integer may seem like "almost the same sets of values"; the
> >>> Integer
> >>> >> value set has one more value -- null -- than the int value set, and
> for
> >>> >> each of the other values, there is a bidirectional, 1:1 mapping
> >>> between the
> >>> >> two value sets.  But if we look closer, in fact these value sets are
> >>> >> disjoint!  An int is not an Integer (even if they describe the same
> >>> >> number.)
> >>> >>
> >>> >> So one big difference between references and values is nullability;
> >>> null
> >>> >> is a special kind of reference, the reference to no object at all.
> >>> >> Reference types can be null; primitive types cannot.  (There's
> another,
> >>> >> even more subtle distinction, which is tearability, which comes from
> >>> the
> >>> >> guarantees of the Java memory model.)
> >>> >>
> >>> >> If we have a value class:
> >>> >>
> >>> >>     value class X { }
> >>> >>
> >>> >> this gives rise to a reference type X, whose values are references
> to
> >>> >> instances of X.  But those instances do not have identity, which
> means
> >>> we
> >>> >> can freely shred an X into the values of its fields, and later
> >>> reconstitute
> >>> >> it into a new X, all without anyone noticing.  That's what the lack
> of
> >>> >> identity enables.  But the flip side of that means that any given X
> >>> does
> >>> >> not "live" anywhere; it is just a loose aggregation field values,
> which
> >>> >> behaves like an object when called upon to do object-y things.
> >>> >>
> >>> >>
> >>> >>
> >>> >>
> >>> >>
> >>> >> On 3/13/2022 5:46 AM, Julian Waters wrote:
> >>> >>
> >>> >> Hi Quân Anh, thanks for the reply,
> >>> >>
> >>> >> I think I understand what you mean; Since value objects have no
> >>> identity,
> >>> >> changing their fields would essentially mean the object is now
> entirely
> >>> >> different. However since that's the case, I'm still a little
> confused
> >>> by
> >>> >> the semantics of what they really are. Specifically, most of their
> >>> benefits
> >>> >> are centered around them being nothing more than their fields in
> >>> memory,
> >>> >> but at the same time documentation states that they're referred to
> by
> >>> >> reference, which I find a little contradictory. If it's the former,
> >>> they'd
> >>> >> be no different from primitives, and if the latter, they'd be the
> exact
> >>> >> same as identity objects, which has left me puzzled for quite some
> >>> time.
> >>> >>
> >>> >> Sorry for all the trouble, have a great day
> >>> >>
> >>> >> best regards,
> >>> >> Julian
> >>> >>
> >>> >> On Sun, Mar 13, 2022 at 4:26 PM Quân Anh Mai <anhmdq at gmail.com> <
> >>> anhmdq at gmail.com> wrote:
> >>> >>
> >>> >>
> >>> >> Hi,
> >>> >>
> >>> >> Regarding your concern of mutable value objects, having a mutable
> >>> >> identity-less object is illogical. Because a value class does not
> have
> >>> a
> >>> >> unique identity, upon modification, the object is changed to become
> >>> another
> >>> >> object. A value object is immutable in the same way that an int is
> >>> >> immutable. You can change a variable int a from containing a value
> of 3
> >>> >> to a value of 4, but you can’t change the number itself, it has been
> >>> >> mathematically and programmatically defined to be a specific bit
> >>> sequence.
> >>> >> Similarly, you can change a variable Point a from enclosing the
> point
> >>> (3,
> >>> >> 4) into the point (2, 5), but you can’t change the coordination of
> the
> >>> >> points themselves, they have been (in this case) also mathematically
> >>> >> defined. Your understanding of how value classes work is also not
> >>> correct.
> >>> >> The fact that a value object can be deconstructed to its fields does
> >>> not
> >>> >> mean that it will. This is simply an optimisation choice of the
> >>> compiler.
> >>> >>
> >>> >> Regards,
> >>> >> Quan Anh
> >>> >>
> >>> >> On Sun, 13 Mar 2022 at 15:42, Julian Waters <
> tanksherman27 at gmail.com>
> >>> <tanksherman27 at gmail.com>
> >>> >> wrote:
> >>> >>
> >>> >>
> >>> >> Hi all,
> >>> >>
> >>> >> I'd like to discuss several topics related to the current draft on
> >>> value
> >>> >> classes.
> >>> >>
> >>> >> As mentioned in another post to this list at
> >>> >>
> >>>
> https://mail.openjdk.java.net/pipermail/valhalla-dev/2022-January/009871.html
> >>> >> ,
> >>> >> currently value classes are specified as immutable, with all fields
> >>> being
> >>> >> declared as final. If I understand this correctly, value based
> classes,
> >>> >> unlike the true primitives which work is currently focused on, can
> >>> still
> >>> >> be
> >>> >> referred to by references; It is only identity that has been given
> up.
> >>> In
> >>> >> that instance, naively speaking, wouldn't it be possible for value
> >>> objects
> >>> >> to have mutable fields? In the same way that one can reference the
> >>> fields,
> >>> >> one might possibly be able to also change their values through the
> >>> >> available object reference as well. From what I can tell, value
> objects
> >>> >> are
> >>> >> planned to work internally by decomposing them to nothing more than
> >>> their
> >>> >> constituent fields and reconstructing them elsewhere. If that is the
> >>> case,
> >>> >> shouldn't modification of their fields be possible? To me it seems
> the
> >>> >> modification would simply modify the copied value object *b *while
> >>> leaving
> >>> >> original value object *a *unchanged, which sits perfectly with the
> >>> >> constraint that identity should not be supported. Am I mistaken in
> my
> >>> >> assumption?
> >>> >>
> >>> >> Additionally, if the above holds true, I also suggest allowing an
> >>> object
> >>> >> to
> >>> >> be declared as value based at the site of their usage, instead of
> just
> >>> at
> >>> >> their definition. Something like
> >>> >>
> >>> >> // Item is by default an identity class, but the field "item" here
> is
> >>> now
> >>> >> // a value object due to the declaration of value
> >>> >> value Item item = new Item();
> >>> >>
> >>> >> would allow typical identity classes to be treated as value objects
> >>> where
> >>> >> they're used. This would, to me, present a great deal of
> flexibility as
> >>> >> one
> >>> >> could then choose how to allocate a particular object without
> >>> >> constraining *every
> >>> >> *instance of that class to a specific value/identity dichotomy, and
> >>> also
> >>> >> avoids the hassle of having to know which classes should be value or
> >>> >> identity types ahead of time. On a side note, the current proposal
> also
> >>> >> includes the ability to mark records as value based, given that
> records
> >>> >> are
> >>> >> meant exclusively as data classes, I suggest we flip that around and
> >>> >> instead have records as *value based by default, *and instead allow
> >>> >> marking
> >>> >> them as identity objects explicitly if required, with the currently
> >>> used
> >>> >> ref keyword (Or whatever ref will eventually become), both at
> >>> definition
> >>> >> and when an actual instance is constructed, as mentioned above. This
> >>> could
> >>> >> save frustration from having to type value over and over whenever
> >>> writing
> >>> >> the definition of a new record.
> >>> >>
> >>> >> Have a great day, hope I can hear your opinions on this! :)
> >>> >>
> >>> >> best regards,
> >>> >> Julian
> >>> >>
> >>> >>
> >>> >>
> >>> >>
> >>>
> >>
> >>
> >> --
> >> Pedro Lamarão
> >> https://www.prodist.com.br
> >> Securing Critical Systems
> >> Tel: +55 11 4380-6585
> >>
> >> Antes de imprimir esta mensagem e seus anexos, certifique-se que seja
> >> realmente necessário.
> >> Proteger o meio ambiente é nosso dever.
> >> Before printing this e-mail or attachments, be sure it is necessary.
> >> It is in our hands to protect the environment.
>



More information about the valhalla-dev mailing list