我正在读“Scala with cats”一书。作者说,Semigroupal并不总能提供我们期望的行为。他展示了这个例子:
import cats.Semigroupal
import cats.instances.future._ // for Semigroupal
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.language.higherKinds
val futurePair = Semigroupal[Future].
product(Future("Hello"), Future(123))
Await.result(futurePair, 1.second)
// res1: (String, Int) = (Hello,123)
在书中结果是(Hello,123)
但我们期待Future(Hello, 123)
。据我所知,我们失去了Future
,所以没有预期的背景。
我决定重现这个例子并得到这个结果:
Future(Success((Hello,123)))
在这里的背景。嗯。然后我尝试了这个实验:
val futurePair = Semigroupal[Future]
.product(Future{Thread.sleep(100);"Hello"}, Future(123))
println(futurePair)
结果是Future(<not completed>)
。正如我所料。
所以我无法理解Future
有什么问题。我得到了预期的行为,我没有失去计算的背景。也许是因为Future
在创建的那一刻开始计算?但为什么这是一个问题呢?
Await.result
剥离了Future
,而不是product
,所以你的期望与这里的实际行为相匹配。他所说的是有些人可能期望顺序执行而不是并行,因为其他半群的表现如何,但他选择了一个糟糕的代码示例,因为他的例子的结果是相同的,无论是并行执行还是顺序执行。一个更好的例子来说明作者的观点是这样的:
val futurePair = Semigroupal[Future].product(
Future{Thread.sleep(750); "Hello},
Future{Thread.sleep(750); 123}
)
Await.result(futurePair, 1.second)
如果Await.result
按顺序运行,Futures
会超时。