I have a bulk operation that operates on a 2 dimensional array. It shall call a given method "func" on each element in the array:
function forEachMatrixElement(matrix: Complex[][], func: Function): Complex[][] {
let matrixResult: Complex[][] = new Array(countRows(matrix)).fill(false).map(() => new Array(countCols(matrix)).fill(false)); // Creates a result 2D-Matrix
for (let row = 0; row < countRows(matrix); row++) {
for (let col = 0; col < countCols(matrix); col++) {
matrixResult[row][col] = func.call(matrix[row][col]); // Call the given method
}
}
return matrixResult;
}
I have two functions that I want to delegate to this method:
This one takes no additional arguments and works fine:
export function conjugateMatrix(matrix: Complex[][]): Complex[][] {
return forEachMatrixElement(matrix, Complex.prototype.conjugate);
}
This one takes an additional argument (a scalar). But I don’t know how to add this argument to this method reference on the prototype:
export function multiplyMatrixScalar(matrix: Complex[][], scalar: Complex): Complex[][] {
return forEachMatrixElement(matrix, Complex.prototype.mul); // TODO Call with scalar
}
>Solution :
Reaching into the prototype and manipulating the value of this with call() is usually a bad idea. This can be made simpler.
Instead, the forEachMatrixElement should simply take a function that accepts a Complex instance, and the caller can decide what that function does and how to apply its arguments.
For example:
function forEachMatrixElement(
matrix: Complex[][],
func: (complex: Complex) => Complex // Changed this function type
): Complex[][] {
let matrixResult: Complex[][] = new Array(countRows(matrix)).fill(false).map(() => new Array(countCols(matrix)).fill(false));
for (let row = 0; row < countRows(matrix); row++) {
for (let col = 0; col < countCols(matrix); col++) {
// just invoke the function like any other. No .call()
matrixResult[row][col] = func(matrix[row][col]);
}
}
return matrixResult;
}
Now the functions that call this can simply be:
export function conjugateMatrix(matrix: Complex[][]): Complex[][] {
return forEachMatrixElement(matrix, (c) => c.conjugate());
}
export function multiplyMatrixScalar(matrix: Complex[][], scalar: Complex): Complex[][] {
return forEachMatrixElement(matrix, (c) => c.mul(scalar));
}