Saltar al contenido

Comprensión implícita en Scala

Basta ya de investigar por internet ya que estás al espacio correcto, tenemos la solución que necesitas encontrar pero sin complicaciones.

Solución:

Explicaré los principales casos de uso de implícitos a continuación, pero para obtener más detalles, consulte el capítulo correspondiente 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 choques, 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 valor implícito Int!

ejemplo:

  // 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"

Conversiones implícitas

Cuando el compilador encuentra una expresión del tipo incorrecto para el contexto, buscará una expresión implícita Function valor de un tipo que le permitirá comprobar el tipo. Entonces, si un A es necesario y encuentra un B, buscará un valor implícito de tipo B => A en alcance (también comprueba algunos otros lugares como en el B y A objetos complementarios, si existen). Ya que defs se puede “expandir eta” en Function objetos, un implicit def xyz(arg: B): A también lo hará.

Entonces, la diferencia entre sus métodos es que el marcado implicit será insertado por usted por el compilador cuando un Double se encuentra pero un Int es requerido.

implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0

funcionará igual que

def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)

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 su primer fragmento de Play:

Las acciones se explican en esta página de la documentación de Play (consulte también los documentos API). Tu estas usando

apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]

sobre 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

request => ...

En una función literal, la parte antes de la => es una declaración de valor y se puede marcar implicit si quieres como en cualquier otro val declaración. Aquí, requestno tiene que estar marcado implicit para que esto escriba check, pero al hacerlo será disponible como 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 el bindFromRequest método en la clase Form requiere un implícito Request argumento.

ADVERTENCIA: contiene sarcasmo juiciosamente! YMMV …

La respuesta de Luigi es completa y correcta. Este es solo para extenderlo un poco con un ejemplo de cómo puede gloriosamente usarlo en exceso. implicitos, como sucede con bastante frecuencia en los proyectos de Scala. En realidad, con tanta frecuencia, es probable que incluso pueda encontrarlo en uno de los “Mejores prácticas” guías.

object HelloWorld 
  case class Text(content: String)
  case class Prefix(text: String)

  implicit def String2Text(content: String)(implicit prefix: Prefix) = 
    Text(prefix.text + " " + content)
  

  def printText(text: Text): Unit = 
    println(text.content)
  

  def main(args: Array[String]): Unit = 
    printText("World!")
  

  // Best to hide this line somewhere below a pile of completely unrelated code.
  // Better yet, import its package from another distant place.
  implicit val prefixLOL = Prefix("Hello")

En scala implícita funciona como:

Convertidor

Inyector de valor de parámetro

Método de extensión

Hay 3 tipos de uso de implícito

  1. Conversión de tipo implícita : Convierte la asignación que produce el error en el tipo previsto

    val x :String = "1"
    
    val y:Int = x
    

Cuerda No es el subtipo de Int , por lo que el error ocurre en la línea 2. Para resolver el error, el compilador buscará un método de este tipo en el alcance que tenga una palabra clave implícita y tome una Cuerda como argumento y devuelve un En t .

asi que

implicit def z(a:String):Int = 2

val x :String = "1"

val y:Int = x // compiler will use z here like val y:Int=z(x)

println(y) // result 2  & no error!
  1. Conversión de receptor implícita: Generalmente, por el 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 el miembro de la clase / objeto de ese receptor.

     class Mahadi
    
     val haveCar:String ="BMW"
    
     
    

    class Johnny

    val haveTv:String = "Sony"

    

   val mahadi = new Mahadi



   mahadi.haveTv // Error happening

Aquí mahadi.haveTv producirá un error. Debido a que el compilador de Scala buscará primero el haveTv propiedad a Mahadi receptor. No encontrará. En segundo lugar, buscará un método en el alcance que tenga palabra clave implícita que toma Objeto Mahadi como argumento y devoluciones Objeto de Johnny. Pero no tiene aquí. Entonces creará error. Pero lo siguiente está bien.

class Mahadi

val haveCar:String ="BMW"



class Johnny

val haveTv:String = "Sony"



val mahadi = new Mahadi

implicit def z(a:Mahadi):Johnny = new Johnny

mahadi.haveTv // compiler will use z here like new Johnny().haveTv

println(mahadi.haveTv)// result Sony & no error
  1. Inyección de parámetros implícitamente: Si llamamos a un método y no pasamos su valor de parámetro, causará un error. El compilador de Scala funciona así: primero intentará pasar el valor, pero no obtendrá ningún valor directo para el parámetro.

     def x(a:Int)= a
    
     x // ERROR happening
    

En segundo lugar, si el parámetro tiene alguna palabra clave implícita, buscará cualquier val en el alcance que tienen el el mismo tipo de valor. Si no se obtiene, se producirá un error.

def x(implicit a:Int)= a

x // error happening here

Para resolver este problema, el compilador buscará un val implícito tener el tipo de Int porque el parámetro a tiene palabra clave implícita.

def x(implicit a:Int)=a

implicit val z:Int =10

x // compiler will use implicit like this x(z)
println(x) // will result 10 & no error.

Otro ejemplo:

def l(implicit b:Int)

def x(implicit a:Int)= l(a)

también podemos escribirlo como-

def x(implicit a:Int)= l

Porque l tiene un parámetro implícito y en el alcance de cuerpo del método x, hay un variable local implícita(los parámetros son variables locales) a que es el parámetro de X, entonces en el cuerpo de xmétodo la firma del método valor del argumento implícito de l es archivado por el Variable implícita local del método x (parámetro) a implícitamente.

Entonces

 def x(implicit a:Int)= l

estará en un compilador como este

def x(implicit a:Int)= l(a)

Otro ejemplo:

def c(implicit k:Int):String = k.toString

def x(a:Int => String):String =a

x
x => c

Causará error, porque C en x x => c Necesita pasar explícitamente un valor en un argumento o un valor implícito en alcance.

Entonces podemos hacer que la función sea literal parámetro explícitamente implícito cuando llamamos al método x

x
implicit x => c // the compiler will set the parameter of c like this c(x)

Esto se ha utilizado en método de acción de Play-Framework

in view folder of app the template is declared like
@()(implicit requestHreader:RequestHeader)

in controller action is like

def index = Action
implicit request =>

Ok(views.html.formpage())  


si no menciona el parámetro de solicitud como implícito explícitamente, debe haber sido escrito-

def index = Action
request =>

Ok(views.html.formpage()(request))  


  1. Método de extensión

Piense, queremos agregar un nuevo método con el objeto Integer. El nombre del método será meterToCm,

> 1 .meterToCm 
res0 100 

para hacer esto, necesitamos crear una clase implícita dentro de un objeto / clase / rasgo. Esta clase no puede ser una clase de caso.

object Extensions
    
    implicit class MeterToCm(meter:Int)
        
        def  meterToCm=
             meter*100
        

    


Nota la clase implícita solo tomará un parámetro de constructor.

Ahora importe la clase implícita en el alcance que desea usar

import  Extensions._

2.meterToCm // result 200

Valoraciones y comentarios

Tienes la opción de añadir valor a nuestra información participando con tu experiencia en los comentarios.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *