This page is no longer maintained — Please continue to the home page at www.scala-lang.org

A seemingly strange question

7 replies
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Bonjour Scalars,

Given a

def foo[T](bar : Manifest[T], baz : Any) = ...

What'd be the simplest way to determine whether said bar is assignable from said foo?

(Gotto work for primitives, arrays and other assorted objects)

--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: A seemingly strange question
You mean baz instead of foo?
def foo[T](bar: Manifest[T], baz: Any) = bar.erasure.isAssignableFrom(baz.getClass)
Or maybe invert bar.erasure and baz.getClass. I always found isAssignableFrom unintuitive.

On Mon, Apr 26, 2010 at 6:27 PM, Viktor Klang <viktor [dot] klang [at] gmail [dot] com> wrote:
Bonjour Scalars,

Given a

def foo[T](bar : Manifest[T], baz : Any) = ...

What'd be the simplest way to determine whether said bar is assignable from said foo?

(Gotto work for primitives, arrays and other assorted objects)

--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang



--
Daniel C. Sobral

I travel to the future all the time.
Moritz Uhlig
Joined: 2010-01-08,
User offline. Last seen 42 years 45 weeks ago.
Re: A seemingly strange question

This is what I would come up with, not really a thing of beauty, not really a simple way:

def foo[T](x: Any)(implicit mf: Manifest[T]) = mf == manifest[Any] || {
def primitive(c: Class[_]) = mf == manifest[AnyVal] || mf.erasure == c
x match {
case _:Int => primitive(classOf[Int])
case _:Unit => primitive(classOf[Unit])
case _:Long => primitive(classOf[Long])
// ... other AnyVals
case null =>
!(mf.erasure.isPrimitive || classOf[NotNull].isAssignableFrom(mf.erasure))
case x:AnyRef => mf.erasure.isAssignableFrom(x.getClass)
}
}

Works for all AnyVals, arrays and unparametrized types.

Regards,

Moritz

Am 26.04.2010 um 23:27 schrieb Viktor Klang:

> Bonjour Scalars,
>
> Given a
>
> def foo[T](bar : Manifest[T], baz : Any) = ...
>
> What'd be the simplest way to determine whether said bar is assignable from
> said foo?
>
> (Gotto work for primitives, arrays and other assorted objects)
>

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: A seemingly strange question

On Mon, Apr 26, 2010 at 11:27:58PM +0200, Viktor Klang wrote:
> def foo[T](bar : Manifest[T], baz : Any) = ...
>
> What'd be the simplest way to determine whether said bar is assignable from
> said foo?
>
> (Gotto work for primitives, arrays and other assorted objects)

No time this moment to write you a thrilling implementation, but
depending on what you mean by "work for primitives" it is not possible
as you have framed it. You can't tell whether an "Any" parameter was a
primitive Int or a java.lang.Integer unless you take additional measures
which are not present in that signature.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: A seemingly strange question
On Mon, Apr 26, 2010 at 11:27:58PM +0200, Viktor Klang wrote: > def foo[T](bar : Manifest[T], baz : Any) = ... So again depending on what you're trying to do, you might look at the code that I used to have in trunk in scala.reflect.Invocation, which I pulled because I had to lower the surface area of the stuff I'm trying to get in good shape for 2.8. But here is how I wrote a generic interface which maintained the distinction between primitives and the boxed versions. Take a time machine to see the original file for how it's used in context. But these days I would just use manifests. https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala... /**

* In order to encapsulate anything to do with reflection, we must * overcome an issue with the boxing of primitives. If we declare a * method which takes arguments of type Any, by the time the * method parameters can be examined, the primitives have already been boxed. * The reflective call will then fail because classOf[java.lang.Integer] * is not the same thing as classOf[scala.Int]. *

*

* Any useful workaround will require examining the arguments before * the method is called. The approach here is to define two implicits, * one for AnyRef's and one for AnyVal's, and * box them in a container which preserves their original class identity. *

*/ trait PrimitivePreserver[T] { val value: T val clazz: JClass[_] } case class PreservedAnyVal[T <: AnyVal](value: T) extends PrimitivePreserver[T] { val clazz = getAnyValClass(value) } case class PreservedAnyRef[T <: AnyRef](value: T) extends PrimitivePreserver[T] { val clazz = value.getClass } implicit def makePreservedAnyRef[T <: AnyRef](x: T) = PreservedAnyRef(x) implicit def makePreservedAnyVal[T <: AnyVal](x: T) = PreservedAnyVal(x)
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A seemingly strange question


On Tue, Apr 27, 2010 at 4:51 AM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Mon, Apr 26, 2010 at 11:27:58PM +0200, Viktor Klang wrote:
> def foo[T](bar : Manifest[T], baz : Any) = ...

So again depending on what you're trying to do, you might look at the
code that I used to have in trunk in scala.reflect.Invocation, which I
pulled because I had to lower the surface area of the stuff I'm trying
to get in good shape for 2.8.  But here is how I wrote a generic
interface which maintained the distinction between primitives and the
boxed versions.

The problem is erasure, I have a list of a parameterized type, something like: List[MyType[_]]
And for each of these, I'm going to try to set a value into it, if that value is compatible with the original tpye the MyType was parameterized with.

class MyType[T : Manifest]{
  val myType = manifest[T]

  var myTypeValue : Option[T] = None
 
  def set(t : T) = ... //T Here will be unknown because of the unknown type in the list
  def set(a : Any) = ... //Set value a into myTypeValue if, and only if, said "a" is assiblable from the type T as specified by the manifest "myType"
}

Does any of this make sense?
 

Take a time machine to see the original file for how it's used in
context.  But these days I would just use manifests.

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/reflect/Invocation.scala?rev=19692

 /** <p>
  *    In order to encapsulate anything to do with reflection, we must
  *    overcome an issue with the boxing of primitives.  If we declare a
  *    method which takes arguments of type <code>Any</code>, by the time the
  *    method parameters can be examined, the primitives have already been boxed.
  *    The reflective call will then fail because <code>classOf[java.lang.Integer]</code>
  *    is not the same thing as <code>classOf[scala.Int].</code>
  *  </p>
  *  <p>
  *    Any useful workaround will require examining the arguments before
  *    the method is called.  The approach here is to define two implicits,
  *    one for <code>AnyRef</code>'s and one for <code>AnyVal</code>'s, and
  *    box them in a container which preserves their original class identity.
  *  </p>
  */
 trait PrimitivePreserver[T] {
   val value: T
   val clazz: JClass[_]
 }
 case class PreservedAnyVal[T <: AnyVal](value: T) extends PrimitivePreserver[T] {
   val clazz = getAnyValClass(value)
 }
 case class PreservedAnyRef[T <: AnyRef](value: T) extends PrimitivePreserver[T] {
   val clazz = value.getClass
 }
 implicit def makePreservedAnyRef[T <: AnyRef](x: T) = PreservedAnyRef(x)
 implicit def makePreservedAnyVal[T <: AnyVal](x: T) = PreservedAnyVal(x)

--
Paul Phillips      | Where there's smoke, there's mirrors!
Apatheist          |
Empiricist         |
up hill, pi pals!  |----------* http://www.improving.org/paulp/ *----------



--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A seemingly strange question


On Tue, Apr 27, 2010 at 11:01 AM, Viktor Klang <viktor [dot] klang [at] gmail [dot] com> wrote:


On Tue, Apr 27, 2010 at 4:51 AM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Mon, Apr 26, 2010 at 11:27:58PM +0200, Viktor Klang wrote:
> def foo[T](bar : Manifest[T], baz : Any) = ...

So again depending on what you're trying to do, you might look at the
code that I used to have in trunk in scala.reflect.Invocation, which I
pulled because I had to lower the surface area of the stuff I'm trying
to get in good shape for 2.8.  But here is how I wrote a generic
interface which maintained the distinction between primitives and the
boxed versions.

The problem is erasure, I have a list of a parameterized type, something like: List[MyType[_]]
And for each of these, I'm going to try to set a value into it, if that value is compatible with the original tpye the MyType was parameterized with.

class MyType[T : Manifest]{
  val myType = manifest[T]

  var myTypeValue : Option[T] = None
 
  def set(t : T) = ... //T Here will be unknown because of the unknown type in the list
  def set(a : Any) = ... //Set value a into myTypeValue if, and only if, said "a" is assiblable from the type T as specified by the manifest "myType"
}

Does any of this make sense?

Also, to throw more stuff into the mix, the instances will be transported over different VMs.

Basically, what I want to know, is that given a manifest and an Any, is that Any assignable from that manifest type.
 
 

Take a time machine to see the original file for how it's used in
context.  But these days I would just use manifests.

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/reflect/Invocation.scala?rev=19692

 /** <p>
  *    In order to encapsulate anything to do with reflection, we must
  *    overcome an issue with the boxing of primitives.  If we declare a
  *    method which takes arguments of type <code>Any</code>, by the time the
  *    method parameters can be examined, the primitives have already been boxed.
  *    The reflective call will then fail because <code>classOf[java.lang.Integer]</code>
  *    is not the same thing as <code>classOf[scala.Int].</code>
  *  </p>
  *  <p>
  *    Any useful workaround will require examining the arguments before
  *    the method is called.  The approach here is to define two implicits,
  *    one for <code>AnyRef</code>'s and one for <code>AnyVal</code>'s, and
  *    box them in a container which preserves their original class identity.
  *  </p>
  */
 trait PrimitivePreserver[T] {
   val value: T
   val clazz: JClass[_]
 }
 case class PreservedAnyVal[T <: AnyVal](value: T) extends PrimitivePreserver[T] {
   val clazz = getAnyValClass(value)
 }
 case class PreservedAnyRef[T <: AnyRef](value: T) extends PrimitivePreserver[T] {
   val clazz = value.getClass
 }
 implicit def makePreservedAnyRef[T <: AnyRef](x: T) = PreservedAnyRef(x)
 implicit def makePreservedAnyVal[T <: AnyVal](x: T) = PreservedAnyVal(x)

--
Paul Phillips      | Where there's smoke, there's mirrors!
Apatheist          |
Empiricist         |
up hill, pi pals!  |----------* http://www.improving.org/paulp/ *----------



--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang



--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A seemingly strange question


On Tue, Apr 27, 2010 at 2:45 AM, Moritz Uhlig <moritz [dot] uhlig [at] jsolution [dot] de> wrote:
This is what I would come up with, not really a thing of beauty, not really a simple way:

def foo[T](x: Any)(implicit mf: Manifest[T]) = mf == manifest[Any] || {
 def primitive(c: Class[_]) = mf == manifest[AnyVal] || mf.erasure == c
 x match {
   case _:Int => primitive(classOf[Int])
   case _:Unit => primitive(classOf[Unit])
   case _:Long => primitive(classOf[Long])
   // ... other AnyVals
   case null =>
     !(mf.erasure.isPrimitive || classOf[NotNull].isAssignableFrom(mf.erasure))
   case x:AnyRef => mf.erasure.isAssignableFrom(x.getClass)
 }
}


Works for all AnyVals, arrays and unparametrized types.

Thanks for the example, I'll take it for a spin and see if it'll work.

More suggestions are needed tough! :-)
 


Regards,

Moritz

Am 26.04.2010 um 23:27 schrieb Viktor Klang:

> Bonjour Scalars,
>
> Given a
>
> def foo[T](bar : Manifest[T], baz : Any) = ...
>
> What'd be the simplest way to determine whether said bar is assignable from
> said foo?
>
> (Gotto work for primitives, arrays and other assorted objects)
>
> --
> Viktor Klang
> | "A complex system that works is invariably
> | found to have evolved from a simple system
> | that worked." - John Gall
>
> Akka - the Actor Kernel: Akkasource.org
> Twttr: twitter.com/viktorklang




--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland