¿Qué es un "limitado al contexto" en Scala?
Una de las nuevas características de Scala 2.8 son los límites de contexto. ¿Qué está vinculado a un contexto y dónde es útil?
Por supuesto, busqué primero (y encontré, por ejemplo, esto ), pero no pude encontrar ninguna información realmente clara y detallada.
La respuesta de Robert cubre los detalles técnicos de Context Bounds. Te daré mi interpretación de su significado.
En Scala, un límite de vista ( A <% B
) captura el concepto de "puede verse como" (mientras que un límite superior <:
captura el concepto de "es un"). Un contexto enlazado ( A : C
) dice "tiene un" sobre un tipo. Puede leer los ejemplos sobre manifiestos como " T
tiene un Manifest
". El ejemplo al que vinculó about Ordered
vs Ordering
ilustra la diferencia. Un método
def example[T <% Ordered[T]](param: T)
dice que el parámetro puede verse como un archivo Ordered
. Comparar con
def example[T : Ordering](param: T)
que dice que el parámetro tiene un Ordering
.
En términos de uso, tomó un tiempo establecer las convenciones, pero se prefieren los límites de contexto a los límites de vista ( los límites de vista ahora están en desuso ). Una sugerencia es que se prefiere un límite de contexto cuando necesita transferir una definición implícita de un ámbito a otro sin necesidad de hacer referencia a ella directamente (este es ciertamente el caso de lo que se ClassManifest
usa para crear una matriz).
Otra forma de pensar sobre los límites de vista y los límites de contexto es que el primero transfiere conversiones implícitas desde el alcance de la persona que llama. El segundo transfiere objetos implícitos desde el alcance de la persona que llama.
¿ Encontraste este artículo ? Cubre la nueva función vinculada al contexto, dentro del contexto de las mejoras de la matriz.
Generalmente, un parámetro de tipo con un contexto vinculado tiene la forma [T: Bound]
; se expande a un parámetro de tipo simple T
junto con un parámetro implícito de tipo Bound[T]
.
Considere el método tabulate
que forma una matriz a partir de los resultados de aplicar una función dada f en un rango de números desde 0 hasta una longitud determinada. Hasta Scala 2.7, la tabulación se podía escribir de la siguiente manera:
def tabulate[T](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
En Scala 2.8 esto ya no es posible porque la información del tiempo de ejecución es necesaria para crear la representación correcta de Array[T]
. Es necesario proporcionar esta información pasando a ClassManifest[T]
al método como parámetro implícito:
def tabulate[T](len: Int, f: Int => T)(implicit m: ClassManifest[T]) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
Como forma abreviada, se puede utilizar un límite de contextoT
en el parámetro de tipo , dando:
def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}