DynamicExpresso.SetFunction not working with method overload - c#

I'm using Dynamic Expresso for expression evaluation and works like a charm. Actually setting up custom functions, but seems like there is a something wrong with a method overload.
I've actually got two Round methods:
First one with one argument:
public static decimal Round(decimal userNumber)
{
return Math.Round(userNumber);
}
Second one with two arguments:
public static decimal Round(decimal userNumber, int decimals)
{
return Math.Round(userNumber, decimals);
}
Delegates got declared and Interpreter.SetFunction is called with no errors as well:
Func<decimal, decimal> roundFunction1 = (userNumber) => Round(userNumber);
Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Round(userNumber, decimals);
interpreter.SetFunction("ROUND", roundFunction1);
interpreter.SetFunction("ROUND", roundFunction2);
Variables are correctly passed and I've checked many times already that the parameter I'm passing is, in fact, a decimal.
The evaluation expression I pass, finally contains the following string, which has nothing wrong since the Interpreter.SetVariable(property.Key, property.Value) is inserting an "ImporteTotal" and a 666.66:
ROUND(ImporteTotal)
So, the exception I get when the evaluation gets done is:
Argument list incompatible with delegate expression (at index 0).
Note that I'm actually setting lots of functions which uses even DateTimes, int, strings and so on even combined, overloads as well! All of them work perfectly, but seems that deleting any of those overloads helps it working. In case both of them are "imported" on Dynamic Expresso, it complains.
Any ideas?
Many thanks.
UPDATE-EDIT:
I reviewed the UnitTesting Davide provided through pastebin and seems I got it failing.
This unit testing seems that is failing.
[Test]
public static void TestInterpreter()
{
var interpreter = new Interpreter();
Func<decimal, decimal> roundFunction1 = (userNumber) => Round(userNumber);
Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Round(userNumber, decimals);
Func<string, string, int> charindexFunction1 = (toFind, userString) => Charindex(toFind, userString);
Func<string, string, int, int> charindexFunction2 = (toFind, userString, offset) => Charindex(toFind, userString, offset);
interpreter.SetFunction("ROUND", roundFunction1);
interpreter.SetFunction("ROUND", roundFunction2);
interpreter.SetFunction("CHARINDEX", charindexFunction1);
interpreter.SetFunction("CHARINDEX", charindexFunction2);
var importe = 666.66M;
interpreter.SetVariable("ImporteTotal", importe);
var textoAlbaran = "ALBARAN-01";
interpreter.SetVariable("Albaran", textoAlbaran);
Assert.AreEqual(Round(importe), interpreter.Eval("ROUND(ImporteTotal)"));
Assert.AreEqual(Round(importe, 1), interpreter.Eval("ROUND(ImporteTotal, 1)"));
Assert.AreEqual(Charindex("BARAN", textoAlbaran), interpreter.Eval("CHARINDEX(\"BARAN\", Albaran"));
Assert.AreEqual(Charindex("BARAN", textoAlbaran, 2), interpreter.Eval("CHARINDEX(\"BARAN\", Albaran, 2)"));
}
public static decimal Round(decimal userNumber)
{
return Math.Round(userNumber);
}
public static decimal Round(decimal userNumber, int decimals)
{
return Math.Round(userNumber, decimals);
}
public static int Charindex(string toFind, string userString)
{
return userString.IndexOf(toFind);
}
public static int Charindex(string toFind, string userString, int offset)
{
return userString.IndexOf(toFind, offset);
}

Starting with DynamicExpresso 2.5.0, it's possible to register multiple methods with the same name (ie. overloads):
Func<decimal, decimal> roundFunction1 = (userNumber) => Math.Round(userNumber);
Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Math.Round(userNumber, decimals);
var interpreter = new Interpreter();
interpreter.SetFunction("ROUND", roundFunction1);
interpreter.SetFunction("ROUND", roundFunction2);
Assert.AreEqual(3.13M, interpreter.Eval("ROUND(3.12789M, 2)"));
Assert.AreEqual(3M, interpreter.Eval("ROUND(3.12789M)"));

Related

Is this possible? Specify any generic type as long as the + operation is defined on it

I'm not sure if this is possible, but if it is then it would be useful.
I am attempting to program in a class called Matrix<T>. The intent is to be able to have matrices of various data types, such as integers, floats, doubles, etc.
I now want to define addition:
public static Matrix<T> operator +(Matrix<T> first, Matrix<T> second)
{
if (first.dimension != second.dimension)
{
throw new Exception("The matrices' dimensions do not match");
}
Matrix<T> add = new Matrix<T>(first.dimension);
for (int i = 1; i <= first.rows; i++)
{
for (int j = 1; j <= first.columns; i++)
{
add[i,j] = first[i,j] + second[i,j];
}
}
return add;
}
There is an issue with the line add[i,j] = first[i,j] + second[i,j]; since the operation + is not defined on a general object of type T.
I only want to specify matrices where T is a type such that addition is defined, however. So, I can make a matrix of ints, floats, doubles, etc. but if I were to try and define a matrix of, say, int[]s, I would want this to throw an exception since + is not defined for int[]s.
So, instead of writing T, is there some way of telling the computer "this can take in any generic type, as long as an operator + is defined on the type? Or, is this not possible and I would have to sepeately define a matrix of ints, matrix of floats, and so on?
Edit: I don't see how the linked question from closure is related to this - I see nothing about operators there. If they are related, can somebody explain how?
Currently it is not possible (at least without losing compile time safety or changing the API) but with preview features enabled and System.Runtime.Experimental nuget you can use IAdditionOperators to restrict T to have + operator defined. I would say that adding this interface also to Matrix itself can be a good idea:
class Matrix<T> : IAdditionOperators<Matrix<T>, Matrix<T>, Matrix<T>> where T : IAdditionOperators<T, T, T>
{
public static Matrix<T> operator +(Matrix<T> left, Matrix<T> right)
{
// swap to real implementation here
T x = default;
T y = default;
Console.WriteLine(x + y);
return default;
}
}
See also:
Generic math (especially section about trying it out, note - VS 2022 recommended)
It's possible using reflection
class Int
{
readonly int v;
public int Get => v;
public Int(int v)
{
this.v = v;
}
public static Int operator +(Int me, Int other) => new Int(me.v + other.v);
}
class Arr<T>
{
T[] _arr;
public Arr(T[] arr)
{
_arr = arr;
}
public T this[int index] => _arr[index];
public static Arr<T> operator+(Arr<T> me, Arr<T> other)
{
var addMethod = typeof(T).GetMethod("op_Addition");
if (addMethod == null)
throw new InvalidOperationException($"Type {typeof(T)} doesn't implement '+' operator");
var result = me._arr.Zip(other._arr)
.Select(elements => addMethod.Invoke(null, new object[] { elements.First, elements.Second }))
.Cast<T>()
.ToArray();
return new Arr<T>(result);
}
}
[Test]
public void TestAdd()
{
var firstArray = new Arr<Int>(new[] { new Int(1), new Int(2) });
var secondArray = new Arr<Int>(new[] { new Int(2), new Int(3) });
var sum = firstArray + secondArray;
Assert.AreEqual(3, sum[0].Get);
Assert.AreEqual(5, sum[1].Get);
}
Reduced the example to array.
Unfortunetly it compiles even if T doesn't implement add operator, so you will get a exception in runtime. You could also check if the add method has proper signature (returns T and takes two T's). If you need help understanding the code, let me know!

Code on Func and Action

http://simpleprogrammer.com/2010/09/24/explaining-what-action-and-func-are/
The above code explains in simple terms about Action and Func.
Still I am not getting what it is for 100%. Or not able to make the code work for me.
public void SteamVegetable(Vegetable vegetable, int timeInMinutes)
{
CookVegetable(vegetable, Steam, timeInMinutes);
}
public void FryVegetable(Vegetable vegetable, int timeInMinutes)
{
CookVegetable(vegetable, Fry, timeInMinutes);
}
public void BakeVegetable(Vegetable vegetable, int timeInMinutes)
{
CookVegetable(vegetable, Bake, timeInMinutes);
}
public void CookVegetable(Vegetable vegetable,
Action<Vegetable, CookingTime> cookingAction,
int timeInMinutes)
{
Clean(vegetable);
cookingAction(vegetable, Minutes.Is(timeInMinutes));
Serve(vegetable);
}
Can someone help me to convert the code from vegetable to numbers and Steam --> Addition, Fry --> Multiplication, Bake --> subtraction when two operands are passed to it.
When I see the code working I can understand it better.
In the example you provided, Fry, Steam, and Bake are probably supposed to be methods.
Basically, Actions and Funcs let you pass a chunk of code into a method, then execute that chunk of code.
So, you could do
public void Foo(Action<int> actionToPerform, int someInt)
{
actionToPerform(someInt);
}
Then, you could use the Foo method with any "chunk of code" that takes an integer.
So,
public void Bar()
{
Action<int> writeToConsole = i => { Console.WriteLine(i); }
Action<int> writeToSomeLogger = i => { Logger.WriteLog(i); }
Foo(writeToConsole, 10);
Foo(writeToSomeLogger, 100);
}
I'm going to throw my example in.. I tried to make it simple, so hopefully this helps.
Take this for example:
class MathClass {
public int Add(int number1, int number2) {
return DoSomeMathOperation(number1, number2, theAddingIsActuallyDoneHere); // The method "theAddingIsActuallyDoneHere" below is what gets called.
}
private int theAddingIsActuallyDoneHere(int number1, int number2) {
return number1 + number2;
}
public int Multiply(int number1, int number2) {
return DoSomeMathOperation(number1, number2, theMultiplicationIsDoneHere); // The method "theMultiplicationIsDoneHere" is what gets called.
}
private int theMultiplicationIsDoneHere(int number1, int number2) {
return number1 * number2;
}
public int DoSomeMathOperation(int number1, int number2, Func<int, int, int> mathOperationFunc) {
return mathOperationFunc(number1, number2); // This is where you call the method passed in above.
}
}
The above code, can be used like this:
MathClass mathClass = new MathClass();
Console.WriteLine(mathClass.Add(5, 10)); // displays 15
Console.WriteLine(mathClass.Multiply(5, 5)); // displays 25
Imagine though, that you required a subtraction method. You can create one, via the DoSomeMathOperation function, which expects a Func<int, int, int>, which is a function that "takes 2 integer parameters and returns an integer". This would be implemented as follows:
Console.WriteLine(mathClass.DoSomeMathOperation(100, 50, (num1, num2) => num1 - num2)); // displays "50"
In the above code, you're passing the numbers 100 and 50 into the DoSomeMathOperation method, and those two parameters are being passed into the Func<int, int, int>. The result is then returned.
..hopefully that makes sense..
I might be wrong in understanding what you want, but I'll try to answer it. Note, that I omit many complex things in example, like I would use generics instead of plain int values, but this will just create redundant complexity in the example.
In example below I just define high-order function, which takes two int values, function, that transforms two values into string (i.e. encapsulate some behavior) and them embrace this result into enclosing and opening tags, one of which is passed in. Note, that I assume you are familiar with lambda notation in C#.
ApplyAndPrettyPrint(100, 3, "summ of 100 and 3 is equal to: ", (x,y) => (x*y).ToString("N0"));
ApplyAndPrettyPrint(100, 3, "100 to power 3 is: ", (x,y) => (Math.Pow(x,y)).ToString("N0"));
ApplyAndPrettyPrint(2, 33, "2 * root of 33 is: ", (x,y) => (x * Math.Sqrt(y)).ToString("N0"));
public void ApplyAndPrettyPrint( int firstNumber, int secondNumber, string startTag, Func<int, int, string> evaludationFunction)
{
string result = startTag;
result += evaludationFunction(firstNumber, secondNumber);
result += ";";
Console.WriteLine (result);
}
So that Func here is used like a box, with two integers as input and one string as output.
Second example shows how we can pass Action into method, that will be evaluated over some array of numbers. Again, I omit details of IEnumerable interfaces and generics.
int[] numbers = new []{ 1, 2, 4, 5, 6, 7 };
ApplyForEach(numbers, (x) => Console.WriteLine ("square of {0} is {1}", x, x*x));
public void ApplyForEach(int[] numbers, Action<int> someFunction)
{
foreach (var number in numbers)
{
someFunction(number);
}
}
The result will just print squares of integers with some descriptive chars. In other word Action is delegate with no outputs. You can think of them as box with some inputs, but with no outputs at all.
Hope that this will do the trick for your understanding. The bottom line is that the only difference between delegate types of Action and Func is the semantics of the last generic type: in Func it is the returning value, in Action returning value is void, so last generic type just goes to input parameter.
If you find this topic somewhat difficult, Jon Skeet describes delegates within Chapter 5 "Fast-tracked delegates" in his marvelous book "C# in Depth"

Why my Generic Extension Method says cannot convert from T to ..... or .... to T

Further to my questions
https://stackoverflow.com/questions/10241345/any-percentage-function-in-net
https://stackoverflow.com/questions/9942202/percentage-of-each-element-in-linq
i want to create a generic extension method in .Net 4.0 which will generate percentage of the list items to the sum of the list. This list will be of Numeric types only.
My code is
public static T Percentage<T>(this T array) where T: ? // What should come in place of ?
{
double[] darray = (double[])T; // Error convert type 'T' to 'double[]'
darray = darray.Select(x=> x * 100 / darray.Sum()).ToArray();
return darray; // Error convert type 'double[]' to 'T'
}
I want to call it like
double[] MD = {8.0,21.0,25.0,13.0,26.0,37.0,37.0,33.0,71.0,9.0};
MD = MD.Percentage().ToArray();
What am i doing wrong;
You cannot constrain types by "numeric" values. It is somewhat of a limitation of the framework.
Your best best is to do this:
public static IEnumerable<double> Percentage(this IEnumerable<int> values)
{
var sum = values.Sum();
return values.Select(v => (double)v / (double)sum).ToArray();
}
public static IEnumerable<double> Percentage(this IEnumerable<long> values)
{
var sum = values.Sum();
return values.Select(v => (double)v / (double)sum).ToArray();
}
public static IEnumerable<double> Percentage(this IEnumerable<double> values)
{
var sum = values.Sum();
return values.Select(v => v / sum).ToArray();
}
Essentially you need to produce an overload for each type you want to support.
It is not possible to have constrain of type you want. Check out Constraining a generic type argument to numeric types for details.
Since there are not too many numeric types (int/float/double/decimal) it may be easier to simply provide concrete implementations.
More options
require IConvertable and use IConvertible.ToDouble to perform all math in doubles
use https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html mentioned here C#: Generic Interface for Numbers.
There is an alternative that works, which is to pass in the selector function that allows you to convert to doubles when you call Percentage. This is the extension method:
public static double[] Percentage<T>(this T[] array, Func<T,double> selector)
{
var doubles = array.Select(selector);
var sum = doubles.Sum();
var result = doubles.Select(x => x * 100 / sum).ToArray();
return result;
}
Usage:
double[] MD = {8.0,21.0,25.0,13.0,26.0,37.0,37.0,33.0,71.0,9.0};
var MDPercent = MD.Percentage(x => x).ToArray();
And then you can have a simple double version:
public static double[] Percentage(this double[] array)
{
return Percentage(array, x => x);
}
Or an int version:
public static double[] Percentage(this int[] array)
{
return array.Percentage(x => (double)x);
}
Which are simpler to use:
var MDPercent = MD.Percentage().ToArray();

Cannot use ref or out parameter in lambda expressions

Why can't you use a ref or out parameter in a lambda expression?
I came across the error today and found a workaround but I was still curious why this is a compile-time error.
CS1628: Cannot use in ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression
Here's a simple example:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
Lambdas have the appearance of changing the lifetime of variables that they capture. For instance, the following lambda expression causes the parameter p1 to live longer than the current method frame as its value can be accessed after the method frame is no longer on the stack
Func<int> Example(int p1) {
return () => p1;
}
Another property of captured variables is that changes to the variables are also visible outside the lambda expression. For example, the following code prints out 42
void Example2(int p1) {
Action del = () => { p1 = 42; };
del();
Console.WriteLine(p1);
}
These two properties produce a certain set of effects which fly in the face of a ref parameter in the following ways:
ref parameters may have a fixed lifetime. Consider passing a local variable as a ref parameter to a function.
Side effects in the lambda would need to be visible on the ref parameter itself. Both within the method and in the caller.
These are somewhat incompatible properties and are one of the reasons they are disallowed in lambda expressions.
Under the hood, the anonymous method is implemented by hoisting captured variables (which is what your question body is all about) and storing them as fields of a compiler generated class. There is no way to store a ref or out parameter as a field. Eric Lippert discussed it in a blog entry. Note that there is a difference between captured variables and lambda parameters. You can have "formal parameters" like the following as they are not captured variables:
delegate void TestDelegate (out int x);
static void Main(string[] args)
{
TestDelegate testDel = (out int x) => { x = 10; };
int p;
testDel(out p);
Console.WriteLine(p);
}
You can but you must explicitly define all the types so
(a, b, c, ref d) => {...}
Is invalid, however
(int a, int b, int c, ref int d) => {...}
Is valid
As this is one of the top results for "C# lambda ref" on Google; I feel I need to expand on the above answers. The older (C# 2.0) anonymous delegate syntax works and it does support more complex signatures (as well closures). Lambda's and anonymous delegates at the very least have shared perceived implementation in the compiler backend (if they are not identical) - and most importantly, they support closures.
What I was trying to do when I did the search, to demonstrate the syntax:
public static ScanOperation<TToken> CreateScanOperation(
PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
return delegate(string text, ref int position, ref PositionInformation currentPosition)
{
var token = oldScanOperation(text, ref position, ref currentPosition);
if (token == null)
return null;
if (tokenDefinition.LeftDenotation != null)
token._led = tokenDefinition.LeftDenotation(token);
if (tokenDefinition.NullDenotation != null)
token._nud = tokenDefinition.NullDenotation(token);
token.Identifier = tokenDefinition.Identifier;
token.LeftBindingPower = tokenDefinition.LeftBindingPower;
token.OnInitialize();
return token;
};
}
Just keep in mind that Lambdas are procedurally and mathematically safer (because of the ref value promotion mentioned earlier): you might open a can of worms. Think carefully when using this syntax.
And maybe this?
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
var val = value;
int newValue = array.Where(a => a == val).First();
}
You can not use an out parameter directly in a lambda expression. The reason why you can not do that is explained in the other answers.
Workaround
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
private static int OuterFunc (int i_param1, out int o_param2)
{
int param2 = 0;
var del = () => InnerFunc (i_param1, out param2);
int result = del ();
o_param2 = param2;
return result;
}
private static int InnerFunc (int i_param1, out int o_param2)
{
o_param2 = i_param1;
return i_param1;
}
private static void Main (string[] args)
{
int result = OuterFunc (123, out int param2);
Console.WriteLine (result); // prints '123'
Console.WriteLine (param2); // prints '123'
}
Please note
The question was created in 2009. My answer was created in 2023 using C#10 and .NET 6. I don't know whether this answer had also worked back in 2009, which means, the code here might depend on enhancements to C# and .NET that might have been made in the meantime.
I will give you another example.
Description
The code below will throw out this error. Because the change brought by the lambda expression (i)=>{...} only works in the function test.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
Solution
So, if you remove out of the parameter, it works.
static void test(System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
If you need out really, don't change the parameter in the lambda expression directly. Instead, use a temporary variable please.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
System.Drawing.Image[] bitmapsTemp = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmapsTemp[i] = System.Drawing.Image.FromFile("2.bmp");
});
bitmaps = bitmapsTemp;
}

Explanation of Func

I was wondering if someone could explain what Func<int, string> is and how it is used with some clear examples.
Are you familiar with delegates in general? I have a page about delegates and events which may help if not, although it's more geared towards explaining the differences between the two.
Func<T, TResult> is just a generic delegate - work out what it means in any particular situation by replacing the type parameters (T and TResult) with the corresponding type arguments (int and string) in the declaration. I've also renamed it to avoid confusion:
string ExpandedFunc(int x)
In other words, Func<int, string> is a delegate which represents a function taking an int argument and returning a string.
Func<T, TResult> is often used in LINQ, both for projections and predicates (in the latter case, TResult is always bool). For example, you could use a Func<int, string> to project a sequence of integers into a sequence of strings. Lambda expressions are usually used in LINQ to create the relevant delegates:
Func<int, string> projection = x => "Value=" + x;
int[] values = { 3, 7, 10 };
var strings = values.Select(projection);
foreach (string s in strings)
{
Console.WriteLine(s);
}
Result:
Value=3
Value=7
Value=10
A Func<int, string> eats ints and returns strings. So, what eats ints and returns strings? How about this ...
public string IntAsString( int i )
{
return i.ToString();
}
There, I just made up a function that eats ints and returns strings. How would I use it?
var lst = new List<int>() { 1, 2, 3, 4, 5 };
string str = String.Empty;
foreach( int i in lst )
{
str += IntAsString(i);
}
// str will be "12345"
Not very sexy, I know, but that's the simple idea that a lot of tricks are based upon. Now, let's use a Func instead.
Func<int, string> fnc = IntAsString;
foreach (int i in lst)
{
str += fnc(i);
}
// str will be "1234512345" assuming we have same str as before
Instead of calling IntAsString on each member, I created a reference to it called fnc (these references to methods are called delegates) and used that instead. (Remember fnc eats ints and returns strings).
This example is not very sexy, but a ton of the clever stuff you will see is based on the simple idea of functions, delegates and extension methods.
One of the best primers on this stuff I've seen is here. He's got a lot more real examples. :)
It is a delegate that takes one int as a parameter and returns a value of type string.
Here is an example of its usage:
using System;
class Program
{
static void Main()
{
Func<Int32, String> func = bar;
// now I have a delegate which
// I can invoke or pass to other
// methods.
func(1);
}
static String bar(Int32 value)
{
return value.ToString();
}
}
Func<int, string> accepts an int value parameter and returns a string value. Here's an example where an additional supporting method is unnecessary.
Func<int, string> GetDogMessage = dogAge =>
{
if (dogAge < 3) return "You have a puppy!";
if (dogAge < 7) return "Strong adult dog!";
return "Age is catching up with the dog!";
};
string youngDogMessage = GetDogMessage(2);
NOTE: The last object type in Func (i.e. "string" in this example) is the functions return type (i.e. not limited to primitives, but any object). Therefore, Func<int, bool, float> accepts int and bool value parameters, and returns a float value.
Func<int, bool, float> WorthlessFunc = (intValue, boolValue) =>
{
if(intValue > 100 && boolValue) return 100;
return 1;
};
float willReturn1 = WorthlessFunc(21, false);
float willReturn100 = WorthlessFunc(1000, true);
HTH

Categories

Resources