Peter W. Lount wrote:
p.s. check out the Version of Smalltalk from the 24th century on the web site. I think you'll like it. ;--)
[site contains an audio file of Star Trek's Picard & Data]
Picard: Smalltalk? Data: Yes, sir.... I've found that humans often use smalltalk during awkward moments, therefore I've written a new subroutine for that purpose.
So, I guess that they are *still* using subroutines in the 24th century. I guess we shouldn't be looking to hard at their UI's either.
At least Data didn't have to reboot himself.
mklein@alumni.caltech.edu
Michael S. Klein wrote:
Peter W. Lount wrote:
p.s. check out the Version of Smalltalk from the 24th century on the web site. I think you'll like it. ;--)
[site contains an audio file of Star Trek's Picard & Data]
Picard: Smalltalk? Data: Yes, sir.... I've found that humans often use smalltalk
Can't someone edit the sound bite to end here? I think that it sounds better.
during awkward moments, therefore I've written a new subroutine for that purpose.
So, I guess that they are *still* using subroutines in the 24th century. I guess we shouldn't be looking to hard at their UI's either.
At least Data didn't have to reboot himself.
Not true! Data has had to be rebooted several times. Once at least, he did have to reboot himself in some story about time-travel, San Francisco, and Mark Twain.
mklein@alumni.caltech.edu
John-Reed Maffeo
- Now that I found Squeak, I don't need Startrek anymore;)
"Michael S. Klein" wrote:
Picard: Smalltalk? Data: Yes, sir.... I've found that humans often use smalltalk during awkward moments, therefore I've written a new subroutine for that purpose.
So, I guess that they are *still* using subroutines in the 24th century.
Huh? Methods are just subroutines by another name. Yes, there is a (single) difference (polymorphism). Everything else is old hat: parameter passing (with an additional implicit 'self' parameter), local variables, synchronous call/return sequence, recursion etc.
This was one of my initial grudges against Smalltalk: Lots of new words meaning just the same old stuff, making it difficult to understand what was really new about Smalltalk. Just try it:
Smalltalk terminology Standard terminology method subroutine message send subroutine call object data structure self first parameter
I concede there are important differences, and a different set of concepts. But some Smalltalk-80 books said that the difference is in methods and messages, and that's just not true; these concepts may have been designed to be different but turned out to map quite clearly to well-established concepts.
Regards, Joachim
This was one of my initial grudges against Smalltalk: Lots of new words meaning just the same old stuff
.. . .
I concede there are important differences, and a different set of concepts.
A crticial concession: Important differences and different concepts. This is *why* its a good idea to use different words.
Messaging is a different concept from a "subroutine call with special first parameter." Trying to think about oo programming in simple imperative concepts is one of the things that kept me from "getting it" with oodls initially, because I was always thinking about these things constructs by their analogues.
In general, a programming language concept *is* a thing which is different from the various ways it might be implemented in another programming language. I can think of monitors and CSS as an implementation of semaphores and streams as well, but to do so simply misses the point.
Besides, there's nothing special about subroutines either. Subroutines are just a couple of pushes onto a stack, a save of an instruction pointer, and a naked jump to some other code. And a while loop is just a special case of a goto. Why don't we just go back to coding purely with stores, loads, tests, logical ops and jumps? Aren't they all just the same thing?
And heck, every programming language concept is just an implementation of a state machine with a read/write movable head and a very large tape. Why don't we just express programming concepts in terms of Turing machine programming techniques?
All meaningful programming languages are capable of expressing any computable function. This doesn't mean that all programming language concepts are "just the same thing."
Correspondence between those languages, in the sense that one might be implemented in another, isn't necessarily a useful observation, even if true. But more important, expecting a new programming language to be capable of expressing a program that another one cannot is unreasonable -- at least theoretically speaking, they're all just flawed implementations of a Turing machine, capable of generating the same set of programs.
Although one might attempt to reason about Smalltalk code by way of these analogues, I think it is losing to try to learn Smalltalk in this fashion, at least once you have gotten past the syntax and basic semantics stage. Once I recognized that these *were* a different set of concepts with important differences, and started to think about them independently of the various possible ways to implement them, I found myself empowered in a way that surprised me.
[Mind you, I had the Smalltalk books on my Shelf since I bought them at graduate school in the early 80's -- I, too, simply looked at the books, tried to figure out how it was like Pascal, Algol, C and Lisp, and shelved it as "nothing new." Almost two decades later, after a fair amount of experience programming in OODLs, I found Squeak and ultimately learned something, I think, in part BECAUSE of the new nomenclature.
Edsger Dijkstra wasn't the first to note, although he was a principal exponent of the notion, that a notation and language colors and impacts the quality of our ability to conceive and implement solutions, and hence, the scope and quality of programs we are capable of creating given a fixed amount of programmer effort. Coding Smalltalk by thinking about it as C with some tweaks leads to frustration, not with the words, but with the mismataches between concepts. Coding Smalltalk qua Smalltalk is another thing entirely.
Agreed, the words are distracting at first, but like all techniques learned, they are quickly absorbed once you set out to learn them, and rapidly become second nature. Interestingly, as I found myself misusing the words in different ways initially, I learned that I was likewise misunderstanding the concepts. Nomenclature is a VERY useful thing. Agreed, I can code up Smalltalk methods in C, modelling them as subroutines. But I no longer think of them in this way, and found Squeak a much nicer place to play once I did.
Excellent answer! Ftm, all programming languages are eventually binary streams - why not just program in machine language?!!!
I respectfully suggest that Joachim read your post carefully. You're absolutely right - that type of thinking is what will prevent him from fully exploiting the object-oriented model.
Larry -- rapp@lmr.com
"Andrew C. Greenberg" wrote:
This was one of my initial grudges against Smalltalk: Lots of new words meaning just the same old stuff
. . .
I concede there are important differences, and a different set of concepts.
A crticial concession: Important differences and different concepts. This is *why* its a good idea to use different words.
Not if there are strong similarities. In such a case, the new nomenclature should retain a similarity to the original concepts. Heck, it would have helped if the Smalltalk literature had contained a hint like "a message send is just like a subroutine call, except that....". This would have helped me *tremendously*.
Messaging is a different concept from a "subroutine call with special first parameter."
Right. I overlooked the dynamic dispatch involved (which is the central concept; the implicit parameter is just a technical detail).
Trying to think about oo programming in simple imperative concepts is one of the things that kept me from "getting it" with oodls initially, because I was always thinking about these things constructs by their analogues.
Hm. I'm doing OO programming based on the ADT concept, and quite successful with that (I'm helping out at a customer site, and whenever they have a design problem they ask me to solve it...).
In general, a programming language concept *is* a thing which is different from the various ways it might be implemented in another programming language. ...
Besides, there's nothing special about subroutines either. ... And a while loop is just a special case of a goto. ...
And heck, every programming language concept is just an implementation of a state machine with a read/write movable head and a very large tape. ...
All meaningful programming languages are capable of expressing any computable function. This doesn't mean that all programming language concepts are "just the same thing."
Correspondence between those languages, in the sense that one might be implemented in another, isn't necessarily a useful observation, ...
Fully agreed. Programming language design is about human psychology, and form matters greatly when the human mind is involved. But that's not the point I was trying to make. My point was that the Smalltalk presentation downplayed the similarities and emphasized the differences. This mislead me into assuming differences where there were none (and took up mental capacity that I'd have liked to spend for the really interesting differences).
Although one might attempt to reason about Smalltalk code by way of these analogues, I think it is losing to try to learn Smalltalk in this fashion, at least once you have gotten past the syntax and basic semantics stage. Once I recognized that these *were* a different set of concepts with important differences, and started to think about them independently of the various possible ways to implement them, I found myself empowered in a way that surprised me.
[Mind you, I had the Smalltalk books on my Shelf since I bought them at graduate school in the early 80's -- I, too, simply looked at the books, tried to figure out how it was like Pascal, Algol, C and Lisp, and shelved it as "nothing new."
The concept of a class, together with dynamic dispatch, was really novel. What was not novel was the flow of control once the system had determined which routine to call. The Smalltalk literature just failed to mention this, and I had to painstakingly find this out by tracing the execution of the model VM in one of the Smalltalk books.
Almost two decades later, after a fair amount of experience programming in OODLs, I found Squeak and ultimately learned something, I think, in part BECAUSE of the new nomenclature.
Well, I had to go the detour via C++ to find out what all this nomenclature actually meant.
Agreed, the words are distracting at first, but like all techniques learned, they are quickly absorbed once you set out to learn them, and rapidly become second nature. Interestingly, as I found myself misusing the words in different ways initially, I learned that I was likewise misunderstanding the concepts. Nomenclature is a VERY useful thing. Agreed, I can code up Smalltalk methods in C, modelling them as subroutines. But I no longer think of them in this way, and found Squeak a much nicer place to play once I did.
Unfortunately, special nomenclature creates unnecessary barriers. Nomenclature should reflect similarities as well as differences. I know this is different; and I know it is probably asking too much of the researchers at their time to present not only a wholly new environment but to also fully understand what's similar and what's dissimilar, and in what ways a similarity is relevant or not. Still, I would have liked to know that.
Regards, Joachim
"Joachim Durchholz" wrote, in part:
The concept of a class, together with dynamic dispatch, was really novel. What was not novel was the flow of control once the system had determined which routine to call. The Smalltalk literature just failed to mention this, and I had to painstakingly find this out by tracing the execution of the model VM in one of the Smalltalk books.
What I hear here is that you'd have benefitted from even a single example of the correspondence between methods and subroutines, especially if the differences were highlighted by explicit commentary. Many more may yet follow that path. Would you take an hour to create the annotated example that would address that educational goal?
Dick
Dick Karpinski wrote:
"Joachim Durchholz" wrote, in part:
The concept of a class, together with dynamic dispatch, was really novel. What was not novel was the flow of control once the system had determined which routine to call. The Smalltalk literature just failed to mention this, and I had to painstakingly find this out by tracing the execution of the model VM in one of the Smalltalk books.
What I hear here is that you'd have benefitted from even a single example of the correspondence between methods and subroutines, especially if the differences were highlighted by explicit commentary. Many more may yet follow that path. Would you take an hour to create the annotated example that would address that educational goal?
Ouch... I should have kept my large mouth shut. I'm having some difficulties complying whith this one. My thinking mode is very abstract, and not using examples at all; so I'm having difficulties producing one. I'll produce a raw explanation instead; somebody with a better grasp of examples could add one. Besides, English is not my native tongue, so somebody please clean the following up.
Explanation of message sends for traditional programmers -------------------------------------------------------- You may be wondering how this all relates to the more traditional ways of programming. What "is" a message send in terms of a standard programming language? Well, it's both very traditional and novel. It is traditional in the mechanics of execution. The caller provides a set of parameter values for the message handler ((is "message handler" the right terminology?)). A message handler executes just like a subroutine: It accepts the parameter values in its formal parameters and does whatever it wants. It may have local variables, and it may return a value that will become the result of the call. What's not so traditional is the process that selects the message handler. ((Add a reference to the following topics here: (a) overriding, (b) dynamic binding, (c) polymorphism.))
Another thing that should be explained to OO programmers is that Smalltalk classes are just implementation inheritance; Smalltalk has no types, so there is no interface inheritance. What's closest to a type in Smalltalk is called a "protocol" here. (I have mentioned elsewhere in this list that Smalltalk might benefit from formalizing the protocols, but that's an entirely different issue.)
Regards, Joachim
Explanation of message sends for traditional programmers
You may be wondering how this all relates to the more traditional ways of programming. What "is" a message send in terms of a standard programming language? Well, it's both very traditional and novel. It is traditional in the mechanics of execution. The caller provides a set of parameter values for the message handler ((is "message handler" the right terminology?)). A message handler executes just like a subroutine: It accepts the parameter values in its formal parameters and does whatever it wants. It may have local variables, and it may return a value that will become the result of the call. What's not so traditional is the process that selects the message handler. ((Add a reference to the following topics here: (a) overriding, (b) dynamic binding, (c) polymorphism.))
Yeah, that old tradition of double dispatching, routine passing of lambdaesque functional parameters, and other things that make explaining:
String streamContents: [:s | foo process: s ]
in terms of function calls just cake. Or even better yet:
'Now here''s some Real Progress' displayProgressAt: Sensor cursorPoint from: 0 to: 10 during: [:bar | 1 to: 10 do: [:x | bar value: x. (Delay forMilliseconds: 500) wait]].
just simple to explain as a procedure call. And we routinely write such code in imperative language all the time, don't we?
With all due respect, while your points might be well taken, these types of operations took my breath away the first time I saw them, and I only really got it when I realized that a message send is a message send, and not a procedure call.
If we are discussing Turing equivalence, there is no dispute here. But if we are discussing pedagogy here, what Joachim suggests to me makes no sense at all. Perhaps as an initial pass, yes. But only for the sake of a quick bootstrapping, so on the second pass there can be a real understanding.
"Andrew C. Greenberg" writes:
Explanation of message sends for traditional programmers ... handler. ((Add a reference to the following topics here: (a) overriding, (b) dynamic binding, (c) polymorphism.))
Yeah, that old tradition of double dispatching, routine passing of lambdaesque functional parameters, and other things that make explaining:
String streamContents: [:s | foo process: s ]
in terms of function calls just cake. Or even better yet:
'Now here''s some Real Progress' displayProgressAt: Sensor cursorPoint from: 0 to: 10 during: [:bar | 1 to: 10 do: [:x | bar value: x. (Delay forMilliseconds: 500) wait]].
just simple to explain as a procedure call. And we routinely write such code in imperative language all the time, don't we?
With all due respect, while your points might be well taken, these types of operations took my breath away the first time I saw them, and I only really got it when I realized that a message send is a message send, and not a procedure call.
How may I understand these tiny examples? My own educational goals would be well served by understanding them clearly.
Dick
"Andrew C. Greenberg" wrote:
Yeah, that old tradition of double dispatching, routine passing of lambdaesque functional parameters, and other things that make explaining:
String streamContents: [:s | foo process: s ]
in terms of function calls just cake.
Such things are standard issue in functional programming (which does not claim to have a special "message passing" thing). Yes, it is very special. And it is not common in imperative programming. But it doesn't warrant a new name for things today; mainstream terminology is fully capable of describing these features. (I'm well aware that mainstream terminology in the 80ies wasn't there yet.)
'Now here''s some Real Progress' displayProgressAt: Sensor cursorPoint from: 0 to: 10 during: [:bar | 1 to: 10 do: [:x | bar value: x. (Delay forMilliseconds: 500) wait]].
just simple to explain as a procedure call. And we routinely write such code in imperative language all the time, don't we?
With all due respect, while your points might be well taken, these types of operations took my breath away the first time I saw them, and I only really got it when I realized that a message send is a message send, and not a procedure call.
Hm. I did exactly this type of things in my student days with a Lisp system. It took my breath away, but it was entirely nonpolymorphic.
If we are discussing Turing equivalence, there is no dispute here. But if we are discussing pedagogy here, what Joachim suggests to me makes no sense at all. Perhaps as an initial pass, yes. But only for the sake of a quick bootstrapping, so on the second pass there can be a real understanding.
Ah well, we all have our different learning histories and habits. I understand the stuff better if I see how new stuff relates to known stuff. I was under the impression that this would benefit everybody, but it's obvious that I don't meet consensus here.
Regards, Joachim
squeak-dev@lists.squeakfoundation.org