in starlark/library.go [1000:1044]
func sorted(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
// Oddly, Python's sorted permits all arguments to be positional, thus so do we.
var iterable Iterable
var key Callable
var reverse bool
if err := UnpackArgs("sorted", args, kwargs,
"iterable", &iterable,
"key?", &key,
"reverse?", &reverse,
); err != nil {
return nil, err
}
iter := iterable.Iterate()
defer iter.Done()
var values []Value
if n := Len(iterable); n > 0 {
values = make(Tuple, 0, n) // preallocate if length is known
}
var x Value
for iter.Next(&x) {
values = append(values, x)
}
// Derive keys from values by applying key function.
var keys []Value
if key != nil {
keys = make([]Value, len(values))
for i, v := range values {
k, err := Call(thread, key, Tuple{v}, nil)
if err != nil {
return nil, err // to preserve backtrace, don't modify error
}
keys[i] = k
}
}
slice := &sortSlice{keys: keys, values: values}
if reverse {
sort.Stable(sort.Reverse(slice))
} else {
sort.Stable(slice)
}
return NewList(slice.values), slice.err
}