在C ++中的惰性求值 [英] Lazy evaluation in C++

查看:320
本文介绍了在C ++中的惰性求值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++没有本机支持延迟评估(如Haskell所做)。

C++ does not have native support for lazy evaluation (as Haskell does).

我想知道是否可以在C ++中实现延迟评估方式。如果是,你会怎么做?

I'm wondering if it is possible to implement lazy evaluation in C++ in a reasonable manner. If yes, how would you do it?

编辑:我喜欢Konrad Rudolph的回答。

I like Konrad Rudolph's answer.

想知道是否可以以更通用的方式实现它,例如通过使用一个参数化的类lazy,基本上用于矩阵matrix_add的矩阵的工作方式。

I'm wondering if it's possible to implement it in a more generic fashion, for example by using a parametrized class lazy that essentially works for T the way matrix_add works for matrix.

任何操作on T会返回lazy。唯一的问题是将参数和操作代码存储在lazy本身内部。

Any operation on T would return lazy instead. The only problem is to store the arguments and operation code inside lazy itself. Can anyone see how to improve this?

推荐答案


我想知道是否可以实现在C ++中以合理的方式进行惰性求值。如果是,您会如何做?

I'm wondering if it is possible to implement lazy evaluation in C++ in a reasonable manner. If yes, how would you do it?

是的,这是可能的,用于矩阵计算。促进这一点的主要机制是操作符重载。考虑矩阵相加的情况。函数的签名通常看起来像这样:

Yes, this is possible and quite often done, e.g. for matrix calculations. The main mechanism to facilitate this is operator overloading. Consider the case of matrix addition. The signature of the function would usually look something like this:

matrix operator +(matrix const& a, matrix const& b);

现在,为了使此函数延迟,只需返回代理而不是实际结果: / p>

Now, to make this function lazy, it's enough to return a proxy instead of the actual result:

struct matrix_add;

matrix_add operator +(matrix const& a, matrix const& b) {
    return matrix_add(a, b);
}

现在所需要做的就是写这个代理:

Now all that needs to be done is to write this proxy:

struct matrix_add {
    matrix_add(matrix const& a, matrix const& b) : a(a), b(b) { }

    operator matrix() const {
        matrix result;
        // Do the addition.
        return result;
    }
private:
    matrix const& a, b;
};

魔术在于方法 c>这是从 matrix_add 到plain matrix 的隐式转换运算符。这样,你可以链接多个操作(当然提供适当的重载)。仅当最终结果分配给 matrix 实例时才会进行评估。

The magic lies in the method operator matrix() which is an implicit conversion operator from matrix_add to plain matrix. This way, you can chain multiple operations (by providing appropriate overloads of course). The evaluation takes place only when the final result is assigned to a matrix instance.

强>我应该更明确。因为它是,代码没有意义,因为虽然评估发生迟缓,它仍然发生在同一个表达式。特别是,除非 matrix_add 结构更改为允许链接添加,否则另一个添加将评估此代码。 C ++ 0x通过允许可变参数模板(即可变长度的模板列表)大大方便了这一点。

EDIT I should have been more explicit. As it is, the code makes no sense because although evaluation happens lazily, it still happens in the same expression. In particular, another addition will evaluate this code unless the matrix_add structure is changed to allow chained addition. C++0x greatly facilitates this by allowing variadic templates (i.e. template lists of variable length).

然而,一个非常简单的例子,直接受益如下:

However, one very simple case where this code would actually have a real, direct benefit is the following:

int value = (A + B)(2, 3);

这里,假设 A B 是二维矩阵,并且去参考在Fortran符号中完成,即上述从矩阵和中计算一个元素。添加整个矩阵当然是浪费。 matrix_add 到救援:

Here, it is assumed that A and B are two-dimensional matrices and that dereferencing is done in Fortran notation, i.e. the above calculates one element out of a matrix sum. It's of course wasteful to add the whole matrices. matrix_add to the rescue:

struct matrix_add {
    // … yadda, yadda, yadda …

    int operator ()(unsigned int x, unsigned int y) {
        // Calculate *just one* element:
        return a(x, y) + b(x, y);
    }
};

其他例子比比皆是。我刚刚记得我已经实现了不久前相关的东西。基本上,我不得不实现一个字符串类,应该坚持一个固定的,预定义的接口。但是,我的特定字符串类处理了巨大的字符串,实际上并不存储在内存中。通常,用户只需使用函数 infix 从原始字符串访问小的子字符串。我重载这个函数为我的字符串类型返回一个代理,保存对我的字符串,以及所需的开始和结束位置的引用。只有当这个子字符串被实际使用时,它才查询一个C API来检索字符串的这个部分。

Other examples abound. I've just remembered that I have implemented something related not long ago. Basically, I had to implement a string class that should adhere to a fixed, pre-defined interface. However, my particular string class dealt with huge strings that weren't actually stored in memory. Usually, the user would just access small substrings from the original string using a function infix. I overloaded this function for my string type to return a proxy that held a reference to my string, along with the desired start and end position. Only when this substring was actually used did it query a C API to retrieve this portion of the string.

这篇关于在C ++中的惰性求值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆