|
Manifest.classType() just doesn't seem to like value types.
(assume import java.{lang => jl} in all quoted examples...) Using Int as an example here, the problem starts with classOf[Int], which returns jl.Integer.TYPE (this is the reflected type of Java's int primitive)
So far, so good, it *is* Java's reflection library after all, and scala.Int gets translated into an int primitive in Javaland The problem is when I then pull that back into the world of Scala
Manifest.classType[(classOf[Int]) == Manifest[int] it's subtle... look at the capitalisation of that 'i' So we're getting the Manifest of a primitive type, which would seem to be an oddity in a similar vein to Some(null).
However this one has no reason to exist, as the erasure of Manifest.Int is jl.Integer.TYPE anyway! So here's my work-around: val ByteClass = classOf[scala.Byte]
val ShortClass = classOf[scala.Short] val CharClass = classOf[scala.Char]
val IntClass = classOf[scala.Int] val LongClass = classOf[scala.Long]
val FloatClass = classOf[scala.Float] val DoubleClass = classOf[scala.Double]
val BooleanClass = classOf[scala.Boolean] val NullClass = classOf[scala.Null]
val UnitClass = classOf[scala.Unit]
def manifestOf(c : Class[_]) = c match { case jl.Byte.TYPE | ByteClass => Manifest.Byte
case jl.Short.TYPE | ShortClass => Manifest.Short case jl.Character.TYPE | CharClass => Manifest.Char
case jl.Integer.TYPE | IntClass => Manifest.Int case jl.Long.TYPE | LongClass => Manifest.Long
case jl.Float.TYPE | FloatClass => Manifest.Float case jl.Double.TYPE | DoubleClass => Manifest.Double
case jl.Boolean.TYPE | BooleanClass => Manifest.Boolean case jl.Void.TYPE | UnitClass => Manifest.Unit
case null | NullClass => Manifest.Null case x => classType(x)
}
Can anyone see a good reason why I shouldn't just create a ticket and submit a patch pushing this logic back into Manifest.classType() ?
-- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
Actually, even that workaround isn't enough!
It needs to explicitly check for Java's boxed types as well... On 14 August 2010 18:53, Kevin Wright <[hidden email]> wrote: Manifest.classType() just doesn't seem to like value types. -- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
On Sat, Aug 14, 2010 at 8:27 PM, Kevin Wright <[hidden email]> wrote: Actually, even that workaround isn't enough! Primitives, gift that just keeps giving.
-- Viktor Klang, Code Connoisseur Work: www.akkasource.com Code: github.com/viktorklang Follow: twitter.com/viktorklang Read: klangism.tumblr.com |
|
Heh heh
At this rate, I may just go and write that Scala reflection library after all... It's actually looking more and more like the easy option nowadays :) On 14 August 2010 19:39, Viktor Klang <[hidden email]> wrote:
-- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
Corporate sponsors welcome :)
On 14 August 2010 19:44, Kevin Wright <[hidden email]> wrote: Heh heh -- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
In reply to this post by Kevin Wright-3
On Sat, Aug 14, 2010 at 06:53:37PM +0100, Kevin Wright wrote:
> So we're getting the Manifest of a primitive type, which would seem to be an > oddity in a similar vein to Some(null). > However this one has no reason to exist, as the erasure of Manifest.Int > is jl.Integer.TYPE anyway! If it didn't exist, what would this return: scala> manifest[List[Int]].typeArguments res0: List[scala.reflect.Manifest[_]] = List(Int) I'm sure you're right there's something to be fixed here, but I'm not so sure yet what is the fix. -- Paul Phillips | Atheists dig the best foxholes. Analgesic | Empiricist | pp: i haul pills |----------* http://www.improving.org/paulp/ *---------- |
Maybe I'm missing something (it *is* getting late...), but I can't see how that relates :(
My biggest concern is getting a Manifest[int] instead of a Manifest[Int]. ( actually, it should be the unique instance `Manifest.Int`, which is a specialisation of AnyValManifest[Int] )
The former type shouldn't exist, as it exposes a java primitive into Scala code, and Manifest.Int has an erasure of jl.Integer.TYPE anyway, so there's no need for the distinction Another issue is handling of boxed types, there it does make sense to distinguish between Manifest[Integer] and Manifest[Int], but as soon as Java reflection is involved, things become much harder :)
This fortunately only seems to crop up when constructing manifests dynamically, so I doubt that more than a handful of people are likely to be exposed to it for the time being. -- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
On Sat, Aug 14, 2010 at 10:40:53PM +0100, Kevin Wright wrote:
> My biggest concern is getting a Manifest[int] instead of a > Manifest[Int]. ( actually, it should be the unique instance > `Manifest.Int`, which is a specialisation of AnyValManifest[Int] ) > > The former type shouldn't exist, as it exposes a java primitive into > Scala code The method you describe actually exists, in ClassManifest: def fromClass[T](clazz: Predef.Class[T]): ClassManifest[T] = clazz match { case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]] case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]] case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]] case java.lang.Integer.TYPE => Int.asInstanceOf[ClassManifest[T]] case java.lang.Long.TYPE => Long.asInstanceOf[ClassManifest[T]] case java.lang.Float.TYPE => Float.asInstanceOf[ClassManifest[T]] case java.lang.Double.TYPE => Double.asInstanceOf[ClassManifest[T]] case java.lang.Boolean.TYPE => Boolean.asInstanceOf[ClassManifest[T]] case java.lang.Void.TYPE => Unit.asInstanceOf[ClassManifest[T]] case _ => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]] } scala> scala.reflect.Manifest.classType(classOf[scala.Int]) res1: scala.reflect.Manifest[Nothing] = int scala> scala.reflect.ClassManifest.fromClass(classOf[scala.Int]) res2: scala.reflect.ClassManifest[Int] = Int scala> res2 == manifest[Int] res3: Boolean = true The method seems to be used in ArrayOps and nowhere else. I don't know what thinking went into all of this but I'm sure some of it is no longer applicable. I don't even really know who to ask. If there's some intentional/useful distinction being made between the "type of Int" and the "class of Int" we should find out what it is. -- Paul Phillips | The important thing here is that the music is not in Protagonist | the piano. And knowledge and edification is not in the Empiricist | computer. The computer is simply an instrument whose pull his pi pal! | music is ideas. -- Alan Kay |
|
Getting closer, I can't see any reason not to use a ClassManifest instead of a Manifest
(to be honest, I'm not entirely sure of the difference) It's still not ideal for working with Java reflection though
if I use MethodParameter#getGenericParameterType against a Seq[Int] param, it'll come back with Seq[jl.Integer] and Seq[jl.Integer] != Seq[Int] Perhaps I need to be thinking at a higher level here, and add a factory method to ClassManifest that accepts a MethodParameter then does the right thing.
For the sake of interop, how would you feel about checking if the method's class is derived from ScalaObject, and translating from boxed primitive types to the equivalent scala types if so. On 15 August 2010 02:37, Paul Phillips <[hidden email]> wrote:
-- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
|
Manifests are not quite done yet. They are supposed to be fleshed out
as part of the Scala reflection library which is also not done yet. The only parts that are definitely stable are those dealing with arrays. So if a method is used from ArrayOps you can assume that it will stay as it is. I would be glad to give you some better assurances but unfortunately that's all I can say at the moment. Cheers -- Martin On Sun, Aug 15, 2010 at 3:50 PM, Kevin Wright <[hidden email]> wrote: > Getting closer, I can't see any reason not to use a ClassManifest instead of > a Manifest > (to be honest, I'm not entirely sure of the difference) > It's still not ideal for working with Java reflection though > if I use MethodParameter#getGenericParameterType against a Seq[Int] param, > it'll come back with Seq[jl.Integer] > and Seq[jl.Integer] != Seq[Int] > Perhaps I need to be thinking at a higher level here, and add a factory > method to ClassManifest that accepts a MethodParameter then does the right > thing. > For the sake of interop, how would you feel about checking if the method's > class is derived from ScalaObject, and translating from boxed primitive > types to the equivalent scala types if so. > > On 15 August 2010 02:37, Paul Phillips <[hidden email]> wrote: >> >> On Sat, Aug 14, 2010 at 10:40:53PM +0100, Kevin Wright wrote: >> > My biggest concern is getting a Manifest[int] instead of a >> > Manifest[Int]. ( actually, it should be the unique instance >> > `Manifest.Int`, which is a specialisation of AnyValManifest[Int] ) >> > >> > The former type shouldn't exist, as it exposes a java primitive into >> > Scala code >> >> The method you describe actually exists, in ClassManifest: >> >> def fromClass[T](clazz: Predef.Class[T]): ClassManifest[T] = clazz match >> { >> case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]] >> case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]] >> case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]] >> case java.lang.Integer.TYPE => Int.asInstanceOf[ClassManifest[T]] >> case java.lang.Long.TYPE => Long.asInstanceOf[ClassManifest[T]] >> case java.lang.Float.TYPE => Float.asInstanceOf[ClassManifest[T]] >> case java.lang.Double.TYPE => Double.asInstanceOf[ClassManifest[T]] >> case java.lang.Boolean.TYPE => Boolean.asInstanceOf[ClassManifest[T]] >> case java.lang.Void.TYPE => Unit.asInstanceOf[ClassManifest[T]] >> case _ => classType[T with >> AnyRef](clazz).asInstanceOf[ClassManifest[T]] >> } >> >> scala> scala.reflect.Manifest.classType(classOf[scala.Int]) >> res1: scala.reflect.Manifest[Nothing] = int >> >> scala> scala.reflect.ClassManifest.fromClass(classOf[scala.Int]) >> res2: scala.reflect.ClassManifest[Int] = Int >> >> scala> res2 == manifest[Int] >> res3: Boolean = true >> >> The method seems to be used in ArrayOps and nowhere else. I don't know >> what thinking went into all of this but I'm sure some of it is no longer >> applicable. I don't even really know who to ask. If there's some >> intentional/useful distinction being made between the "type of Int" and >> the "class of Int" we should find out what it is. >> >> -- >> Paul Phillips | The important thing here is that the music is not in >> Protagonist | the piano. And knowledge and edification is not in >> the >> Empiricist | computer. The computer is simply an instrument whose >> pull his pi pal! | music is ideas. -- Alan Kay > > > > -- > Kevin Wright > > mail/google talk: [hidden email] > wave: [hidden email] > skype: kev.lee.wright > twitter: @thecoda > > |
|
Okay, that sounds fair enough :)
I'll need to clarify exactly what improvements I need and create a trac ticket. Then I can build the functionality for release via scalaj-spring, and later rework it into a patch against ClassManifest for some future release.
Paul, when this is is ready, are you okay to accept a pull request via the starrless branch ad give it a quick code review? I've signed the agreement :)
On 15 August 2010 22:48, martin odersky <[hidden email]> wrote: Manifests are not quite done yet. They are supposed to be fleshed out -- Kevin Wright mail/google talk: [hidden email] wave: [hidden email] skype: kev.lee.wright twitter: @thecoda |
| Powered by Nabble | Edit this page |
