josdejong / mathjs

An extensive math library for JavaScript and Node.js
https://mathjs.org
Apache License 2.0
14.39k stars 1.24k forks source link

Allow adding units after a unit conversion #1305

Open zcohan opened 6 years ago

zcohan commented 6 years ago

I'm not sure if this is a bug report or feature request, but I'd like the following to work if possible:

10 km in meters + 100 meters //this is an error, 'Parameter x contains a unit with undefined value'
(10 km in meters) + 100 meters //this works fine

'10 km in meters' produces a result in meters, so I'd expect to be able to add more meters to it without bracketing. But I guess there's a precedence issue.

ericman314 commented 6 years ago

Yes, I believe it is due to the precedence of in (or equivalently, to). I've ran into the same problem myself when I've used this library for doing engineering. The problem is that it gets parsed as:

(10 km) in (meters + 100 meters)

Which is obviously not what you want.

What if the precedence of in was higher than addition and multiplication? Then it would be:

10 (km in meters) + 100 meters 10 (1000 meters) + 100 meters 10100 meters

That works, but take this example:

10 miles + 10 km in meters 10 miles + 10 (km in meters) 10 miles + 10000 meters

The conversion is lost inside the evaluation, and now the result might be displayed in miles instead of meters.

What if we could somehow make in have equal precedence as multiplication? That might work, but at the time we introduced units, having lower precedence made a lot of sense for these reasons.

Maybe there is a way to adjust the parser so that when it encounters the in or to keywords, it also consumes the very next token as the unit to convert to. If the next token is not a unit, it will throw an error. The one exception is in, wherein if the next token is not a unit, it is interpreted as being identical to the unit inch. In effect, the string 'in meters' would be consumed as a single token, a postfix operator of low precedence that converts the node before it to meters. Not sure if that is a good idea, or even possible.

josdejong commented 6 years ago

Thanks for your clear explanation @ericman314 . I'm afraid that there is no silver bullet here: no matter which precedence you give to in, there are cases where it does not give the most intuitive interpretation. I guess the best solution is simply to use parentheses in such cases.

ericman314 commented 6 years ago

Right, I completely agree. But do you think my last suggestion would work?

Maybe there is a way to adjust the parser so that when it encounters the in or to keywords, it also consumes the very next token as the unit to convert to.... In effect, the string 'in meters' would be consumed as a single token, a postfix operator of low precedence that converts the node before it to meters.

zcohan commented 6 years ago

Thanks for your clear explanation @ericman314 . I'm afraid that there is no silver bullet here: no matter which precedence you give to in, there are cases where it does not give the most intuitive interpretation. I guess the best solution is simply to use parentheses in such cases.

Yeah, fair enough.

josdejong commented 6 years ago

@ericman314 ah, that's a smart idea! That would solve these edge cases. I cannot really think of any disadvantages of this approach, and it sounds not quite straight forward to implement.