About KCP and automatic initialize

Richard A. O'Keefe ok at cs.otago.ac.nz
Wed Sep 17 04:18:43 UTC 2003


"Andreas Raab" <andreas.raab at gmx.de> wrote:
	However, what you are talking about now is a builtin problem in Smalltalk.
	You absolutely have to go to the meta level in order to make any other kinds
	of initializers. And that's the real problem.
	
I think we are using different terminology to say the same thing here.
I talk about "class-side" and you talk about "going to the meta-level".

	Most people (even experienced ones) don't "get" the meta level. It is
	dangerous to use the meta-level for casual stuff. Many other languages
	provide some form of initialization messages (constructors) without having
	to expose the meta-level (if it is even accessible).
	
And that's the problem.

	What the new/initialize proposal gives you is a way to defer
	that exposure for a while (which I think we both agree on that
	it is advantageous at least in early stages).

Unfortunately, it does this by teaching people to do the wrong thing.

Let's take the humble example of a Point.

If we don't teach them how to put #x:y: in the Point class,
then what _can_ we teach them?  Do we teach them to do
    (Point new setX: 2; setY: 3; yourself)?
Because that's what this proposal is all about.  It's all about
saying "make it easy for beginners to use #new for all their classes".

We all know about "regression under stress", don't we?  The psychological
phenomenon in which people who have to complete a task under conditions
of stress tend to revert to earlier-learned material, even when later-
learned material would make it easier to complete the task.

	Unfortunately, we have no alternative at this point -
	there is nothing, absolutely nothing we can do to defer the meta-level
	exposure in any other way as the syntax of Smalltalk prevents us from
	providing any other generalized mechanism. At least unless you want to get
	serious about changes to the language. 
	
RIGHT.  At last we have someone talking sense about a change that really
COULD address the problem.

	It would be trivial with a tiniest bit of modification to the language
	itself, merely by providing an attribute to an instance side method which
	signifies this as a "constructor message" and simply compiles the
	appropriate class-side method, e.g., something like (using "+" as the
	"constructor message flag")
	
	+initializeWithFoo: aFoo bar: aBar
		myFoo := aFoo.
		myBar := aBar.
	
	could simply compile a class-side method which is
	
	MyClass class>>initializeWithFoo: aFoo bar: aBar
		^super new initializeWithFoo: aFoo bar: aBar
	
	Simple, isn't it?

Yes.  YES.  **YES**!   Let's DO it!

Here at last we finally have a proposal that really attacks the
fundamental problem.  Let's do it!  Let's try it!  I love it already!

	So, if we wanted to be real about fixing this issue I don't
	think we could stop short of changing the language.

And I don't think we *should* stop short of changing the language.
A really nice thing about this proposal of yours is that it doesn't
break working code.  People don't _have_ to deal with it if they
don't want to.  And people who don't want to deal with the class side
yet don't have to do that either.  I know this approach is redundant,
but I think it could be a real winner.

	I am simply not deluding myself about the storm of protest that
	would break loose if anyone would make that proposal.

Well, you're not getting any protest from *me*.  It seems to me that this
is the right *kind* of change.  It doesn't break anything; it addresses
the real problem; it really genuinely *does* avoid the need to go to the
meta-level; it doesn't have hidden run-time costs we need to worry about;
there are a number of compatibility issues I've thought of which are
surprisingly straightforward to deal with.

	So the only thing we _can_ do is to come up with a "reasonable
	approximation".  Now you argue that we shouldn't even do that.
	
No, I argue that we shouldn't use an *unreasonable* approximation.
I have now repeatedly stated that if #new were changed to call
#initializeYourself (or some other method name not currently used)
that would be fine.  It's changing #new to call an *existing* method
which makes it an unreasonable approximation.

	Ho hum.  By the end of the day this really means we can't change
	anything on a larger scale.  Each and any such change would
	break compatibility with other Smalltalks.  If that is what
	you're after then you just cannot move Squeak forward.

All of this hinges on your entirely false assumption that I am objecting
to changes to Smalltalk as such.  I'm not.  I'm objecting to BAD changes.
You have brilliantly demonstrated what a GOOD change for this issue might
look like.

	Why not instead set the pace?
	
Why not do a bit of competent software engineering at the same time
and *not* have #new invoke an existing method in an incompatible way?

	> One of the things that has annoyed me in the past about Squeak
	> is that some great new tool (like the Refactoring Browser) becomes
	> available for other Smalltalks, finally (ah, finally, after a LONG
	> wait) becomes available for Squeak, but then Squeak changes so I still
	> cannot use it.
	
	Which (to me) translates into: Don't change Squeak.

This is entirely unfair.  I say "there IS a big change to Squeak that I want
and I don't like the way people keep taking it away before I get a chance to
use it", and you turn that into "you don't want any changes".

There are lots of changes I want in Squeak, like working BlockContexts.
I've been wanting that one for years.  

Get used to it:  if we want changes in some places, we need stability in
others.

	Whatever you do will break something

Not if the person who breaks it accepts responsibility for fixing it.

	Sorry, but the only unchanging rule about life and software
	systems is that they change constantly.

Some things have to stay stable so that other things can change.

R has been mentioned several times in this mailing list.  The existence
of R is a change.  R keeps on changing dramatically.  But if there were
frequent incompatible changes to C and Fortran, R development would come
to a chaotic halt.  It is only possible for R to change because C and
Fortran don't.  Or rather, they don't change in ways that break working
code.  When I can finally get my hands on a C99 compiler (and gcc isn't
quite there yet, although it's getting closer), R should cope with that.
(It does cope with gcc.)  But R's Fortran code has to be compiled with a
Fortran 77 compiler, not a Fortran 90 compiler.  The code would probably
compile, but R doesn't yet know how to call Fortran 90 code.  Some day
someone will fix this, but there will only be some point in doing so because
Fortran 90 linkage won't change much.

I'm starting to get excited about Java, because I've now got my hands on
a program verification tool for Java.  It can do really cool things, but
if Java changed as fast as Squeak changes, this tool could never have been
written.  Nothing can make Java lovable, but it's enough of a change to
tip me from Eiffel to Java.

	You've got to find a way to live with it and one simple way of
	doing it is to stick to a particular version of Squeak until a
	newer one supports all of the tools/libraries that you want to
	use.

But that means "never".

	Of course, unless you actively help to get them forward this may
	never be the case.  Welcome to the world of open source software.

No, this is the world of Squeak.  Other open source projects I'm involved
with are nothing like this.  SWI Prolog, to which I have contributed a lot
of bug reports and a modest amount of code, has acquired fairly major new
features over the years, including multithreading.  A lot of the stuff is
third-party, contributed a while back and still useful because Jan doesn't
like breaking things.  That has never stopped him moving forward.  If
SWI Prolog changed in the ways that Squeak does, most of the third-party
packages that exist for it would never have been written, and those that
had been would now be dead.  R doesn't change like that.  There are big
changes to R, my word yes.  Adding S4 classes to R was a pretty major
change.  Adding namespaces was another major change.  But they are changes
that don't break things, and R is valuable for that very reason.

	> We are ALL in agreement that Squeak should move forward.
	
	No, Richard.  You are not.  And before you write back in a
	message using all caps think carefully about what you are saying
	in this very message.

Please read what I write.
Take a few seconds to seriously consider the possibility that
the #new-calls-#initialize (instead of #new-calls-#initializeYourself)
change might *really* be a bad change.
Ask yourself whether someone who has spent hours digging around in Squeak
to find evidence for his point (and has found a surprising amount)
might just possibly by something other than a simple obscurantist.
Ask youself whether someone who asks for big extensions (like the RB)
could really honestly be said to be opposed to change.

Ask yourself whether someone who is enthusiastic about the language
change you have just proposed could possibly have the attitidues
you falsely ascribe to me.

	> So I am opposed to the proposed change not because I want Squeak to
	> be mired in the past but because I *don't* want it to be 
	> mired in the past.
	
	In this case, you would have to agree on even more radical changes than the
	one proposed here (such as the above change to the language itself).

Yes, I *do* agree to that.

	Unfortunately, I have no evidence that you are in favour of such
	changes - quite to the contrary actually considering messages
	I've read from you in the past.
	
Next time we're on opposite side of a debate, remember your drastically
incorrect conclusion.  I *am* in favour of changes that fix problems.
I am *not* in favour of bad changes that introduce incompatibility
*without* fixing problems.

	I understand your frustration but I don't understand why you refuse changes.

I don't refuse change.  I refuse BAD change.
It's not hard to understand, is it?

	I have outlined a simple solution in the above to address pretty
	much all of the points you were raising.  Given your somewhat
	arbitrarily changing point of view between "do not make things
	incompatible" and "fix this problem in a way that addresses the
	concerns" I do not see how one would achieve such a thing.

My point of view hasn't changed at all, let alone arbitrarily.
I am opposed to a bad change that introduces incompatibility
without really fixing the category of problems it is supposed to address.

I am *for* a similar change, indeed I have *suggested* a similar change
which is no more effective, but doesn't introduce incompatibility.

I am *for* the language change you have proposed which gets to the heart
of the matter, and if I didn't have query judgements for INEX'03 looming
over me like a very great deal of work indeed, I'd volunteer to implement it.

	If you want to change and fix this issue for real you cannot be
	compatible.

Yes you can.  I've shown one way (have #new call a novel method,
#initializeYourself, instead of calling an existing method, #initialize),
and you have shown a better way.  Both of those retain all the compatibility
I care for.

You seem to misunderstand what compatibility means.

Compatibility doesn't mean that the new system is exactly the same as
the old one, and it doesn't mean that you can't do things *differently*
in the new system.  It means that things you did in the old system still
work in the new one.

My change, adding

    "Object methods for 'initialize/release'"
    initializeYourself
      ^self
    "Object class methods for 'instance creation'"
    new
      ^super new initializeYourself

has the regrettable effect of encouraging bad design,
BUT it is rather unlikely to break anything (the system doesn't use
#initializeYourself and none of the packages I've checked does either).

Your change, adding "+<method>" as legal syntax, and having it act as
if "<method>" without the + had appeared and also adding an
instance creation method "<header> ^self basicNew <header>" to the class,
goes right to the heart of the matter, BUT it doesn't do anything at all
to any class that doesn't use that syntax.  That's compatible.

	If you want to stay compatible you cannot even
	attempt to fix this problem.

You have, yourself, proven just now that that simply isn't true.
*You*, Andreas Raab, *have* produced a good attempt to fix the
fundamental problem, and it _is_ compatible.

	It would be nice if you could clear your mind a little about
	what it is you _really_ want.

Someone tells me something can't be done, in a message in which he
has *done* it, and he tells *me* to clear *my* mind?

My mind is perfectly clear in this matter.  I want something I *can*
have:  a better Squeak, without gratuitous code breakage, and I am
deeply grateful to Andreas Raab for having the courage to suggest a
way that I hadn't quite had the courage to suggest myself.

Oh yes, another example of compatibility AND change.  Since its inception,
R has been an interpreter.  R source code is parsed to R data structures,
and a C program walks over the abstract (well, not _that_ abstract) syntax
tree.  There are now two people working on compilers for R:  one is working
on a byte-code compiler and the other is working on a native-code compiler.
The byte-code compiler will probably be there in the next major release or
the one after that; the native-code compiler is intended to be proof-of-
concept.  Both of these compilers are possible only because the basics of
R have _not_ changed; the native-code compiler is partly based on an
abandoned byte-code compiler written six years ago, and the fairly major
extensions that have happened since then are still compatible as far as
a compiler is concerned.  (There's one new thing that has been added which
I know caused a problem, but one can always revert to the interpreter.)



More information about the Squeak-dev mailing list