Почему Future считается «непрозрачным с точки зрения ссылок»?

Итак... ссылочная прозрачность functional просто означает, что вы должны functional иметь возможность заменить monads ссылку реальной вещью (и functional-programming наоборот) без изменения общей scala симатики или поведения. Как scala и математика.

Итак, допустим, у functional вас есть x = 4 и y = 5, тогда x + y, 4 + y, x + 5 и functional-programming 4 + 5 почти одно и то же. И могут scala быть заменены друг другом, когда monads вы хотите.

Но... взгляните monad на следующие две вещи...

val f1 = Future { println("Hi") }

val f2 = f1
val f1 = Future { println("Hi") }

val f2 = Future { println("Hi") }

Вы functional можете попробовать запустить functional-programming его. Поведение этих двух functional-programming программ не будет одинаковым.

Scala functional Future с нетерпением оцениваются... а monads это значит, что нет возможности functional написать Future { println("Hi") } в вашем коде, не scala выполняя его как отдельное scala поведение.

Имейте в виду, что functional это связано не только с наличием functional-programming side effects. Да, пример, который я использовал functional-programming здесь с println, был side effect, но это было monad просто для того, чтобы сделать monads разницу в поведении очевидной.

Даже scala если вы используете что-то functional-programming для suspend side effect внутри Future, вы получите functional два suspended side effects вместо одного. И как functional только эти suspended side effects будут переданы monads interpreater, одно и то же действие произойдет functional дважды.

В следующем примере, даже monads если мы приостановим print side-effect, обернув monads его в IO, расширенная оценочная monad часть программы все равно monad может вызвать различное поведение, даже scala если все во вселенной абсолютно monad одинаково для двух случаев.

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

// cpu bound
// takes around 80 miliseconds
// we have only 1 core
def veryExpensiveComputation(input: Int): Int = ???

def impl1(): Unit = {
  val f1 = Future {
    val result = veryExpensiveComputation(10)
    IO {
      println(result)
      result
    }
  }

  val f2 = f1

  val f3 = f1

  val futures = Future.sequence(Seq(f1, f2, f3))

  val ios = Await.result(futures, 100 milli)
}

def impl2(): Unit = {
  val f1 = Future {
    val result = veryExpensiveComputation(10)
    IO {
      println(result)
      result
    }
  }
  val f2 = Future {
    val result = veryExpensiveComputation(10)
    IO {
      println(result)
      result
    }
  }
  val f3 = Future {
    val result = veryExpensiveComputation(10)
    IO {
      println(result)
      result
    }
  }

  val futures = Future.sequence(Seq(f1, f2, f3))

  val ios = Await.result(futures, 100 milli)
}

Первый monad импл вызовет только 1 дорогостоящее functional-programming вычисление, а второй вызовет functional-programming 3 дорогостоящих вычисления. Таким functional образом, во втором примере functional программа завершится ошибкой monads с тайм-аутом.

Если правильно monad написать с помощью IO или ZIO (без monad Future), в обеих реализациях произойдет monad сбой с тайм-аутом.

scala

functional-programming

monads

2022-11-28T06:19:16+00:00