Call for feedback !

Coordinator
Aug 4, 2009 at 8:13 AM

I would like to hear from you in order to decide which functionalities should be implemented in the next version.

I have already refactored the grammar based on the new ANTLR version, and added Cached trees functionality. Before releasing a beta I would like to take you feedback into account. So please answer to this post to say what you want in NCalc vNext

Aug 5, 2009 at 8:47 AM
Edited Aug 5, 2009 at 9:10 AM

I use NCalc extensively in my application. It hasn't let me down so far and with new version I expect even more.

based on previous discussion I would suggest these features:

1) Global (maybe static ) Switch for making functions case sensitive

2) % function behavior change from module to percent, or at least allow to override standard functions

3) Easier way to introduce new global functions. Let's say i want to add a pluggable library of functions, which I could use as the standard ones you already have in ncalc (Abs, Sin,Cos..). 

4) you could put these and other requests to issue tracker and let people vote on them.

 

Thank you very much for asking our opinion and  for the work done.

 

Huseyn

Sep 8, 2009 at 6:32 AM

I use NCalc often for doing math on each element of arrays - let me say:

Double a[] = new Double[]{1,2,3,4,5};
Double b[] = new Double[]{6,7,8,9,0};

Expression express = new Expression("([a] * [b])^2");
//pseudo: Double c[] = express.Evaluate();

For now I check the parameter array sizes (must be equal) and iterate in the "express.EvaluateParameter += delegate(string name, ParameterArgs arg)" function for each element of a and b. Would be cool if NCalc has an "ArrayMath" option.

Chris

Coordinator
Sep 8, 2009 at 9:20 AM

Hi Chris,

 

I have deployed a new release including this feature. Just add this option: EvaluateOptions.IterateParameters.

Sep 8, 2009 at 7:32 PM

Wow hey cool - this will save me a bunch of lines of code - thanks! I just cant figure out how it works ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Evaluant.Calculator;

namespace NCalcTest2
{
    class Program
    {
        static void Main(string[] args)
        {
            Double[] a = new Double[]{1,2,3,4,5};
            Double[] b = new Double[]{6,7,8,9,0};
            Double c = 3.0;

            Expression e = new Expression("([a] * [b])^c", EvaluateOptions.IterateParameters);
            e.Parameters = new Dictionary<String, Object>();

            e.EvaluateParameter += delegate(String name, ParameterArgs arg)
            {
                if (name.Equals("a"))
                    arg.Result = a;
                if (name.Equals("b"))
                    arg.Result = b;
                if (name.Equals("c"))
                    arg.Result = c;
            };

            
            Object foo = e.Evaluate();
            Console.WriteLine(e.HasErrors().ToString());
            Console.WriteLine(foo.GetType().ToString());

            List<Object> bar = (List<Object>)foo;
            Console.WriteLine(bar.Count);

            foreach (Object o in bar)
            {
                Console.WriteLine(o.ToString());
            }

            Console.ReadKey();
        }
    }
}

 

Console said errors false and lenght of bar is 0. Ok, where I did wrong? ;-)

Thanks
Chris

 

Coordinator
Sep 9, 2009 at 7:08 AM

Actually this is far more simlpler than that:

Expression e = new Expression("([a] * [b]) ^ c", EvaluateOptions.IterateParameters);
e.Parameters["a"] = new int[] { 1, 2, 3, 4, 5 };
e.Parameters["b"] = new int[] { 6, 7, 8, 9, 0 };
e.Parameters["c"] = 3;

foreach (var result in (IList)e.Evaluate())
{
    Console.WriteLine(result);
}

//  216
//  2744
//  13824
//  46656
//  0

Every IEnumerable parameter is projected when IterateParameters option is used. The result of the evaluation is an IList.

If the parameter is not IEnumerable (c in your example), it will will used as it is for every iteration. If the IEnumerable parameters don't have the same number of items, an exception will be thrown.

 

Sep 9, 2009 at 3:57 PM

Note that in this thread and everywhere in the wiki where you mentioned this feature, you've bracketed the IEnumerable parameters, and did not bracket the non-IEnumerable parameter.  This suggests that the bracketing is relevant to the use of IterateParameters  (when I assume it's really just coincidental)

Coordinator
Sep 9, 2009 at 4:02 PM

It's a coincidence, I have copy-pasted some code given by the user who has reported this functionality. I change the documentation right now.

As a reminder, brackets were historically the only way to set parameters in the expression. Now we can also use standard names like x, y, z. But brackets can now be used to defines ambiguous names like [a spaced parameter] or [2].

Sep 9, 2009 at 4:30 PM
Edited Sep 10, 2009 at 5:08 PM

Moved to another tread because its not a features feedback :-)

http://ncalc.codeplex.com/Thread/View.aspx?ThreadId=68544

Sep 18, 2009 at 1:30 PM

Hi Sebastien

Once useful feature I think would be to use 'Cache Providers' so that we can plugin our own caching system (e.g. using ASP.NET cache when using the system in a website).

Let me know if you need more information - and thanks for the project!

Lee

 

Coordinator
Sep 18, 2009 at 2:52 PM

Hi Lee,

You can add your own Cache technique by using the Expression.Compile() method since a few releases, and disable the internal one. Though, I'd like to know a little more information about the reasons behind ? Can you explain a potential scenario of your needs compared to the cached already mplemented ?

Sep 18, 2009 at 3:21 PM
Edited Sep 18, 2009 at 3:44 PM

Hi Sebastien

By using ASP.NET's cache, it would allow management of the members of the cache - e.g. expire if not used within a certain amount of time, etc. This would mean that you wouldn't have to implement all those features for NCALC's own cache. Of course, not everyone want's to use ncalc in asp.net, but by implementing, say, ICache, each user can plug in their own (or use one created by someone else).

Lee

-----Original Message-----
From: sebastienros
Sent: 9/18/2009 1:52:10 PM
To: [email removed]
Subject: Re: Call for feedback ! [ncalc:64384]

From: sebastienros

Hi Lee,

You can add your own Cache technique by using the Expression.Compile() method since a few releases, and disable the internal one. Though, I'd like to know a little more information about the reasons behind ? Can you explain a potential scenario of your needs compared to the cached already mplemented ?

Coordinator
Sep 18, 2009 at 4:52 PM

The cache only contains the abstract tree of the expression. It means if you have "3 * x + y", the cache nows only that x and y are needed, but not the value. If you clear the cache, the next compilation will be exactly the same abstract tree result: + ( * ( 3, x ) , y ). When calling Evaluate(), this tree is taken from the cache and then only the parameters' value are resolved. If you create another Expression instance with the same text, the abstract tree will be taken from the tree, not doing a useless compilation. In three centuries, the same expression will be evaluated as the same abstract tree ;). So invalidating the cache is not needed.

The only reason to invalidate it is to gain memory, but it's already implemented internally using weak references.

Sep 21, 2009 at 12:05 PM

But lets suppose I'm using this is a long-running system. The system needs to evaluate many different expressions. Some may be identical, but yet some may only be used once. If the cache does not have the ability to remove objects that have not been used, and keep the most regularly-used ones, then eventutally, the cache will use too much memory.

ASP.NET cache has the ability to mange this much better. You could right your own one with the same sophistication, but wouldn't it be better to program to an interface, and let the users to select the implementation (or write their own).

Lee

Jan 20, 2010 at 11:23 PM

This is a great library and we were able to get it running very quickly. Thank you!

I would like to see:

- Support for versions. e.g. 1.2.3.4 < 1.2.4

- Support for .NET Compact Framework

Jason

Mar 13, 2010 at 11:23 PM

Sabastienros,

NCALC really does a great job, I've implemented NCALC in a little irc bot I put together, it was extremely quick and easy.

It would be nice if it included a random function eg: random(upperbounds) and random(lower, upper).

Note: NCALC compiles under .net 4.0 without issue.

Thanks.

 

 

Jun 30, 2010 at 5:47 AM

I found this excellent library, and I know this thread was created for suggestions but cheking the code (and is an old example) by coordinator, if the returned value for the last iteration where the expression is (5 * 0) ^ 3 is 0 then maybe is a bug beacuse the returned result should be 1. (All number pow by 0 is equal to 1).

Am I Wrong?

-----

Actually this is far more simlpler than that:.

Expression e = new Expression("([a] * [b]) ^ c", EvaluateOptions.IterateParameters);
e.Parameters["a"] = new int[] { 1, 2, 3, 4, 5 };
e.Parameters["b"] = new int[] { 6, 7, 8, 9, 0 };
e.Parameters["c"] = 3;

foreach (var result in (IList)e.Evaluate())
{
    Console.WriteLine(result);
}

//  216
//  2744
//  13824
//  46656
//  0
Jun 30, 2010 at 9:34 AM

(5 * 0) ^ 3 = 0 ^ 3 = 0 * 0 * 0 = 0

So the answer is zero

Lee

 

Jul 1, 2010 at 4:29 PM
(All number pow by 0 is equal to 1). ------ Sorry as I said before all number elevated to 0 es equal to 1 but obviously this is not case ... is powed to 3. I don't know where were my head .... :( For a moment I saw a zero instead of three.
Jul 7, 2010 at 2:42 PM

first off...cool code, just what I was looking for!

for a suggestion...

Can we have an option that treats strings values containing only numbers as numbers.

for example if your expression was the string "[value1] + [value2]" and you parameters where value1= the string "100" and value2= the string "50", when you evaluate you will get "10050" not 150

thanks

Moose

Jul 19, 2010 at 8:45 AM

Hello Sebastien,

Thank you for the good library! Is there any effort to make it localizable or to provide the text in a resource? I would appreciate your comment.

Best regards,

José

Mar 28, 2012 at 6:09 PM

Sebastien,

Thanks for the great library.

Feature Request

One feature that would be nice would be to pass in operators as parameters. Let's say I have a particular formula that requires addition in some cases and multiplication in other cases with the rest of the formula staying the same:

((a * b * c) + d) + e

as well as

((a * b * c) + d) * e

It would be nice to instead write a the formula something like this:

(([a] * [b] * [c]) + [d]) [operatorParameter] [e]

Instead I am stuck with:

if( <my condition>, (([a] * [b] * [c]) + [d]) + [e], (([a] * [b] * [c]) + [d]) * [e])

Back-End Expression Processing

As for future development on this project, I have recently been reading about the System.Linq.Expressions namespace and the functionality seems equivalent to much of what this library does (other than the lexer and parser part). In fact there is another open source project that I am considering as an alternative to this one in my project (although right now NCalc is winning because the input expressions can be stored as smaller strings). The project is at:

http://expressiontree.codeplex.com/

Not that you want to take the extra step of serilaizing here, but that project shows the potential.

A good explanation of the expression trees in the framework is in the book "C# in Depth". Listings 9.6 thru 9.10 in Chapter 9 give some examples of how the expressions can be built up and compiled using System.Linq.Expressions.

The expression trees in the System.Linq.Expressions namespace could potentially work as a back end for this and make it easier to add additional functionality to this project in the future. Consider it for version 2.0...

Regards,

NightOwl888