Re: immutibility

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
48 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 18 March 2010 17:55, Bert Freudenberg <[hidden email]> wrote:

> On 18.03.2010, at 16:45, Igor Stasenko wrote:
>>
>> On 18 March 2010 17:23, Bert Freudenberg <[hidden email]> wrote:
>>> On 18.03.2010, at 15:51, Colin Putney wrote:
>>>>
>>>>
>>>> On 2010-03-18, at 5:39 AM, Bert Freudenberg wrote:
>>>>
>>>>> HO there should be no way to reset the immutable flag. You can implement "soft" immutability in the image, but "hard" VM-level immutability needs to be permanent, no fiddling possible. Once set, the object stays immutable. Only a copy of an immutable object will be mutable again.
>>>>
>>>> This would be good for some use cases - literals, for example, but not so good for others. One of the common uses of "immutability" is not so much to *prevent* mutation, as to control it: databases, concurrency etc. Do you have another feature in mind for these cases, or some overriding interest in immutable immutability that you want to pursue?
>>>>
>>>> Colin
>>>
>>>
>>> Seems to me like two separate issues - one being informed of modifications, and one preventing modifications. Immutability to me means the latter. The former is more like a write barrier.
>>>
>> Right! And for OODBs first is sufficient.
>>
>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>
>> I don't sharing your optimism, based on immutability.
>> You can't run away from the fact that computing is the way of
>> transforming data from one form into another.
>> So, somewhere, either in language or at VM level, you have to mutate
>> the state of data, otherwise you can't do much.
>
> Free advice of the day: don't ever get near a convention of functional programmers ;)
>
It is good to use a universal approach in modelling the universe.
And as to me, 'everything is an object' is more universal than
'everything is a function' ;)

> - Bert -
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Eliot Miranda-2
In reply to this post by Bert Freudenberg


On Thu, Mar 18, 2010 at 8:23 AM, Bert Freudenberg <[hidden email]> wrote:
On 18.03.2010, at 15:51, Colin Putney wrote:
>
>
> On 2010-03-18, at 5:39 AM, Bert Freudenberg wrote:
>
>> HO there should be no way to reset the immutable flag. You can implement "soft" immutability in the image, but "hard" VM-level immutability needs to be permanent, no fiddling possible. Once set, the object stays immutable. Only a copy of an immutable object will be mutable again.
>
> This would be good for some use cases - literals, for example, but not so good for others. One of the common uses of "immutability" is not so much to *prevent* mutation, as to control it: databases, concurrency etc. Do you have another feature in mind for these cases, or some overriding interest in immutable immutability that you want to pursue?
>
> Colin


Seems to me like two separate issues - one being informed of modifications, and one preventing modifications. Immutability to me means the latter. The former is more like a write barrier.

With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.

But the same VM support can allow both styles.  The VM support is a per-object bit that marks an object as immutable along with modifications to inst var assign and at:put: primitives to check for the immutability bit, and a pair of primitives to fetch and set the per-object isImmutable flag.    If the primitive to set immutablity is removed and replaced with a primitive that can only enable immutability, or if use of the primitive is suitably restricted then one can prevent clearing of the flag.  The VM is the same in oth cases; it simply has to check for the immtability flag on each write, but above that one can use this as a write-barrier or to implement "true" immutability.

Note that the cost of checking immutability on each write is quite small in the at:put: primitives because these must fetch the object header containing an object's size to do bounds checking, and testing a bit in a register containng the header merely adds a register operation not a more expensive read.  It does add to the cost of inst var write, but again the overhead is not that large because inst var write also involves the GC's write barrier.  So overall the performance impact is in my experience (VW & Newspeak) < 5% overall speed decrease for macro benchmarks.

- Bert -





Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Brent Pinkney-2
In reply to this post by Bert Freudenberg
Ahoy,

I would like to contribute to this thread by explaining a problem that occurs often in telecommunications and logistics.

It is common to have planning tools that allow the user to 'fork' the master view of the 'domain model' and make local changes to
explore "what ifs". Alas. the domain model is a directed graph of many thousands of instances, born of hundreds of classes, so
duplicating all of this is not feasible.

I have always wanted an object mechanism to detect 'copy of write', so that I might slay this pesky problem. If I had "OCOW"
(Object Copy on Write), I could let the happy users work on the master object graph and manage the small portion that was changed
by an such user experimentation. Obviously, there would need to be a nice exceptions or dependencies to wrap all this.


My question (I really do not know) then is: does immutability, as proposed in this thread, help ?

Brent

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Eliot Miranda-2


On Thu, Mar 18, 2010 at 10:11 AM, Brent Pinkney <[hidden email]> wrote:
Ahoy,

I would like to contribute to this thread by explaining a problem that occurs often in telecommunications and logistics.

It is common to have planning tools that allow the user to 'fork' the master view of the 'domain model' and make local changes to
explore "what ifs". Alas. the domain model is a directed graph of many thousands of instances, born of hundreds of classes, so
duplicating all of this is not feasible.

I have always wanted an object mechanism to detect 'copy of write', so that I might slay this pesky problem. If I had "OCOW"
(Object Copy on Write), I could let the happy users work on the master object graph and manage the small portion that was changed
by an such user experimentation. Obviously, there would need to be a nice exceptions or dependencies to wrap all this.


My question (I really do not know) then is: does immutability, as proposed in this thread, help ?

Yes.  For example take Alan Knight's GLORP framework which does object-relaitonal mapping.  How does one maintain the set of changed objects and the changes?  Mark the set of objects uploaded from the DB as immutable.  As each is first written to, trap the exception, take a shallow copy of the object and enter it into a dictionary mapping modified object to unmodified copy.  At commit time the modified objects are the keys in the dictionary and what slots have been modified can be found by comparing the unmodified copy with the modified current object.  The use of immutability here is an extremely beneficial optimization.  It avoids work, depending on what the base implementation is, e.g.

- avoids having to compare the entire object graph with the state of the database to discover differences
- avoids having to take a copy of the data set uploaded from the database (makes copying lazy)

cheers
Eliot


Brent




Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
In reply to this post by Brent Pinkney-2
On 18 March 2010 19:11, Brent Pinkney <[hidden email]> wrote:

> Ahoy,
>
> I would like to contribute to this thread by explaining a problem that occurs often in telecommunications and logistics.
>
> It is common to have planning tools that allow the user to 'fork' the master view of the 'domain model' and make local changes to
> explore "what ifs". Alas. the domain model is a directed graph of many thousands of instances, born of hundreds of classes, so
> duplicating all of this is not feasible.
>
> I have always wanted an object mechanism to detect 'copy of write', so that I might slay this pesky problem. If I had "OCOW"
> (Object Copy on Write), I could let the happy users work on the master object graph and manage the small portion that was changed
> by an such user experimentation. Obviously, there would need to be a nice exceptions or dependencies to wrap all this.
>
>
> My question (I really do not know) then is: does immutability, as proposed in this thread, help ?
>
I saw a paper which addressing exactly this problem, as well as an
implementation.
If i'm not mistaken, Lucas Renggli wrote it.

> Brent
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

jgfoster
In reply to this post by Eliot Miranda-2
On Mar 18, 2010, at 9:19 AM, Eliot Miranda wrote:

On Thu, Mar 18, 2010 at 8:17 AM, James Foster <[hidden email]> wrote:
On Mar 17, 2010, at 11:28 PM, Igor Stasenko wrote:

> the above is an example when object, recorded as an immutable one,
> then mutated outside a DB transaction. So db can't capture the attempt
> to modify it. What GemStone doing to handle this?

Actually, GemStone traps object modification at the byte-code level in the VM so does not rely on immutability to be informed of a modification.

Not preferrentially.  It used to do that, but it is a problematic approach.  The preferred implementation is above VM-supported per-object immutability.  We've recently discussed this topic, I think on the Pharo list.  Martin McClure of GemStone wrote excellent posts describing the implementations, their trade offs, and the higher levels of the framework which support installing managers for the immutability exception that supports multiple frameworks using immutability concurrently.

Sorry. I was discussing GemStone's server VM, not the replication/proxy activity in a client Smalltalk remote from GemStone (such as GBS in VW).

James


Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bryce Kampjes
In reply to this post by Bert Freudenberg
On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:

> On 18.03.2010, at 16:30, Ralph Johnson wrote:
> >
> > On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
> >
> >> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
> >
> > I've developed in a mixed object/functional style for years, and I
> > think a lot of other people do, too.   You don't need language support
> > for this, though I expect it would be helpful.  It makes concurrency
> > and distributed programming easier, and is important when you are
> > dealing with databases.  Eric Evans calls this "Value Object" in his
> > book "Domain Driven Design".
> >
> > -Ralph Johnson
>
> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.

Even perfectly VM enforced immutability isn't enough to allow
optimisation if you still allow become:. It's always possible to swap
out the immutable object with a different one via become:.

Bryce


Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 30.03.2010, at 11:45, Bryce Kampjes wrote:

>
> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>
>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>
>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>
>>> I've developed in a mixed object/functional style for years, and I
>>> think a lot of other people do, too.   You don't need language support
>>> for this, though I expect it would be helpful.  It makes concurrency
>>> and distributed programming easier, and is important when you are
>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>> book "Domain Driven Design".
>>>
>>> -Ralph Johnson
>>
>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>
> Even perfectly VM enforced immutability isn't enough to allow
> optimisation if you still allow become:. It's always possible to swap
> out the immutable object with a different one via become:.

It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):

a := Array with: A new.
b := Array with: B new beImmutable.
c := (Array with: C new) beImmutable.
a first become: b first. "a points to the immutable B instance, b to the A instance".
a first become: c first. "both a and c now point to the immutable C instance"

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:

> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>
>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>
>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>
>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>
>>>> I've developed in a mixed object/functional style for years, and I
>>>> think a lot of other people do, too.   You don't need language support
>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>> and distributed programming easier, and is important when you are
>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>> book "Domain Driven Design".
>>>>
>>>> -Ralph Johnson
>>>
>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>
>> Even perfectly VM enforced immutability isn't enough to allow
>> optimisation if you still allow become:. It's always possible to swap
>> out the immutable object with a different one via become:.
>
> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>
> a := Array with: A new.
> b := Array with: B new beImmutable.
> c := (Array with: C new) beImmutable.
> a first become: b first. "a points to the immutable B instance, b to the A instance".
> a first become: c first. "both a and c now point to the immutable C instance"
>

one of the problem with #become:/becomeForward: that it should swap
all of existing references atomically.
Now imagine that while walking the heap, it replaced a 50% of
references to given object, and then discoreved that it
needs to swap a reference held by immutable object.
Now, what you suppose to do? Revert all changes and fail primitive?
Ignore this object (do not alter it references) and continue?
Or, before doing the real swapping, scan the heap and check all object
to make sure that none of them are immutable and so, #become will work
ok?


> - Bert -
>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 15:03, Igor Stasenko wrote:

>
> On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:
>> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>>
>>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>>
>>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>>
>>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>>
>>>>> I've developed in a mixed object/functional style for years, and I
>>>>> think a lot of other people do, too.   You don't need language support
>>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>>> and distributed programming easier, and is important when you are
>>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>>> book "Domain Driven Design".
>>>>>
>>>>> -Ralph Johnson
>>>>
>>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>>
>>> Even perfectly VM enforced immutability isn't enough to allow
>>> optimisation if you still allow become:. It's always possible to swap
>>> out the immutable object with a different one via become:.
>>
>> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>>
>> a := Array with: A new.
>> b := Array with: B new beImmutable.
>> c := (Array with: C new) beImmutable.
>> a first become: b first. "a points to the immutable B instance, b to the A instance".
>> a first become: c first. "both a and c now point to the immutable C instance"
>>
>
> one of the problem with #become:/becomeForward: that it should swap
> all of existing references atomically.
> Now imagine that while walking the heap, it replaced a 50% of
> references to given object, and then discoreved that it
> needs to swap a reference held by immutable object.
> Now, what you suppose to do? Revert all changes and fail primitive?
> Ignore this object (do not alter it references) and continue?
> Or, before doing the real swapping, scan the heap and check all object
> to make sure that none of them are immutable and so, #become will work
> ok?

Just ignore all writes into immutable objects (that is, in the become code, do not insert a forwarding block), otherwise proceed as usual.

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 31 March 2010 16:07, Bert Freudenberg <[hidden email]> wrote:

> On 31.03.2010, at 15:03, Igor Stasenko wrote:
>>
>> On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:
>>> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>>>
>>>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>>>
>>>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>>>
>>>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>>>
>>>>>> I've developed in a mixed object/functional style for years, and I
>>>>>> think a lot of other people do, too.   You don't need language support
>>>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>>>> and distributed programming easier, and is important when you are
>>>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>>>> book "Domain Driven Design".
>>>>>>
>>>>>> -Ralph Johnson
>>>>>
>>>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>>>
>>>> Even perfectly VM enforced immutability isn't enough to allow
>>>> optimisation if you still allow become:. It's always possible to swap
>>>> out the immutable object with a different one via become:.
>>>
>>> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>>>
>>> a := Array with: A new.
>>> b := Array with: B new beImmutable.
>>> c := (Array with: C new) beImmutable.
>>> a first become: b first. "a points to the immutable B instance, b to the A instance".
>>> a first become: c first. "both a and c now point to the immutable C instance"
>>>
>>
>> one of the problem with #become:/becomeForward: that it should swap
>> all of existing references atomically.
>> Now imagine that while walking the heap, it replaced a 50% of
>> references to given object, and then discoreved that it
>> needs to swap a reference held by immutable object.
>> Now, what you suppose to do? Revert all changes and fail primitive?
>> Ignore this object (do not alter it references) and continue?
>> Or, before doing the real swapping, scan the heap and check all object
>> to make sure that none of them are immutable and so, #become will work
>> ok?
>
> Just ignore all writes into immutable objects (that is, in the become code, do not insert a forwarding block), otherwise proceed as usual.
>
But such semantics is no longer can be treated as #become (or #becomeForward),
because you leaving a references to old object instead of uniformly
replacing them with swapped one.

> - Bert -
>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 16:10, Igor Stasenko wrote:

>
> On 31 March 2010 16:07, Bert Freudenberg <[hidden email]> wrote:
>> On 31.03.2010, at 15:03, Igor Stasenko wrote:
>>>
>>> On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:
>>>> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>>>>
>>>>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>>>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>>>>
>>>>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>>>>
>>>>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>>>>
>>>>>>> I've developed in a mixed object/functional style for years, and I
>>>>>>> think a lot of other people do, too.   You don't need language support
>>>>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>>>>> and distributed programming easier, and is important when you are
>>>>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>>>>> book "Domain Driven Design".
>>>>>>>
>>>>>>> -Ralph Johnson
>>>>>>
>>>>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>>>>
>>>>> Even perfectly VM enforced immutability isn't enough to allow
>>>>> optimisation if you still allow become:. It's always possible to swap
>>>>> out the immutable object with a different one via become:.
>>>>
>>>> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>>>>
>>>> a := Array with: A new.
>>>> b := Array with: B new beImmutable.
>>>> c := (Array with: C new) beImmutable.
>>>> a first become: b first. "a points to the immutable B instance, b to the A instance".
>>>> a first become: c first. "both a and c now point to the immutable C instance"
>>>>
>>>
>>> one of the problem with #become:/becomeForward: that it should swap
>>> all of existing references atomically.
>>> Now imagine that while walking the heap, it replaced a 50% of
>>> references to given object, and then discoreved that it
>>> needs to swap a reference held by immutable object.
>>> Now, what you suppose to do? Revert all changes and fail primitive?
>>> Ignore this object (do not alter it references) and continue?
>>> Or, before doing the real swapping, scan the heap and check all object
>>> to make sure that none of them are immutable and so, #become will work
>>> ok?
>>
>> Just ignore all writes into immutable objects (that is, in the become code, do not insert a forwarding block), otherwise proceed as usual.
>>
> But such semantics is no longer can be treated as #become (or #becomeForward),
> because you leaving a references to old object instead of uniformly
> replacing them with swapped one.

I don't see a problem with that. Can you give an example where it would be problematic?

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 31 March 2010 17:14, Bert Freudenberg <[hidden email]> wrote:

> On 31.03.2010, at 16:10, Igor Stasenko wrote:
>>
>> On 31 March 2010 16:07, Bert Freudenberg <[hidden email]> wrote:
>>> On 31.03.2010, at 15:03, Igor Stasenko wrote:
>>>>
>>>> On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:
>>>>> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>>>>>
>>>>>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>>>>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>>>>>
>>>>>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>>>>>
>>>>>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>>>>>
>>>>>>>> I've developed in a mixed object/functional style for years, and I
>>>>>>>> think a lot of other people do, too.   You don't need language support
>>>>>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>>>>>> and distributed programming easier, and is important when you are
>>>>>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>>>>>> book "Domain Driven Design".
>>>>>>>>
>>>>>>>> -Ralph Johnson
>>>>>>>
>>>>>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>>>>>
>>>>>> Even perfectly VM enforced immutability isn't enough to allow
>>>>>> optimisation if you still allow become:. It's always possible to swap
>>>>>> out the immutable object with a different one via become:.
>>>>>
>>>>> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>>>>>
>>>>> a := Array with: A new.
>>>>> b := Array with: B new beImmutable.
>>>>> c := (Array with: C new) beImmutable.
>>>>> a first become: b first. "a points to the immutable B instance, b to the A instance".
>>>>> a first become: c first. "both a and c now point to the immutable C instance"
>>>>>
>>>>
>>>> one of the problem with #become:/becomeForward: that it should swap
>>>> all of existing references atomically.
>>>> Now imagine that while walking the heap, it replaced a 50% of
>>>> references to given object, and then discoreved that it
>>>> needs to swap a reference held by immutable object.
>>>> Now, what you suppose to do? Revert all changes and fail primitive?
>>>> Ignore this object (do not alter it references) and continue?
>>>> Or, before doing the real swapping, scan the heap and check all object
>>>> to make sure that none of them are immutable and so, #become will work
>>>> ok?
>>>
>>> Just ignore all writes into immutable objects (that is, in the become code, do not insert a forwarding block), otherwise proceed as usual.
>>>
>> But such semantics is no longer can be treated as #become (or #becomeForward),
>> because you leaving a references to old object instead of uniformly
>> replacing them with swapped one.
>
> I don't see a problem with that. Can you give an example where it would be problematic?
>

It defeats a purpose of #become.
If you think about objects as a nodes in directed graph, then
become is a way to replace a single node with another one,
such that all nodes pointing to node A, now start pointing to node B.
If you make any exceptions, you'll end up with having part of nodes in
graph pointing to B, while
another part still pointing to node A.
Many things in system relying on such semantics, and i don't even want
to guess, how many places will break
if you change that, because in all cases where one using #become, he
expects that all references is replaced, but now he should keep in
mind that some references keep unchanged and moreover, you don't have
a reliable control over this process.
So, instead of simple and predictable behavior, #become will be
something unreliable and brittle, which cannot be fully trusted.

> - Bert -
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 17:01, Igor Stasenko wrote:

>
> On 31 March 2010 17:14, Bert Freudenberg <[hidden email]> wrote:
>> On 31.03.2010, at 16:10, Igor Stasenko wrote:
>>>
>>> On 31 March 2010 16:07, Bert Freudenberg <[hidden email]> wrote:
>>>> On 31.03.2010, at 15:03, Igor Stasenko wrote:
>>>>>
>>>>> On 30 March 2010 14:09, Bert Freudenberg <[hidden email]> wrote:
>>>>>> On 30.03.2010, at 11:45, Bryce Kampjes wrote:
>>>>>>>
>>>>>>> On Thu, 2010-03-18 at 16:40 +0100, Bert Freudenberg wrote:
>>>>>>>> On 18.03.2010, at 16:30, Ralph Johnson wrote:
>>>>>>>>>
>>>>>>>>> On 3/18/10, Bert Freudenberg <[hidden email]> wrote:
>>>>>>>>>
>>>>>>>>>> With true immutables you can start developing in a mixed object/functional style, which would allow interesting optimizations, e.g. for concurrency, memoization etc.
>>>>>>>>>
>>>>>>>>> I've developed in a mixed object/functional style for years, and I
>>>>>>>>> think a lot of other people do, too.   You don't need language support
>>>>>>>>> for this, though I expect it would be helpful.  It makes concurrency
>>>>>>>>> and distributed programming easier, and is important when you are
>>>>>>>>> dealing with databases.  Eric Evans calls this "Value Object" in his
>>>>>>>>> book "Domain Driven Design".
>>>>>>>>>
>>>>>>>>> -Ralph Johnson
>>>>>>>>
>>>>>>>> Right, the style is possible without VM support in your own subsystem. But being able to *guarantee* immutability would allow to generalize this beyond your own special-purpose code. And possibly it would enable further VM-level optimizations.
>>>>>>>
>>>>>>> Even perfectly VM enforced immutability isn't enough to allow
>>>>>>> optimisation if you still allow become:. It's always possible to swap
>>>>>>> out the immutable object with a different one via become:.
>>>>>>
>>>>>> It's fine to swap immutable objects, unless the object holding the reference is itself unmutable. No instance variable of an immutable object can be stored into, not even by become:.  Obviously, become: would have to honor the immutability flag:. For references inside immutable objects, become: becomes a forward-become (or a no-op if both were immutable):
>>>>>>
>>>>>> a := Array with: A new.
>>>>>> b := Array with: B new beImmutable.
>>>>>> c := (Array with: C new) beImmutable.
>>>>>> a first become: b first. "a points to the immutable B instance, b to the A instance".
>>>>>> a first become: c first. "both a and c now point to the immutable C instance"
>>>>>>
>>>>>
>>>>> one of the problem with #become:/becomeForward: that it should swap
>>>>> all of existing references atomically.
>>>>> Now imagine that while walking the heap, it replaced a 50% of
>>>>> references to given object, and then discoreved that it
>>>>> needs to swap a reference held by immutable object.
>>>>> Now, what you suppose to do? Revert all changes and fail primitive?
>>>>> Ignore this object (do not alter it references) and continue?
>>>>> Or, before doing the real swapping, scan the heap and check all object
>>>>> to make sure that none of them are immutable and so, #become will work
>>>>> ok?
>>>>
>>>> Just ignore all writes into immutable objects (that is, in the become code, do not insert a forwarding block), otherwise proceed as usual.
>>>>
>>> But such semantics is no longer can be treated as #become (or #becomeForward),
>>> because you leaving a references to old object instead of uniformly
>>> replacing them with swapped one.
>>
>> I don't see a problem with that. Can you give an example where it would be problematic?
>>
>
> It defeats a purpose of #become.
> If you think about objects as a nodes in directed graph, then
> become is a way to replace a single node with another one,
> such that all nodes pointing to node A, now start pointing to node B.
> If you make any exceptions, you'll end up with having part of nodes in
> graph pointing to B, while
> another part still pointing to node A.
> Many things in system relying on such semantics, and i don't even want
> to guess, how many places will break
> if you change that, because in all cases where one using #become, he
> expects that all references is replaced, but now he should keep in
> mind that some references keep unchanged and moreover, you don't have
> a reliable control over this process.
> So, instead of simple and predictable behavior, #become will be
> something unreliable and brittle, which cannot be fully trusted.

self call: Shenanigans ;)

Show me a single place that would break in a real-world use-case.

In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Andreas.Raab
On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
> Show me a single place that would break in a real-world use-case.
>
> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.

I think there is one, and only one, place where #become: is
intrinsically required: Changing class shape.

Cheers,
   - Andreas


Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 17:23, Andreas Raab wrote:
>
> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>> Show me a single place that would break in a real-world use-case.
>>
>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>
> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.

Thought about that. Should be fine.

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:

> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>
>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>> Show me a single place that would break in a real-world use-case.
>>>
>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>
>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>
> Thought about that. Should be fine.
>
Magma using a forwarding proxies to indicate a not-yet reified objects
in memory.

Suppose that you having multiple different objects, which referencing
such proxy.
Proxy is not reified before a first message sent to it and used as a
simple reference.
Nothing prevents you from having many other objects, which pointing to
that proxy without reifying a real object.
And now, think about that with introduction of immutability, some of
these objects is immutable. This means that it is now possible to have
an immutable object, which having a reference to forwarding proxy.
(even more than that, this is more than likely, because Magma will use
an immutability for own purposes, to track changes to objects which
belong to DB graph).
At some stage, your model sending a message to forwarding proxy, and
therefore magma needs to reify a real object
in memory and replace all references to proxy with it.
This is easy to implement by using a #becomeForward:, but if you
change the  #becomeForward: semantics to not replace the references in
immutable objects, you will efficiently break this scheme , and it
can't be used reliably anymore.

So, with such change, we have to invent a different way, how OODB
could reliably replace a forwarding proxy with real object, which is
read from remote storage.

> - Bert -
>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 18:15, Igor Stasenko wrote:

>
> On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:
>> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>>
>>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>>> Show me a single place that would break in a real-world use-case.
>>>>
>>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>>
>>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>>
>> Thought about that. Should be fine.
>>
> Magma using a forwarding proxies to indicate a not-yet reified objects
> in memory.
>
> Suppose that you having multiple different objects, which referencing
> such proxy.
> Proxy is not reified before a first message sent to it and used as a
> simple reference.
> Nothing prevents you from having many other objects, which pointing to
> that proxy without reifying a real object.
> And now, think about that with introduction of immutability, some of
> these objects is immutable. This means that it is now possible to have
> an immutable object, which having a reference to forwarding proxy.
> (even more than that, this is more than likely, because Magma will use
> an immutability for own purposes, to track changes to objects which
> belong to DB graph).
> At some stage, your model sending a message to forwarding proxy, and
> therefore magma needs to reify a real object
> in memory and replace all references to proxy with it.
> This is easy to implement by using a #becomeForward:, but if you
> change the  #becomeForward: semantics to not replace the references in
> immutable objects, you will efficiently break this scheme , and it
> can't be used reliably anymore.

Not at all. Of course you should not make an object immutable that you want to mutate later. That's the whole point really.

> So, with such change, we have to invent a different way, how OODB
> could reliably replace a forwarding proxy with real object, which is
> read from remote storage.

No, you just cannot use VM-level immutability for detecting this case.

It would still be perfectly fine to put immutable objects into Magma. You just couldn't modify them. Again, that's the point of immutability.

It'd also be fine to have a proxy for an immutable object. But when the proxied object is brought in, it will have to bring in all the objects it referenced, because these are immutable by definition, too.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 31 March 2010 19:25, Bert Freudenberg <[hidden email]> wrote:

> On 31.03.2010, at 18:15, Igor Stasenko wrote:
>>
>> On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:
>>> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>>>
>>>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>>>> Show me a single place that would break in a real-world use-case.
>>>>>
>>>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>>>
>>>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>>>
>>> Thought about that. Should be fine.
>>>
>> Magma using a forwarding proxies to indicate a not-yet reified objects
>> in memory.
>>
>> Suppose that you having multiple different objects, which referencing
>> such proxy.
>> Proxy is not reified before a first message sent to it and used as a
>> simple reference.
>> Nothing prevents you from having many other objects, which pointing to
>> that proxy without reifying a real object.
>> And now, think about that with introduction of immutability, some of
>> these objects is immutable. This means that it is now possible to have
>> an immutable object, which having a reference to forwarding proxy.
>> (even more than that, this is more than likely, because Magma will use
>> an immutability for own purposes, to track changes to objects which
>> belong to DB graph).
>> At some stage, your model sending a message to forwarding proxy, and
>> therefore magma needs to reify a real object
>> in memory and replace all references to proxy with it.
>> This is easy to implement by using a #becomeForward:, but if you
>> change the  #becomeForward: semantics to not replace the references in
>> immutable objects, you will efficiently break this scheme , and it
>> can't be used reliably anymore.
>
> Not at all. Of course you should not make an object immutable that you want to mutate later. That's the whole point really.
>

I'd say, that there is virtually no objects in system which you won't
want to mutate later (taking a considerably big time span).
Because otherwise, a system degenerates into a set of static state,
which you can't change , and the more static parts in system, the less
usefull it becomes from computational point of view.

>> So, with such change, we have to invent a different way, how OODB
>> could reliably replace a forwarding proxy with real object, which is
>> read from remote storage.
>
> No, you just cannot use VM-level immutability for detecting this case.
>
> It would still be perfectly fine to put immutable objects into Magma. You just couldn't modify them. Again, that's the point of immutability.
>
> It'd also be fine to have a proxy for an immutable object. But when the proxied object is brought in, it will have to bring in all the objects it referenced, because these are immutable by definition, too.
>

I am assuming that you talking about immutability propagation here.
I.e. an immutable object can't have a references to mutable objects
itself.
Then , this means, that OODB having no means to keep only a partial
view of arbitrary objects graph in memory, because you have to bring
in all immutable objects at once, once only first become accessible,
no matter if it used or not (or will be used or not).
But such approach hits hard on OODB's efficiency, isnt?
And it is fun, because one of arguments for bringing in an
immutability is to serve for improving OODBs efficiency.

> - Bert -


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Denis Kudriashov
In reply to this post by Bert Freudenberg


2010/3/31 Bert Freudenberg <[hidden email]>
On 31.03.2010, at 18:15, Igor Stasenko wrote:
>
> On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:
>> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>>
>>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>>> Show me a single place that would break in a real-world use-case.
>>>>
>>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>>
>>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>>
>> Thought about that. Should be fine.
>>
> Magma using a forwarding proxies to indicate a not-yet reified objects
> in memory.
>
> Suppose that you having multiple different objects, which referencing
> such proxy.
> Proxy is not reified before a first message sent to it and used as a
> simple reference.
> Nothing prevents you from having many other objects, which pointing to
> that proxy without reifying a real object.
> And now, think about that with introduction of immutability, some of
> these objects is immutable. This means that it is now possible to have
> an immutable object, which having a reference to forwarding proxy.
> (even more than that, this is more than likely, because Magma will use
> an immutability for own purposes, to track changes to objects which
> belong to DB graph).
> At some stage, your model sending a message to forwarding proxy, and
> therefore magma needs to reify a real object
> in memory and replace all references to proxy with it.
> This is easy to implement by using a #becomeForward:, but if you
> change the  #becomeForward: semantics to not replace the references in
> immutable objects, you will efficiently break this scheme , and it
> can't be used reliably anymore.

Not at all. Of course you should not make an object immutable that you want to mutate later. That's the whole point really.


With your "become logic" reference to proxy (like proxy in magma and glorp) will never materialized if immutability used for object modification tracking.
And it will break this frameworks (magma, glorp)




123