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 un miembro selection
que sea aplicable args
(incluso después de intentar convertir args
con vistas implícitas). En este caso, el compilador busca miembros implícitos, definidos localmente en los ámbitos actuales o delimitadores, heredados o importados, que son funciones desde el tipo de ese the.prefix
tipo hasta un tipo con selection
métodos implícitos definidos o 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>
Acceso a un parámetro implícito introducido por un contexto limitado
Los parámetros implícitos son posiblemente una característica más importante de Scala que las Vistas implícitas. Soportan el patrón de clase de tipo. La biblioteca estándar usa esto en algunos lugares: vea scala.Ordering
y cómo se usa SeqLike#sorted
. Los parámetros implícitos también se utilizan para pasar manifiestos de matriz e CanBuildFrom
instancias.
Scala 2.8 permite una sintaxis abreviada para parámetros implícitos, llamados límites de contexto. 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 reescribirse como:
def foo[A: M]
Pero, ¿qué sentido tiene pasar el parámetro implícito pero no nombrarlo? ¿Cómo puede ser útil esto al implementar el método foo
?
A menudo, no es necesario hacer referencia directa al parámetro implícito, se canalizará como un argumento implícito a otro método que se llama. Si es necesario, aún puede conservar la firma del método con el Context Bound 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 clases 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é sucede si queremos cambiar la forma en que se genera el nombre? Podemos llamar explícitamente PersonShow
, pasar explícitamente una alternativa Show[String]
, pero queremos que el compilador pase la Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Implicitly
está disponible en Scala 2.8 y se define en Predef como:Se usa comúnmente para verificar si un valor implícito de tipo
T
está disponible y devolverlo si ese es el caso.Ejemplo simple de la presentación del retrónimo :
fuente
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") )
, especialmente para recuperar un parámetro implícito introducido por un Context Bound:def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
Una respuesta de "enseñarle a pescar" es usar el índice de miembros alfabéticos actualmente disponible en los nightlies de Scaladoc . Las letras (y
#
, para los nombres no alfabéticos) en la parte superior del panel del paquete / clase son enlaces al índice de los nombres de los miembros que comienzan con esa letra (en todas las clases). Si eligeI
, por ejemplo, encontrará laimplicitly
entrada con una sola aparición, enPredef
, que puede visitar desde el enlace allí.fuente
implicit
parece ser una característica importante del lenguaje en Scala, y definitivamente merece una explicación adecuada. Pensar que los documentos que detallan solo un recuento de firmas de tipo parece más una autogratificación intelectual que una respuesta genuina. Vea las preguntas específicas formuladas por el OP: ¿qué es y cómo se usa? Ni respondido por esto, ni en los documentos nocturnos a los que ni siquiera proporciona un enlace real. scala-lang.org/files/archive/nightly/docs/library/… Esto no enseña nada. Consulte Niklaus Wirth o Turbo Pascal para ver ejemplos de documentos genuinos. -1implicit
yimplicitly
están relacionados, pero son muy distintos. Laimplicit
palabra clave es parte del lenguaje.implicitly
se define en código Scala simple en la biblioteca estándar. Dado que los documentos en línea incluyen enlaces de origen, creo que aún es mejor remitir a los interrogadores a esos documentos y a la fuente vinculada.