Lex Spoon lex@cc.gatech.edu wrote: I still think it's likely -- it's the way I code, and it's the way I've heard many people suggest coding.
When you do a rewrite by inline expansion of a method, do you always throw away the assertions, error checks, and guard code? Because that's what's needed for this example.
It's unreasonable to do full proofs of correctness, and it's unhelpful to point the finger and say it's so and so's responsibility to do such an unreasonable thing. Nobody has suggested proofs of correctness, only (1) reasonable testing and (2) not throwing away guard code.
| x | x := self allFooishMembers. self removeNonTrueBelievers. "at this point, is x the same as it was up above? you'd like it to be!!" This is discussed in the Smalltalk Style Guide, which is currently at home or I'd cite the page number. I argued at length (only to be jumped on hard by A----- G-------) that objects shouldn't hand out references to their innards, and if they do, they don't have a usable class invariant any more. In different language, the Smalltalk Style Guide suggests handing out _new_ collections as a good thing to do.
While I know that C++ 'strstream' is frowned on, it does count as an example. Once you ask for (and are given) a reference to a ostrstream's buffer, that's practically _all_ you can do with the ostrstream thereafter.
"Richard A. O'Keefe" ok@cs.otago.ac.nz wrote: [... inline the assertions, too ...]
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
It's unreasonable to do full proofs of correctness, and it's unhelpful to point the finger and say it's so and so's responsibility to do such an unreasonable thing.
Nobody has suggested proofs of correctness, only (1) reasonable testing and (2) not throwing away guard code.
| x | x := self allFooishMembers. self removeNonTrueBelievers. "at this point, is x the same as it was up above? you'd like it to be!!"
This is discussed in the Smalltalk Style Guide, which is currently at home or I'd cite the page number. I argued at length (only to be jumped on hard by A----- G-------) that objects shouldn't hand out references to their innards, and if they do, they don't have a usable class invariant any more. In different language, the Smalltalk Style Guide suggests handing out _new_ collections as a good thing to do.
This is actually the point of view I'm coming from. If you follow this style guideline fervently, then you never have to worry about "a removeAll: b" with a==b. If you like the guideline but would are lazy in its implementation, then you'd like to get warnings whenever you violate it in an erroneous or even borderline situation. When, precisely, would a programmer want to do "a removeAll: b" where a==b ? It seems like you have to completely disdain the above guideline if you conciously write such code.
-Lex
On Wednesday, September 11, 2002, at 07:31 PM, Lex Spoon wrote:
"Richard A. O'Keefe" ok@cs.otago.ac.nz wrote: [... inline the assertions, too ...]
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
Which, of course, concedes the point that fooAll: methods entail an implied iteration on its parameter.
Q.E.D.
Hi all!
"Andrew C. Greenberg" werdna@mucow.com wrote:
On Wednesday, September 11, 2002, at 07:31 PM, Lex Spoon wrote:
"Richard A. O'Keefe" ok@cs.otago.ac.nz wrote: [... inline the assertions, too ...]
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
What is this last statement based on? Is it the Squeak image? Using the MethodFinder and looking at all methods with "all:" I can actually not find many methods that " just do: on the argument and foo: each element"...
The only ones I found (a cursory look) where:
Collection>>addAll: Collection>>removeAll: CompositeEvent>>addAll: POSimplePolygon>>addAll:
And I also found that OrderedCollection>>addAll: and SortedCollection>>addAll: does NOT do that! Of course, what they do is equivalent to "just do: and foo:" but it is still different code.
Further I found quite a lot of methods named "somethingAll:" but the only thing I can see that they have in common is that they take an argument that is intended to be a Collection of something. That is all.
Which, of course, concedes the point that fooAll: methods entail an implied iteration on its parameter.
Even if the statement was correct (which I do not agree with Lex, at least not if we look at the image) it would only show that most such methods where *implemented* that way. IMHO it doesn't "imply" anything.
Q.E.D.
:-) Nah.
regards, Göran
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
What is this last statement based on? Is it the Squeak image? Using the MethodFinder and looking at all methods with "all:" I can actually not find many methods that " just do: on the argument and foo: each element"...
The only ones I found (a cursory look) where:
Collection>>addAll: Collection>>removeAll: CompositeEvent>>addAll: POSimplePolygon>>addAll:
And I also found that OrderedCollection>>addAll: and SortedCollection>>addAll: does NOT do that! Of course, what they do is equivalent to "just do: and foo:" but it is still different code.
Further I found quite a lot of methods named "somethingAll:" but the only thing I can see that they have in common is that they take an argument that is intended to be a Collection of something. That is all.
Which, of course, concedes the point that fooAll: methods entail an implied iteration on its parameter.
Even if the statement was correct (which I do not agree with Lex, at least not if we look at the image) it would only show that most such methods where *implemented* that way. IMHO it doesn't "imply" anything.
I've been programming Smalltalk for a while, and I know what the implicitions are the same way I know what words in my native tongue mean. By itself, the "all" implies that the argument is a collection. If it's "fooAll:" where "foo" is a verb, and especially if there exists a "foo:" method in parallel, then I stand by claiming that the expectation is that the method will iterate over the argument and perform a "foo" on all of them.
Your data actually agrees with this analysis. I didn't mean to say that the methods were *implemented* to literally use #do:. In fact, a primary reason to have optimized implementations of removeAll: is to get rid of the explicit iteration. Nevertheless, they will examine the elements of the argument in some fashion. It seems a very heavy burden to require them to tolerate the argument changing as the method does it's work. As a general rule, experienced Smalltalkers will not expect methods should to cope with their arguments changing while the method progresses. When they do,
The ability to cope with such is extraordinary and often imposes a large implementation burden.
Hi all!
"Lex Spoon" lex@cc.gatech.edu wrote:
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
What is this last statement based on? Is it the Squeak image? Using the MethodFinder and looking at all methods with "all:" I can actually not find many methods that " just do: on the argument and foo: each element"...
The only ones I found (a cursory look) where:
Collection>>addAll: Collection>>removeAll: CompositeEvent>>addAll: POSimplePolygon>>addAll:
And I also found that OrderedCollection>>addAll: and SortedCollection>>addAll: does NOT do that! Of course, what they do is equivalent to "just do: and foo:" but it is still different code.
Further I found quite a lot of methods named "somethingAll:" but the only thing I can see that they have in common is that they take an argument that is intended to be a Collection of something. That is all.
Which, of course, concedes the point that fooAll: methods entail an implied iteration on its parameter.
Even if the statement was correct (which I do not agree with Lex, at least not if we look at the image) it would only show that most such methods where *implemented* that way. IMHO it doesn't "imply" anything.
I've been programming Smalltalk for a while, and I know what the implicitions are the same way I know what words in my native tongue
I am not sure what point you are getting at here.
mean. By itself, the "all" implies that the argument is a collection.
Yes, agree.
If it's "fooAll:" where "foo" is a verb, and especially if there exists a "foo:" method in parallel, then I stand by claiming that the expectation is that the method will iterate over the argument and perform a "foo" on all of them.
My expectation is that they will all get foo'ed. Period. Can't see why it would imply an iteration just because that is the common implementation. Or in other words - I wouldn't be suprised if there was an iteration in there, and if someone wanted me to guess about it I would probably guess that too - but I wouldn't argue that if there wasn't an iteration in there the implementor somehow broke some "unspoken contract" of some kind.
But perhaps we are simply misunderstanding each other here. I am still arguing this because I felt that encapsulation is important and the argument raised by Andrew (I think) that there was an iteration implied and therefore that is what it should be - then I disagree.
One perfectly good way of implementing "x removeAll: x" (so that it works - all other arguments aside) would be to simply empty x. So in that case no iteration takes place whatsoever.
But I can understand arguments about portability etc so as long as we add removeAll (no colon) then issuing a signal is fine by me.
Your data actually agrees with this analysis. I didn't mean to say that the methods were *implemented* to literally use #do:. In fact, a primary reason to have optimized implementations of removeAll: is to get rid of the explicit iteration. Nevertheless, they will examine the elements of the argument in some fashion. It seems a very heavy burden to require them to tolerate the argument changing as the method does it's work. As a general rule, experienced Smalltalkers will not expect
Wait a minute - I am not arguing for that. I am simply saying that I don't agree about "implied iteration". That was all.
regards, Göran
Bergel Alexandre bergel@iam.unibe.ch asked: To: squeak-dev@lists.squeakfoundation.org
Hello,> Is it a bug ?
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= t := #(1 2 3 4) asOrderedCollection. t removeAll: t -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= => an OrderedCollection(2 4)
Bergel:
So, did they answer your question?
:-)
Philip
My apologies as to my previous post -- I misread Lex's e-mail as an attribution of the quoted excerpt to Richard. It would appear those were Lex's words, not Richard's.
On Wednesday, September 11, 2002, at 07:31 PM, Lex Spoon wrote:
"Richard A. O'Keefe" ok@cs.otago.ac.nz wrote: [... inline the assertions, too ...]
That's an interesting way to look at the situation, but do note that most Smalltalkers will be suprised to find those assertions or corrections in removeAll:. Most fooAll: methods just do: on the argument and foo: each element, and have no particular protection against #foo: modifying the argument.
squeak-dev@lists.squeakfoundation.org