- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
scala puzzler: I'm holding in my hand...
Fri, 2011-05-06, 02:32
In my hand, I have the left hand side of an assignment. It's a
perfectly ordinary lhs. You believe me? Ah, you have fallen right into
my trap. For this is no ordinary lhs...
If you call .toString on it, you will enjoy a null pointer exception.
If you assign null to it, and THEN call .toString on it, you won't.
In other words, there is some XXX such that:
XXX.toString // NPE
XXX = null ; XXX.toString // no NPE
What does it have in its pocketses?
Fri, 2011-05-06, 03:27
#2
Re: scala puzzler: I'm holding in my hand...
In your hand you have a shrink wrap...
class Shrink[T <: Any] { var wrap: T = null.asInstanceOf[T] }
val shrink = new Shrink[Unit]
// shrink.wrap is XXX
shrink.wrap.toString // NPE
shrink.wrap = null; shrink.wrap.toString // no NPE
Unit ftw.
On Thu, May 5, 2011 at 8:32 PM, Paul Phillips wrote:
> In my hand, I have the left hand side of an assignment. It's a perfectly
> ordinary lhs. You believe me? Ah, you have fallen right into my trap. For
> this is no ordinary lhs...
>
> If you call .toString on it, you will enjoy a null pointer exception.
> If you assign null to it, and THEN call .toString on it, you won't.
>
> In other words, there is some XXX such that:
>
> XXX.toString // NPE
> XXX = null ; XXX.toString // no NPE
>
> What does it have in its pocketses?
>
Fri, 2011-05-06, 03:47
#3
Re: scala puzzler: I'm holding in my hand...
That's much slicker! I found the following form less distracting:
class Shrink[T] { var wrap: T = _ }
Cheers,
Cay
2011/5/6 Lex :
> In your hand you have a shrink wrap...
>
> class Shrink[T <: Any] { var wrap: T = null.asInstanceOf[T] }
> val shrink = new Shrink[Unit]
>
> // shrink.wrap is XXX
> shrink.wrap.toString // NPE
> shrink.wrap = null; shrink.wrap.toString // no NPE
>
> Unit ftw.
>
>
> On Thu, May 5, 2011 at 8:32 PM, Paul Phillips wrote:
>> In my hand, I have the left hand side of an assignment. It's a perfectly
>> ordinary lhs. You believe me? Ah, you have fallen right into my trap. For
>> this is no ordinary lhs...
>>
>> If you call .toString on it, you will enjoy a null pointer exception.
>> If you assign null to it, and THEN call .toString on it, you won't.
>>
>> In other words, there is some XXX such that:
>>
>> XXX.toString // NPE
>> XXX = null ; XXX.toString // no NPE
>>
>> What does it have in its pocketses?
>>
>
Fri, 2011-05-06, 05:27
#4
Re: scala puzzler: I'm holding in my hand...
On 5/5/11 7:11 PM, Cay Horstmann wrote:
> I am sure you have something much slicker in mind, but since one can
> overload getters of a field, this isn't hard to achieve.
I never pile enough conditions onto these things. I should have locked
out some of these forms of cheating (where cheating is defined as "not
what I was going for.")
Okay: No generics. No casts. No getters. No setters.
Fri, 2011-05-06, 06:57
#5
Re: scala puzzler: I'm holding in my hand...
2011/5/6 Paul Phillips :
> On 5/5/11 7:11 PM, Cay Horstmann wrote:
>> I am sure you have something much slicker in mind, but since one can
>> overload getters of a field, this isn't hard to achieve.
>
> I never pile enough conditions onto these things. I should have locked
> out some of these forms of cheating (where cheating is defined as "not
> what I was going for.")
>
> Okay: No generics. No casts. No getters. No setters.
>
I guess you'd want to outlaw apply/update as well:
class X {
private var s = ""
def apply(i: Int) = if (s == null) "" else null
def update(i: Int, s: String) { this.s = s }
}
Fri, 2011-05-06, 07:57
#6
Re: scala puzzler: I'm holding in my hand...
2011/5/6 Cay Horstmann :
> 2011/5/6 Paul Phillips :
>> On 5/5/11 7:11 PM, Cay Horstmann wrote:
>>> I am sure you have something much slicker in mind, but since one can
>>> overload getters of a field, this isn't hard to achieve.
>>
>> I never pile enough conditions onto these things. I should have locked
>> out some of these forms of cheating (where cheating is defined as "not
>> what I was going for.")
>>
>> Okay: No generics. No casts. No getters. No setters.
>>
>
> I guess you'd want to outlaw apply/update as well:
>
> class X {
> private var s = ""
> def apply(i: Int) = if (s == null) "" else null
> def update(i: Int, s: String) { this.s = s }
> }
>
And implicit conversions
class X extends NotNull { private var c = 0; override def toString =
if (c > 0) throw new NullPointerException else { c += 1; "" } }
// the counter is just so you can do this in the REPL
class Y extends X { override def toString = "" }
implicit def n2x(n: Null) = new Y
val xxx = new X
xxx.toString // throws NPE
xxx = null // sets xxx to new Y
xxx.toString // returns ""
Fri, 2011-05-06, 11:57
#7
Re: scala puzzler: I'm holding in my hand...
Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java
1.6.0_23).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val a = new Array[Unit](3)
a: Array[Unit] = Array(null, null, null)
scala> a(0).toString
java.lang.NullPointerException
at .(:7)
at .()
at RequestResult$.(:9)
at RequestResult$.()
at RequestResult$scala_repl_result()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
at scala.util.control.Exception$Catch.apply(Exception.scala:79)
at scala.tools.nsc...
scala> a(0) = null
scala> a(0).toString
res2: java.lang.String = ()
I knew it was something with Unit, but I didn't find the solution
until I saw the ticket...
Regards,
Rüdiger
2011/5/6 Cay Horstmann :
> 2011/5/6 Cay Horstmann :
>> 2011/5/6 Paul Phillips :
>>> On 5/5/11 7:11 PM, Cay Horstmann wrote:
>>>> I am sure you have something much slicker in mind, but since one can
>>>> overload getters of a field, this isn't hard to achieve.
>>>
>>> I never pile enough conditions onto these things. I should have locked
>>> out some of these forms of cheating (where cheating is defined as "not
>>> what I was going for.")
>>>
>>> Okay: No generics. No casts. No getters. No setters.
>>>
>>
>> I guess you'd want to outlaw apply/update as well:
>>
>> class X {
>> private var s = ""
>> def apply(i: Int) = if (s == null) "" else null
>> def update(i: Int, s: String) { this.s = s }
>> }
>>
>
> And implicit conversions
>
> class X extends NotNull { private var c = 0; override def toString =
> if (c > 0) throw new NullPointerException else { c += 1; "" } }
> // the counter is just so you can do this in the REPL
> class Y extends X { override def toString = "" }
> implicit def n2x(n: Null) = new Y
> val xxx = new X
> xxx.toString // throws NPE
> xxx = null // sets xxx to new Y
> xxx.toString // returns ""
>
Fri, 2011-05-06, 13:47
#8
Re: scala puzzler: I'm holding in my hand...
This doesn't work in compiled version. The first "a(0).toString" gets
inlined as Unit.
On Fri, May 6, 2011 at 5:53 AM, Rüdiger Keller
wrote:
> Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java
> 1.6.0_23).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> val a = new Array[Unit](3)
> a: Array[Unit] = Array(null, null, null)
>
> scala> a(0).toString
> java.lang.NullPointerException
> at .(:7)
> at .()
> at RequestResult$.(:9)
> at RequestResult$.()
> at RequestResult$scala_repl_result()
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
> at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
> at scala.util.control.Exception$Catch.apply(Exception.scala:79)
> at scala.tools.nsc...
> scala> a(0) = null
>
> scala> a(0).toString
> res2: java.lang.String = ()
>
>
> I knew it was something with Unit, but I didn't find the solution
> until I saw the ticket...
>
> Regards,
> Rüdiger
>
>
> 2011/5/6 Cay Horstmann :
>> 2011/5/6 Cay Horstmann :
>>> 2011/5/6 Paul Phillips :
>>>> On 5/5/11 7:11 PM, Cay Horstmann wrote:
>>>>> I am sure you have something much slicker in mind, but since one can
>>>>> overload getters of a field, this isn't hard to achieve.
>>>>
>>>> I never pile enough conditions onto these things. I should have locked
>>>> out some of these forms of cheating (where cheating is defined as "not
>>>> what I was going for.")
>>>>
>>>> Okay: No generics. No casts. No getters. No setters.
>>>>
>>>
>>> I guess you'd want to outlaw apply/update as well:
>>>
>>> class X {
>>> private var s = ""
>>> def apply(i: Int) = if (s == null) "" else null
>>> def update(i: Int, s: String) { this.s = s }
>>> }
>>>
>>
>> And implicit conversions
>>
>> class X extends NotNull { private var c = 0; override def toString =
>> if (c > 0) throw new NullPointerException else { c += 1; "" } }
>> // the counter is just so you can do this in the REPL
>> class Y extends X { override def toString = "" }
>> implicit def n2x(n: Null) = new Y
>> val xxx = new X
>> xxx.toString // throws NPE
>> xxx = null // sets xxx to new Y
>> xxx.toString // returns ""
>>
>
Fri, 2011-05-06, 14:17
#9
Re: scala puzzler: I'm holding in my hand...
Do you have a bug? :)
On Fri, May 6, 2011 at 9:32 AM, Lex <lexn82@gmail.com> wrote:
On Fri, May 6, 2011 at 9:32 AM, Lex <lexn82@gmail.com> wrote:
This doesn't work in compiled version. The first "a(0).toString" gets
inlined as Unit.
On Fri, May 6, 2011 at 5:53 AM, Rüdiger Keller
<ruediger.keller@googlemail.com> wrote:
> Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java
> 1.6.0_23).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> val a = new Array[Unit](3)
> a: Array[Unit] = Array(null, null, null)
>
> scala> a(0).toString
> java.lang.NullPointerException
> at .<init>(<console>:7)
> at .<clinit>(<console>)
> at RequestResult$.<init>(<console>:9)
> at RequestResult$.<clinit>(<console>)
> at RequestResult$scala_repl_result(<console>)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
> at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
> at scala.util.control.Exception$Catch.apply(Exception.scala:79)
> at scala.tools.nsc...
> scala> a(0) = null
>
> scala> a(0).toString
> res2: java.lang.String = ()
>
>
> I knew it was something with Unit, but I didn't find the solution
> until I saw the ticket...
>
> Regards,
> Rüdiger
>
>
> 2011/5/6 Cay Horstmann <cay.horstmann@gmail.com>:
>> 2011/5/6 Cay Horstmann <cay.horstmann@gmail.com>:
>>> 2011/5/6 Paul Phillips <paulp@improving.org>:
>>>> On 5/5/11 7:11 PM, Cay Horstmann wrote:
>>>>> I am sure you have something much slicker in mind, but since one can
>>>>> overload getters of a field, this isn't hard to achieve.
>>>>
>>>> I never pile enough conditions onto these things. I should have locked
>>>> out some of these forms of cheating (where cheating is defined as "not
>>>> what I was going for.")
>>>>
>>>> Okay: No generics. No casts. No getters. No setters.
>>>>
>>>
>>> I guess you'd want to outlaw apply/update as well:
>>>
>>> class X {
>>> private var s = ""
>>> def apply(i: Int) = if (s == null) "" else null
>>> def update(i: Int, s: String) { this.s = s }
>>> }
>>>
>>
>> And implicit conversions
>>
>> class X extends NotNull { private var c = 0; override def toString =
>> if (c > 0) throw new NullPointerException else { c += 1; "" } }
>> // the counter is just so you can do this in the REPL
>> class Y extends X { override def toString = "" }
>> implicit def n2x(n: Null) = new Y
>> val xxx = new X
>> xxx.toString // throws NPE
>> xxx = null // sets xxx to new Y
>> xxx.toString // returns ""
>>
>
Fri, 2011-05-06, 14:57
#10
Re: scala puzzler: I'm holding in my hand...
On 5/6/11 5:32 AM, Lex wrote:
> This doesn't work in compiled version. The first "a(0).toString" gets
> inlined as Unit.
No, it doesn't. (This was indeed the answer we were looking for.)
object Test {
val arr = new Array[Unit](3)
def main(args: Array[String]): Unit = {
try println(arr(0).toString) catch { case ex => println(ex) }
arr(0) = null
println(arr(0).toString)
}
}
% scalac a.scala
% scala Test
java.lang.NullPointerException
()
Fri, 2011-05-06, 15:27
#11
Re: scala puzzler: I'm holding in my hand...
Well, looks like my project for experimentation has -optimize on it,
so arr(0) was always getting inlined as Unit.
Technically the trick was to have a ref of type Unit and null value,
which was delivered. Also you are violating your own "no generics"
rule, because Scala has unified generics, so Array[Unit] is using
generics ;)
On Fri, May 6, 2011 at 8:43 AM, Paul Phillips wrote:
> On 5/6/11 5:32 AM, Lex wrote:
>> This doesn't work in compiled version. The first "a(0).toString" gets
>> inlined as Unit.
>
> No, it doesn't. (This was indeed the answer we were looking for.)
>
> object Test {
> val arr = new Array[Unit](3)
> def main(args: Array[String]): Unit = {
> try println(arr(0).toString) catch { case ex => println(ex) }
> arr(0) = null
> println(arr(0).toString)
> }
> }
>
> % scalac a.scala
> % scala Test
> java.lang.NullPointerException
> ()
>
Fri, 2011-05-06, 15:37
#12
Re: scala puzzler: I'm holding in my hand...
On 5/6/11 7:23 AM, Lex wrote:
> Well, looks like my project for experimentation has -optimize on it,
> so arr(0) was always getting inlined as Unit.
> Technically the trick was to have a ref of type Unit and null value,
> which was delivered. Also you are violating your own "no generics"
> rule, because Scala has unified generics, so Array[Unit] is using
> generics ;)
Generics means something specific on the JVM, and arrays aren't it. (I
intentionally didn't exclude parameterized types.)
Fri, 2011-05-06, 16:07
#13
Re: scala puzzler: I'm holding in my hand...
On 5/6/11 7:23 AM, Lex wrote:
> Well, looks like my project for experimentation has -optimize on it,
> so arr(0) was always getting inlined as Unit.
I was hoping that was true because it would be hopeful that code to
better deal with it was already in place.
% rcscalac -optimise a.scala
% rcscala Test
java.lang.NullPointerException
()
Fri, 2011-05-06, 16:57
#14
Re: scala puzzler: I'm holding in my hand...
On Fri, May 6, 2011 at 7:29 AM, Paul Phillips <paulp@improving.org> wrote:
On 5/6/11 7:23 AM, Lex wrote:
> Well, looks like my project for experimentation has -optimize on it,
> so arr(0) was always getting inlined as Unit.
> Technically the trick was to have a ref of type Unit and null value,
> which was delivered. Also you are violating your own "no generics"
> rule, because Scala has unified generics, so Array[Unit] is using
> generics ;)
Generics means something specific on the JVM, and arrays aren't it. (I
intentionally didn't exclude parameterized types.)
Oh darn -- I had stumbled on the Array[Unit] solution last night, but thought it didn't count because of the type parameter -- I guess I need to learn the diff b/w "type parameters" and "generics"...
BTW, for the confused:
"scala.runtime.Unit" is a scalar type in Scala. That is, Unit extends Any, not AnyRef, just like scala.runtime.Int, scala.runtime.Long, and other scalar types. Normally you cannot assign a null value to a scalar reference; this is illegal according to the Scala type system, so should be prevented statically by the compiler. An odd situation exists with initialization of Array[Unit], however -- the JVM always initializes array members to a "zero" value. The "zero" value is interpreted as 0 for numeric types, false for Booleans, etc. But for Unit there is (apparently) no correct interpretation of this initial "zeroed" value. So, at least initially, the Unit elements of the array have value null.
This is a pretty odd situation, since only AnyRefs should be able to have null values -- the scala Null type extends AnyRef, and is not a subtype of scala.runtime.Unit. There is no scaladoc on the Null type, but using implicit type constraints in the REPL we can verify that Null is not directly related to Unit:
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.
scala> implicitly[Null <:< AnyRef]
res5: <:<[Null,AnyRef] = <function1>
scala> implicitly[Null <:< Any]
res6: <:<[Null,Any] = <function1>
scala> implicitly[Unit <:< AnyRef]
<console>:6: error: could not find implicit value for parameter e: <:<[Unit,AnyRef]
implicitly[Unit <:< AnyRef]
^
So, you normally cannot directly coerce a Null value to Unit. However, there is an implicit conversion that gets used when you assign a null value to a Unit reference: "null => ()". (I'm not sure if there's an explicitly-defined implicit conversion, or if that's something baked in to the compiler.) During Array[Unit] initialization to the "zero" state, this conversion is not applied. So in the end you get this weird condition where a null value is stored in a non-AnyRef ref -- abomination!
val a = new Array[Null](1)
// a in the wierd "zero" state, so array elements are null, even though static type is Unit
a(0).toString // NPE
// assigning "null" to a Unit kicks in the automatic conversion "null => () ", so array element paradoxically has a non-null value after the following assignment
a(0) = null
a(0).toString // Yields "()"
PUNCHLINE:
Who the hell would ever use an Array[Unit]? Except in a trivia question, never use an Array[Unit]. And you can forget everything else in this thread.
--
Best regards,
Brian Maso
(949) 395-8551
Follow me: @bmaso
brian@blumenfeld-maso.com
Fri, 2011-05-06, 17:37
#15
Re: scala puzzler: I'm holding in my hand...
On 5/6/11 8:53 AM, Brian Maso wrote:
> "scala.runtime.Unit" is a scalar type in Scala.
You mean scala.Unit. There is no scala.runtime.Unit type. There used
to be an object, but it is deprecated since I got everything into the
scala.Unit companion object.
> That is, Unit extends
> Any, not AnyRef,
AnyVal.
> just like scala.runtime.Int ,
> scala.runtime.Long, and other scalar types.
Same story, those don't exist either except as deprecated dummies, and
those are terms, not types.
> But for
> Unit there is (apparently) no correct interpretation of this initial
> "zeroed" value. So, at least initially, the Unit elements of the array
> have value null.
There is a correct interpretation for the actual type of the Array,
which is scala.runtime.BoxedUnit, and it is null. The trick is to deal
with that: the jvm is doing what it does, but scala the language says
"Unit is never null". But the set of allowable type parameters for
Arrays is fixed, and offers nothing for Unit but AnyRef.
> (I'm not sure if there's an
> explicitly-defined implicit conversion, or if that's something baked in
> to the compiler.)
It is its own thing, called "value discarding".
> During Array[Unit] initialization to the "zero" state,
> this conversion is not applied. So in the end you get this weird
> condition where a null value is stored in a non-AnyRef ref -- abomination!
Also, you can see this abomination with other anyvals in less contrived
ways.
scala> class C[T] { var x: T = _ }
defined class C
scala> new C[Int]
res1: C[Int] = C@3c10098b
scala> res1.x
res2: Int = 0
scala> res1.x.toString
java.lang.NullPointerException
at .(:10)
at .()
at .(:11)
at .()
at $export()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
scala> res1.x = 0
scala> res1.x.toString
res4: java.lang.String = 0
Fri, 2011-05-06, 21:37
#16
Re: scala puzzler: I'm holding in my hand...
Im using scala.2.8.1.final. Probably something in 2.9 changed so it no
longer inlines.
Generics and parametrized types are often used interchangeably, so
your are splitting a hair here. I guess the real requirement was to
read your mind, in which case it's not much of a riddler.
On Fri, May 6, 2011 at 9:57 AM, Paul Phillips wrote:
> On 5/6/11 7:23 AM, Lex wrote:
>> Well, looks like my project for experimentation has -optimize on it,
>> so arr(0) was always getting inlined as Unit.
>
> I was hoping that was true because it would be hopeful that code to
> better deal with it was already in place.
>
> % rcscalac -optimise a.scala
> % rcscala Test
> java.lang.NullPointerException
> ()
>
>
Sat, 2011-05-07, 14:37
#17
Re: scala puzzler: I'm holding in my hand...
Somehow inverted, but one of my favorites:
scala> val nArr= Array.ofDim(1)nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
scala> println(nArr(0).toString)java.lang.NullPointerException
scala> val nArr= Array.ofDim(1)nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
scala> println(nArr(0).toString)java.lang.NullPointerException
Sat, 2011-05-07, 14:57
#18
Re: scala puzzler: I'm holding in my hand...
What's weird about that?
On May 7, 2011 3:32 PM, "friedrich esser" <esser.friedrich@gmail.com> wrote:> Somehow inverted, but one of my favorites:
>
> scala> val nArr= Array.ofDim(1)
> nArr: Array[Nothing] = Array(null)
>
> scala> println(nArr(0))
> null
>
> scala> println(nArr(0).toString)
> java.lang.NullPointerException
>
Sat, 2011-05-07, 20:07
#19
Re: scala puzzler: I'm holding in my hand...
No need for a contrived example.
scala> println(null)
null
scala> println(null.toString)
java.lang.NullPointerException
On Sat, May 7, 2011 at 10:32 AM, friedrich esser <esser.friedrich@gmail.com> wrote:
scala> println(null)
null
scala> println(null.toString)
java.lang.NullPointerException
On Sat, May 7, 2011 at 10:32 AM, friedrich esser <esser.friedrich@gmail.com> wrote:
Somehow inverted, but one of my favorites:
scala> val nArr= Array.ofDim(1) nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
scala> println(nArr(0).toString)java.lang.NullPointerException
Sat, 2011-05-07, 20:17
#20
Re: scala puzzler: I'm holding in my hand...
(Which is not weird at all, println accepts null and prints "null".)
2011/5/7 Tomás Lázaro <tlazaro18@gmail.com>
2011/5/7 Tomás Lázaro <tlazaro18@gmail.com>
No need for a contrived example.
scala> println(null)
null
scala> println(null.toString)
java.lang.NullPointerException
On Sat, May 7, 2011 at 10:32 AM, friedrich esser <esser.friedrich@gmail.com> wrote:
Somehow inverted, but one of my favorites:
scala> val nArr= Array.ofDim(1) nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
scala> println(nArr(0).toString)java.lang.NullPointerException
Sat, 2011-05-07, 21:37
#21
Re: scala puzzler: I'm holding in my hand...
> No need for a contrived example.
So that is ok?
scala> val nArr= Array.ofDim(1)nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
Nothing is represented by null, although it has no instance.
So that is ok?
scala> val nArr= Array.ofDim(1)nArr: Array[Nothing] = Array(null)
scala> println(nArr(0))null
Nothing is represented by null, although it has no instance.
Sat, 2011-05-07, 21:57
#22
Re: scala puzzler: I'm holding in my hand...
One last word on null:
In Java null has no Type, its. kind of special. As it is a pointer to nirwana, you have to check each and everywhere for null,otherwise NPE.
Of course Scala does it much better!
A Null Type with one element null, which inherits all methods from AnyRef. So youmay write null == "" without NPE. But now you have to be even more careful:
If you use inherited methods like equals or toString, ... same procedure then every year.
Cheers
In Java null has no Type, its. kind of special. As it is a pointer to nirwana, you have to check each and everywhere for null,otherwise NPE.
Of course Scala does it much better!
A Null Type with one element null, which inherits all methods from AnyRef. So youmay write null == "" without NPE. But now you have to be even more careful:
If you use inherited methods like equals or toString, ... same procedure then every year.
Cheers
Mon, 2011-05-09, 01:27
#23
Re: scala puzzler: I'm holding in my hand...
On 06/05/2011 18:22, Paul Phillips wrote:
> Also, you can see this abomination with other anyvals in less contrived
> ways.
Just to be sure I understand what is going on here:
> scala> class C[T] { var x: T = _ }
> defined class C
OK, so here, we have an Any, so the JVM sees an Object, and it's
initialized to null.
> scala> new C[Int]
> res1: C[Int] = C@3c10098b
We say that after all, it's not an Any, but an Int. That doesn't change
the bytecode, so we still have a null object for x.
What is funny is that in 2.8.1, using @specialized for T in a compiled
class file leads to only printing 0 (cool), but crashes the REPL with an
"Exception in thread "main" java.lang.Error: Unknown type: ,
[class scala.tools.nsc.symtab.Types$NoType$, class
scala.tools.nsc.symtab.Types$NoType$] TypeRef? false, false"
In 2.9.0rc4, it works as expected (cool !).
> scala> res1.x
> res2: Int = 0
Hum. Here, I don't understand why it's not null. Ho, but it seems to not
be the same in the REPL and for a compiled file: a println of x prints
null.
So, is it that the REPL is wainting an Int, sees a null, transform that
to the default value for Int and print 0 ?
> scala> res1.x.toString
> java.lang.NullPointerException
> at .(:10)
> at .()
> at .(:11)
> at .()
> at $export()
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>
> scala> res1.x = 0
>
> scala> res1.x.toString
> res4: java.lang.String = 0
These ones are simple.
Thanks,
2011/5/6 Paul Phillips :
> In my hand, I have the left hand side of an assignment. It's a perfectly
> ordinary lhs. You believe me? Ah, you have fallen right into my trap. For
> this is no ordinary lhs...
>
> If you call .toString on it, you will enjoy a null pointer exception.
> If you assign null to it, and THEN call .toString on it, you won't.
>
> In other words, there is some XXX such that:
>
> XXX.toString // NPE
> XXX = null ; XXX.toString // no NPE
>
> What does it have in its pocketses?
>
I am sure you have something much slicker in mind, but since one can
overload getters of a field, this isn't hard to achieve.
class X {
private var _x = ""
def x = if (_x == null) "" else null
def x_=(x: String) { _x = x }
}
val xx = new X
xx.x.toString // throws NullPointerException
xx.x = null
xx.x.toString // returns ""
Cheers,
Cay