Фьючерсы в Scala действительно функциональны?

Я читаю этот пост в блоге, который утверждает Futures не являются "функциональными", так как они являются просто обертками для побочных вычислений. Например, они содержат вызовы RPC, HTTP-запросы и т. Д. Это правильно?

В блоге приведен следующий пример:

def twoUsersFeed(a: UserHandle, b: UserHandle)
                (implicit ec: ExecutionContext): Future[Html] =
  for {
    feedA <- usersFeed(a)
    feedB <- usersFeed(b)
  } yield feedA ++ feedB

you lose the desired property: consistent results (the referential transparency). Also you lose the property of making as few requests as possible. It is difficult to use multi-valued requests and have composable code.

Боюсь, я не понимаю. Не могли бы вы объяснить, как мы теряем consistent result в этом случае?

1 ответ

Решение

Сообщение в блоге не в состоянии провести надлежащее различие между Future сам и способ, которым это обычно используется, IMO. Вы можете написать чисто функциональный код с Futureесли бы ты только написал Futures, которые называются чистыми, полными функциями; такой код будет ссылочно прозрачным и "функциональным" во всех отдаленно разумных смыслах этого слова.

Что правда в том, что Futures дают вам ограниченный контроль над побочными эффектами, если вы используете их с методами, которые имеют побочные эффекты. Если вы создаете Futureупаковка webClient.getзатем создаем Future отправит вызов HTTP. Но это не факт о Futureэто факт о webClient.get!

В этом посте есть доля правды. Отделение выражения вашего вычисления от его выполнения полностью, например, с помощью бесплатной монады, может привести к более эффективному и более тестируемому коду. Например, вы можете создать "язык запросов", где вы выражаете такую ​​операцию, как "получить фотографии профиля всех общих друзей А и Б", фактически не запуская его. Это облегчает проверку правильности вашей логики (потому что очень легко сделать, например, тестовую реализацию, которая может "запускать" одни и те же запросы - или даже просто проверять "объект запроса" напрямую) и, как я думаю, в блоге пытается предложить, означает, что вы можете, например, объединить несколько запросов для получения одного и того же профиля. (Это даже не просто проблема функционального программирования - некоторые ОО-книги имеют идею "шаблона команд" - хотя инструменты функционального программирования IME, такие как for/yield синтаксис делает работу намного проще). Принимая во внимание, что если все, что у вас есть, это fetchProfile метод, который при запуске немедленно запускает HTTP-запрос, а затем, если ваша логика кода запрашивает один и тот же профиль дважды, нет способа избежать выборки одного и того же профиля дважды.

Но это не совсем Future По сути, и IMO, этот пост в блоге больше сбивает с толку, чем полезно.

Другие вопросы по тегам