In the following code, in a class called Test which is a subclass of
Presenter, the 2nd line results in a #doesNotUnderstand message where the receiver is nil. test2 self model when: #aaa: perform: [ : m | ] . self model "<== self is nil here" The debugger identifiers the outer message being evaluated as UndefinedObject(Test)>>test2 I have seen this before but could not isolate it from my project. I have now been able to reduce it to a small test case which fails in a default image. Following is a .cls file. To reproduce, file in and evaluate: Test demo. -alan r. ---------------------------------------------------------------------- "Filed out from Dolphin Smalltalk 2000 release 4.01"! Presenter subclass: #Test instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! Test comment: ''! Test guid: (GUID fromString: '{E22B6117-D39E-4F43-9B0C-E40AC0B35B80}')! !Test categoriesForClass!Unclassified! ! !Test methodsFor! test2 self model when: #aaa: perform: [ : m | ] . self model ! ! !Test categoriesFor: #test2!*-unclassified!public! ! !Test class methodsFor! demo self new model: Object new ; test2! ! !Test class categoriesFor: #demo!*-unclassified!public! ! |
Are blocks not supported as the action for a #when:perform:? I see that the
event action receiver is getting set to nil in EventMessageSequence>>add: ,so for a block that is the method context which explains why subsequent references to self are nil in the method. It never even occurred to me that blocks weren't polymorphic with messages for events, coming from the Digitalk smalltalks. event actions are such a nice place for blocks :( On Fri, 25 Jan 2002 23:49:09 GMT, ar <[hidden email]> wrote: >In the following code, in a class called Test which is a subclass of >Presenter, the 2nd line results in a #doesNotUnderstand message where the >receiver is nil. > >test2 > > self model when: #aaa: perform: [ : m | ] . > self model "<== self is nil here" > >The debugger identifiers the outer message being evaluated as >UndefinedObject(Test)>>test2 > >I have seen this before but could not isolate it from my project. I have now >been able to reduce it to a small test case which fails in a default image. >Following is a .cls file. To reproduce, file in and evaluate: > > Test demo. > >-alan r. >---------------------------------------------------------------------- >"Filed out from Dolphin Smalltalk 2000 release 4.01"! > >Presenter subclass: #Test > instanceVariableNames: '' > classVariableNames: '' > poolDictionaries: '' > classInstanceVariableNames: ''! >Test comment: ''! > >Test guid: (GUID fromString: '{E22B6117-D39E-4F43-9B0C-E40AC0B35B80}')! > >!Test categoriesForClass!Unclassified! ! >!Test methodsFor! > >test2 > > self model when: #aaa: perform: [ : m | ] . > self model > > > >! ! >!Test categoriesFor: #test2!*-unclassified!public! ! > >!Test class methodsFor! > >demo > > self new > model: Object new > ; test2! ! >!Test class categoriesFor: #demo!*-unclassified!public! ! > |
> It never even occurred to me that blocks weren't polymorphic with messages
for > events, coming from the Digitalk smalltalks. Dolphin used to have a #when:evaluate: method which took a block as an argument. It was removed as, at the time, it was felt that caused more problems than it solved as it was much to easy to get into a situation where the blocks were holding onto references to objects and preventing garbage collection. I can't remember any subsequent changes that may have made this safer now, but who knows what's happened "under the hood". There was a little bit of discussion in the newsgroup about this back in 1997. Search the archive for when:evaluate: and when:perform: > event actions are such a nice place for blocks :( Hmmm. Not sure I completely agree with that. Scattering code around in blocks seems a bit more open to problems (the code in the block has to know about the object it is passed) than sending the object a message and asking it to do it to itself. I suppose it depends on what you are asking the block to do though. Regards Ian |
On Sat, 26 Jan 2002 08:52:23 -0000, "Ian Bartholomew" <[hidden email]>
wrote: >There was a little bit of discussion in the newsgroup about this back in >1997. Search the archive for when:evaluate: and when:perform: >Dolphin used to have a #when:evaluate: method which took a block as an >argument. It was removed as, at the time, it was felt that caused more >problems than it solved as it was much to easy to get into a situation where >the blocks were holding onto references to objects and preventing garbage >collection. Thanks, I am all caught up on this issue now. I'm only about 5 years behind :) As I alluded to in the imager-packager thread, I have seen referencing gc problems which could be attributed to using block actions. This was on VSE which had ANSI blocks and also an implementation of weak references and finalization which was poor compared to Dolphin's (a metaphorical masterpiece:) and wasnt utilized properly by the event framework. >> event actions are such a nice place for blocks :( >Hmmm. Not sure I completely agree with that. Scattering code around in >blocks seems a bit more open to problems (the code in the block has to know >about the object it is passed) than sending the object a message and asking >it to do it to itself. I suppose it depends on what you are asking the >block to do though. Without the implementation issues, blocks would be advantageous as event handlers for all the reasons that blocks are advantageous in general. They can capture state from the context creating the event and can use it in the event. They dont have to be evaluated until actually used. They allow defining immediate code (as in ifTrue/ifFalse) instead of having to institutionalize every custom bit of behavior in a separate method. This aspect was mentioned by Harry in the original discussions. Imagine using messages as parameters to collection>>do or ifTrue:ifFalse:. I think that might be theoretically doable but with a (significant) diminution of expressiveness, which is the same for events . The only difference really is that by convention the former are used immediately and then discarded. regards, alan r (untested idea: when: #blah perform: [ [ ..... ] value] to 'protect' the inside block. A hack , but just curious in theory if it would work or would the inner block suffer when the outer one lost its home context.. If when:evaluate: implementation was significantly different than when:perform: I'd be curious to see it... |
Alan,
> Without the implementation issues, blocks would be advantageous as event > handlers for all the reasons that blocks are advantageous in general. [snip] All good points that I can't disagree with. I suppose I have just got used to the Dolphin pattern of using events. You normally get a simple initialisation line in an initialisation method of some sort and then a target method that begins with #on and contains the event name within the selector. When I am reading code I know this pattern and, should I be looking for event handlers, will scan methods like this first. I just feel that having some event handling done in blocks defined as part of the initialisation and some in methods (scattering them about) makes things that much more complicated. Regards Ian |
Free forum by Nabble | Edit this page |