Arguments for user supplied functions

Aug 14, 2008 at 3:39 PM

In the ECalc version on CodeProject (http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx) I could relatively easily add my own functions by defining a delegate like

 private static void e_EvaluateFunction(string name, FunctionArgs args) {
     if (name == "MyFunc1") { args.Result = MyFunc1(args.Parameters); return; }
     if (name == "MyFunc2") { args.Result = MyFunc2(args.Parameters); return; }
 }

and then defining

 private static float MyFunc1(params object[] numbers)
 {
  ...
 }

which was unaware of being used in the ECalc context. Just convert the arguments to floats or whatever C# type and go.
Now the arguments are of type Evaluant.Calculator.Expression and this no longer works. In my function I have to repeat the whole handling of Parameters etc again for each argument.

Was the old way not better or is there an alternative now?

Tx,

Andriks

Coordinator
Aug 14, 2008 at 5:12 PM
Hi Andriks,

I have found the reason and the alternative. Actually I made this change as the if() function didn't work. Let me explain:

The mistake was that the if(a, b, c) function should return "b" if "a" is true, and "c" otherwise. This function is often used when testing divisions by zeeo. For instance, if([x] != 0, 16/[x], 0).
Now imagine [x] is 0. If NCalc was evaluating all parameters, we would always have the exception, before the real if() behaviour is called. Thus this is to the if() function to define when each parameters as to be called, and that's why external functions get Expression instances. Because this could be also you case.

Though, in your case you prefer to have the pre-evaluated values. I've just implemented a solution for this case. I'll create a release later, but you can already use this technique inside you delegate:

public object[] EvaluateParameters()

{

    object[] values = new object[parameters.Length];

    for (int i = 0; i < values.Length; i++)

    {

        values[i] = parameters[i].Evaluate();

    }

 

    return values;

}

This method is now added to FunctionArgs. In the meantime you can add it as a static one inside your code and to take your example have this:

 private static void e_EvaluateFunction(string name, FunctionArgs args) {
     if (name == "MyFunc1") { args.Result = MyFunc1(EvaluateParameters(args.Parameters)); return; }
     if (name == "MyFunc2") { args.Result = MyFunc2(EvaluateParameters(args.Parameters)); return; }
 }

Hope this helps,

Sébastien

Aug 18, 2008 at 12:27 PM
Hi Sébastien,

I see your point. Indeed if you use the IF function it is handy not to have all arguments evaluated beforehand ;-)

I can live with the EvaluateParameters function and it's use.

Thank you,

Andriks