Preamble
As we are vectorising our colour API, we are changing the accepted input types for most of our functions. We would be keen on keeping backward compatibility with the existing code.
Let's define the following input variables:
numeric
R
shape: ()
A pixel R value of an RGB triplet for example.
1d
[R, G, B]
shape: (3)
A pixel RGB values triplet for example.
2d
[[R, G, B],
[R, G, B],
[R, G, B],
[R, G, B],
[R, G, B],
[R, G, B]]
shape: (6, 3)
A line of RGB values triplet for example.
3d
[[[R, G, B],
[R, G, B],
[R, G, B]],
[[R, G, B],
[R, G, B],
[R, G, B]]]
shape: (2, 3, 3)
An image of RGB values triplet for example.
Expectations
A function that was previously accepting a numeric as input may now accept a numeric or a 1d array. A function previously accepting a 1d array as input may now accept a 1d, 2d or 3d array.
Most of our codebase vectorisation is now prototyped. Specifically, in order to support 1d, 2d or 3d arrays with functions originally taking a 1d array as input, we convert the input array to a 2d one. The inner algorithms now work with the 2d arrays thus their implementation is straightforward and predictable.
For a given function, as we modify the input array dimensions for its algorithm purpose, the resulting output array dimensions are altered (if we don't do anything about it).
We would like to know the following:
Is trying to maintain the array dimensions a commonly expected behaviour?
A path that seems logical is to maintain the dimensions of the input array: for example we suppose that somebody inputing an image (with a 3d shape) to our RGB_to_XYZ
function would probably expect to get an image with a 3d shape, somebody inputing a 1d RGB pixel to that same function would probably expect to get a 1d XYZ pixel in return and not a 2d array.
An alternative path would be to enforce the expected input / output array dimensions for each function (which would break backward compatibility).
Implementations
The alternative path doesn't present any difficulties in its implementation.
The logical path is however trickier: as we have prototyped the code in that regard, we have a lot of redundant boiler plate code at the start and end of each function in order to retrieve the dimensions of the input array, change its dimensions and reshape the output array. This is not very elegant and confusing for somebody reading the code while contributing to a harder maintainability.
Is there an elegant way to implement the "logical" path behaviour?
We are thinking about a wrapper function (decorator as we are using Python) that could be responsible of handling all the dimensions / reshaping wizardry, the functions themselves could then have fixed expectations on the input / output like in the alternative path.