Scala通过将函数作为参数传递隐式参数来感受adnvatage

时间:2013-09-17 16:14:49

标签: scala

我尝试在Scala中感受implicit参数的优势。 (已编辑:使用匿名函数时的特殊情况。请查看此问题中的链接)

我尝试根据this帖子进行简单的模拟。在Action解释了PlayFramework的工作原理。这也与that有关。

以下代码用于此目的:

object ImplicitArguments extends App {

  implicit val intValue = 1 // this is exiting value to be passed implicitly to everyone who might use it

  def fun(block: Int=>String): String = { // we do not use _implicit_ here !
    block(2)  // ?? how to avoid passing '2' but make use of that would be passed implicitly ?
  }

  // here we use _implicit_ keyword to make it know that the value should be passed !
  val result = fun{ implicit intValue =>  {  // this is my 'block'
                         intValue.toString     // (which is anonymous function)
                       }
  }

 println(result) // prints 2

}

我想要打印“1”。

如何避免传递魔法“2”但使用隐含定义的“1”?

另请参阅我们在定义中不使用implicit的{​​{3}},但它存在,因为匿名函数传递了implicit

编辑: 为了以防万一,我发布了另一个例子 - 简单模拟Play'Action如何工作:

  object ImplicitArguments extends App {

  case class Request(msg:String)

  implicit val request = Request("my request")

  case class Result(msg:String)

  case class Action(result:Result)
  object Action {
    def apply(block:Request => Result):Action = {
     val result = block(...) // what should be here ??
     new Action(result)
    }
  }

  val action = Action { implicit request =>
    Result("Got request [" + request + "]")
  }

  println(action)

}

2 个答案:

答案 0 :(得分:6)

Implicits不能像这样工作。没有魔力。它们只是(通常)隐藏的参数,因此在调用函数时会被解析。

有两种方法可以使代码正常工作。

您可以修复fun

的所有调用的隐含值
def fun(block: Int=>String): String = { 
  block(implicitly[Int]) 
}

implicitly是Predef中定义的函数。再一次没有魔力。这是它的定义

def implicitly[A](implicit value: A) = value

但这意味着当声明 fun而不是每次调用时,它将解析隐含值。

如果要为不同的调用使用不同的值,将需要来添加隐式参数

def fun(block: Int=>String)(implicit value: Int): String = { 
  block(value) 
}

现在这将取决于呼叫站点的隐式范围。你可以像这样轻松覆盖它

val result = fun{ _.toString }(3)

,结果将是"3",因为最后有明确的3。但是,没有办法从声明中神奇地更改fun以从隐式作用域中获取值。

我希望你现在能够更好地理解隐含的内容,起初可能有点棘手。

答案 1 :(得分:0)

对于我提出的那个特殊情况,似乎答案可能是这样的:

对于接受(匿名)的函数,仅使用一个参数implicit intValueimplicit request以及implicitly()并不是一个好主意功能

为什么不呢,因为:

比方说,如果在lock(...)中的apply()我会使用implicitly[Request],那么 我是否使用“隐式请求”并不重要 - 它会使用 在某处隐式定义的请求。即使我会通过我的 自己对Action { myOwnRequest =Result }的请求。

对于特定情况,最好在第二个参数中使用curryingtwo arguments和.. - (第一个)(第二个)使用implicit

像这样:

def apply(block:Request => Result)(implicit request:Request):Action2

在此处查看此示例/用例的little effort


但是,到目前为止,我没有看到任何关于如何通过传递(匿名)函数作为参数来使用implicit的好例子(我的初始问题):

fun{ implicit intValue =>  {intValue.toString}

或那个(更新版本):

val action = Action { implicit request =>
    Result("Got request [" + request + "]")
  }