One of the new features of Scala 2.8 are context bounds. What is a context bound and where is it useful?
Of course I searched first (and found for example this) but I couldn't find any really clear and detailed information.
Robert's answer covers the techinal details of Context Bounds. I'll give you my interpretation of their meaning.
In Scala a View Bound (A <% B
) captures the concept of 'can be seen as' (whereas an upper bound <:
captures the concept of 'is a'). A context bound (A : C
) says 'has a' about a type. You can read the examples about manifests as "T
has a Manifest
". The example you linked to about Ordered
vs Ordering
illustrates the difference. A method
def example[T <% Ordered[T]](param: T)
says that the parameter can be seen as an Ordered
. Compare with
def example[T : Ordering](param: T)
which says that the parameter has an associated Ordering
.
In terms of use, it took a while for conventions to be established, but context bounds are preferred over view bounds (view bounds are now deprecated). One suggestion is that a context bound is preferred when you need to transfer an implicit definition from one scope to another without needing to refer to it directly (this is certainly the case for the ClassManifest
used to create an array).
Another way of thinking about view bounds and context bounds is that the first transfers implicit conversions from the caller's scope. The second transfers implicit objects from the caller's scope.
Did you find this article? It covers the new context bound feature, within the context of array improvements.
Generally, a type parameter with a context bound is of the form [T: Bound]
; it is expanded to plain type parameter T
together with an implicit parameter of type Bound[T]
.
Consider the method tabulate
which forms an array from the results of applying
a given function f on a range of numbers from 0 until a given length. Up to Scala 2.7, tabulate could be
written as follows:
def tabulate[T](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
In Scala 2.8 this is no longer possible, because runtime information is necessary to create the right representation of Array[T]
. One needs to provide this information by passing a ClassManifest[T]
into the method as an implicit parameter:
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
}
As a shorthand form, a context bound can be used on the type parameter T
instead, giving:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With