Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:用于理解的可重写隐式_Scala_Overriding_Future_For Comprehension_Implicits - Fatal编程技术网

Scala:用于理解的可重写隐式

Scala:用于理解的可重写隐式,scala,overriding,future,for-comprehension,implicits,Scala,Overriding,Future,For Comprehension,Implicits,我试图通过API定义隐式,并希望允许客户端重写它们。下面是一个讨论:[我已经用最简单的解决方案尝试过了。它可以按预期工作。现在我想用相同的方式定义基于未来的API,ExecutionContext定义为隐式,并带有默认值 /** * Client can reuse default implicit execution context or override it */ trait CappuccinoWithOverridableExecutionContext { import

我试图通过API定义隐式,并希望允许客户端重写它们。下面是一个讨论:[我已经用最简单的解决方案尝试过了。它可以按预期工作。现在我想用相同的方式定义基于未来的API,ExecutionContext定义为隐式,并带有默认值

/**
  * Client can reuse default implicit execution context or override it
  */
trait CappuccinoWithOverridableExecutionContext {
  import scala.concurrent.ExecutionContext.Implicits.global
  import scala.concurrent.Future
  import scala.util.Random
  import com.savdev.fp.monad.composition.future.scala.Cappuccino._

  def grind(beans: CoffeeBeans)
           (implicit executor:ExecutionContext = global )
  : Future[GroundCoffee] = Future {
    println("01.Start start grinding..., " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    if (beans == "baked beans") throw GrindingException("are you joking?")
    println("01.End finished grinding...")
    s"ground coffee of $beans"
  }(implicitly(executor))

  def heatWater(water: Water)
               (implicit executor:ExecutionContext = global )
  : Future[Water] = Future {
    println("02.Start heating the water now, " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("02.End hot, it's hot!")
    water.copy(temperature = 85)
  }(implicitly(executor))

  def frothMilk(milk: Milk)
               (implicit executor:ExecutionContext = global )
  : Future[FrothedMilk] = Future {
    println("03.Start milk frothing system engaged!, " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("03.End shutting down milk frothing system")
    s"frothed $milk"
  }(implicitly(executor))

  def brew(coffee: GroundCoffee, heatedWater: Water)
          (implicit executor:ExecutionContext = global )
  : Future[Espresso] = Future {
    println("04.Start happy brewing :), " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("04.End it's brewed!")
    "espresso"
  }(implicitly(executor))

  def combine(espresso: Espresso, frothedMilk: FrothedMilk)
             (implicit executor:ExecutionContext = global )
  : Future[Cappuccino.Cappuccino] = Future {
    println("05.Start happy combining :), " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("05.End it's combined!")
    "cappuccino"
  } (implicitly(executor))

  // going through these steps asynchroniously:
  def prepareCappuccinoAsynchroniously(implicit executor:ExecutionContext = global )
  : Future[Cappuccino.Cappuccino] = {
    println("Preparing cappucchino with overridable execution context")
    val groundCoffee = grind("arabica beans")(implicitly(executor))
    val heatedWater = heatWater(Water(20))(implicitly(executor))
    val frothedMilk = frothMilk("milk")(implicitly(executor))
    for {
      ground <- groundCoffee
      water <- heatedWater
      foam <- frothedMilk
      espresso <- brew(ground, water)(implicitly(executor))
      cappuchino <- combine(espresso, foam)(implicitly(executor))
    } yield cappuchino
  }

}
我得到了同样的错误:

[ERROR] .../src/main/scala/com/savdev/fp/monad/composition/future/scala/CappuccinoWithOverridableExecutionContext.scala:25: error: ambiguous implicit values:
[ERROR]  both lazy value global in object Implicits of type => scala.concurrent.ExecutionContext
[ERROR]  and value executor of type scala.concurrent.ExecutionContext
[ERROR]  match expected type scala.concurrent.ExecutionContext
[ERROR]   }(implicitly[ExecutionContext])
preparecappuccinoasynchronous
中清除传递
executor
,也没有任何帮助。 @francoisr,你能举一个有效的例子吗,因为你的建议要么不起作用,要么我没有得到正确的答案

更新2。这是一个基于@Levi Ramsey和@ukasz提案的工作版本

/**
  * Client can reuse default implicit execution context or override it
  */
trait CappuccinoWithOverridableExecutionContext {
  import scala.concurrent.Future
  import scala.util.Random
  import com.savdev.fp.monad.composition.future.scala.Cappuccino._

  //do not import it:
  //import scala.concurrent.ExecutionContext.Implicits.global
  val defaultEc = scala.concurrent.ExecutionContext.Implicits.global

  def grind(beans: CoffeeBeans)
           (implicit executor:ExecutionContext = defaultEc)
  : Future[GroundCoffee] = Future {
    println("01.Start start grinding..., " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    if (beans == "baked beans") throw GrindingException("are you joking?")
    println("01.End finished grinding...")
    s"ground coffee of $beans"
  }

  def heatWater(water: Water)
               (implicit executor:ExecutionContext = defaultEc)
  : Future[Water] = Future {
    println("02.Start heating the water now, " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("02.End hot, it's hot!")
    water.copy(temperature = 85)
  }

  def frothMilk(milk: Milk)
               (implicit executor:ExecutionContext = defaultEc )
  : Future[FrothedMilk] = Future {
    println("03.Start milk frothing system engaged!, " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("03.End shutting down milk frothing system")
    s"frothed $milk"
  }

  def brew(coffee: GroundCoffee, heatedWater: Water)
          (implicit executor:ExecutionContext = defaultEc )
  : Future[Espresso] = Future {
    println("04.Start happy brewing :), " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("04.End it's brewed!")
    "espresso"
  }

  def combine(espresso: Espresso, frothedMilk: FrothedMilk)
             (implicit executor:ExecutionContext = defaultEc )
  : Future[Cappuccino.Cappuccino] = Future {
    println("05.Start happy combining :), " +
      "thread: " + Thread.currentThread().getName)
    TimeUnit.SECONDS.sleep(Random.nextInt(3))
    println("05.End it's combined!")
    "cappuccino"
  }

  // going through these steps synchroniously, wrong way:
  def prepareCappuccinoSequentially(implicit executor:ExecutionContext = defaultEc )
  : Future[Cappuccino.Cappuccino] = {
    for {
      ground <- grind("arabica beans")
      water <- heatWater(Water(20))
      foam <- frothMilk("milk")
      espresso <- brew(ground, water)
      cappuchino <- combine(espresso, foam)
    } yield cappuchino
  }

  // going through these steps asynchroniously:
  def prepareCappuccinoAsynchroniously(implicit executor:ExecutionContext = defaultEc)
  : Future[Cappuccino.Cappuccino] = {
    println("Preparing cappucchino with overridable execution context")
    val groundCoffee = grind("arabica beans")
    val heatedWater = heatWater(Water(20))
    val frothedMilk = frothMilk("milk")
    for {
      ground <- groundCoffee
      water <- heatedWater
      foam <- frothedMilk
      espresso <- brew(ground, water)
      cappuchino <- combine(espresso, foam)
    } yield cappuchino
  }

}
/**
*客户端可以重用默认的隐式执行上下文或重写它
*/
trait CappuccinoWithOverridableExecutionContext{
导入scala.concurrent.Future
导入scala.util.Random
导入com.savdev.fp.monad.composition.future.scala.Cappuccino_
//不要导入它:
//导入scala.concurrent.ExecutionContext.Implicits.global
val defaultEc=scala.concurrent.ExecutionContext.Implicits.global
def研磨(咖啡豆:咖啡豆)
(隐式执行器:ExecutionContext=defaultEc)
:Future[磨碎的咖啡]=Future{
println(“01.开始研磨…”+
“线程:”+thread.currentThread().getName)
时间单位。秒。睡眠(随机。nextInt(3))
如果(beans==“bakedbeans”)抛出GrindingException(“你在开玩笑吗?”)
println(“01.结束研磨…”)
s“豆磨咖啡”
}
def热水(水:水)
(隐式执行器:ExecutionContext=defaultEc)
:未来[水]=未来{
println(“02.现在开始加热水,”+
“线程:”+thread.currentThread().getName)
时间单位。秒。睡眠(随机。nextInt(3))
println(“02.End热,很热!”)
水。复印件(温度=85)
}
def泡沫牛奶(牛奶:牛奶)
(隐式执行器:ExecutionContext=defaultEc)
:Future[泡沫牛奶]=Future{
println(“03.启动牛奶起泡系统已启用!”+
“线程:”+thread.currentThread().getName)
时间单位。秒。睡眠(随机。nextInt(3))
println(“03.End关闭牛奶起泡系统”)
s“泡沫牛奶”
}
def冲泡(咖啡:磨咖啡,热水:水)
(隐式执行器:ExecutionContext=defaultEc)
:Future[浓缩咖啡]=Future{
println(“04.Start happy brewing:),”+
“线程:”+thread.currentThread().getName)
时间单位。秒。睡眠(随机。nextInt(3))
println(“04.End,它已经煮好了!”)
“浓缩咖啡”
}
def组合咖啡(浓缩咖啡:浓缩咖啡,泡沫牛奶:泡沫牛奶)
(隐式执行器:ExecutionContext=defaultEc)
:Future[卡布奇诺.卡布奇诺]=Future{
println(“05.开始快乐组合:),”+
“线程:”+thread.currentThread().getName)
时间单位。秒。睡眠(随机。nextInt(3))
println(“05.End它被合并了!”)
“卡布奇诺”
}
//以错误的方式同步执行这些步骤:
def preparecappuccinosequentily(隐式执行器:ExecutionContext=defaultEc)
:Future[Cappuccino.Cappuccino]={
为了{

地面您不需要在
preparecappuccinoasynchronously
中的任何位置显式传递
executor
,因为
preparecappuccinoasynchronously
范围内的隐式参数将优先于
全局导入

隐式
方法实际上不是一个关键字,而是在
scala.Predef
中定义的一个实际方法。它的实现如下:

def implicitly[T](implicit t: T): T = t
它不是要被赋予它的参数,而是要强制查找给定类型的隐式。也就是说,如果需要隐式提供
T
,可以使用
val T=implicitly[T]
强制它

在您的案例中,您根本不需要隐式地使用
,因为您声明了一个
隐式
参数,因此您已经有了它的名称。此
隐式
方法通常与上下文绑定一起使用,这是一个密切相关但稍微高级的概念。您可以在您感兴趣的网站中查找它,但它没有这对你的问题并不重要

尝试通过隐式删除任何
,让隐式完成工作。下面是一个简短的示例:

def grind(beans: CoffeeBeans)(implicit executor:ExecutionContext = global): Future[GroundCoffee] = Future { ??? }(executor)
实际上,您甚至应该能够删除
executor
部分,只编写

def grind(beans: CoffeeBeans)(implicit executor:ExecutionContext = global): Future[GroundCoffee] = Future { ??? }

编辑:我误读了你的帖子,你需要使用
import scala.concurrent.ExecutionContext.global
而不是
import scala.concurrent.ExecutionContext.Implicits.global
,因为隐式导入
global
会在这里造成歧义。

你不需要显式传递
executer
任何地方e> PrepareCapuccinoAsynchronously
,因为
PrepareCapuccinoAsynchronously
范围内的隐式参数将优先于
全局导入

隐式
方法实际上不是一个关键字,而是在
scala.Predef
中定义的一个实际方法。它的实现如下:

def implicitly[T](implicit t: T): T = t
它不是要被赋予它的参数,而是要强制查找给定类型的隐式。也就是说,如果需要隐式提供
T
,可以使用
val T=implicitly[T]
强制它

在您的案例中,您根本不需要隐式地使用
,因为您声明了一个
隐式
参数,因此您已经有了它的名称。此
隐式
方法通常与上下文绑定一起使用,这是一个密切相关但稍微高级的概念。您可以在您感兴趣的网站中查找它,但它没有这对你的问题并不重要

尝试通过隐式删除任何
,让隐式完成工作。下面是一个简短的示例:

def grind(beans: CoffeeBeans)(implicit executor:ExecutionContext = global): Future[GroundCoffee] = Future { ??? }(executor)
实际上,您甚至应该能够删除
executor
部分,只编写

def grind(beans: CoffeeBeans)(implicit executor:ExecutionContext = global): Future[GroundCoffee] = Future { ??? }
编辑:我看错了你的pos
object EcTest extends App {

  import scala.concurrent.Future
  import scala.concurrent.ExecutionContext
  import java.util.concurrent.Executors


  val default = scala.concurrent.ExecutionContext.Implicits.global

  def test(comp: String)(implicit exc: ExecutionContext = default): Future[String] = Future { 
    println("Using executor: " + Thread.currentThread().getName)
    comp 
  }

  test("Use default executor")

  val myExecutor = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor)
  test("Use custom executor")(myExecutor)

}
scalac EcTest.scala
scala EcTest

// output
Using executor: scala-execution-context-global-10
Using executor: pool-1-thread-1