[英]scala: override implicit parameter around a call-by-name code block
有沒有辦法覆蓋控制結構塊內調用的函數使用的隱式參數? 我有一些看起來像這樣的代碼:
def g()(implicit y: Int) {
// do stuff with y
}
class A {
implicit val x: Int = 3
def f() {
overrideImplicit(...) { // <-- overrideImplicit() is permitted to do anything it wants make it so that g() sees a different implicit val, as long as we do not explicitly declare "implicit" here (though it could happen within the method/function)
g() // somehow sees the new implicit as opposed to x
}
}
}
我的理解是,即使 overrideImplicit() 在自身內部設置了隱式,g() 仍然會看到當時在范圍內的那個,也就是在 A 中聲明的那個。我意識到這是獲得所需的一種方法行為是在 f() 中明確聲明“隱式 val x2: Int = 4”,但我想避免這種情況並隱藏使用隱式的事實。 有沒有辦法做到這一點? 謝謝。
這目前正在 STM 中完成,如下所示:
implicit object globalCtx extends Ctx
val r = ref(0)
atomic { implicit txn =>
r := 5 // resolves `txn` as the implicit parameter instead of globalCtx
}
所以據我所知,沒有更好的方法來做到這一點。 至少還沒有 - 請參閱有關 SAM(單一抽象方法)類型的討論,並可能將它們添加到 Scala。 有時建議 SAM 閉包可以解決這個問題,如果它們被實現,那么 SAM 閉包內部的隱式在目標類型的上下文中再次解決。
我真的會質疑你為什么想要做這樣的事情背后的原因,因為我相信這可能會導致一些意想不到的行為。
如果你可以接受x
是一個var
(並且可以從overrideImplicit
定義訪問),這可能會讓你接近
def overrideImplicit(i:Int)(block: =>Unit) = {
val old = x
x = i
block
x = old
}
我不確定這樣做的方法,但我也不認為這是一個好主意,因為您不能使用具有相同類型的兩個不同變量,並且即使您讓它工作對於許多人來說,預期行為是什么並不明顯。 您是否考慮過使用可變堆棧? 就像是
object Example {
private[this] val stack = collection.mutable.ArrayStack[Int](0)
def g() { println(stack.top) }
def using(i: Int)(f: => Unit) { stack push i; f; stack pop }
def f() {
using(1) { g }
}
}
這就是我的做法:
trait A {
implicit val unwantedImplicit: X = ...
}
object/class B extends A {
def blockWhereMeWannaOverrideImplicit() = ({
implicit unwantedImplicit: X => // here I have new X instead of one from trait A
...
})(new X)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.