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

时间:2015-10-19 16:01:54

标签: dart language-features

是否存在本机(支持语言)的延迟评估语法?类似于Scala中的lazy val

我已经通过the docs,但找不到任何东西。只有一章关于"懒洋洋地加载一个图书馆",但它不是我要问的。

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

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

修改:

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

  1. 简洁的语法
  2. 延迟计算直到需要该值
  3. 缓存结果(按需懒惰)
  4. 不要打破纯粹的功能性范例(下面的解释)
  5. 一个简单的例子:

    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的lazy功能,那么我也会有一个语言支持来拥有一个常量构造函数。这要归功于懒惰的评估_resreferentially 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);
    }
    

2 个答案:

答案 0 :(得分:2)

<强> 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中试用

<强>更新

如果计算需要引用实例成员(this.xxx),可重用的Lazy<T>在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/的Dart版本:

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

中试用

答案 1 :(得分:0)

我认为这个小片段可能对你有帮助......

int _val;
int get val => _val ?? _val = 9;