[vwnc] Some history on Collection>>remove:[ifAbsent:]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[vwnc] Some history on Collection>>remove:[ifAbsent:]

thomas.hawker

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!

 

Tom Hawker

Senior Framework Developer

Home

+1 (408) 274-4128

The Environment:

We take it personally

Office

+1 (408) 576-6591

Mobile

+1 (408) 835-3643

 

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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Travis Griggs-3

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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Niall Ross
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Anthony Lander-2

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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Travis Griggs-3
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Steven Kelly
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

Anthony Lander-2
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

thomas.hawker
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection&gt;&gt;remove:[ifAbsent:]

Nicolas Cellier-3
 <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
jas
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

jas
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
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Some history on Collection>>remove:[ifAbsent:]

thomas.hawker
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