4

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

我尝试根据这篇文章进行简单的仿真。在哪里解释了如何Action工作PlayFramework。这也与那个有关。

以下代码就是为此目的:

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,但它存在,因为匿名函数通过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)

}
4

2 回答 2

6

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

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

您可以修复所有调用的隐式值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声明更改为从隐式范围获取值。

我希望你现在能更好地理解隐式,一开始它们可能有点难以理解。

于 2013-09-17T17:06:42.123 回答
0

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

对于接受(匿名)函数的函数,使用implicit intValue或仅使用implicit request一个参数并不是一个好主意。implicitly()

为什么不呢,因为:

说,如果在 b lock(...)inapply()我会使用implicitly[Request],那么我是否使用“隐式请求”都没有关系 - 它将使用在某处隐式定义的请求。即使我将自己的请求传递给Action { myOwnRequest =Result }.

对于这种特殊情况,最好在第二个参数中使用curryingand two argumentsand.. - (first)(second) 使用implicit

像这样:

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

在此处查看我围绕此示例/用例所做的一些努力。


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

fun{ implicit intValue =>  {intValue.toString}

或者那个(更新版本):

val action = Action { implicit request =>
    Result("Got request [" + request + "]")
  }
于 2013-09-17T19:57:52.760 回答