[squeak-dev] The Trunk: Collections-nice.582.mcz

David T. Lewis lewis at mail.msen.com
Mon Sep 22 15:51:55 UTC 2014


We need positive confirmation that the code derived from that public
repository was licensed MIT, or a statement from the original author that
is now being released under MIT. I'm sure that the original author will be
happy to do that, but we do need a clear statement of license before we
can allow the code to be added to trunk.

Dave

> It was ported from a "public repository" into trunk.  Everything
> posted to trunk is MIT.
>
>
> On Mon, Sep 22, 2014 at 3:26 AM, Frank Shearar <frank.shearar at gmail.com>
> wrote:
>> Yes, it looks very very nice.
>>
>> What's its licence again?
>>
>> frank
>>
>> On 21 September 2014 22:46, Chris Muller <asqueaker at gmail.com> wrote:
>>> What a *gorgeous* solution to multi-level sorting!  I love this!!
>>>
>>> Now I need to update some of my images to latest trunk just so I can
>>> get this..
>>>
>>> On Fri, Sep 19, 2014 at 3:24 PM,  <commits at source.squeak.org> wrote:
>>>> Nicolas Cellier uploaded a new version of Collections to project The
>>>> Trunk:
>>>> http://source.squeak.org/trunk/Collections-nice.582.mcz
>>>>
>>>> ==================== Summary ====================
>>>>
>>>> Name: Collections-nice.582
>>>> Author: nice
>>>> Time: 19 September 2014, 10:22:13.338 pm
>>>> UUID: 52a598f1-224e-4649-a95f-4e78547b5ed5
>>>> Ancestors: Collections-nice.581
>>>>
>>>> Port TAG-SortFunctions of Travis Griggs from Cincom public store -
>>>> version (11,tgriggs)
>>>>
>>>> Note that no collation policy were used for String.
>>>> The spaceship operator <=> is also required in Kernel-Numbers.
>>>>
>>>> See also the blog
>>>> http://objology.blogspot.fr/2010/11/tag-sortfunctions.html
>>>>  and http://objology.blogspot.fr/2010/11/tag-sortfunctions-redux.html
>>>>
>>>> Note about the cost of these sort functions:
>>>> as shown by this mini-bench on cog, using a Symbol costs a bit more
>>>> (perform:) than a block activation, and monadic block a bit more than
>>>> dyadic one because activated twice more, but it seems acceptable to me
>>>> with regard to the great simplification and expressiveness of code :
>>>>
>>>> | collec1 collec2 collec3 |
>>>> collec1 := (1 to: 200000) collect: [:i | 1000000 atRandom-500000].
>>>> collec2 := collec1 copy.
>>>> collec3 := collec1 copy.
>>>> {
>>>> [collec1 sort: [:a :b | a abs < b abs]] timeToRun.
>>>> [collec2 sort: [:e | e abs] ascending] timeToRun.
>>>> [collec3 sort: #abs ascending] timeToRun.
>>>> }
>>>>  #(345 532 912)
>>>>
>>>> =============== Diff against Collections-nice.581 ===============
>>>>
>>>> Item was added:
>>>> + SortFunction subclass: #ChainedSortFunction
>>>> +       instanceVariableNames: 'next'
>>>> +       classVariableNames: ''
>>>> +       poolDictionaries: ''
>>>> +       category: 'Collections-Support'!
>>>> +
>>>> + !ChainedSortFunction commentStamp: 'nice 3/13/2014 22:25' prior: 0!
>>>> + I add to my parent the idea of a "next" function to use when two
>>>> objects are equal by my particular collator.
>>>> +
>>>> + Usage
>>>> +
>>>> + SortFunctions can be chained together in primary, secondary,
>>>> tertiary, etc order using the comma method. Consider a sequence of
>>>> customer objects, where each customer object responds to the messages
>>>> firstName, lastName, and age. If we want to sort them lastName first,
>>>> then firstName, and finally oldest first, we would use an expression
>>>> like:
>>>> +
>>>> + customers sort: #lastName ascending, #firstName ascending, #age
>>>> descending
>>>> +
>>>> + As noted in my super's comment, unary symbols or single arg blocks
>>>> can be used. One can omit the the ascending methods on arguments (not
>>>> the receiver), it will default blocks or symbols to be ascending if
>>>> none is specified. In other words, the above expression could be
>>>> simplified slightly as
>>>> +
>>>> + customers sort: #lastName ascending, #firstName, #age descending
>>>> +
>>>> + (note the missing ascending on the #firstName argument)
>>>> +
>>>> + Instance Variables
>>>> +       next    <SortFunction>  the next SortFunction to evaluate in
>>>> the event my evaluator results in equal values.
>>>> +
>>>> + !
>>>>
>>>> Item was added:
>>>> + ----- Method: ChainedSortFunction>>, (in category 'converting')
>>>> -----
>>>> + , aSortFunction
>>>> +
>>>> +       self next: next , aSortFunction!
>>>>
>>>> Item was added:
>>>> + ----- Method: ChainedSortFunction>>next: (in category
>>>> 'initialize-release') -----
>>>> + next: anObject
>>>> +
>>>> +       next := anObject!
>>>>
>>>> Item was added:
>>>> + ----- Method: ChainedSortFunction>>value:value: (in category
>>>> 'evaluating') -----
>>>> + value: anObject value: bObject
>>>> +       "Refinement of the parent behavior. If the result of my
>>>> collator is 0, then pass on to the next variable to work it out."
>>>> +
>>>> +       | result |
>>>> +       result := (collator value: anObject value: bObject) *
>>>> direction.
>>>> +       ^result isZero
>>>> +               ifTrue: [next value: anObject value: bObject]
>>>> +               ifFalse: [result < 0]!
>>>>
>>>> Item was added:
>>>> + Object subclass: #SortFunction
>>>> +       instanceVariableNames: 'direction collator'
>>>> +       classVariableNames: ''
>>>> +       poolDictionaries: ''
>>>> +       category: 'Collections-Support'!
>>>> +
>>>> + !SortFunction commentStamp: 'nice 3/13/2014 22:24' prior: 0!
>>>> + I am intended to be used in place of two arg sort blocks.
>>>> +
>>>> + Usage
>>>> +
>>>> + In the following example, an ascending SortFunction is created based
>>>> on the result of the #first message send to each object.
>>>> + #(#(1 2) #(2 3) #(0 0)) sorted: #first ascending.
>>>> +
>>>> + To sort by the #last element, but descending, the following would be
>>>> used:
>>>> + #(#(1 2) #(2 3) #(0 0)) sorted: #last descending.
>>>> +
>>>> + One can use blocks as well. The following sorts in descending order,
>>>> the sub elements based on the sum of their values.
>>>> + | sumBlock |
>>>> + sumBlock := [:sequence | sequence inject: 0 into: [:sum :each | sum
>>>> + each]].
>>>> + #(#(1 2) #(2 3) #(0 0)) sorted: sumBlock descending.
>>>> +
>>>> + One can even use 2 arg blocks, for those cases where the function
>>>> isn't expressible with objects that respond to < and =. The only
>>>> catch, is that such a function has to return not true and false, but
>>>> instead a collation order, values of -1 (for before), 0 (the same) or
>>>> 1 (to follow). For example:
>>>> +
>>>> + | oddBlock |
>>>> + oddBlock :=
>>>> +               [:a :b |
>>>> +               a odd = b odd ifTrue: [0] ifFalse: [a odd ifTrue: [-1]
>>>> ifFalse: [1]]].
>>>> + #(1 5 1 3 2 7 9 4 6) asSortedCollection: oddBlock descending
>>>> +
>>>> + Instance Variables
>>>> +       collator        <BlockClosure>  This is the collation function
>>>> that must return a -1, 0, or 1. It is usually composed by an
>>>> initialization method such as sendMessage: or monadicBlock:, but may
>>>> be set directly.
>>>> +       direction       <SmallInteger>  1 for ascending, -1 for
>>>> descending
>>>> +
>>>> + !
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction class>>ascend (in category 'instance
>>>> creation') -----
>>>> + ascend
>>>> +
>>>> +       ^self new ascend!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction class>>descend (in category 'instance
>>>> creation') -----
>>>> + descend
>>>> +
>>>> +       ^self new descend!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>, (in category 'converting') -----
>>>> + , aSortFunction
>>>> +       "Return a new SortFunction which is the concatenation of
>>>> aSortFunction to me, I will be the primary sort, but if I compare
>>>> equal, I will defer to the argument."
>>>> +
>>>> +       ^(ChainedSortFunction new)
>>>> +               collator: collator;
>>>> +               direction: direction;
>>>> +               next: aSortFunction asSortFunction!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>asSortFunction (in category
>>>> 'converting') -----
>>>> + asSortFunction
>>>> +
>>>> +       ^self!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>ascend (in category
>>>> 'initailize-release') -----
>>>> + ascend
>>>> +
>>>> +       direction := 1!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>collator: (in category
>>>> 'initailize-release') -----
>>>> + collator: a2ArgBlock
>>>> +       "a2ArgBlock MUST return the collation order, -1, 0, or 1"
>>>> +
>>>> +       collator := a2ArgBlock!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>descend (in category
>>>> 'initailize-release') -----
>>>> + descend
>>>> +
>>>> +       direction := -1!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>direction: (in category
>>>> 'initailize-release') -----
>>>> + direction: anInteger
>>>> +
>>>> +       direction := anInteger!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>isAscending (in category 'testing')
>>>> -----
>>>> + isAscending
>>>> +
>>>> +       ^direction = 1!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>isDescending (in category 'testing')
>>>> -----
>>>> + isDescending
>>>> +
>>>> +       ^direction = -1!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>monadicBlock: (in category
>>>> 'initailize-release') -----
>>>> + monadicBlock: aSingleArgBlock
>>>> +       "Initialze the receiver's collation block to compare the
>>>> results of evaluating aSingleArgBlock with each argument, and then
>>>> collate the return values with the <=> method."
>>>> +
>>>> +       collator := [:a :b | (aSingleArgBlock value: a) <=>
>>>> (aSingleArgBlock value: b)]!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>sendMessage: (in category
>>>> 'initailize-release') -----
>>>> + sendMessage: aUnarySymbol
>>>> +       "Initialze the receiver's collation block to compare the
>>>> results of sending aUnarySymbol to each argument, and then collate
>>>> them with the <=> method."
>>>> +
>>>> +       collator := [:a :b | (a perform: aUnarySymbol) <=> (b perform:
>>>> aUnarySymbol)]!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>toggleDirection (in category
>>>> 'converting') -----
>>>> + toggleDirection
>>>> +       "Invert my current direction, if I'm currently ascending, this
>>>> will cause me to be descending now, and vice-versa."
>>>> +
>>>> +       direction := direction * -1!
>>>>
>>>> Item was added:
>>>> + ----- Method: SortFunction>>value:value: (in category 'evaluating')
>>>> -----
>>>> + value: anObject value: bObject
>>>> +       "Masquerade as a two argument block, used by many of the
>>>> sorting APIs, by returning whether anObject should be placed before
>>>> bObject or not."
>>>> +
>>>> +       | result |
>>>> +       result := (collator value: anObject value: bObject) *
>>>> direction.
>>>> +       ^result <= 0!
>>>>
>>>> Item was added:
>>>> + ----- Method: String>><=> (in category 'sorting') -----
>>>> + <=> aCharacterArray
>>>> +       "Return a collation order of -1, 0, or 1, indicating whether I
>>>> should be collated before the receiver, am equal, or after.
>>>> +       See also:  http://en.wikipedia.org/wiki/Spaceship_operator"
>>>> +
>>>> +       ^self = aCharacterArray
>>>> +               ifTrue: [ 0 ]
>>>> +               ifFalse: [self < aCharacterArray
>>>> +                       ifTrue: [ -1 ]
>>>> +                       ifFalse: [ 1 ]]!
>>>>
>>>> Item was added:
>>>> + ----- Method: Symbol>>asSortFunction (in category 'sorting') -----
>>>> + asSortFunction
>>>> +
>>>> +       ^self ascending!
>>>>
>>>> Item was added:
>>>> + ----- Method: Symbol>>ascending (in category 'sorting') -----
>>>> + ascending
>>>> +       "Return a SortFunction around the receiver, where the receiver
>>>> will be used as a unary message to send to both a and b during
>>>> sorting, and then the result of said send will be collated in
>>>> ascending order using the <=> method."
>>>> +       "Example: #('abc'  'de' 'fghi') sorted: #size asscending"
>>>> +
>>>> +       ^SortFunction ascend sendMessage: self!
>>>>
>>>> Item was added:
>>>> + ----- Method: Symbol>>descending (in category 'sorting') -----
>>>> + descending
>>>> +       "Return a SortFunction around the receiver, where the receiver
>>>> will be used as a unary message to send to both a and b during
>>>> sorting, and then the result of said send will be collated in
>>>> descending order using the <=> method."
>>>> +       "Example: #('abc'  'de' 'fghi') sorted: #size descending"
>>>> +
>>>> +       ^SortFunction descend sendMessage: self!
>>>>
>>>> Item was added:
>>>> + ----- Method: Text>><=> (in category 'sorting') -----
>>>> + <=> aCharacterArray
>>>> +       "Return a collation order of -1, 0, or 1, indicating whether I
>>>> should be collated before the receiver, am equal, or after.
>>>> +       See also:  http://en.wikipedia.org/wiki/Spaceship_operator"
>>>> +
>>>> +       ^string = aCharacterArray
>>>> +               ifTrue: [ 0 ]
>>>> +               ifFalse: [string < aCharacterArray asString
>>>> +                       ifTrue: [ -1 ]
>>>> +                       ifFalse: [ 1 ]]!
>>>>
>>>>
>>>
>>
>




More information about the Squeak-dev mailing list