def conversion scala implicits

conversion - ¿Qué es el identificador de Scala "implícitamente"?



scala implicit conversion (3)

Aquí hay algunas razones para usar el método deliciosamente simple implicitly .

Para comprender / solucionar problemas de vistas implícitas

Una Vista implícita se puede activar cuando el prefijo de una selección (considere por ejemplo, the.prefix.selection(args) no contiene una selection miembro que sea aplicable a args (incluso después de tratar de convertir args con Vistas implícitas). En este caso, el compilador busca miembros implícitos, localmente definidos en los ámbitos actuales o adjuntos, heredados o importados, que son funciones del tipo de ese the.prefix a un tipo con selection definida, o métodos implícitos equivalentes.

scala> 1.min(2) // Int doesn''t have min defined, where did that come from? res21: Int = 1 scala> implicitly[Int => { def min(i: Int): Any }] res22: (Int) => AnyRef{def min(i: Int): Any} = <function1> scala> res22(1) // res23: AnyRef{def min(i: Int): Int} = 1 scala> .getClass res24: java.lang.Class[_] = class scala.runtime.RichInt

Las Vistas implícitas también se pueden activar cuando una expresión no se ajusta al Tipo esperado, como se muestra a continuación:

scala> 1: scala.runtime.RichInt res25: scala.runtime.RichInt = 1

Aquí el compilador busca esta función:

scala> implicitly[Int => scala.runtime.RichInt] res26: (Int) => scala.runtime.RichInt = <function1>

Acceder a un parámetro implícito introducido por un contexto enlazado

Los parámetros implícitos son sin duda una característica más importante de Scala que las Vistas implícitas. Son compatibles con el patrón de clase de tipo. La biblioteca estándar usa esto en algunos lugares: consulte el orden de scala.Ordering cómo se usa en SeqLike#sorted . Los Parámetros implícitos también se usan para pasar los manifiestos de Array y CanBuildFrom instancias de CanBuildFrom .

Scala 2.8 permite una sintaxis abreviada para parámetros implícitos, llamada Context Bounds. Brevemente, un método con un parámetro de tipo A que requiere un parámetro implícito de tipo M[A] :

def foo[A](implicit ma: M[A])

puede ser reescrito como:

def foo[A: M]

¿Pero cuál es el punto de pasar el parámetro implícito pero no nombrarlo? ¿Cómo puede ser útil cuando se implementa el método foo ?

A menudo, el parámetro implícito no necesita ser referido directamente, será un túnel a través de un argumento implícito a otro método que se llama. Si es necesario, aún puede conservar la firma del método breve con el límite de contexto y llamar implicitly para materializar el valor:

def foo[A: M] = { val ma = implicitly[M[A]] }

Pasar un subconjunto de parámetros implícitos explícitamente

Supongamos que está llamando a un método que imprime bastante a una persona, utilizando un enfoque basado en clase de tipo:

trait Show[T] { def show(t: T): String } object Show { implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString } implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s } def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase } } case class Person(name: String, age: Int) object Person { implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] { def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")" } } val p = Person("bob", 25) implicitly[Show[Person]].show(p)

¿Qué pasa si queremos cambiar la forma en que se emite el nombre? Podemos llamar explícitamente a PersonShow , pasar explícitamente un Show[String] alternativo, pero queremos que el compilador pase el Show[Int] .

Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)

He visto una función llamada implicitly utilizada en los ejemplos de Scala. ¿Qué es y cómo se usa?

Ejemplo aquí :

scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo { | implicit def stringImpl = new Foo[String] { | def apply(list : List[String]) = println("String") | } | implicit def intImpl = new Foo[Int] { | def apply(list : List[Int]) = println("Int") | } | } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x) defined trait Foo defined module Foo foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit scala> foo(1) <console>:8: error: type mismatch; found : Int(1) required: List[?] foo(1) ^ scala> foo(List(1,2,3)) Int scala> foo(List("a","b","c")) String scala> foo(List(1.0)) <console>:8: error: could not find implicit value for evidence parameter of type Foo[Double] foo(List(1.0)) ^

Tenga en cuenta que tenemos que escribir implicitly[Foo[A]].apply(x) ya que el compilador cree que implicitly[Foo[A]](x) significa que llamamos implicitly con parámetros.

Ver también Cómo investigar objetos / tipos / etc. de Scala REPL? y ¿Dónde busca Scala las implicidades?


Una respuesta de "enseñarle a pescar" es usar el índice de miembro alfabético actualmente disponible en los Nightlies de Scaladoc . Las letras (y el # , para nombres no alfabéticos) en la parte superior del panel paquete / clase son enlaces al índice para nombres de miembros que comienzan con esa letra (en todas las clases). Si elige I , por ejemplo, encontrará la entrada implicitly con una ocurrencia, en Predef , que puede visitar desde el enlace allí.


Implicitly está disponible en Scala 2.8 y se define en Predef como:

def implicitly[T](implicit e: T): T = e

Se usa comúnmente para verificar si un valor implícito de tipo T está disponible y devolverlo si tal es el caso.

Ejemplo simple de la presentación de retronym :

scala> implicit val a = "test" // define an implicit value of type String a: java.lang.String = test scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b b: String = test scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c <console>:6: error: could not find implicit value for parameter e: Int val c = implicitly[Int] ^