我正在读《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)
如果按顺序运行Futures
,则Await.result
将超时。