about SortFunctions

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
52 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Thierry Goubier


2017-11-07 13:47 GMT+01:00 Denis Kudriashov <[hidden email]>:
2017-11-07 13:11 GMT+01:00 Thierry Goubier <[hidden email]>:

Now, if you explained me something like that:

people nilFirst ascending

Then I'd be more convinced. Or even

people sorted nilFirst ascending (if one would prefer restricting the implementations of #nilFirst).

I think we can easily support it. But of course it will work only for objects which understand #threeWayCompareTo:. Now it looks like
#(one nil two) sorted: #yourself ascending undefinedFirst.
And I prefer this version instead of extending collection with new sorting messages.

My position is that we have few messages (which are not business logic related) for sorting, so they could easily extend collection (and #yourself here is just noise). Now, you want to keep that mix of business logic + ordering, hence the syntax you're choosing.

Thierry

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Thierry Goubier
2017-11-07 13:50 GMT+01:00 Thierry Goubier <[hidden email]>:

10 years ago now, we designed a DSL above our parallel language, with the same kind of tradeoffs you described there. We ended up discarding it, because we had to maintain the full procedural code for the cases we couldn't cover. Discarding it was a wise decision.

That's why SortFunction is now abstract class. If you want some complex logic you are able to create custom function class which will incapsulate it and make it reusable. 

Then we agree: a good choice is having a proper place (sort function object, a method in simple cases) to implement that business logic if it is not obvious.
 
I already mentioned possible SortMethodFunction. It takes care about binary method order which should be always on top of ascending list. It would be ugly to implement it in block or with composition of selectors. And I don't think that method should define #>

On a short analysis, I could give you half a dozen valid orderings for SortMethodFunction... You've chosen one, put it as the master one, and gave it a general name 'Ordering of Methods'. You could have written it as #>, the way you're doing it.

Sorry Thierry that it is not obvious: given name is an example. Of course it is better to have explicit name.
 

Regards,

Thierry
 
  

Now, if you explained me something like that:

people nilFirst ascending

Then I'd be more convinced. Or even

people sorted nilFirst ascending (if one would prefer restricting the implementations of #nilFirst).

Could the symbol use be a smell of not putting the right responsabilities into the People class?

Thierry
 
               
     




Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Nicolas Cellier
I have new question. Why we really need threeWayCompareTo:?
DefaultSortFunction can implement it using standard comparison methods.

2017-11-05 0:37 GMT+01:00 Nicolas Cellier <[hidden email]>:
Hi all,
I started a discussion with Denis in a pull request
But since it's going beyond simple code review, it probably has a better place here.

First, I want to say thanks for enriching this original work of Travis Griggs.
http://objology.blogspot.fr/2010/11/tag-sortfunctions-redux.html
Of course, I'm never satisfied.
So I don't really appreciate the rewrite of space ship operator <=> into a more heavy threeWayCompareTo:

In my eyes, it's so obvious that <=> means < or = or > in the context of SortFunction
And also that the order matches the signs
< = >
-1 0 1
IOW result will be -1 if receiver is <, 0 if equal, +1 if superior

#threeWayCompareTo: does not tell as well.
But maybe It's a question of taste and I don't have the same eyes as Pharo people?
To me it's also a question of respect to the original author, don't change a good selector for the sake of changing.

Apart this detail, I wanted to speak about SortByPropertyFunction.
SortByProperty is super usefull for composing / chaining like this:

    population sortBy: #name ascending , #age descending.

But currently, SortByPropertyFunction is allways using the default hardcoded collation <=> ... He he, it's also notice it's shorter to write ;)

Imagine that my properties are neither String nor Magnitude, or they are, but I want a different collation policy, because in French $é must not be sorted too far from $e.

It could be written quite simply with:

   c sortBy: #name collatedInFrench ascending , #age descending

With current implementation, collatedInFrench would have to use a block (thru a CollatorBlockFunction which is a proxy to the block in a SortFunction disguise):

    Symbol>>collatedInFrench
        "interpret self as a property"
        ^[:a :b | FrenchCollator collate: (self value: a) with: (self value: b)]

But IMO SortByPropertyFunction should better feed a reified CollatorFunction, or said differently a SortFunction, as Denis said.

    Symbol>>collatedInFrench
        ^FrenchCollator new onProperty: self

    SortFunction>>onProperty: aValuable
        ^SortByPropertyFunction sortProperty: aValuable with: self

What do you think?

Nicolas


Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Thierry Goubier
In reply to this post by Denis Kudriashov


2017-11-07 13:59 GMT+01:00 Denis Kudriashov <[hidden email]>:
2017-11-07 13:50 GMT+01:00 Thierry Goubier <[hidden email]>:

10 years ago now, we designed a DSL above our parallel language, with the same kind of tradeoffs you described there. We ended up discarding it, because we had to maintain the full procedural code for the cases we couldn't cover. Discarding it was a wise decision.

That's why SortFunction is now abstract class. If you want some complex logic you are able to create custom function class which will incapsulate it and make it reusable. 

Then we agree: a good choice is having a proper place (sort function object, a method in simple cases) to implement that business logic if it is not obvious.
 
I already mentioned possible SortMethodFunction. It takes care about binary method order which should be always on top of ascending list. It would be ugly to implement it in block or with composition of selectors. And I don't think that method should define #>

On a short analysis, I could give you half a dozen valid orderings for SortMethodFunction... You've chosen one, put it as the master one, and gave it a general name 'Ordering of Methods'. You could have written it as #>, the way you're doing it.

Sorry Thierry that it is not obvious: given name is an example. Of course it is better to have explicit name.

Understood :)

Thierry
 
 

Regards,

Thierry
 
  

Now, if you explained me something like that:

people nilFirst ascending

Then I'd be more convinced. Or even

people sorted nilFirst ascending (if one would prefer restricting the implementations of #nilFirst).

Could the symbol use be a smell of not putting the right responsabilities into the People class?

Thierry
 
               
     





Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier
In reply to this post by Denis Kudriashov


2017-11-07 14:20 GMT+01:00 Denis Kudriashov <[hidden email]>:
I have new question. Why we really need threeWayCompareTo:?
DefaultSortFunction can implement it using standard comparison methods.


But what would the DefaultSortFunction use?
2 among the 3 selectors < = > ?
It's just that we might scan String twice when <=> would do it once, but apart that is OK


2017-11-05 0:37 GMT+01:00 Nicolas Cellier <[hidden email]>:
Hi all,
I started a discussion with Denis in a pull request
But since it's going beyond simple code review, it probably has a better place here.

First, I want to say thanks for enriching this original work of Travis Griggs.
http://objology.blogspot.fr/2010/11/tag-sortfunctions-redux.html
Of course, I'm never satisfied.
So I don't really appreciate the rewrite of space ship operator <=> into a more heavy threeWayCompareTo:

In my eyes, it's so obvious that <=> means < or = or > in the context of SortFunction
And also that the order matches the signs
< = >
-1 0 1
IOW result will be -1 if receiver is <, 0 if equal, +1 if superior

#threeWayCompareTo: does not tell as well.
But maybe It's a question of taste and I don't have the same eyes as Pharo people?
To me it's also a question of respect to the original author, don't change a good selector for the sake of changing.

Apart this detail, I wanted to speak about SortByPropertyFunction.
SortByProperty is super usefull for composing / chaining like this:

    population sortBy: #name ascending , #age descending.

But currently, SortByPropertyFunction is allways using the default hardcoded collation <=> ... He he, it's also notice it's shorter to write ;)

Imagine that my properties are neither String nor Magnitude, or they are, but I want a different collation policy, because in French $é must not be sorted too far from $e.

It could be written quite simply with:

   c sortBy: #name collatedInFrench ascending , #age descending

With current implementation, collatedInFrench would have to use a block (thru a CollatorBlockFunction which is a proxy to the block in a SortFunction disguise):

    Symbol>>collatedInFrench
        "interpret self as a property"
        ^[:a :b | FrenchCollator collate: (self value: a) with: (self value: b)]

But IMO SortByPropertyFunction should better feed a reified CollatorFunction, or said differently a SortFunction, as Denis said.

    Symbol>>collatedInFrench
        ^FrenchCollator new onProperty: self

    SortFunction>>onProperty: aValuable
        ^SortByPropertyFunction sortProperty: aValuable with: self

What do you think?

Nicolas



Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
2017-11-07 14:40 GMT+01:00 Nicolas Cellier <[hidden email]>:


2017-11-07 14:20 GMT+01:00 Denis Kudriashov <[hidden email]>:
I have new question. Why we really need threeWayCompareTo:?
DefaultSortFunction can implement it using standard comparison methods.


But what would the DefaultSortFunction use?
2 among the 3 selectors < = > ?
It's just that we might scan String twice when <=> would do it once, but apart that is OK

Yes, you are right.
And we already have VM based String compare: with strange logic returning 1, 2, 3. So we already can optimize current String>>threeWayCompareTo:.
 


2017-11-05 0:37 GMT+01:00 Nicolas Cellier <[hidden email]>:
Hi all,
I started a discussion with Denis in a pull request
But since it's going beyond simple code review, it probably has a better place here.

First, I want to say thanks for enriching this original work of Travis Griggs.
http://objology.blogspot.fr/2010/11/tag-sortfunctions-redux.html
Of course, I'm never satisfied.
So I don't really appreciate the rewrite of space ship operator <=> into a more heavy threeWayCompareTo:

In my eyes, it's so obvious that <=> means < or = or > in the context of SortFunction
And also that the order matches the signs
< = >
-1 0 1
IOW result will be -1 if receiver is <, 0 if equal, +1 if superior

#threeWayCompareTo: does not tell as well.
But maybe It's a question of taste and I don't have the same eyes as Pharo people?
To me it's also a question of respect to the original author, don't change a good selector for the sake of changing.

Apart this detail, I wanted to speak about SortByPropertyFunction.
SortByProperty is super usefull for composing / chaining like this:

    population sortBy: #name ascending , #age descending.

But currently, SortByPropertyFunction is allways using the default hardcoded collation <=> ... He he, it's also notice it's shorter to write ;)

Imagine that my properties are neither String nor Magnitude, or they are, but I want a different collation policy, because in French $é must not be sorted too far from $e.

It could be written quite simply with:

   c sortBy: #name collatedInFrench ascending , #age descending

With current implementation, collatedInFrench would have to use a block (thru a CollatorBlockFunction which is a proxy to the block in a SortFunction disguise):

    Symbol>>collatedInFrench
        "interpret self as a property"
        ^[:a :b | FrenchCollator collate: (self value: a) with: (self value: b)]

But IMO SortByPropertyFunction should better feed a reified CollatorFunction, or said differently a SortFunction, as Denis said.

    Symbol>>collatedInFrench
        ^FrenchCollator new onProperty: self

    SortFunction>>onProperty: aValuable
        ^SortByPropertyFunction sortProperty: aValuable with: self

What do you think?

Nicolas




Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
2017-11-07 14:45 GMT+01:00 Denis Kudriashov <[hidden email]>:
2017-11-07 14:40 GMT+01:00 Nicolas Cellier <[hidden email]>:


2017-11-07 14:20 GMT+01:00 Denis Kudriashov <[hidden email]>:
I have new question. Why we really need threeWayCompareTo:?
DefaultSortFunction can implement it using standard comparison methods.


But what would the DefaultSortFunction use?
2 among the 3 selectors < = > ?
It's just that we might scan String twice when <=> would do it once, but apart that is OK

Yes, you are right.
And we already have VM based String compare: with strange logic returning 1, 2, 3. So we already can optimize current String>>threeWayCompareTo:.

Maybe good idea to open ticket and modify image level methods to return standard -1,0,1 values.
 
 


2017-11-05 0:37 GMT+01:00 Nicolas Cellier <[hidden email]>:
Hi all,
I started a discussion with Denis in a pull request
But since it's going beyond simple code review, it probably has a better place here.

First, I want to say thanks for enriching this original work of Travis Griggs.
http://objology.blogspot.fr/2010/11/tag-sortfunctions-redux.html
Of course, I'm never satisfied.
So I don't really appreciate the rewrite of space ship operator <=> into a more heavy threeWayCompareTo:

In my eyes, it's so obvious that <=> means < or = or > in the context of SortFunction
And also that the order matches the signs
< = >
-1 0 1
IOW result will be -1 if receiver is <, 0 if equal, +1 if superior

#threeWayCompareTo: does not tell as well.
But maybe It's a question of taste and I don't have the same eyes as Pharo people?
To me it's also a question of respect to the original author, don't change a good selector for the sake of changing.

Apart this detail, I wanted to speak about SortByPropertyFunction.
SortByProperty is super usefull for composing / chaining like this:

    population sortBy: #name ascending , #age descending.

But currently, SortByPropertyFunction is allways using the default hardcoded collation <=> ... He he, it's also notice it's shorter to write ;)

Imagine that my properties are neither String nor Magnitude, or they are, but I want a different collation policy, because in French $é must not be sorted too far from $e.

It could be written quite simply with:

   c sortBy: #name collatedInFrench ascending , #age descending

With current implementation, collatedInFrench would have to use a block (thru a CollatorBlockFunction which is a proxy to the block in a SortFunction disguise):

    Symbol>>collatedInFrench
        "interpret self as a property"
        ^[:a :b | FrenchCollator collate: (self value: a) with: (self value: b)]

But IMO SortByPropertyFunction should better feed a reified CollatorFunction, or said differently a SortFunction, as Denis said.

    Symbol>>collatedInFrench
        ^FrenchCollator new onProperty: self

    SortFunction>>onProperty: aValuable
        ^SortByPropertyFunction sortProperty: aValuable with: self

What do you think?

Nicolas





Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

tblanchard
In reply to this post by Ben Coman
Which is weird because I think the magic is its decentralized nature.

On Nov 6, 2017, at 1:52 PM, Ben Coman <[hidden email]> wrote:

Some would say it was github that "made" git (popular). 

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Damien Pollet
In reply to this post by Denis Kudriashov


On 7 November 2017 at 14:48, Denis Kudriashov <[hidden email]> wrote:
And we already have VM based String compare: with strange logic returning 1, 2, 3. So we already can optimize current String>>threeWayCompareTo:.

Maybe good idea to open ticket and modify image level methods to return standard -1,0,1 values.

If we're modifying core sorting methods, we might as well use proper objects instead of magic numbers…

Ordering
  Lesser
  Equal
  Greater
  (Unordered?)

And while I'm on the topic of vocabulary, I'm not convinced by SortFunction… "to sort" means either to screen, to classify, or to arrange. There is a notion of going through all elements and swapping them around or putting in specific bins. Think QuickSort, MergeSort, etc

The mathematical term for the thing that determines whether two elements a and b are such that a ≤ b is "Order relation". So IMHO Java's Comparator fits the purpose much better; OrderFunction or OrderRelation would be nice and just Order would have my preference:

Order with: aPredicate
(Order with: [:a :b | a < b]) value: 1 value 2. → the singleton instance of Lesser

Order by: aMappingBlock
people sorted: (Order by: #name) , (Order by: #age)

Lesser >> #, innerOrder
  ^ self

Equal >> #, innerOrder
  ^ innerOrder

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Damien Pollet
On 9 November 2017 at 14:00, Damien Pollet <[hidden email]> wrote:
Order by: aMappingBlock
people sorted: (Order by: #name) , (Order by: #age)

Lesser >> #, innerOrder
  ^ self

Equal >> #, innerOrder
  ^ innerOrder

oh well, I got the Order composition and the Ordering flattening mixed up, but you get the idea :)

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Damien Pollet
Hi Damien.

2017-11-09 14:00 GMT+01:00 Damien Pollet <[hidden email]>:


On 7 November 2017 at 14:48, Denis Kudriashov <[hidden email]> wrote:
And we already have VM based String compare: with strange logic returning 1, 2, 3. So we already can optimize current String>>threeWayCompareTo:.

Maybe good idea to open ticket and modify image level methods to return standard -1,0,1 values.

If we're modifying core sorting methods, we might as well use proper objects instead of magic numbers…

Ordering
  Lesser
  Equal
  Greater
  (Unordered?)

I also thought about it. But it looks like overengineering to me. These magic numbers are too well known to be magic.
Do you have real cases where this approach will improve the code? 
 

And while I'm on the topic of vocabulary, I'm not convinced by SortFunction… "to sort" means either to screen, to classify, or to arrange. There is a notion of going through all elements and swapping them around or putting in specific bins. Think QuickSort, MergeSort, etc

The mathematical term for the thing that determines whether two elements a and b are such that a ≤ b is "Order relation". So IMHO Java's Comparator fits the purpose much better; OrderFunction or OrderRelation would be nice and just Order would have my preference:

Order with: aPredicate
(Order with: [:a :b | a < b]) value: 1 value 2. → the singleton instance of Lesser

Order by: aMappingBlock
people sorted: (Order by: #name) , (Order by: #age)

Lesser >> #, innerOrder
  ^ self

Equal >> #, innerOrder
  ^ innerOrder

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Damien Pollet
Not really, but I'd be interested in understanding why it's overengineering for Ordering but not for Boolean…

On 9 November 2017 at 14:16, Denis Kudriashov <[hidden email]> wrote:
Hi Damien.

2017-11-09 14:00 GMT+01:00 Damien Pollet <[hidden email]>:


On 7 November 2017 at 14:48, Denis Kudriashov <[hidden email]> wrote:
And we already have VM based String compare: with strange logic returning 1, 2, 3. So we already can optimize current String>>threeWayCompareTo:.

Maybe good idea to open ticket and modify image level methods to return standard -1,0,1 values.

If we're modifying core sorting methods, we might as well use proper objects instead of magic numbers…

Ordering
  Lesser
  Equal
  Greater
  (Unordered?)

I also thought about it. But it looks like overengineering to me. These magic numbers are too well known to be magic.
Do you have real cases where this approach will improve the code? 
 

And while I'm on the topic of vocabulary, I'm not convinced by SortFunction… "to sort" means either to screen, to classify, or to arrange. There is a notion of going through all elements and swapping them around or putting in specific bins. Think QuickSort, MergeSort, etc

The mathematical term for the thing that determines whether two elements a and b are such that a ≤ b is "Order relation". So IMHO Java's Comparator fits the purpose much better; OrderFunction or OrderRelation would be nice and just Order would have my preference:

Order with: aPredicate
(Order with: [:a :b | a < b]) value: 1 value 2. → the singleton instance of Lesser

Order by: aMappingBlock
people sorted: (Order by: #name) , (Order by: #age)

Lesser >> #, innerOrder
  ^ self

Equal >> #, innerOrder
  ^ innerOrder

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet




--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet
123