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

Nicolas Cellier


2017-11-06 21:04 GMT+01:00 Stephane Ducasse <[hidden email]>:
Hi nicolas

While I know the ascending and other protocol, it is still unclear to
me the composition aspect. Did Travis write a tutorial
can we can use as documentation/comment?

BTW
"Example: #('abc'  'de' 'fghi') sorted: #size asscending"
=>

"Example: (#('abc'  'de' 'fghi') sorted: #size) ascending
=> show the result"

Stef

Well, I willl repeat what I wrote in squeak-dev:
Travis has just seeded the very simple and light library with chaining:

    points sorted: #x ascending , #y descending.

Denis then added possibility to sort properties even if undefined, a common case:

    people sorted: #name ascending undefinedFirst , #age descending

And he started to use subclasses with the intention to enrich the library I presume.
But current implementation does not use composition.
It adds an instance variable undefinedDirection to PropertySortFunction and specific behavior.
What I say here is that it's easier and more powerfull to implement such feature with composition.

That is, sorting nil first is an elementary sort function, than can be complemented by #name ascending, another elementary sort function.
In which case, you compose simple and little sort function with less code, and even branchless code.

Similarly, descending invoke toggleDirection which changes a direction inst var in Travis' implementation.
With such implementation, every SortFunction has to care of direction inst. var.
But it could be implemented with a simple composition too, with a wrapper for toggling direction (ReverseSortFunction), and no direction inst var at all.

Less states, less inst vars, less responsibility, very small and cute classes
The best is to read code - if I manage to both publish and answer mails ;)


PS: In Pharo we do not remove history of methods for the fun.
I can tell you that I do not really like Git but I do not want our
language to be looking like a terrible system just because it does not
use a modern versioning control system.


I don't see why it requires that mc ancestry was removed...
And mc ancestry was removed well before the git switch.

I do not expect that we will move to another versioning control system
in the near future so we will be able to take advantage of the git
infrastructure.
And versioning code with resources and decent branch support will be
game changing.


MC is not so bad. OK branches are not named (or neeed not be), GUID are inferior to SHA, etc...
The biggest difference comes from github, that is the social environment, not necessarily git.


On Mon, Nov 6, 2017 at 12:06 AM, Nicolas Cellier
<[hidden email]> wrote:
> I've put some of the proposed composition features into
>
> http://source.squeak.org/inbox/Collections-nice.766.mcz
> http://source.squeak.org/inbox/CollectionsTests-nice.283.mcz
>
> http://source.squeak.org/inbox/Collections-nice.766.diff
> http://source.squeak.org/inbox/CollectionsTests-nice.283.diff
>
> SInce it's Squeak based, it uses <=>, but never mind, that's the same
> functions.
>
>
> Stephane: the original comments were from Travis Griggs.
> It's more a tutorial for using the SortFunction than a detailed explanation
> of implementation.
>
> The original idea is that oSortFunction are composable.
> For example, it's possible to chain sorting on a first criterion, then
> resort on a second criterion if objects have same rank with first.
>
> For this, we need a to distinguish when objects have same rank (=) and
> cannot use a binary result (Boolean) like legacy sortBlock,
> So we rather need a ternary comparison (<=>).
>
> This thread is about extending composition, and generalizing implementation
> by composition (like Xtreams)
> - for sorting nil first (or last)
> - for reversing the order
> - for sorting properties with any collation order, and not just default <=>
>
> 2017-11-05 17:52 GMT+01:00 Stephane Ducasse <[hidden email]>:
>>
>> Hi guys
>>
>> Do you have some nice comments somewhere? because I do not understand
>> anything about this thread.
>> I check the code and the comments are well... unclear and confusing.
>>
>> Stef
>>
>> On Sun, Nov 5, 2017 at 4:15 PM, Nicolas Cellier
>> <[hidden email]> wrote:
>> >
>> >
>> > 2017-11-05 16:06 GMT+01:00 Denis Kudriashov <[hidden email]>:
>> >>
>> >>
>> >> 2017-11-05 11:33 GMT+01:00 Nicolas Cellier
>> >> <[hidden email]>:
>> >>>
>> >>>
>> >>> Ah, I messed up, UndefinedSorter must not be chained, it must be a
>> >>> wrapper!
>> >>> Otherwise comparing to nil will resort to sorting by properties and
>> >>> fail...
>> >>>
>> >>>     SortFunction>>undefinedFirst
>> >>>         ^UndefinedSorter descending wrap: self
>> >>>
>> >>>     UndefinedSorter>> collate: value1 with: value2
>> >>>        "sort all nil according to the direction (first if -1, last if
>> >>> +1), then"
>> >>>         value1 ifNil: [value2 ifNil: [^0] ifNotNil: [^direction]].
>> >>>         value2 ifNil: [^direction negated].
>> >>>         ^sorterForNonNil collate: value1 with: value2
>> >>>
>> >>> It's important to have the UndefinedSorter :
>> >>>     - decoupled from property sort, because it can be generally
>> >>> usefull
>> >>>     - collating 2 nil as 0, so that another property can be chained
>> >>
>> >>
>> >> I like your idea.
>> >> It also forced me to think that direction itself should be implemented
>> >> as
>> >> wrapper. I would name it InvertedSortFunction:
>> >>
>> >> InvertedSortFunction>>collate: value1 with: value2
>> >>     ^(actualSortFunction collate: value1 with: value2) * -1
>> >>
>> >>
>> >> If we will do it then direction will be not part of SortFunction. And
>> >> all
>> >> current functions will be in fact ascending.
>> >> And to explicitly reflect this fact I would introduce
>> >> AscendingSortFunction as their superclass.
>> >> InvertedSortFunction and ChainedSortFunction will stay subclasses of
>> >> SortFunction.
>> >>
>> >> So what you think?
>> >
>> >
>> > Yes, I was thinking the same.
>> > On another hand, direction makes thing symmetric and has its elegance
>> > too.
>> > What I don't like with it is that it forces the library to have two
>> > different messages for the same thing:
>> > - collate:with: in base class accounting for direction
>> > - threeWayCompare:with: in every subclass
>> >
>> > The fact to hardcode the direction in base class could be seen as an
>> > optimization too.
>> > I'm not sure what Sista optimization could bring in this case, because
>> > the
>> > selectors may get megamorphic...
>> >
>> >
>> >>
>> >>>
>> >>>
>> >>> In
>> >>>
>> >>>     people sortBy: #name ascending undefinedFirst , #age descending
>> >>>
>> >>> we could then have people with name nil still sorted by age, what is
>> >>> not
>> >>> possible with current implementation
>> >>>
>> >>
>> >
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Stephane Ducasse-3
On Mon, Nov 6, 2017 at 9:52 PM, Nicolas Cellier
<[hidden email]> wrote:
>
>
> 2017-11-06 21:04 GMT+01:00 Stephane Ducasse <[hidden email]>:
>>
>> Hi nicolas
>>
>> While I know the ascending and other protocol, it is still unclear to
>> me the composition aspect. Did Travis write a tutorial
>> can we can use as documentation/comment?

>> BTW
>> "Example: #('abc'  'de' 'fghi') sorted: #size asscending"
>> =>
>>
>> "Example: (#('abc'  'de' 'fghi') sorted: #size) ascending
>> => show the result

It was about a method comment. I sent this to help you because the
snippet did not work :)



I'm sorry but I do not read squeak-dev since years.

> Travis has just seeded the very simple and light library with chaining:
>
>     points sorted: #x ascending , #y descending.
>
> Denis then added possibility to sort properties even if undefined, a common
> case:
>
>     people sorted: #name ascending undefinedFirst , #age descending
>
> And he started to use subclasses with the intention to enrich the library I
> presume.
> But current implementation does not use composition.
> It adds an instance variable undefinedDirection to PropertySortFunction and
> specific behavior.
> What I say here is that it's easier and more powerfull to implement such
> feature with composition.
>
> That is, sorting nil first is an elementary sort function, than can be
> complemented by #name ascending, another elementary sort function.
> In which case, you compose simple and little sort function with less code,
> and even branchless code.
>
> Similarly, descending invoke toggleDirection which changes a direction inst
> var in Travis' implementation.
> With such implementation, every SortFunction has to care of direction inst.
> var.
> But it could be implemented with a simple composition too, with a wrapper
> for toggling direction (ReverseSortFunction), and no direction inst var at
> all.
>
> Less states, less inst vars, less responsibility, very small and cute
> classes
> The best is to read code - if I manage to both publish and answer mails ;)

I really like this library this is why I pushed it to Pharo now I
would like to improve the comments.


>> PS: In Pharo we do not remove history of methods for the fun.
>> I can tell you that I do not really like Git but I do not want our
>> language to be looking like a terrible system just because it does not
>> use a modern versioning control system.
>>
>
> I don't see why it requires that mc ancestry was removed...
> And mc ancestry was removed well before the git switch.

Because of the size.
Ask marcus because he was really concerned


>> I do not expect that we will move to another versioning control system
>> in the near future so we will be able to take advantage of the git
>> infrastructure.
>> And versioning code with resources and decent branch support will be
>> game changing.
>>
>>
> MC is not so bad.

I know this is me and marcus that decided to use it to manage squeak.


> OK branches are not named (or neeed not be), GUID are
> inferior to SHA, etc...
> The biggest difference comes from github, that is the social environment,
> not necessarily git.

Indeed and that people love complexity and a real distributed model.
Now I do not like git (far far too complex for my taste) but I do not
want to live in a museum.

We will produce on top IceCube or TipTop a tool to offer the comfort
of MC, because Iceberg
is tooo complex (not its fault) but still I do not like all the
complexity when I do not need it.
And I imagine newbie (even if some people believe that newbie can
master git - I do not believe this lie :)


Stef

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Ben Coman
In reply to this post by Nicolas Cellier


On Tue, Nov 7, 2017 at 4:52 AM, Nicolas Cellier <[hidden email]> wrote:

MC is not so bad. OK branches are not named (or neeed not be), GUID are inferior to SHA, etc...
The biggest difference comes from github, that is the social environment, not necessarily git.

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

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier

2017-11-06 22:52 GMT+01:00 Ben Coman <[hidden email]>:


On Tue, Nov 7, 2017 at 4:52 AM, Nicolas Cellier <[hidden email]> wrote:

MC is not so bad. OK branches are not named (or neeed not be), GUID are inferior to SHA, etc...
The biggest difference comes from github, that is the social environment, not necessarily git.

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

cheers -ben


Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

If we defined <=> in Boolean (orWhatEverTheLongSelectorYouPreferBecausePharoHasTheFreedomToHaveOwnTaste:)
in order to have true sorted first, then we can generalize.

    "sort by absolute value, but put the negative first"
    numbers sorted: #negative sortedFirst, #abs

    "sort by name, but put the undefined last"
    people sorted: (#name collatedBy: #isNil sortedLast) , #name.

sortedFirst in this case would be a synonym for ascending (or asSortFunction).
Alternatively, if we don't want <=> in Boolean because it's not natural (the fact that we need a synonym is a clue)
then we can have sortedFirst answering a specialized BooleanSortFunction.


2017-11-07 1:21 GMT+01:00 Nicolas Cellier <[hidden email]>:

2017-11-06 22:52 GMT+01:00 Ben Coman <[hidden email]>:


On Tue, Nov 7, 2017 at 4:52 AM, Nicolas Cellier <[hidden email]> wrote:

MC is not so bad. OK branches are not named (or neeed not be), GUID are inferior to SHA, etc...
The biggest difference comes from github, that is the social environment, not necessarily git.

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

cheers -ben



Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Sven Van Caekenberghe-2
In reply to this post by Nicolas Cellier


> On 7 Nov 2017, at 01:21, Nicolas Cellier <[hidden email]> wrote:
>
> Back to the thread: https://github.com/pharo-project/pharo/pull/440

Thx!

> 2017-11-06 22:52 GMT+01:00 Ben Coman <[hidden email]>:
>
>
> On Tue, Nov 7, 2017 at 4:52 AM, Nicolas Cellier <[hidden email]> wrote:
>
> MC is not so bad. OK branches are not named (or neeed not be), GUID are inferior to SHA, etc...
> The biggest difference comes from github, that is the social environment, not necessarily git.
>
> Some would say it was github that "made" git (popular).
>
> cheers -ben
>
>


Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Stephane Ducasse-3
On Mon, Nov 6, 2017 at 9:52 PM, Nicolas Cellier
<[hidden email]> wrote:
> Travis has just seeded the very simple and light library with chaining:
>
>     points sorted: #x ascending , #y descending.
>
> Denis then added possibility to sort properties even if undefined, a common
> case:
>
>     people sorted: #name ascending undefinedFirst , #age descending
>
> And he started to use subclasses with the intention to enrich the library I
> presume.
> But current implementation does not use composition.
> It adds an instance variable undefinedDirection to PropertySortFunction and
> specific behavior.

Just little note. I not introduced anything new. In original Pharo version all this states were part of single SortFunction. And for example direction and undefinedDirection were used only in the mode with one arg block or selector.
So I just split it by subclasses for existing uses cases.
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier


2017-11-07 10:30 GMT+01:00 Denis Kudriashov <[hidden email]>:
On Mon, Nov 6, 2017 at 9:52 PM, Nicolas Cellier
<[hidden email]> wrote:
> Travis has just seeded the very simple and light library with chaining:
>
>     points sorted: #x ascending , #y descending.
>
> Denis then added possibility to sort properties even if undefined, a common
> case:
>
>     people sorted: #name ascending undefinedFirst , #age descending
>
> And he started to use subclasses with the intention to enrich the library I
> presume.
> But current implementation does not use composition.
> It adds an instance variable undefinedDirection to PropertySortFunction and
> specific behavior.

Just little note. I not introduced anything new. In original Pharo version all this states were part of single SortFunction. And for example direction and undefinedDirection were used only in the mode with one arg block or selector.
So I just split it by subclasses for existing uses cases.

Exactly, the inst var were from original author Travis Griggs.
The fact that you split the classes put us on the way to rethink the whole library,

The addition of undefinedDirection is just what lighted my own bulb on.
I absolutely don't want to denigrate this work, on the contrary.

Thanks for initiating the refactoring
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Nicolas Cellier

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Thierry Goubier


2017-11-07 11:24 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.


This code has a cost, however.

First, it's rather slow (hidden #perform: in there).

Second, I had a first hand experience that it is making it significantly more complex to understand for newcomers (implying that it creates additional, special semantics compared to basic smalltalk). I know that there is no special semantic involved, but it looks as if to practitionners of other programming languages and their complex semantics.

I do like the SortFunctions idea (and its extension), but it's important IMHO to not make it too cryptic.
 
Regards,

Thierry
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

NorbertHartl
In reply to this post by Denis Kudriashov

Am 07.11.2017 um 11:24 schrieb Denis Kudriashov <[hidden email]>:


2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.

And it is really valuable for databases. The query tree can be transformed into the query language of another system like a database.

Norbert

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier


2017-11-07 11:37 GMT+01:00 Norbert Hartl <[hidden email]>:

Am 07.11.2017 um 11:24 schrieb Denis Kudriashov <[hidden email]>:


2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.

And it is really valuable for databases. The query tree can be transformed into the query language of another system like a database.

Norbert


I was thinking of the same chevron selector or maybe a pipe |, but I find that >> better indicates that result is directed to next block/function/processing unit.
Of course it sounds much like a DSL.

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Thierry Goubier


2017-11-07 11:36 GMT+01:00 Thierry Goubier <[hidden email]>:


2017-11-07 11:24 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.


This code has a cost, however.

First, it's rather slow (hidden #perform: in there).

Second, I had a first hand experience that it is making it significantly more complex to understand for newcomers (implying that it creates additional, special semantics compared to basic smalltalk). I know that there is no special semantic involved, but it looks as if to practitionners of other programming languages and their complex semantics.

I do like the SortFunctions idea (and its extension), but it's important IMHO to not make it too cryptic.

That's why I said it is not related to SortFunction. 
Generally we rarely use symbol for #collect:/#select: in production. But it is supper handy for scripting/debugging/inspecting. I use it all the time.
Also performance in that case can be covered by Sista.
Another problem: it complicates debugging because it is not easy to step into selector in that case. With block we just press "Through" button and we are done. But I am sure we can improve it too. Our debugger is in our hands.

Another advantage of symbol based functions: there is not potential memory leak here. In case of block we always have reference to outer context. So it is dangerous to use blocks in caches for example.

 
Regards,

Thierry

Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Denis Kudriashov
In reply to this post by Nicolas Cellier

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

If we defined <=> in Boolean (orWhatEverTheLongSelectorYouPreferBecausePharoHasTheFreedomToHaveOwnTaste:)
in order to have true sorted first, then we can generalize.

    "sort by absolute value, but put the negative first"
    numbers sorted: #negative sortedFirst, #abs

sortedFirst in this case would be a synonym for ascending (or asSortFunction).
Alternatively, if we don't want <=> in Boolean because it's not natural (the fact that we need a synonym is a clue)
then we can have sortedFirst answering a specialized BooleanSortFunction.

I like this idea. And I think it is better to add threeWayCompare: to Boolean because it allows to avoid extra selector:
#negative ascending, #abs
#isNil descending, #name
From the other side it will force remembering convention for boolean order. So maybe it should be explicit:
#negative trueFirst, #abs
#isNil trueLast, #name
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Nicolas Cellier
In reply to this post by Thierry Goubier


2017-11-07 11:36 GMT+01:00 Thierry Goubier <[hidden email]>:


2017-11-07 11:24 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.


This code has a cost, however.

First, it's rather slow (hidden #perform: in there).

Second, I had a first hand experience that it is making it significantly more complex to understand for newcomers (implying that it creates additional, special semantics compared to basic smalltalk). I know that there is no special semantic involved, but it looks as if to practitionners of other programming languages and their complex semantics.

I do like the SortFunctions idea (and its extension), but it's important IMHO to not make it too cryptic.
 
Regards,

Thierry

Hi Thierry
I ear those objections.
Concerning the cost, i wonder what Clement thinks about it.
Repeated perform: could benefit from PIC too, and adaptive inlining.

Concerning syntactic sugar (even if it's pure Smalltalk) I have same cicrconspection
In the case of #name >> #size it's like we are creating another language for the basic mechanisms we already have (send messages)
What we try to achieve here is in fact the reify the send, what is not really in the base Smalltalk.
For a more functional style, we would rapidly need currying anyway so even more syntactic sugar...
On the other hand, PetitParser is nice too.

For SortFunction, I think we all agree that there's no debate, procedural style is so ugly

    people sorted: [:a :b |
        a name
            ifNil:
                [ b name
                    ifNil: [a age > b age]
                    ifNotNil: [true "a first"]]
            ifNotNil:
                [ b name
                    ifNil: [false "b first"]
                    ifNotNil: [a name = b name
                        ifTrue: [a age > b age]
                        ifFalse: [a name < b name]]]

compared to:

    people sorted: #name ascending undifiedFirst , #age descending

or even

    people sorted: (#name collatedWith: #isNil) , #age descending
               
     
Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Thierry Goubier
In reply to this post by Denis Kudriashov


2017-11-07 11:55 GMT+01:00 Denis Kudriashov <[hidden email]>:


2017-11-07 11:36 GMT+01:00 Thierry Goubier <[hidden email]>:


2017-11-07 11:24 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.


This code has a cost, however.

First, it's rather slow (hidden #perform: in there).

Second, I had a first hand experience that it is making it significantly more complex to understand for newcomers (implying that it creates additional, special semantics compared to basic smalltalk). I know that there is no special semantic involved, but it looks as if to practitionners of other programming languages and their complex semantics.

I do like the SortFunctions idea (and its extension), but it's important IMHO to not make it too cryptic.

That's why I said it is not related to SortFunction. 
Generally we rarely use symbol for #collect:/#select: in production. But it is supper handy for scripting/debugging/inspecting. I use it all the time.

Hum, among users of # symbol instead of blocks, they do leave it in production. Or they have a different concept of "production" than I do.
 
Also performance in that case can be covered by Sista.

Sure.
 
Another problem: it complicates debugging because it is not easy to step into selector in that case. With block we just press "Through" button and we are done. But I am sure we can improve it too. Our debugger is in our hands.

Yes, this is a concern.
 

Another advantage of symbol based functions: there is not potential memory leak here. In case of block we always have reference to outer context. So it is dangerous to use blocks in caches for example.

Clean blocks are easy to check for.

Thierry
 

 
Regards,

Thierry


Reply | Threaded
Open this post in threaded view
|

Re: about SortFunctions

Thierry Goubier
In reply to this post by Nicolas Cellier


2017-11-07 12:09 GMT+01:00 Nicolas Cellier <[hidden email]>:


2017-11-07 11:36 GMT+01:00 Thierry Goubier <[hidden email]>:


2017-11-07 11:24 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 9:23 GMT+01:00 Nicolas Cellier <[hidden email]>:
I have other ideas yet.

The selector undefinedFirst is good, but the implementation not so.
I don't like the UndefinedSortFunction: too specific, compose oddly...

In the PR, collatedBy: is the way to tell how we sort properties (if you have a better name, go, it's bikesheding day)

    "sort by size of name"
    (people sorted: (#name collatedBy: #size))
        =  (people sorted: [:p| p name size])

It is nice idea but it should be not bound to sort functions. Because this feature is useful for other block based messages:
people collect: #name >> #size
people select: #name >> #size >> #even
(I use >> as example). 
Generally it is about functional programming. Would be nice to have this in image because it will simplify scripting a lot. 
I remember nice set of blog posts from Vassili Bykov about such kind of things http://blog.3plus4.org/2007/03/.


This code has a cost, however.

First, it's rather slow (hidden #perform: in there).

Second, I had a first hand experience that it is making it significantly more complex to understand for newcomers (implying that it creates additional, special semantics compared to basic smalltalk). I know that there is no special semantic involved, but it looks as if to practitionners of other programming languages and their complex semantics.

I do like the SortFunctions idea (and its extension), but it's important IMHO to not make it too cryptic.
 
Regards,

Thierry

Hi Thierry
I ear those objections.
Concerning the cost, i wonder what Clement thinks about it.
Repeated perform: could benefit from PIC too, and adaptive inlining.

Hi Nicolas,

I agree it could be optimised away. For now, it is slow. And there is so much for Clement to optimise for.
 

Concerning syntactic sugar (even if it's pure Smalltalk) I have same cicrconspection
In the case of #name >> #size it's like we are creating another language for the basic mechanisms we already have (send messages)
What we try to achieve here is in fact the reify the send, what is not really in the base Smalltalk.
For a more functional style, we would rapidly need currying anyway so even more syntactic sugar...

Yes, that would be my worry. There is a value in keeping simple consistent semantics... especially because there is no one else still maintaining that focus (apart from STEPS that is) and that we are under constant pressure from other languages to add stuff.
 
On the other hand, PetitParser is nice too.

?
 

For SortFunction, I think we all agree that there's no debate, procedural style is so ugly

    people sorted: [:a :b |
        a name
            ifNil:
                [ b name
                    ifNil: [a age > b age]
                    ifNotNil: [true "a first"]]
            ifNotNil:
                [ b name
                    ifNil: [false "b first"]
                    ifNotNil: [a name = b name
                        ifTrue: [a age > b age]
                        ifFalse: [a name < b name]]]

compared to:

    people sorted: #name ascending undifiedFirst , #age descending

or even

    people sorted: (#name collatedWith: #isNil) , #age descending

I find that exemple interesting because the obvious solution to the procedural style is to create a nice, correct People>>#>, which is of great value for the overall code understanding. So, is it a good idea to make it easier not to write a proper #>?

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.

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

2017-11-07 13:11 GMT+01:00 Thierry Goubier <[hidden email]>:
2017-11-07 12:09 GMT+01:00 Nicolas Cellier <[hidden email]>:
Concerning syntactic sugar (even if it's pure Smalltalk) I have same cicrconspection
In the case of #name >> #size it's like we are creating another language for the basic mechanisms we already have (send messages)
What we try to achieve here is in fact the reify the send, what is not really in the base Smalltalk.
For a more functional style, we would rapidly need currying anyway so even more syntactic sugar...

Yes, that would be my worry. There is a value in keeping simple consistent semantics... especially because there is no one else still maintaining that focus (apart from STEPS that is) and that we are under constant pressure from other languages to add stuff.

One note: we are not discussing here the possible new language or system core feature. It should be in separate package with clear intention in the name (like FunctionalProgramming). So it can provide nice handy message for their domain.
  

For SortFunction, I think we all agree that there's no debate, procedural style is so ugly

    people sorted: [:a :b |
        a name
            ifNil:
                [ b name
                    ifNil: [a age > b age]
                    ifNotNil: [true "a first"]]
            ifNotNil:
                [ b name
                    ifNil: [false "b first"]
                    ifNotNil: [a name = b name
                        ifTrue: [a age > b age]
                        ifFalse: [a name < b name]]]

compared to:

    people sorted: #name ascending undifiedFirst , #age descending

or even

    people sorted: (#name collatedWith: #isNil) , #age descending

I find that exemple interesting because the obvious solution to the procedural style is to create a nice, correct People>>#>, which is of great value for the overall code understanding. So, is it a good idea to make it easier not to write a proper #>?

It will not help because desired order depends on concrete use case. Different reports can represent people in completely different order.
And do you think that any object should implement comparison?
 

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. 
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 #>
  

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 Thierry Goubier
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.
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:37 GMT+01:00 Denis Kudriashov <[hidden email]>:

2017-11-07 13:11 GMT+01:00 Thierry Goubier <[hidden email]>:
2017-11-07 12:09 GMT+01:00 Nicolas Cellier <[hidden email]>:
Concerning syntactic sugar (even if it's pure Smalltalk) I have same cicrconspection
In the case of #name >> #size it's like we are creating another language for the basic mechanisms we already have (send messages)
What we try to achieve here is in fact the reify the send, what is not really in the base Smalltalk.
For a more functional style, we would rapidly need currying anyway so even more syntactic sugar...

Yes, that would be my worry. There is a value in keeping simple consistent semantics... especially because there is no one else still maintaining that focus (apart from STEPS that is) and that we are under constant pressure from other languages to add stuff.

One note: we are not discussing here the possible new language or system core feature. It should be in separate package with clear intention in the name (like FunctionalProgramming). So it can provide nice handy message for their domain.

Hum, I've already seen that sort of package for Squeak. Or at least I know someone who codes like that in Squeak.

  

For SortFunction, I think we all agree that there's no debate, procedural style is so ugly

    people sorted: [:a :b |
        a name
            ifNil:
                [ b name
                    ifNil: [a age > b age]
                    ifNotNil: [true "a first"]]
            ifNotNil:
                [ b name
                    ifNil: [false "b first"]
                    ifNotNil: [a name = b name
                        ifTrue: [a age > b age]
                        ifFalse: [a name < b name]]]

compared to:

    people sorted: #name ascending undifiedFirst , #age descending

or even

    people sorted: (#name collatedWith: #isNil) , #age descending

I find that exemple interesting because the obvious solution to the procedural style is to create a nice, correct People>>#>, which is of great value for the overall code understanding. So, is it a good idea to make it easier not to write a proper #>?

It will not help because desired order depends on concrete use case. Different reports can represent people in completely different order.
And do you think that any object should implement comparison?

No, but that hiding it into a mix of business domain specific messages mixed up with general sorting arguments somewhere at the point of sorting people is bad software design. 
 
 

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.

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
 
               
     



123