nicklockwood / Expression

A cross-platform Swift library for evaluating mathematical expressions at runtime
MIT License
829 stars 51 forks source link

Question: Is implicit multiplication possible with Expression? #47

Open graycampbell opened 1 year ago

graycampbell commented 1 year ago

Is implicit multiplication possible with Expression? I see according to #39 that implicit multiplication is sort of possible using a custom operator for parenthesis, but I haven't seen any indication that implicit multiplication without parenthesis is possible.

For example: try Expression("2 * pi") is valid, but try Expression("2pi") is not.

Using the recommendation in #39, I could add the custom operator for parenthesis, but in my case (a scientific calculator that takes user input), I'd have to parse the input beforehand and intelligently wrap anything that should be implicitly multiplied in parenthesis before passing it to Expression.

So is there any other way to enable implicit multiplication, or will I have to use the recommendation in #39 along with parsing the input separately to intelligently wrap certain parts of the expression in parenthesis?

nicklockwood commented 1 year ago

@graycampbell it's not really possible at the moment I'm afraid. Two consecutive values are treated as an error unless one of them is registered as an operator. It might be possible to fudge it, e.g. by overriding pi with a postfix operator that multiplies the previous value by pi, but I'm not sure if that would work for all of your use cases.

vanniktech commented 1 year ago

I also would like to have this. I've got the constants defined for Euler's number & PI:

        constants: [
            "π": Double.pi,
            "ℇ": Darwin.M_E,
        ],

and would like to have support for 3π.

For Android I use the following library and they support it: https://github.com/ezylang/EvalEx

nicklockwood commented 1 year ago

@vanniktech for that particular use-case, you can define them as postfix operators.

EDIT: I tested and can confirm that this works:

let expression = "2π"

let result = try Expression(
    expression,
    constants: ["π": .pi],
    symbols: [.postfix("π"): { $0[0] * .pi }]
).evaluate()

print(result) // 6.28319
nicklockwood commented 1 year ago

@graycampbell apologies, it seems I misled you! implicit multiplication is possible, at least for some cases. In addition to the solution for implicit multiplication of constants mentioned above (by using a postfix operator), you can also use the "()" operator to implement implicit multiplication of values in parenthesis, like this:

let expression = "4(5)"

let result = try Expression(
    expression,
    symbols: [
        .infix("()"): { $0[0] * $0[1] }
    ]
).evaluate()

print(result) // 20
vanniktech commented 1 year ago

This is amazing! Can be closed from my side.