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

Frank Shearar frank.shearar at gmail.com
Mon Sep 22 20:38:20 UTC 2014


On 22 September 2014 20:10, Chris Muller <asqueaker at gmail.com> wrote:
> On Mon, Sep 22, 2014 at 12:10 PM, Nicolas Cellier
> <nicolas.cellier.aka.nice at gmail.com> wrote:
>>
>>
>> 2014-09-22 17:51 GMT+02:00 David T. Lewis <lewis at mail.msen.com>:
>>>
>>> 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
>>>
>>
>> Sorry  for the late reply.
>> 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.
>> I have sent private e-mail to Travis 2 days ago, but haven't received an
>> answer yet.
>> I don't know him personnally, so I would welcome any one having a more
>> direct channel to contact him.
>> Without a clear answer we'll have to retract these commits.
>>
>> Unless you prefer a preventive retractation right now?
>
> Travis hasn't been involved with Smalltalk for over 2 years now
>
>   http://objology.blogspot.com/2012/05/stepping-out-of-balloon.html
>
> so its very possible you'll get no reply.
>
> Note that Cincom reprinted his blog post under their own domain,
> including the part that encourages to "port it to your own flavor of
> Smalltalk".
>
>    http://www.cincomsmalltalk.com/main/2010/12/tag-sortfunctions/
>
> If they would object to this being ported, why would they reprint it
> and not "clarify" that point?
>
> To me, it seems clear that this was meant for adoption by the
> Smalltalk community at large.  It would be a shame to subvert that by
> some (mis)perceived legal technicality.  We are not lawyers, but in
> case we get no reply, if we're that concerned about a lawsuit (waged
> by Cincom?), the SFC does have a legal resource whom we could ask to
> evaluate it.

"Port" means "translate into your Smalltalk". It does not have
anything at all to do with licences. I didn't see Travis saying "this
is public domain", I didn't see a licence declaration, so... what?
Hopefully Travis will come back and say "hey, you know, I'm a
signed-up contributor to Squeak, why are you even asking?" and then we
can all be happy.

Until then, we _do not know_. 'It was ported from a "public
repository" into trunk.  Everything posted to trunk is MIT.' is not an
argument. And the second statement's not even true. Us saying "you
submitted it, therefore it's MIT" is bogus. The submitter needs to
have signed the contributor agreement, _and have the right_ to sign
such an agreement. Your work contract might not permit you to do such
a thing.

And I'm not suggesting ripping anything out. Let's wait for Travis to
respond. Hopefully someone has a more direct line to him, given that
Nicolas has waited two days already.

But this is a very real problem.

frank

>> Nicolas
>>
>>
>>> > 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