Parameters in custom functions

Mar 4, 2009 at 6:53 PM
Hi Sébastien,

I'm using your framework for an internal project and I'm very happy with it.

I just have one question:

I created a custom function, and inside that fucntion, I want to know its parameter's name.

I get all registered parameters but not the function parameters.

Suppose this expression: 

Expression expression = new Expression("MyFunction(p1) + p2 + p3 + p4 + p5");

So I have to register them:

expression.Parameter["p1"] = 1;
expression.Parameter["p2"] = 2;
...

And my custom function:

expression.EvaluateFunction += ...

So, inside my custom function, I can't get the name of its parameter. (Is it p1? p2?)

void MyFunction(FunctionArgs args) {
    Expression ex = args.Parameters[0];
    //what's the name (string) of args.Parameters[0] ??? I need to know in my function...
    //if I try "ex.Parameters" I get ALL registered parameters (p1, p2, p3...)
}

Is there a way to get the string "p1" (in this case) inside my custom function?

Thank you in advance,

André Carlucci
Coordinator
Mar 5, 2009 at 6:42 AM
Edited Mar 5, 2009 at 6:44 AM
Hi André,

There is no way to get the name used as the functions arguments for a really simple reason, parameters don't have names. You are actually using here only one of the several ways to pass values as arguments.

For example, what would be the name of the arguments in this case :

new Expression("MyFunction(1, a, a+b, a+2, Round(a+2))");

1 -> ????
a -> ok ;) what you use
a+b -> ?
a+2 -> ?
...

You see, we can have very complex stuff in function's arguments, so we can't define a name for this.

Function can just get the values or expressions passed as arguments. And they can just access these values. Exactly like normal C# methods, in such you know the values, not the name of the parameter that was used to set it.

Watch this example:

public void MyFunction(object a, object b)
{
  // do stuf
}

If I call it like that:

var myName = 5;
MyFunction(1+2, myName);

Do you think you can get "myName" frrom MyFunction ? If you have the answer for C# you have the answer for NCalc.

You should really think about arguments as a defined number of ordered values to process a function, simply.

Moreover, I have checked and in the args.Parameters[] you really get only the arguments in the so called function. If not please send me a working example.

Cheers,
Sébastien
Mar 6, 2009 at 12:43 PM

Hi Sébastien,

Thanks a lot for your quick answer. You are totally right.

In fact, sorry about my dumb question, I should have thought 10s before impulsively posting ;)

Anyway, I would like to suggest some features to NCalc. See if you like:

- A public method for equation parsing (returns bool).
Sometimes it's good know if the expression is correct before executing it (it saves a lot of execution time!).

- A public getter (string) for the parsedExpression when on custom functions
I'm using complex functions as user supplied functions and some of them are very slow. To speed things up, I would like to cache some results (it makes sense only in some cases). To do that, I need the context. Ex:

MyFunction(OtherFunction(a + b * 3, c) + 1)

When executing "OtherFunction", I would like to have the access to the strings "a + b * 3" and "c". It's there already, but the property parsedExpression is protected.

- Replace existing functions
I would like to change the behavior, number of parameters, etc.. of the the existing functions. Ex: write my own Sum or Max function or simply remove them.

Well, that's it. Thanks a lot for this great project.

Cheers,
André

Mar 31, 2009 at 10:05 AM
Hi guys,
Sébastien thanks for good work.

i join André in his feature requests:


- A public method for equation parsing (returns bool).

This is must have for GUI usage. For example I do excel like application, I would like to validate formula before accepting it.
What I do in this case, is to run normal formula execution via Evaluate wrapped in try-except block. What would be nice, is to have a function for example Validate, which would work exactly like Evaluate, but would not raise exceptions and return true/false.

Other 2 requests are also valid ones.

Also i would like to ask for one more feature.

As I understand most of the time is taken by parsing of the formula.
What often people have are similar formulas with different parameters. So what would be nice if one could do the following:

      var exp = new Expression(formula);

       exp.EvaluateParameter += delegate(string name, ParameterArgs args, Object externalParameter )
            {              
                args.Result = (myType) externalParameter.getMember(name);
            };

   for (int i = 0; i < similarObjectsList.Length; i++)
        {
          myType val=similarObjectsList[i];
          val.Answer=exp.Evaluate(val)
      }

Basically be able, to parse the same formula, against different objects.
This way formula could be parsed once and reused for many times.

Thanks.
Huseyn