|
Hello, My custom data type gets a recursion error when putting "add" and "subtract" in the dependencies list in its factory function. I would like to use the core add and subtract functions to work with Units. My guess is it's because I also have a custom "add" and "subtract" for this datatype. Is it possible to use add/subtract without resolving the Dim dependency? Thanks! import { factory } from "mathjs";
import { FORMAT_CONFIG } from "@math/printer";
export const createDimType = factory(
"Dim",
["typed", "typeOf", "format", "config", "add", "subtract"],
({ typed, typeOf, format, config, add, subtract }) => {
class Dim {
constructor(nominal, tolerance, options) {
if (typeOf(nominal) !== typeOf(tolerance)) {
throw new Error(
"Both nominal and tolerance must be of the same type: either numbers or instances of Unit"
);
}
if (typeOf(nominal) === "Unit" && !nominal.equalBase(tolerance)) {
throw new Error(
"Both nominal and tolerance must be of the same unit"
);
}
this.nominal = nominal;
this.tolerance = tolerance;
this.options = options;
if ("isoFit" in options) this.isoFit = this.options["isoFit"];
this.isDim = true;
}
get symmetryString() {
return `${Dim.formatValue(this.nominal)} ± ${Dim.formatValue(this.tolerance)}`;
}
get limitString() {
const usl = add(this.nominal, this.tolerance);
const lsl = subtract(this.nominal, this.tolerance);
return `${Dim.formatValue(lsl)} ${Dim.formatValue(usl)}`;
}
static formatValue(value) {
return format(value, {
precision: config.precision,
...FORMAT_CONFIG,
});
}
toString() {
if (this.isoFit) {
return this.isoFit.print();
}
if (
"printLimit" in this.options &&
this.options["printLimit"] === true
) {
return this.limitString;
}
return this.symmetryString;
}
clone() {
const copy = new Dim(this.nominal, this.tolerance, this.options);
return copy;
}
}
typed.addType({
name: "Dim",
test: (x) => x && x.isDim === true,
});
return Dim;
}
);import { factory } from "mathjs";
export const createAddDim = factory(
"add",
["typed", "Dim"],
({ typed, Dim }) => {
return typed("add", {
"Dim, Dim": typed.referToSelf(
(self) =>
function (a, b) {
return new Dim(
self(a.nominal, b.nominal),
self(a.tolerance, b.tolerance)
);
}
),
});
}
);import { factory } from "mathjs";
export const createSubtractDim = factory(
"subtract",
["typed", "Dim", "add"],
({ typed, Dim, add }) => {
return typed("subtract", {
"Dim, Dim": typed.referToSelf(
(self) =>
function (a, b) {
return new Dim(
self(a.nominal, b.nominal),
add(a.tolerance, b.tolerance),
{ printLimit: true }
);
}
),
});
}
); |
Replies: 2 comments 1 reply
|
Sorry it takes a bit for someone to get to the questions; mathjs is a tad understaffed ;-) The fact that the above code gives a stack size exceeded error rather than a message about the recursion is a bug, so thanks for reporting and I have filed #3439. To your question, though, I can offer two ways to break the circularity. First, if you are OK with the 'nominal' and 'tolerance' properties always/only being mathjs "scalars" (number, BigNumber, bigint, Fraction, Complex, Unit, at the moment), then you can have the Dim factory depend on This prints which is I think what you want. |
|
Second approach: If you want to support Array/Matrix dims, then you can put add and subtract methods in your class definition, and then when extending mathjs add and subtract, just call those methods: This displays which might be useful if you could have vector-valued Hope these examples help. |
Second approach: If you want to support Array/Matrix dims, then you can put add and subtract methods in your class definition, and then when extending mathjs add and subtract, just call those methods: