I have been using XojoScript in one of my projects to evaluate expressions of user-entered variables.
For Instance after defining NumCars = 20 and SeatsPerCar = 6 the user can enter an expression like NumCars * SeatsPerCar and the app evaluates the result as 120.
This has been working great using code based on the XojoScript Evaluator example. In my app, I build up XojoScript source code like this:
dim NumCars as double = 20
dim SeatsPerCar as double = 6
dim result as double = NumCars * SeatsPerCar
This works well until the user enters a large number of variables and a large number of expressions, then the app slows down to a crawl. This happens because I am compiling and running the XojoScript once for each expression to be evaluated.
What I cant seem to figure out is how to compile and run the XojoScript once, and have it iterate through the expressions using the same set of compiled variables. All my efforts have encountered the same issue: the parsing and evaluation of the expression only happens once on compilation. Iterating through expressions at runtime hasn’t worked because the expression strings are not parsed as code.
Is there something obvious Im missing here? Can anyone suggest a direction I can take to speed up this process? Fully willing to SMH.
There are a number of ways to handle this, but the best method will depend on the details of your application.
Do you intend to change just the values of variables NumCars and SeatsPerCar, or do you want to be able to change the expression too?
The variable names can remain the same for each run, but can change from run to run. I need to loop through a long list of expressions for each run.
Sorry, maybe I wasn’t clear. The expressions and variables could both change from run to run.
I still don’t completely follow what you are doing, but the most general approach (though not the fastest) is simply to set up the call to your xojoscript inside a loop, and each time through the loop change the xojo source code to suit the changed variable values and expression. Then you need to compile and run the script each time through the loop.
Again, there may be more efficient methods, depending on the exact details of your application
If the expression remains the same and you are only changing variable values, then you could have the values assigned to arrays, and then have the loop inside the xojoscript. This would run much faster, but would not handle a different expression per iteration.
Thanks, Robert. That’s what I have been doing, and I can attest that it’s not the fastest!
Basically, what I’m doing is like the calculation of a spreadsheet. Each time I calculate the sheet, I need to loop through all the expressions using a fixed set of variables. The variable list will not change during the loop across the expressions. That’s why I want to be able to compile the variables once since there may be hundreds of variables and hundreds of expressions.
I’m wondering if a XojoScript can be the context to another XojoScript which when precompiled can give me access to a fixed set of compiled variables? Hmmm.
You could set up the xojoscript code something like this:
dim NumCars() as double = array(10,20,30)
dim SeatsPerCar() as double = array(2,4,6)
dim result(,) as double
for i as integer = 0 to n
for j as integer = 0 to s
result(i,j) = NumCars(i) * SeatsPerCar(j)
Each unique expression would have to be implemented as additional source code, but you could put it all inline so that the xojoscript only needs to be compiled once.
since the issue is the compile speed per run of the script you write is it possible to NOT run it once per expression ?
could you write ONE giant script compile it and get each result out as needed instead of running one script iteration per “cell” ?
For a spreadsheet kind of application where the user may be constantly entering and changing expressions, you may want to have a look at the ExpressionEvaluator class that I wrote last year. It’s an open source project that doesn’t use xojoscript. It parses the expressions as the user enters them, and these can then be evaluated later in a loop as required. The evaluation speed won’t be as fast as you could get with xojoscript, but you will avoid the xojoscript compile time which appears to be significant in your case. The ExpressionEvaluator class can typically evaluate over 1200 expressions/second, depending on expression complexity and hardware speed. I use this class in a non-linear solver project which evaluates user entered expressions many thousands of times per run.
Thanks for the input. I’m taking these suggestions and trying for a solution.
Robert’s non-xojoscript approach is a possibility that I will investigate if the XojoScript angle ultimately fails.
I think the all in one script could work, although I foresee issues with being able to identify a syntax error on a specific expression since they are all lumped in on one script. I think that if an error is encountered, it may stop the entire script. I’ll try to work in Try/Catch clauses but how to identify which expression caused the error is still unclear.
Thanks for the insight!
I’m too sleepy at the moment to point you to the detailed info, but there are xojoscript compile time features that will flag the line number in your xojoscript where syntax errors occur. So, you could use that to identify the syntax errors in specific user entered formulas.