If possible I want to define a function, for example as an accumulator, that can be infinitely chained as follows:
f(2)returns 2f(2)(3)returns 5f(2)(3)(10)returns 15f(2)(3)(10)(100)returns 115f(2)(3)(10)(100)()()...returns …
static void Main()
{
Func<int, Func<int, int>> f = (x) =>
{
return (y) =>
{
return x += y;
};
};
Console.WriteLine(f(2)(3));
// Console.WriteLine(f(2)(3)(10)); should return 15
}
Any idea?
Note: I am not asking f(param int[] x){} approach.
>Solution :
f cannot return an int, because you cannot invoke an int after calling f once. It can return a wrapper type that wraps an int though. f just needs to return the wrapper type, and then you can infinitely chain.
If you are fine with the indexer access syntax [...] instead of the method invocation syntax (...), then you can just create a struct like this:
struct F {
public int Count { get; }
private F(int count) {
Count = count;
}
public F this[int acc] => new F(Count + acc);
// override ToString to return Count.ToString,
// or an implicit conversion to int, if you want
}
Then,
F f = new F(); // this could be a static field somewhere, making it effectively a global variable
Console.WriteLine(f[1][2][3][4].Count);
If you really like the method invocation syntax though, you would need to use dynamic and inherit from DynamicObject, overriding TryInvoke, like in this answer.
Example:
dynamic f = new F();
Console.WriteLine(f(1)(2)(3)(4).Count);
class F: DynamicObject {
public int Count { get; }
public F(int count = 0) {
Count = count;
}
public override Boolean TryInvoke(InvokeBinder binder, object?[]? args, out object? result) {
if (args?.Length == 1 && args?[0] is int acc) {
result = new F(Count + acc);
return true;
}
result = null;
return false;
}
}