2015-10-19 6 views
1

Есть ли родной (поддерживаемый языком) ленивый синтаксис оценки? Что-то вроде lazy val в Скале.Как сделать ленивую оценку в Dart?

Я прошел через the docs и ничего не нашел. Существует только глава о «ленивой загрузке библиотеки», но я не об этом спрашиваю.

Основываясь на этом исследовании, я склонен верить (пожалуйста, поправьте меня, если я ошибаюсь), что в настоящее время такой вещи нет. Но, может быть, вы знаете какие-либо планы или запросы функций, которые будут обеспечивать функциональность? Или, возможно, это было рассмотрено и отклонено командой Дарта?

Если на самом деле нет никакой поддержки для этого, тогда какая наилучшая практика (лучший синтаксис) для реализации ленивой оценки? Примером может служить оценка.

Edit:

Преимущества функции, которые я искал в основном те же, что и в реализации на других языках: Scala's lazy val или C#'s Lazy<T> или Hack's __Memorize attribute:

  1. кратким синтаксис
  2. отложенное вычисление до тех пор, пока не потребуется значение
  3. кэш-результат (по запросу лень)
  4. не нарушают чисто функциональной парадигмы (объяснение ниже)

Простой пример:

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); 
} 

Поглотитель очень многословным и имеет повторяющийся код. Кроме того, я не могу сделать конструктор const, потому что переменная кэширования _res должна быть вычислена по требованию. Я предполагаю, что если бы у меня была Scala-подобная функция lazy, то у меня также была бы поддержка языка для создания постоянного конструктора. Это связано с тем, что ленивый оцененный _res - referentially transparent и would 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); 
} 
+0

Может йо u, пожалуйста, укажите конкретный пример того, чего вы хотите добиться, используя ленивую оценку. Насколько мне известно, нет специальной поддержки языка и не обсуждается. Многие методы в List, Map, ... которые ленивы оцениваются. Например, 'map()', 'fold()', 'reduce()', ... См. Например http://stackoverflow.com/questions/20491777/dart-fold-vs-reduce. Возможно, закрытие делает то, что вы хотите. –

ответ

1

Update2

От @lrn комментария пользователя - используя EXPANDO для кэширования позволяет работать с ПОСТОЯННЫМ:

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> может выглядеть так, как показано ниже в Dart, но это также не работает с константой и не может использоваться в инициализаторах поля, если для вычисления необходимо передать члены экземпляра (this.xxx).

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

оригинальный

Dart версия 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

+0

Благодарим вас за ответ. Я знаком с этой статьей, которую вы связали. На самом деле это одна из причин, по которой я ищу хорошую * ленивую оценку * в Dart. Оба примера, которые вы предоставили, имеют недостатки в том, чего я пытаюсь достичь. Первый вычисляется независимо от того, используется ли результат или нет. Второе не может использоваться с членами класса и постоянными конструкторами в Dart. Не могли бы вы взглянуть на редактирование на мой вопрос? –

+0

Я немного поглядел на него. См. [DartPad] (https://dartpad.dartlang.org/a4489204eb37f57ed067) для кода. Я не думаю, что есть способ использовать ленивую оценку в сочетании с const в Dart. –

+0

Статические члены ленивы инициализированы в Dart, но я предполагаю, что это также только ограниченное использование для вашего требования. –

 Смежные вопросы

  • Нет связанных вопросов^_^