Custom and native functions togheter

Topics: General, Help
Feb 14, 2012 at 9:19 PM

Hello sebastienros, excellent work!

I'he a question about how to use custom and native functions thogheter. An example:

Expression e = new Expression("...formula...");
...adding a long list of parameters to e...
e.EvaluateParameter += delegate(string name, ParameterArgs args) {
	args.Result = getMeTheValueOfAParameterNotInExpression(name);
};
e.EvaluateFunction += delegate(string name, FunctionArgs args) {
	args.Result = solveOneOfMyFunctions(name, args);
};

When e.Evaluate() is working:

- if the formula has a parameter in e parameter's list then the value is used

- if the formula has a parameter not in e parameter's list then the EvaluateParameter delegate is used (and calls my getMeTheValueOfAParameterNotInExpression(name) function and use the returned value)

- if the formula has a custom function then the EvaluateFunction delegate is used (and calls my solveOneOfMyFunctions(name, args); function and use the returned value)

- but, if the formula has a native function (like function if) then the EvaluateFunction delegate is used and calls my function for solve the if funcion

 

What can I do for call my function only on custom functions and let NCalc still handling native functions?

There is something that I'm doing wrong?

I apologize for my english, I'm learning it.

I wait for your response.

Thank you very much!

Mar 15, 2012 at 11:50 PM

I have a similar issue.  If I have a custom function anywhere in the formula, normal processing of Parameters does not work

  • "Sqrt(9)" - Works
  • "Sqrt([TEST]) - Works
  • "MyFunc(2, 3, 4, 5)" - Works
  • "MyFunc([TEST2])" - does not trigger e.EvaluateParameter
  • "MyFunc([TEST2]) + [TEST]" - does not trigger e.EvaluateParameter for either parameter

This is going to be a big deal for us. Any chnace this has been addressed in the latest beta?

Coordinator
Mar 15, 2012 at 11:52 PM

Let me try it ...

Coordinator
Mar 15, 2012 at 11:56 PM

In what is this unit test different than your code ?

[TestMethod]
public void ExpressionShouldEvaluateCustomFunctionsWithParameters()
{
    var e = new Expression("SecretOperation([e], 6) + f");
    e.Parameters["e"] = 3;
    e.Parameters["f"] = 1;

    e.EvaluateFunction += delegate(string name, FunctionArgs args)
        {
            if (name == "SecretOperation")
                args.Result = (int)args.Parameters[0].Evaluate() + (int)args.Parameters[1].Evaluate();
        };

    Assert.AreEqual(10, e.Evaluate());
}

Mar 16, 2012 at 2:09 PM

Yes, I am not setting the e.Parameters first.  I am only trying to get a list of parameters in the formula like I mentioned in my post in this thread:

http://ncalc.codeplex.com/discussions/79258

I downloaded the sourcecode, found the unti test you mentioned and if I comment out the 2 e.Parameter setting lines, it will not enter the e.EvaluateFunction delegate just like I am experiencing.

It is very important to the way that we do things to be able to get a list of parameters in the formula.  The parameters reference external data that needs to be queried and loaded prior to evaluating the formula.

 

Mar 16, 2012 at 2:16 PM
Edited Mar 16, 2012 at 3:00 PM

So, I guess another way to look at it is that you can't use both:

e.EvaluateParameter += delegate(string name, ParameterArgs args)
    {
    };

e.EvaluateFunction += delegate(string name, FunctionArgs args) 
    {
    };

In the same Evaluate

I am editing my post to add this test I just tried.  It will hit the args.Result in the EvaluateFunction, but won't hit the args.Result in the EvaluateParameter:

Expression e = new Expression("MyFunc([a]");

e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
    args.Result = random.Next(0, 100);
};

e.EvaluateFunction += delegate(string name, FunctionArgs args)
{
    args.Result = random.Next(0, 100);
};

try
{
    e.Evaluate();
}
catch
{
}


Mar 16, 2012 at 3:47 PM

Found the solution.  I was not calling Evaluate on the parameter from the EvaluateFunction.  This solved it:

Random random = new Random();

Expression e = new Expression(this.Formula, EvaluateOptions.IgnoreCase);

e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
    args.Result = random.Next(0, 100);
};

e.EvaluateFunction += delegate(string name, FunctionArgs args)
{
    foreach (Expression param in args.Parameters)
    {
        param.Evaluate();
    }

    args.Result = random.Next(0, 100);
};

try
{
    e.Evaluate();
}
catch
{
}