Modify elements during filter check to improve slice diffs
- Dominant language
- Go
- Stars
- 4.7k
- Forks
- 243
- PR merge metrics
- No merged PRs in 30d
Description
# Problem
## Code ([playground](https://go.dev/play/p/8EG103MFcxj)):
```go
a := []int{1, 2}
b := []int{2, 3}
fmt.Println(cmp.Diff(a, b))
```
## What happens:
```sh
[]int{
- 1, 2,
+ 2, 3,
}
```
## What I would like to see:
```sh
[]int{
2,
- 1,
+ 3,
}
```
# Solution
## The workaround:
"Intercept" both slices before comparing and sort them such that matching items are at the front.
```sh
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](https://pkg.go.dev/github.com/google/go-cmp/cmp#Comparer) it is often explicitly mentioned when a function must be pure (not modify). This is never mentioned for [`FilterValues`](https://pkg.go.dev/github.com/google/go-cmp/cmp#FilterValues). **Does that mean that the workaround outlined above is okay?**
## Proper solution / proposal:
Can we have a [`Transformer`](https://pkg.go.dev/github.com/google/go-cmp/cmp#Transformer) that has access to both compared elements such as: `func(T,T) R,R`? Where we can do the sorting.
Contributor guide
Assessment
This issue has not been assessed yet.