2

from time to time, i deal with java that has stuff like the following in it:

def printDbl(d:Double) { println("dbl: " + d) } def printInt(i:Int) { println("int: " + i) } 

naturally, i'd like to wrap this in some scala, which ends up looking like this:

def print[T:Manifest] (t:T) { if (manifest[T] <:< manifest[Int]) { printInt(t.asInstanceOf[Int]) ; return } if (manifest[T] <:< manifest[Double]) { printDbl(t.asInstanceOf[Double]) ; return } throw new UnsupportedOperationException("not implemented: " + manifest[T]) } 

but when i run the following, i get a runtime exception:

print(1) print(2.0) print("hello") 

i seem to recall there being a way to catch this at compile time, but i can't seem to google it up. perhaps some clever implied conversions?

4 Answers 4

6

Why don't you just take advantage of method overloading and write your Scala wrapper like this?:

object Printer { def print(d: Double) { printDbl(d) } def print(i: Int) { printInt(i) } } 

This is very simple and provides the desired behavior:

import Printer._ print(1.) // dbl: 1.0 print(1) // int: 1 print("hello") // compile-time type error 
Sign up to request clarification or add additional context in comments.

Comments

1
scala> object SpecType { | trait SpecType[T] { | def is(s: String): Boolean | } | implicit object DoubleType extends SpecType[Double] { | def is(s: String) = s == "Double" | } | implicit object IntType extends SpecType[Int] { | def is(s: String) = s == "Int" | } | } defined module SpecType scala> import SpecType._ import SpecType._ scala> def print[T: SpecType](x: T) { | if(implicitly[SpecType[T]].is("Int")) println("Int") | if(implicitly[SpecType[T]].is("Double")) println("Double") | } print: [T](x: T)(implicit evidence$1: SpecType.SpecType[T])Unit scala> print(1) Int scala> print(1.0) Double scala> print("") <console>:21: error: could not find implicit value for evidence parameter of typ e SpecType.SpecType[String] print("") 

1 Comment

I guess this code can improved by using Double/Int instead of String and change the layout of the code so that you can do something like: implicitly[SpecType[T]].println(x) See here for example: debasishg.blogspot.de/2010/06/…
0

this is the best i've come up with

class CanPrint[T] (t:T) { def getT = t} implicit def canPrint(i:Int) = new CanPrint[Int](i) implicit def canPrint(d:Double) = new CanPrint[Double](d) def print[T:Manifest] (t:CanPrint[T]) { if (manifest[T] <:< manifest[Int]) { printInt(t.getT.asInstanceOf[Int]) ; return } if (manifest[T] <:< manifest[Double]) { printDbl(t.getT.asInstanceOf[Double]) ; return } throw new UnsupportedOperationException("not implemented: " + manifest[T]) } 

the following does not compile

print(1) print(1.0) print("hello") 

and the following does what i expect

print(1) print(1.0) 

however, this is bad code because i have to import the implicit defs for it to work, and as a consumer of this code all i see is the method signature saying that i have to pass in a CanPrint object, which i can instantiate.

print(new CanPrint("hello")) // pwned 

can i make the constructor private and only accessible to the implicit methods or some such?

Comments

0
def printDbl(d:Double) { println("dbl: " + d) } def printInt(i:Int) { println("int: " + i) } trait Printer[T] { def print(t:T) } class PD extends Printer[Double] { def print(d:Double) = printDbl(d) } class PI extends Printer[Int] { def print(i:Int) = printInt(i) } implicit val pd = new PD() implicit val pi = new PI() def print[T](t:T)(implicit printer:Printer[T]) = printer.print(t) print(1) // 1 print(2.0) // 2.0 print("hello") // Error:(88, 7) could not find implicit value for parameter printer: A$A336.this.Printer[String] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.