Как эти возвращаемые функции работают в Dart? - PullRequest
1 голос
/ 06 января 2020

официальная документация Blo c дает этот фрагмент кода:

Stream<int> countStream(int max) async* {
    for (int i = 0; i < max; i++) {
        yield i;
    }
}

Этот выглядит очень простым для меня, пока я не пойму, что функция делает ничего не вернуть (нет return оператора), но все время выдает (что для меня - исходя из python - не то же самое, что и оператора возврата).

Есть также этот пример, который еще более понятен:

Future<int> sumStream(Stream<int> stream) async {
    int sum = 0;
    await for (int value in stream) {
        sum += value;
    }
    return sum;
}

Здесь явно указан int, , но , если я правильно прочитал, определение функции должно вернуть тип Future<int> :

Future<int> sumStream(Stream<int> stream) async { //...

Теперь, как это работает? Я немного запутался здесь.

Заранее спасибо! Axel.

Ответы [ 2 ]

2 голосов
/ 06 января 2020

Для вашего первого примера countStream - это Stream целого числа, разработанный с asyn c*. (позаботьтесь о звезде)
В этом определении потока Yield испускает новое целое число в потоке потока (целое число, как сказано stream .
Если вы используете поток, вы получите 0,1,2,3,4, ..., max-1

Во втором фрагменте прочитайте его как: sumStream is a Future, который должен возвращать int.
В более общем случае экземпляр Future создает значение типа T.
sumStream будет использовать поток (заданный в параметре) и до тех пор, пока это Поток имеет значения, суммируйте их и верните последнюю сумму, когда закончите. Sum - целое число: это нормально для определения Future.

Используя оба, вы можете иметь:

> void main() async  {   
   print(await sumStream(countStream(5)));   
}

результат: 10 (0 + 1 + 2 + 3 + 4)

Поскольку sumStream является Future, main может ожидать асинхронного выполнения: она объявляет о своем намерении использовать функцию asyn c (asyn *) 1047 * объявление), тогда он может использовать await, чтобы остановить собственное выполнение, пока не вернется sumStream.

Другой способ, если вы выйдете из main ut asyn c - добавить в будущее предложение .then :

void main()  {
  sumStream(countStream(5)).then((x)=>print(x));
  print("after sumStream");
}

Результат:
после sumStream
10

Как вы можете видеть, что основной проход через sumStream начался, но он еще не завершен, и сначала выведите («после sumStream»).
Затем основной завершен, но Дарт знает, что все еще выполняется асинхронное задание c. и он будет ждать, пока все не будет сделано, поэтому мы можем увидеть результат, но как только Future sumStream будет завершен.

HTH

1 голос
/ 06 января 2020

Это выглядит очень просто для меня, пока я не пойму, что функция ничего не возвращает (нет оператора возврата)

Прежде всего, эта функция возвращает Stream<int> значение результата как указывается в объявлении функции. Эта функция часто называется функцией генератора.

Stream<int> countStream(int max) async*

Код тела функции (генератор) сгенерирует значения int и выдаст эти сгенерированные значения первоначально возвращенному потоку Stream<int>.

Оператор yield означает в этом случае следующий лог c работы:
Добавьте значение к контроллеру Stream<int> и вернитесь к следующему оператору в теле функции, следующей за этим: утверждение yield.

Примерно так:

import 'dart:async';

Future<void> main() async {
  await for (final i in countStream(5)) {
    print(i);
  }
}

Stream<int> countStream(int max) {
  int i;
  final _ctl$ = StreamController<int>();
  void Function(int) _switchState$;
  _switchState$ = (int _state$) {
    while (true) {
      switch (_state$) {
        case 0:
          // for (int i = 0;
          i = 0;
          _state$ = 1;
          break;
        case 1:
          // i < max;
          if (i < max) {
            _state$ = 2;
          } else {
            return;
          }
          break;
        case 2:
          // yield i;
          _ctl$.add(i);
          Timer.run(() => _switchState$(3));
          return;
        case 3:
          // i++
          i++;
          _state$ = 1;
          break;
      }
    }
  };

  Timer.run(() => _switchState$(0));
  return _ctl$.stream;
}

Результат:

0
1
2
3
4
...