/// <summary> /// Produces a pure function with optimizations from the given lambda /// </summary> /// <typeparam name="T">Function parameter type</typeparam> /// <typeparam name="TResult">Function return type</typeparam> /// <param name="ex">The function. /// Note: The lambda will usually take the form of (funcName) => (parameter) => body, so that funcName(arg) can be called for self-recursion.</param> /// <param name="caching">Enable result caching</param> /// <param name="threaded">Enable multithreading</param> /// <returns>Optimized pure function.</returns> public static PureFunc <T, TResult> PureFunction <T, TResult>(Expression <Func <Func <T, TResult>, Func <T, TResult> > > ex, bool caching = true, bool threaded = true) { var methodVar = Expression.Variable(typeof(Func <T, TResult>), ex.Parameters[0].Name); var paramVar = ((LambdaExpression)ex.Body).Parameters[0]; //Expression<PureFunc<Func<T,TResult>,PureFunc<T, TResult>>> makePure = (a) => new PureFunc<T, TResult>(a); var resultingExpression = Expression.Lambda(Expression.Block( new[] { methodVar }, Expression.Assign(methodVar, ReplaceInstancesOfExpressionFactory(ex.Parameters[0], methodVar, caching, threaded, true)(ex.Body) ), Expression.Invoke(methodVar, paramVar) ), paramVar); while (resultingExpression.CanReduce) { resultingExpression = (LambdaExpression)resultingExpression.Reduce(); } var compiled = resultingExpression.Compile(); return(new PureFunc <T, TResult>((Func <T, TResult>)compiled)); }
/// <summary> /// Create a recursive lambda. /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="ex">The expression for the Lambda. /// Note: The lambda will usually take the form of (funcName) => (parameter) => body, so that funcName(arg) can be called for self-recursion.</param> /// <returns></returns> public static Func <T, TResult> RecursiveLambda <T, TResult>(Expression <Func <Func <T, TResult>, Func <T, TResult> > > ex) { var methodVar = Expression.Variable(typeof(Func <T, TResult>), ex.Parameters[0].Name); var paramVar = ((LambdaExpression)ex.Body).Parameters[0]; var resultingExpression = Expression.Lambda(Expression.Block( new[] { methodVar }, Expression.Assign(methodVar, ReplaceInstancesOfExpressionFactory(ex.Parameters[0], methodVar)(ex.Body) ), Expression.Invoke(methodVar, paramVar) ), paramVar); while (resultingExpression.CanReduce) { resultingExpression = (LambdaExpression)resultingExpression.Reduce(); } var compiled = resultingExpression.Compile(); return((Func <T, TResult>)compiled); }