Review API for consistency
The methods of DataFrame were created at different time over 2 years. Because of that API is sometimes inconsistent. We need to review all methods, remove the redundant ones and rename those with confusing names. Protocols also have to be reviewed.
DataSeries withKeyDo: aBlock needs aBlock to have :value and :key as arguments. It should, however, accept only 1 argument - key.
Also, since DataSeries inherits OrderedDictionary, which has keysDo (and keysAndValuesDo), do we need withKeyDo?
I'm not sure if I understood you correctly, but:
Collections in Smalltalk respond to a message do: which accepts aBlock as argument and applies that block to every element of the collection. aBlock therefore takes one argument - the element on which it will be applied.
Example:
Transcript open; clear.
#(a b c d) do: [ :each |
Transcript show: each; cr ].
Result:
a
b
c
d
For sequenceable collections, there is also a message withIndexDo: which allows to enumerate their elements together with their indices. This message accepts a two-argument block: first argument is the element, second argument is the index of that element.
Example:
Transcript open; clear.
#(a b c d) withIndexDo: [ :each :index |
Transcript show: '[', index asString, '] ', each; cr ].
Result:
[1] a
[2] b
[3] c
[4] d
OrderedDictionary, which is the superclass of DataSeries is basically a SequentiableCollection (an array) with keys instead of indices. In my opinion, current implementation of OrderedDictionary is bad and very inconsistent - we should improve it. So I will show examples on DataSeries.
temperature := DataSeries
withKeys: (#('01:10' '01:30' '01:50' '02:10' '02:30') collect: #asTime)
values: #(2.4 0.5 -1.2 -2.3 3.2)
name: #temperature.
DataSeries has message do: which takes aBlock as an argument and applies it to every element of the series. The block therefore takes one argument - the element to which it should be applied:
Example:
Transcript open; clear.
temperature do: [ :each |
Transcript show: each; cr ].
Result:
2.4
0.5
-1.2
-2.3
3.2
There is also a message withIndexDo: which allows you to enumerate elements together with their indices. It takes as argument a two-argument block which expects an element and an index:
Example:
Transcript open; clear.
temperature withIndexDo: [ :each :index |
Transcript show: '[', index asString, '] ', each asString; cr ].
Result:
[1] 2.4
[2] 0.5
[3] -1.2
[4] -2.3
[5] 3.2
And a similar message withKeyDo: that allows you to enumerate elements together with their keys:
Example:
Transcript open; clear.
temperature withKeyDo: [ :each :key |
Transcript show: '[', key asString, '] ', each asString; cr ].
Result:
[1:10 am] 2.4
[1:30 am] 0.5
[1:50 am] -1.2
[2:10 am] -2.3
[2:30 am] 3.2
And there is a message keysDo: which allows you to enumerate only keys. It takes a one-argument block and applies it to each key of the data series.
Example:
Transcript open; clear.
temperature keysDo: [ :key |
Transcript show: key; cr ].
Result:
1:10 am
1:30 am
1:50 am
2:10 am
2:30 am
In fact, it is the same as asking temperature series for a collection of its keys and sending do: message to that collection:
Transcript open; clear.
temperature keys do: [ :key |
Transcript show: key; cr ].
Interesting literature on this topic:
- Section
2.7. Enumerating values of data seriesof the DataFrame booklet - Section
Enumerating Elements(p. 136) of Chapter9. Protocol for All Collection Classesof the Blue Book - Thread on the mailing list where we discussed the interface for
withIndexDo:
Thanks for the detailed explanation and links. I assumed withKeysDo: was same as keysDo and got confused. Now it's all clear :)