Could someone provide me a little history on the remove:[ifAbsent:] selectors? Any insight from anyone involved with the ANSI committee would be useful, too.
I’m wondering why these methods return the search argument and not the real object found in the collection. For identity collections these would be the same, but most are equality collections, and so the two could be different. I have this problem in several places, where I use a search object for a set, but the reply of the method is the search object, not the entity in the set. In fact, there doesn’t seem to be a way to get that entity without using detect:[ifNone:].
Cheers!
_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
On Jan 19, 2010, at 10:59 AM, <[hidden email]> <[hidden email] > wrote: > Could someone provide me a little history on the remove:[ifAbsent:] > selectors? Any insight from anyone involved with the ANSI committee > would be useful, too. > > I’m wondering why these methods return the search argument and not > the real object found in the collection. For identity collections > these would be the same, but most are equality collections, and so > the two could be different. I have this problem in several places, > where I use a search object for a set, but the reply of the method > is the search object, not the entity in the set. In fact, there > doesn’t seem to be a way to get that entity without using detect: > [ifNone:]. I don't have a justification or a preference. But it does seem to me, that if you're going to consider this issue, you should consider the following code as well: (Set with: 4.0) add: 4 Currently, at the add:/remove: behaviors are consistent with each other at least. It would seem that to change one, you ought to change the other. And perhaps if one has a justification/preference for the add: behavior, then it illuminates, at least in part, why remove: works the way it does. -- Travis Griggs Objologist Light travels faster than sound. This is why some people appear bright until you hear them speak... _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Dear Thomas and Travis,
whenever implementing #add...: and remove:... methods on classes encapsulating Sets or similar, I always return the matched object, not the parameter. With this implementation of it, I find the 'return the parameter, not self' approach of Smalltalk enabling; without it, code can get needlessly complex to handle cases where they could differ, as Thomas remarks. I have never yet encountered a case where returning the parameter instead of the matched object _was_ the right thing to do (i.e. _was_ the choice that simplified calling code instead of complexifying it); does anyone have counter-examples? For years, I have wished for a change in the standard, and in all Smalltalks, to make such add: and remove:[ifAbsent:] methods return the matched object whenever it could be non-identical to the parameter. Alas, such code is so basic that this change has many hurdles to overcome (phrases like 'snowball's chance in hell' occur). However, it would good to know whether people all agree, or else do not all agree, that this is what it _should_ do. Yours faithfully Niall Ross >On Jan 19, 2010, at 10:59 AM, <[hidden email]> <[hidden email] > > wrote: > > > >>Could someone provide me a little history on the remove:[ifAbsent:] >>selectors? Any insight from anyone involved with the ANSI committee >>would be useful, too. >> >>I’m wondering why these methods return the search argument and not >>the real object found in the collection. For identity collections >>these would be the same, but most are equality collections, and so >>the two could be different. I have this problem in several places, >>where I use a search object for a set, but the reply of the method >>is the search object, not the entity in the set. In fact, there >>doesn’t seem to be a way to get that entity without using detect: >>[ifNone:]. >> >> > >I don't have a justification or a preference. But it does seem to me, >that if you're going to consider this issue, you should consider the >following code as well: > >(Set with: 4.0) add: 4 > >Currently, at the add:/remove: behaviors are consistent with each >other at least. It would seem that to change one, you ought to change >the other. And perhaps if one has a justification/preference for the >add: behavior, then it illuminates, at least in part, why remove: >works the way it does. > >-- >Travis Griggs >Objologist >Light travels faster than sound. This is why some people appear bright >until you hear them speak... > > > > > >_______________________________________________ >vwnc mailing list >[hidden email] >http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > > > > _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
On 10-Jan-20, at 10:45 AM, Niall Ross wrote: > I have never yet encountered a case where returning the parameter > instead of the matched object _was_ the right thing to do (i.e. _was_ > the choice that simplified calling code instead of complexifying it); > does anyone have counter-examples? I don't. In fact, I agree with you completely. The calling method is already in possession of the parameter by virtue of having passed it to #add: or #remove:, so there is no reason to return it. Returning the matched object is the correct behaviour because it provides information to the caller that was not available before the call. _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Travis Griggs-3
On Jan 19, 2010, at 11:20 AM, Travis Griggs wrote:
> I don't have a justification or a preference. Upon further reflection, I think the reason I don't care too much, is that instead I shudder to have to care about the code that cares about this return value. If I'm reading along and I see something like (someCollection add: anObject) doSomething and have to be aware of the subtle nuances that differ depending on whether doSomething is sent to one object or the other, that seems like an undesirable amount of subtle/sneaky/tricky to care about. Especially if I were maintaining the code months later. Flippantly, I'd suggest that on Tuesday, it do one thing, and on Wednesday another, just so people wouldn't write code that cares. High-horsed affinity for flippancy aside, I'd like to actually learn something here. I assume there are cases where caring is a legit concern, that I ought not make light of. I'd like to learn more. Can you guys share some examples (not necessarily source, just description) of code that you consider quality, but that has to worry about this kind of thing? I'm curious. -- Travis Griggs Objologist "There are a thousand hacking at the branches of evil to one who is striking at the root" - Henry David Thoreau _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by thomas.hawker
Niall Ross wrote:
> I have never yet encountered a case where returning the parameter > instead of the matched object _was_ the right thing to do (i.e. _was_ > the choice that simplified calling code instead of complexifying it); > does anyone have counter-examples? I completely agree that returning the removed match is better than returning the parameter. But since you ask, here's a trivial counter-example: I have a collection of elements, myIdentitySet, that I want to remove from another collection, bigEqualitySet. I want myIdentitySet to be left with my elements that weren't found. It's a little contrived, but not impossible: we can often deal with our own local collections on the basis of identity, but have to use equality with collections from further afield (e.g. read from a database). myIdentitySet copy do: [:myElt | myIdentitySet remove: (bigEqualitySet remove: myElt ifAbsent: [#miss]) ifAbsent: []] Obviously, this is fairly yucky, and the same could be achieved in several other ways. If this is the best use case we can come up with, we clearly don't need to support it. Steve _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Travis Griggs-3
Sure, Travis.
One app I was working on had a lot of Date instances. In fact, so many (and so many #= dates), that it was a problem. So we put them all in a collection (cannonicalDates), and when you wanted a date, you would use one from the collection. The easiest way is to make the date you want, and then get the equal one from cannonicalDates, adding it if it's not there. -Anthony On 10-Jan-20, at 11:40 AM, Travis Griggs wrote: > On Jan 19, 2010, at 11:20 AM, Travis Griggs wrote: > >> I don't have a justification or a preference. > > Upon further reflection, I think the reason I don't care too much, is > that instead I shudder to have to care about the code that cares about > this return value. If I'm reading along and I see something like > > (someCollection add: anObject) doSomething > > and have to be aware of the subtle nuances that differ depending on > whether doSomething is sent to one object or the other, that seems > like an undesirable amount of subtle/sneaky/tricky to care about. > Especially if I were maintaining the code months later. > > Flippantly, I'd suggest that on Tuesday, it do one thing, and on > Wednesday another, just so people wouldn't write code that cares. > > High-horsed affinity for flippancy aside, I'd like to actually learn > something here. I assume there are cases where caring is a legit > concern, that I ought not make light of. I'd like to learn more. Can > you guys share some examples (not necessarily source, just > description) of code that you consider quality, but that has to worry > about this kind of thing? I'm curious. > > -- > Travis Griggs > Objologist > "There are a thousand hacking at the branches of evil to one who is > striking at the root" - Henry David Thoreau > > > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Travis Griggs-3
Travis,
The following case I've been dealing with on-and-off for 20+ years. I have to admit this is the first time I ever really considered asking why it works the way it does. Yes, I agree that flipping the semantics would be terrible because of the subtle ways in which working apps would stop doing so... I have a registry keyed by some characteristic (not always a single value). In the registry are "fully-populated" elements. I create a search object (one that looks like the regular element but isn't fully populated) that has the same characteristic. I then ask the registry to remove the object whose characteristic is given by the search object. The matched object may or may not need to do post-delete processing... Ultimately, this is all based on sets and dictionaries, but the result is a remove returns the search object, not the matched object. I have to do two probes - one to find the matched object, then one to delete it. If the set is used, the only existing method in the VW base code that allows me to get my hands on it is detect:[ifNone:] - at a cost of O(n) rather than O(1). Just having at:[ifAbsent:] would be useful here. Cheers! Tom Hawker -------------------------- Senior Framework Developer -------------------------- Home +1 (408) 274-4128 Office +1 (408) 576-6591 Mobile +1 (408) 835-3643 -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Travis Griggs Sent: Wednesday, January 20, 2010 8:40 AM To: VWNC List Subject: Re: [vwnc] Some history on Collection>>remove:[ifAbsent:] On Jan 19, 2010, at 11:20 AM, Travis Griggs wrote: [snipped] High-horsed affinity for flippancy aside, I'd like to actually learn something here. I assume there are cases where caring is a legit concern, that I ought not make light of. I'd like to learn more. Can you guys share some examples (not necessarily source, just description) of code that you consider quality, but that has to worry about this kind of thing? I'm curious. -- Travis Griggs Objologist "There are a thousand hacking at the branches of evil to one who is striking at the root" - Henry David Thoreau IMPORTANT NOTICE Email from OOCL is confidential and may be legally privileged. If it is not intended for you, please delete it immediately unread. The internet cannot guarantee that this communication is free of viruses, interception or interference and anyone who communicates with us by email is taken to accept the risks in doing so. Without limitation, OOCL and its affiliates accept no liability whatsoever and howsoever arising in connection with the use of this email. Under no circumstances shall this email constitute a binding agreement to carry or for provision of carriage services by OOCL, which is subject to the availability of carrier's equipment and vessels and the terms and conditions of OOCL's standard bill of lading which is also available at http://www.oocl.com. _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
<thomas.hawker <at> oocl.com> writes:
> > Travis, > > The following case I've been dealing with on-and-off for 20+ years. I have to admit this is the first time I > ever really considered asking why it works the way it does. Yes, I agree that flipping the semantics would > be terrible because of the subtle ways in which working apps would stop doing so... > > I have a registry keyed by some characteristic (not always a single value). In the registry are > "fully-populated" elements. I create a search object (one that looks like the regular element but isn't > fully populated) that has the same characteristic. I then ask the registry to remove the object whose > characteristic is given by the search object. The matched object may or may not need to do post-delete processing... > > Ultimately, this is all based on sets and dictionaries, but the result is a remove returns the search > object, not the matched object. I have to do two probes - one to find the matched object, then one to delete > it. If the set is used, the only existing method in the VW base code that allows me to get my hands on it is > detect:[ifNone:] - at a cost of O(n) rather than O(1). Just having at:[ifAbsent:] would be useful here. > > Cheers! > > Tom Hawker In Squeak, this poeration is named #like: Nicolas _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Travis Griggs-3
At 08:40 AM 1/20/2010, you wrote:
>On Jan 19, 2010, at 11:20 AM, Travis Griggs wrote: > >> I don't have a justification or a preference. > >Upon further reflection, I think the reason I don't care too much, is >that instead I shudder to have to care about the code that cares about >this return value. If I'm reading along and I see something like > >(someCollection add: anObject) doSomething > >and have to be aware of the subtle nuances that differ depending on >whether doSomething is sent to one object or the other, that seems >like an undesirable amount of subtle/sneaky/tricky to care about. >Especially if I were maintaining the code months later. Yes -- if #add: were properly non-deterministic, the right way to handle the non-determinism would be to ensure that we don't care which result occurs - either should suffice. >Flippantly, I'd suggest that on Tuesday, it do one thing, and on >Wednesday another, just so people wouldn't write code that cares. If something like this were included in the spec, #add: would become properly non-determnistic. Almost. You'd also need to specify that the behavior on a given day-of-the-week could not be relied upon. >High-horsed affinity for flippancy aside, I'd like to actually learn >something here. I assume there are cases where caring is a legit >concern, that I ought not make light of. I'd like to learn more. Can >you guys share some examples (not necessarily source, just >description) of code that you consider quality, but that has to worry >about this kind of thing? I'm curious. *has* to worry about this kind of thing is misleading. How about *gets* to worry about this kind of thing? If we shift attention away from the method, as in should we answer the parameter or the matched? and onto to the collection itself, as in should the collection retain, and answer, the (first) duplicate; or replace, thereby keeping, and answering, the (last) duplicate? we get a different point of view: firstAmongEquals == (collection remove: (collection add: firstAmongEquals)) ifTrue: [collection isRetaining | collection isReplacing] ifFalse: [collection isBroken]. firstAmongEquals == (collection remove: (collection add: aDuplicate)) ifTrue: [collection isRetaining] ifFalse: [collection isBroken]. aDuplicate == (collection remove: (collection add: aDuplicate)) ifTrue: [collection isReplacing] ifFalse: [collection isBroken]. Hashed collections are not, at present, maintaining these invariants, and hence hashed collections {Sets, Bags, Dictionaries, etc.} can be described as non-deterministically non-deterministic -- a.k.a. NFG. Therefore the solution described above (whether flippant or fully spec'd) is inappropriate, because the non-determinism isn't *proper*, algorithmic non-determinism. We *should* care about the nuances -- both contexts are legitimate, and *would* occur in practise, if we *could* care about the nuances. But we *can't*. Well, *you* can't. I can send an implementation which corrects for this, but as the treatment is not recognized as "standard practice" and as the malady you are no doubt suffering from is quite clearly a pre-existing condition, I'm afraid your insurance is unlikely to cover any of the costs, which are, alas, unknown, but possibly extensive. Have a nice day. Cheers, -cstb >-- >Travis Griggs >Objologist >"There are a thousand hacking at the branches of evil to one who is >striking at the root" - Henry David Thoreau Nice quote ;-) _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
CTSB (acronym?),
My logic for adding to my various collections always removes a pre-existing match. I realized that, for my case, I /had/ to return the original object on a removal. Since dictionaries always return the value object on a remove I only had to deal with sets, which use a different set of methods. I added removeOriginal: and removeOriginal:ifAbsent: to provide the behavior. It's fairly clean - I guess I could have used something other than "Original" to better indicate the intent. Cheers! Tom Hawker -------------------------- Senior Framework Developer -------------------------- Home +1 (408) 274-4128 Office +1 (408) 576-6591 Mobile +1 (408) 835-3643 -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of cstb Sent: Thursday, January 28, 2010 10:48 AM To: Travis Griggs Cc: [hidden email] Subject: Re: [vwnc] Some history on Collection>>remove:[ifAbsent:] At 08:40 AM 1/20/2010, you wrote: >On Jan 19, 2010, at 11:20 AM, Travis Griggs wrote: > >> I don't have a justification or a preference. > >Upon further reflection, I think the reason I don't care too much, is >that instead I shudder to have to care about the code that cares about >this return value. If I'm reading along and I see something like > >(someCollection add: anObject) doSomething > >and have to be aware of the subtle nuances that differ depending on >whether doSomething is sent to one object or the other, that seems >like an undesirable amount of subtle/sneaky/tricky to care about. >Especially if I were maintaining the code months later. Yes -- if #add: were properly non-deterministic, the right way to handle the non-determinism would be to ensure that we don't care which result occurs - either should suffice. >Flippantly, I'd suggest that on Tuesday, it do one thing, and on >Wednesday another, just so people wouldn't write code that cares. If something like this were included in the spec, #add: would become properly non-determnistic. Almost. You'd also need to specify that the behavior on a given day-of-the-week could not be relied upon. >High-horsed affinity for flippancy aside, I'd like to actually learn >something here. I assume there are cases where caring is a legit >concern, that I ought not make light of. I'd like to learn more. Can >you guys share some examples (not necessarily source, just >description) of code that you consider quality, but that has to worry >about this kind of thing? I'm curious. *has* to worry about this kind of thing is misleading. How about *gets* to worry about this kind of thing? If we shift attention away from the method, as in should we answer the parameter or the matched? and onto to the collection itself, as in should the collection retain, and answer, the (first) duplicate; or replace, thereby keeping, and answering, the (last) duplicate? we get a different point of view: firstAmongEquals == (collection remove: (collection add: firstAmongEquals)) ifTrue: [collection isRetaining | collection isReplacing] ifFalse: [collection isBroken]. firstAmongEquals == (collection remove: (collection add: aDuplicate)) ifTrue: [collection isRetaining] ifFalse: [collection isBroken]. aDuplicate == (collection remove: (collection add: aDuplicate)) ifTrue: [collection isReplacing] ifFalse: [collection isBroken]. Hashed collections are not, at present, maintaining these invariants, and hence hashed collections {Sets, Bags, Dictionaries, etc.} can be described as non-deterministically non-deterministic -- a.k.a. NFG. Therefore the solution described above (whether flippant or fully spec'd) is inappropriate, because the non-determinism isn't *proper*, algorithmic non-determinism. We *should* care about the nuances -- both contexts are legitimate, and *would* occur in practise, if we *could* care about the nuances. But we *can't*. Well, *you* can't. I can send an implementation which corrects for this, but as the treatment is not recognized as "standard practice" and as the malady you are no doubt suffering from is quite clearly a pre-existing condition, I'm afraid your insurance is unlikely to cover any of the costs, which are, alas, unknown, but possibly extensive. Have a nice day. Cheers, -cstb >-- >Travis Griggs >Objologist >"There are a thousand hacking at the branches of evil to one who is >striking at the root" - Henry David Thoreau Nice quote ;-) _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc IMPORTANT NOTICE Email from OOCL is confidential and may be legally privileged. If it is not intended for you, please delete it immediately unread. The internet cannot guarantee that this communication is free of viruses, interception or interference and anyone who communicates with us by email is taken to accept the risks in doing so. Without limitation, OOCL and its affiliates accept no liability whatsoever and howsoever arising in connection with the use of this email. Under no circumstances shall this email constitute a binding agreement to carry or for provision of carriage services by OOCL, which is subject to the availability of carrier's equipment and vessels and the terms and conditions of OOCL's standard bill of lading which is also available at http://www.oocl.com. _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Free forum by Nabble | Edit this page |