Should every kernel class x provide support for (x new) printString and (x new) hash

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Should every kernel class x provide support for (x new) printString and (x new) hash

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. 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


Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Bert Freudenberg
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 -



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Ralph Johnson
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

Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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


Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Ralph Johnson
> 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

Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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 -
>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Philippe Marschall
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
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

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

Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Bert Freudenberg
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 -



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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 -


Reply | Threaded
Open this post in threaded view
|

DNU wording (was Re: Should every kernel class ...)

Bert Freudenberg
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 -



Reply | Threaded
Open this post in threaded view
|

Re: DNU wording (was Re: Should every kernel class ...)

Klaus D. Witzel
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 -
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Ralph Johnson
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

Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Lex Spoon-3
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



Reply | Threaded
Open this post in threaded view
|

Re: Should every kernel class x provide support for (x new) printString and (x new) hash

Klaus D. Witzel
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
>
>
>
>