EvalEx 0.1.0
dotnet add package EvalEx --version 0.1.0
NuGet\Install-Package EvalEx -Version 0.1.0
<PackageReference Include="EvalEx" Version="0.1.0" />
paket add EvalEx --version 0.1.0
#r "nuget: EvalEx, 0.1.0"
// Install EvalEx as a Cake Addin #addin nuget:?package=EvalEx&version=0.1.0 // Install EvalEx as a Cake Tool #tool nuget:?package=EvalEx&version=0.1.0
EvalEx -- Expression Evaluator
EvalEx is a simple yet powerful expression evaluator written in C# and provided as a class library. EvalEx extensively supports double
-based calculations, and has a limited support for double[]
, string
, integer (as long
data types) and JSON objects, using the Newtonsoft library.
EvalEx can be extended adding new functions and even operators.
This project initially started porting to C# the EvalEx Java project by Udo Klimaschewski (thanks 🙏).
Basic Usage
using EvalEx;
Expression e = new Expression();
e.SetIntVariable("A", 10);
e.SetIntVariable("a", 20);
long result = e.EvalInt("a+A"); // -> 30
Variables
Basic variables data types are double
, double[]
and string
. JSON objects are basically handled as strings, and converted to JSON only when a JSON properties or JSON Path expressions are used.
Variables are added to expression instances and a name is assigned. Note that variable names are case sensitive.
using EvalEx;
Expression e = new Expression();
e.SetDoubleVariable("d", 123.45d);
e.SetArrayVariable("a", new double[] { 12.1d, 23.2d, 34.3d });
e.SetStringVariable("s", "Hello World!");
e.SetStringVariable("s", "{ \"key\" : 123 }");
Functions
Functions can be added as C# classes, extending the Function
or LazyFunction
(for lazily evaluated functions) class
protected class TestSum : Function
{
public TestSum() : base("TESTSUM", 2) { }
public override double Eval(List<double> parameters)
{
return parameters[0] + parameters[1];
}
}
...
e.AddFunction(new TestSum());
or using the DynaFunction
class, using a specific syntax
FUNCTION(param1: [type], param2: [type], ...): [return type] => [function]
[type]
can be one of Float, Int, String.
DynaFunction d = new DynaFunction("PITAGORA(leg1: Float, leg2: Float): Float => SQRT( leg1^2 + leg2^2 )");
expression.AddLazyFunction(d.AsLazyFunction());
Expression Break
Sometimes, you may want to inform your application that a particular expression should not return a value. In such cases, you can use the IFBRK(check, result)
function. This function returns result
if check
returns a true (!= 0) value, otherwise throws an ExpressionBreakException
e.EvalDouble("IFBRK(3<5, 1.0)"); // returns 1.0 (double
e.EvalDouble("IFBRK(3>5, 1.0)"); // throws ExpressionBreakException
Arrays, map and reduce
EvalEx offers a basic array support (see "Builtin Functions" for more informations), and depending on the use cases, you'll probably want to write your own functions to handle with them. Nevertheless, there are two operators to work with arrays: map ($
) and reduce (@
).
Map iteratively invokes a function that takes at least one parameter on any element of the array and returns a "mutated" version of the array.
Reduce invokes a function that takes at least two parameters passing the first two elements of the array as arguments, and then iteratively invokes the same functions passing as first argument the result of the preceding computation, and the next element of the array as second argument.
Suppose you have declared in your expression two functions "SQUARE(x)" defined as x^2
, and "SUM(a,b)" defined as a+b
.
double[] arr = new double[] { 1d, 3d, 5d };
expression.EvalArray("$SQUARE(arr)")); // returns { 1d, 9d, 25d }
expression.EvalInt("@SUM(arr)")); // returns (1+3)+5 => 9
CachingExpression
If you plan to evaluate the same function in a loop, and the function might be computational intensive, you can use the CachingExpression
class, superclass of Expression
, that caches a signature of the expression and returns a cached value of it.
Expressions showcase
Simple numeric expressions
"5+3" -> 8
"SIN(PI)" -> 0
"x^3" -> 8 (x = 2)
"3^x" -> 9
"81^0.75" -> 27
IF
IF
function is always lazily evaluated
IF(3<5, 1, 3/0); // returns 1, does not throw a division by zero
Scientific Notation
Supported with both uppercase or lowercase E
.
e.EvalInt("123.4567E4"); /// 1234567 (long)
e.EvalDouble("1e-10"); // 0.0000000001d (double)
JSON
Simple JSON properties access can be inlined using dot notation
e.SetStringVariable("jj", @"{'adouble':123.45d,'aint':37, 'anested': { 'nstring': 'hello world' } }");
e.EvalInt("jj.aint"); // 37
e.EvalString("jj.nested.nstring"); // "hello world"
more complex JSON Path expressions can be put inside double quotes
expression.EvalInt("bigjson.\"$.Manufacturers[?(@.Name == 'Acme Co')].Products[0].Price\"")); // 50
// if multiple values are returned, double or double[] values, they will be merged:
expression.EvalArray("bigjson.\"$..Products[?(@.Price >= 50)].Deps\"")); // { 1, 3, 5, 2, 4, 6 }
Builtins
Operators
Double-based Operators
Arithmetic operators +
, -
, *
, /
, modulus %
, and power ^
operator.
Unary +
and -
operators.
Logical operators and &&
, or ||
and not !
.
Equal to =
, greater than >
, less than <
, greater-or-equal-to >=
, less-than-or-equal-to <=
, different than <>
operators. Notice that a boolean false value is 0.0d
, while any other double value is considered as true
; logical true is returned as 1.0d
.
String Operators
Concatenation %%
, concatenation with a blank in between ++
(e.g. "hello"++"world"
⇒ "hello world"
), concatenation with a blank-plus-blank sequence +++
(e.g. "hello"+++"world"
⇒ "hello + world"
).
String comparison, equal ==
and different !=
(notice that strings are trimmed via .Trim()
method before being compared!
String length comparison, longer than >>
and shorter than <<
(notice that strings are trimmed via .Trim()
method before being compared!
Functions
IF
evaluates the first argument and, if it represents a truth value, the second argument is evaluated and returned, the second otherwise.
IFBRK
evaluates the first argument and, if it represents a truth value, the argument is evaluated and returned, otherwise an ExpressionBreakException
is raised.
Double-based Functions
NOT
returns the logical negation of the double argument.
RANDOM
returns a random number between 0 (inclusive) and 1 (exclusive).
Trigonometric functions SIN
, COS
, TAN
, ASIN
, ACOS
, ATAN
, argument is an angle measured in radians.
RAD
converts degrees to radians, and DEG
converts an radians to degrees.
MAX
, MIN
, AVG
return the maximum, the minimum and the average of the provided double arguments.
ABS
returns the absolute value.
LN
and LOG
return the natural (base e
) logarithm.
SQRT
returns the square root of the argument.
ROUND
, returns the rounded (0.5 based) double value of the argument
FLOOR
returns the greatest integer value lower than or equal to the argument.
CEIL
returns the lowest integer value greater than or equal to the argument.
Array-based Functions
JOIN
returns an array that is the concatenation of the arguments; if an argument is a double, it's treated as a single-value array.
SORT
returns an array that contains a concatenation of the arguments, sorted in ascending order.
String-based Functions
CONCAT
returns the strings joined (just like the %%
operator, but with multiple arguments).
STRLEN
returns the length of the string (not trimmed).
STRCMP
compares the first string argument with all the other arguments and returns true or false.
STRICMP
same as STRCMP
, but ignoring case (case insensitive).
IN
returns true if the first argument as a string is equal to one of the other arguments
Constants
e
the base of the natural logarithms, aka the Napier's constant
PI
the greek-pi
NaN
a placeholder for the double "Not a Number" constant
null
same as NaN
TRUE
is 1.0d
FALSE
is 0.0d
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Newtonsoft.Json (>= 12.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.1.0 | 585 | 4/30/2020 |