簡體   English   中英

scala:覆蓋按名稱調用代碼塊周圍的隱式參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM