libmir / mir-algorithm

Dlang Core Library
http://mir-algorithm.libmir.org
Other
173 stars 37 forks source link

Improve user-friendliness of `shouldApprox` for floating point slices #452

Open jmh530 opened 1 year ago

jmh530 commented 1 year ago

mir.test.shouldApprox only works with floating point numbers. This requires some workaround when working with floating point slices. Some kind of improvement in the user-friendliness would be a positive. This could include an overload for shouldApprox, or other approaches.

The code below fails because shouldApprox only accepts a floating point input.

import mir.test: shouldApprox;
import mir.ndslice.slice: sliced;

void main() {
    auto x = [1.0, 2, 3, 4];
    auto y = x.sliced;
    y.shouldApprox == y;
}

The alterative, is to use all with a lambda, but this isn't so user-friendly and makes documented unit tests uglier.

import mir.test: shouldApprox;
import mir.ndslice.slice: sliced;
import mir.algorithm.iteration: all;

void main() {
    auto x = [1.0, 2, 3, 4];
    auto y = x.sliced;
    y.all!((a, b) => a.shouldApprox == b)(y);
}

So it doesn't need ShouldApprox to work with floating point slices, just an overload of shouldApprox that incorporates the all/lambda.

The only reason to have an alternate version of ShouldApprox would be if you want to have a better error message for slices.

jmh530 commented 1 year ago

This might be complicated to implement more generally for the different kinds of slices that could be passed to it. (e.g. with all you have to use it multiple times with (some?) 2+ dimensional slices).

Another approach would be to define a shouldApproxEqual that is basically (a, b) => a.shouldApprox == b. Since it would return a bool it would be a drop-in replacement for approxEqual with better error messages.