Hi folks,
on the beginners list Brent McConnell reported a situation in which (Collection new) was assigned to an automatic declared variable x and a subsequent (x := OrderedCollection new) still called for the dubugger, because aDictionary(Set) relies on ((Collection new) hash) for already declared variables. You can provoke the walkback with printIt on (Collection new) hash but also on (Collection new) Q: wouldn't it be noob-friendlier if *all* kernel classes avoided the debugger in doIt/printIt situations? Just my CHF 0.05 :) /Klaus |
Am Jan 21, 2007 um 11:51 schrieb Klaus D. Witzel:
> Hi folks, > > on the beginners list Brent McConnell reported a situation in which > (Collection new) was assigned to an automatic declared variable x > and a subsequent (x := OrderedCollection new) still called for the > dubugger, because aDictionary(Set) relies on ((Collection new) > hash) for already declared variables. Interesting find - I couldn't believe it when I read it, but it is indeed as Brent says. > You can provoke the walkback with printIt on > > (Collection new) hash > > but also on > > (Collection new) IMHO that's not the actual problem at hand, but rather, that compiling an assignment breaks depending on the previous *value* of the binding. We should fix that. Reproduce be evaluating these two lines *separately* in a Workspace: c := Collection new c := 42 > Q: wouldn't it be noob-friendlier if *all* kernel classes avoided > the debugger in doIt/printIt situations? You mean I should be able to write "1 / 0" and not get a debugger? ;-) I don't think so. I also don't think that is necessary, I guess you try to instantiate an abstract Collection only once. So my answer to your subject's question would be a clear "no". *If* we wanted to be newbie friendly we would make "Collection" an alias to "OrderedCollection" so you can actually work with it. I'd be opposed to that suggestion, too, of course ;) - Bert - |
Collection is an abstract class, so you should never say "Collection new".
The problems that you are discussing should be fixed, but I thought someone should say this, too. The answer to the question is "yes, all concrete subclasses of Object should support #printString and #hash" -Ralph |
On Sun, 21 Jan 2007 14:52:20 +0100, Ralph Johnson wrote:
> Collection is an abstract class, so you should never say "Collection > new". Well. People are coming from platforms on which abstract classes cannot be instantiated. I won't want to convince anybody but the first experience of a potential convert should not be the debugger balking at completely unrelated things (here: a subclass should have implemented #do: which the outermost abstract class apparently requires from itself). That's just a contradiction. Funny, (Object new) doesn't have such problems. So, would you say that about "Object new", too. I doubt, because almost every Smalltalk pro does so ;-) Again, just my CHF 0.05 :) /Klaus |
> Funny, (Object new) doesn't have such problems. So, would you say that
> about "Object new", too. I doubt, because almost every Smalltalk pro does > so ;-) Object has no abstract methods, but it is still an abstract class, and I never make instances of it. i consider it a hack to do so, an amusing hack, but a hack nevertheless. I have been teaching that to my students for twenty years, and I do not believe that almost every Smalltalk pro makes instances of Object. Smalltalk does not have static type-checking. The compiler does not stop you from doing stupid things. An abstract class is a class that you do not instantiate, but use only as a superclass. Sometimes it is hard to tell whether a class is abstract, but Collection says it in its comment, and it has a #subclassResponsibility method. -Ralph Johnson |
In reply to this post by Bert Freudenberg
Hi Bert,
on Sun, 21 Jan 2007 13:41:01 +0100, you wrote: > Am Jan 21, 2007 um 11:51 schrieb Klaus D. Witzel: > >> Hi folks, >> >> on the beginners list Brent McConnell reported a situation in which >> (Collection new) was assigned to an automatic declared variable x and a >> subsequent (x := OrderedCollection new) still called for the dubugger, >> because aDictionary(Set) relies on ((Collection new) hash) for already >> declared variables. > > Interesting find - I couldn't believe it when I read it, but it is > indeed as Brent says. > >> You can provoke the walkback with printIt on >> >> (Collection new) hash >> >> but also on >> >> (Collection new) > > IMHO that's not the actual problem at hand, but rather, that compiling > an assignment breaks depending on the previous *value* of the binding. Even more so: just do a recompile on any method on the class side of Unicode. Doing the binding of class var GeneralCategory (Unicode generalCategory size => 917632), same with class var DecimalProperty, this takes ages. Ever switched a browser to the class side of Unicode and then tried to select some method? Try to recompile #generalCategory after adding some whitespace. > We should fix that. Reproduce be evaluating these two lines *separately* > in a Workspace: > > c := Collection new > > c := 42 > >> Q: wouldn't it be noob-friendlier if *all* kernel classes avoided the >> debugger in doIt/printIt situations? > > You mean I should be able to write "1 / 0" and not get a debugger? ;-) Nada, the situation was described in the subject line and has nothing to do with programmer's new mistakes. Just with the downloaded kernel classes' implementation of #printString, obviously the first place where beginners get in touch with Smalltalk's objects. What's the problem with the kernel classes being polite to noobs in a workspace, would that be too much for Smalltalk ;-) > I don't think so. I also don't think that is necessary, I guess you try > to instantiate an abstract Collection only once. Once per class during the rest of your life as Smalltalker, and only if you ever do #printString and/or #hash before going production. Smalltalk size => currently 2887 in my dev-image. /Klaus > So my answer to your subject's question would be a clear "no". *If* we > wanted to be newbie friendly we would make "Collection" an alias to > "OrderedCollection" so you can actually work with it. I'd be opposed to > that suggestion, too, of course ;) > > - Bert - > > > > |
In reply to this post by Ralph Johnson
Hi Ralph,
I have nothing to say against your arguments :) just asked if it is possibile to be more polite to potential converts when they begin using a workspace :) OTOH, for (Object new), you might try - http://www.google.com/search?q=smalltalk+%22object+new%22 to see the tip of the iceberg (keeping in mind that google still does not crawl each and every piece of publicly available Smalltalk code). /Klaus On Sun, 21 Jan 2007 16:23:09 +0100, Ralph Johnson wrote: >> Funny, (Object new) doesn't have such problems. So, would you say that >> about "Object new", too. I doubt, because almost every Smalltalk pro >> does >> so ;-) > > Object has no abstract methods, but it is still an abstract class, and > I never make instances of it. i consider it a hack to do so, an > amusing hack, but a hack nevertheless. I have been teaching that to > my students for twenty years, and I do not believe that almost every > Smalltalk pro makes instances of Object. > > Smalltalk does not have static type-checking. The compiler does not > stop you from doing stupid things. > > An abstract class is a class that you do not instantiate, but use only > as a superclass. Sometimes it is hard to tell whether a class is > abstract, but Collection says it in its comment, and it has a > #subclassResponsibility method. > > -Ralph Johnson > > |
In reply to this post by Ralph Johnson
2007/1/21, Ralph Johnson <[hidden email]>:
> > Funny, (Object new) doesn't have such problems. So, would you say that > > about "Object new", too. I doubt, because almost every Smalltalk pro does > > so ;-) > > Object has no abstract methods, Object has abstract methods like every class in Squeak (but two or three subclasses of ProtoObject). Philippe > but it is still an abstract class, and > I never make instances of it. i consider it a hack to do so, an > amusing hack, but a hack nevertheless. I have been teaching that to > my students for twenty years, and I do not believe that almost every > Smalltalk pro makes instances of Object. > > Smalltalk does not have static type-checking. The compiler does not > stop you from doing stupid things. > > An abstract class is a class that you do not instantiate, but use only > as a superclass. Sometimes it is hard to tell whether a class is > abstract, but Collection says it in its comment, and it has a > #subclassResponsibility method. > > -Ralph Johnson > > |
In reply to this post by Klaus D. Witzel
On 1/21/07, Klaus D. Witzel <[hidden email]> wrote:
> Hi Ralph, > > I have nothing to say against your arguments :) just asked if it is > possibile to be more polite to potential converts when they begin using a > workspace :) Sure, it is good to be friendly. Perhaps change Collection>>do: to do: aBlock self class = Collection ifTrue: [self error: 'Collection is an abstract class. You should probably use OrderedCollection instead.']. self subclassResponsibility Or maybe change #new to be new self = Collection ifTrue: [^OrderedCollection new]. ^super new My guess is that you'd have to play around with a few approaches to figure out which is best for newcomers. i agree that we should be nice to them, and since Collection is abstract, it ought to be possible to make it more friendly without changing the behavior of existing programs. -Ralph |
Am Jan 21, 2007 um 21:15 schrieb Ralph Johnson:
> On 1/21/07, Klaus D. Witzel <[hidden email]> wrote: >> Hi Ralph, >> >> I have nothing to say against your arguments :) just asked if it is >> possibile to be more polite to potential converts when they begin >> using a >> workspace :) > > Sure, it is good to be friendly. > > Perhaps change Collection>>do: to > > do: aBlock > self class = Collection ifTrue: [self error: 'Collection is an > abstract class. You should probably use OrderedCollection instead.']. > self subclassResponsibility That's an excellent idea! Maybe we could even reword the notice in the general subclassResponsibility method. In general, Squeak error messages are quite unhelpful. Like, the first thing everyone encounters is a DNU for nil - the message could be way more informative. > Or maybe change #new to be > > new > self = Collection ifTrue: [^OrderedCollection new]. > ^super new This one I do not like. - Bert - |
On Sun, 21 Jan 2007 21:23:54 +0100, Bert Freudenberg wrote:
> Am Jan 21, 2007 um 21:15 schrieb Ralph Johnson: > >> On 1/21/07, Klaus D. Witzel wrote: >>> Hi Ralph, >>> >>> I have nothing to say against your arguments :) just asked if it is >>> possibile to be more polite to potential converts when they begin >>> using a >>> workspace :) >> >> Sure, it is good to be friendly. >> >> Perhaps change Collection>>do: to >> >> do: aBlock >> self class = Collection ifTrue: [self error: 'Collection is an >> abstract class. You should probably use OrderedCollection instead.']. >> self subclassResponsibility > > That's an excellent idea! I agree. But it might create a problem for (re-)engineering tools, which expect "self subclassResponsibility" to be the one-and-only statement in such situations. > Maybe we could even reword the notice in the general > subclassResponsibility method. In general, Squeak error messages are > quite unhelpful. Like, the first thing everyone encounters is a DNU for > nil - the message could be way more informative. Also, agreed. Mind to sketch an example for the DNU text on nil, since I'm not sure that I understand what's wrong with the ages old DNU error text. Thank you. >> Or maybe change #new to be >> >> new >> self = Collection ifTrue: [^OrderedCollection new]. >> ^super new > > This one I do not like. Me too. #new can only have one implementor (the primitive call done in Behavior) plus, ((aClass new) class == aClass) must hold, otherwise one's rather lost instead of being excited about Smalltalk :) /Klaus > - Bert - |
Am Jan 22, 2007 um 9:39 schrieb Klaus D. Witzel:
> On Sun, 21 Jan 2007 21:23:54 +0100, Bert Freudenberg wrote: >> Maybe we could even reword the notice in the general >> subclassResponsibility method. In general, Squeak error messages >> are quite unhelpful. Like, the first thing everyone encounters is >> a DNU for nil - the message could be way more informative. > > Also, agreed. Mind to sketch an example for the DNU text on nil, > since I'm not sure that I understand what's wrong with the ages old > DNU error text. Thank you. Well, newbies take the text literally. They wonder *why* UndefinedObject does not understand the perfectly valid (because it exists in the system) message. There are (at least) to obstacles to understanding here. Firstly, they focus on the message name, check for misspellings etc. It does not even occur to them that it is not the *message* that is wrong, but the *receiver*. But that is usually what went wrong. This applies to all DNU's. In the special case of UndefinedObject DNU, it's totally non-obvious that "UndefinedObject" has anything to do with "nil". And even if they knew, they wonder how that thing could have *become* nil. Actually, most often this is a strong hint that something was not initialized the way it should have, but still *is* nil. This "gut feeling" is something you only develop with experience. I doubt we could express this in the error text ... although an "extended help" button might hint at it. Anyway, I'd argue that an error text more like "... is nil" would be way more helpful, although technically of course it is not as accurate. - Bert - |
On Mon, 22 Jan 2007 11:47:55 +0100, Bert Freudenberg wrote:
> Am Jan 22, 2007 um 9:39 schrieb Klaus D. Witzel: >> On Sun, 21 Jan 2007 21:23:54 +0100, Bert Freudenberg wrote: >>> Maybe we could even reword the notice in the general >>> subclassResponsibility method. In general, Squeak error messages are >>> quite unhelpful. Like, the first thing everyone encounters is a DNU >>> for nil - the message could be way more informative. >> >> Also, agreed. Mind to sketch an example for the DNU text on nil, since >> I'm not sure that I understand what's wrong with the ages old DNU error >> text. Thank you. > > Well, newbies take the text literally. They wonder *why* UndefinedObject > does not understand the perfectly valid (because it exists in the > system) message. > > There are (at least) to obstacles to understanding here. > > Firstly, they focus on the message name, check for misspellings etc. It > does not even occur to them that it is not the *message* that is wrong, > but the *receiver*. But that is usually what went wrong. This applies to > all DNU's. > > In the special case of UndefinedObject DNU, it's totally non-obvious > that "UndefinedObject" has anything to do with "nil". And even if they > knew, they wonder how that thing could have *become* nil. Actually, most > often this is a strong hint that something was not initialized the way > it should have, but still *is* nil. This "gut feeling" is something you > only develop with experience. I doubt we could express this in the error > text ... although an "extended help" button might hint at it. Yeah, *that* makes sense: a "what's up?" button or bubble-text, following the #explain idea but offering possible alternatives (nil versus #zork). Could be made available by the class side of exceptions, defaulting to "this is an exception for which I have as yet no explanation" ;-) > Anyway, I'd argue that an error text more like "... is nil" would be way > more helpful, although technically of course it is not as accurate. This can be let as is for the pros, IMHO :) /Klaus > - Bert - > > > |
In reply to this post by Klaus D. Witzel
> Me too. #new can only have one implementor (the primitive call done in
> Behavior) plus, ((aClass new) class == aClass) must hold, otherwise one's > rather lost instead of being excited about Smalltalk :) In fact, #new has 103 implementors in Squeak 3.9. But it is unusual for #new to return an instance of a different class. -Ralph Johnson |
Hi Ralph,
on Mon, 22 Jan 2007 16:54:42 +0100, you wrote: >> Me too. #new can only have one implementor (the primitive call done in >> Behavior) plus, ((aClass new) class == aClass) must hold, otherwise >> one's >> rather lost instead of being excited about Smalltalk :) > > In fact, #new has 103 implementors in Squeak 3.9. Mea culpa, must have had slot #basicNew in mind (therefore mentioned the primitive call) while writing about slot #new. Crap. Thanks. > But it is unusual > for #new to return an instance of a different class. Right. /Klaus > -Ralph Johnson > > |
In reply to this post by Ralph Johnson
"Ralph Johnson" <[hidden email]> writes:
> Collection is an abstract class, so you should never say "Collection new". For newbie friendliness, it would help to do one of the following: Option 1. Make "Collection new" return an error describing the situation. For example: new ^(self == Collection) ifTrue: [ self error: "Collection is abstract and cannot be implemented" ] ifFalse: [ super new ] With some thought, this bit of code could be abstracted, so people can just write something like: new ^self newIfSubclass Even better, we could set things up so that this would work: Collection class>>initialize self abstract That is, we could directly mark classes as abstract, and the default "new" implementation would check this flag. Option 2. Just make it work! Have the method return some reasonable default. This is not an area where the system will collapse if they get the wrong collection type; their program will simple run slowly. new ^(self == Collection) ifTrue: [ OrderedCollection new ] ifFalse: [ super new ] -Lex |
Hi Lex,
on Wed, 24 Jan 2007 17:29:49 +0100, you wrote: > "Ralph Johnson" <[hidden email]> writes: >> Collection is an abstract class, so you should never say "Collection >> new". > > For newbie friendliness, it would help to do one of the following: > > Option 1. Make "Collection new" return an error describing the > situation. For example: > > new > ^(self == Collection) ifTrue: [ > self error: "Collection is abstract and cannot be implemented" > ] ifFalse: [ > super new ] > > > With some thought, this bit of code could be abstracted, so people can > just write something like: > > new > ^self newIfSubclass > > > Even better, we could set things up so that this would work: > > Collection class>>initialize > self abstract Looks great: can be checked by default handlers and debugger, when need arises (and lazyness is at work). > That is, we could directly mark classes as abstract, and the default > "new" implementation would check this flag. Uhm, doesn't really taste good (that the default #new implementation gets involved into preventive error handling, I mean). > > > Option 2. Just make it work! Have the method return some reasonable > default. This is not an area where the system will collapse if they > get the wrong collection type; their program will simple run slowly. > > new > ^(self == Collection) ifTrue: [ > OrderedCollection new > ] ifFalse: [ > super new ] IMHO this is as hard to debug for noobs (and for pros as well, between 02:30 and 03:45 in the morning ;-) as it is with the cause of this thread. /Klaus > -Lex > > > > |
Free forum by Nabble | Edit this page |