如何在Dart中进行懒惰评估?

是否存在本机(支持语言)的惰性评估语法?像
Scala中的lazy val之类的东西.

我经历了the docs,找不到任何东西.只有一章关于“懒惰加载图书馆”,但这不是我要问的.

基于这项研究,我倾向于相信(请纠正我,如果我错了),目前没有这样的事情.但是,您是否知道将提供功能的任何计划或功能请求?或者也许它被Dart团队考虑并拒绝了?

如果确实没有本机支持,那么实现延迟评估的最佳实践(最佳语法)是什么?一个例子将不胜感激.

编辑:

我正在寻找的功能的好处与其他语言的实现大致相同:Scala’s lazy valC#’s Lazy<T>Hack’s __Memorize attribute

>简洁的语法
>延迟计算直到需要该值
>缓存结果(按需懒惰)
>不要打破纯粹的功能范式(下面的解释)

一个简单的例子:

class Fibonacci {

  final int n;
  int _res = null;

  int get result {
    if (null == _res) {
      _res = _compute(this.n);
    }
    return _res;
  }

  Fibonacci(this.n);

  int _compute(n) {
    // ...
  }
}

main(List<String> args) async {
  print(new Fibonacci(5).result);
  print(new Fibonacci(9).result);
}

getter非常冗长,并且有重复的代码.此外,我不能使构造函数const,因为缓存变量_res必​​须按需计算.我想如果我有一个类似Scala的懒惰功能,那么我也会有一个语言支持来拥有一个常量构造函数.这要归功于懒惰的评估_res是referentially transparentwould not be in the way.

class Fibonacci {

  final int n;
  int lazy result => _compute(this.n);

  const Fibonacci(this.n);  // notice the `const`

  int _compute(n) {
    // ...
  }
}

main(List<String> args) async {
  // now these makes more sense:
  print(const Fibonacci(5).result);
  print(const Fibonacci(9).result);
}

最佳答案 UPDATE2

来自@lrn的评论 – 使用Expando进行缓存使其适用于const:

class Lazy<T> {
  static final _cache = new Expando();
  final Function _func;
  const Lazy(this._func);
  T call() {
    var result = _cache[this];
    if (identical(this, result)) return null;
    if (result != null) return result;
    result = _func();
    _cache[this] = (result == null) ? this : result;
    return result;
  }
}


defaultFunc() {
  print("Default Function Called");
  return 42;
}
main([args, function = const Lazy(defaultFunc)]) {
  print(function());
  print(function());
}

在DartPad中尝试一下

更新

可重复使用的Lazy T< T>.如果计算需要引用实例成员(this.xxx),那么在Dart中可能看起来像下面但是它也不适用于const并且不能在字段初始值设定项中使用.

void main() {
  var sc = new SomeClass();
  print('new');
  print(sc.v);
}

class SomeClass {
  var _v  = new Lazy<int>(() {
    print('x');
    return 10;
  });
  int get v => _v();
}

class Lazy<T> {
  final Function _func;
  bool _isEvaluated = false;
  Lazy(this._func);
  T _value;
  T call() {
    if(!_isEvaluated) {
      if(_func != null) {
        _value = _func();
      }
      _isEvaluated = true;
    }
    return _value;
  }
}

DartPad尝试一下

原版的

飞镖版http://matt.might.net/articles/implementing-laziness/使用闭包进行懒惰评估:

void main() {
  var x = () { 
    print ("foo"); 
    return 10; 
  }();
  print("bar");
  print(x);
  // will print foo, then bar then 10.
  print('===');
  // But, the following Scala program:
  x = () { 
    print("foo"); 
    return 10; 
  };
  print ("bar");
  print (x());
  // will print bar, then foo, then 10, since it delays the computation of x until it’s actually needed.
}

DartPad尝试一下

点赞