If you wanted to take a mutable object and make it immutable and be
able to go back again to mutable, how could you do that? In particular the part that has me as a smalltalk beginner stumped is how to disallow any messages that would result in a state change while still allowing messages that only read state. Do you have to handle on a message by message basis? ( Eeek lots and lots of work ) Or is there something you could work into a superclass and use in its descendents? ( ideal for what I need. ) _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
>>>>> "Sean" == Sean Allen <[hidden email]> writes:
Sean> If you wanted to take a mutable object and make it immutable and be able Sean> to go back again to mutable, how could you do that? Squeak doesn't have that sort of capability. The immutability of a few classes is because the VM recognizes them specially, and not available at the programmer level without modifying the VM. Other Smalltalk VMs are different. I think both VisualWorks and GemStone/S have primitive bits on an object to be informed when a mutation might be attempted. You can simulate that *mostly* in Squeak by using a "proxy" object that intercepts all messages and looks for the dangerous ones, but that's gonna be a bit hard to do, and won't be aware of any new code that might call the mutating primitives directly. (*Any* method can call a primitive.) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by SeanTAllen
Surely if you have a wrapper class which only holds a reference to a single object that has all of the data, and that has accessors, then the wrapper can only use the accessors? The data object could have a flag that causes all of the accessors to throw an exception when it is set.
Or am I missing something?
On 10/2/08, Randal L. Schwartz <[hidden email]> wrote:
>>>>> "Sean" == Sean Allen <[hidden email]> writes: _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
You'd have to specially code each accessor in that case to check the flag.
Ideally I'd like to be able to step in front of every message send to descendent objects and decide whether to pass along ( read call ) or reject ( write call ). then, all the logic is in one place and the accessors don't need to know about what is going on. any way to do that? i'm ok with the primitive problem as i don't need real immutability. just 'application level' immutability... ideally, without special coding in every accessor method ( that would get tedious very quickly ). On Oct 2, 2008, at 12:47 PM, Marcin Tustin wrote:
_______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by SeanTAllen
Am 02.10.2008 um 08:50 schrieb Sean Allen: > If you wanted to take a mutable object and make it immutable and be > able to go back again to mutable, > how could you do that? What is your use case? > In particular the part that has me as a smalltalk beginner stumped > is how to disallow any messages > that would result in a state change while still allowing messages > that only read state. > > Do you have to handle on a message by message basis? ( Eeek lots and > lots of work ) > Or is there something you could work into a superclass and use in > its descendents? ( ideal for what I need. ) Well, it's hardly a beginner's topic, but you could make your class use a modified compiler that protects instance variable assignment by the check of an "immutable" flag. This is basically how Avi's WriteBarrier works. - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by SeanTAllen
Am 02.10.2008 um 10:17 schrieb Sean Allen: > You'd have to specially code each accessor in that case to check the > flag. > > Ideally I'd like to be able to step in front of every message send > to descendent objects and > decide whether to pass along ( read call ) or reject ( write call ). > > then, all the logic is in one place and the accessors don't need to > know about what is going on. > > any way to do that? The proxy Randal was suggesting can do that. It encapsulates an object, and decides wether to pass on messages or not. > i'm ok with the primitive problem as i don't need real immutability. > just 'application level' immutability... > ideally, without special coding in every accessor method ( that > would get tedious very quickly ). > > > On Oct 2, 2008, at 12:47 PM, Marcin Tustin wrote: > >> Surely if you have a wrapper class which only holds a reference to >> a single object that has all of the data, and that has accessors, >> then the wrapper can only use the accessors? The data object could >> have a flag that causes all of the accessors to throw an exception >> when it is set. >> >> Or am I missing something? >> >> On 10/2/08, Randal L. Schwartz <[hidden email]> wrote: >>>>> >> "Sean" == Sean Allen <[hidden email]> writes: >> >> Sean> If you wanted to take a mutable object and make it immutable >> and be able >> Sean> to go back again to mutable, how could you do that? >> >> Squeak doesn't have that sort of capability. The immutability of a >> few >> classes is because the VM recognizes them specially, and not >> available >> at the programmer level without modifying the VM. >> >> Other Smalltalk VMs are different. I think both VisualWorks and >> GemStone/S >> have primitive bits on an object to be informed when a mutation >> might be >> attempted. >> >> You can simulate that *mostly* in Squeak by using a "proxy" object >> that >> intercepts all messages and looks for the dangerous ones, but >> that's gonna be >> a bit hard to do, and won't be aware of any new code that might >> call the >> mutating primitives directly. (*Any* method can call a primitive.) >> >> -- >> Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 >> 777 0095 >> <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> >> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. >> See http://methodsandmessages.vox.com/ for Smalltalk and Seaside >> discussion >> ______________________________________________ _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Marcin Tustin
>>>>> "Marcin" == Marcin Tustin <[hidden email]> writes:
Marcin> Surely if you have a wrapper class which only holds a reference to a Marcin> single object that has all of the data, and that has accessors, then Marcin> the wrapper can only use the accessors? The data object could have a Marcin> flag that causes all of the accessors to throw an exception when it is Marcin> set. Well, if everyone using the object promises to play nice, sure. But the debugger doesn't have any special privileges, and it can clearly access every inst var, regardless of whether accessors exist or not, through the magic of #instVarAt: and friends. So code would merely have to execute the equivalent of the primitives behind #instVarAt: and #instVarAt:put:, and no amount of wrapper class would help. If the problem is "how do I ensure this object *doesn't* get mutated?", this is not a complete solution, just a slow simulation as long as everyone cooperates. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Am 02.10.2008 um 10:26 schrieb Randal L. Schwartz: > > But the debugger doesn't have any special privileges, and it can > clearly > access every inst var, regardless of whether accessors exist or not, > through > the magic of #instVarAt: and friends. There is no magic in #instVarAt:. It exists merely for helping debugging. > So code would merely have to execute the equivalent of the > primitives behind > #instVarAt: and #instVarAt:put:, and no amount of wrapper class > would help. That is not correct. There are no primitives that modify/access *other* objects. That would break encapsulation. All you need to do to prevent the debugger from accessing instance variables is overwriting the methods the debugger invokes. - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by SeanTAllen
Ok, there are two options...
First, if the object needs to be inmutable, just doit without setters. Let it be updated at once, with only one message which updates the instance variables from an already valid object. This way you can ensure that the original object will only be updated when you want to. It's an 'Application level' inmutability. The second option is the proxy one, with a collection of 'dangerous' messages that will throw an exception when sended. This can be easily done by defining only the doesNotUnderstand: method in the proxy to search for the message in the collection and if it's found, raise the exception, if not, resend it to the proxyed object. -- Mariano. www.egola.com.ar On Thu, Oct 2, 2008 at 2:17 PM, Sean Allen <[hidden email]> wrote:
_______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:
Bert> There is no magic in #instVarAt:. It exists merely for helping Bert> debugging. I meant the primitive it invokes. Encapsulated magic is still magic. >> So code would merely have to execute the equivalent of the primitives behind >> #instVarAt: and #instVarAt:put:, and no amount of wrapper class would help. Bert> All you need to do to prevent the debugger from accessing instance Bert> variables is overwriting the methods the debugger invokes. Ahh, but a determined outsider could still add methods to the class of the object on the fly, hand-compiling them if necessary. Unless you're now voting for an immutable method dictionary. :) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Marcin Tustin
On Thu, Oct 2, 2008 at 6:17 PM, Sean Allen <[hidden email]> wrote:
Yes. This is unlikely to be a problem unless you have a lot of members. Alternatively you could adapt the code that generates your accessors to put in that check, or you could use/adapt magritte to generate your objects.
_______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Randal L. Schwartz
Am 02.10.2008 um 11:25 schrieb Randal L. Schwartz: >>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes: > > Bert> There is no magic in #instVarAt:. It exists merely for helping > Bert> debugging. > > I meant the primitive it invokes. Encapsulated magic is still magic. > >>> So code would merely have to execute the equivalent of the >>> primitives behind >>> #instVarAt: and #instVarAt:put:, and no amount of wrapper class >>> would help. > > > Bert> All you need to do to prevent the debugger from accessing > instance > Bert> variables is overwriting the methods the debugger invokes. > > Ahh, but a determined outsider could still add methods to the class > of the > object on the fly, hand-compiling them if necessary. How would that outsider get at the class of the object? > Unless you're now voting for an immutable method dictionary. :) > > -- > Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 > 777 0095 > <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> > Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. > See http://methodsandmessages.vox.com/ for Smalltalk and Seaside > discussion - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Marcin Tustin
On Oct 2, 2008, at 2:31 PM, Marcin Tustin wrote:
lots of members across lots of classes. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
On Oct 2, 2008, at 1:18 PM, Bert Freudenberg wrote: > Well, it's hardly a beginner's topic, but you could make your class > use a modified compiler that protects instance variable assignment > by the check of an "immutable" flag. > > This is basically how Avi's WriteBarrier works. I'm going to have to load that into an image and take a look at that. The description is intriguing. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
On Oct 2, 2008, at 1:18 PM, Bert Freudenberg wrote: >> If you wanted to take a mutable object and make it immutable and be >> able to go back again to mutable, >> how could you do that? > > What is your use case? use case. system needs to track changes to itself. one option that has come up is... linked list of different 'versions' of same object. head is the live object. everything else past versions. want to mutate object? you have to 'unlock'. unlocking gives you a new copy and updates the linked list, allowing all the accessors that mutate state to work. when locked, calling one of those accessors would result in an error. but when locked, read access still needed. if i can find a way to put this in a superclass and have children get the functionality w/o doing anything else, then i really like it. it cuts down on the 'real' programming as there are many classes and many messages that need said functionality and honestly, the disk space etc for the objects isnt a concern. there are other options that have been looked at but all require mucking about with each different class which ideally, we want to avoid. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:
Bert> How would that outsider get at the class of the object? I believe #class is "NoLookup", meaning that I can't define a method of my own to do something weird with that. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
>>>>> "Randal" == Randal L Schwartz <[hidden email]> writes:
Randal> I believe #class is "NoLookup", meaning that I can't define a method Randal> of my own to do something weird with that. Feh. Ignore me. I have no idea what I'm talking about. :) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by SeanTAllen
On Thu, Oct 02, 2008 at 02:55:34PM -0400, Sean Allen wrote:
> > On Oct 2, 2008, at 1:18 PM, Bert Freudenberg wrote: > > >> If you wanted to take a mutable object and make it immutable and be > >> able to go back again to mutable, > >> how could you do that? > > > > What is your use case? > > use case. > > system needs to track changes to itself. > > one option that has come up is... > > linked list of different 'versions' of same object. > head is the live object. everything else past versions. > > want to mutate object? you have to 'unlock'. > unlocking gives you a new copy and updates the linked list, > allowing all the accessors that mutate state to work. > > when locked, calling one of those accessors would result in > an error. but when locked, read access still needed. > > if i can find a way to put this in a superclass and have > children get the functionality w/o doing anything else, > then i really like it. heh. I'm making something that creates a new object version whenever an ivar is changed. I'm using tweak's fields and compiler to do it, so it will only work in a Croquet image. Not to mention that I've just barely started. The code is at http://croquet-src-01.oit.duke.edu:8886/RayTracing/Quansi-Core-mtf.10.mcz -- Matthew Fulmer -- http://mtfulmer.wordpress.com/ _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Am 02.10.2008 um 12:44 schrieb Matthew Fulmer:
> On Thu, Oct 02, 2008 at 02:55:34PM -0400, Sean Allen wrote: >> >> On Oct 2, 2008, at 1:18 PM, Bert Freudenberg wrote: >> >>>> If you wanted to take a mutable object and make it immutable and be >>>> able to go back again to mutable, >>>> how could you do that? >>> >>> What is your use case? >> >> use case. >> >> system needs to track changes to itself. >> >> one option that has come up is... >> >> linked list of different 'versions' of same object. >> head is the live object. everything else past versions. >> >> want to mutate object? you have to 'unlock'. >> unlocking gives you a new copy and updates the linked list, >> allowing all the accessors that mutate state to work. >> >> when locked, calling one of those accessors would result in >> an error. but when locked, read access still needed. >> >> if i can find a way to put this in a superclass and have >> children get the functionality w/o doing anything else, >> then i really like it. > > heh. I'm making something that creates a new object version > whenever an ivar is changed. I'm using tweak's fields and > compiler to do it, so it will only work in a Croquet image. > Not to mention that I've just barely started. The code is at > > http://croquet-src-01.oit.duke.edu:8886/RayTracing/Quansi-Core-mtf.10.mcz That seems to be en vogue right now ... see http://www.vpri.org/pdf/rn2008001_worlds.pdf - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |