At 9:49 PM 8/25/98, Travis Griggs wrote:
Maurice Rabb wrote:
<snip> For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value? <snip>
Just out of curiousity and because it's late and I'm in a devil's advocate mood... What's wrong with diluting protocols? I have vaguely seen threads about this, but I've never really seen (or paid attention long enough), a good reason not to dilute protocols. It's just kind of one of those unexplained commandments (too me). I have personally thought many times that it would be cool to totally blur the lines between collections and single objects in Smalltalk for quite some time. Isn't that one of the things Lisp kind of does? Why does enumeration have to be bound to a storage strategy?
Travis--
Well lets review what the wise ones have said:
At 7:46 AM 5/29/98, Ralph E. Johnson wrote RE: Pluggability
I looked at Actions, and liked what I saw. I've seen and done things like that before. My main complaint is that the method should be #value and #value:, not #evaluate and #evaluate: A block is a built-in Action, and it already defines a protocol, so we should use it.
One of the interesting things is that Actions define both #value and #evaluate. So, you can use an Action instead of a block, but you can't use a block instead of an Action. Why? A block is just a built-in Action. Now, the fileIn defines #evaluate and #evaluate: for blocks, but that does not passify me! We should not proliferate protocols, and #value and #value: are well defined and short. They are not particular logical, but that is not so important for the most common messages. #at:put: is not particularly logical, either.
It is a mistake to put #evaluate and #evaluate: in Object. ParcPlace did this with #value and #value: for awhile, and the problem is that you lose useful information because errors don't get caught right away but the system keeps on running for awhile before finally noticing some error. It is so easy to convert an object into an Action (just send #asAction to it) that you don't need these helper methods in Object. Further, using #asAction provides helpful information to the reader that an object is going to be used as an action, so it gives hints that can prevent the reader from having to keep on reading.
BlockContext should define asAction to return self, not to make a new action that returns itself. A block is just a built-in action.
(I'm hoping that if I say it enough, people will believe me!)
At 4:08 PM 5/29/98, Andreas Raab continued:
It is a mistake to put #evaluate and #evaluate: in Object. ParcPlace did this with #value and #value: for awhile, and the problem is that you lose useful information because errors don't get caught right away but the system keeps on running for awhile before finally noticing some error.
I absolutely agree. One thing I don't like at the moment is that Object implements #do: It's easy enough to define either asCollection or to implement #do: in classes where this is really needed.
(I'm hoping that if I say it enough, people will believe me!)
I do ;-)
Andreas
Turning to the "Way Back Machine" even further back, a _very_ wise Smalltalker wrote Re: Proposal: Object>>valueIn:
At 2:44 PM 11/3/97, Travis Griggs wrote:
Ah yes, you are right. Having now thought about it, I think they should both exist. They accomplish different things semantically. I still like the presence of do: in Object for the purpose of "iterating" over single objects as if they were indeed aggregations.
--
If you think about it you could argue that this is the same argument as #valueIn: (i.e. #in: as it is now) vs. #do: The semantics of a Collection iterating over itself, and 0-1-Many iterating over itself _as_ a Collection are subtly different enough to make a separate protocol a "safe" ideal. In practice, the gurus say that it tends to hide normal Collection use errors. Likewise, the potential of not catching error of using any old Object instead of an intended BlockContext.
Personally Travis, I waffle back and forth toward your position. There is a simple elegance in a unilateral #do: and a unilateral #value.
--Maurice
--------------------------------------------------------------------------- Maurice Rabb 773.281.6003 Stono Technologies, LLC Chicago, USA
Maurice Rabb wrote:
At 9:49 PM 8/25/98, Travis Griggs wrote:
Maurice Rabb wrote:
<snip> For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value? <snip>
Just out of curiousity and because it's late and I'm in a devil's advocate mood... What's wrong with diluting protocols? I have vaguely seen threads about this, but I've never really seen (or paid attention long enough), a good reason not to dilute protocols. It's just kind of one of those unexplained commandments (too me). I have personally thought many times that it would be cool to totally blur the lines between collections and single objects in Smalltalk for quite some time. Isn't that one of the things Lisp kind of does? Why does enumeration have to be bound to a storage strategy?
Travis--
Well lets review what the wise ones have said:
At 7:46 AM 5/29/98, Ralph E. Johnson wrote RE: Pluggability
I looked at Actions, and liked what I saw. I've seen and done things like that before. My main complaint is that the method should be #value and #value:, not #evaluate and #evaluate: A block is a built-in Action, and it already defines a protocol, so we should use it.
One of the interesting things is that Actions define both #value and #evaluate. So, you can use an Action instead of a block, but you can't use a block instead of an Action. Why? A block is just a built-in Action. Now, the fileIn defines #evaluate and #evaluate: for blocks, but that does not passify me! We should not proliferate protocols, and #value and #value: are well defined and short. They are not particular logical, but that is not so important for the most common messages. #at:put: is not particularly logical, either.
It is a mistake to put #evaluate and #evaluate: in Object. ParcPlace did this with #value and #value: for awhile, and the problem is that you lose useful information because errors don't get caught right away but the system keeps on running for awhile before finally noticing some error. It is so easy to convert an object into an Action (just send #asAction to it) that you don't need these helper methods in Object. Further, using #asAction provides helpful information to the reader that an object is going to be used as an action, so it gives hints that can prevent the reader from having to keep on reading.
BlockContext should define asAction to return self, not to make a new action that returns itself. A block is just a built-in action.
(I'm hoping that if I say it enough, people will believe me!)
At 4:08 PM 5/29/98, Andreas Raab continued:
It is a mistake to put #evaluate and #evaluate: in Object. ParcPlace did this with #value and #value: for awhile, and the problem is that you lose useful information because errors don't get caught right away but the system keeps on running for awhile before finally noticing some error.
I absolutely agree. One thing I don't like at the moment is that Object implements #do: It's easy enough to define either asCollection or to implement #do: in classes where this is really needed.
(I'm hoping that if I say it enough, people will believe me!)
I do ;-)
Andreas
Turning to the "Way Back Machine" even further back, a _very_ wise Smalltalker wrote Re: Proposal: Object>>valueIn:
At 2:44 PM 11/3/97, Travis Griggs wrote:
Ah yes, you are right. Having now thought about it, I think they should both exist. They accomplish different things semantically. I still like the presence of do: in Object for the purpose of "iterating" over single objects as if they were indeed aggregations.
--
If you think about it you could argue that this is the same argument as #valueIn: (i.e. #in: as it is now) vs. #do: The semantics of a Collection iterating over itself, and 0-1-Many iterating over itself _as_ a Collection are subtly different enough to make a separate protocol a "safe" ideal. In practice, the gurus say that it tends to hide normal Collection use errors. Likewise, the potential of not catching error of using any old Object instead of an intended BlockContext.
Personally Travis, I waffle back and forth toward your position. There is a simple elegance in a unilateral #do: and a unilateral #value.
Scary to have your own quotes, long forgotten, dredged up out of the dust. I feel like Bill (Gates or Clinton, take your pick). What continues to gnaw at brain is what you sum up so well with the statement
"In practice, the gurus say that it tends to hide normal Collection use errors"
When, I read this, the Hemmingway quote, "For every thousand hacking at the leaves there is one hacking at the roots of a problem" comes to mind. It's like it's a copp out. Not that I necessarily have the solution, but to just say it and leave it at that is what bugs me. One of my FAVORITE things about Smalltalk is it's readibility. Computers express ideas one way, and humans another. Smalltalk is one of the BEST practical solutions to allowing me the programmer to express ideas my way, and not the computer's. And in the english language at least, I dilute the hell out of protocols. And for the most part, I get my message across. What's wrong with our language/class library that we can't do the same? Maybe it's just one of those very difficult basically intractible problems...
For a while now, we've had a ?framework? in VisualWorks that I've thought about porting over to Squeak and releasing, but I've always feared the flame about diluting protocols. But tonight, I'm coming out. :) Long ago, I went to work for a company that used Smalltalk to write engineering decision/design tools. We were always crunching numbers, especially collections of numbers. The OrderedCollection was the first thing all of us FORTRAN nerds fell in love with. Patterns of what we did with these collections of numbers began to emerge. We were always adding the elements of one collection against the elements of another, or scaling all of the elements of a collection by some constant, etc. The first thing we did was write a NumericCollection object. At first it was a subclass of Array, then OrderedCollection, and then we got smart and made it a wrapper type object. But we got sick and tired of sending #asNumericCollection to all of our collections. So finally, we just said to hell with it, and we implemented the basic ArithmeticValue protocols in Collection and SequenceableCollection. This was a bit scary for us. But, the use of double dispatching made it a huge mental hard on, because it was so easy and slick. Today, I work at another company that also does engineering/scientific stuff with Smalltalk. This framework is still with me, and it's still my favorite. I used to do homework with it in college all the time, and blow my friends and teachers away. I would just whip up little expressions:
#((1 2 3 4 5) + #(6 7 8 9 10) * 4) sum
and it would blow them away. It's like having MathCad inside of a Turing complete, interactive programming system. What's the point of this long drawn out post? To date, I have had one occurence of one of those errors where I had to scratch my head a little longer than I might have other wise because this is in place. And that's about 5 years of extensive use. In the year and a half or so that we used the wrapper approach, I had many more errors where I forgot to *cast* the collection into a numerically savvy one. Ammusingly, that one error that I speak of occured because I had forgotten to send asNumber to aString. Since String is a subclass of Collection, it dutifually tried to increment all of its character values by the argument, but got hung because the result was larger than 255. :)
Maybe the arithmetic protocol is one that dilutes better. We've found it to be immensely powerful (and that includes two Junior Smalltalkers who tend to make more silly mistakes), and we're not getting bogged down by errors that take longer to occur.
-- Travis Griggs Key Technology tgriggs@keyww.com Smalltalk - 100% Pure Objects, Always had 'em, Always will!
BTW: We've been thinking about that one String error, and we've got a solution. We're going to make Strings understand the Arithmetic protocol too, but in that case we're going to implicitly extract the number from the string if possible. Can you say Perl?
squeak-dev@lists.squeakfoundation.org