Add uniq() builtin
Opened this issue · 2 comments
antonmedv commented
Add uniq() builtin
jippi commented
Not sure if usable or not, but I implemented this recently in my own project (source + docs)
I couldn't figure out how to make the input accept cmp.Ordered
instead of specific types :)
and inline below
func UniqSlice[T cmp.Ordered](in []T) []T {
slices.Sort(in)
return slices.Compact(in)
}
// Uniq takes a list of strings or interface{}, sorts them
// and remove duplicated values
var Uniq = expr.Function(
"uniq",
func(args ...any) (any, error) {
switch elements := args[0].(type) {
case []any:
var result []string
for _, element := range elements {
result = append(result, fmt.Sprintf("%s", element))
}
return UniqSlice(result), nil
case []string:
return UniqSlice(elements), nil
default:
return nil, fmt.Errorf("invalid input, must be an array of [string] or [interface], got %T", args[0])
}
},
new(func([]any) []string), // []any -> []string (when using map() that always return []any)
new(func([]string) []string), // []string -> []string
)
antonmedv commented
I couldn't figure out how to make the input accept cmp.Ordered instead of specific types :)
This is one of the limitations of our virtual machine. As we use stack of []any
, information on type is "lost" (can be retrieved via reflection).
For uniq() builtin to work not only with strings, we need to implement a more general approach, probably implementing in in bytecode or in VM.
Implementing uniq() is much ore tricky 👀