[squeak-dev] The Inbox: Collections-nice.825.mcz

Fabio Niephaus lists at fniephaus.com
Wed Sep 11 17:39:49 UTC 2019


On Sun, Apr 7, 2019 at 11:10 PM <commits at source.squeak.org> wrote:
>
> Nicolas Cellier uploaded a new version of Collections to project The Inbox:
> http://source.squeak.org/inbox/Collections-nice.825.mcz
>
> ==================== Summary ====================
>
> Name: Collections-nice.825
> Author: nice
> Time: 7 April 2019, 11:10:11.564693 pm
> UUID: c9836c60-9acc-45eb-83b2-851f147b70ca
> Ancestors: Collections-nice.824
>
> Try to improve some Interval of Float Behavior.
>
> - change #last so that it agrees with (self at: self size)
>  Note that last behavior slightly changes for empty Interval: (3 to: 0) last is now 2 instead of 0 previously. I don't know of any code impacted, but it's not a completely neutral change
>
> Note: this solves 2 out of the 3 failures of #testIntervalOfFloatLast... The last element might still overshoot the prescribed upper bound. I can also fix it, but implementation of #last is getting overkill.
>
> - implement a ReversedInterval that lazily reverse an Interval of Float, and resolves #testIntervalOfFloatReversed.
>
> The alternative would be resorting to an Array...
>
> - renounce fuzzy inclusion test. As exhibited by #testSurprisingFuzzyInclusionBehavior, it creates more weirdness than it tries to solve. There will be two more test failing, asserting this fuzzy inclusion, but we can later change them.
>
> =============== Diff against Collections-nice.824 ===============
>
> Item was changed:
>   ----- Method: Interval>>indexOf:startingAt: (in category 'accessing') -----
>   indexOf: anElement startingAt: startIndex
>         "startIndex is an positive integer, the collection index where the search is started."
> -       "during the computation of val , floats are only used when the receiver contains floats"
>
> +       | index |
> -       | index val |
>         (self rangeIncludes: anElement) ifFalse: [ ^0 ].
> +       index := (anElement - start / step) rounded + 1.
> -       val := anElement - self first / self increment.
> -       val isFloat
> -               ifTrue: [
> -                       (val - val rounded) abs * 100000000 < 1 ifFalse: [ ^0 ].
> -                       index := val rounded + 1 ]
> -               ifFalse: [
> -                       val isInteger ifFalse: [ ^0 ].
> -                       index := val + 1 ].
> -       "finally, the value of startIndex comes into play:"
>         (index between: startIndex and: self size) ifFalse: [ ^0 ].
> +       (self at: index) = anElement ifFalse: [ ^0 ].
>         ^index!
>
> Item was changed:
>   ----- Method: Interval>>last (in category 'accessing') -----
>   last
>         "Refer to the comment in SequenceableCollection|last."
>
> +       ^start + (step * (self size - 1))!
> -       ^stop - (stop - start \\ step)!
>
> Item was changed:
>   ----- Method: Interval>>reversed (in category 'converting') -----
>   reversed
>         self isEmpty ifTrue: [^stop to: start by: step negated].
> +       (start isFraction and: [step isFraction]) ifFalse: [^ReversedInterval newFrom: self].
>         ^self last to: start by: step negated!
>
> Item was added:
> + SequenceableCollection subclass: #ReversedInterval
> +       instanceVariableNames: 'original'
> +       classVariableNames: ''
> +       poolDictionaries: ''
> +       category: 'Collections-Sequenceable'!
> +
> + !ReversedInterval commentStamp: 'nice 4/6/2019 16:30' prior: 0!
> + A ReversedInterval is an Interval reversed.
> + An Interval reversed is generally an Interval, except when made of Float.
> + This is because Float arithmetic does not guarantee reversible operations.
> +
> + Instead of transforming the reversed Float Interval into an Array, I keep a lazier and cheaper representation.
> + I can even pretend being an Interval myself. As long as I quake like a duck...
> +
> + Instance Variables
> +       original:               <Interval>
> +
> + original
> +       - the Interval being reversed
> + !
>
> Item was added:
> + ----- Method: ReversedInterval class>>newFrom: (in category 'as yet unclassified') -----
> + newFrom: aCollection
> +       "Answer an instance of me containing the same elements as aCollection, reversed."
> +
> +       aCollection isInterval ifTrue: [^self basicNew setOriginal: aCollection].
> +       ^(Interval newFrom: aCollection) reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>+ (in category 'arithmetic') -----
> + + aNumber
> +       ^(original + aNumber) reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>- (in category 'arithmetic') -----
> + - aNumber
> +       ^(original - aNumber) reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>= (in category 'comparing') -----
> + = anObject
> +       ^ self == anObject
> +               or: [anObject class = self class
> +                       and: [original = anObject reversed]]!
>
> Item was added:
> + ----- Method: ReversedInterval>>at: (in category 'accessing') -----
> + at: anInteger
> +       ^original at: original size + 1 - anInteger!
>
> Item was added:
> + ----- Method: ReversedInterval>>copyFrom:to: (in category 'copying') -----
> + copyFrom: startIndex to: stopIndex
> +       (startIndex = 1 and: [stopIndex = self size]) ifTrue: [^self].
> +       stopIndex < startIndex ifTrue: [^self copyEmpty].
> +       ^((self at: stopIndex) to: (self at: startIndex) by: original increment) reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>do: (in category 'enumerating') -----
> + do: aBlock
> +       original reverseDo: aBlock!
>
> Item was added:
> + ----- Method: ReversedInterval>>hash (in category 'comparing') -----
> + hash
> +       ^original hash bitXor: SmallInteger maxVal!
>
> Item was added:
> + ----- Method: ReversedInterval>>isEmpty (in category 'testing') -----
> + isEmpty
> +       ^self size = 0!
>
> Item was added:
> + ----- Method: ReversedInterval>>printOn: (in category 'printing') -----
> + printOn: aStream
> +       aStream
> +               nextPut: $(;
> +               print: original;
> +               nextPut: $);
> +               space;
> +               nextPutAll: #reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>reverseDo: (in category 'enumerating') -----
> + reverseDo: aBlock
> +       original do: aBlock!
>
> Item was added:
> + ----- Method: ReversedInterval>>reversed (in category 'converting') -----
> + reversed
> +       ^original!
>
> Item was added:
> + ----- Method: ReversedInterval>>setOriginal: (in category 'private') -----
> + setOriginal: anInterval
> +       original := anInterval!
>
> Item was added:
> + ----- Method: ReversedInterval>>size (in category 'accessing') -----
> + size
> +       ^original size!
>
> Item was added:
> + ----- Method: ReversedInterval>>sorted (in category 'sorting') -----
> + sorted
> +       original increment > 0 ifTrue: [^original].
> +       ^self!
>
> Item was added:
> + ----- Method: ReversedInterval>>species (in category 'private') -----
> + species
> +
> +       ^original species!
>
> Item was added:
> + ----- Method: ReversedInterval>>storeOn: (in category 'printing') -----
> + storeOn: aStream
> +       aStream
> +               nextPut: $(;
> +               store: original;
> +               nextPut: $);
> +               space;
> +               nextPutAll: #reversed!
>
> Item was added:
> + ----- Method: ReversedInterval>>sum (in category 'accessing') -----
> + sum
> +       ^original sum!
>
>

"An Interval reversed is generally an Interval, except when made of Float."
Should ReversedInterval be renamed to ReversedFloatInterval then?

Nonetheless, this seems to fix #testIntervalOfFloatLast and
#testIntervalOfFloatReversed of IntervalTest. Do we want to integrate
this proposal or shall we mark these two tests as expected failures?

Fabio


More information about the Squeak-dev mailing list