expr icon indicating copy to clipboard operation
expr copied to clipboard

Add uniq() builtin

Open antonmedv opened this issue 1 year ago • 2 comments

antonmedv avatar May 10 '24 16:05 antonmedv

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
)

jippi avatar May 12 '24 19:05 jippi

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 👀

antonmedv avatar May 13 '24 09:05 antonmedv

Could u pls be more concrete and provide at least signature?)

OlgaNovg avatar Sep 03 '24 08:09 OlgaNovg

Fixed in #705

antonmedv avatar Sep 06 '24 08:09 antonmedv