linq 表达式的惰性求值

发布于 2024-09-25 21:17:12 字数 780 浏览 5 评论 0原文

我正在尝试构建一个表达式评估器 Linq 表达式。我正在努力做到这一点 所有函数参数都是惰性求值的,但不能完全求值 到那里。

我在这里写的是假的,但真实的事情是 linq 表达式。

示例表达式:

Func1(Func2(10) + 1, Func3(10))

更新

Expression.Call(Func1,
    Expression.Add(
        Expression.Call(Func2, Expression.Constant(10)),
        Expression.Constant(1))
    Expression.Call(Func3, Expression.Constant(10))
)

我希望 Func1 的参数在调用时进行计算 也就是说,我希望对参数进行惰性评估。包裹的时候是可以的 lambda 表达式内的参数表达式,但如果我这样做,则二进制表达式 Func2(10) + 1 将失败,因为无法将 lambda 添加到常量表达式。

实际的函数代码如下所示:

  int Func1(Func<int> arg1, Func<int> arg2)
  {
  }

arg1 运行时将计算“Func2(10) + 1”
arg2 在运行时将评估“Func3(10)”,

因此在这里我可以选择是否要评估参数,以获得惰性效果。

这有可能实现吗?

Im trying to build a expression evaluator with
Linq expressions. Im trying to make It so that
all function arguments are lazy evaluated but can't quite
get there.

I'm writing in psuedo here but the real thing is
linq expressions.

Example expression:

Func1(Func2(10) + 1, Func3(10))

Update

Expression.Call(Func1,
    Expression.Add(
        Expression.Call(Func2, Expression.Constant(10)),
        Expression.Constant(1))
    Expression.Call(Func3, Expression.Constant(10))
)

I want the arguments to Func1 to be evaluated at invoke-time
that is I want the arguments to be lazy evaluated. It's doable when wrapping the
argument expressions inside a lambda expression but if I do that the binary expression
Func2(10) + 1 will fail because one can't add a lambda to a constant expression.

The actual function code will look like this:

  int Func1(Func<int> arg1, Func<int> arg2)
  {
  }

arg1 when run will evaluate "Func2(10) + 1"
arg2 when run will evaluate "Func3(10)"

So here I can choose if I want to evalute the argument or not, to get the lazy effect.

Is this possible to accomplish?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盗梦空间 2024-10-02 21:17:12

首先,我认为首先讨论不使用表达式树的问题会很有帮助。您说这是您要调用的函数:

int Func1(Func<int> arg1, Func<int> arg2)
{
}

并且您想弄清楚如何使用表达式树实现以下功能?

Func1(() => Func2(10) + 1, () => Func3(10));

到目前为止这是正确的吗?如果这一切都是真的,那么考虑这个类:

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine(Func1(() => Func2(10) + 1, () => Func3(10)));            

        var arg1 = Expression.Add(Expression.Call(typeof(Program), "Func2", Type.EmptyTypes, Expression.Constant(10)), Expression.Constant(1));
        var arg2 = Expression.Call(typeof(Program), "Func3", Type.EmptyTypes, Expression.Constant(10));
        var callFunc1 = Expression.Call(typeof(Program), "Func1", Type.EmptyTypes, Expression.Lambda<Func<int>>(arg1), Expression.Lambda<Func<int>>(arg2));
        var tester = Expression.Lambda<Func<int>>(callFunc1);
        int result = tester.Compile()();

        Console.WriteLine(result);
    }

    static int Func1(Func<int> arg1, Func<int> arg2)
    {
        return arg1() + arg2();
    }

    static int Func2(int arg)
    {
        return arg;
    }

    static int Func3(int arg)
    {
        return 2 * arg;
    }
}

它将两次打印出 31(10 + 1) + (10 * 2)。第一个是直接调用它,第二个使用表达式树。

To begin, I think it would be helpful to first discuss the problem without the use of expression trees. You said that this is the function you want to call:

int Func1(Func<int> arg1, Func<int> arg2)
{
}

And you want to figure out how to implement the following using expression trees?

Func1(() => Func2(10) + 1, () => Func3(10));

Is this correct so far? If that is all true, then consider this class:

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine(Func1(() => Func2(10) + 1, () => Func3(10)));            

        var arg1 = Expression.Add(Expression.Call(typeof(Program), "Func2", Type.EmptyTypes, Expression.Constant(10)), Expression.Constant(1));
        var arg2 = Expression.Call(typeof(Program), "Func3", Type.EmptyTypes, Expression.Constant(10));
        var callFunc1 = Expression.Call(typeof(Program), "Func1", Type.EmptyTypes, Expression.Lambda<Func<int>>(arg1), Expression.Lambda<Func<int>>(arg2));
        var tester = Expression.Lambda<Func<int>>(callFunc1);
        int result = tester.Compile()();

        Console.WriteLine(result);
    }

    static int Func1(Func<int> arg1, Func<int> arg2)
    {
        return arg1() + arg2();
    }

    static int Func2(int arg)
    {
        return arg;
    }

    static int Func3(int arg)
    {
        return 2 * arg;
    }
}

It will print out 31 both times: (10 + 1) + (10 * 2). The first is invoking it directly, the second using expression trees.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文