(granted, 10 are under the .git directory, so I guess 57)
But in any other language, we'd still have the same 57 definitions of how to sort a type.... we'd just have 3 fewer lines of boilerplate for each of those (which live off in the bottom of a file somewhere and will never ever need to change).
Aside from trivial types, like strings or integers, how does the language know how to sort a list of values, if you don't tell it how to?
Translate this into whatever language you like:
Machine {
Name string
OS string
RAM int
}
You have 3 places that want to sort a list of machines, one by name, one by OS, and one by RAM. You're telling me there's a language that can do that without having to write some kind of code like this for each?
sort(machines, key: Name)
I don't understand how that's possible, but I welcome your explanation.
Sorting on all three fields in priority order is what I had in mind, and that's trivial in Haskell by adding "deriving(Ord)" to the data type definition and then just using the standard "sort :: Ord a => [a] -> [a]".
If you're always going to sort them based on some (other)
relation between the fields, make your type a custom instance of Ord, e.g. "instance Ord Machine where compare = compare `on` name".
To sort the same type with distinct comparators, you'll obviously need to distinguish them, as in e.g. "osSort = sortBy (compare `on` os)".
So... you will still need 57 spots in the code where you define how to sort a type.
Maybe my reference to sort.Interface is confusing people. When I say we have 57 implementations of sort.Interface, that's 57 different types and/or different ways of sorting one of those types. So, like, sorting Machine by Name would be one implementation, sorting Machine by Name then OS then RAM would be another implementation. You write an implementation of sort.Interface for every type, and for each way you would like to be able to sort it.
An implementation of sort.Interface just requires three methods:
Len() int // return the length of the list
Swap(i, j int) // swap items at indices i and j
Less(i, j int) bool // return true if list[i] is less than list[j]
It's the implementation in Less that determines the order.
That's not really so different than what you're describing in Haskell, it's just not part of the type, it's a new type that you convert the original type into, to pass into the sort.Sort() function (and because the underlying type is a slice, which is a glorified struct with a pointer to an array, that also sorts the original value).
It's possible to make one implementation for a type that supports multiple orderings, at the cost of another indirection [0]. This turns O(N*M) implementations for N types and M sorting orders into just O(N). (I'm not counting an inline anonymous function as a new implementation.)
In practice, it's rare to need to sort a slice more than one way.
This is an extensively solved problem in modern programming languages.
As a bonus, the opportunity for making an error each time you want to sort a new type of array in a new way is reduced if you only have to write one line of code each time.
The canonical solution to this problem is to provide a function to perform the comparison, or to require the types implement a "Sortable" or "Comparable" interface.
yes, which for 57 different types and/or comparison methods requires 57 different functions... which is basically the exact same thing you do in Go. It's just in go, you define a new type based on the original value, rather than just a function.
Just to nitpick, that is 4 lines because you add a type too.
Also, I noticed this in controller.go:
// Unreachable based on the rules of there not being duplicate
// environments of the same name for the same owner, but return false
// instead of panicing.
return false
Guess what, I worked with a sort function with the same kind of assumptions, but the implicit rules was broken: the "should never happen" path happened (names were not unique, after all). I found about that only after I wrote my own sort which was careful enough to check that the order was indeed total and when results diverged for some tests.
I really disliked that because sorting was an important part in that tool (maybe it is not in yours).
> Hahaha. This has to be satire right?
Nope.
(granted, 10 are under the .git directory, so I guess 57)But in any other language, we'd still have the same 57 definitions of how to sort a type.... we'd just have 3 fewer lines of boilerplate for each of those (which live off in the bottom of a file somewhere and will never ever need to change).