7

(Scala beginner question)

I am trying to write a program in Scala that does a number of checks on C++ source files, and I want to implement optional logging of checks.

The following works fine for a single check:

  val headerFiles = files.filter(_.matches(".*?\\.h$"))
  val headerGuardChecker = if(options.contains('verbose)) {
    new HeaderGuard with LoggingFileCheckerTrait
  } else {
    new HeaderGuard
  } 
  headerFiles.foreach(h => if (! headerGuardChecker.check(new File(h))) println(h + " doesn't have a header guard"))

however when I try to generalize this using generics:

  def checker[T] = if(options.contains('verbose)) {
    new T with LoggingFileCheckerTrait
  } else {
    new T
  } 
  val headerFiles = files.filter(_.matches(".*?\\.h$"))
  headerFiles.foreach(h => if (! checker[HeaderGuard].check(new File(h))) println(h + " doesn't have a header guard"))

I get compile errors on the two new statements, claiming that T isn't a type. I believe this caused by type erasure, but I haven't found a way of working round this. Is there a way of doing what I want to do?

Anthony Berent
  • 105
  • 1
  • 6
  • Duplicate of http://stackoverflow.com/questions/818996/abstract-types-type-parameters-in-scala/820345#820345 – James Iry Dec 08 '11 at 17:35
  • @JamesIry your solution does not show how to create a new `T with TraitXYZ`. How do you do that, or is it possible? – Luigi Plinge Dec 08 '11 at 23:52

1 Answers1

7

Take a look at Scala "manifests". They often allow you to circumvent type erasure on the JVM.

scala> def instantiate[T](implicit m:Manifest[T]) = m.erasure.newInstance().asInstanceOf[T]
instantiate: [T](implicit m: Manifest[T])T

scala> instantiate[String]
res0: String = ""

Here's a good intro for manifests in Scala

Community
  • 1
  • 1
Adam Rabung
  • 5,232
  • 2
  • 27
  • 42
  • 1
    and remember that there's no guarantee that `T` has a no-arg constructor; so a `try`/`catch` might be a good idea (or use reflection to check) – Luigi Plinge Dec 08 '11 at 14:11
  • Thanks, that seems to get me past that problem. It is still not doing quite what I expect, but at least it compiles and runs. – Anthony Berent Dec 08 '11 at 18:51
  • Actually I still have a problem. erasure is loosing the trait, so _instantiate[HeaderGuard with LoggingFileCheckerTrait]_ gives me the same as _instantiate[HeaderGuard]_ – Anthony Berent Dec 08 '11 at 20:23
  • Agreed, good point. I've asked scala-user this, hopefully we'll get an authoritative answer. The fact that it looks sound at compile time and fails at runtime is disturbing! http://groups.google.com/group/scala-user/browse_frm/thread/92d02112dbf5e077 – Adam Rabung Dec 10 '11 at 02:44