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

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

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

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

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

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

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

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

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

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

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

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

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 вычисление, а второй вызовет scala 3 дорогостоящих вычисления. Таким scala образом, во втором примере monads программа завершится ошибкой functional с тайм-аутом.

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

scala

functional-programming

monads

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