C# 将具有部分应用程序的函数定义为委托
C# define function with partial application as delegate
考虑以下方法:
int Foo(string st, float x, int j)
{
...
}
现在我想通过为参数 st
和 j
提供值将其包装在类型 Func<float, int>
的委托中。但我不知道语法。有人可以帮忙吗?
这是想法(可能看起来有点 Haskell-ish):
Func<float, int> myDelegate = new Func<float, int>(Foo("myString", _ , 42));
// by providing values for st and j, only x is left as a parameter and return value is int
这应该可以解决问题:
Func<float, int> f = (x) => { return Foo("myString", x, 42); };
按照您想要的方式部分应用函数目前只能在 F# 中实现,而不能在 C# 中实现。
部分应用程序没有特定的语法。你可以通过
来模拟它
Func<int, int, int, int> multiply = (a, b, c) => a*b*c;
Func<int, int, int> multiplyPartialApplication = (a, b) => multiply(a, b, 100);
请注意,这可能不是您想要在资源受限的应用程序中执行的操作,因为它会导致额外的分配。
希望此解决方案对您有所帮助:
public static class FunctionExtensions
{
public static Func<T1, Func<T2, Func<T3, TResult>>> Curried<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func)
{
return x1 => x2 => x3 => func(x1, x2, x3);
}
}
//you create your delegate
var myDelegate = new Func<string, int, float, int>((st, j, x) => Foo(st, x, j)).Curried();
//call it with your two specified parameters where you have only them and pass the returned function that expects your float parameter
var returnedFunction = myDelegate("myString")(42);
//call the returned function eventually with your float parameter
var result = returnedFunction(0f);
[死灵法术]
我认为这个替代方案是最灵活和直接的,尽管如果不习惯这个练习会有些困难。
// Given
int Foo(string st, float x, int j) => default;
// Inlined partial application
Func<string, int, Func<float, int>> applyFoo
= (st, j) => (x) => Foo(st, x, j);
// Or as part of a function
Func<float, int> ApplyFoo(string st, int j)
=> (x) => Foo(st, x, j);
// Usage
var bar = 42;
var appliedFoo = applyFoo("foo", bar);
var result = appliedFoo(12.34);
// Or
var result = applyFoo("foo", bar)(12.34);
参数顺序的选择在这种情况下会有所不同,因为如果 Foo
被定义为 int Foo(string st, int j, float x)
,那么处理起来会更简单(通过 pApply 助手),因为它创建位置部分应用程序助手非常容易。
考虑以下方法:
int Foo(string st, float x, int j)
{
...
}
现在我想通过为参数 st
和 j
提供值将其包装在类型 Func<float, int>
的委托中。但我不知道语法。有人可以帮忙吗?
这是想法(可能看起来有点 Haskell-ish):
Func<float, int> myDelegate = new Func<float, int>(Foo("myString", _ , 42));
// by providing values for st and j, only x is left as a parameter and return value is int
这应该可以解决问题:
Func<float, int> f = (x) => { return Foo("myString", x, 42); };
按照您想要的方式部分应用函数目前只能在 F# 中实现,而不能在 C# 中实现。
部分应用程序没有特定的语法。你可以通过
来模拟它Func<int, int, int, int> multiply = (a, b, c) => a*b*c;
Func<int, int, int> multiplyPartialApplication = (a, b) => multiply(a, b, 100);
请注意,这可能不是您想要在资源受限的应用程序中执行的操作,因为它会导致额外的分配。
希望此解决方案对您有所帮助:
public static class FunctionExtensions
{
public static Func<T1, Func<T2, Func<T3, TResult>>> Curried<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func)
{
return x1 => x2 => x3 => func(x1, x2, x3);
}
}
//you create your delegate
var myDelegate = new Func<string, int, float, int>((st, j, x) => Foo(st, x, j)).Curried();
//call it with your two specified parameters where you have only them and pass the returned function that expects your float parameter
var returnedFunction = myDelegate("myString")(42);
//call the returned function eventually with your float parameter
var result = returnedFunction(0f);
[死灵法术]
我认为这个替代方案是最灵活和直接的,尽管如果不习惯这个练习会有些困难。
// Given
int Foo(string st, float x, int j) => default;
// Inlined partial application
Func<string, int, Func<float, int>> applyFoo
= (st, j) => (x) => Foo(st, x, j);
// Or as part of a function
Func<float, int> ApplyFoo(string st, int j)
=> (x) => Foo(st, x, j);
// Usage
var bar = 42;
var appliedFoo = applyFoo("foo", bar);
var result = appliedFoo(12.34);
// Or
var result = applyFoo("foo", bar)(12.34);
参数顺序的选择在这种情况下会有所不同,因为如果 Foo
被定义为 int Foo(string st, int j, float x)
,那么处理起来会更简单(通过 pApply 助手),因为它创建位置部分应用程序助手非常容易。