The Artima Developer Community
Sponsored Link

Scala Buzz
Manifests: Reified Types

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
David Bernard

Posts: 109
Nickname: davidb31
Registered: Dec, 2007

scala-blogs is a group of tutorials and articles about scala
Manifests: Reified Types Posted: Dec 3, 2008 7:50 PM
Reply to this message Reply

This post originated from an RSS feed registered with Scala Buzz by David Bernard.
Original Post: Manifests: Reified Types
Feed Title: Scala Blog
Feed URL: http://www.scala-blogs.org/feeds/posts/default?alt=rss
Feed Description: In an effort to realize the "grow together" spirit, the developers of lift have teamed up with other great minds in the Scala community to bring you Scala-Blogs.org. Our mission is to strengthen the community by sharing our experiences and knowledge so that others can learn from our mistakes and triumph along with our successes. At Scala-Blogs.org you will find tutorials and articles written by a growing host of enthusiasts, each with a different background and area of expertise.
Latest Scala Buzz Posts
Latest Scala Buzz Posts by David Bernard
Latest Posts From Scala Blog

Advertisement
Reification (n.): When an abstract concept [...] is treated as a concrete 'thing'.[1]
When Java-the-language added generic types in version 1.5, Java-the-virtual-machine (JVM) did not. Generic types are a fiction of the compiler. They exist at compile time, but they are omitted from the generated bytecode and are therefore unavailable at run time. This phenomenon is known as erasure.

By contrast, when C# added generic types in version 2.0, the .NET Common Language Runtime (CLR) added them as well. This allows C# to access information about generic types at run time. We say that C#'s generic types are reified.

Java's type erasure leads to some peculiar limitations. To deal with these limitations, Java programmers often find themselves passing around java.lang.Class<T> objects: concrete manifestations of the otherwise abstract concept that is the type "T".

Starting with version 2.7.2, Scala has added manifests, an undocumented (and still experimental) feature for reifying types. They take advantage of a pre-existing Scala feature: implicit parameters.

To use Manifests, simply add an implicit scala.reflect.Manifest[T] parameter to your method, like so:
def name[T](implicit m: scala.reflect.Manifest[T]) = m.toString
This method prints the name of any Scala type. To use it, invoke the method with some type parameter:
name[Int => Int]
// returns "scala.Function1[int, int]"
When using implicit parameters, you usually have to declare a implicit identifier with the same type as your method expects, in the same scope where the method is called. With Manifests, the compiler automatically injects the implicit parameter for you, as long as it has enough type information to generate a Manifest. Essentially, this is a way of carrying over type information available at compile time into objects available at run time.

An Example: Generic Collections Optimized for Primitives

In Java, generic collections can't be used with primitive types. The boxed types must be used instead. This has implications for both run time performance and memory consumption. Despite HotSpot's best optimization efforts, boxed types can add significant overhead in performance-critical code.

In C#, by contrast, generic collections are optimized for performance with primitive types. This is possible because C#'s types are reified. If your code calls for a List<T>, C# knows at run time what T is and can use the specific implementation of List that is optimized for your T.

Let's see what Scala can do with Manifests and a lot of help from the fastutil library, which provides 1000+ (!) Java collection classes optimized for primitives.
import scala.reflect.Manifest
import it.unimi.dsi.fastutil._

def mkList[T](implicit m: Manifest[T]) = {
(m.toString match {
case "boolean" => new booleans.BooleanArrayList
case "byte" => new bytes.ByteArrayList
case "char" => new chars.CharArrayList
case "double" => new doubles.DoubleArrayList
case "float" => new floats.FloatArrayList
case "int" => new ints.IntArrayList
case "long" => new longs.LongArrayList
case "short" => new shorts.ShortArrayList
case _ => new objects.ObjectArrayList[T]
}).asInstanceOf[java.util.List[T]]
}
Now, invoking the mkList method with the proper type (i.e., mkList[Int], mkList[Double], etc.) will create an ArrayList optimized for that particular primitive type. We can verify that the correct classes are being instantiated by doing a little reflection.
mkList[Int].getClass.getName
// returns "it.unimi.dsi.fastutil.ints.IntArrayList"

mkList[Double].getClass.getName
// returns "it.unimi.dsi.fastutil.doubles.DoubleArrayList"
These optimized collections can have considerable benefits over their unoptimized counterparts in java.util. Just imagine, for example, the memory overhead of storing boxed Bytes instead of unboxed bytes. Storing just the pointer for one boxed Byte takes up at least four (and possibly eight) bytes!

Of course, the same effect could be achieved in Java by passing an explicit java.lang.Class<T> parameter to mkList. The disadvantage is that this imposes a significant overhead on the programmer to create and pass around these Class<T> objects. Scala's support for implicit parameters, and the automatic injection of Manifests by the compiler, makes reifying types on the JVM slightly less painful.

Appendix: Other Methods on Manifests

In this example, the only method we used on Manifests was toString. What other methods are available? Manifests are as-yet undocumented (not in the official Scaladocs), but looking through the source can give us an idea of what's available.

erasure

This method returns the java.lang.Class that corresponds to the run time erasure of the Scala type represented by the Manifest.

<:< and >:>

These methods test whether the type represented by the Manifest is a subtype or a supertype (respectively) of the type represented by the given parameter. As the source warns, the current implementation is merely an approximation, as it is based on the erasure of the two types.

equals

This method tests whether two types are equal. Again, the source warns that the current implementation is merely an approximation, as it is based on the erasure of the two types.

Thanks to David Hall for suggesting the example.

Read: Manifests: Reified Types

Topic: Java Just Died (no closures in Java 7) Previous Topic   Next Topic Topic: Coincidence?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use