Skip to content

Commit eaee5de

Browse files
committed
feat: make use of Symbol.species to allow creating new matrices in any class
- defaults to the current constructor - views override it to return a new Matrix
1 parent f077732 commit eaee5de

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

src/abstractMatrix.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ function abstractMatrix(superCtor) {
1818
* @param {number} [nColumns] - Number of columns of the new matrix
1919
*/
2020
class Matrix extends superCtor {
21+
static get [Symbol.species]() {
22+
return this;
23+
}
24+
2125
/**
2226
* Constructs a Matrix with the chosen dimensions from a 1D array
2327
* @param {number} newRows - Number of rows
@@ -339,7 +343,7 @@ function abstractMatrix(superCtor) {
339343
repeat(rowRep, colRep) {
340344
rowRep = rowRep || 1;
341345
colRep = colRep || 1;
342-
var matrix = new this.constructor(this.rows * rowRep, this.columns * colRep);
346+
var matrix = new this.constructor[Symbol.species](this.rows * rowRep, this.columns * colRep);
343347
for (var i = 0; i < rowRep; i++) {
344348
for (var j = 0; j < colRep; j++) {
345349
matrix.setSubMatrix(this, this.rows * i, this.columns * j);
@@ -929,7 +933,7 @@ function abstractMatrix(superCtor) {
929933
var n = this.columns;
930934
var p = other.columns;
931935

932-
var result = new this.constructor(m, p);
936+
var result = new this.constructor[Symbol.species](m, p);
933937

934938
var Bcolj = new Array(n);
935939
for (var j = 0; j < p; j++) {
@@ -1010,7 +1014,7 @@ function abstractMatrix(superCtor) {
10101014
var p = other.rows;
10111015
var q = other.columns;
10121016

1013-
var result = new this.constructor(m * p, n * q);
1017+
var result = new this.constructor[Symbol.species](m * p, n * q);
10141018
for (var i = 0; i < m; i++) {
10151019
for (var j = 0; j < n; j++) {
10161020
for (var k = 0; k < p; k++) {
@@ -1028,7 +1032,7 @@ function abstractMatrix(superCtor) {
10281032
* @returns {Matrix}
10291033
*/
10301034
transpose() {
1031-
var result = new this.constructor(this.columns, this.rows);
1035+
var result = new this.constructor[Symbol.species](this.columns, this.rows);
10321036
for (var i = 0; i < this.rows; i++) {
10331037
for (var j = 0; j < this.columns; j++) {
10341038
result.set(j, i, this.get(i, j));
@@ -1075,7 +1079,7 @@ function abstractMatrix(superCtor) {
10751079
if ((startRow > endRow) || (startColumn > endColumn) || (startRow < 0) || (startRow >= this.rows) || (endRow < 0) || (endRow >= this.rows) || (startColumn < 0) || (startColumn >= this.columns) || (endColumn < 0) || (endColumn >= this.columns)) {
10761080
throw new RangeError('Argument out of range');
10771081
}
1078-
var newMatrix = new this.constructor(endRow - startRow + 1, endColumn - startColumn + 1);
1082+
var newMatrix = new this.constructor[Symbol.species](endRow - startRow + 1, endColumn - startColumn + 1);
10791083
for (var i = startRow; i <= endRow; i++) {
10801084
for (var j = startColumn; j <= endColumn; j++) {
10811085
newMatrix[i - startRow][j - startColumn] = this.get(i, j);
@@ -1098,7 +1102,7 @@ function abstractMatrix(superCtor) {
10981102
throw new RangeError('Argument out of range');
10991103
}
11001104

1101-
var newMatrix = new this.constructor(indices.length, endColumn - startColumn + 1);
1105+
var newMatrix = new this.constructor[Symbol.species](indices.length, endColumn - startColumn + 1);
11021106
for (var i = 0; i < indices.length; i++) {
11031107
for (var j = startColumn; j <= endColumn; j++) {
11041108
if (indices[i] < 0 || indices[i] >= this.rows) {
@@ -1124,7 +1128,7 @@ function abstractMatrix(superCtor) {
11241128
throw new RangeError('Argument out of range');
11251129
}
11261130

1127-
var newMatrix = new this.constructor(endRow - startRow + 1, indices.length);
1131+
var newMatrix = new this.constructor[Symbol.species](endRow - startRow + 1, indices.length);
11281132
for (var i = 0; i < indices.length; i++) {
11291133
for (var j = startRow; j <= endRow; j++) {
11301134
if (indices[i] < 0 || indices[i] >= this.columns) {

src/matrix.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
'use strict';
22

3+
require('./symbol-species');
34
var abstractMatrix = require('./abstractMatrix');
45
var util = require('./util');
56

67
class Matrix extends abstractMatrix(Array) {
78
constructor(nRows, nColumns) {
9+
if (arguments.length === 1 && typeof nRows === 'number') {
10+
return new Array(nRows);
11+
}
812
if (Matrix.isMatrix(nRows)) {
913
return nRows.clone();
1014
} else if (Number.isInteger(nRows) && nRows > 0) { // Create an empty matrix
@@ -37,11 +41,6 @@ class Matrix extends abstractMatrix(Array) {
3741
this.columns = nColumns;
3842
}
3943

40-
// Native array methods should return instances of Array, not Matrix
41-
static get [Symbol.species]() {
42-
return Array;
43-
}
44-
4544
set(rowIndex, columnIndex, value) {
4645
this[rowIndex][columnIndex] = value;
4746
return this;
@@ -56,7 +55,7 @@ class Matrix extends abstractMatrix(Array) {
5655
* @returns {Matrix}
5756
*/
5857
clone() {
59-
var newMatrix = new this.constructor(this.rows, this.columns);
58+
var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns);
6059
for (var row = 0; row < this.rows; row++) {
6160
for (var column = 0; column < this.columns; column++) {
6261
newMatrix.set(row, column, this.get(row, column));

src/symbol-species.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
if (!Symbol.species) {
4+
Symbol.species = Symbol.for('@@species');
5+
}

src/views/base.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
var abstractMatrix = require('../abstractMatrix');
4+
var Matrix;
45

56
class BaseView extends abstractMatrix() {
67
constructor(matrix, rows, columns) {
@@ -9,6 +10,13 @@ class BaseView extends abstractMatrix() {
910
this.rows = rows;
1011
this.columns = columns;
1112
}
13+
14+
static get [Symbol.species]() {
15+
if (!Matrix) {
16+
Matrix = require('../matrix');
17+
}
18+
return Matrix;
19+
}
1220
}
1321

1422
module.exports = BaseView;

0 commit comments

Comments
 (0)