Skip to content

Modify elements during filter check to improve slice diffs #384

@bauersimon

Description

@bauersimon

Problem

Code (playground):

a := []int{1, 2}
b := []int{2, 3}
fmt.Println(cmp.Diff(a, b))

What happens:

[]int{
- 	1, 2,
+ 	2, 3,
  }

What I would like to see:

[]int{
  	2,
- 	1,
+ 	3,
  }

Solution

The workaround:

"Intercept" both slices before comparing and sort them such that matching items are at the front.

var dummy = cmp.Comparer(func(_, _ interface{}) bool { return false })

fmt.Println(cmp.Diff(a, b,
	cmp.FilterValues(func(x, y interface{}) bool {
		vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
		if !vx.IsValid() || !vy.IsValid() || vx.Type() != vy.Type() {
			return false
		}
		if vx.Type() == reflect.TypeOf(([]int)(nil)) {
			xValue := vx.Interface().([]int)
			if xValue[0] == 1 {
				fmt.Println("found [1,2], (fake) sorting to have matching elements in the front (this would access the other slice in practice")
				xValue[0] = 2
				xValue[1] = 1
			}
		}
		return false
	}, dummy),
))

Is this correct/doable?

In the documentation it is often explicitly mentioned when a function must be pure (not modify). This is never mentioned for FilterValues. Does that mean that the workaround outlined above is okay?

Proper solution / proposal:

Can we have a Transformer that has access to both compared elements such as: func(T,T) R,R? Where we can do the sorting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions