<div dir="ltr">Hi Eliot.<div><br></div><div>I definitely sure that nil parameter smells very bad:  </div><div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="color:rgb(0,0,0);font-size:12.800000190734863px">Object>>noModificationErrorFor<wbr>: selector value: value</div></div><div><div style="color:rgb(0,0,0);font-size:12.800000190734863px"><span class="gmail-m_-5412380556337104864gmail-m_-4721815780106111gmail-Apple-tab-span" style="white-space:pre-wrap">   </span>^(NoModificationError receiver: self selector: selector <b>index: nil</b> value: value) raiseRequest</div></div></blockquote><div><div style="color:rgb(0,0,0);font-size:12.800000190734863px"><br></div></div><div>Because in that case all users will be forced to check nils if they are interesting only about field modification.</div></div><div>I can imaging such library which records history of object changes. It will need exact field index which was modified.<br></div><div>Also ORM frameworks needs to handle differently field modification and class modification of objects. Because new class can be mapped in different table and such update will require complex logic. It would be natural to dispatch concrete logic by error classes.</div><div><br></div><div>So I would introduce little hierarchy which I already mentioned:</div><div><br></div><div>ModificationForbidden</div><div>   FieldModificationForbidden</div><div>   ClassModificationForbidden</div><div>   BecomeModificationForbidden</div><div><br></div><div><span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px">On the base class there will be object, newValue, retrySelector and isMirror flag. And fieldIndex will be moved to the FieldModificationForbidden.</span><br></div><div><font color="#24292e" face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol"><span style="font-size:14px">Mirror flag is required to correctly retry mirror based modification because first argument in that case is always "actual receiver" instead of index.</span></font></div><div><font color="#24292e" face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol"><span style="font-size:14px"><br></span></font></div><div><font color="#24292e" face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol"><span style="font-size:14px">I split class and become based modifications because it is logically different errors. Maybe it is not important distinction from the first look but at least it is easy to name them separately. Do we have other cases which are not related to field modification?</span></font></div><div><br></div><div>Also I have question about become which I sent to VM list.</div><div><br></div><div>Best regards,</div><div>Denis</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2018-01-06 19:45 GMT+01:00 Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div dir="ltr">Hi Norbert, Hi Denis,<div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jan 6, 2018 at 4:06 AM, Norbert Hartl <span dir="ltr"><<a href="mailto:norbert@hartl.name" target="_blank">norbert@hartl.name</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 style="word-wrap:break-word"><br><div><br><blockquote type="cite"><div>Am 05.01.2018 um 16:53 schrieb Clément Bera <<a href="mailto:bera.clement@gmail.com" target="_blank">bera.clement@gmail.com</a>>:</div><br class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-interchange-newline"><div><br class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-interchange-newline"><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_quote" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">On Fri, Jan 5, 2018 at 4:05 PM, Norbert Hartl<span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span><span dir="ltr"><<a href="mailto:norbert@hartl.name" target="_blank">norbert@hartl.name</a>></span><span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span>wro<wbr>te:<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 style="word-wrap:break-word">You mean<div><br></div><div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space:pre-wrap"> </span><primitive: 174 error: ec></div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space:pre-wrap"> </span>self isReadOnlyObject </div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space:pre-wrap">          </span>ifTrue: [(ModificationForbidden for: self atInstVar: index with: anObject) signal]</div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space:pre-wrap">               </span>ifFalse: [ self primitiveFailed ]</div><div>?</div><div><br></div><div>Norbert</div></div></div></blockquote><div><br></div><div>yes something like that.</div><div><br></div><div><br></div><div>Same thing for Object>>#at:put:, floatAt:put: and so on.</div></div></div></blockquote><div><br></div>I’m working on it and came by</div><div><br></div><div>Object>>#primitiveChangeClassT<wbr>o:</div><div><br></div><div>and I wonder what would be the approach here. The ModificationForbidden/NoModifi<wbr>cationError seems to be tight to an index. What would be the case for a class change? Another Exception class? How is that solved in VW? </div></div></blockquote><div><br></div><div>I don't think that adding variants of NoModificationError is wise.  One can imagine adding other state changes that read-onliness should prevent, such as unpinning.  So one could end up having to add a lot of subclasses of NoModificationError, each rather inflexible and able to respond to only one specific error.  We would end up with at least InstanceVariableModificationEr<wbr>ror IndexedVariableModificationErr<wbr>or ClassModificationError BecomeIdentotyChangeError etc.  And even then IndexedVariableModificationErr<wbr>or would need a message since there are many different kinds of at:put:s, at:put:, byteAt:put: unsignedLongAt:put: etc.</div><div><br></div><div>In VW it is handled by the NoModificationError holding a Message that can be used for the retry operation.  i.e.</div><div><br></div><div>Object>><wbr>noModificationErrorFor: selector index: index value: value</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>^(NoModificationError receiver: self selector: selector index: index value: value) raiseRequest</div><div><br></div><div>(N.B. the following is sent by the VM when an inst var assignment fails due to read-onlyness; see recreateSpecialObjectsArray)</div><div>Object>>attemptToAssign: aValue withIndex: index</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>^self noModificationErrorFor: #instVarAt:put: index: index value: aValue</div><div><br></div><div>Object>>at: index put: value</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>"Store the argument value in the indexable field of the receiver indicated by</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">  </span> index. Fail if the index is not an Integer or is out of bounds. Fail if the</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">        </span> value is not of the right type for this kind of collection. Answer the</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">     </span> value that was stored."</div><div><br></div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">      </span><primitive: 61 errorCode: ec></div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>index isInteger ifTrue:</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">             </span>[(index >= 1 and: [index <= self basicSize])</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">                  </span>ifTrue:</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">                             </span>[self isImmutable</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">                                   </span>ifTrue: [^self noModificationErrorFor: #at:put: index: index value: value]</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">                                  </span>ifFalse: [^self improperStoreError]]</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>ifFalse: [^self subscriptBoundsErrorFor: #at:put: index: index value: value]].</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>index respondsToArithmetic</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">          </span>ifTrue: [^self at: index asSmallInteger put: value]</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">         </span>ifFalse: [^self nonIntegerIndexError: index]</div><div><br></div><div>Behavior>>adoptInstance: anObject</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>"Changes the class of the argument to be that of the receiver provided that</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">    </span>  a)<span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>anObject is not immutable (which includes immediates)</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">       </span>  b)<span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>anObject is bits and the receiver is a bits class, or</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">       </span>  c)<span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>anObject is pointers and the receiver is pointers and anObject has the same</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">         </span>number of inst vars as specified by the receiver, or the receiver is variable and</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">           </span>anObject has at least as many inst vars as specified by the receiver.</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">       </span> Answers the receiver."</div><div><br></div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">       </span><primitive: 536 errorCode: errCode></div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">   </span>^(errCode ~~ nil</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">    </span>   and: [errCode name = #'no modification'])</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">               </span>ifTrue: [anObject noModificationErrorFor: #changeClassTo: index: nil value: self]</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">           </span>ifFalse: [self primitiveFailed]</div><div><br></div><div>etc.  This is much more flexible and works well in practice.  In the vw7.7nc image I looked at there are 20 senders of #noModificationErrorFor:index:<wbr>value: for variants of 5 operations:</div><div><br></div><div>- attempting to assign to an inst var of a read-only object, either directly in code via an inst var assignment or via an instVarAt:put: send</div><div>- attempting to assign to an indexed inst var of a read-only object, via an at:put: send (at:put: byteAt:put: unsignedLongAt:put: etc)</div>- attempting to assign to an indexed inst var of a read-only object via a BitBlt primitive (e.g. copyBitsClippedStride:<wbr>width:atX:y:from:stride:width:<wbr>atX:y:width:height:rule:)<div>- attempting to become a read-only object via two-way become; forwarding become is not considered a modification.</div><div>- attempting to change the class of a read-only object</div><div><br></div><div><br></div><div><br></div><div>Digression:</div><div><br></div><div>Looking at the above the obvious convenience is to add</div><div><br></div><div><div>Object>><wbr>noModificationErrorFor: selector value: value</div><div><span class="m_-5658225091363802390gmail-Apple-tab-span" style="white-space:pre-wrap">       </span>^(NoModificationError receiver: self selector: selector index: nil value: value) raiseRequest</div></div><div><br></div><div>which would be applicable in 8 of the 20 uses, but it would imply adding overrides in subclasses.  #noModificationErrorFor:<wbr>index:value: is implemented in ProtoObect, Object, Symbol and VariableBinding. The implementations in Symbol and VariableBinding simply provide more explanatory error messages.</div><div><br></div><div>HTH</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 style="word-wrap:break-word"><div><br></div><div>Norbert</div><div><br><blockquote type="cite"><div><div class="gmail_quote" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div> </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 style="word-wrap:break-word"><div><div><br><blockquote type="cite"><div>Am 05.01.2018 um 14:22 schrieb Clément Bera <<a href="mailto:bera.clement@gmail.com" target="_blank">bera.clement@gmail.com</a>>:</div><br class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930Apple-interchange-newline"><div><div dir="ltr"><div>Hi,</div><div><br></div><div>No this is not a bug.</div><div><br></div>This needs to be handled in the primitive failure code in the image, the method should be something like that :<div><br><div><div><font face="monospace, monospace">Object>>instVarAt: index put: anObject</font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap"> </span><primitive: 174 error: ec></font></div><div><font face="monospace, monospace">       <span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span>self isReadOnlyObject ifTrue: [(ModificationForbidden for: self atInstVar: index with: anObject) signal]</font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap">    </span>self primitiveFailed</font></div><div><br></div><div>All primitive fall-back code triggering object mutation should be rewritten this way, especially primitives such as #at:put:, #instVarAt:put:, etc.</div><div><br></div></div></div><div>Cheers</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 5, 2018 at 1:42 PM, Norbert Hartl<span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span><span dir="ltr"><<a href="mailto:norbert@hartl.name" target="_blank">norbert@hartl.name</a>></span><span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span>wro<wbr>te:<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 style="word-wrap:break-word">If I do <div><br></div><div><div>(#foo -> #bar)</div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space:pre-wrap">        </span>beReadOnlyObject;</div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space:pre-wrap">  </span>value: #baz</div></div><div><br></div><div>it throws</div><div><br></div><div><b>ModificationForbidden:  #foo->#bar is read-only, hence its field 2 cannot be modified with #baz</b></div><div><br></div><div> which is as expected. But if I do</div><div><br></div><div><div>(#foo -> #bar)</div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space:pre-wrap">      </span>beReadOnlyObject;</div><div><span class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space:pre-wrap">  </span>instVarNamed: #value put: #baz</div></div><div><br></div><div>I get</div><div><br></div><div><b>PrimitiveFailed: primitive #instVarAt:put: in Association failed</b></div><div><br></div><div>I think this a bug, no?</div><div><br></div><div>Norbert</div></div><br></blockquote></div><br><br clear="all"><div><br></div>--<span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span><br><div class="m_-5658225091363802390gmail-m_-6620910617287063281m_8231836668159255930gmail_signature"><div dir="ltr"><span style="font-size:12.8px">Clément Béra</span><div style="font-size:12.8px">Pharo consortium engineer</div><div style="font-size:12.8px"><a href="https://clementbera.wordpress.com/" target="_blank">https://clementbera.wordpress.<wbr>com/</a><br></div><div style="font-size:12.8px"><span style="line-height:16px">Bâtiment B 40, avenue Halley 59650 </span><span style="font-weight:bold;line-height:16px">Villeneuve d'Ascq</span></div></div></div></div></div></blockquote></div><br></div></div><br></blockquote></div><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br clear="all" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><span style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline">--<span class="m_-5658225091363802390gmail-m_-6620910617287063281Apple-converted-space"> </span></span><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="m_-5658225091363802390gmail-m_-6620910617287063281gmail_signature" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div dir="ltr"><span style="font-size:12.8px">Clément Béra</span><div style="font-size:12.8px">Pharo consortium engineer</div><div style="font-size:12.8px"><a href="https://clementbera.wordpress.com/" target="_blank">https://clementbera.wordpress.<wbr>com/</a><br></div><div style="font-size:12.8px"><span style="line-height:16px">Bâtiment B 40, avenue Halley 59650 </span><span style="font-weight:bold;line-height:16px">Villeneuve d'Ascq</span></div></div></div></div></blockquote></div><br></div><br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="m_-5658225091363802390gmail_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>
<br></blockquote></div><br></div>