延迟求值和无穷(5)
发表于 2007-08-15 03:12 AM 作者: liuxinyu
4 Infinity
从上面一节给出的超市交易问题看出,使用延迟求值模型,能够减少不必要的计算次 数,只有在真正需要某个数据时,才去进行计算。这样大大节约了计算成本,对于大 量的数据处理,能提高不少效率。
实际上,延迟求值不仅可以应用于大量数据处理,甚至可以直接为无穷的概念建 模。而针对无穷的计算是使用传统计算模型难以做到的。例如面对这样的需求:“建 立一个列表,代表全部自然数”。这个需求,用C++的数组类型,或者vector容器类 型,是难以满足的。而利用前面给出的stream_record 却可以非常简单的实现,如 下:
代码:
template< typename Succ>
stream_record<int>* create_series(int n, Succ f){
return (new stream_record<int>(n)) ->setNext(create_series< Succ>, n, f);
}
template<class T >
struct AddTo{
AddTo(int n):_n(n){}
T operator()(T x){ return x + _n; }
T _n;
};
//...
stream_record<int>* N =create_series(1, AddTo <int>(1));
std::cout<<”natural number created.n”;
std::cout<<”7th: ”<<getAt(N, 6)<<”n”; 代码:
template<class T >
class stream_record{
public:
//...
stream_record(T v, stream_record* r=0):value(v), _next(r){}
//...
T value; 代码:
template<class T =double> class stream_record;
template<class Func, class Obj, class Arg, class T >
stream_record< T >* create_delay_record(Func f, Obj x, Arg arg);
template<class T >
class stream_record{
public:
//… 代码:
template<class T > class stream_record{
public:
//...
template<class Func, class Obj, class Arg >
stream_record* setNext(Func f, Obj x, Arg arg){
_next = create_delay_record< Func, Obj, Arg, T >(f, x, arg);
return this;
} 代码:
template<class Func, class Obj, class Arg, class T >
stream_record< T >* create_delay_record(Func f, Obj x, Arg arg){
return new delayed_record< Func, Obj, Arg, T >(f, x, arg);
} 代码:
f(r->next(), arg)
代码:
create_series(Increase(n), Increase); ==> f(arg(n), arg)
代码:
template<class Func, class Obj, class Arg, class T >
class delayed_record: public stream_record< T >{
public:
delayed_record(Func f, Obj x, Arg arg): _f(f), _x(x), _arg(arg){}
stream_record< T >* operator()(){
std::cout<<”nlazy eval: ”;
stream_record< T >* res = _f(_arg(_x), _arg);
delete this;
return res;
}
private:
Func _f;
Obj _x;
Arg _arg;
};
//partial instatiate
template<class Func, class Arg, class T >
class delayed_record< Func, stream_record< T >*, Arg, T >: public stream_record< T >{
public:
delayed_record(Func f, stream_record< T >* x, Arg arg): _f(f), _x(x), _arg(arg){}
stream_record< T >* operator()(){
std::cout<<”nstill empty, eval: ”;
stream_record< T >* res = _f(_x ->next(), _arg);
delete this;
return res;
}
private:
Func _f;
stream_record< T >* _x;
Arg _arg;
}; 经过上述改动,全体自然数的延迟求值模型就可以正常使用了,程序输入如下结 果:
natural number created.
lazy eval:
lazy eval:
lazy eval:
lazy eval:
lazy eval:
lazy eval: 7th: 7
既然延迟求值可以给自然数这类的无穷序列建模,一个进一步的想法是,直接对 无穷序列进行操作,完成各种计算任务。例如下面的程序,可以将两个无穷序列加起 来:
代码:
template<class Record>
Record* add_series(Record* a, Record* b){
return (new Record(a ->value+ b ->value)) ->setNext(add_series< Record>, a, b);
} 代码:
template<class Func, class T >
class delayed_record<
Func,
stream_record< T >*, stream_record< T >*,
T >: public stream_record< T >{
public:
delayed_record(Func f, stream_record< T >* x, stream_record< T >* y): _f(f), _x(x), _y(y){}
stream_record< T >* operator()(){
stream_record< T >* res = _f(_x ->next(), _y ->next());
delete this;
return res;
}
private:
Func _f;
stream_record< T >* _x;
stream_record< T >* _y;
}; 代码:
typedef stream_record<int> IntStream; IntStream* ones=create_series(1, AddTo <int>(0)); IntStream* N1 =add_series(ones, N); std::cout<<”7th: ”<<getAt(N1, 6)<<”n”;
代码:
lazy eval: lazy eval: lazy eval: lazy eval: lazy eval: lazy eval: 7th: 8
代码:
IntStream* integers= new IntStream(1); integers->setNext(add_series(ones, integers));
代码:
template<class T >
class stream_record{
//...
stream_record* setNext(stream_record* r){
_next = r;
return this;
} 评论总数 0
评论
发表评论 |
作者为 liuxinyu 的最新文章
- beautiful code第20章和第29章翻译 (2007-11-06)
- 延迟求值和无穷(6) (2007-08-15)
- 延迟求值和无穷(5) (2007-08-15)
- 延迟求值和无穷(4) (2007-08-15)
- 延迟求值和无穷(3) (2007-08-15)




