原创作者: qiezi   阅读:1136次   评论:0条   更新时间:2011-05-26    
写了一个编译期执行的fibonacci模板:

template fibonacci(long n){
    static if(n <= 2)
        const long fibonacci = 1;
    else
        const long fibonacci = fibonacci!(n-1) + fibonacci!(n-2);
}

static long a = fibonacci!(40);


D语言新支持的编译期执行函数也可以完成:

long fibonacci(long n){
    if (n <= 2) return 1;
    return fibonacci(n-1) + fibonacci(n-2);
}

static long a = fibonacci(40);


这2种实现,我原想编译效率应该都比较低,因为编译期执行是要花编译时间的。结果前一种编译效率非常高,后一种则比较低。仔细想想,的确应该是这样,这与模板产生代码的机制有关。

模板在实例化时,会根据参数产生出不同的代码。比如上面的第一个例子,fibonacci!(1)和fibonacci!(2)就会实例化出2份代码,所以fibonacci!(40)相当于产生了这样一组代码:

// ....
const long fibonacci_38 = fibonacci_37 + fibonacci_36;
const long fibonacci_39 = fibonacci_38 + fibonacci_37;
const long fibonacci_40 = fibonacci_39 + fibonacci_38;
static long a = fibonacci_40;


把每一个值都给缓存下来了,效率当然高了,我们使用相同的缓存策略也可以缩短函数的运行时间。

编译期执行的函数则没有这个优点,它和普通的函数没有区别,不同点在于它在编译的时候运行。把编译器看成一种动态语言运行环境,那么编译“编译期执行的函数”的过程就像是运行动态语言程序的过程。如果程序中存在大量编译期执行函数,可能极大地降低编译效率,对于它的使用应该尽量避免。

模板提供的是一种声明式语法,在复杂的静态执行逻辑面前有时候会显得力不从心,编译期执行函数在解决这个问题的同时,却带来了上面这种副作用。如果能把两者的优点结合起来,用函数的语法来写程序,由编译器生成优化的模板代码,这种编译期执行才可以大量使用。
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

  • qiezi在2007-03-15创建
  • qiezi在2011-05-26更新
Global site tag (gtag.js) - Google Analytics