Estaba abriéndome camino a través del tutorial de Scala Playframework y me encontré con este fragmento de código que me tenía desconcertado:
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
Así que decidí investigar y me encontré con esta publicación .
Aún no lo entiendo.
¿Cuál es la diferencia entre esto?
implicit def double2Int(d : Double) : Int = d.toInt
y
def double2IntNonImplicit(d : Double) : Int = d.toInt
aparte del hecho obvio, tienen nombres de métodos diferentes.
¿Cuándo debo usar implicit
y por qué?
scala
syntax
playframework
keyword
Clive
fuente
fuente
Respuestas:
Explicaré los principales casos de uso de implicidades a continuación, pero para más detalles vea el capítulo relevante de Programación en Scala .
Parámetros implícitos
La lista final de parámetros de un método se puede marcar
implicit
, lo que significa que los valores se tomarán del contexto en el que se llaman. Si no hay un valor implícito del tipo correcto en el alcance, no se compilará. Dado que el valor implícito debe resolverse en un solo valor y para evitar conflictos, es una buena idea hacer que el tipo sea específico para su propósito, por ejemplo, ¡no requiera que sus métodos encuentren un implícitoInt
!ejemplo:
Conversiones implícitas
Cuando el compilador encuentra una expresión del tipo incorrecto para el contexto, buscará un
Function
valor implícito de un tipo que le permita verificar el tipo. Entonces, siA
se requiere un y encuentra unB
, buscará un valor implícito de tipoB => A
en el alcance (también verifica algunos otros lugares como en los objetos complementariosB
yA
, si existen). Comodef
s puede ser "expandido en eta" enFunction
objetos, unaimplicit def xyz(arg: B): A
voluntad también lo hará.Entonces, la diferencia entre sus métodos es que
implicit
el compilador insertará el marcado para usted cuandoDouble
se encuentre un peroInt
se requiere un.funcionará igual que
En el segundo, hemos insertado la conversión manualmente; en el primero el compilador hizo lo mismo automáticamente. La conversión es necesaria debido a la anotación de tipo en el lado izquierdo.
Con respecto a tu primer fragmento de Play:
Las acciones se explican en esta página de la documentación de Play (ver también documentos de API ). Tu estas usando
en el
Action
objeto (que es el compañero del rasgo del mismo nombre).Por lo tanto, debemos proporcionar una función como argumento, que se puede escribir como literal en la forma
En una función literal, la parte anterior a la
=>
es una declaración de valor, y puede marcarseimplicit
si lo desea, como en cualquier otraval
declaración. Aquí,request
no tiene que estar marcadoimplicit
para que esto escriba check, pero al hacerlo estará disponible como un valor implícito para cualquier método que pueda necesitarlo dentro de la función (y, por supuesto, también se puede usar explícitamente) . En este caso particular, esto se ha hecho porque elbindFromRequest
método en la clase Form requiere unRequest
argumento implícito .fuente
ADVERTENCIA: contiene sarcasmo juiciosamente! YMMV ...
La respuesta de Luigi es completa y correcta. Éste es sólo para extenderla un poco con un ejemplo de cómo se puede gloriosamente uso excesivo implícitos , como ocurre muy a menudo en proyectos Scala. En realidad, tan a menudo, incluso puede encontrarlo en una de las guías de "Mejores prácticas" .
fuente
Por qué y cuándo debe marcar el
request
parámetro comoimplicit
:Algunos métodos que utilizará en el cuerpo de su acción tienen una lista de parámetros implícitos como, por ejemplo, Form.scala define un método:
No necesariamente se da cuenta de esto, ya que simplemente llamaría
myForm.bindFromRequest()
. No tiene que proporcionar los argumentos implícitos explícitamente. No, deja el compilador para buscar cualquier objeto candidato válido para pasar cada vez que se encuentra con una llamada a un método que requiere una instancia de la solicitud. Ya que hacer un pedido disponibles, todo lo que necesita hacer es para marcarlo comoimplicit
.Usted lo marca explícitamente como disponible para uso implícito .
Usted le sugiere al compilador que está "bien" usar el objeto de solicitud enviado por el marco de Play (que le dimos el nombre de "solicitud" pero que podría haber usado solo "r" o "req") donde sea necesario, "a escondidas" .
¿Míralo? ¡No está allí, pero está allí!
Simplemente sucede sin tener que colocarlo manualmente en cada lugar que sea necesario (pero puede pasarlo explícitamente, si lo desea, sin importar si está marcado
implicit
o no):Sin marcarlo como implícito, tendría que hacer lo anterior. Marcarlo como implícito no es necesario.
¿Cuándo debe marcar la solicitud como
implicit
? Realmente solo necesita hacerlo si está utilizando métodos que declaran una lista implícita de parámetros esperando una instancia de la Solicitud . Pero para simplificarlo, puede acostumbrarse a marcar la solicitudimplicit
siempre . De esa manera puedes escribir un hermoso código conciso.fuente
En scala funciona implícitamente como :
Convertidor
Valor del parámetro inyector
Hay 3 tipos de uso de implícito
Conversión de tipo implícita : convierte el error que produce la asignación en el tipo deseado
val x: String = "1"
val y: Int = x
String no es el subtipo de Int , por lo que se produce un error en la línea 2. Para resolver el error, el compilador buscará dicho método en el ámbito que tenga una palabra clave implícita y tome un String como argumento y devuelva un Int .
entonces
Conversión implícita del receptor : generalmente, por receptor, llamamos a las propiedades del objeto, por ejemplo. métodos o variables. Entonces, para llamar a cualquier propiedad por un receptor, la propiedad debe ser miembro de la clase / objeto de ese receptor.
Aquí mahadi.haveTv producirá un error. Debido a que el compilador Scala buscará primero la haveTv propiedad a Mahadi receptor. No lo encontrarás. En segundo lugar, buscará un método en el alcance que tenga una palabra clave implícita que tome el objeto Mahadi como argumento y devuelva el objeto Johnny . Pero no tiene aquí. Entonces creará un error . Pero lo siguiente está bien.
Inyección implícita de parámetros : si llamamos a un método y no pasamos su valor de parámetro, causará un error. El compilador scala funciona así: primero intentará pasar el valor, pero no obtendrá ningún valor directo para el parámetro.
Segundo, si el parámetro tiene alguna palabra clave implícita, buscará cualquier valor en el alcance que tenga el mismo tipo de valor. Si no lo consigue, causará un error.
Para resolver este problema, el compilador buscará un valor implícito que tenga el tipo de Int porque el parámetro a tiene una palabra clave implícita .
Otro ejemplo:
también podemos escribirlo como
Debido a que l tiene un parámetro implícito y dentro del alcance del cuerpo del método x , existe una variable local implícita (los parámetros son variables locales ) a, que es el parámetro de x , por lo que en el cuerpo del método x el valor de argumento implícito de la firma del método l es presentada por la variable de del método local x implícita (parámetro)
a
implícitamente .Entonces
estará en un compilador como este
Otro ejemplo:
que causará error, porque c en x {x => c} necesita explícitamente el valor de paso en el argumento o val implícita en su alcance .
Entonces podemos hacer que el parámetro de la función literal sea explícitamente implícito cuando llamamos al método x
Esto se ha utilizado en el método de acción de Play-Framework
si no menciona el parámetro de solicitud como implícito explícitamente, entonces debe haber sido escrito
fuente
Además, en el caso anterior debería haber una
only one
función implícita cuyo tipo esdouble => Int
. De lo contrario, el compilador se confunde y no se compilará correctamente.fuente
Un ejemplo muy básico de Implicits in scala.
Parámetros implícitos :
Nota: Aquí se
multiplier
pasará implícitamente a la funciónmultiply
. Los parámetros que faltan en la llamada a la función se buscan por tipo en el alcance actual, lo que significa que el código no se compilará si no hay una variable implícita de tipo Int en el alcance.Conversiones implícitas :
Nota: Cuando llamamos a la
multiply
función que pasa un valor doble, el compilador intentará encontrar la función implícita de conversión en el ámbito actual, que convierteInt
aDouble
(Como parámetro demultiply
aceptación de funciónInt
). Si no hay unaconvert
función implícita , el compilador no compilará el código.fuente
Tenía exactamente la misma pregunta que usted y creo que debería compartir cómo comencé a entenderla con algunos ejemplos realmente simples (tenga en cuenta que solo cubre los casos de uso comunes).
Hay dos casos de uso comunes en el uso de Scala
implicit
.Los ejemplos son los siguientes
Usándolo en una variable . Como puede ver, si la
implicit
palabra clave se usa en la última lista de parámetros, se usará la variable más cercana.Usándolo en una función . Como puede ver, si
implicit
se usa en la función, se usará el método de conversión de tipo más cercano.Espero que esto pueda ayudar.
fuente