about Dictionary valuesDo:

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

about Dictionary valuesDo:

Nicolas Cellier
Is there any difference with #do: ?
If not, I suggest deprecating #valuesDo:

More other, browsing #values senders, this pattern:
    aDictionary values do: [:aValue | self doSomethingWith: aValue].
can often be replaced with:
    aDictionary do: [:aValue | self doSomethingWith: aValue].
except of course when aDictionary is modified inside the loop.

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: about Dictionary valuesDo:

Nicolas Cellier
Traditionally in st80, #keys returns a Set of keys, and #values a Bag
of values...
Rationale: none of them is ordered.
Now I noticed squeak #values returns an Array, and wondered why by
analyzing senders.
Most of them are superfluous, and maybe this will explain latest wave
of commits in the trunk.

Now I find the idea of answering an Array a good one,
- because it is faster than a Bag (no lookup)
- for historical reasons, some senders expect a SequenceableCollection,
- while no senders seems to rely on a Bag protocol

Others think the same should apply to keys, because of speed too, and
because of rare expectation of Set specific protocol.
This is #fasterKeys.
What do squeakers think ? Shouldn't we do to the #keys what we did to
the #values ?

Nicolas

2009/10/19 Nicolas Cellier <[hidden email]>:

> Is there any difference with #do: ?
> If not, I suggest deprecating #valuesDo:
>
> More other, browsing #values senders, this pattern:
>    aDictionary values do: [:aValue | self doSomethingWith: aValue].
> can often be replaced with:
>    aDictionary do: [:aValue | self doSomethingWith: aValue].
> except of course when aDictionary is modified inside the loop.
>
> Nicolas
>

Reply | Threaded
Open this post in threaded view
|

Re: about Dictionary valuesDo:

Nicolas Cellier
So I gave it a try with a bunch of commits
(ouch, commiting is longer than editing!)

I used #fasterKeys because the message already exist.
I cannot change keys directly, a few senders really expect a Set (plus
external packages...)

Reverting is easy, just change senders of fasterKeys -> keys, or force
load of packages from update-nice.40.mcm.

Nicolas

2009/10/19 Nicolas Cellier <[hidden email]>:

> Traditionally in st80, #keys returns a Set of keys, and #values a Bag
> of values...
> Rationale: none of them is ordered.
> Now I noticed squeak #values returns an Array, and wondered why by
> analyzing senders.
> Most of them are superfluous, and maybe this will explain latest wave
> of commits in the trunk.
>
> Now I find the idea of answering an Array a good one,
> - because it is faster than a Bag (no lookup)
> - for historical reasons, some senders expect a SequenceableCollection,
> - while no senders seems to rely on a Bag protocol
>
> Others think the same should apply to keys, because of speed too, and
> because of rare expectation of Set specific protocol.
> This is #fasterKeys.
> What do squeakers think ? Shouldn't we do to the #keys what we did to
> the #values ?
>
> Nicolas
>
> 2009/10/19 Nicolas Cellier <[hidden email]>:
>> Is there any difference with #do: ?
>> If not, I suggest deprecating #valuesDo:
>>
>> More other, browsing #values senders, this pattern:
>>    aDictionary values do: [:aValue | self doSomethingWith: aValue].
>> can often be replaced with:
>>    aDictionary do: [:aValue | self doSomethingWith: aValue].
>> except of course when aDictionary is modified inside the loop.
>>
>> Nicolas
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: about Dictionary valuesDo:

Andreas.Raab
Hi Nicolas -

I agree with your (original) reasoning that keys should return an array
just like values. Not only because of performance, but also because it
preserves ordering between keys and values making "aDict keys with:
aDict values do:" nicely symmetrical to "aDict keysAndValuesDo:".

Nicolas Cellier wrote:
> So I gave it a try with a bunch of commits
> (ouch, commiting is longer than editing!)
>
> I used #fasterKeys because the message already exist.
> I cannot change keys directly, a few senders really expect a Set (plus
> external packages...)

Which ones are those? I do dislike the idea of using fasterKeys. It's a
bad name (like using #valuesWithOrder instead of #values) and unless the
difficulties with the change are systematic (i.e., usage patterns that
are not easily detected and lead to hidden and hard to find issues) I
would much rather see this fixed than worked around.

Can you provide some examples of places that break?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Nicolas Cellier
2009/10/20 Andreas Raab <[hidden email]>:

> Hi Nicolas -
>
> I agree with your (original) reasoning that keys should return an array just
> like values. Not only because of performance, but also because it preserves
> ordering between keys and values making "aDict keys with: aDict values do:"
> nicely symmetrical to "aDict keysAndValuesDo:".
>
> Nicolas Cellier wrote:
>>
>> So I gave it a try with a bunch of commits
>> (ouch, commiting is longer than editing!)
>>
>> I used #fasterKeys because the message already exist.
>> I cannot change keys directly, a few senders really expect a Set (plus
>> external packages...)
>
> Which ones are those? I do dislike the idea of using fasterKeys. It's a bad
> name (like using #valuesWithOrder instead of #values) and unless the
> difficulties with the change are systematic (i.e., usage patterns that are
> not easily detected and lead to hidden and hard to find issues) I would much
> rather see this fixed than worked around.
>

Totally agree about the bad name !
My plan was to use this name in an interim period, gradually handle
special cases of methods expecting a Set, change keys to behave as
fasterKeys, then deprecate message fasterKeys.

> Can you provide some examples of places that break?
>

Look among 49 remaining senders of keys, a few use usage like #selectors do.

Nicolas

> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Bert Freudenberg
In reply to this post by Andreas.Raab

On 20.10.2009, at 06:54, Andreas Raab wrote:

> Hi Nicolas -
>
> I agree with your (original) reasoning that keys should return an  
> array just like values. Not only because of performance, but also  
> because it preserves ordering between keys and values making "aDict  
> keys with: aDict values do:" nicely symmetrical to "aDict  
> keysAndValuesDo:".
>
> Nicolas Cellier wrote:
>> So I gave it a try with a bunch of commits
>> (ouch, commiting is longer than editing!)
>> I used #fasterKeys because the message already exist.
>> I cannot change keys directly, a few senders really expect a Set  
>> (plus
>> external packages...)
>
> Which ones are those? I do dislike the idea of using fasterKeys.  
> It's a bad name (like using #valuesWithOrder instead of #values) and  
> unless the difficulties with the change are systematic (i.e., usage  
> patterns that are not easily detected and lead to hidden and hard to  
> find issues) I would much rather see this fixed than worked around.
>
> Can you provide some examples of places that break?
>
> Cheers,
>  - Andreas

Yes, #fasterKeys is ugly. I'd rather replace the places that need a  
Set with "keys asSet". Unless ANSI says differently - could someone  
check?

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Nicolas Cellier
2009/10/20 Bert Freudenberg <[hidden email]>:

>
> On 20.10.2009, at 06:54, Andreas Raab wrote:
>
>> Hi Nicolas -
>>
>> I agree with your (original) reasoning that keys should return an array
>> just like values. Not only because of performance, but also because it
>> preserves ordering between keys and values making "aDict keys with: aDict
>> values do:" nicely symmetrical to "aDict keysAndValuesDo:".
>>
>> Nicolas Cellier wrote:
>>>
>>> So I gave it a try with a bunch of commits
>>> (ouch, commiting is longer than editing!)
>>> I used #fasterKeys because the message already exist.
>>> I cannot change keys directly, a few senders really expect a Set (plus
>>> external packages...)
>>
>> Which ones are those? I do dislike the idea of using fasterKeys. It's a
>> bad name (like using #valuesWithOrder instead of #values) and unless the
>> difficulties with the change are systematic (i.e., usage patterns that are
>> not easily detected and lead to hidden and hard to find issues) I would much
>> rather see this fixed than worked around.
>>
>> Can you provide some examples of places that break?
>>
>> Cheers,
>>  - Andreas
>
> Yes, #fasterKeys is ugly. I'd rather replace the places that need a Set with
> "keys asSet". Unless ANSI says differently - could someone check?
>
> - Bert -
>

That's what it will turn into...
OK, I realize we should better attack the problem under this angle:
1) modify senders expecting a Set keys -> keys asSet
2) change keys implentation -> faster keys implementation

I can do this this evening, unless there is another taker

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: about Dictionary valuesDo:

Andreas.Raab
In reply to this post by Nicolas Cellier
Nicolas Cellier wrote:
>> Can you provide some examples of places that break?
>
> Look among 49 remaining senders of keys, a few use usage like #selectors do.

Looking through this, nothing springs to mind that would break. Even
places like, e.g., aClass selectors includes: aSelector should continue
to work with the one possible exception that in cases where
IdentityDictionary keys are used the resulting collection should compare
identity not equality, which would be a problem if there were code that
expects e.g., Object selectors includes: 'yourself' => false. (that
seems rare)

But other than that I don't really see anything that would break with
the change. Have you tried making the change and just run all the tests
to see which ones break and why?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Eliot Miranda-2
In reply to this post by Bert Freudenberg


On Tue, Oct 20, 2009 at 1:49 AM, Bert Freudenberg <[hidden email]> wrote:

On 20.10.2009, at 06:54, Andreas Raab wrote:

Hi Nicolas -

I agree with your (original) reasoning that keys should return an array just like values. Not only because of performance, but also because it preserves ordering between keys and values making "aDict keys with: aDict values do:" nicely symmetrical to "aDict keysAndValuesDo:".

Nicolas Cellier wrote:
So I gave it a try with a bunch of commits
(ouch, commiting is longer than editing!)
I used #fasterKeys because the message already exist.
I cannot change keys directly, a few senders really expect a Set (plus
external packages...)

Which ones are those? I do dislike the idea of using fasterKeys. It's a bad name (like using #valuesWithOrder instead of #values) and unless the difficulties with the change are systematic (i.e., usage patterns that are not easily detected and lead to hidden and hard to find issues) I would much rather see this fixed than worked around.

Can you provide some examples of places that break?

Cheers,
 - Andreas

Yes, #fasterKeys is ugly. I'd rather replace the places that need a Set with "keys asSet". Unless ANSI says differently - could someone check?

You're in the clear.  Here's the relevant screed from my draft standard:

Protocol: <abstractDictionary XE "abstractDictionary" >

Conforms To

<collection>

Description

Provides protocol for accessing, adding, removing, and iterating over the elements of an unordered collection whose elements are accessed using an explicitly assigned external key.

Glossary Entries

Messages

addAll:

at:

at:ifAbsent:

at:ifAbsentPut:

at:put:

collect:

includesKey:

keyAtValue:

keyAtValue:ifAbsent:

keys

keysAndValuesDo:

keysDo:

reject:

removeAllKeys:

removeAllKeys:ifAbsent:

removeKey:

removeKey:ifAbsent:

select:

values


...

Message: keys

Synopsis

Answer a collection of keys at which there is an element stored in the receiver.

Definition: <abstractDictionary>

Answer a collection of all the keys in the receiver.  The size of the result is equal to the size of the receiver.

Return Values

<collection> unspecified

Errors

none


...

There are also places where the standard explicitly denotes something as unspecified. Most notably, the protocol section allows an unspecified return value. The specifics of such features are not defined by the standard although some reasonable behavior is required.  Conforming implementation must support the feature but need not documented the details of the implementation.

A Smalltalk program conforms to the standard if it only makes use of features defined in the standard. It may use implementation-defined features or unspecified features and still be considered a conforming program, though doing so may limit the program's portability.



- Bert -






Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Nicolas Cellier
In reply to this post by Andreas.Raab
well, among 49 senders of keys, I see very few problem:

Bag>>#asSet obviously
Behavior>>#selector the comment tells Set, but is it necessary ?

among 92 usages of selectors

basicLocalSelectors: aSetOrNil
        localSelectors := aSetOrNil
traits ? didn't try to follow further

some will use remove which is not an Array protocol (removeAllFoundIn:
from #replaceSilently:to:)

some usages like class selectors includes: will be a bit less efficient

#classVarNames comment tells a Set, though code would behave as well
with a sorted collection...

some = test might not work if collection is arbitrarily ordered
(tempRefs keys = method startpcsToBlockExtents values asSet)

ImageSegment findRogueRootsRefStrm: will use remove:

A few asSet should be necessary.

Nicolas


2009/10/20 Andreas Raab <[hidden email]>:

> Nicolas Cellier wrote:
>>>
>>> Can you provide some examples of places that break?
>>
>> Look among 49 remaining senders of keys, a few use usage like #selectors
>> do.
>
> Looking through this, nothing springs to mind that would break. Even places
> like, e.g., aClass selectors includes: aSelector should continue to work
> with the one possible exception that in cases where IdentityDictionary keys
> are used the resulting collection should compare identity not equality,
> which would be a problem if there were code that expects e.g., Object
> selectors includes: 'yourself' => false. (that seems rare)
>
> But other than that I don't really see anything that would break with the
> change. Have you tried making the change and just run all the tests to see
> which ones break and why?
>
> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Nicolas Cellier
So my plan is currently:

- track #keys usage, and use #asSet where due to be future proof
- this involves inquiring some keys senders like selectors and classVarNames
- publish a mcm
- change keys to behave like fasterKeys
- publish a mcm
- revert fasterKeys senders to just send keys (except the bug I found,
and a few #sort shortcuts)

Don't know if feasible in one evening...

2009/10/20 Nicolas Cellier <[hidden email]>:

> well, among 49 senders of keys, I see very few problem:
>
> Bag>>#asSet obviously
> Behavior>>#selector the comment tells Set, but is it necessary ?
>
> among 92 usages of selectors
>
> basicLocalSelectors: aSetOrNil
>        localSelectors := aSetOrNil
> traits ? didn't try to follow further
>
> some will use remove which is not an Array protocol (removeAllFoundIn:
> from #replaceSilently:to:)
>
> some usages like class selectors includes: will be a bit less efficient
>
> #classVarNames comment tells a Set, though code would behave as well
> with a sorted collection...
>
> some = test might not work if collection is arbitrarily ordered
> (tempRefs keys = method startpcsToBlockExtents values asSet)
>
> ImageSegment findRogueRootsRefStrm: will use remove:
>
> A few asSet should be necessary.
>
> Nicolas
>
>
> 2009/10/20 Andreas Raab <[hidden email]>:
>> Nicolas Cellier wrote:
>>>>
>>>> Can you provide some examples of places that break?
>>>
>>> Look among 49 remaining senders of keys, a few use usage like #selectors
>>> do.
>>
>> Looking through this, nothing springs to mind that would break. Even places
>> like, e.g., aClass selectors includes: aSelector should continue to work
>> with the one possible exception that in cases where IdentityDictionary keys
>> are used the resulting collection should compare identity not equality,
>> which would be a problem if there were code that expects e.g., Object
>> selectors includes: 'yourself' => false. (that seems rare)
>>
>> But other than that I don't really see anything that would break with the
>> change. Have you tried making the change and just run all the tests to see
>> which ones break and why?
>>
>> Cheers,
>>  - Andreas
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Nicolas Cellier
2009/10/20 Nicolas Cellier <[hidden email]>:
> So my plan is currently:
>
> - track #keys usage, and use #asSet where due to be future proof
> - this involves inquiring some keys senders like selectors and classVarNames

done, I added very few asSet
and I changed classVarNames messages to return a sorted Array. Hope it
works OK (no add: no remove: ).
Note that sorted Array do compare well with equality =

> - publish a mcm

update-nice.40.mcm

> - change keys to behave like fasterKeys
> - publish a mcm

Done, but the server just lost update-nice.41.mcm ...

> - revert fasterKeys senders to just send keys (except the bug I found,
> and a few #sort shortcuts)
Note: I kept (x keys asArray sort) rather than just (x keys sort) just
for compatibility issues.

- publish a mcm

update-nice.42.mcm but now that update-nice.41.mcm disappeared, I
don't know if it will work OK

- deprecate #fasterKeys

Done with my contract

Now we just have to chase the eventual bugs...

Nicolas


>
> Don't know if feasible in one evening...
>
> 2009/10/20 Nicolas Cellier <[hidden email]>:
>> well, among 49 senders of keys, I see very few problem:
>>
>> Bag>>#asSet obviously
>> Behavior>>#selector the comment tells Set, but is it necessary ?
>>
>> among 92 usages of selectors
>>
>> basicLocalSelectors: aSetOrNil
>>        localSelectors := aSetOrNil
>> traits ? didn't try to follow further
>>
>> some will use remove which is not an Array protocol (removeAllFoundIn:
>> from #replaceSilently:to:)
>>
>> some usages like class selectors includes: will be a bit less efficient
>>
>> #classVarNames comment tells a Set, though code would behave as well
>> with a sorted collection...
>>
>> some = test might not work if collection is arbitrarily ordered
>> (tempRefs keys = method startpcsToBlockExtents values asSet)
>>
>> ImageSegment findRogueRootsRefStrm: will use remove:
>>
>> A few asSet should be necessary.
>>
>> Nicolas
>>
>>
>> 2009/10/20 Andreas Raab <[hidden email]>:
>>> Nicolas Cellier wrote:
>>>>>
>>>>> Can you provide some examples of places that break?
>>>>
>>>> Look among 49 remaining senders of keys, a few use usage like #selectors
>>>> do.
>>>
>>> Looking through this, nothing springs to mind that would break. Even places
>>> like, e.g., aClass selectors includes: aSelector should continue to work
>>> with the one possible exception that in cases where IdentityDictionary keys
>>> are used the resulting collection should compare identity not equality,
>>> which would be a problem if there were code that expects e.g., Object
>>> selectors includes: 'yourself' => false. (that seems rare)
>>>
>>> But other than that I don't really see anything that would break with the
>>> change. Have you tried making the change and just run all the tests to see
>>> which ones break and why?
>>>
>>> Cheers,
>>>  - Andreas
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Re: about Dictionary valuesDo:

Igor Stasenko
I wonder, if its a feasible to make a proxies which instead of
creating a separate collection
will direct the requests to dictionary, i.e.:

Set subclass: #DictionaryKeys
instanceVariableNames: 'dict'
...

then:

Dictionary>>keys
  ^ DictionaryKeys on: self


same for values.
Any #asXXX methods should instantiate new collection. But any
iterations, like #do: etc.. should use dictionary.


2009/10/21 Nicolas Cellier <[hidden email]>:

> 2009/10/20 Nicolas Cellier <[hidden email]>:
>> So my plan is currently:
>>
>> - track #keys usage, and use #asSet where due to be future proof
>> - this involves inquiring some keys senders like selectors and classVarNames
>
> done, I added very few asSet
> and I changed classVarNames messages to return a sorted Array. Hope it
> works OK (no add: no remove: ).
> Note that sorted Array do compare well with equality =
>
>> - publish a mcm
>
> update-nice.40.mcm
>
>> - change keys to behave like fasterKeys
>> - publish a mcm
>
> Done, but the server just lost update-nice.41.mcm ...
>
>> - revert fasterKeys senders to just send keys (except the bug I found,
>> and a few #sort shortcuts)
> Note: I kept (x keys asArray sort) rather than just (x keys sort) just
> for compatibility issues.
>
> - publish a mcm
>
> update-nice.42.mcm but now that update-nice.41.mcm disappeared, I
> don't know if it will work OK
>
> - deprecate #fasterKeys
>
> Done with my contract
>
> Now we just have to chase the eventual bugs...
>
> Nicolas
>
>
>>
>> Don't know if feasible in one evening...
>>
>> 2009/10/20 Nicolas Cellier <[hidden email]>:
>>> well, among 49 senders of keys, I see very few problem:
>>>
>>> Bag>>#asSet obviously
>>> Behavior>>#selector the comment tells Set, but is it necessary ?
>>>
>>> among 92 usages of selectors
>>>
>>> basicLocalSelectors: aSetOrNil
>>>        localSelectors := aSetOrNil
>>> traits ? didn't try to follow further
>>>
>>> some will use remove which is not an Array protocol (removeAllFoundIn:
>>> from #replaceSilently:to:)
>>>
>>> some usages like class selectors includes: will be a bit less efficient
>>>
>>> #classVarNames comment tells a Set, though code would behave as well
>>> with a sorted collection...
>>>
>>> some = test might not work if collection is arbitrarily ordered
>>> (tempRefs keys = method startpcsToBlockExtents values asSet)
>>>
>>> ImageSegment findRogueRootsRefStrm: will use remove:
>>>
>>> A few asSet should be necessary.
>>>
>>> Nicolas
>>>
>>>
>>> 2009/10/20 Andreas Raab <[hidden email]>:
>>>> Nicolas Cellier wrote:
>>>>>>
>>>>>> Can you provide some examples of places that break?
>>>>>
>>>>> Look among 49 remaining senders of keys, a few use usage like #selectors
>>>>> do.
>>>>
>>>> Looking through this, nothing springs to mind that would break. Even places
>>>> like, e.g., aClass selectors includes: aSelector should continue to work
>>>> with the one possible exception that in cases where IdentityDictionary keys
>>>> are used the resulting collection should compare identity not equality,
>>>> which would be a problem if there were code that expects e.g., Object
>>>> selectors includes: 'yourself' => false. (that seems rare)
>>>>
>>>> But other than that I don't really see anything that would break with the
>>>> change. Have you tried making the change and just run all the tests to see
>>>> which ones break and why?
>>>>
>>>> Cheers,
>>>>  - Andreas
>>>>
>>>>
>>>
>>
>
>



--
Best regards,
Igor Stasenko AKA sig.