【发布时间】:2014-05-08 20:48:50
【问题描述】:
我在使用隐式 var 和期货时遇到问题。假设如下场景:
object ImplicitMess extends App {
implicit var curStr = "Initial Value"
def useImplicit(implicit str: String) = {
println(str)
str.length
}
useImplicit
val ftr = future {
Thread.sleep(1000)
useImplicit
}
curStr = "Modified Value"
Await.ready(ftr, 2.seconds)
}
在创建未来时,隐含值是“初始值”,但当它实际执行时,值是“修改后的值”,这不是所需的行为。 之所以这样,是因为未来的主体引用的是 var 而不是当前值。
所以我想出的第一个解决方案是在一个块内的 val 中捕获 var 值,认为这将使隐式更接近并解决歧义。但由于“模糊隐含值”错误,它甚至无法编译。
...
val ftr = {
implicit val str = curStr
future {
Thread.sleep(1000)
useImplicit
}
}
...
所以,我想要的是某种包装异步代码(期货上的任何操作)的方法,您可以在定义异步代码时使用固定的隐式值,而不是在评估它时。
这是一个库,示例是问题的真正简化版本,所以我需要这样的东西有两个原因:1)为了实现所需的行为。 2) 让用户有责任了解所有这些复杂性。
...
val ftr = fixImplicit {
// All within this block will use the current value of the implicit var
future {
Thread.sleep(1000)
useImplicit
}
}
...
你认为这可能吗?
谢谢。
[已编辑] 为所有对 var 使用感到恐惧的人添加一些上下文。
我需要这个来改进我的一个项目,即 akka-contextual-actor (github),它是关于在参与者之间传播公共上下文以避免使用方面库。因此,主要需求之一是透明地进行,而不是显式地传递隐式。
我在很大程度上依赖于隐式转换来包装和解包消息,除了将上下文放在 actor 的 var 中以使其在接收中可用之外,我没有其他选择。您可以查看代码以了解我是如何做到的。
再次感谢。
加斯顿。
@ktonga
【问题讨论】:
-
我从来没有意识到隐式变量甚至是可能的,并且在 Scala 中想不出比这更可怕的事情了。您确定必须这样做吗?
-
@TravisBrown 你的隐式执行上下文应该完全是一个 var,所以你可以随时切换它!
-
嗨@TravisBrown,你用“更可怕的东西”让我大笑起来。我真的很确定第一个答案或评论会警告我不要使用 vars。我知道这很糟糕。我已经编辑了添加更多上下文的问题。
标签: scala