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