Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- 2 participants
- 50347 messages
Minimality
by Cédrick Béler
Just a reflexion that Iâd like to share here.
When Hilaire talks about complexity. I have to agree too, even if I like the progress under the hood, and explored spaces like GToolkit.
But how to change such legacy beast, the pharo image ? Potential is huge but resistance is also tough for so few people⦠Just imagining changing method protocols seems so complex at the end !
Instead, Iâd start with minimal images, bootstrapped ones. A system I would love to understand every bits. Iâm pretty sure this is what lots of us have in mind and the progress in bootstrap has been teasing us ;-)
<dreamMode>
For instance, Iâd want minimal images that would be able to deal with collections of informations (text/data processing) with (web)socket connectivity or whatever cheapest way to communicate. It would be some kind of information store, a minimal image that can store information objects and that I can interact with a client in a full pharo image (or in a web browser).
Wouldnât it be possible to start from scratch, literally from nothing (nil) and define little by little what necessary and along the way define minimal protocols, minimal Object class and then iteratively a clean collection hierarchy until ⦠(for me) ⦠the information store.
That would probably need some filesystem support but itâs not an obligation. Iâd far prefer web socket stream support and interaction with object only within the image. Another image could be responsible of exporting information objects to files⦠It also need some basic mime types support and probably parsing (xml/html, json, geojson, ical, â¦). I donât know well. But it has to be iteratively done anyway.
I imagine there are not one but several images (and therefore source code) that would lead to functionally equivalent images. There should be some ways to abstract functionalities we expect of a system (if people have pointers on that) ?
We could even imagine like a Contest to come up with the nicest pharo images (contest driven by tests ^^).
Depending on the functionality coverage, thatâd be just crazy to see similarities between code/imagesâ¦
</dreamMode>
Is it feasible, does some of the remarks makes sense to some of you ?
At least, Caro, as we talked a bit, your writings on such a quest will be terrific, and Iâm sure well followed ;-)
Have a nice Easter Monday,
Cédrick
April 13, 2020
Re: [Pharo-users] Discussions on method categories (Was: Moving/rolling average implementations ?)
by Cédrick Béler
(this is not really noise, at least useful one ie. an information like the +1 :) )
At least, I think we need « standard » protocols list, at least for the most used ones. Some conventions too.
For instance, all the initialize* (+ class side)⦠I can cope with that but this is clearly a brain stopper for me :grinning:.
Were they some attempts to define such standard list / best practices for protocols ?
I guess this is a huge task but one important one. Regarding implementations, it might be hard to change too much for compatibility reasons (nb: exercice for later => get all protocols name of an image)
@++
Cédrick
> Le 13 avr. 2020 à 12:03, Guillermo Polito <guillermopolito(a)gmail.com> a écrit :
>
>
>
>> El 13 abr 2020, a las 11:17, Cédrick Béler <cdrick65(a)gmail.com> escribió:
>>
>>
>>> Used consistently and well, method categories are not only a
>>> navigation aid, helping you to find methods you do not know the names
>>> of, but a helpful documentation aid. For example, #runningMeans: is
>>> in the 'summarising' category. In my Smalltalk, that means
>>> - it inspects every element of the collection
>>> - it does not change the collection
>>> - the result is somehow a summary or distillation of the elements
>>
>> Great. If only categories were more first class, we could store such information.
>
> Haha just said the same in the other thread ^^.
> Sorry for the noise
April 13, 2020
Re: [Pharo-users] Discussions on method categories (Was: Moving/rolling average implementations ?)
by Guillermo Polito
> El 13 abr 2020, a las 11:17, Cédrick Béler <cdrick65(a)gmail.com> escribió:
>
>
>> Used consistently and well, method categories are not only a
>> navigation aid, helping you to find methods you do not know the names
>> of, but a helpful documentation aid. For example, #runningMeans: is
>> in the 'summarising' category. In my Smalltalk, that means
>> - it inspects every element of the collection
>> - it does not change the collection
>> - the result is somehow a summary or distillation of the elements
>
> Great. If only categories were more first class, we could store such information.
Haha just said the same in the other thread ^^.
Sorry for the noise
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Guillermo Polito
> El 13 abr 2020, a las 11:00, Richard O'Keefe <raoknz(a)gmail.com> escribió:
>
> Concerning method categories:
> VIsualAge Smalltalk manages without them. Of all the Smalltalk
> systems available to me, it's the only one where I don't enjoy using
> the browser. It carves up the world of methods another way, which I
> find of little or no help. That in no way detracts from it being a
> solid system fit for its intended uses.
>
> GNU Smalltalk uses <category: 'whatever'> pragmas to put methods into
> categories.
>
> Used consistently and well, method categories are not only a
> navigation aid, helping you to find methods you do not know the names
> of, but a helpful documentation aid. For example, #runningMeans: is
> in the 'summarising' category. In my Smalltalk, that means
> - it inspects every element of the collection
> - it does not change the collection
> - the result is somehow a summary or distillation of the elements
> Of course, to get the most from method categories, the method
> categories need to be documented, and you need to keep them as up to
> date as any other part of the source code.
It would be interesting if protocols had comments :)
>
> I can say that the discipline of trying to come up with meaningful
> categories and use them consistently has improved the quality of my
> code.
>
> On Mon, 13 Apr 2020 at 00:38, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>
>> Fully agree on proper names.
>>
>> === I donât know if this is because of free confinement time but I can keep on asking questions so I share some I hope will make sense (for the sake of discussion).
>>
>> For instance, I'm wondering if tests on conditions so as to raise proper exceptions is a good practice (for instance if the width object does not make sense, like a float) #doesNotMakeSense btw would be a cool name for the « maybe » cases Richard was talking.
>>
>> Then I asked myself what are the drawbacks (especially on performance) on adding extra information to source code (a bit like longer variable names) ?
>>
>> There is the raw code and the sources code file that helps separating concerns. At least we donât mind at all having longer literals (variables names, â¦).
>>
>> I cannot help is what about pragmas. I kind see roughly how they work. But is it possible to distinguish between runtime / source only pragmas (not sure Iâm clear here but it seems to me that some are important for documentation purposes that are not needed at runtime) ?
>>
>> Also, Iâve never really liked method categories. I donât really see how there are implemented but they donât feel nice to me.
>> Could they be only pragmas ?
>>
>>
>>
>>
>>
>> Happy eater Sunday, stay all preserved (sad day for the game of life),
>>
>> Cédrick
>>
>>
>>
>>> Le 12 avr. 2020 à 14:22, Sven Van Caekenberghe <sven(a)stfx.eu> a écrit :
>>>
>>>
>>>
>>>> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>>>
>>>> Beautiful ^^
>>>
>>> I also like it.
>>>
>>> But why the single letter variable names ? Why not:
>>>
>>> SequenceableCollection>>#runningMeans: width
>>> | means sum index |
>>> means := Array new: self size - width + 1.
>>> sum := 0.
>>> 1 to: width do: [ :each |
>>> sum := sum + (self at: each) ].
>>> index := 1.
>>> means at: index put: sum / width.
>>> width + 1 to: self size do: [ :each |
>>> sum := sum - (self at: index) + (self at: each).
>>> index := index + 1.
>>> means at: index put: sum / width ].
>>> ^ means
>>>
>>> A good comment, a correct initial bounds check and unit tests are also needed.
>>>
>>>> I would vote for inclusion in the base image ?
>>>> With your explanation as comments.
>>>>
>>>> Iâll play with it.
>>>>
>>>> Thanks
>>>> Cedrick
>>>>
>>>>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>>>>
>>>>> 
>>>>> I have coded and benchmarked 8 different running mean algorithms.
>>>>> In the presence of inexact numbers it is not as accurate as
>>>>> redoing the sums, but it's pretty close, and it's fast.
>>>>> If "width" is not an integer or is out of range, an error
>>>>> will be reported by #new: or #at:[put:]. It's based on Welford's
>>>>> stable update.
>>>>>
>>>>> Of course this approach does NOT work for trimmed or Winsorised
>>>>> means or for medians or any kind of robust estimate of location.
>>>>>
>>>>> SequenceableCollection
>>>>> methods for: 'summarising'
>>>>> runningMeans: width
>>>>> |a m d|
>>>>> a := Array new: self size - width + 1.
>>>>> m := 0.
>>>>> 1 to: width do: [:i |
>>>>> m := (self at: i) + m].
>>>>> m := m / width.
>>>>> d := 1.
>>>>> a at: d put: m.
>>>>> width + 1 to: self size do: [:i |
>>>>> m := ((self at: i) - (self at: d)) / width + m.
>>>>> d := d + 1.
>>>>> a at: d put: m].
>>>>> ^a
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>>
>
April 13, 2020
Discussions on method categories (Was: Moving/rolling average implementations ?)
by Cédrick Béler
> Used consistently and well, method categories are not only a
> navigation aid, helping you to find methods you do not know the names
> of, but a helpful documentation aid. For example, #runningMeans: is
> in the 'summarising' category. In my Smalltalk, that means
> - it inspects every element of the collection
> - it does not change the collection
> - the result is somehow a summary or distillation of the elements
Great. If only categories were more first class, we could store such information.
I agree that a proper name is important but this is kind of hell to do bu yourself as minait no help.
>From you definition, I see that the category can be associated to tests that might eventually auto categorize.
Anyway, with such artefact, this is before being a tool artefact, a discipline one (convetions). I just have headaches each time I have to write my categories ^^especially with the UI.
Shouldnât category by more like tags ? And first class object (more source oriented even if some could be helpful at runtime like private methods) ?
Cheers,
Cédrick
> Of course, to get the most from method categories, the method
> categories need to be documented, and you need to keep them as up to
> date as any other part of the source code.
>
> I can say that the discipline of trying to come up with meaningful
> categories and use them consistently has improved the quality of my
> code.
>
> On Mon, 13 Apr 2020 at 00:38, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>
>> Fully agree on proper names.
>>
>> === I donât know if this is because of free confinement time but I can keep on asking questions so I share some I hope will make sense (for the sake of discussion).
>>
>> For instance, I'm wondering if tests on conditions so as to raise proper exceptions is a good practice (for instance if the width object does not make sense, like a float) #doesNotMakeSense btw would be a cool name for the « maybe » cases Richard was talking.
>>
>> Then I asked myself what are the drawbacks (especially on performance) on adding extra information to source code (a bit like longer variable names) ?
>>
>> There is the raw code and the sources code file that helps separating concerns. At least we donât mind at all having longer literals (variables names, â¦).
>>
>> I cannot help is what about pragmas. I kind see roughly how they work. But is it possible to distinguish between runtime / source only pragmas (not sure Iâm clear here but it seems to me that some are important for documentation purposes that are not needed at runtime) ?
>>
>> Also, Iâve never really liked method categories. I donât really see how there are implemented but they donât feel nice to me.
>> Could they be only pragmas ?
>>
>>
>>
>>
>>
>> Happy eater Sunday, stay all preserved (sad day for the game of life),
>>
>> Cédrick
>>
>>
>>
>>> Le 12 avr. 2020 à 14:22, Sven Van Caekenberghe <sven(a)stfx.eu> a écrit :
>>>
>>>
>>>
>>>> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>>>
>>>> Beautiful ^^
>>>
>>> I also like it.
>>>
>>> But why the single letter variable names ? Why not:
>>>
>>> SequenceableCollection>>#runningMeans: width
>>> | means sum index |
>>> means := Array new: self size - width + 1.
>>> sum := 0.
>>> 1 to: width do: [ :each |
>>> sum := sum + (self at: each) ].
>>> index := 1.
>>> means at: index put: sum / width.
>>> width + 1 to: self size do: [ :each |
>>> sum := sum - (self at: index) + (self at: each).
>>> index := index + 1.
>>> means at: index put: sum / width ].
>>> ^ means
>>>
>>> A good comment, a correct initial bounds check and unit tests are also needed.
>>>
>>>> I would vote for inclusion in the base image ?
>>>> With your explanation as comments.
>>>>
>>>> Iâll play with it.
>>>>
>>>> Thanks
>>>> Cedrick
>>>>
>>>>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>>>>
>>>>> 
>>>>> I have coded and benchmarked 8 different running mean algorithms.
>>>>> In the presence of inexact numbers it is not as accurate as
>>>>> redoing the sums, but it's pretty close, and it's fast.
>>>>> If "width" is not an integer or is out of range, an error
>>>>> will be reported by #new: or #at:[put:]. It's based on Welford's
>>>>> stable update.
>>>>>
>>>>> Of course this approach does NOT work for trimmed or Winsorised
>>>>> means or for medians or any kind of robust estimate of location.
>>>>>
>>>>> SequenceableCollection
>>>>> methods for: 'summarising'
>>>>> runningMeans: width
>>>>> |a m d|
>>>>> a := Array new: self size - width + 1.
>>>>> m := 0.
>>>>> 1 to: width do: [:i |
>>>>> m := (self at: i) + m].
>>>>> m := m / width.
>>>>> d := 1.
>>>>> a at: d put: m.
>>>>> width + 1 to: self size do: [:i |
>>>>> m := ((self at: i) - (self at: d)) / width + m.
>>>>> d := d + 1.
>>>>> a at: d put: m].
>>>>> ^a
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>>
>
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Cédrick Béler
And maybe another one to show deviation problem ?
testRunningMeansDeviation
| result1 result2 col1 col2 |
col1 := #(0.3s1 1s1 0.1s1 0.3s1 1s1 0.1s1 0.3s1 1s1 0.1s1).
result1 := col1 runningMeans: 2.
col2 := #(0.3 1 0.1 0.3 1 0.1 0.3 1 0.1).
result2 := col2 runningMeans: 2.
self assert: result1 first equals: result1 fourth.
"presence of a rounding error"
self deny: result2 first equals: result2 fourth.
self assert: result2 first closeTo: result2 fourth.
> Le 13 avr. 2020 à 10:48, Cédrick Béler <cdrick65(a)gmail.com> a écrit :
>
> What about this test (in OrderedCollectionTest - it suggests a Trait too) ?
>
> testRunningMeans
>
> | result col |
> col := #(1 1 2 2 3 3) asOrderedCollection.
> result := col runningMeans: 2.
>
> self assert: (result = {1. (3/2). 2. (5/2). 3}).
>
> self assert: (result class = Array).
>
> self assert: result size <= (col size). "Running means with 1 has little interest ?"
>
> self should: [ col runningMeans: 7 ] raise: SubscriptOutOfBounds.
> self should: [ col runningMeans: -2 ] raise: SubscriptOutOfBounds.
> self should: [ col runningMeans: 1.3 ] raise: Error withExceptionDo: [ :anException | self assert: anException messageText equals: 'primitive #basicNew: in Array class failedâ ]
>
>
> Cheers,
> Cédrick
>
>> Le 13 avr. 2020 à 04:47, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>
>> I did mention that it was one of eight implementations that I tried.
>> In fact you broke it with your change.
>> It is important ***NOT*** to keep a running sum but a running MEAN.
>> The line
>> m := ((self at: i) - (self at: d)) / width + m
>> was written that way for a reason.
>>
>> I did think of renaming the variables for general use, but decided to display
>> the actual code that I tested. If you want polished code, here it is.
>>
>> runningMeans: width
>> "This returns an array of running means as if the receiver
>> were broken into overlapping segments 'width' long and the
>> mean of each calculated. This uses an adaptation of
>> Welford's algorithm for stably updating the mean; it is
>> important to maintain a current MEAN not a current SUM.
>> This has been tested against 7 other algorithms. It was
>> the most accurate of the faster ones. The result is an
>> Array no matter what kind of sequence the receiver is.
>> If the receiver is a tree (like a virtual concatenation)
>> or a singly or doubly linked list you should convert the
>> receiver to an Array first. Note that there is no
>> explicit check that width is an Integer or is in range;
>> none is needed because those checks happen anyway."
>> |result mean resultIndex|
>> result := Array new: self size - width + 1.
>> mean := 0.
>> 1 to: width do: [:i | mean := (self at: i) + mean].
>> mean := mean / width.
>> resultIndex := 1.
>> result at: resultIndex put: mean.
>> width + 1 to: self size do: [:i |
>> mean := ((self at: i) - (self at: resultIndex)) / width + mean.
>> resultIndex := resultIndex + 1.
>> result at: resultIndex put: mean].
>> ^result
>>
>>
>>
>> On Mon, 13 Apr 2020 at 00:23, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>>>
>>>
>>>
>>>> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>>>
>>>> Beautiful ^^
>>>
>>> I also like it.
>>>
>>> But why the single letter variable names ? Why not:
>>>
>>> SequenceableCollection>>#runningMeans: width
>>> | means sum index |
>>> means := Array new: self size - width + 1.
>>> sum := 0.
>>> 1 to: width do: [ :each |
>>> sum := sum + (self at: each) ].
>>> index := 1.
>>> means at: index put: sum / width.
>>> width + 1 to: self size do: [ :each |
>>> sum := sum - (self at: index) + (self at: each).
>>> index := index + 1.
>>> means at: index put: sum / width ].
>>> ^ means
>>>
>>> A good comment, a correct initial bounds check and unit tests are also needed.
>>>
>>>> I would vote for inclusion in the base image ?
>>>> With your explanation as comments.
>>>>
>>>> Iâll play with it.
>>>>
>>>> Thanks
>>>> Cedrick
>>>>
>>>>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>>>>
>>>>> 
>>>>> I have coded and benchmarked 8 different running mean algorithms.
>>>>> In the presence of inexact numbers it is not as accurate as
>>>>> redoing the sums, but it's pretty close, and it's fast.
>>>>> If "width" is not an integer or is out of range, an error
>>>>> will be reported by #new: or #at:[put:]. It's based on Welford's
>>>>> stable update.
>>>>>
>>>>> Of course this approach does NOT work for trimmed or Winsorised
>>>>> means or for medians or any kind of robust estimate of location.
>>>>>
>>>>> SequenceableCollection
>>>>> methods for: 'summarising'
>>>>> runningMeans: width
>>>>> |a m d|
>>>>> a := Array new: self size - width + 1.
>>>>> m := 0.
>>>>> 1 to: width do: [:i |
>>>>> m := (self at: i) + m].
>>>>> m := m / width.
>>>>> d := 1.
>>>>> a at: d put: m.
>>>>> width + 1 to: self size do: [:i |
>>>>> m := ((self at: i) - (self at: d)) / width + m.
>>>>> d := d + 1.
>>>>> a at: d put: m].
>>>>> ^a
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Richard O'Keefe
Concerning method categories:
VIsualAge Smalltalk manages without them. Of all the Smalltalk
systems available to me, it's the only one where I don't enjoy using
the browser. It carves up the world of methods another way, which I
find of little or no help. That in no way detracts from it being a
solid system fit for its intended uses.
GNU Smalltalk uses <category: 'whatever'> pragmas to put methods into
categories.
Used consistently and well, method categories are not only a
navigation aid, helping you to find methods you do not know the names
of, but a helpful documentation aid. For example, #runningMeans: is
in the 'summarising' category. In my Smalltalk, that means
- it inspects every element of the collection
- it does not change the collection
- the result is somehow a summary or distillation of the elements
Of course, to get the most from method categories, the method
categories need to be documented, and you need to keep them as up to
date as any other part of the source code.
I can say that the discipline of trying to come up with meaningful
categories and use them consistently has improved the quality of my
code.
On Mon, 13 Apr 2020 at 00:38, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>
> Fully agree on proper names.
>
> === I donât know if this is because of free confinement time but I can keep on asking questions so I share some I hope will make sense (for the sake of discussion).
>
> For instance, I'm wondering if tests on conditions so as to raise proper exceptions is a good practice (for instance if the width object does not make sense, like a float) #doesNotMakeSense btw would be a cool name for the « maybe » cases Richard was talking.
>
> Then I asked myself what are the drawbacks (especially on performance) on adding extra information to source code (a bit like longer variable names) ?
>
> There is the raw code and the sources code file that helps separating concerns. At least we donât mind at all having longer literals (variables names, â¦).
>
> I cannot help is what about pragmas. I kind see roughly how they work. But is it possible to distinguish between runtime / source only pragmas (not sure Iâm clear here but it seems to me that some are important for documentation purposes that are not needed at runtime) ?
>
> Also, Iâve never really liked method categories. I donât really see how there are implemented but they donât feel nice to me.
> Could they be only pragmas ?
>
>
>
>
>
> Happy eater Sunday, stay all preserved (sad day for the game of life),
>
> Cédrick
>
>
>
> > Le 12 avr. 2020 à 14:22, Sven Van Caekenberghe <sven(a)stfx.eu> a écrit :
> >
> >
> >
> >> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
> >>
> >> Beautiful ^^
> >
> > I also like it.
> >
> > But why the single letter variable names ? Why not:
> >
> > SequenceableCollection>>#runningMeans: width
> > | means sum index |
> > means := Array new: self size - width + 1.
> > sum := 0.
> > 1 to: width do: [ :each |
> > sum := sum + (self at: each) ].
> > index := 1.
> > means at: index put: sum / width.
> > width + 1 to: self size do: [ :each |
> > sum := sum - (self at: index) + (self at: each).
> > index := index + 1.
> > means at: index put: sum / width ].
> > ^ means
> >
> > A good comment, a correct initial bounds check and unit tests are also needed.
> >
> >> I would vote for inclusion in the base image ?
> >> With your explanation as comments.
> >>
> >> Iâll play with it.
> >>
> >> Thanks
> >> Cedrick
> >>
> >>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
> >>>
> >>> 
> >>> I have coded and benchmarked 8 different running mean algorithms.
> >>> In the presence of inexact numbers it is not as accurate as
> >>> redoing the sums, but it's pretty close, and it's fast.
> >>> If "width" is not an integer or is out of range, an error
> >>> will be reported by #new: or #at:[put:]. It's based on Welford's
> >>> stable update.
> >>>
> >>> Of course this approach does NOT work for trimmed or Winsorised
> >>> means or for medians or any kind of robust estimate of location.
> >>>
> >>> SequenceableCollection
> >>> methods for: 'summarising'
> >>> runningMeans: width
> >>> |a m d|
> >>> a := Array new: self size - width + 1.
> >>> m := 0.
> >>> 1 to: width do: [:i |
> >>> m := (self at: i) + m].
> >>> m := m / width.
> >>> d := 1.
> >>> a at: d put: m.
> >>> width + 1 to: self size do: [:i |
> >>> m := ((self at: i) - (self at: d)) / width + m.
> >>> d := d + 1.
> >>> a at: d put: m].
> >>> ^a
> >>>
> >>>
> >>>
> >>>
> >>>
> >>
> >
> >
>
>
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Cédrick Béler
What about this test (in OrderedCollectionTest - it suggests a Trait too) ?
testRunningMeans
| result col |
col := #(1 1 2 2 3 3) asOrderedCollection.
result := col runningMeans: 2.
self assert: (result = {1. (3/2). 2. (5/2). 3}).
self assert: (result class = Array).
self assert: result size <= (col size). "Running means with 1 has little interest ?"
self should: [ col runningMeans: 7 ] raise: SubscriptOutOfBounds.
self should: [ col runningMeans: -2 ] raise: SubscriptOutOfBounds.
self should: [ col runningMeans: 1.3 ] raise: Error withExceptionDo: [ :anException | self assert: anException messageText equals: 'primitive #basicNew: in Array class failedâ ]
Cheers,
Cédrick
> Le 13 avr. 2020 à 04:47, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>
> I did mention that it was one of eight implementations that I tried.
> In fact you broke it with your change.
> It is important ***NOT*** to keep a running sum but a running MEAN.
> The line
> m := ((self at: i) - (self at: d)) / width + m
> was written that way for a reason.
>
> I did think of renaming the variables for general use, but decided to display
> the actual code that I tested. If you want polished code, here it is.
>
> runningMeans: width
> "This returns an array of running means as if the receiver
> were broken into overlapping segments 'width' long and the
> mean of each calculated. This uses an adaptation of
> Welford's algorithm for stably updating the mean; it is
> important to maintain a current MEAN not a current SUM.
> This has been tested against 7 other algorithms. It was
> the most accurate of the faster ones. The result is an
> Array no matter what kind of sequence the receiver is.
> If the receiver is a tree (like a virtual concatenation)
> or a singly or doubly linked list you should convert the
> receiver to an Array first. Note that there is no
> explicit check that width is an Integer or is in range;
> none is needed because those checks happen anyway."
> |result mean resultIndex|
> result := Array new: self size - width + 1.
> mean := 0.
> 1 to: width do: [:i | mean := (self at: i) + mean].
> mean := mean / width.
> resultIndex := 1.
> result at: resultIndex put: mean.
> width + 1 to: self size do: [:i |
> mean := ((self at: i) - (self at: resultIndex)) / width + mean.
> resultIndex := resultIndex + 1.
> result at: resultIndex put: mean].
> ^result
>
>
>
> On Mon, 13 Apr 2020 at 00:23, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>>
>>
>>
>>> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>>
>>> Beautiful ^^
>>
>> I also like it.
>>
>> But why the single letter variable names ? Why not:
>>
>> SequenceableCollection>>#runningMeans: width
>> | means sum index |
>> means := Array new: self size - width + 1.
>> sum := 0.
>> 1 to: width do: [ :each |
>> sum := sum + (self at: each) ].
>> index := 1.
>> means at: index put: sum / width.
>> width + 1 to: self size do: [ :each |
>> sum := sum - (self at: index) + (self at: each).
>> index := index + 1.
>> means at: index put: sum / width ].
>> ^ means
>>
>> A good comment, a correct initial bounds check and unit tests are also needed.
>>
>>> I would vote for inclusion in the base image ?
>>> With your explanation as comments.
>>>
>>> Iâll play with it.
>>>
>>> Thanks
>>> Cedrick
>>>
>>>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>>>
>>>> 
>>>> I have coded and benchmarked 8 different running mean algorithms.
>>>> In the presence of inexact numbers it is not as accurate as
>>>> redoing the sums, but it's pretty close, and it's fast.
>>>> If "width" is not an integer or is out of range, an error
>>>> will be reported by #new: or #at:[put:]. It's based on Welford's
>>>> stable update.
>>>>
>>>> Of course this approach does NOT work for trimmed or Winsorised
>>>> means or for medians or any kind of robust estimate of location.
>>>>
>>>> SequenceableCollection
>>>> methods for: 'summarising'
>>>> runningMeans: width
>>>> |a m d|
>>>> a := Array new: self size - width + 1.
>>>> m := 0.
>>>> 1 to: width do: [:i |
>>>> m := (self at: i) + m].
>>>> m := m / width.
>>>> d := 1.
>>>> a at: d put: m.
>>>> width + 1 to: self size do: [:i |
>>>> m := ((self at: i) - (self at: d)) / width + m.
>>>> d := d + 1.
>>>> a at: d put: m].
>>>> ^a
>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>
>>
>
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Richard O'Keefe
I did mention that it was one of eight implementations that I tried.
In fact you broke it with your change.
It is important ***NOT*** to keep a running sum but a running MEAN.
The line
m := ((self at: i) - (self at: d)) / width + m
was written that way for a reason.
I did think of renaming the variables for general use, but decided to display
the actual code that I tested. If you want polished code, here it is.
runningMeans: width
"This returns an array of running means as if the receiver
were broken into overlapping segments 'width' long and the
mean of each calculated. This uses an adaptation of
Welford's algorithm for stably updating the mean; it is
important to maintain a current MEAN not a current SUM.
This has been tested against 7 other algorithms. It was
the most accurate of the faster ones. The result is an
Array no matter what kind of sequence the receiver is.
If the receiver is a tree (like a virtual concatenation)
or a singly or doubly linked list you should convert the
receiver to an Array first. Note that there is no
explicit check that width is an Integer or is in range;
none is needed because those checks happen anyway."
|result mean resultIndex|
result := Array new: self size - width + 1.
mean := 0.
1 to: width do: [:i | mean := (self at: i) + mean].
mean := mean / width.
resultIndex := 1.
result at: resultIndex put: mean.
width + 1 to: self size do: [:i |
mean := ((self at: i) - (self at: resultIndex)) / width + mean.
resultIndex := resultIndex + 1.
result at: resultIndex put: mean].
^result
On Mon, 13 Apr 2020 at 00:23, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>
>
> > On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
> >
> > Beautiful ^^
>
> I also like it.
>
> But why the single letter variable names ? Why not:
>
> SequenceableCollection>>#runningMeans: width
> | means sum index |
> means := Array new: self size - width + 1.
> sum := 0.
> 1 to: width do: [ :each |
> sum := sum + (self at: each) ].
> index := 1.
> means at: index put: sum / width.
> width + 1 to: self size do: [ :each |
> sum := sum - (self at: index) + (self at: each).
> index := index + 1.
> means at: index put: sum / width ].
> ^ means
>
> A good comment, a correct initial bounds check and unit tests are also needed.
>
> > I would vote for inclusion in the base image ?
> > With your explanation as comments.
> >
> > Iâll play with it.
> >
> > Thanks
> > Cedrick
> >
> >> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
> >>
> >> 
> >> I have coded and benchmarked 8 different running mean algorithms.
> >> In the presence of inexact numbers it is not as accurate as
> >> redoing the sums, but it's pretty close, and it's fast.
> >> If "width" is not an integer or is out of range, an error
> >> will be reported by #new: or #at:[put:]. It's based on Welford's
> >> stable update.
> >>
> >> Of course this approach does NOT work for trimmed or Winsorised
> >> means or for medians or any kind of robust estimate of location.
> >>
> >> SequenceableCollection
> >> methods for: 'summarising'
> >> runningMeans: width
> >> |a m d|
> >> a := Array new: self size - width + 1.
> >> m := 0.
> >> 1 to: width do: [:i |
> >> m := (self at: i) + m].
> >> m := m / width.
> >> d := 1.
> >> a at: d put: m.
> >> width + 1 to: self size do: [:i |
> >> m := ((self at: i) - (self at: d)) / width + m.
> >> d := d + 1.
> >> a at: d put: m].
> >> ^a
> >>
> >>
> >>
> >>
> >>
> >
>
>
April 13, 2020
Re: [Pharo-users] Moving/rolling average implementations ?
by Cédrick Béler
Fully agree on proper names.
=== I donât know if this is because of free confinement time but I can keep on asking questions so I share some I hope will make sense (for the sake of discussion).
For instance, I'm wondering if tests on conditions so as to raise proper exceptions is a good practice (for instance if the width object does not make sense, like a float) #doesNotMakeSense btw would be a cool name for the « maybe » cases Richard was talking.
Then I asked myself what are the drawbacks (especially on performance) on adding extra information to source code (a bit like longer variable names) ?
There is the raw code and the sources code file that helps separating concerns. At least we donât mind at all having longer literals (variables names, â¦).
I cannot help is what about pragmas. I kind see roughly how they work. But is it possible to distinguish between runtime / source only pragmas (not sure Iâm clear here but it seems to me that some are important for documentation purposes that are not needed at runtime) ?
Also, Iâve never really liked method categories. I donât really see how there are implemented but they donât feel nice to me.
Could they be only pragmas ?
Happy eater Sunday, stay all preserved (sad day for the game of life),
Cédrick
> Le 12 avr. 2020 à 14:22, Sven Van Caekenberghe <sven(a)stfx.eu> a écrit :
>
>
>
>> On 12 Apr 2020, at 13:53, Cédrick Béler <cdrick65(a)gmail.com> wrote:
>>
>> Beautiful ^^
>
> I also like it.
>
> But why the single letter variable names ? Why not:
>
> SequenceableCollection>>#runningMeans: width
> | means sum index |
> means := Array new: self size - width + 1.
> sum := 0.
> 1 to: width do: [ :each |
> sum := sum + (self at: each) ].
> index := 1.
> means at: index put: sum / width.
> width + 1 to: self size do: [ :each |
> sum := sum - (self at: index) + (self at: each).
> index := index + 1.
> means at: index put: sum / width ].
> ^ means
>
> A good comment, a correct initial bounds check and unit tests are also needed.
>
>> I would vote for inclusion in the base image ?
>> With your explanation as comments.
>>
>> Iâll play with it.
>>
>> Thanks
>> Cedrick
>>
>>> Le 12 avr. 2020 à 12:19, Richard O'Keefe <raoknz(a)gmail.com> a écrit :
>>>
>>> 
>>> I have coded and benchmarked 8 different running mean algorithms.
>>> In the presence of inexact numbers it is not as accurate as
>>> redoing the sums, but it's pretty close, and it's fast.
>>> If "width" is not an integer or is out of range, an error
>>> will be reported by #new: or #at:[put:]. It's based on Welford's
>>> stable update.
>>>
>>> Of course this approach does NOT work for trimmed or Winsorised
>>> means or for medians or any kind of robust estimate of location.
>>>
>>> SequenceableCollection
>>> methods for: 'summarising'
>>> runningMeans: width
>>> |a m d|
>>> a := Array new: self size - width + 1.
>>> m := 0.
>>> 1 to: width do: [:i |
>>> m := (self at: i) + m].
>>> m := m / width.
>>> d := 1.
>>> a at: d put: m.
>>> width + 1 to: self size do: [:i |
>>> m := ((self at: i) - (self at: d)) / width + m.
>>> d := d + 1.
>>> a at: d put: m].
>>> ^a
>>>
>>>
>>>
>>>
>>>
>>
>
>
April 12, 2020