.net - 如何将一个表达式柯里化(Currying)为另一个表达式?

标签 .net expression currying

我不确定这是否是严格柯里化(Currying),但我基本上想要实现以下目标。给定一个表达式:

Expression<Func<T1, T2, TResult>> expression

我想传入一个参数并生成一个相应的表达式,其中该参数的值是固定的。生成的表达式在功能上应与表达式 等效,只是它应少包含一个参数。

结果表达式看起来像这样:

Expression<Func<T2, TResult>> curriedExpression;

我已经尝试过此操作,但它不起作用,因为 Expression 不会隐式转换为 lambda 表达式:

curriedExpression = b => expression(fixedValueForT1, b);

请注意,curredExpression 不应包含对表达式 的调用;除了固定值之外,它应该包含重复的逻辑。

我希望这是有道理的。如果这含糊不清或解释得不好,请告诉我。

最佳答案

我认为你可以从 ExpressionVisitor 得出以简单的方式上课。这是一个概念证明 - 它可能过于简单化,但我认为这就是您所追求的:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main()
    {
        Expression<Func<int, int, int>> original = (x, y) => MethodX(x) + MethodY(y);
        Console.WriteLine("Original: {0}", original);
        var partiallyApplied = ApplyPartial(original, 10);
        Console.WriteLine("Partially applied: {0}", partiallyApplied);
    }

    static int MethodX(int x)
    {
        return x + 1;
    }

    static int MethodY(int x)
    {
        return -x;
    }

    static Expression<Func<T2, TResult>> ApplyPartial<T1, T2, TResult>
        (Expression<Func<T1, T2, TResult>> expression, T1 value)
    {
        var parameter = expression.Parameters[0];
        var constant = Expression.Constant(value, parameter.Type);
        var visitor = new ReplacementVisitor(parameter, constant);
        var newBody = visitor.Visit(expression.Body);
        return Expression.Lambda<Func<T2, TResult>>(newBody, expression.Parameters[1]);
    }
}

class ReplacementVisitor : ExpressionVisitor
{
    private readonly Expression original, replacement;

    public ReplacementVisitor(Expression original, Expression replacement)
    {
        this.original = original;
        this.replacement = replacement;
    }

    public override Expression Visit(Expression node)
    {
        return node == original ? replacement : base.Visit(node);
    }
}

输出:

Original: (x, y) => (MethodX(x) + MethodY(y))
Partially applied: y => (MethodX(10) + MethodY(y))

关于.net - 如何将一个表达式柯里化(Currying)为另一个表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19151810/

相关文章:

c# - 按类型从表达式中提取所有条件

javascript - 如何柯里化(Currying)一个以选项对象作为参数而不是几个不同参数的函数?

c# - 在完成后长时间保留 Task 对象有什么缺点吗?

Python正则表达式重复

javascript - 查找 JavaScript 表达式的各个部分

javascript - 如何协调 Javascript 与柯里化(Currying)和函数组合

Javascript Curry 函数对这段代码有好处吗?

c# - C# 中的邮件存储配额检查器

c# - 并行分块与顺序分块文件上传

.net - 在请求取消之前永远不会结束的任务