google / google/go-cmp

Modify elements during filter check to improve slice diffs

Open
#384 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.