<div dir="ltr">Hi Denis,<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 10, 2018 at 2:46 AM, Denis Kudriashov <span dir="ltr"><<a href="mailto:dionisiydk@gmail.com" target="_blank">dionisiydk@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"> <br><div dir="ltr">Hi.<div><br></div><div>Look at following example:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div>p1 := 10@20.</div></div><div><div>p2 := 40@50.</div></div><div>p1 becomeForward: p2.<br></div><div>p1 == p2 "==> true"</div></blockquote><div><br></div><div>It shows that become operation do not modifies p1 instance. It just replaces value in all references.</div><div>Now if p1 will be read only object then become will fail:</div><div><br></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 := 10@20.</div><div>p2 := 40@50.</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 beReadOnlyObject.</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 becomeForward: p2. "==> fail by modification error"<br></div><div><br></div></blockquote>My question is why this logic is valid? As simple user I do not see how become modifies the state of receiver p1.</div></div></blockquote><div><br></div><div>Well, the reason is to prevent changing literals.  Let's say you have a method like</div><div><br></div><div>Object>>printOn: aStream</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">  </span>"Append to the argument, aStream, a sequence of characters that  </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>identifies the receiver."</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>| title |</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">      </span>title := self class name.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">      </span>aStream</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>nextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']);</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">             </span>nextPutAll: title</div><div><br></div><div>Without read-only literals there is nothing to stop the programmer from making the mistake of doing something like</div><div>    ((Object>>#printOn:) literalAt: 4) at: 1 put: $A</div><div>which would cause Object new to print as 'An Object', not 'an Object'.  Once literals are read-only then this can't happen; the at:put: will fail.</div><div><br></div><div>But one can use becomeForward: or become: in exactly the same way.  Unless become is illegal for read-only objects, there is nothing to stop the programmer from making the mistake of doing</div>    ((Object>>#printOn:) literalAt: 4) becomeForward: 'An '<br>    ((Object>>#printOn:) literalAt: 4) become: 'An '<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>And what I expect is failing on another case which surprisingly do not fail:<br></div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div>p1 := 10@20.</div></div><div><div>p2 := 40@50.</div></div><div><div>array := {  p1. p2}.</div></div><div><div>array beReadOnlyObject.</div></div><div><div>p1 becomeForward: p2.</div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>array = {40@50. 40@50} "==true"</div><div><br></div></blockquote>Here become operation modifies state of read only object. But it not fails.</div></blockquote><div><br></div><div>The reason here is to do with instance migration on class definition.  We want becomeForward: to update any and all instances of a class when we shape change a class.  Further, the only way the VM can prevent this is by scanning the entire heap looking for any reference to the receiver of becomeForward: from a read-only object.  And we want becomeForward: to be fast; the last thing we want is to introduce a full heap scan when we introduce read-only objects.  So we're being pragmatic; the definitions here, that two-way become fails if either is a read-only object, and that one-way become fails if the receiver is read-only, work well with the way the system implements instance migration, and allow us to implement become in the presence of read-only objects without a full heap scan.</div><div><br></div><div>This matches the VW implementation which makes the same choices for the same reasons.  It's not ideal, but neither is having the VM catch your last case.  Instead it's a workable compromise.  HTH</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Best regards,<br></div><div>Denis</div></div></blockquote><div><br></div><div>Likewise.  Happy New Year!</div><div><br></div></div><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>