递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码(将尾递归转化为迭代);
柯里化(Currying)和部分(偏)函数(Partial Function)
是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
主要功能是提供了强大的动态函数创建方法,通过调用另一个函数并为它传入要柯里化(currying)的函数和必要的参数而得到。通俗点说就是利用已有的函数,再创建一个动态的函数,该动态函数内部还是通过已有的函数来发生作用。
柯里化就是一个函数在参数没给全时返回另一个函数,返回的函数的参数正好是余下的参数。比如:你制定了x和y, 如2的3次方,就返回8, 如果你只制定x为2,y没指定, 那么就返回一个函数:2的y次方, 这个函数只有一个参数:y。
curry就是对高阶函数(就是一种对过程的抽象 参考map它就是一个抽象的过程)的降阶处理。
2大特性:
将多个参数的函数进行拆分,拆成多个只有一个参数的函数。为什么要拆分,λ 演算。
示例:
常规的写法:Func<int, int, int> Add = (x, y) => x + y;
拆分: Func<int, Func<int, int>> Add = x => y => x + y;
输入一个参数,返回一个具有一个参数的函数,接着再调用返回的函数,就完成整个调用。
调用:
var add2 = Add(3);
var ret = add2(4);
写成一行:
var ret = Add(3)(4);
或者不重写,只要为原来的方法加一个扩展方法:
public static Func<T1,Func<T2,T3>> Currey<T1,T2,T3>(this Func<T1,T2,T3> func)
{
return x => y => func(x,y);
}
这样就可以对C#标准的GenralAdd(int x,int y)方法执行Currey转换为部分(偏)函数了:
Func<int, int, int> Add = GenralAdd;
var CurreyedAdd = Add.Currey()(3)(4);
示例:比如我们经常需要执行SQL语句,当然需要使用SqlConnection,然后附加上对应的SQL语句,为此我们可以开发一个简单的函数,用来简化这一过程:
Func<SqlConnection, Func<String, DataSet>> ExecSql = x => y =>
{
using (x)
{
x.Open();
var com = x.CreateCommand();
DataSet ds = new DataSet();
com.CommandText = y;
SqlDataAdapter adapter = new SqlDataAdapter(com);
adapter.Fill(ds);
return ds;
}
};
调用:
var esql = ExecSql(new SqlConnection("xxx"));
var rds = esql("select xxxx from xxx");
rds = esql("select ffff from ffff");
如果想先传入Sql语句再传入SqlConnection:
Func<String, Func<SqlConnection, DataSet>> ExecSqlT = x => y => ExecSql(y)(x)