I want to clear its contents (size goes back to zero), and can't seem to find something like #clear or #empty. Cannot use a new collection as there are shared references to it.
Thanks - Sophie
Some kind of facade that holds a collection, and replaces it with an empty one when you call #empty? You could forward all other calls.
On Feb 18, 2008 7:41 PM, itsme213 itsme213@hotmail.com wrote:
I want to clear its contents (size goes back to zero), and can't seem to find something like #clear or #empty. Cannot use a new collection as there are shared references to it.
Thanks - Sophie
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
I would do:
aCollection removeAll: aCollection
Also, I have Aida in my image and I have:
OrderedCollection>>removeAll "remove all elements quickly" self become: OrderedCollection new
but not sure this way is good because of #become:. I don't know either if this will keep your references.
hth
Cédrick
Hi Sophie,
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing the index will cause you to skip elements.
Ron
-----Original Message----- From: itsme213
I want to clear its contents (size goes back to zero), and can't seem to find something like #clear or #empty. Cannot use a new collection as there are shared references to it.
Thanks - Sophie
Isn't Cedrick's aida solution going to be significantly faster?
On Feb 19, 2008 1:02 AM, Ron Teitelbaum Ron@usmedrec.com wrote:
Hi Sophie,
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing the index will cause you to skip elements.
Ron
-----Original Message----- From: itsme213
I want to clear its contents (size goes back to zero), and can't seem to find something like #clear or #empty. Cannot use a new collection as
there
are shared references to it.
Thanks - Sophie
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become.
On Feb 19, 2008 1:38 AM, cdrick cdrick65@gmail.com wrote:
Isn't Cedrick's aida solution going to be significantly faster?
this is not mine :)
butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ?
Thanks _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
My understanding as well is that this is the purpose of #become:, but also that it is not very efficient in some versions of Smalltalk. If you are using an OrderedCollection, this is probably a reasonably efficient method as it doesn't need to search through the whole list every time it removes an element:
removeAll [self notEmpty] whileTrue: [self removeLast]
Brian.
On Feb 18, 2008 6:42 PM, Marcin Tustin mm3@zepler.net wrote:
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become.
On Feb 19, 2008 1:38 AM, cdrick cdrick65@gmail.com wrote:
Isn't Cedrick's aida solution going to be significantly faster?
this is not mine :)
butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ?
Thanks
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
"Brian" == Brian Murphy-Dye brian@murphydye.com writes:
Brian> My understanding as well is that this is the purpose of #become:, but Brian> also that it is not very efficient in some versions of Smalltalk. If Brian> you are using an OrderedCollection, this is probably a reasonably Brian> efficient method as it doesn't need to search through the whole list Brian> every time it removes an element:
Brian> removeAll Brian> [self notEmpty] whileTrue: [self removeLast]
What makes you think #removeLast doesn't need to search through the whole list in some kinds of OrderedCollection? You *do* have an implementation assumption there.
I'd just do:
removeAll self notEmpty ifTrue: [self become: self species new].
and let subclasses make it more efficient using implementation knowledge.
merlyn@stonehenge.com (Randal L. Schwartz) wrote:
"Brian" == Brian Murphy-Dye brian@murphydye.com writes:
Brian> My understanding as well is that this is the purpose of #become:, but Brian> also that it is not very efficient in some versions of Smalltalk. If Brian> you are using an OrderedCollection, this is probably a reasonably Brian> efficient method as it doesn't need to search through the whole list Brian> every time it removes an element:
Brian> removeAll Brian> [self notEmpty] whileTrue: [self removeLast]
What makes you think #removeLast doesn't need to search through the whole list in some kinds of OrderedCollection? You *do* have an implementation assumption there.
I'd just do:
removeAll self notEmpty ifTrue: [self become: self species new].
and let subclasses make it more efficient using implementation knowledge.
I would never use become: in "regular code" like this. :)
regards, Göran
"goran" == goran goran@krampe.se writes:
I'd just do:
removeAll self notEmpty ifTrue: [self become: self species new].
and let subclasses make it more efficient using implementation knowledge.
goran> I would never use become: in "regular code" like this. :)
First, how "regular" is it if the method hasn't been missed by anyone in 27 years. :)
Second, what are you objecting to? #become: is clearly a part of the image, and works fine. This code also cleans out a grown collection to be the smallest it possiby can become, where delete-one-at-a-time solutions don't.
And, if there's a more efficient thing for subclasses, they can certainly override it.
On Feb 20, 2008 8:09 AM, Randal L. Schwartz merlyn@stonehenge.com wrote:
"goran" == goran goran@krampe.se writes:
I'd just do:
removeAll self notEmpty ifTrue: [self become: self species new].
and let subclasses make it more efficient using implementation
knowledge.
goran> I would never use become: in "regular code" like this. :)
First, how "regular" is it if the method hasn't been missed by anyone in 27 years. :)
Second, what are you objecting to? #become: is clearly a part of the image, and works fine. This code also cleans out a grown collection to be the smallest it possiby can become, where delete-one-at-a-time solutions don't.
#become: and its friends are voodoo. Don't use them in your code unless you have absolutely no other option.
It doesn't work fine. It breaks code that relies on hashes; specifically, a Dictionary elsewhere in your image can start acting screwy if you do a #become: variant that doesn't preserve an object's hash. See #becomeForward>>copyHash:. You would then also be relying on a Squeakish behaviour and your code would become less portable across Smalltalk dialects.
They are also a fantastic way to introduce bugs of various sorts, and can even cause an image to crash (as in, stack trace and exit to the OS). Say, for example, that one of the arguments you pass is accidently nil, true or false? Your image would continue working... for a while.
#become: and variants are also very slow and causes the equivalent of a full GC on every invocation.
Gulik.
merlyn@stonehenge.com (Randal L. Schwartz) wrote:
"goran" == goran goran@krampe.se writes:
I'd just do:
removeAll self notEmpty ifTrue: [self become: self species new].
and let subclasses make it more efficient using implementation knowledge.
goran> I would never use become: in "regular code" like this. :)
First, how "regular" is it if the method hasn't been missed by anyone in 27 years. :)
Second, what are you objecting to? #become: is clearly a part of the image, and works fine. This code also cleans out a grown collection to be the smallest it possiby can become, where delete-one-at-a-time solutions don't.
And, if there's a more efficient thing for subclasses, they can certainly override it.
Yes, I probably agree it would be a nice default implementation. Modulo someone now telling us we missed something of course. :)
regards, Göran
My understanding as well is that this is the purpose of #become:, but also that it is not very efficient in some versions of Smalltalk. If you are using an OrderedCollection, this is probably a reasonably efficient method as it doesn't need to search through the whole list every time it removes an element:
removeAll [self notEmpty] whileTrue: [self removeLast]
Brian.
On Feb 18, 2008 6:42 PM, Marcin Tustin mm3@zepler.net wrote:
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become.
On Feb 19, 2008 1:38 AM, cdrick cdrick65@gmail.com wrote:
Isn't Cedrick's aida solution going to be significantly faster?
this is not mine :)
butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ?
Thanks
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Hi Marcin,
I'm not a fan of using #become. I will use it for very specific behavior when I need to retain pointers to an object. For example for implementing a proxy. In that case become is a very useful tool. I think that #become is overkill for this situation, but I won't argue that it doesn't work. In most cases you have a well encapsulated collection. That collection is not referenced outside the object so you can just reinitialize your collection without #become. If it is complicated enough to worry about pointers I wouldn't use #become. Someone will get lost and miss your #become hidden inside #removeAll: . I'm not saying this will cause problems but I think I would rather work with the collection directly instead of using the #become.
Also if you are working on a collection that is large enough to worry about performance then you are probably missing a database that would significantly improve your performance.
Ron Teitelbaum
________________________________________ From: beginners-bounces@lists.squeakfoundation.org [mailto:beginners-bounces@lists.squeakfoundation.org] On Behalf Of Marcin Tustin Sent: Monday, February 18, 2008 8:43 PM To: A friendly place to get answers to even the most basic questions aboutSqueak. Subject: Re: [Newbies] How to empty a collection?
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become. On Feb 19, 2008 1:38 AM, cdrick cdrick65@gmail.com wrote:
Isn't Cedrick's aida solution going to be significantly faster?
this is not mine :)
butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ?
Thanks _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
On Feb 19, 2008 2:29 AM, Ron Teitelbaum Ron@usmedrec.com wrote:
Hi Marcin,
I'm not a fan of using #become. I will use it for very specific behavior when I need to retain pointers to an object. For example for implementing a proxy. In that case become is a very useful tool. I think that #become is overkill for this situation, but I won't argue that it doesn't work. In most cases you have a well encapsulated collection. That collection is not referenced outside the object so you can just reinitialize your collection
Re-initialize how? I can't see a way to run object initialisation over again on an existing object.
without #become. If it is complicated enough to worry about pointers I wouldn't use #become. Someone will get lost and miss your #become hidden inside #removeAll: . I'm not saying this will cause problems but I think I would rather work with the collection directly instead of using the #become.
Also if you are working on a collection that is large enough to worry about performance then you are probably missing a database that would significantly improve your performance.
Ron Teitelbaum
From: beginners-bounces@lists.squeakfoundation.org [mailto:beginners-bounces@lists.squeakfoundation.org] On Behalf Of Marcin Tustin Sent: Monday, February 18, 2008 8:43 PM To: A friendly place to get answers to even the most basic questions aboutSqueak. Subject: Re: [Newbies] How to empty a collection?
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become. On Feb 19, 2008 1:38 AM, cdrick cdrick65@gmail.com wrote:
Isn't Cedrick's aida solution going to be significantly faster?
this is not mine :)
butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ?
Thanks _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
On Feb 19, 2008, at 10:53 , Marcin Tustin wrote:
Re-initialize how? I can't see a way to run object initialisation over again on an existing object.
Everything in Smalltalk happens by sending a message. How was your object initialized? By sending a message. How can you initialize it again? Send the message again.
Case in point - OrderedCollection. How is it initialized? Look at #new:. It sends #setCollection:. So send #setCollection: with a new Array and you're done.
Well, of course you're not *supposed* to be doing this. But you could, and it would only be half-evil ;)
- Bert -
Bert Freudenberg wrote:
Well, of course you're not *supposed* to be doing this. But you could, and it would only be half-evil ;)
It wouldn't be evil at all. This is Smalltalk, not Ada!!
But seriously, it seems a major oversight that such a basic task isn't in the standard protocol. The language has been around a while, someone else must have wanted to empty a collection.
Well, of course you're not *supposed* to be doing this. But
you could,
and it would only be half-evil ;)
It wouldn't be evil at all. This is Smalltalk, not Ada!!
But seriously, it seems a major oversight that such a basic task isn't in the standard protocol. The language has been around a while, someone else must have wanted to empty a collection.
-- Jeffrey Straszheim http://straszheim.50megs.com
It not being standardized just means there's no consensus to the *right* way to do it. I'd bet many of us have our own versions of #removeAll in our images, I know I do.
Ramon Leon http://onsmalltalk.com
Hi,
This method is mine :) Ok, with a little IRC help from Radoslav Hodnicak.
Why #become: ? As Marcin already suggested is a problem how to nil all existing elements in a collection, so to be garbage collected. This is specially problematic when collection has many elements and just doing an usual remove is too slow. In that case #become: is much faster, even that this method is slow on some dialects. Also, collection identity is preserved. But main point is that all elements are for sure GCed!
Best regards Janko
Marcin Tustin wrote:
My own testing suggests that references to the object remain in place. I would guess that that is the whole point of become.
cdrick wrote:
> Isn't Cedrick's aida solution going to be significantly faster? > this is not mine :) butI'd interested to see if it's a good use of #become:... Does it keep references ? is it safe ? Thanks
On Tue, 19 Feb 2008 02:35:34 +0100, Marcin Tustin wrote:
Isn't Cedrick's aida solution going to be significantly faster?
No, solutions based on #become: are the slowest possible. The VM has to sweep the whole memory, for all variables in the system, to find all references during #become:, like this
| oop | oop := self someObject. ["check+replace reference in variables of oop, then" oop := oop nextObject. oop = 0 ] whileFalse.
Now think that you (and every other user of your software ;-) have an .image with 2-4gigs every time you use #become: ...
If you want something faster, look at Bert's
myCollection removeAllSuchThat: [:each | true]
and try to make it faster but keep still it correct (old elements must be nil'ed).
/Klaus
On Feb 19, 2008 1:02 AM, Ron Teitelbaum Ron@usmedrec.com wrote:
Hi Sophie,
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing the index will cause you to skip elements.
Ron
-----Original Message----- From: itsme213
I want to clear its contents (size goes back to zero), and can't seem
to
find something like #clear or #empty. Cannot use a new collection as
there
are shared references to it.
Thanks - Sophie
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Hi!
CCing squeak-dev because I would like to see this fixed. :)
"Ron Teitelbaum" Ron@USMedRec.com wrote:
Hi Sophie,
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing the index will cause you to skip elements.
Because modifying the collection while iterating over the same is not safe generally. The above idiom is "known" - but of course it sucks. :)
I advocated to add a #removeAll message in the protocol of Collection and then implement it in subclasses using efficient variants a looooong while back but it never got accepted. The climate today for such a change is much more... "pragmatic" I think and hope. So we should simply add it!
The *normal* way people usually do it thoiugh is to *not depend on the identity* of the Collection - different objects should typically not share the same Collection. And if you don't share - then the easy way out is to just do:
myCollection := OrderedCollection new "or whatever class you use"
...in order to empty it.
But in low level code it would be nice to have the #removeAll method because it can be very efficiently implemented in different subclasses and would avoid reallocations etc.
regards, Göran
goran@krampe.se wrote:
The *normal* way people usually do it thoiugh is to *not depend on the identity* of the Collection - different objects should typically not share the same Collection. And if you don't share - then the easy way out is to just do:
myCollection := OrderedCollection new "or whatever class you use"
...in order to empty it.
A word of caution: identity should be preserved in the 'normal' case, replacing with another collection should be regarded as the exceptional case. Your assertion that "different objects should typically not share the same Collection." is only valid in limited cases.
I'm talking from my experience with building mvc-based apps on VisualWorks. Code needs to be decoupled, ie 'model' objects and collections should not know about the UI's that are coupled to them, this is achieved with the various dependency mechanisms available in VW.
Changing identity of the collections will break this paradigm big time (regardless of whether the dependents are managed in a global dictionary or by the collection itself).
As to the implementation of #removeAll on non-growable collections: follow whatever pattern the squeak library uses for other messages that alter the size (#add:, #remove:,...). In VW the idiom is to call #shouldNotImplement.
Cheers,
R -
Hi!
Reinout Heeck reinz@desk.org wrote:
goran@krampe.se wrote:
The *normal* way people usually do it thoiugh is to *not depend on the identity* of the Collection - different objects should typically not share the same Collection. And if you don't share - then the easy way out is to just do:
myCollection := OrderedCollection new "or whatever class you use"
...in order to empty it.
A word of caution: identity should be preserved in the 'normal' case,
I agree. While I still think relying too much on identities is a dangerous practice.
replacing with another collection should be regarded as the exceptional case. Your assertion that "different objects should typically not share the same Collection." is only valid in limited cases.
Well, I still stand by it as a general "nice rule". :)
I'm talking from my experience with building mvc-based apps on VisualWorks. Code needs to be decoupled, ie 'model' objects and collections should not know about the UI's that are coupled to them, this is achieved with the various dependency mechanisms available in VW.
I know, I used VW back in the 2.5-3.x days and while I first thought the adapter-frenzy was cool I later also started thinking it was over-engineered as hell. ;)
Changing identity of the collections will break this paradigm big time (regardless of whether the dependents are managed in a global dictionary or by the collection itself).
Yes, if your adapters/UI components etc cling onto the collections themselves, then yes, you will be bitten big time. I still think that paradigm is fishy - but again, I only presented the way people *typically* go about this thing - I still of course would like to preserve identity and introduce #removeAll. It is better in all respects.
If the *intent* is to "remove all elements" - then the message should state exactly that intent. Doing stuff like "aColl copy do: [:each | aColl remove: each]" is just plain dumb and silly, though it would probably qualify as a default implementation in class Collection. :)
regards, Göran
Hi all!
Ok, since this was discussed AT PAINFULLY GREAT LENGTH back in aug/sept 2002 I just wanted to give you some reading on the subject at hand. Don't *ever* presume the issue you are bringing attention to hasn't been argued to death already :) :)
Threads of discussions related to this from 2002:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-August/04315 7.html http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-September/04 3926.html http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-September/04 3928.html
Especially Richard O Keefe did an awesome job back then IIRC.
Now, if those threads will not exhaust you completely :) - then feel free to hack up a changeset that is a conclusion of all findings in there. :)
regards, Göran
Hi Goran!
I just want to point out that the long links in your mail were broken for me (although a little cut and paste fixed that). Perhaps a service like tinyURL would be useful when sending long links from the dark and distant past.
I have noticed in this thread an undertone of "#become is the Devil's playground"
Could someone succinctly explain to someone who is a coarse and styless programmer like myself why this is so, and when its use is justified?
Thanks,
John (keeping the newb in newbie for many years now)
Hi all!
Ok, since this was discussed AT PAINFULLY GREAT LENGTH back in aug/sept 2002 I just wanted to give you some reading on the subject at hand. Don't *ever* presume the issue you are bringing attention to hasn't been argued to death already :) :)
Threads of discussions related to this from 2002:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-August/04315 7.html http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-September/04 3926.html http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-September/04 3928.html
<snip>
regards, Göran
On Feb 20, 2008 8:47 AM, johnps11@bigpond.com wrote:
Hi Goran!
I just want to point out that the long links in your mail were broken for me (although a little cut and paste fixed that). Perhaps a service like tinyURL would be useful when sending long links from the dark and distant past.
I have noticed in this thread an undertone of "#become is the Devil's playground"
Could someone succinctly explain to someone who is a coarse and styless programmer like myself why this is so, and when its use is justified?
Hi John the Newbie.
It would be appreciated if you replied under a quoted message rather than above it.
I've just sent an email in the original thread about this.
It's use would only be justified if there are no other options. I've used it myself in my remote object architecture[1] for converting a message-capturing object proxy into the original object when an object is migrated between computers. My intention was to keep the remoteness of the objects involved as hidden as possible, making the use of #become: necessary. In retrospect, it was a big and dangerous time-waster. Many images died to bring me this information.
Originally, the Collections framework in Squeak used become: to grow some collections. The blue book design of the Smalltalk VM[2] has an object lookup table where the implementation of #become: was very fast - switch a single pointer. The Squeak VM uses direct pointers between objects now, so the entire object memory needs to be scanned.
[1] http://www.gulik.co.nz/dpon_design.pdf, http://www.squeaksource.com/DPON . [2] http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_imp_toc.html
Gulik.
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing the index will cause you to skip elements.
I forgot that in my first attemp (and I knew that !)...
col := #(1 2 3) asOrderedCollection. col removeAll: col. ^col returns an OrderedCollection(2)
col removeAll: col copy is ok.
So, following Bert suggestion, would it be possible to change removeAll: from...
removeAll: aCollection aCollection do: [:each | self remove: each]. ^ aCollection to
removeAll: aCollection aCollection copy do: [:each | self remove: each]. ^ aCollection or
removeAll: aCollection aCollection == self ifTrue: [aCollection copy do: [:each | self remove: each]] ifFalse: [aCollection do: [:each | self remove: each]]. ^ aCollection
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]].
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Cédrick
Hi Cédrick,
I believe there is too little agreement to do very much. The suggestion you presented as Bert's suggestion was actually mine. So given the discussion that followed I think I would actually follow Bert's advice.
aColl removeAllSuchThat: [:anElement| true].
But I suppose that is still following my own advice because
removeAllSuchThat: aBlock "Evaluate aBlock for each element and remove all that elements from the receiver for that aBlock evaluates to true. Use a copy to enumerate collections whose order changes when an element is removed (i.e. Sets)."
self copy do: [:each | (aBlock value: each) ifTrue: [self remove: each]]
:)
Ron Teitelbaum
-----Original Message----- From: cdrick [mailto:cdrick65@gmail.com]>
aCollection copy do: [:anElement | aCollection remove: anElement ].
Why copy? If you start removing items from the collection, increasing
the
index will cause you to skip elements.
I forgot that in my first attemp (and I knew that !)...
col := #(1 2 3) asOrderedCollection. col removeAll: col. ^col returns an OrderedCollection(2)
col removeAll: col copy is ok.
So, following Bert suggestion, would it be possible to change removeAll: from...
removeAll: aCollection aCollection do: [:each | self remove: each]. ^ aCollection to
removeAll: aCollection aCollection copy do: [:each | self remove: each]. ^ aCollection or
removeAll: aCollection aCollection == self ifTrue: [aCollection copy do: [:each | self remove: each]] ifFalse: [aCollection do: [:each | self remove: each]]. ^ aCollection
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]].
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Cédrick
On Feb 19, 2008, at 16:06 , cdrick wrote:
So, following Bert suggestion, would it be possible to change removeAll: from...
I'm pretty certain I did not suggest anything like this. Nothing is broken here, so let's not fix it.
A new feature would be adding #removeAll, which sounds reasonable¹.
- Bert -
¹I do smell a bit of premature optimization here, or does anyone have a really convincing use case?
I'm pretty certain I did not suggest anything like this. Nothing is broken here, so let's not fix it.
My mistake, I'm sorry... It was Goran: "Because modifying the collection while iterating over the same is not safe generally. The above idiom is "known" - but of course it sucks. :)
I advocated to add a #removeAll message in the protocol of Collection and then implement it in subclasses using efficient variants a looooong while back but it never got accepted. The climate today for such a change is much more... "pragmatic" I think and hope. So we should simply add it!"
I'm really tired today... ;)
See you
Cédrick
On Tue, 19 Feb 2008 16:06:50 +0100, cdrick wrote:
...
I forgot that in my first attemp (and I knew that !)...
col := #(1 2 3) asOrderedCollection. col removeAll: col. ^col returns an OrderedCollection(2)
col removeAll: col copy is ok.
So, following Bert suggestion, would it be possible to change removeAll: from...
removeAll: aCollection aCollection do: [:each | self remove: each]. ^ aCollection to
removeAll: aCollection aCollection copy do: [:each | self remove: each]. ^ aCollection or
removeAll: aCollection aCollection == self ifTrue: [aCollection copy do: [:each | self remove: each]] ifFalse: [aCollection do: [:each | self remove: each]]. ^ aCollection
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]].
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Thumbs down, I do not want anybody copy a collection behind my back (however small or large it is) just because remove* has nothing to do with copy.
Cédrick
On Tue, 19 Feb 2008 16:56:48 +0100, cdrick wrote:
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Thumbs down, I do not want anybody copy a collection behind my back (however small or large it is) just because remove* has nothing to do with copy.
Ok, I can understand. What about the error ?
This is a bug, Smalltalk cannot compromise its fundamental structures (#removeAll is ANSI). Enter the report if not already on mantis & attach your fix.
/Klaus
On Tue, 19 Feb 2008 17:21:57 +0100, Klaus D. Witzel wrote:
On Tue, 19 Feb 2008 16:56:48 +0100, cdrick wrote:
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Thumbs down, I do not want anybody copy a collection behind my back (however small or large it is) just because remove* has nothing to do with copy.
Ok, I can understand. What about the error ?
This is a bug, Smalltalk cannot compromise its fundamental structures (#removeAll is ANSI). Enter the report if not already on mantis & attach your fix.
Sorry, s/#removeAll /#removeAll: /
/Klaus
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Thumbs down, I do not want anybody copy a collection behind my back (however small or large it is) just because remove* has nothing to do with copy.
Ok, I can understand. What about the error ?
This is a bug, Smalltalk cannot compromise its fundamental structures (#removeAll is ANSI). Enter the report if not already on mantis & attach your fix.
I actually didn't meant it was a bug :) I need to be sharper with my english... I meant raising an error message if self == aCollection ... Could it be a fix ?
Because in a way, the behavior is not really an error, it's more a bad use because we know it's iterative and then, self and aCollection change in the same time...
I hope you don't take my remarks, as "I want to change smalltalk"... I just want to understand it better ;)
Cheers
Cédrick
ps: by the way, I'll open a bug report, as finally I think it's an error (arf....) because I shouldn't be aware removeAll is iterative....etc... so here is the bug report (http://bugs.squeak.org/view.php?id=6937).
cdrick a écrit :
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]].
Or maybe, if aCollection == self, a warning could be raised ?
What do you think ?
Cédrick
aCollection == self is not the only case that can fail. Imagine i pass a wrapper collection on self, like a MappedCollection.
When i will change self with remove:, i will also change the argument which is just a wrapper on self.
Hope my explanations are not too much confusing...
Nicolas
On Tue, 19 Feb 2008 21:01:14 +0100, nicolas cellier wrote:
cdrick a écrit :
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]]. Or maybe, if aCollection == self, a warning could be raised ? What do you think ? Cédrick
aCollection == self is not the only case that can fail. Imagine i pass a wrapper collection on self, like a MappedCollection.
When i will change self with remove:, i will also change the argument which is just a wrapper on self.
Hope my explanations are not too much confusing...
Let's see: "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification."
What mapping would *not* raise the error notification ;-)
BTW: MappedCollection does not exist in sq3.10-7159dev08.02.1.image ...
/Klaus
Nicolas
Klaus D. Witzel a écrit :
On Tue, 19 Feb 2008 21:01:14 +0100, nicolas cellier wrote:
cdrick a écrit :
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]]. Or maybe, if aCollection == self, a warning could be raised ? What do you think ? Cédrick
aCollection == self is not the only case that can fail. Imagine i pass a wrapper collection on self, like a MappedCollection.
When i will change self with remove:, i will also change the argument which is just a wrapper on self.
Hope my explanations are not too much confusing...
Let's see: "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification."
What mapping would *not* raise the error notification ;-)
My interpretation of the comment was rather for the case when we try to remove an element which is not in the collection... But OK, I take it as is...
However i can construct a test case that will not do what is expected and will not raise a notification, wanna bet?
| collec1 collec2 | collec1 := OrderedCollection with: 'a' with: 'b' with: 'c'. collec2 := MappedCollection collection: collec1 map: (1 to: 2). "collec2 only map first two elements 'a' and 'b'" collec1 removeAll: collec2. "this should remove 'a' and 'b' from collec1" self assert: collec1 first = 'c' "too bad... it's 'b'"
BTW: MappedCollection does not exist in sq3.10-7159dev08.02.1.image ...
MappedCollection is just an example of possible wrapper collection, even if there is none in core images nowadays, that's a classical pattern which avoid copying for example.
MappedCOllection is in 3.9 image.
/Klaus
Nicolas
On Tue, 19 Feb 2008 22:00:09 +0100, nicolas cellier wrote:
Klaus D. Witzel a écrit :
On Tue, 19 Feb 2008 21:01:14 +0100, nicolas cellier wrote:
cdrick a écrit :
or again removeAll: aCollection aCollection == self ifTrue: [self removeAll: aCollection copy] ifFalse: [aCollection do: [:each | self remove: each]]. Or maybe, if aCollection == self, a warning could be raised ? What do you think ? Cédrick
aCollection == self is not the only case that can fail. Imagine i pass a wrapper collection on self, like a MappedCollection.
When i will change self with remove:, i will also change the argument which is just a wrapper on self.
Hope my explanations are not too much confusing...
Let's see: "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification." What mapping would *not* raise the error notification ;-)
My interpretation of the comment was rather for the case when we try to remove an element which is not in the collection... But OK, I take it as is...
However i can construct a test case that will not do what is expected and will not raise a notification, wanna bet?
No, just let the next people who attempt to bring MappedCollection back to Squeak > 3.10 take care ;-)
BTW: do you have as much energy for fixing problems as you seem to have for imagine the currently non-existing ;-) This would help Squeak jump forward :)
| collec1 collec2 | collec1 := OrderedCollection with: 'a' with: 'b' with: 'c'. collec2 := MappedCollection collection: collec1 map: (1 to: 2). "collec2 only map first two elements 'a' and 'b'" collec1 removeAll: collec2. "this should remove 'a' and 'b' from collec1" self assert: collec1 first = 'c' "too bad... it's 'b'"
BTW: MappedCollection does not exist in sq3.10-7159dev08.02.1.image ...
MappedCollection is just an example of possible wrapper collection, even if there is none in core images nowadays, that's a classical pattern which avoid copying for example.
MappedCOllection is in 3.9 image.
/Klaus
Nicolas
Klaus D. Witzel a écrit :
On Tue, 19 Feb 2008 22:00:09 +0100, nicolas cellier wrote:
However i can construct a test case that will not do what is expected and will not raise a notification, wanna bet?
No, just let the next people who attempt to bring MappedCollection back to Squeak > 3.10 take care ;-)
As a user of collection wrappers, proposed patch just hit the alarm buzzer my nervous brain is equipped with.
But your position is wise. As long as a MappedCollection, lazy list or lazy collection (see these projects on SqueakSource) are all created under our control, we can manage...
BTW: do you have as much energy for fixing problems as you seem to have for imagine the currently non-existing ;-) This would help Squeak jump forward :)
That's precisely how i find and fix unknown bugs: Imagine how i could break current implementation.
For this reason, most patches i proposed are minor. Hope a few are usefull, since adopted in 3.8.1, 3.9 and 3.10. Any minor contribution counts anyway :)
Nicolas
beginners@lists.squeakfoundation.org