-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow implicit multiplication of multiple single-character variables #2236
Comments
I don't think this is obvious at all in a “programming setting”. For example Mathematica would treat it as one symbol called |
I'm grading answers to math problems. I'd like users to be able to input the math using as natural an expression language as possible. From a user experience perspective, I need things like |
That sounds like a very interesting use case, thanks for the explanation! I think that whether this feature should be added to mathjs boils down to whether we want the parser to be more like Mathematica (an actual programming language) or like Wolfram Alpha (a heuristic-based expression parsing engine). @josdejong What is your vision regarding the parser? However, even if we decided to support it, there's still a problem: the scope is unknown at parse time. It is, by design, only known once you either execute or compile it. Therefore, with the current design, we'd have to implement the heuristic “at runtime” (ie. when fetching parameters from the scope), we couldn't do it “at compile time” (ie. when parsing). One of the side-effects of this would be that I think that a better solution (both for your use case and for the math.js library) would be to add a support for visitors. Visitors are a common feature in syntax tree systems, but they're either missing from math.js, or they are undocumented. The code could look something like this: function visitor(node) {
if (isSymbolNode(node) && node.name.length > 1) {
const multiplicands = [...node.name].map( x => new math.SymbolNode(x) )
return new math.OperatorNode('*', 'multiply', multiplicands, true)
}
return node
}
const standardizedTree = parse(expr).visit(visitor) @josdejong Can something like this be already achieved in the current math.js? |
@m93a I think you sum up the situation well. Your |
Interesting discussion, thanks @joshhansen. Using single-character variables makes sense in mathematical context where you have a handful of variables only, with a sort of "fixed" meaning, so everyone already knows what you mean. So there it makes sense to interpret In general however I think using single character variables is an anti pattern, and it is better to use meaningful, self describing variable names like The expression parser is indeed determining interpreting an expression without looking at the actual values of variables. That makes it's behavior reliable and predictable. It may be interesting to look into taking into account the current scope to try understand the users intention, add heuristics. This can become very complex very soon though (you can look up some of the discussions we had about coming up with a good solution to interpret implicit multiplication in combination with division and units, see #792). In that case I suggest we open a separate topic to think this through, and implement it as a separate version of If you do want to interpret single-character variables, it is quite easy to write either a regular expression replacing function splitSingleVariableNames(node) {
return (node.isSymbolNode && node.name.length > 1)
? new math.FunctionNode('prod', node.name.split('').map(name => new math.SymbolNode(name)))
: node
}
const original = math.parse('4ac')
const transformed = original.transform(splitSingleVariableNames)
console.log(original.toString()) // '4 ac'
console.log(transformed.toString()) // '4 prod(a, c)' |
Closing this for now, can reopen if needed |
The quadratic formula's
4ac
currently parses as a constant4
times a single symbolac
. But it is obvious to anyone familiar with the formula that it represents a constant times symbola
times symbolc
.Enhancing the MathJS expression syntax to allow multiple single-character variables to be implicitly multiplied would make it more closely resemble mathematics as typically used. (Implicit multiplication of multi-character variables doesn't seem to be "allowed":
revenue*units
but notrevenueunits
.)To do this would require the parser to know which variable and function names might be referenced, information presently available only to
compile
andevaluate
.The main issue would be the introduction of ambiguity relative to variable and function names.
For example, with variables
s
,q
,r
, andt
declared, the expressionsqrt(4)
becomes ambiguous as it could either be a series of implicit multiplications or an invocation of the existing functionsqrt
.A simple rule would eliminate the ambiguity: any token that can be understood as a function or variable name in its entirety should be interpreted as such; otherwise implicit multiplication of single-character variables should be considered.
So
sqrt(4)
would be interpreted as square root of four because a functionsqrt
is known to exist, even if variabless
,q
,r
, andt
are also defined and could possibly be interpreted as implicitly multiplied. Butqrt
would be interpreted asq * r * t
because no function or variableqrt
is already known to exist.The restriction to single-character variables is key, as it eliminates one form of ambiguity that arises with multi-character variables. For instance, allowing implicit multiplication of multi-character variables with variables
a
,ab
,bc
, andc
defined leads to two potential parses ofabc
:ab * c
anda * bc
. But with single-character variables only allowed in multiple implicit multiplication, the only possible parse would bea * b * c
, if variablesa
,b
, andc
all exist.It also turns an exhaustive search into a series of table lookups. The implicit multiplication interpretation is possible only if each character in the token is itself defined as a variable.
The text was updated successfully, but these errors were encountered: