'eval() confusing two minuses `--` with decrement operator
Let me just start by saying I know using eval() is considered bad practice, but I'm using it on an application that's purely client-based, so no DBs and backends. I'm using it just for evaluating mathematical expressions.
Say I have this string which has been stripped from spaces from the beginning: "1-(2-3)". If you call eval() with it you get eval("1-(2-3)") == 1-(-1) == 2.
But here's the catch. For some complex reasons (which are irrelevant to this question), I have to evaluate the parenthesis first and replace the parenthesis with its evaluated value. So I will get the string "1--1". But if I call eval like this: eval("1--1"), it will interpret -- as an decrement operation and I get the error
Uncaught SyntaxError: Invalid left-hand side expression in postfix operation
For example,
const input = "1-(2-3)"
const str = input.replace("(2-3)", eval("(2-3)"))
console.log(str) // "1--1"
const result = eval(str) // Here things go wrong. Eval parses `--` as the decrement operator.
console.log(result)
I know this isn't a fault of eval, it's meant to evaluate general code, not just mathematical expressions, but how can I get around this?
Solution 1:[1]
Actually, I thought about it and the simplest solution is probably just using String.prototype.replaceAll() to replace all occurrences of -- to - -.
const input = "1-(2-3)"
let str = input.replace("(2-3)", eval("(2-3)"))
console.log(str) // "1--1"
str = str.replaceAll('--', '- -')
const result = eval(str)
console.log(result) // 2
Solution 2:[2]
another option is you can just wrap eval in
let str = input.replace("(2-3)", eval("(2-3)")) with parenthesis to make it let str = input.replace("(2-3)", "(${eval("(2-3)")})"). That would be the quickest workaround fort this particular problem. But different ones may arise.
As Sharjeel mentioned, BODMAS is important, but another hint is:
You can look into Reverse Polish Notation as this way of taking down complex equations is the way computers think basically. It will help you understand how to properly calculate longer expressions and will make your mechanism ready for different problems you may face with current version
Solution 3:[3]
You could pad with space for every nested expression before you add the value to the outer string.
x = '-1';
r = eval('1-' + ` ${x} `);
Solution 4:[4]
Try this
const input = "1-(2-3)"
const str = input.replace("2-3", eval("2-3")) // Don't include the paranthesis in the value to be replaced, because it will create an expression that would be mathematically incorrectl
console.log(str)
const result = eval(str)
console.log(result)
There's no special problem with your code or your concepts. You just need a little bit of knowledge of the Mathematics BODMAS rule which in different places is also known as the PEMDAS or DMAS rule.
What is BODMAS?
BODMAS is an acronym to help children remember the order of mathematical operations – the correct order in which to solve maths problems.
Bodmas stands for B-Brackets, O-Orders (powers/indices or roots), D-Division, M-Multiplication, A-Addition, and S-Subtraction.
Since the question is only relevant to the coding practice, I'm not going to explain this mathematical concept here but you can read about it in the given below reference.
https://thirdspacelearning.com/blog/what-is-bodmas/#:~:text=What%20is%20the%20BODMAS%20rule
Solution 5:[5]
Alternative to @SharjeelFaiq 's answer.
You can add parenthesis in the replace method
const input = "1-(2-3)"
const str = input.replace("(2-3)", `(${eval(1-3)})`)
console.log(str) //now str is 1-(-1)
const result = eval(str)
console.log(result)
Suggestion - same code with less line of code
const input = "1-(2-3)"
const finalResult = eval(input.replace("(2-3)", `(${eval(1-3)})`))
console.log(finalResult) // "1--1"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nermin |
| Solution 2 | waszqba |
| Solution 3 | Nina Scholz |
| Solution 4 | |
| Solution 5 |
