了解Scala中的隐式 [英] Understanding implicit in Scala
问题描述
我正在遍历Scala播放框架教程,并且遇到了使我感到困惑的这段代码:
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
所以我决定进行调查,并发现了这篇文章. >
我还是不明白.
这有什么区别:
implicit def double2Int(d : Double) : Int = d.toInt
和
def double2IntNonImplicit(d : Double) : Int = d.toInt
除了明显的事实,它们具有不同的方法名称.
我什么时候应该使用implicit
,为什么?
def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)
第二步,我们手动插入了转换;首先,编译器会自动执行相同的操作.由于左侧有类型注释,因此需要进行转换.
关于Play中的第一个片段:
有关操作的信息,请参见Play文档中的此页面(另请参见 API文档).您正在使用
apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
(同名特征的伴侣). 因此,我们需要提供一个Function作为参数,可以将其写为 在函数文字中, I was making my way through the Scala playframework tutorial and I came across this snippet of code which had me puzzled: So I decided to investigate and came across this post. I still don't get it. What is the difference between this: and other than the obvious fact they have different method names. When should I use I'll explain the main use cases of implicits below, but for more detail see the relevant chapter of Programming in Scala. Implicit parameters The final parameter list on a method can be marked example: Implicit conversions When the compiler finds an expression of the wrong type for the context, it will look for an implicit So the difference between your methods is that the one marked will work the same as In the second we've inserted the conversion manually; in the first the compiler did the same automatically. The conversion is required because of the type annotation on the left hand side. Regarding your first snippet from Play: Actions are explained on this page from the Play documentation (see also API docs). You are using on the So we need to supply a Function as the argument, which can be written as a literal in the form In a function literal, the part before the 这篇关于了解Scala中的隐式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!request => ...
=>
之前的部分是值声明,并且可以将其标记为implicit
,就像在其他任何val
声明中一样.在这里,不必request
标记为implicit
来进行类型检查,但是这样做可以将用作任何方法的隐式值函数中可能需要它(当然,也可以显式使用它).在此特定情况下,已完成此操作,因为Request
参数.def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
implicit def double2Int(d : Double) : Int = d.toInt
def double2IntNonImplicit(d : Double) : Int = d.toInt
implicit
and why?implicit
, which means the values will be taken from the context in which they are called. If there is no implicit value of the right type in scope, it will not compile. Since the implicit value must resolve to a single value and to avoid clashes, it's a good idea to make the type specific to its purpose, e.g. don't require your methods to find an implicit Int
! // probably in a library
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
// then probably in your application
implicit val myImplicitPrefixer = new Prefixer("***")
addPrefix("abc") // returns "***abc"
Function
value of a type that will allow it to typecheck. So if an A
is required and it finds a B
, it will look for an implicit value of type B => A
in scope (it also checks some other places like in the B
and A
companion objects, if they exist). Since def
s can be "eta-expanded" into Function
objects, an implicit def xyz(arg: B): A
will do as well.implicit
will be inserted for you by the compiler when a Double
is found but an Int
is required. implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0
def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)
apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
Action
object (which is the companion to the trait of the same name).request => ...
=>
is a value declaration, and can be marked implicit
if you want, just like in any other val
declaration. Here, request
doesn't have to be marked implicit
for this to type check, but by doing so it will be available as an implicit value for any methods that might need it within the function (and of course, it can be used explicitly as well). In this particular case, this has been done because the bindFromRequest
method on the Form class requires an implicit Request
argument.