Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sort: add a method requiring closures as the sort interface #9998

Closed
daviddengcn opened this issue Feb 25, 2015 · 3 comments
Closed

sort: add a method requiring closures as the sort interface #9998

daviddengcn opened this issue Feb 25, 2015 · 3 comments

Comments

@daviddengcn
Copy link

The method signature looks like this:

func SortF(Len int, Less func(int, int) bool, Swap func(int, int))

The could simplify some code and make it much easier to read and maintain when closures can be used.

@minux minux changed the title Add a method requiring closures as the sort interface in the "sort" package. sort: add a method requiring closures as the sort interface Feb 25, 2015
@mattn
Copy link
Member

mattn commented Feb 26, 2015

Hmm, I think it's difficult judgement for include the sorter because we can't make sure how the sorter is useful for everyone, I think.

package main

import (
    "fmt"
    "sort"
)

type sorter struct {
    FLen  func() int
    FLess func(int, int) bool
    FSwap func(int, int)
}

func (s *sorter) Len() int {
    return s.FLen()
}

func (s *sorter) Less(i, j int) bool {
    return s.FLess(i, j)
}

func (s *sorter) Swap(i, j int) {
    s.FSwap(i, j)
}

func main() {
    fs := []struct {
        v int
    }{
        {3}, {1}, {2},
    }

    sort.Sort(&sorter{
        FLen:  func() int { return len(fs) },
        FLess: func(i, j int) bool { return fs[i].v < fs[j].v },
        FSwap: func(i, j int) { fs[i], fs[j] = fs[j], fs[i] },
    })
    fmt.Println(fs)
}

@daviddengcn
Copy link
Author

Here're two standard scenarios:

Sorting the same array with different comparators

It's very inconvinient to define a type for the array of a custom type and assert it just for sorting. When you have to sort in different ways, things become worse.

Sorting without changing the original array

I.e. create an index array to represent the sorting result.

Here are some code fragments showing these cases:

type MyData struct {
    score int
    time   int
}

func main() {
    list := []MyData{...}
    // descending sort by score
    sort.Sort(len(list), func(i, j int) bool {
        return list[i].score > list[i].score
    }, func(i, j int) {
        list[i], list[j] = list[j], list[i]
    })

    // sort by time
    sort.Sort(len(list), func(i, j int) bool {
        return list[i].time < list[i].time
    }, func(i, j int) {
        list[i], list[j] = list[j], list[i]
    })

    // sort with indexes
    indexes := make([]int, len(list)
    for i := range list {
        indexes[i] = i
    }
    sort.Sort(len(list), func(i, j int) bool {
        return list[indexes[i]].score < list[indexes[j]].score
    }, func(i, j) {
        indexes[i], indexes[j] = indexes[j], indexes[i]
    })
}

Closures are clearly making the code consie and much easier to maintain.

PS: I think the Len not necessary to be a function but just a integer field.

@rsc
Copy link
Contributor

rsc commented Apr 10, 2015

If you want this, it is easy to create:

type funcSorter struct {
    len int
    less func(int, int) bool
    swap func(int, int)
}

func (f *funcSorter) Len() int { return f.len }
func (f *funcSorter) Less(i, j int) bool { return f.less(i, j) }
func (f *funcSorter) Swap(i, j int) { f.swap(i, j) }

func SortF(len int, less func(int, int) bool, swap func(int, int)) {
    sort.Sort(&funcSorter{len, less, swap})
}

It doesn't need to be in the standard library. There is already one way to write a sort, and that's better than two.

@rsc rsc closed this as completed Apr 10, 2015
@golang golang locked and limited conversation to collaborators Jun 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants