any comments?

266 views
Skip to first unread message

Vlad Patryshev

unread,
Aug 26, 2016, 8:49:57 PM8/26/16
to scala-user

scala> val n = null.asInstanceOf[Int]

n: Int = 0


scala> val n = null.asInstanceOf[Double]

n: Double = 0.0


Thanks,
-Vlad

Seth Tisue

unread,
Aug 26, 2016, 9:27:23 PM8/26/16
to scala-user
http://stackoverflow.com/q/10749010/86485

"asInstanceOf doesn't have to make sense. What this method does is to tell the compiler to STOP MAKING SENSE, and trust what you are saying" — Daniel Sobral

Simon Ochsenreither

unread,
Aug 27, 2016, 5:30:26 AM8/27/16
to scala-user
Works as expected.

Vlad Patryshev

unread,
Aug 27, 2016, 9:55:00 AM8/27/16
to Simon Ochsenreither, scala-user

I'd expect it to fail in compilation. AnnUal extends NotNull. In Java it fails in runtime.


On Aug 27, 2016 2:30 AM, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:
Works as expected.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Arya Irani

unread,
Aug 27, 2016, 10:07:13 AM8/27/16
to Vlad Patryshev, Simon Ochsenreither, scala-user
"Now, if you want to know why it returns 0, that's because asInstanceOf works on AnyRef, not onAnyVal. When applied to an AnyVal, it will use the boxed version instead, and a boxed nullhas value 0." -- Daniel Sobral

On Sat, Aug 27, 2016 at 9:54 AM Vlad Patryshev <vpatr...@gmail.com> wrote:

I'd expect it to fail in compilation. AnnUal extends NotNull. In Java it fails in runtime.

On Aug 27, 2016 2:30 AM, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:
Works as expected.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Seth Tisue

unread,
Aug 27, 2016, 11:17:14 AM8/27/16
to scala-user
On Sat, Aug 27, 2016 at 6:54 AM, Vlad Patryshev <vpatr...@gmail.com> wrote:

I'd expect it to fail in compilation

asInstanceOf never fails at compilation. That's what asInstanceOf *is*. That's why I posted that Daniel Sobral quote.

Oliver Ruebenacker

unread,
Aug 28, 2016, 4:07:03 PM8/28/16
to Arya Irani, Vlad Patryshev, Simon Ochsenreither, scala-user

     Hello,

  I'm trying to understand what "boxed null has value 0" means. The term "boxed null" is a bit misleading, because it makes it sound as if there was a box with a null inside, but in fact, the box itself is null. If a box is null and I ask what is inside, why is this not NullPointerException?

  Do I ever get 0 other than with isInstanceOf? For example:

Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> Double2double(null)
java.lang.NullPointerException
  at scala.Predef$.Double2double(Predef.scala:365)
  ... 32 elided

  If boxed null has value 0, why I don't get 0?

     Best, Oliver


On Sat, Aug 27, 2016 at 10:06 AM, Arya Irani <arya....@gmail.com> wrote:
"Now, if you want to know why it returns 0, that's because asInstanceOf works on AnyRef, not onAnyVal. When applied to an AnyVal, it will use the boxed version instead, and a boxed nullhas value 0." -- Daniel Sobral
On Sat, Aug 27, 2016 at 9:54 AM Vlad Patryshev <vpatr...@gmail.com> wrote:

I'd expect it to fail in compilation. AnnUal extends NotNull. In Java it fails in runtime.

On Aug 27, 2016 2:30 AM, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:
Works as expected.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

Vlad Patryshev

unread,
Aug 28, 2016, 11:57:38 PM8/28/16
to Oliver Ruebenacker, Arya Irani, Simon Ochsenreither, scala-user
Actually, this trick works only with null-to-numbers. If "asInstanceOf" were allowed by compiler, for some psychological purposes, it's ok. But it's compiled into something that does not fail, unlike "".asInstanceOf[Int] or 1.asInstacneOf[String].

Even funnier, 1.asInstanceOf[String] compiles and fails in runtime; but 1.asInstanceOf[Long] does not compile. 

I still believe there's some kind of inconsistency.

Thanks,
-Vlad

Oliver Ruebenacker

unread,
Aug 29, 2016, 7:44:07 AM8/29/16
to Vlad Patryshev, Arya Irani, Simon Ochsenreither, scala-user

     Hello,

  That is indeed funny that 1.asInstanceOf[Long] does not compile, but null.asInstanceOf[Int] compiles and runs without exception.

  I disagree with Daniel Sobral that asInstanceOf "does not (have to) make sense". It is clearly defined as a cast, so a.asInstanceOf[B] clearly means "the compiler should now treat a as of type B, even if the compiler can't prove it".

  If the cast is incorrect (a is not of type B), I would expect it to throw a class cast exception.

  Moreover, if the compiler can prove that the cast is incorrect, it should report an error.

 I see Rex Kerr says the current behaviour is intended to make this:

  var x: X = _

  the same as this:

  var x: X = null.asInstanceOf[X]

  But I don't see why we want that. If the idea is that null is a default value and therefore it should cast to a default value, I don't see that as consistent, because other default values like 0, 0L or false can't be cast to other default values either (0.asInstanceOf[AnyRef] is not null).

     Best, Oliver

Jasper-M

unread,
Aug 29, 2016, 7:51:16 AM8/29/16
to scala-user, vpatr...@gmail.com, arya....@gmail.com, simon.och...@gmail.com
I would just like to say that 1.asInstanceOf[Long] works in my REPL (2.10.4 and 2.11.8).

Op maandag 29 augustus 2016 13:44:07 UTC+2 schreef Oliver Ruebenacker:

Thanks,
-Vlad

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

Simon Ochsenreither

unread,
Aug 29, 2016, 9:38:40 AM8/29/16
to scala-user, vpatr...@gmail.com, arya....@gmail.com, simon.och...@gmail.com
Ideally we would have something like defaultOf[T], that would relieve null.asInstanceOf[T] from some of its duties, but nobody had enough time to propose and implement it.

Oliver Ruebenacker

unread,
Aug 30, 2016, 5:56:18 AM8/30/16
to Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani

     Hello,

  Are you saying there actually is a use case for null.asInstanceOf[T], namely as a kind of defaultOf[T]?

  You could just use "var x:X = _", couldn't you? Or just "var x:X".

  Or do you need the default value of a type parameter? You'd need a type tag for that to be possible either way due to erasure.

  So, it would be something like (untested):

  def defaultOf[T: TypeTag]: T = {
    val tpe = typeOf[T]
    val value =
      if(tpe =:= typeOf[Int] { 0 }
      else if (tpe =:= typeOf[Long] { 0L }     
      else if (tpe =:= typeOf[Float] { 0.0 }     
      else if (tpe =:= typeOf[Double] { 0.0 }     
      else if (tpe =:= typeOf[Short] { 0 }     
      else if (tpe =:= typeOf[Byte] { 0 }     
      else if (tpe =:= typeOf[Char] { 0 }     
      else if (tpe =:= typeOf[Boolean] { false }     
      else { null }
    value.asInstanceOf[T]
  }

  It's still null.asInstanceOf[T] for AnyRef, but not for AnyVal.

  Thoughts?

     Best, Oliver

On Mon, Aug 29, 2016 at 9:38 AM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
Ideally we would have something like defaultOf[T], that would relieve null.asInstanceOf[T] from some of its duties, but nobody had enough time to propose and implement it.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Haoyi Li

unread,
Aug 30, 2016, 6:00:52 AM8/30/16
to Oliver Ruebenacker, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani
Ideally we would have something like defaultOf[T], that would relieve null.asInstanceOf[T] from some of its duties, but nobody had enough time to propose and implement it.

FWIW, C# has such a thing built into the language as a keyword:


Though in Scala we could probably (?) get by with just a library or macro or something

Kevin Wright

unread,
Aug 30, 2016, 6:12:57 AM8/30/16
to Oliver Ruebenacker, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani
Noooooooo -  This falls on the wrong side of the expression problem.  If you're doing it in a library then it becomes impossible for users to add their own default values to the mechanism.  This is exactly why we have type classes!

trait HasDefault[T] { def default: T }
object HasDefault {
  object IntHasDefault extends HasDefault[Int] { val default = 0 }
  object LongHasDefault extends HasDefault[Long] { val default = 0L }
  object DoubleHasDefault extends HasDefault[Double] { val default = 0.0d }
  object StringHasDefault extends HasDefault[String] { val default = “" }
  …
  def defaultOf[T](implicit ev: HasDefault[T]) = ev.default
}

later…

import HasDefault._
println(defaultOf[Int])

Alternatively, just use an appropriate predefined monoid from cats/scalaz/whatever


Kevin Wright
mail / hangouts / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Oliver Ruebenacker

unread,
Aug 30, 2016, 6:18:42 AM8/30/16
to Kevin Wright, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani

     Hello,

  Not sure what you mean by "add your own default value". The default value is null except for Int, Long, Short, Float, Double, Char, Byte and Boolean.

  Either the type is statically known, then you can just do:

  println({var x:T; x})

  Or the type is not statically known, because it is a type parameter, in which case you cannot resolve the right implicit for it.

     Best, Oliver

Kevin Wright

unread,
Aug 30, 2016, 6:26:38 AM8/30/16
to Oliver Ruebenacker, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani
“The default value is null except…”  Sure, as you defined it this is the case.

One might also contend that null is an especially poor choice of “default”, and that a better choice can be found in almost all cases, with a compile-time failure if such a value isn’t explicitly defined.  We should be looking to eliminate to use of nulls, not find more places to support and encourage them!

Defaulting String to “” is one such example, but what if someone wanted to use e.g. defaultOf[Waveform] ?

Oliver Ruebenacker

unread,
Aug 30, 2016, 6:40:37 AM8/30/16
to Kevin Wright, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani

     Hello,

  I meant compiler default values. You mean user-preferred default values, which is a different thing, since the compiler cannot always know what users prefer.

  I agree that use of compiler default values should be discouraged.

     Best, Oliver

Oliver Ruebenacker

unread,
Aug 30, 2016, 6:46:40 AM8/30/16
to Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani

     Hello,

  I'm starting to see how deep the rabbit hole goes: when I said "var x:X = _" would not work for type parameters because of type erasure - well I would say it really does not work, but it tries hard to pretend it does:


Kevin Wright

unread,
Aug 30, 2016, 6:52:10 AM8/30/16
to Oliver Ruebenacker, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani

“Beware that, when fighting monsters, you yourself do not become a monster... for when you gaze long into the abyss. The abyss gazes also into you.” ~ Friedrich Nietzsche

Oliver Ruebenacker

unread,
Aug 30, 2016, 6:54:41 AM8/30/16
to Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani
  Oops, hit sent by mistake.

  Anyway, at first glance, it seems to work just fine:

scala> class A[T] { var x:T = _ }
defined class A

scala> val aInt = new A[Int]
aInt: A[Int] = A@36f6e879

scala> aInt.x
res2: Int = 0

  Until you take a closer look:

scala> class A[T] { var x:T = _; println(x) }
defined class A

scala> val aInt = new A[Int]
null
aInt: A[Int] = A@3fee9989

scala> aInt.x
res3: Int = 0

  It actually chooses null as default value for x, even though x is Int. And when you call A.x, it casts null to Int and get 0.

  I guess that's why null.asInstanceOf[Int] is 0.

  On the other hand, that bolsters the case for an actually working defaultOf[T]. The drawback: it needs a type tag and therefore needs to be part of the Scala Reflection library. But there, I think it would be useful.

  Thoughts?

     Best, Oliver

martin odersky

unread,
Aug 30, 2016, 7:35:49 AM8/30/16
to Kevin Wright, Oliver Ruebenacker, Simon Ochsenreither, scala-user, Vlad Patryshev, Arya Irani
On Tue, Aug 30, 2016 at 12:52 PM, Kevin Wright <kev.lee...@gmail.com> wrote:

“Beware that, when fighting monsters, you yourself do not become a monster... for when you gaze long into the abyss. The abyss gazes also into you.” ~ Friedrich Nietzsche



Nice quote!

 - Martin



--

Martin Odersky
EPFL and Lightbend

Naftoli Gugenheim

unread,
Aug 31, 2016, 3:33:50 AM8/31/16
to Oliver Ruebenacker, Simon Ochsenreither, Arya Irani, Vlad Patryshev, scala-user


On Tue, Aug 30, 2016, 6:54 AM Oliver Ruebenacker <cur...@gmail.com> wrote:
  Oops, hit sent by mistake.

  Anyway, at first glance, it seems to work just fine:

scala> class A[T] { var x:T = _ }
defined class A

scala> val aInt = new A[Int]
aInt: A[Int] = A@36f6e879

scala> aInt.x
res2: Int = 0

  Until you take a closer look:

scala> class A[T] { var x:T = _; println(x) }
defined class A

scala> val aInt = new A[Int]
null
aInt: A[Int] = A@3fee9989

scala> aInt.x
res3: Int = 0

  It actually chooses null as default value for x, even though x is Int. And when you call A.x, it casts null to Int and get 0.

  I guess that's why null.asInstanceOf[Int] is 0.

  On the other hand, that bolsters the case for an actually working defaultOf[T]. The drawback: it needs a type tag and therefore needs to be part of the Scala Reflection library. But there, I think it would be useful.

TypeTag is a typeclass representing metadata about a type. Why not have a dedicated typeclass instead?


  Thoughts?

     Best, Oliver

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Naftoli Gugenheim

unread,
Aug 31, 2016, 3:43:18 AM8/31/16
to Seth Tisue, scala-user
Perhaps the question is *why* should asinstanceof behave that way?

One possible answer is, well the whole purpose of it is that when all is said and done, the compiler could be wrong, and so we need an escape hatch that allows as to tell the compiler to forget what it thinks and accept what we say. If we're so certain that we're ready to risk a ClassCastException, the compiler will defer to our judgement.
But here, the compiler is clearly not just forgetting what it thinks. It's being clever and inserting a "conversion." That seems a bit orthogonal to plain old casting...

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Naftoli Gugenheim

unread,
Aug 31, 2016, 3:43:48 AM8/31/16
to Oliver Ruebenacker, Arya Irani, Simon Ochsenreither, Vlad Patryshev, scala-user


On Sun, Aug 28, 2016, 4:06 PM Oliver Ruebenacker <cur...@gmail.com> wrote:

     Hello,

  I'm trying to understand what "boxed null has value 0" means.

+1

The term "boxed null" is a bit misleading, because it makes it sound as if there was a box with a null inside, but in fact, the box itself is null. If a box is null and I ask what is inside, why is this not NullPointerException?

  Do I ever get 0 other than with isInstanceOf? For example:

Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> Double2double(null)
java.lang.NullPointerException
  at scala.Predef$.Double2double(Predef.scala:365)
  ... 32 elided

  If boxed null has value 0, why I don't get 0?

     Best, Oliver

On Sat, Aug 27, 2016 at 10:06 AM, Arya Irani <arya....@gmail.com> wrote:
"Now, if you want to know why it returns 0, that's because asInstanceOf works on AnyRef, not onAnyVal. When applied to an AnyVal, it will use the boxed version instead, and a boxed nullhas value 0." -- Daniel Sobral
On Sat, Aug 27, 2016 at 9:54 AM Vlad Patryshev <vpatr...@gmail.com> wrote:

I'd expect it to fail in compilation. AnnUal extends NotNull. In Java it fails in runtime.

On Aug 27, 2016 2:30 AM, "Simon Ochsenreither" <simon.och...@gmail.com> wrote:
Works as expected.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Naftoli Gugenheim

unread,
Aug 31, 2016, 3:50:30 AM8/31/16
to Oliver Ruebenacker, Vlad Patryshev, Arya Irani, Simon Ochsenreither, scala-user
On Mon, Aug 29, 2016, 7:43 AM Oliver Ruebenacker <cur...@gmail.com> wrote:

     Hello,

  That is indeed funny that 1.asInstanceOf[Long] does not compile, but null.asInstanceOf[Int] compiles and runs without exception.

  I disagree with Daniel Sobral that asInstanceOf "does not (have to) make sense". It is clearly defined as a cast, so a.asInstanceOf[B] clearly means "the compiler should now treat a as of type B, even if the compiler can't prove it".

  If the cast is incorrect (a is not of type B), I would expect it to throw a class cast exception.

  Moreover, if the compiler can prove that the cast is incorrect, it should report an error.

 I see Rex Kerr says the current behaviour is intended to make this:

  var x: X = _

Can't we just deprecate that?


  the same as this:

  var x: X = null.asInstanceOf[X]

  But I don't see why we want that. If the idea is that null is a default value and therefore it should cast to a default value, I don't see that as consistent, because other default values like 0, 0L or false can't be cast to other default values either (0.asInstanceOf[AnyRef] is not null).

Besides being inconsistent I don't see the point.

The only case I can think of where any of these is necessary is if you have a var of a generic type that could be a reference type or a value type. How often does anyone need that? And when they do, you could either pass the default in as a parameter or typeclass, there could be a special method that implements this corner case behavior instead of asinstanceof.



     Best, Oliver


Thanks,
-Vlad

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Oliver Ruebenacker

unread,
Aug 31, 2016, 6:43:32 AM8/31/16
to Naftoli Gugenheim, Simon Ochsenreither, Arya Irani, Vlad Patryshev, scala-user

     Hello,

On Wed, Aug 31, 2016 at 3:33 AM, Naftoli Gugenheim <nafto...@gmail.com> wrote:


On Tue, Aug 30, 2016, 6:54 AM Oliver Ruebenacker <cur...@gmail.com> wrote:
  Oops, hit sent by mistake.

  Anyway, at first glance, it seems to work just fine:

scala> class A[T] { var x:T = _ }
defined class A

scala> val aInt = new A[Int]
aInt: A[Int] = A@36f6e879

scala> aInt.x
res2: Int = 0

  Until you take a closer look:

scala> class A[T] { var x:T = _; println(x) }
defined class A

scala> val aInt = new A[Int]
null
aInt: A[Int] = A@3fee9989

scala> aInt.x
res3: Int = 0

  It actually chooses null as default value for x, even though x is Int. And when you call A.x, it casts null to Int and get 0.

  I guess that's why null.asInstanceOf[Int] is 0.

  On the other hand, that bolsters the case for an actually working defaultOf[T]. The drawback: it needs a type tag and therefore needs to be part of the Scala Reflection library. But there, I think it would be useful.

TypeTag is a typeclass representing metadata about a type. Why not have a dedicated typeclass instead?

  It would be nice to have something like that in the standard library. Like

  trait DefaultValueProvider[T] { def value: T }

  and then we provide implementations for AnyRef, Int, Long, Short, Float, Double, Char, Byte and Boolean.

  I'm wondering, does TypeTag depend on compiler magic, or can it be implemented with user code? And without reflection?

  Usually, for each implicit argument, an implicit value must be in scope, but somehow that is not a requirement when we call methods that require TypeTags. Is that compiler magic or some trick I don't know yet?

  Maybe Kevin Wright was right after all and you can add your own default values?

  Thanks!

     Best, Oliver


  Thoughts?

     Best, Oliver

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Kevin Wright

unread,
Aug 31, 2016, 7:18:43 AM8/31/16
to Oliver Ruebenacker, Naftoli Gugenheim, Simon Ochsenreither, Arya Irani, Vlad Patryshev, scala-user
Yes, there’s compiler “magic” behind TypeTag (Also ClassTag, Manifest, etc)… The compiler will generate the required implicit on demand.

You can also create instances in macros or via reflection if necessary.

Oliver Ruebenacker

unread,
Aug 31, 2016, 8:55:50 AM8/31/16
to Kevin Wright, Naftoli Gugenheim, Simon Ochsenreither, Arya Irani, Vlad Patryshev, scala-user
It would be nice if for creating default values, or for creating arrays, from type parameters, you would not need the reflection library

Naftoli Gugenheim

unread,
Aug 31, 2016, 9:18:52 AM8/31/16
to Oliver Ruebenacker, Arya Irani, Simon Ochsenreither, Vlad Patryshev, scala-user
Only for concrete types. The way TypeTag solves erasure of genetics is that whenever you go from concrete to generic, i.e., a method or class with a type parameter invoked with a concrete type, you declare that you need an implicit TypeTag, so at the call site where it's concrete the compiler will "magically" materialize it, but from then on (within the generic context) it's a plain old typeclass instance.
In other words, implicitly[TypeTag[Seq[Int]]] uses compiler "magic," while implicitly[TypeTag[T]] uses ordinary implicit lookup.



  Thoughts?

     Best, Oliver

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Vlad Patryshev

unread,
Aug 31, 2016, 10:44:20 AM8/31/16
to Kevin Wright, Oliver Ruebenacker, Simon Ochsenreither, scala-user, Arya Irani
BTW, why defaultOf[Double] is not Dobule.NaN? Makes more sense (to me).

Thanks,
-Vlad

Roland Kuhn

unread,
Aug 31, 2016, 11:16:12 AM8/31/16
to Vlad Patryshev, Kevin Wright, Oliver Ruebenacker, Simon Ochsenreither, scala-user, Arya Irani
If it is 0 for integer types, why should it be different for floating-point types? The choice is arbitrary, for sure, but having the default coincide with the neutral element for addition seems like a good move to me.

Regards,

Roland

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Viktor Klang

unread,
Aug 31, 2016, 11:33:07 AM8/31/16
to Roland Kuhn, Arya Irani, Simon Ochsenreither, Oliver Ruebenacker, scala-user, Kevin Wright, Vlad Patryshev

it's in the JVM spec which are the default values for fields.

--
Cheers,

Roland Kuhn

unread,
Aug 31, 2016, 11:35:46 AM8/31/16
to √iktor Klang, Arya Irani, Simon Ochsenreither, Oliver Ruebenacker, scala-user, Kevin Wright, Vlad Patryshev
Technically, a separate defaultOf[X] operator could deviate from the default JVM field value. I’m not saying that that is a good idea, though, so I’d count this as another reason for using 0d for Double.

Regards,

Roland

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Vlad Patryshev

unread,
Aug 31, 2016, 12:52:24 PM8/31/16
to Roland Kuhn, Kevin Wright, Oliver Ruebenacker, Simon Ochsenreither, scala-user, Arya Irani
There's a NaN for floating-point types, that's why. There's nothing like that for integers. Another (funny) argument is this: integers are a ring, floating points are not (no associativity of addition).

Thanks,
-Vlad

Vlad Patryshev

unread,
Aug 31, 2016, 12:55:31 PM8/31/16
to Viktor Klang, Roland Kuhn, Arya Irani, Simon Ochsenreither, Oliver Ruebenacker, scala-user, Kevin Wright
This is reasonable. But very unfortunate. We are doing it differently here at H2O (I hope).

Thanks,
-Vlad

Kevin Wright

unread,
Aug 31, 2016, 3:10:03 PM8/31/16
to Vlad Patryshev, Viktor Klang, Roland Kuhn, Arya Irani, Simon Ochsenreither, Oliver Ruebenacker, scala-user
The problem is that, fundamentally, “default” is something of a context-sensitive term.  There are many valid reasons why NaN might be considered a better default than 0… It all depends on what you want the default FOR

The usual fix to such issues is to pick a better term :)

In this case, I’d probably start with “zeroOf”

Then I’d figure that even that isn’t perfect (What’s the zero of a waveform, for example? Is it an infinite flat line, or is it zero-length, both are valid depending on how you’ll add them).  At which point I’d just end up back at monoids


Naftoli Gugenheim

unread,
Aug 31, 2016, 3:14:01 PM8/31/16
to Viktor Klang, Roland Kuhn, Arya Irani, Kevin Wright, Oliver Ruebenacker, Simon Ochsenreither, Vlad Patryshev, scala-user


On Wed, Aug 31, 2016, 11:33 AM Viktor Klang <viktor...@gmail.com> wrote:

it's in the JVM spec which are the default values for fields.


Is var x: X = _ generating initialization code or not? If not then we don't need asInstanceOf to treat null specially because = _ doesn't need it. And if it does use it then what does it have to do with the JVM spec?

--
Cheers,


Roland


Thanks,
-Vlad

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Kevin Wright
mail / hangouts / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Seth Tisue

unread,
Aug 31, 2016, 3:55:53 PM8/31/16
to scala-user
On Wed, Aug 31, 2016 at 12:13 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
Is var x: X = _ generating initialization code or not?

No:

Welcome to Scala 2.11.8

scala> class C[X] { var x: X = _ }
defined class C

scala> :javap C
  public C();
...
         0: aload_0
         1: invokespecial #21                 // Method java/lang/Object."<init>":()V
         4: return

As a sanity check, if we instead write `var x: X = null.asInstanceOf[X]`, this gets added:

         4: aload_0
         5: aconst_null
         6: putfield      #12                 // Field x:Ljava/lang/Object;

so that confirms we’re looking in the right place.

(I’m answering your question, but I also want to show how easy it is to check these things in the REPL, at least assuming you can read disassembled bytecode.)

Seth Tisue / Scala team / Lightbend, Inc.

Naftoli Gugenheim

unread,
Aug 31, 2016, 4:27:12 PM8/31/16
to Seth Tisue, scala-user
Ok, so that disproves the theory that the null.asInstanceOf behavior is needed to implement var x: X = null correctly, and that removing it would require some alternative defaultOf mechanism.

So the question stands, what is the point in the "special" behavior of this cast vs. other casts?

--

Rex Kerr

unread,
Aug 31, 2016, 5:11:07 PM8/31/16
to Naftoli Gugenheim, Seth Tisue, scala-user
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

So, you could
  (1) invent a new operation
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?  But how?  Since surely

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

but the way this is achieved is precisely by boxing it as an AnyRef.

So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

So then the only question remaining is how you box/unbox `null`.  Your only real choices are

  a) NullPointerException
  b) JVM-mandated default value

If you want any code that works with `AnyRef` to also work with `Any`, you can't just throw exceptions.  So you have to use the default value.

And since that's the most sensible choice--not the only possible one, but the one that provides maximal consistency--you are left with allowing it when invoked explicitly also.

  --Rex


To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

Naftoli Gugenheim

unread,
Aug 31, 2016, 8:28:20 PM8/31/16
to Rex Kerr, Seth Tisue, scala-user
On Wed, Aug 31, 2016 at 5:11 PM Rex Kerr <ich...@gmail.com> wrote:
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

So, you could
  (1) invent a new operation

I guess you're alluding to the `defaultOf[T]` / `zeroOf[T]` idea in this thread?
 
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

Curious what the error-prone solution would be.
I suppose the "extra boilerplate" solution is what I mentioned earlier, namely requiring you to get the default value as a parameter. That parameter could be implicit -- it could be a typeclass. And `zeroOf` could be implemented via a typeclass. So we could unify #1 and #3...

 

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?

Why not explode right away?
 
  But how?  Since surely

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

Why?

Type ascription can invoke views (such as implicit conversions or type widening). I don't letting them box and unbox (although those are outside the scope of the type system). Casting doesn't invoke views. For example  "".asInstanceOf[WrappedString] throws a CCE.
And I think that's logical, because casting tells the compiler to discard its conclusions and submit to our assertions. So I don't see that the two should behave the same.
 

but the way this is achieved is precisely by boxing it as an AnyRef.

The way what is achieved?
 

So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

I think the boxing happens before getting to the asInstanceOf, no? Does 7.asInstanceOf[AnyRef] mean call the "method" Any#asInstanceOf on 7, and that method's implementation does boxing? Or, asInstanceOf can only be "called" on a boxed value, so the compiler inserts a box and the "method call" on that?

 

So then the only question remaining is how you box/unbox `null`.  Your only real choices are 

  a) NullPointerException
  b) JVM-mandated default value

null is an AnyRef, why would you box it or unbox it?
 
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

Oliver Ruebenacker

unread,
Sep 1, 2016, 4:59:15 AM9/1/16
to Naftoli Gugenheim, Seth Tisue, scala-user

     Hello,

  var x: X = _

  If X is known, it can just insert the correct default value. If X is an unbound type parameter, it will initialize it to null and cast it if called from a place where X is known:

Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> class A[X] { var x: X = _; println(s"The value of x is $x") }
defined class A

scala> (new A[Int]).x
The value of x is null
res1: Int = 0

  This is where null.asInstanceOf[Int] comes in behind the scene.

     Best, Oliver



To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Naftoli Gugenheim

unread,
Sep 1, 2016, 5:23:29 AM9/1/16
to Oliver Ruebenacker, Seth Tisue, scala-user


On Thu, Sep 1, 2016, 4:59 AM Oliver Ruebenacker <cur...@gmail.com> wrote:

     Hello,

  var x: X = _

  If X is known, it can just insert the correct default value. If X is an unbound type parameter, it will initialize it to null and cast it if called from a place where X is known:

Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> class A[X] { var x: X = _; println(s"The value of x is $x") }
defined class A

scala> (new A[Int]).x
The value of x is null
res1: Int = 0

  This is where null.asInstanceOf[Int] comes in behind the scene.

Since it's behind the scenes, and what's happening is the compiler is inserting something it knows to be safe, it seems a very different situation than casting. I don't see that as a motivation for asInstanceOf to do two orthogonal things.




     Best, Oliver



To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Oliver Ruebenacker

unread,
Sep 1, 2016, 5:25:00 AM9/1/16
to Rex Kerr, Naftoli Gugenheim, Seth Tisue, scala-user

     Hello,

On Wed, Aug 31, 2016 at 5:11 PM, Rex Kerr <ich...@gmail.com> wrote:
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

  Maybe it should not be legal to create a default value if you don't know what type it is.
 
So, you could
  (1) invent a new operation
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

  If we could provide something similar to TypeTag/ClassManifest, but more lightweight, and part of the standard library (not the reflectio library). Let's call it TypeFamily, and it only tracks whether something is AnyRef, Int, Long, Short, Char, Float, Double, Byte or Boolean. You could use that to create default values or arrays.
  

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?  But how?  Since surely

  ClassCastException. 7 is not an AnyRef.

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

but the way this is achieved is precisely by boxing it as an AnyRef.

  AnyRef is a static type. Boxing and unboxing is an implementation detail. An AnyVal is not an AnyRef, even if an AnyRef is sometimes used behind the scenes to implement it.
 
So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

So then the only question remaining is how you box/unbox `null`.  Your only real choices are

  a) NullPointerException
  b) JVM-mandated default value

 c) ClassCastException

If you want any code that works with `AnyRef` to also work with `Any`, you can't just throw exceptions.  So you have to use the default value.

  Why? If it can be AnyRef, you don't unbox.

     Best, Oliver



--

Rex Kerr

unread,
Sep 1, 2016, 7:07:18 AM9/1/16
to Naftoli Gugenheim, Seth Tisue, scala-user
On Wed, Aug 31, 2016 at 5:28 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:


On Wed, Aug 31, 2016 at 5:11 PM Rex Kerr <ich...@gmail.com> wrote:
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

So, you could
  (1) invent a new operation

I guess you're alluding to the `defaultOf[T]` / `zeroOf[T]` idea in this thread?

Correct.
 
 
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

Curious what the error-prone solution would be.

def parseWrong[A, B, C]: (A, B, C) = {
  var x, y, z: Any = null
  while (whatever) { if (isX) x = thing; else if (isY) y = thang; else z = theng; }
  (x.asInstanceOf[A], y.asInstanceOf[B], z.asInstanceOf[C])
}

You are forced to abandon types and cast at the end if you will eventually get a value, if you try to avoid boilerplate and no facilities are provided for doing this kind of thing.
 
I suppose the "extra boilerplate" solution is what I mentioned earlier, namely requiring you to get the default value as a parameter. That parameter could be implicit -- it could be a typeclass. And `zeroOf` could be implemented via a typeclass. So we could unify #1 and #3...

 

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?

Why not explode right away?

(7: Any).asInstanceOf[AnyRef] doesn't explode.  Exploding violates LSP.
 
 
  But how?  Since surely

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

Why?

Because (7: Any).asInstanceOf[Any] is a no-op.
 

Type ascription can invoke views (such as implicit conversions or type widening). I don't letting them box and unbox (although those are outside the scope of the type system). Casting doesn't invoke views. For example  "".asInstanceOf[WrappedString] throws a CCE.

But "".asInstanceOf[CharSequence] doesn't.
 
And I think that's logical, because casting tells the compiler to discard its conclusions and submit to our assertions. So I don't see that the two should behave the same.
 

but the way this is achieved is precisely by boxing it as an AnyRef.

The way what is achieved?

(7: Any).
 
 

So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

I think the boxing happens before getting to the asInstanceOf, no? Does 7.asInstanceOf[AnyRef] mean call the "method" Any#asInstanceOf on 7, and that method's implementation does boxing? Or, asInstanceOf can only be "called" on a boxed value, so the compiler inserts a box and the "method call" on that?

I'm not sure why it matters.
 

 

So then the only question remaining is how you box/unbox `null`.  Your only real choices are 

  a) NullPointerException
  b) JVM-mandated default value

null is an AnyRef, why would you box it or unbox it?

Because you tell the compiler, via asInstanceOf, that you know that, actually, this thing is an Int.  But, actually, it finds a null there, because Java (or whatever).  Now what?

Suppose you have this code.

class Sloppy[A] { var value: A = _ }
(new Sloppy[Option[Boolean]]).value.asInstanceOf[String]
(new Sloppy[Option[Boolean]]).value.asInstanceOf[Float]

For consistency's sake, either both of these should throw an exception or neither should.

You can't make the first one throw an exception, because `null` is a valid `String`.  So you can't make the second one throw an exception either unless you're willing to give up consistency.

  --Rex


Rex Kerr

unread,
Sep 1, 2016, 7:11:50 AM9/1/16
to Oliver Ruebenacker, Naftoli Gugenheim, Seth Tisue, scala-user
On Thu, Sep 1, 2016 at 2:24 AM, Oliver Ruebenacker <cur...@gmail.com> wrote:

     Hello,

On Wed, Aug 31, 2016 at 5:11 PM, Rex Kerr <ich...@gmail.com> wrote:
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

  Maybe it should not be legal to create a default value if you don't know what type it is.

This makes for rather painful code when you have several generics to initialize but you don't know the order in which you'll find them.
 
 
So, you could
  (1) invent a new operation
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

  If we could provide something similar to TypeTag/ClassManifest, but more lightweight, and part of the standard library (not the reflectio library). Let's call it TypeFamily, and it only tracks whether something is AnyRef, Int, Long, Short, Char, Float, Double, Byte or Boolean. You could use that to create default values or arrays.

Not useful if everything is typed as Any.  It still needs to behave sanely then.
 
  

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?  But how?  Since surely

  ClassCastException. 7 is not an AnyRef.

Well, java.lang.Integer(7) is an AnyRef.  And guess what (7: Any) is?  And if (7: Any) can do something, 7 should be able to also according to LSP.
 

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

but the way this is achieved is precisely by boxing it as an AnyRef.

  AnyRef is a static type. Boxing and unboxing is an implementation detail. An AnyVal is not an AnyRef, even if an AnyRef is sometimes used behind the scenes to implement it.

The type system doesn't let you completely escape the consequences of this implementation detail.
 
 
So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

So then the only question remaining is how you box/unbox `null`.  Your only real choices are

  a) NullPointerException
  b) JVM-mandated default value

 c) ClassCastException

See my answer to Naftoli.  Except note that CCE is even less consistent.

  --Rex
 

Oliver Ruebenacker

unread,
Sep 1, 2016, 7:44:04 AM9/1/16
to Rex Kerr, Naftoli Gugenheim, Seth Tisue, scala-user

     Hello,

On Thu, Sep 1, 2016 at 7:11 AM, Rex Kerr <ich...@gmail.com> wrote:


On Thu, Sep 1, 2016 at 2:24 AM, Oliver Ruebenacker <cur...@gmail.com> wrote:

     Hello,

On Wed, Aug 31, 2016 at 5:11 PM, Rex Kerr <ich...@gmail.com> wrote:
When dealing with generic code, Java has only `Object` while Scala has both `Any` and `AnyRef`.

If you are writing generic code in Java, you can always say `T thing = null` and it will at least not blow up in your face.

But in Scala, if `T` is `Any`, you are stuck.  You _mean_ "just fill in the sensible default".  But you don't have any value you can fill in.

  Maybe it should not be legal to create a default value if you don't know what type it is.

This makes for rather painful code when you have several generics to initialize but you don't know the order in which you'll find them.

  Not sure the relevance of "order", but what if we banish var x:X = _ for unbound X and instead you do:

def myGenericMethod[A: TypeFamily, B: TypeFamily, C: TypeFamily <: NumericFamily] : Whatever = {
  val a: A = defaultOf[A]
  val bArray = Array.for[B]
  val cZero = zeroOf[C]
}
 
So, you could
  (1) invent a new operation
  (2) decide that casting a `null` to an AnyVal type produces the default value for that type
  (3) provide nothing, which encourages extra boilerplate and/or error-prone code

  If we could provide something similar to TypeTag/ClassManifest, but more lightweight, and part of the standard library (not the reflectio library). Let's call it TypeFamily, and it only tracks whether something is AnyRef, Int, Long, Short, Char, Float, Double, Byte or Boolean. You could use that to create default values or arrays.

Not useful if everything is typed as Any.  It still needs to behave sanely then.

  Where is the problem?
 
  

Keep in mind that we have to decide what to do on _all_ `asInstanceOf`s.  What does

  7.asInstanceOf[AnyRef]

mean?  Should it explode later?  But how?  Since surely

  ClassCastException. 7 is not an AnyRef.

Well, java.lang.Integer(7) is an AnyRef.  And guess what (7: Any) is?  And if (7: Any) can do something, 7 should be able to also according to LSP.

  I see, you are right, java.lang.Integer(7) is indeed of type Int. But null is not.
 

  7.asInstanceOf[Any]

ought to produce the same behavior as

  7: Any

but the way this is achieved is precisely by boxing it as an AnyRef.

  AnyRef is a static type. Boxing and unboxing is an implementation detail. An AnyVal is not an AnyRef, even if an AnyRef is sometimes used behind the scenes to implement it.

The type system doesn't let you completely escape the consequences of this implementation detail.
 
 
So your hands are already tied, given the inheritance hierarchy: if asInstanceOf is going to work on Any at all, you're going to have to allow it to box/unbox things as needed.

So then the only question remaining is how you box/unbox `null`.  Your only real choices are

  a) NullPointerException
  b) JVM-mandated default value

 c) ClassCastException

See my answer to Naftoli.  Except note that CCE is even less consistent.

  --Rex
 

     Best, Oliver

Oliver Ruebenacker

unread,
Sep 1, 2016, 7:47:03 AM9/1/16
to Rex Kerr, Naftoli Gugenheim, Seth Tisue, scala-user

     Hello,

  Since null is a valid String, but not a valid Float, I expect the first one to succeed and the second one to fail.

     Best, Oliver
 


  --Rex


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Rex Kerr

unread,
Sep 1, 2016, 1:14:13 PM9/1/16
to Oliver Ruebenacker, Naftoli Gugenheim, Seth Tisue, scala-user
I think this conversation is going on a bit too long (I agree that things can be different with boilerplate).  But just to demonstrate why, given implementation details, things aren't easy:

Given

class Sloppy[A] { var value: A = _ }

This really really ought to work:

{ val s = new Sloppy[String]; s.value = null }.value.asInstanceOf[String]

But you don't know whether the thing in parens has happened, which makes all of these (which in practice assign a null) equivalent:

(new Sloppy[String]).value.asInstanceOf[String]
(new Sloppy[Option[Boolean]]).value.asInstanceOf[String]
(new Sloppy[Float]).value.asInstanceOf[String]

So they must have the same behavior.

For consistency's sake you expect

(new Sloppy[Float]).value.asInstanceOf[Float]

to at least not throw an exception, since the String/String version doesn't.  But this is indistinguishable from

(new Sloppy[Option[Boolean]]).value.asInstanceOf[Float]
(new Sloppy[String]).value.asInstanceOf[Float]

and so you'd better have a way to initialize your Float from a null.

Now you _could_ say that primitives randomly break or you need a bunch of typeclasses to do any initialization (and indeed you _do_ need a bunch of typeclasses to initialize arrays, and it is a pain).

But it also makes some sense that it is the way it is.

  --Rex

Oliver Ruebenacker

unread,
Sep 2, 2016, 9:17:23 AM9/2/16
to Rex Kerr, Naftoli Gugenheim, Seth Tisue, scala-user

     Hello,

On Thu, Sep 1, 2016 at 1:13 PM, Rex Kerr <ich...@gmail.com> wrote:
I think this conversation is going on a bit too long (I agree that things can be different with boilerplate).  But just to demonstrate why, given implementation details, things aren't easy:

  I think this is a very fruitful discussion that uncovers some very surprising behaviors that I think most people were unaware of.

Given

class Sloppy[A] { var value: A = _ }

This really really ought to work:

{ val s = new Sloppy[String]; s.value = null }.value.asInstanceOf[String]

But you don't know whether the thing in parens has happened, which makes all of these (which in practice assign a null) equivalent:

(new Sloppy[String]).value.asInstanceOf[String]
(new Sloppy[Option[Boolean]]).value.asInstanceOf[String]

  The above are all trivial, because they amount to null.asInstanceOf[String], which everybody expects to be (null: String).
 
(new Sloppy[Float]).value.asInstanceOf[String]

So they must have the same behavior.

  I don't see why the last one must have the same behaviour. (new Sloppy[Float]).value in isolation is 0.0, and 0.0.asInstanceOf[String] throws ClassCastException. It seems a glaring inconsistency that the composite expression gives null.

  BTW, this does not work:

scala> val s = new Sloppy[Int]
s: Sloppy[Int] = Sloppy@27a5f880

scala> s.value = null
<console>:13: error: an expression of type Null is ineligible for implicit conversion
       s.value = null
                 ^

 
For consistency's sake you expect

(new Sloppy[Float]).value.asInstanceOf[Float]

to at least not throw an exception, since the String/String version doesn't. 

  I would estimate that at least 95% of people who did not read this discussion would look at above expression and simply think that (new Sloppy[Float]).value is 0.0, and therefore the cast is a NoOp. But you are saying that it is really null, but it should behave like 0.0 for consistency sake, so that's why it can be cast to 0.0.

  Basically, (new Sloppy[Float]).value is sometimes 0.0 and sometimes null, depending on the context.

  And we have (null: String).asInstanceOf[Float] is 0.0, but 0.0.asInstanceOf[AnyRef] is not null but java.lang.Float(0.0)], and 0.0.asInstanceOf[String] throws a ClassCastException.
 
But this is indistinguishable from

(new Sloppy[Option[Boolean]]).value.asInstanceOf[Float]
(new Sloppy[String]).value.asInstanceOf[Float]

and so you'd better have a way to initialize your Float from a null.

  It is only indistinguishable if you assume that (new Sloppy[Float]).value is null, but sometimes behaves like 0.0, which is surprising.
 
Now you _could_ say that primitives randomly break or you need a bunch of typeclasses to do any initialization (and indeed you _do_ need a bunch of typeclasses to initialize arrays, and it is a pain).

But it also makes some sense that it is the way it is.

  I can see that if you have an unbound type parameter T and you want one value to act as a universal default value that you can cast to any default value, then I guess this is the only approach.

  But it leads to very surprising behavior, where a value appears sometimes to be null and sometimes 0/0.0/false etc.

  So we should provide a simple way to avoid such situations where possible. Something like ClassTag/TypeTag, but simpler, more lightweight and in the standard library.

  Let's say I only care which of the following a type T is: AnyRef, Int, Long, Short, Char, Byte, Float, Double, Boolean. So I only need to distinguish between the above nine options. This allows me to provide default values and create appropriate arrays (i.e. an Array[AnyRef] is fine to store Strings, but I want to avoid an expensive Array[AnyRef] when the cheaper Array[Int] would suffice). 

     Best, Oliver

Seth Tisue

unread,
Sep 2, 2016, 8:14:26 PM9/2/16
to scala-user
Note that you can expose the underlying null without even involving `asInstanceOf`:

scala> class Sloppy[A] { var value: A = _ }
defined class Sloppy

scala> new Sloppy[Double].value
res14: Double = 0.0

scala> new Sloppy[Double].value: Any
res15: Any = null

scala> new Sloppy[Double].value: AnyVal
res16: AnyVal = null

scala> println(new Sloppy[Double].value)
null

There is a very old open ticket on it: https://issues.scala-lang.org/browse/SI-1470

Oliver Ruebenacker

unread,
Sep 7, 2016, 3:10:28 PM9/7/16
to Seth Tisue, scala-user

     Hello,

  Wonder what happens when you specialize? The REPL ignores @specialized annotations, so we need to put it in a file and compile and run:

object GenInitApp extends App {

  class Unspecialized[T] { var x: T = _ }
  class Specialized[@specialized(Float) T] { var x: T = _ }

  println((new Unspecialized[Float]).x)
  println((new Specialized[Float]).x)

}

  The output is:

Unspecialized x is null
Specialized x is 0.0


     Best, Oliver


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages