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

Re: null + null = ??

37 replies
Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.

probably this is what happens:

scala> var b = new StringBuilder()
b: StringBuilder = StringBuilder()

scala> b.append( null: String )
res19: StringBuilder = StringBuilder(n, u, l, l)

scala> b.append( null: String )
res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)

scala> b.toString
res21: java.lang.String = nullnull

Am 03.12.2010 um 19:25 schrieb Sciss:

> "The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method." ( http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>
> now the javadoc of StringBuilder says that should cause a null-pointer exception, and in fact it does:
>
> scala> new StringBuilder( null: String )
> java.lang.NullPointerException
>
> but still there seems to be a guard against that hidden somewhere... the same happens in java
>
> public class Test {
> public static void main( String[] args ) {
> String a = null;
> System.out.println( a + a ); // prints nullnull ...
> }
> }
>
> dunno....
>
> best, -sciss-
>
>
>
>
> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>
>> Thanks for the explanations,
>>
>> but I do not understand either of them. Syntactically,
>>
>> a.m(b)
>>
>> is a call of method m with argument b on object a. Right ?
>> And when a is null, the method call on a should return a NullPointerException.
>>
>> At least this is what I used to teach my students.
>>
>> Are saying that this does not apply here ? I refuse to accept that "whatever a compiler does" defines the semantics
>>
>> H.Peter
>>
>>
>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>
>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>> Why does the following compile ??
>>>>
>>>> def main(args: Array[String]): Unit = {
>>>> var s = "Scala";
>>>> s = null
>>>> var t = s.+(s) // Shouldn't this be a NullPointerException
>>>> println(t)
>>>> }
>>>>
>>>> Recompiling 1 files
>>>> compile:
>>>> run:
>>>> nullnull
>>>>
>>>> Greetings,
>>>> H.Peter Gumm
>>>>
>>>>
>>>>
>

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

case StartConcat =>
jcode.emitNEW(StringBuilderClass)
jcode.emitDUP()
jcode.emitINVOKESPECIAL(StringBuilderClass,
JMethod.INSTANCE_CONSTRUCTOR_NAME,
JMethodType.ARGLESS_VOID_FUNCTION)

case StringConcat(el) =>
val jtype = el match {
case REFERENCE(_) | ARRAY(_)=> JObjectType.JAVA_LANG_OBJECT
case _ => javaType(el)
}
jcode.emitINVOKEVIRTUAL(StringBuilderClass,
"append",
new JMethodType(StringBuilderType,
Array(jtype)))
case EndConcat =>
jcode.emitINVOKEVIRTUAL(StringBuilderClass,
"toString",
toStringType)

On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:

> probably this is what happens:
>
> scala> var b = new StringBuilder()
> b: StringBuilder = StringBuilder()
>
> scala> b.append( null: String )
> res19: StringBuilder = StringBuilder(n, u, l, l)
>
> scala> b.append( null: String )
> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>
> scala> b.toString
> res21: java.lang.String = nullnull
>
>
>
> Am 03.12.2010 um 19:25 schrieb Sciss:
>
>> "The Java language provides special support for the string
>> concatenation operator ( + ), and for conversion of other objects to
>> strings. String concatenation is implemented through the
>> StringBuilder(or StringBuffer) class and its append method." (
>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>
>> now the javadoc of StringBuilder says that should cause a null-pointer
>> exception, and in fact it does:
>>
>> scala> new StringBuilder( null: String ) java.lang.NullPointerException
>>
>> but still there seems to be a guard against that hidden somewhere...
>> the same happens in java
>>
>> public class Test {
>> public static void main( String[] args ) {
>> String a = null;
>> System.out.println( a + a ); // prints nullnull ...
>> }
>> }
>>
>> dunno....
>>
>> best, -sciss-
>>
>>
>>
>>
>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>
>>> Thanks for the explanations,
>>>
>>> but I do not understand either of them. Syntactically,
>>>
>>> a.m(b)
>>>
>>> is a call of method m with argument b on object a. Right ? And when a
>>> is null, the method call on a should return a NullPointerException.
>>>
>>> At least this is what I used to teach my students.
>>>
>>> Are saying that this does not apply here ? I refuse to accept that
>>> "whatever a compiler does" defines the semantics
>>>
>>> H.Peter
>>>
>>>
>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>
>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>> Why does the following compile ??
>>>>>
>>>>> def main(args: Array[String]): Unit = {
>>>>> var s = "Scala";
>>>>> s = null
>>>>> var t = s.+(s) // Shouldn't this be a NullPointerException
>>>>> println(t)
>>>>> }
>>>>>
>>>>> Recompiling 1 files
>>>>> compile:
>>>>> run:
>>>>> nullnull
>>>>>
>>>>> Greetings,
>>>>> H.Peter Gumm
>>>>>
>>>>>
>>>>>
>>>>>

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

Whatever the compiler cares to do ...

... the outcome does not make sense, it is plainly a bug. Scala is not
directly to blame, if it intends to stay compatible with Java and
decides to faithfully copy the Java bugs.

The following is what "The Scala Language Specification, Version 2.8"
has to say about Strings:

12.3.1 Class String
Scala’s String class is usually derived from the standard String class
of the underlying host system (and may be identified with it). For
Scala clients the class is taken to support in each case a method
def + (that: Any): String
which concatenates its left operand with the textual representation
of its right operand.

In particular:
1. + is clearly stated to be "a method" of class String
2. Scala's String is not forced to "be identified" with java.lang.String
but it "may be identified" and is only "usually derived"

In conclusion
s.+(s)
is a method call on object s which should return a NullPointerException
when s is null.

Greetings,
H.Peter Gumm

On 03.12.2010 22:34, Jim Balter wrote:
> "probably":
>
> case StartConcat =>
> jcode.emitNEW(StringBuilderClass)
> jcode.emitDUP()
> jcode.emitINVOKESPECIAL(StringBuilderClass,
> JMethod.INSTANCE_CONSTRUCTOR_NAME,
> JMethodType.ARGLESS_VOID_FUNCTION)
>
> case StringConcat(el) =>
> val jtype = el match {
> case REFERENCE(_) | ARRAY(_)=> JObjectType.JAVA_LANG_OBJECT
> case _ => javaType(el)
> }
> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
> "append",
> new JMethodType(StringBuilderType,
> Array(jtype)))
> case EndConcat =>
> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
> "toString",
> toStringType)
>
>
>
> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>
>> probably this is what happens:
>>
>> scala> var b = new StringBuilder()
>> b: StringBuilder = StringBuilder()
>>
>> scala> b.append( null: String )
>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>
>> scala> b.append( null: String )
>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>
>> scala> b.toString
>> res21: java.lang.String = nullnull
>>
>>
>>
>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>
>>> "The Java language provides special support for the string
>>> concatenation operator ( + ), and for conversion of other objects to
>>> strings. String concatenation is implemented through the
>>> StringBuilder(or StringBuffer) class and its append method." (
>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>>
>>> now the javadoc of StringBuilder says that should cause a null-pointer
>>> exception, and in fact it does:
>>>
>>> scala> new StringBuilder( null: String ) java.lang.NullPointerException
>>>
>>> but still there seems to be a guard against that hidden somewhere...
>>> the same happens in java
>>>
>>> public class Test {
>>> public static void main( String[] args ) {
>>> String a = null;
>>> System.out.println( a + a ); // prints nullnull ...
>>> }
>>> }
>>>
>>> dunno....
>>>
>>> best, -sciss-
>>>
>>>
>>>
>>>
>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>
>>>> Thanks for the explanations,
>>>>
>>>> but I do not understand either of them. Syntactically,
>>>>
>>>> a.m(b)
>>>>
>>>> is a call of method m with argument b on object a. Right ? And when a
>>>> is null, the method call on a should return a NullPointerException.
>>>>
>>>> At least this is what I used to teach my students.
>>>>
>>>> Are saying that this does not apply here ? I refuse to accept that
>>>> "whatever a compiler does" defines the semantics
>>>>
>>>> H.Peter
>>>>
>>>>
>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>
>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>> Why does the following compile ??
>>>>>>
>>>>>> def main(args: Array[String]): Unit = {
>>>>>> var s = "Scala";
>>>>>> s = null
>>>>>> var t = s.+(s) // Shouldn't this be a NullPointerException
>>>>>> println(t)
>>>>>> }
>>>>>>
>>>>>> Recompiling 1 files
>>>>>> compile:
>>>>>> run:
>>>>>> nullnull
>>>>>>
>>>>>> Greetings,
>>>>>> H.Peter Gumm
>>>>>>
>>>>>>
>>>>>>
>>>>>>

Alec Zorab
Joined: 2010-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

in predef:

object Predef extends LowPriorityImplicits {
{...}
type String = java.lang.String
}

So obviously s.+(s) isn't calling String.+(), because that doesn't
exist. So where is this method? Intellij (not the highest authority,
but pretty decent) can't find an implicit conversion to anything with
a + method, so it appears your inference that + is a method on string
from the spec is incorrect.

Certainly, my interpretation of that line (and apparently also the
interpretation of the compiler-writers) is that we act *as though it
were a real method* when it is in fact just sugar over something else.

On Fri, Dec 3, 2010 at 5:01 PM, H. Peter Gumm
wrote:
> Whatever the compiler cares to do ...
>
> ... the outcome does not make sense, it is plainly a bug. Scala is not
> directly to blame, if it intends to stay compatible with Java and decides to
> faithfully copy the Java bugs.
>
> The following is what "The Scala Language Specification, Version 2.8" has to
> say about Strings:
>
>    12.3.1 Class String
>    Scala’s String class is usually derived from the standard String class
>    of the underlying host system (and may be identified with it). For
>    Scala clients the class is taken to support in each case a method
>           def + (that: Any): String
>    which concatenates its left operand with the textual representation
>    of its right operand.
>
> In particular:
>  1.  + is clearly stated to be "a method" of class String
>  2.  Scala's String is not forced to "be identified" with java.lang.String
>      but it "may be identified" and is only "usually derived"
>
> In conclusion
>     s.+(s)
> is a method call on object s which should return a NullPointerException when
> s is null.
>
> Greetings,
> H.Peter Gumm
>
>
> On 03.12.2010 22:34, Jim Balter wrote:
>>
>> "probably":
>>
>>         case StartConcat =>
>>           jcode.emitNEW(StringBuilderClass)
>>           jcode.emitDUP()
>>           jcode.emitINVOKESPECIAL(StringBuilderClass,
>>                                   JMethod.INSTANCE_CONSTRUCTOR_NAME,
>>                                   JMethodType.ARGLESS_VOID_FUNCTION)
>>
>>         case StringConcat(el) =>
>>           val jtype = el match {
>>             case REFERENCE(_) | ARRAY(_)=>  JObjectType.JAVA_LANG_OBJECT
>>             case _ =>  javaType(el)
>>           }
>>           jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>                                   "append",
>>                                   new JMethodType(StringBuilderType,
>>                                   Array(jtype)))
>>         case EndConcat =>
>>           jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>                                   "toString",
>>                                   toStringType)
>>
>>
>>
>> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>>
>>> probably this is what happens:
>>>
>>> scala>  var b = new StringBuilder()
>>> b: StringBuilder = StringBuilder()
>>>
>>> scala>  b.append( null: String )
>>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>>
>>> scala>  b.append( null: String )
>>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>>
>>> scala>  b.toString
>>> res21: java.lang.String = nullnull
>>>
>>>
>>>
>>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>>
>>>> "The Java language provides special support for the string
>>>> concatenation operator ( + ), and for conversion of other objects to
>>>> strings. String concatenation is implemented through the
>>>> StringBuilder(or StringBuffer) class and its append method." (
>>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>>>
>>>> now the javadoc of StringBuilder says that should cause a null-pointer
>>>> exception, and in fact it does:
>>>>
>>>> scala>  new StringBuilder( null: String ) java.lang.NullPointerException
>>>>
>>>> but still there seems to be a guard against that hidden somewhere...
>>>> the same happens in java
>>>>
>>>> public class Test {
>>>>   public static void main( String[] args ) {
>>>>      String a = null;
>>>>      System.out.println( a + a );  // prints nullnull ...
>>>>   }
>>>> }
>>>>
>>>> dunno....
>>>>
>>>> best, -sciss-
>>>>
>>>>
>>>>
>>>>
>>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>>
>>>>> Thanks for the explanations,
>>>>>
>>>>> but I do not understand either of them. Syntactically,
>>>>>
>>>>>   a.m(b)
>>>>>
>>>>> is a call of method m with argument b on object a. Right ? And when a
>>>>> is null, the method call on a should return a NullPointerException.
>>>>>
>>>>> At least this is what I used to teach my students.
>>>>>
>>>>> Are saying that this does not apply here ? I refuse to accept that
>>>>> "whatever a compiler does" defines the semantics
>>>>>
>>>>> H.Peter
>>>>>
>>>>>
>>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>>>
>>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>>
>>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>>>
>>>>>>> Why does the following compile ??
>>>>>>>
>>>>>>> def main(args: Array[String]): Unit = {
>>>>>>>    var s = "Scala";
>>>>>>>    s = null
>>>>>>>    var t = s.+(s)    // Shouldn't this be a NullPointerException
>>>>>>>    println(t)
>>>>>>>  }
>>>>>>>
>>>>>>> Recompiling 1 files
>>>>>>> compile:
>>>>>>> run:
>>>>>>> nullnull
>>>>>>>
>>>>>>> Greetings,
>>>>>>> H.Peter Gumm
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>

Alec Zorab
Joined: 2010-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

Actually, thinking about this a bit more,:

SLS page 75 says "A reference to any other member of the “null” object
causes a NullPointerException to be thrown."

So the question is whether "taken to support in each case a method"
means the same thing as "has a member method". This is obviously a
little open to interpretation, but I don't think the two are
equivalent.

On Fri, Dec 3, 2010 at 5:08 PM, Alec Zorab wrote:
> in predef:
>
> object Predef extends LowPriorityImplicits {
>  {...}
>  type String        = java.lang.String
> }
>
> So obviously s.+(s) isn't calling String.+(), because that doesn't
> exist. So where is this method? Intellij (not the highest authority,
> but pretty decent) can't find an implicit conversion to anything with
> a + method, so it appears your inference that + is a method on string
> from the spec is incorrect.
>
> Certainly, my interpretation of that line (and apparently also the
> interpretation of the compiler-writers) is that we act *as though it
> were a real method* when it is in fact just sugar over something else.
>
> On Fri, Dec 3, 2010 at 5:01 PM, H. Peter Gumm
> wrote:
>> Whatever the compiler cares to do ...
>>
>> ... the outcome does not make sense, it is plainly a bug. Scala is not
>> directly to blame, if it intends to stay compatible with Java and decides to
>> faithfully copy the Java bugs.
>>
>> The following is what "The Scala Language Specification, Version 2.8" has to
>> say about Strings:
>>
>>    12.3.1 Class String
>>    Scala’s String class is usually derived from the standard String class
>>    of the underlying host system (and may be identified with it). For
>>    Scala clients the class is taken to support in each case a method
>>           def + (that: Any): String
>>    which concatenates its left operand with the textual representation
>>    of its right operand.
>>
>> In particular:
>>  1.  + is clearly stated to be "a method" of class String
>>  2.  Scala's String is not forced to "be identified" with java.lang.String
>>      but it "may be identified" and is only "usually derived"
>>
>> In conclusion
>>     s.+(s)
>> is a method call on object s which should return a NullPointerException when
>> s is null.
>>
>> Greetings,
>> H.Peter Gumm
>>
>>
>> On 03.12.2010 22:34, Jim Balter wrote:
>>>
>>> "probably":
>>>
>>>         case StartConcat =>
>>>           jcode.emitNEW(StringBuilderClass)
>>>           jcode.emitDUP()
>>>           jcode.emitINVOKESPECIAL(StringBuilderClass,
>>>                                   JMethod.INSTANCE_CONSTRUCTOR_NAME,
>>>                                   JMethodType.ARGLESS_VOID_FUNCTION)
>>>
>>>         case StringConcat(el) =>
>>>           val jtype = el match {
>>>             case REFERENCE(_) | ARRAY(_)=>  JObjectType.JAVA_LANG_OBJECT
>>>             case _ =>  javaType(el)
>>>           }
>>>           jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>>                                   "append",
>>>                                   new JMethodType(StringBuilderType,
>>>                                   Array(jtype)))
>>>         case EndConcat =>
>>>           jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>>                                   "toString",
>>>                                   toStringType)
>>>
>>>
>>>
>>> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>>>
>>>> probably this is what happens:
>>>>
>>>> scala>  var b = new StringBuilder()
>>>> b: StringBuilder = StringBuilder()
>>>>
>>>> scala>  b.append( null: String )
>>>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>>>
>>>> scala>  b.append( null: String )
>>>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>>>
>>>> scala>  b.toString
>>>> res21: java.lang.String = nullnull
>>>>
>>>>
>>>>
>>>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>>>
>>>>> "The Java language provides special support for the string
>>>>> concatenation operator ( + ), and for conversion of other objects to
>>>>> strings. String concatenation is implemented through the
>>>>> StringBuilder(or StringBuffer) class and its append method." (
>>>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>>>>
>>>>> now the javadoc of StringBuilder says that should cause a null-pointer
>>>>> exception, and in fact it does:
>>>>>
>>>>> scala>  new StringBuilder( null: String ) java.lang.NullPointerException
>>>>>
>>>>> but still there seems to be a guard against that hidden somewhere...
>>>>> the same happens in java
>>>>>
>>>>> public class Test {
>>>>>   public static void main( String[] args ) {
>>>>>      String a = null;
>>>>>      System.out.println( a + a );  // prints nullnull ...
>>>>>   }
>>>>> }
>>>>>
>>>>> dunno....
>>>>>
>>>>> best, -sciss-
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>>>
>>>>>> Thanks for the explanations,
>>>>>>
>>>>>> but I do not understand either of them. Syntactically,
>>>>>>
>>>>>>   a.m(b)
>>>>>>
>>>>>> is a call of method m with argument b on object a. Right ? And when a
>>>>>> is null, the method call on a should return a NullPointerException.
>>>>>>
>>>>>> At least this is what I used to teach my students.
>>>>>>
>>>>>> Are saying that this does not apply here ? I refuse to accept that
>>>>>> "whatever a compiler does" defines the semantics
>>>>>>
>>>>>> H.Peter
>>>>>>
>>>>>>
>>>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>>>>
>>>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>>>
>>>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>>>>
>>>>>>>> Why does the following compile ??
>>>>>>>>
>>>>>>>> def main(args: Array[String]): Unit = {
>>>>>>>>    var s = "Scala";
>>>>>>>>    s = null
>>>>>>>>    var t = s.+(s)    // Shouldn't this be a NullPointerException
>>>>>>>>    println(t)
>>>>>>>>  }
>>>>>>>>
>>>>>>>> Recompiling 1 files
>>>>>>>> compile:
>>>>>>>> run:
>>>>>>>> nullnull
>>>>>>>>
>>>>>>>> Greetings,
>>>>>>>> H.Peter Gumm
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>
>

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

This reminds me a bit of my chemistry class back in High School. The
teacher told us the rules but when it came to applying them, they did
not work, because of yet another set of exceptions requiring a different
model. When you learned that better model it did not take long for the
same thing to happen again. This is why I hated Chemistry and went into
Math.

I quit teaching Java and decided teaching the Intro-Class in Scala
because I was sick of all these quirky rules and exceptions i had
earlier wasted my time with, when I'd wanted to teach language
principles rather than Java esoterics. I realize that the point I
raised is not a big thing, however, I would be very disappointed if
Scala was defined by whatever its compiler does or by whatever happened
to be in Predef. A language should be defined by a clear set of rules
and the compiler should follow these - not the other way around.

Greetings,
H.Peter

On 03.12.2010 23:08, Alec Zorab wrote:
> in predef:
>
> object Predef extends LowPriorityImplicits {
> {...}
> type String = java.lang.String
> }
>
> So obviously s.+(s) isn't calling String.+(), because that doesn't
> exist. So where is this method? Intellij (not the highest authority,
> but pretty decent) can't find an implicit conversion to anything with
> a + method, so it appears your inference that + is a method on string
> from the spec is incorrect.
>
> Certainly, my interpretation of that line (and apparently also the
> interpretation of the compiler-writers) is that we act *as though it
> were a real method* when it is in fact just sugar over something else.
>
> On Fri, Dec 3, 2010 at 5:01 PM, H. Peter Gumm
> wrote:
>> Whatever the compiler cares to do ...
>>
>> ... the outcome does not make sense, it is plainly a bug. Scala is not
>> directly to blame, if it intends to stay compatible with Java and decides to
>> faithfully copy the Java bugs.
>>
>> The following is what "The Scala Language Specification, Version 2.8" has to
>> say about Strings:
>>
>> 12.3.1 Class String
>> Scala’s String class is usually derived from the standard String class
>> of the underlying host system (and may be identified with it). For
>> Scala clients the class is taken to support in each case a method
>> def + (that: Any): String
>> which concatenates its left operand with the textual representation
>> of its right operand.
>>
>> In particular:
>> 1. + is clearly stated to be "a method" of class String
>> 2. Scala's String is not forced to "be identified" with java.lang.String
>> but it "may be identified" and is only "usually derived"
>>
>> In conclusion
>> s.+(s)
>> is a method call on object s which should return a NullPointerException when
>> s is null.
>>
>> Greetings,
>> H.Peter Gumm
>>
>>
>> On 03.12.2010 22:34, Jim Balter wrote:
>>> "probably":
>>>
>>> case StartConcat =>
>>> jcode.emitNEW(StringBuilderClass)
>>> jcode.emitDUP()
>>> jcode.emitINVOKESPECIAL(StringBuilderClass,
>>> JMethod.INSTANCE_CONSTRUCTOR_NAME,
>>> JMethodType.ARGLESS_VOID_FUNCTION)
>>>
>>> case StringConcat(el) =>
>>> val jtype = el match {
>>> case REFERENCE(_) | ARRAY(_)=> JObjectType.JAVA_LANG_OBJECT
>>> case _ => javaType(el)
>>> }
>>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>> "append",
>>> new JMethodType(StringBuilderType,
>>> Array(jtype)))
>>> case EndConcat =>
>>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>> "toString",
>>> toStringType)
>>>
>>>
>>>
>>> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>>>
>>>> probably this is what happens:
>>>>
>>>> scala> var b = new StringBuilder()
>>>> b: StringBuilder = StringBuilder()
>>>>
>>>> scala> b.append( null: String )
>>>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>>>
>>>> scala> b.append( null: String )
>>>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>>>
>>>> scala> b.toString
>>>> res21: java.lang.String = nullnull
>>>>
>>>>
>>>>
>>>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>>>
>>>>> "The Java language provides special support for the string
>>>>> concatenation operator ( + ), and for conversion of other objects to
>>>>> strings. String concatenation is implemented through the
>>>>> StringBuilder(or StringBuffer) class and its append method." (
>>>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>>>>
>>>>> now the javadoc of StringBuilder says that should cause a null-pointer
>>>>> exception, and in fact it does:
>>>>>
>>>>> scala> new StringBuilder( null: String ) java.lang.NullPointerException
>>>>>
>>>>> but still there seems to be a guard against that hidden somewhere...
>>>>> the same happens in java
>>>>>
>>>>> public class Test {
>>>>> public static void main( String[] args ) {
>>>>> String a = null;
>>>>> System.out.println( a + a ); // prints nullnull ...
>>>>> }
>>>>> }
>>>>>
>>>>> dunno....
>>>>>
>>>>> best, -sciss-
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>>>
>>>>>> Thanks for the explanations,
>>>>>>
>>>>>> but I do not understand either of them. Syntactically,
>>>>>>
>>>>>> a.m(b)
>>>>>>
>>>>>> is a call of method m with argument b on object a. Right ? And when a
>>>>>> is null, the method call on a should return a NullPointerException.
>>>>>>
>>>>>> At least this is what I used to teach my students.
>>>>>>
>>>>>> Are saying that this does not apply here ? I refuse to accept that
>>>>>> "whatever a compiler does" defines the semantics
>>>>>>
>>>>>> H.Peter
>>>>>>
>>>>>>
>>>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>>>
>>>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>>>> Why does the following compile ??
>>>>>>>>
>>>>>>>> def main(args: Array[String]): Unit = {
>>>>>>>> var s = "Scala";
>>>>>>>> s = null
>>>>>>>> var t = s.+(s) // Shouldn't this be a NullPointerException
>>>>>>>> println(t)
>>>>>>>> }
>>>>>>>>
>>>>>>>> Recompiling 1 files
>>>>>>>> compile:
>>>>>>>> run:
>>>>>>>> nullnull
>>>>>>>>
>>>>>>>> Greetings,
>>>>>>>> H.Peter Gumm
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

On 12/03/2010 02:08 PM, Alec Zorab wrote:
> Certainly, my interpretation of that line (and apparently also the
> interpretation of the compiler-writers) is that we act *as though it
> were a real method* when it is in fact just sugar over something else.

I can see both interpretations (indeed, I initially shared yours), but I
think I'm leaning the other way now. If "the [String] class is taken to
support" a '+' method, then from the client's point of view '+' should
be indistinguishable from a real method call regardless of what the
underlying implementation is.

If the argument is that the current behavior is desirable from an
interop perspective (although that seems somewhat perverse to me), then
the spec should be clarified on this point. Otherwise it should throw an
NPE when the left operand is null.

~Aaron

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

Aha! The method issue aside, I think we can state that this is
unambiguously a bug, based on the behavior attributed to '+':

"... concatenates its *left operand* with the *textual representation
of* its right operand."

Note that it does not say, "... concatenates the textual representation
of its left operand with the textual representation of its right
operand." Clearly "nullnull" is the concatenation of "null" with "null"
and not the concatenation of null with "null", so the operator/method
does not behave according to spec.

Would you like to file the bug or shall I?

P.S. Do I get language lawyer points?

On 12/03/2010 02:01 PM, H. Peter Gumm wrote:
> Whatever the compiler cares to do ...
>
> ... the outcome does not make sense, it is plainly a bug. Scala is not
> directly to blame, if it intends to stay compatible with Java and
> decides to faithfully copy the Java bugs.
>
> The following is what "The Scala Language Specification, Version 2.8"
> has to say about Strings:
>
> 12.3.1 Class String
> Scala’s String class is usually derived from the standard String class
> of the underlying host system (and may be identified with it). For
> Scala clients the class is taken to support in each case a method
> def + (that: Any): String
> which concatenates its left operand with the textual representation
> of its right operand.
>
> In particular:
> 1. + is clearly stated to be "a method" of class String
> 2. Scala's String is not forced to "be identified" with java.lang.String
> but it "may be identified" and is only "usually derived"
>
> In conclusion
> s.+(s)
> is a method call on object s which should return a NullPointerException
> when s is null.
>
> Greetings,
> H.Peter Gumm

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Re: null + null = ??

hey, you are hunting a ghost, please check the remainder of this thread...

http://scala-programming-language.1934581.n4.nabble.com/null-null-tt3071...

Am 03.12.2010 um 23:44 schrieb Aaron Novstrup:

> Aha! The method issue aside, I think we can state that this is
> unambiguously a bug, based on the behavior attributed to '+':
>
> "... concatenates its *left operand* with the *textual representation
> of* its right operand."
>
> Note that it does not say, "... concatenates the textual representation
> of its left operand with the textual representation of its right
> operand." Clearly "nullnull" is the concatenation of "null" with "null"
> and not the concatenation of null with "null", so the operator/method
> does not behave according to spec.
>
> Would you like to file the bug or shall I?
>
> P.S. Do I get language lawyer points?
>
> On 12/03/2010 02:01 PM, H. Peter Gumm wrote:
>> Whatever the compiler cares to do ...
>>
>> ... the outcome does not make sense, it is plainly a bug. Scala is not
>> directly to blame, if it intends to stay compatible with Java and
>> decides to faithfully copy the Java bugs.
>>
>> The following is what "The Scala Language Specification, Version 2.8"
>> has to say about Strings:
>>
>> 12.3.1 Class String
>> Scala’s String class is usually derived from the standard String class
>> of the underlying host system (and may be identified with it). For
>> Scala clients the class is taken to support in each case a method
>> def + (that: Any): String
>> which concatenates its left operand with the textual representation
>> of its right operand.
>>
>> In particular:
>> 1. + is clearly stated to be "a method" of class String
>> 2. Scala's String is not forced to "be identified" with java.lang.String
>> but it "may be identified" and is only "usually derived"
>>
>> In conclusion
>> s.+(s)
>> is a method call on object s which should return a NullPointerException
>> when s is null.
>>
>> Greetings,
>> H.Peter Gumm
>

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

I already read that. It appears Jim found the ghost (and I thought they
were invisible!). As far as I can tell, Jim's post simply confirms that
the compiler is not implementing the spec correctly.

On 12/03/2010 04:02 PM, Sciss wrote:
> hey, you are hunting a ghost, please check the remainder of this thread...
>
> http://scala-programming-language.1934581.n4.nabble.com/null-null-tt3071...
>
> Am 03.12.2010 um 23:44 schrieb Aaron Novstrup:
>
>> Aha! The method issue aside, I think we can state that this is
>> unambiguously a bug, based on the behavior attributed to '+':
>>
>> "... concatenates its *left operand* with the *textual representation
>> of* its right operand."
>>
>> Note that it does not say, "... concatenates the textual representation
>> of its left operand with the textual representation of its right
>> operand." Clearly "nullnull" is the concatenation of "null" with "null"
>> and not the concatenation of null with "null", so the operator/method
>> does not behave according to spec.
>>
>> Would you like to file the bug or shall I?
>>
>> P.S. Do I get language lawyer points?

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 23:36:50 +0100, H. Peter Gumm wrote:

> This reminds me a bit of my chemistry class back in High School. The
> teacher told us the rules but when it came to applying them, they did
> not work, because of yet another set of exceptions requiring a different
> model. When you learned that better model it did not take long for the
> same thing to happen again. This is why I hated Chemistry and went into
> Math.
>
> I quit teaching Java and decided teaching the Intro-Class in Scala
> because I was sick of all these quirky rules and exceptions i had
> earlier wasted my time with, when I'd wanted to teach language
> principles rather than Java esoterics. I realize that the point I
> raised is not a big thing, however, I would be very disappointed if
> Scala was defined by whatever its compiler does or by whatever happened
> to be in Predef. A language should be defined by a clear set of rules
> and the compiler should follow these - not the other way around.

This has been answered several times now. As Paul Philips said, there is
a SPECial SPECtacular SPECific definition, known as the Scala
Language ....ification. If the compiler does not agree with it, then the
compiler is in error. As so often happens, though, if the definition is
even slightly ambiguous, people at first tend to defend the compiler. In
this case I think that's a mistake -- this is a bug. Your disappointment
should only extend to that.

>
> Greetings,
> H.Peter
>
> On 03.12.2010 23:08, Alec Zorab wrote:
>> in predef:
>>
>> object Predef extends LowPriorityImplicits {
>> {...}
>> type String = java.lang.String
>> }
>>
>> So obviously s.+(s) isn't calling String.+(), because that doesn't
>> exist. So where is this method? Intellij (not the highest authority,
>> but pretty decent) can't find an implicit conversion to anything with a
>> + method, so it appears your inference that + is a method on string
>> from the spec is incorrect.
>>
>> Certainly, my interpretation of that line (and apparently also the
>> interpretation of the compiler-writers) is that we act *as though it
>> were a real method* when it is in fact just sugar over something else.
>>
>> On Fri, Dec 3, 2010 at 5:01 PM, H. Peter Gumm
>>
>> wrote:
>>> Whatever the compiler cares to do ...
>>>
>>> ... the outcome does not make sense, it is plainly a bug. Scala is not
>>> directly to blame, if it intends to stay compatible with Java and
>>> decides to faithfully copy the Java bugs.
>>>
>>> The following is what "The Scala Language Specification, Version 2.8"
>>> has to say about Strings:
>>>
>>> 12.3.1 Class String
>>> Scala’s String class is usually derived from the standard String
>>> class of the underlying host system (and may be identified with
>>> it). For Scala clients the class is taken to support in each case
>>> a method
>>> def + (that: Any): String
>>> which concatenates its left operand with the textual
>>> representation of its right operand.
>>>
>>> In particular:
>>> 1. + is clearly stated to be "a method" of class String 2. Scala's
>>> String is not forced to "be identified" with java.lang.String
>>> but it "may be identified" and is only "usually derived"
>>>
>>> In conclusion
>>> s.+(s)
>>> is a method call on object s which should return a
>>> NullPointerException when s is null.
>>>
>>> Greetings,
>>> H.Peter Gumm
>>>
>>>
>>> On 03.12.2010 22:34, Jim Balter wrote:
>>>> "probably":
>>>>
>>>> case StartConcat =>
>>>> jcode.emitNEW(StringBuilderClass)
>>>> jcode.emitDUP()
>>>> jcode.emitINVOKESPECIAL(StringBuilderClass,
>>>> JMethod.INSTANCE_CONSTRUCTOR_NAME,
>>>> JMethodType.ARGLESS_VOID_FUNCTION)
>>>>
>>>> case StringConcat(el) =>
>>>> val jtype = el match {
>>>> case REFERENCE(_) | ARRAY(_)=>
>>>> JObjectType.JAVA_LANG_OBJECT case _ => javaType(el)
>>>> }
>>>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>>> "append",
>>>> new JMethodType(StringBuilderType,
>>>> Array(jtype)))
>>>> case EndConcat =>
>>>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>>>> "toString",
>>>> toStringType)
>>>>
>>>>
>>>>
>>>> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>>>>
>>>>> probably this is what happens:
>>>>>
>>>>> scala> var b = new StringBuilder() b: StringBuilder =
>>>>> StringBuilder()
>>>>>
>>>>> scala> b.append( null: String )
>>>>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>>>>
>>>>> scala> b.append( null: String )
>>>>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>>>>
>>>>> scala> b.toString
>>>>> res21: java.lang.String = nullnull
>>>>>
>>>>>
>>>>>
>>>>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>>>>
>>>>>> "The Java language provides special support for the string
>>>>>> concatenation operator ( + ), and for conversion of other objects
>>>>>> to strings. String concatenation is implemented through the
>>>>>> StringBuilder(or StringBuffer) class and its append method." (
>>>>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html
>>>>>> )
>>>>>>
>>>>>> now the javadoc of StringBuilder says that should cause a
>>>>>> null-pointer exception, and in fact it does:
>>>>>>
>>>>>> scala> new StringBuilder( null: String )
>>>>>> java.lang.NullPointerException
>>>>>>
>>>>>> but still there seems to be a guard against that hidden
>>>>>> somewhere... the same happens in java
>>>>>>
>>>>>> public class Test {
>>>>>> public static void main( String[] args ) {
>>>>>> String a = null;
>>>>>> System.out.println( a + a ); // prints nullnull ...
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> dunno....
>>>>>>
>>>>>> best, -sciss-
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>>>>
>>>>>>> Thanks for the explanations,
>>>>>>>
>>>>>>> but I do not understand either of them. Syntactically,
>>>>>>>
>>>>>>> a.m(b)
>>>>>>>
>>>>>>> is a call of method m with argument b on object a. Right ? And
>>>>>>> when a is null, the method call on a should return a
>>>>>>> NullPointerException.
>>>>>>>
>>>>>>> At least this is what I used to teach my students.
>>>>>>>
>>>>>>> Are saying that this does not apply here ? I refuse to accept that
>>>>>>> "whatever a compiler does" defines the semantics
>>>>>>>
>>>>>>> H.Peter
>>>>>>>
>>>>>>>
>>>>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>>>>
>>>>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>>>>> Why does the following compile ??
>>>>>>>>>
>>>>>>>>> def main(args: Array[String]): Unit = {
>>>>>>>>> var s = "Scala";
>>>>>>>>> s = null
>>>>>>>>> var t = s.+(s) // Shouldn't this be a
>>>>>>>>> NullPointerException println(t)
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Recompiling 1 files
>>>>>>>>> compile:
>>>>>>>>> run:
>>>>>>>>> nullnull
>>>>>>>>>
>>>>>>>>> Greetings,
>>>>>>>>> H.Peter Gumm
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 23:01:43 +0100, H. Peter Gumm wrote:

> Whatever the compiler cares to do ...

Has anyone claimed that? All I did was identify what the compiler *does*
do, after others speculated that it does that.

> ... the outcome does not make sense, it is plainly a bug. Scala is not
> directly to blame, if it intends to stay compatible with Java and
> decides to faithfully copy the Java bugs.
>
> The following is what "The Scala Language Specification, Version 2.8"
> has to say about Strings:
>
> 12.3.1 Class String
> Scala’s String class is usually derived from the standard String
> class of the underlying host system (and may be identified with it).
> For Scala clients the class is taken to support in each case a
> method
> def + (that: Any): String
> which concatenates its left operand with the textual representation
> of its right operand.
>
> In particular:
> 1. + is clearly stated to be "a method" of class String 2. Scala's
> String is not forced to "be identified" with java.lang.String
> but it "may be identified" and is only "usually derived"
>
> In conclusion
> s.+(s)
> is a method call on object s

Not exactly. String is "taken to support" such a method, but there is no
such method of String.

> which should return a NullPointerException
> when s is null.

I agree, it should, since that is what `+` would do if there *were* such
a method of String, and there is no justification for converting (the
first) null to "null" here.

Have you filed a bug yet?

>
> Greetings,
> H.Peter Gumm
>
>
> On 03.12.2010 22:34, Jim Balter wrote:
>> "probably":
>>
>> case StartConcat =>
>> jcode.emitNEW(StringBuilderClass)
>> jcode.emitDUP()
>> jcode.emitINVOKESPECIAL(StringBuilderClass,
>> JMethod.INSTANCE_CONSTRUCTOR_NAME,
>> JMethodType.ARGLESS_VOID_FUNCTION)
>>
>> case StringConcat(el) =>
>> val jtype = el match {
>> case REFERENCE(_) | ARRAY(_)=>
>> JObjectType.JAVA_LANG_OBJECT case _ => javaType(el)
>> }
>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>> "append",
>> new JMethodType(StringBuilderType,
>> Array(jtype)))
>> case EndConcat =>
>> jcode.emitINVOKEVIRTUAL(StringBuilderClass,
>> "toString",
>> toStringType)
>>
>>
>>
>> On Fri, 03 Dec 2010 19:27:54 +0000, Sciss wrote:
>>
>>> probably this is what happens:
>>>
>>> scala> var b = new StringBuilder()
>>> b: StringBuilder = StringBuilder()
>>>
>>> scala> b.append( null: String )
>>> res19: StringBuilder = StringBuilder(n, u, l, l)
>>>
>>> scala> b.append( null: String )
>>> res20: StringBuilder = StringBuilder(n, u, l, l, n, u, l, l)
>>>
>>> scala> b.toString
>>> res21: java.lang.String = nullnull
>>>
>>>
>>>
>>> Am 03.12.2010 um 19:25 schrieb Sciss:
>>>
>>>> "The Java language provides special support for the string
>>>> concatenation operator ( + ), and for conversion of other objects to
>>>> strings. String concatenation is implemented through the
>>>> StringBuilder(or StringBuffer) class and its append method." (
>>>> http://download.oracle.com/javase/6/docs/api/java/lang/String.html )
>>>>
>>>> now the javadoc of StringBuilder says that should cause a
>>>> null-pointer exception, and in fact it does:
>>>>
>>>> scala> new StringBuilder( null: String )
>>>> java.lang.NullPointerException
>>>>
>>>> but still there seems to be a guard against that hidden somewhere...
>>>> the same happens in java
>>>>
>>>> public class Test {
>>>> public static void main( String[] args ) {
>>>> String a = null;
>>>> System.out.println( a + a ); // prints nullnull ...
>>>> }
>>>> }
>>>>
>>>> dunno....
>>>>
>>>> best, -sciss-
>>>>
>>>>
>>>>
>>>>
>>>> Am 03.12.2010 um 19:18 schrieb H. Peter Gumm:
>>>>
>>>>> Thanks for the explanations,
>>>>>
>>>>> but I do not understand either of them. Syntactically,
>>>>>
>>>>> a.m(b)
>>>>>
>>>>> is a call of method m with argument b on object a. Right ? And when
>>>>> a is null, the method call on a should return a
>>>>> NullPointerException.
>>>>>
>>>>> At least this is what I used to teach my students.
>>>>>
>>>>> Are saying that this does not apply here ? I refuse to accept that
>>>>> "whatever a compiler does" defines the semantics
>>>>>
>>>>> H.Peter
>>>>>
>>>>>
>>>>> On 03.12.2010 20:02, HamsterofDeath wrote:
>>>>>> probably compiles to String.valueOf(s) + String.valueOf(s)
>>>>>>
>>>>>> Am 03.12.2010 19:45, schrieb H. Peter Gumm:
>>>>>>> Why does the following compile ??
>>>>>>>
>>>>>>> def main(args: Array[String]): Unit = {
>>>>>>> var s = "Scala";
>>>>>>> s = null
>>>>>>> var t = s.+(s) // Shouldn't this be a NullPointerException
>>>>>>> println(t)
>>>>>>> }
>>>>>>>
>>>>>>> Recompiling 1 files
>>>>>>> compile:
>>>>>>> run:
>>>>>>> nullnull
>>>>>>>
>>>>>>> Greetings,
>>>>>>> H.Peter Gumm
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Sat, 04 Dec 2010 00:02:17 +0000, Sciss wrote:

> hey, you are hunting a ghost, please check the remainder of this
> thread...
>
> http://scala-programming-language.1934581.n4.nabble.com/null-null-
tt3071566.html#a3071805

All I did there is identify the code that implements this ... wrongly; it
isn't relevant to Aaron's comments below, which I agree with.

> Am 03.12.2010 um 23:44 schrieb Aaron Novstrup:
>
>> Aha! The method issue aside, I think we can state that this is
>> unambiguously a bug, based on the behavior attributed to '+':
>>
>> "... concatenates its *left operand* with the *textual representation
>> of* its right operand."
>>
>> Note that it does not say, "... concatenates the textual representation
>> of its left operand with the textual representation of its right
>> operand." Clearly "nullnull" is the concatenation of "null" with "null"
>> and not the concatenation of null with "null", so the operator/method
>> does not behave according to spec.
>>
>> Would you like to file the bug or shall I?
>>
>> P.S. Do I get language lawyer points?
>>
>> On 12/03/2010 02:01 PM, H. Peter Gumm wrote:
>>> Whatever the compiler cares to do ...
>>>
>>> ... the outcome does not make sense, it is plainly a bug. Scala is not
>>> directly to blame, if it intends to stay compatible with Java and
>>> decides to faithfully copy the Java bugs.
>>>
>>> The following is what "The Scala Language Specification, Version 2.8"
>>> has to say about Strings:
>>>
>>> 12.3.1 Class String
>>> Scala’s String class is usually derived from the standard String
>>> class of the underlying host system (and may be identified with it).
>>> For Scala clients the class is taken to support in each case a
>>> method
>>> def + (that: Any): String
>>> which concatenates its left operand with the textual representation
>>> of its right operand.
>>>
>>> In particular:
>>> 1. + is clearly stated to be "a method" of class String 2. Scala's
>>> String is not forced to "be identified" with java.lang.String
>>> but it "may be identified" and is only "usually derived"
>>>
>>> In conclusion
>>> s.+(s)
>>> is a method call on object s which should return a
>>> NullPointerException when s is null.
>>>
>>> Greetings,
>>> H.Peter Gumm
>>

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 14:37:25 -0800, Aaron Novstrup wrote:

> On 12/03/2010 02:08 PM, Alec Zorab wrote:
>> Certainly, my interpretation of that line (and apparently also the
>> interpretation of the compiler-writers) is that we act *as though it
>> were a real method* when it is in fact just sugar over something else.
>
> I can see both interpretations (indeed, I initially shared yours), but I
> think I'm leaning the other way now.

I do not think that's "the other way" ... I don't think Alec recognizes
the implications of what he wrote: if we act as though it were a real
method, then we throw an NPE (what a dumb misnomer for a language without
pointers!) -- that's how a real method would act. Sugar is the wrong
concept here -- `+` isn't "sugar" over StringBuilder, it's *implemented*
in terms of StringBuilder ... wrongly. There is no mention of any
"something else" in the spec, there is only mention of a method call, and
that's what this should act like, *precisely*.

> If "the [String] class is taken to
> support" a '+' method, then from the client's point of view '+' should
> be indistinguishable from a real method call regardless of what the
> underlying implementation is.
>
> If the argument is that the current behavior is desirable from an
> interop perspective (although that seems somewhat perverse to me), then
> the spec should be clarified on this point. Otherwise it should throw an
> NPE when the left operand is null.

Indeed. It's hard to be more perverse than for Scala to *intentionally*
copy Java's bugs.

>
> ~Aaron
> begin:vcard
> fn:Aaron Novstrup
> n:Novstrup;Aaron
> org:Stottler Henke Associates Inc.
> adr;dom:;;1107 NE 45th St;Seattle;WA;98105
> email;internet:anovstrup@stottlerhenke.com title:AI Software Engineer
> tel;work:206.545.2941
> x-mozilla-html:FALSE
> url:www.stottlerhenke.com
> version:2.1
> end:vcard

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

On 12/03/2010 05:42 PM, Jim Balter wrote:
> On Fri, 03 Dec 2010 14:37:25 -0800, Aaron Novstrup wrote:
>> If the argument is that the current behavior is desirable from an
>> interop perspective (although that seems somewhat perverse to me), then
>> the spec should be clarified on this point. Otherwise it should throw an
>> NPE when the left operand is null.
>
> Indeed. It's hard to be more perverse than for Scala to *intentionally*
> copy Java's bugs.

I equivocated on this point somewhat because I can see the argument for
having String concatenation work this way in Java. In particular, one
might desire that the operator be symmetrical with respect to its
operands in the sense that

(a concat b) == cd // for some values a,b, and strings c, d

implies

(b concat a) == dc

In Scala, on the other hand, I think consistency is more important. And
catering to some esoteric corner case involving null Strings does not
seem like The Scala Way.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: null + null = ??

On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote:
> In Scala, on the other hand, I think consistency is more important.
> And catering to some esoteric corner case involving null Strings does
> not seem like The Scala Way.

I can't tell from this whether you think throwing the NPE is "catering
to some esoteric corner case" or NOT throwing the NPE is.

All anyone is likely to get out of this is a spec update. The
alternative, where we slow down every usage of '+' to do a null check
just so we can satisfy someone's desire for NPEs is not so convincing.
I'll ship you a whole box if you're running out.

An amusing aspect of this discussion is that nobody seems to have keyed
in on its irrelevance. Remove the fake '+' method from String and
(null: String) + null will behave... exactly as it does now.

scala> (null: List[Int]) + null
res0: java.lang.String = nullnull

Look, even java classes are messing with the purity of the null pointer
exception. Who knew those jdk classes were so daring.

scala> (null: java.util.ArrayList[String]) + null
res1: java.lang.String = nullnull

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

On 12/03/2010 07:28 PM, Paul Phillips wrote:
> On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote:
>> In Scala, on the other hand, I think consistency is more important.
>> And catering to some esoteric corner case involving null Strings does
>> not seem like The Scala Way.
>
> I can't tell from this whether you think throwing the NPE is "catering
> to some esoteric corner case" or NOT throwing the NPE is.

I meant "catering" in the sense of defining special behavior for the `+`
operator just to be consistent with Java semantics. If it's for
performance reasons, that's another matter entirely.

I'd be happy with a spec change -- at least specifying that the `+`
operator exists and defining its semantics, and taking out the bit about
String's non-existent `+` method.

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 19:28:56 -0800, Paul Phillips wrote:

> On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote:
>> In Scala, on the other hand, I think consistency is more important. And
>> catering to some esoteric corner case involving null Strings does not
>> seem like The Scala Way.
>
> I can't tell from this whether you think throwing the NPE is "catering
> to some esoteric corner case" or NOT throwing the NPE is.

I have no trouble telling that Aaron meant the latter ... let's see if he
confirms that.

> All anyone is likely to get out of this is a spec update. The
> alternative, where we slow down every usage of '+' to do a null check
> just so we can satisfy someone's desire for NPEs is not so convincing.
> I'll ship you a whole box if you're running out.

Why be so nasty? It's not a desire for NPEs, it's a desire that invoking
a method on null does what it's speced to do. The speed argument is, as
usual, not so convincing. The fact is that the argument to StringBuilder
is already being checked for null in order to produce "null"; it would
actually be faster to implement a custom version of StringBuilder that
didn't do that and just produced the NPE. It would also be faster to
invoke the StringBuilder(String) constructor with the first string
instead of invoking the default constructor and then appending the first
string.

> An amusing aspect of this discussion is that nobody seems to have keyed
> in on its irrelevance. Remove the fake '+' method from String and
> (null: String) + null will behave... exactly as it does now.
>
> scala> (null: List[Int]) + null
> res0: java.lang.String = nullnull

You know your way all around this language and I barely know it at all,
so it would help if you would explain that result, and how we know that
the fake '+' isn't being invoked.

>
> Look, even java classes are messing with the purity of the null pointer
> exception. Who knew those jdk classes were so daring.

Your snark does not help. AFAICS, jdk classes can't do anything about the
fact that Null does not implement any methods. ISTM that if null + x does
not throw an NPE, it's because '+' is being handled by the compiler and
not as a method invocation on Null.

>
> scala> (null: java.util.ArrayList[String]) + null res1: java.lang.String
> = nullnull

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

On 12/03/2010 08:53 PM, Jim Balter wrote:
> On Fri, 03 Dec 2010 19:28:56 -0800, Paul Phillips wrote:
>> On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote:
>> I can't tell from this whether you think throwing the NPE is "catering
>> to some esoteric corner case" or NOT throwing the NPE is.
>
> I have no trouble telling that Aaron meant the latter ... let's see if he
> confirms that.

Confirmed.

>> All anyone is likely to get out of this is a spec update. The
>> alternative, where we slow down every usage of '+' to do a null check
>> just so we can satisfy someone's desire for NPEs is not so convincing.
>> I'll ship you a whole box if you're running out.

I *have* been running low these days (not using Java much), but I
generated a few the other day so I think I can hold out.

> The speed argument is, as usual, not so convincing. The fact is that
> the argument to StringBuilder is already being checked for null in
> order to produce "null"; it would actually be faster to implement a
> custom version of StringBuilder that didn't do that and just produced
> the NPE. It would also be faster to invoke the StringBuilder(String)
> constructor with the first string instead of invoking the default
> constructor and then appending the first string.

Good point.

>> An amusing aspect of this discussion is that nobody seems to have keyed
>> in on its irrelevance. Remove the fake '+' method from String and
>> (null: String) + null will behave... exactly as it does now.
>>
>> scala> (null: List[Int]) + null
>> res0: java.lang.String = nullnull
>
> You know your way all around this language and I barely know it at all,
> so it would help if you would explain that result, and how we know that
> the fake '+' isn't being invoked.

I'm curious about this, too, especially since I couldn't find anything
in the spec that would explain it.

>> Look, even java classes are messing with the purity of the null pointer
>> exception. Who knew those jdk classes were so daring.
>
> Your snark does not help.

Maybe he'll correct me, but I don't think Paul intends to be snarky. He
just has a very sarcastic sense of humor that you'll come to appreciate
after being on this list a while. It would be pretty dry here without it.

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 20:24:14 -0800, Aaron Novstrup wrote:

> On 12/03/2010 07:28 PM, Paul Phillips wrote:
>> On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote:
>>> In Scala, on the other hand, I think consistency is more important.
>>> And catering to some esoteric corner case involving null Strings does
>>> not seem like The Scala Way.
>>
>> I can't tell from this whether you think throwing the NPE is "catering
>> to some esoteric corner case" or NOT throwing the NPE is.
>
> I meant "catering" in the sense of defining special behavior for the `+`
> operator just to be consistent with Java semantics.

Yes, somehow the context got lost -- if someone can't tell what the
person they are responding to meant, it might be a good idea to snip
less. The discussion was about whether scala should do something that
appears to be a bug just because Java does it that way. The thing is, as
you pointed out, it isn't a bug in Java because '+' is an operator, not a
method.

> If it's for
> performance reasons, that's another matter entirely.
>
> I'd be happy with a spec change -- at least specifying that the `+`
> operator exists and defining its semantics, and taking out the bit about
> String's non-existent `+` method.

Keep in mind that all operators in Scala are methods. (I seem to be
agreeing with H.Peter's original point.) ISTM that it should be a method
of RichString ... or I guess StringLike in 2.8 . A naive implementation
would take quite a performance hit for more than one '+' in a sequence,
but any optimization should preserve the semantics.

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 21:11:13 -0800, Aaron Novstrup wrote:

>> Your snark does not help.
>
> Maybe he'll correct me, but I don't think Paul intends to be snarky. He
> just has a very sarcastic sense of humor that you'll come to appreciate
> after being on this list a while. It would be pretty dry here without
> it.

From http://en.wiktionary.org/wiki/snark :
Synonyms
* (snide comments): sarcasm

I appreciate well-crafted sarcasm and other forms of humor, but I do not
think it helps to belittle people and misrepresent their intentions and
motivations just to try to win a debate, especially a debate about
whether and what technical changes should be made.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: null + null = ??

On Sat, Dec 04, 2010 at 05:35:47AM +0000, Jim Balter wrote:
> I appreciate well-crafted sarcasm and other forms of humor, but I do
> not think it helps to belittle people and misrepresent their
> intentions and motivations just to try to win a debate, especially a
> debate about whether and what technical changes should be made.

I don't know what prize you have in mind when you speak of winning
something, but you are the only one on the racetrack. I was trying to
save you some effort because there are still a bunch of bikesheds
missing plumbing and silverware and I hate to see people putting another
coat of paint on this one, thinking it might sell if only they can find
the right shade of mauve. I'm sorry I caused you any angst. By all
means, spruce 'er up.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: null + null = ??

On Sat, Dec 04, 2010 at 04:53:53AM +0000, Jim Balter wrote:
> > scala> (null: List[Int]) + null
> > res0: java.lang.String = nullnull
>
> You know your way all around this language and I barely know it at all,
> so it would help if you would explain that result, and how we know that
> the fake '+' isn't being invoked.

You know it isn't being invoked because the fake '+' is a method on
String, not List[Int].

We have lots more of these you know.

// toInt not actually a method on String
scala> "123".toInt
res0: Int = 123

// -> not actually a method on AnyRef
scala> new AnyRef -> 5
res1: (java.lang.Object, Int) = (java.lang.Object@67d7a04,5)

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 21:11:13 -0800, Aaron Novstrup wrote:

> On 12/03/2010 08:53 PM, Jim Balter wrote:
>> On Fri, 03 Dec 2010 19:28:56 -0800, Paul Phillips wrote:
>>> On Fri, Dec 03, 2010 at 06:57:55PM -0800, Aaron Novstrup wrote: I
>>> can't tell from this whether you think throwing the NPE is "catering
>>> to some esoteric corner case" or NOT throwing the NPE is.
>>
>> I have no trouble telling that Aaron meant the latter ... let's see if
>> he confirms that.
>
> Confirmed.
>
>>> All anyone is likely to get out of this is a spec update. The
>>> alternative, where we slow down every usage of '+' to do a null check
>>> just so we can satisfy someone's desire for NPEs is not so convincing.
>>> I'll ship you a whole box if you're running out.
>
> I *have* been running low these days (not using Java much), but I
> generated a few the other day so I think I can hold out.
>
>> The speed argument is, as usual, not so convincing. The fact is that
>> the argument to StringBuilder is already being checked for null in
>> order to produce "null"; it would actually be faster to implement a
>> custom version of StringBuilder that didn't do that and just produced
>> the NPE. It would also be faster to invoke the StringBuilder(String)
>> constructor with the first string instead of invoking the default
>> constructor and then appending the first string.
>
> Good point.
>
>>> An amusing aspect of this discussion is that nobody seems to have
>>> keyed in on its irrelevance. Remove the fake '+' method from String
>>> and (null: String) + null will behave... exactly as it does now.
>>>
>>> scala> (null: List[Int]) + null
>>> res0: java.lang.String = nullnull
>>
>> You know your way all around this language and I barely know it at all,
>> so it would help if you would explain that result, and how we know that
>> the fake '+' isn't being invoked.
>
> I'm curious about this, too, especially since I couldn't find anything
> in the spec that would explain it.

I think I may now understand this (no thanks to Paul, who seems to
prefer to babble about painting bikesheds). From PreDef.scala:

implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)

and from StringAdd:

def +(other: String) = String.valueOf(self) + other

As I pointed out to H.Peter several times, a.m(b) does not apply method m
to a if a's type doesn't have that method; rather, it may apply an
implicit conversion. All his years of teaching his students that an NPE
results if a is null don't apply because he was teaching Java, but this
isn't Java.

Given that this is done implicitly, the spec should be changed not to
talk about `+` being "taken to be" a method on String. The behavior can
be left unchanged, and is not a bug, but no thanks to bogus arguments
about slowing things down with extra null checks.

Note: I have written almost no Scala code, and I am certainly no expert.
I welcome anyone who is an expert to correct any error or misconception
of mine, preferably without being a jerk about it.

>>> Look, even java classes are messing with the purity of the null
>>> pointer exception. Who knew those jdk classes were so daring.
>>
>> Your snark does not help.
>
> Maybe he'll correct me, but I don't think Paul intends to be snarky. He
> just has a very sarcastic sense of humor that you'll come to appreciate
> after being on this list a while. It would be pretty dry here without
> it.

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 03 Dec 2010 22:39:39 -0800, Paul Phillips wrote:

> On Sat, Dec 04, 2010 at 04:53:53AM +0000, Jim Balter wrote:
>> > scala> (null: List[Int]) + null
>> > res0: java.lang.String = nullnull
>>
>> You know your way all around this language and I barely know it at all,
>> so it would help if you would explain that result, and how we know that
>> the fake '+' isn't being invoked.
>
> You know it isn't being invoked because the fake '+' is a method on
> String, not List[Int].

The fake `+` isn't a method at all, its a special CONCAT operation in the
compiler. Since I don't know my way around the compiler, I can't know
that it isn't being invoked somehow. After all, null *is* being converted
to a String, despite having type List[Int]. But I have now seen the
implicit def any2stringadd(x: Any) = new runtime.StringAdd(x) that is
apparently doing that conversion, so I now follow your point that it
would act exactly the same as it does now without CONCAT. You wrote that
it's amusing that no one seems to have keyed into that. I'm so glad know
that the ignorance of those posting on scala.user makes you chuckle. It
might be worth noting that most of the implicits defined in PreDef and
elsewhere are undocumented in Scaladoc, so a certain amount of ignorance
seems justified even beyond mere noobiehood.

>
> We have lots more of these you know.
>
> // toInt not actually a method on String scala> "123".toInt
> res0: Int = 123
>
> // -> not actually a method on AnyRef scala> new AnyRef -> 5
> res1: (java.lang.Object, Int) = (java.lang.Object@67d7a04,5)

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

I did file a bug report, Ticket # 4057.

As insignificant as this error may seem to some of you, recall that the
slighest inconsistency in any axiomatics allows you to prove 0=1,
something which would remove any trust in the axiomatic system.

Mathematics (at least number theory is built upon the empty set {}, that
is:
0 := {}
1 := {0} = {{}}
2 := {0,1} = {{},{{}}}

and so on ...

I'd hate to see Scala submit to being inconsistent, I'd switch to Haskell.

H.Peter

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Sat, 04 Dec 2010 10:48:08 +0100, H. Peter Gumm wrote:

> I did file a bug report, Ticket # 4057.
>
> As insignificant as this error may seem to some of you, recall that the
> slighest inconsistency in any axiomatics allows you to prove 0=1,
> something which would remove any trust in the axiomatic system.
>
> Mathematics (at least number theory is built upon the empty set {}, that
> is:
> 0 := {}
> 1 := {0} = {{}}
> 2 := {0,1} = {{},{{}}}
>
> and so on ...

Um, even if you want to view Scala as a formal axiomatic system, it would
be a *different* FAS from number theory. As I tried to point out to you
several times but never with any acknowledgment, Scala has *implicit*
methods -- methods that are applied when the type of a in a.m(args) does
not contain m as a method. Since m is not a method of a, the object to
which m is applied is *not* a, despite what Java programmers may think
that syntax means. Thus, the rule that an NPE must be produced if a is
null *does not* apply to Scala. Consider

val x:String = null
x.+(true)
x.ensuring(true)
x.->(true)

None of those throws an NPE ... kind of consistent, eh?

> I'd hate to see Scala submit to being inconsistent, I'd switch to
> Haskell.

Don't let the door hit ...

>
> H.Peter

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

I believed, we had closed this discussion, after I filed bug report,
"#4057". I am surprised that after leaving your comments bugTrac, you
reopen the discussion in the list. Well then, I repeat my questions and
concerns here. My question has never been, how the compiler does these
things - my question has always been why Scala does these things even
though they are so conterintuitive.

- Is (null:String) a String ?
If yes, why does (null:String).toString throw an NPE ?
If no, what is it, and why is it different from e.g.
null:List[Char] ?

- Why is
((null:String)+(null:String)).length == 8
even though
(null:String).length throws an NPE ?

- Why does
(null:Null) == (null:String)
yield true, even though they are obviously different ?

E.g. (null:String).+(null:Null) == "nullnull"
whereas (null:Null).+(null:String) --> NPE

I have asked repeatedly for a pointer to any document where the many
null values of Scala are specified. I have not received an answer so
far. Instead you keep telling me which mechanisms of the compiler are
responsible for the particular behaviour of Scala's null values, which
in my eyes is counterintuitive. I had so far believed Scala's Null class
was supposed to improve upon the "null reference" in Java.

Greetings,
H.Peter

.
purpose, when they behave counterintuitively?

For instance:

They are supposed to simplify (or to clean up?) or whatever Java
situation Apparently, (null:String) is something else than (null:Null)
or (null:List[Char]). On the other hand,

where the

1. Null is a class, and null: Null. So null is an object (the sole
object) of Null?
(This is the understanding I get from "Programming in Scala", 2nd
ed. §11.3
The spec (§ 6.3) talks of a '... special "null" object....'
without elaborating the
adjective 'special')
Is that true ?

2. Clearly null:String behaves different from null:Null.
Does that mean, that each reference class has an extra object null
? In particular:
Is null:String a String? Is null:List[Char] a List[Char] ?
That would mean that methods are in general partially defined. E.g.
(null:String). length
is not defined, just as most other String methods, except "+" is
defined.
Is that correct?

3. A language is not a formal system. Agreed. But I expect it to have a
formal semantics,
preferably an easy one, and preferably adhering to established
notational conventions.
In the example we are talking about, I have
((null:String) + (null:String)).length = 8,
whereas
(null:String).length
does not exist. Therefore, Strings with + and length in Scala do
not reflect my
( and I dare to say the well established) understanding of a
String datatype.
This makes formal reasoning difficult. In particular I cannot rely
on simple laws such as,
e.g.
(s1 + s2).length = s1.length + s2.length,
or the like.

In summary, as I have mentioned several times, I would appreciate if
someone could
point me to some spec clearly elaborating the semnatics of those null
values.

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: null + null = ??

Null is a subtype of every other subtype of AnyRef, except for those
that are a subtype of NotNull. (NotNull is experimental and disabled
by default, we should ignore it in this discussion.)

String#+ is a method insofar as the language is concerned. But on the
JVM platform, this does not exist on java.lang.String, instead is
treated specially by the compiler, and calls to this method are
converted into calls into scala.runtime._. This explains how it can
have different semantics to, for example String#length.

There are other such methods added by the compiler, for example Any#asInstanceOf

scala> null.asInstanceOf[Int]
res3: Int = 0

Now, should these methods have different semantics with respect to a
null reference? Perhaps not. Are the current semantics the result of
conscious design decisions, performance tradeoffs, or quirks of
evolution? Most likely, all blend of all three.

Scala runs (primarily) on the JVM and inherits some baggage, but it's
relatively well contained, IMO. You can avoid a lot of this by coding
without using null, avoiding method overloading, avoiding Java raw
types.

-jason

On Fri, Dec 10, 2010 at 1:31 PM, H. Peter Gumm
wrote:
> I believed, we had closed this discussion, after I filed bug report,
> "#4057". I am surprised that after leaving your comments bugTrac, you reopen
> the discussion in the list. Well then, I repeat my questions and concerns
> here. My question has never been, how the compiler does these things - my
> question has always been why Scala does these things even though they are so
> conterintuitive.
>
>   - Is  (null:String) a String ?
>     If yes, why does (null:String).toString throw an NPE ?
>     If no, what is it, and why is it different from e.g. null:List[Char] ?
>
>   - Why is
>            ((null:String)+(null:String)).length == 8
>      even though
>             (null:String).length throws an NPE ?
>
>   - Why does
>          (null:Null) == (null:String)
>     yield true, even though they are obviously different ?
>
>     E.g.                      (null:String).+(null:Null) == "nullnull"
>     whereas              (null:Null).+(null:String) --> NPE
>
> I have asked repeatedly for a pointer to any document where the many null
> values of Scala are specified.  I have not received an answer so far.
> Instead you keep telling me which mechanisms of the compiler are responsible
> for the particular behaviour of Scala's null values, which in my eyes is
> counterintuitive. I had so far believed Scala's Null class was supposed to
> improve upon the "null reference" in Java.
>
> Greetings,
> H.Peter
>
>
>
>
>
>
> .
>  purpose, when they behave counterintuitively?
>
> For instance:
>
> They are supposed to simplify (or to clean up?) or whatever Java situation
> Apparently, (null:String) is something else than (null:Null) or
> (null:List[Char]). On the other hand,
>
>
>
> where the
>
> 1. Null is a class, and null: Null. So null is an object (the sole object)
> of Null?
>    (This is the understanding I get from "Programming in Scala", 2nd ed.
> §11.3
>    The spec (§ 6.3) talks of a  '... special "null" object....'  without
> elaborating the
>    adjective 'special')
>    Is that true ?
>
> 2. Clearly null:String behaves different from null:Null.
>    Does that mean, that each reference class has an extra object null ?  In
> particular:
>            Is null:String a String?  Is null:List[Char]  a List[Char] ?
>    That would mean that methods are in general partially defined. E.g.
>             (null:String). length
>     is not defined, just as most other String methods, except "+" is
> defined.
>    Is that correct?
>
> 3. A language is not a formal system. Agreed. But I expect it to have a
> formal semantics,
>    preferably an easy one, and preferably adhering to established notational
> conventions.
>    In the example we are talking about, I have
>        ((null:String) + (null:String)).length = 8,
>    whereas
>       (null:String).length
>    does not exist. Therefore, Strings  with + and length in Scala do not
> reflect my
>    ( and I dare to say the well established) understanding of a String
>  datatype.
>    This makes formal reasoning difficult. In particular I cannot rely on
> simple laws such as,
>    e.g.
>               (s1 + s2).length = s1.length + s2.length,
>    or the like.
>
> In summary, as I have mentioned several times, I would appreciate if someone
> could
> point me to some spec clearly elaborating the semnatics of those null
> values.

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

Thanks, Jason

i think your message is to the point. That

> Null is a subtype of every other subtype of AnyRef,
is clear, the spec says it. But does the question "Is null:T" an
object of T" have a yes /no answer?

> <... snip ...> except for those
> that are a subtype of NotNull. (NotNull is experimental and disabled
> by default, we should ignore it in this discussion.)

I had alreday noticed that the API shows a trait NotNull, but not a
class Null.
In the spec its the other way round, it mentions a class Null with an
object
null, sporting six or seven methods., but this is not reflected in the API.

> Are the current semantics the result of
> conscious design decisions, performance tradeoffs, or quirks of
> evolution? Most likely, all blend of all three.
This is indeed, what I come to believe through the discussion.
> Scala runs (primarily) on the JVM and inherits some baggage, but it's
> relatively well contained, IMO. You can avoid a lot of this by coding
> without using null, avoiding method overloading, avoiding Java raw
> types.
I agree fully with the first sentence. Yet my interest is not that of a
system engineer, but academic. My question is, whether Scala manages to
tame the ugly null reference via an object null:Null or rather lots of
objects nulls:T, one for each reference class T, and whether its an
advantage or a disadvantage. I am still undecided, and since my frequent
plights for a docu have never been answered, I am starting to believe
that in Scala, the whole Null business is more of an experimental thing
than a theoretically sound feature.

Greetings,
H.Peter

Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

So, if I understand you correctly you aren't asking for practical
reasons for this behavior at all, so explanations about semantics as
the compiler implements it or even how they are specified may not be
satisfying answers for you. If you are instead looking for a cognitive
model of how Scala's method dispatching works, I'll try another
explanation.

The model for dispatching method calls in Java's object model is
relatively simple. You have a receiver and you look up the method in
its runtime class and call it with the params. If the receiver is
null, a NPE is thrown. The simplicity of this model certainly has its
merits but you can find several issues with it if you want to:

* You can't easily add methods to a class if you can't change the
class itself for some reason
* Receiver and parameters aren't equal with regard to dispatching:
first the receiver's class is looked up and then the by parameter
types statically chosen overload is called. So there's no built-in
commutativity even when for data-types where it would make sense
* No runtime dispatching aside from the usual virtual calls
* No multiple inheritance

If you acknowledge that these are things that you may want to fix from
Java, you have to get away from Java's simple dispatching model. So,
other languages have much more complicated dispatching mechanisms than
Java, some have multimethods, some have a much more dynamic
dispatching behavior with classes even changing at runtime, and then
there is Scala.

Scala allows to "extend Classes" by using views, i.e. if a method is
not found for a value of a type T, all the implicit definitions in the
scope are searched for a function from T => X, where X has a method
with that name. This is the well-known and widely used
"pimp-my-library" pattern. (You can read this up in the specification
in "§ 7.3 Views") There may be other changes for method dispatching
from Java but this is the only major one. So remember only this one
rule more:

* If a method `m` is not found for a value `v` of a type `T`, all the
implicit definitions in the scope are searched for a function `f` from
`T` => `X`, where `X` has a method with that name `m`. If exactly one
matching implicit is found the expression is translated from v.m into
f(v).m

Add to this, that Scala unifies method calling and usage of operators
and this is exactly what happens in your `null` case. There is no
method `+` on String, so the implicit scope is searched for a
conversion from String to a class which has a `+` method. And there is
one such implicit: Predef.any2stringadd which is then used to actually
concatenate these two strings (Predef is always in scope). So your
example

(null:String)+(null:String) is translated into
Predef.any2stringadd(null:String).+(null: String) which can be
evaluated, in fact.

To answer your questions:

On Fri, Dec 10, 2010 at 1:31 PM, H. Peter Gumm
wrote:
>   - Is  (null:String) a String ?

Emphatically, yes. `null` is a member of any reference type.

>     If yes, why does (null:String).toString throw an NPE ?
Because (as in Java) this is statically chosen to be call to
String#toString which when called with a null receiver throws an NPE.

>     If no, what is it, and why is it different from e.g. null:List[Char] ?
It has another type, statically. Method dispatching is in many
languages an interplay between statically choosing a target and a
runtime component which chooses the concrete implementation as it's
done with virtual method calls.

>   - Why is
>            ((null:String)+(null:String)).length == 8
>      even though
>             (null:String).length throws an NPE ?

Because Scala has views as explained above.

>   - Why does
>          (null:Null) == (null:String)
>     yield true, even though they are obviously different ?

Because == operates on values and both values are the same even if the
static type differs. The strange thing here might be that the type
hierarchy (lattice) can have a bottom type which is the subtype of any
other type. In Scala those types are Null and Nothing. `null` is an
instance of Null, so the "obvious difference" in static types is no
contradiction because of the bottom type.

>     E.g.                      (null:String).+(null:Null) == "nullnull"
Yep, as above.

>     whereas              (null:Null).+(null:String) --> NPE
It doesn't here:

scala> (null: Null).+(null: String)
:6: error: value + is not a member of Null
(null: Null).+(null: String)
^

scala> null + null
:6: error: value + is not a member of Null
null + null

Your objection here would have to be, why the implicit view isn't
applied here but I can't explain that. Maybe there is some special
casing/shortcut about how dispatching is handled with bottom types.

> I have asked repeatedly for a pointer to any document where the many null
> values of Scala are specified.

There's only one value and its semantics are nothing special.

> I had so far believed Scala's Null class was supposed to
> improve upon the "null reference" in Java.

I don't think there's any important improvement to find here. In fact,
internally the Java compiler has a Null type like Scala's but it
bubbles seldom up to the surface.

I hope this answers your question better, all the things have been in
this thread but perhaps not in an easily understandable form.

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: null + null = ??

No views in this case, just some compiler trickery that equates to the
same thing.

Conceptually, however, views behave the same, and qualifiers pointing
at a null reference can happily be passed as an argument to the
implicit conversion, which is not obliged to raise a NPE.

-jason

On Fri, Dec 10, 2010 at 3:39 PM, Johannes Rudolph
wrote:
> (null:String)+(null:String) is translated into
> Predef.any2stringadd(null:String).+(null: String) which can be
> evaluated, in fact.
>
> To answer your questions:
>
> On Fri, Dec 10, 2010 at 1:31 PM, H. Peter Gumm
> wrote:
>>   - Is  (null:String) a String ?
>
> Emphatically, yes. `null` is a member of any reference type.
>
>>     If yes, why does (null:String).toString throw an NPE ?
> Because (as in Java) this is statically chosen to be call to
> String#toString which when called with a null receiver throws an NPE.
>
>>     If no, what is it, and why is it different from e.g. null:List[Char] ?
> It has another type, statically. Method dispatching is in many
> languages an interplay between statically choosing a target and a
> runtime component which chooses the concrete implementation as it's
> done with virtual method calls.
>
>>   - Why is
>>            ((null:String)+(null:String)).length == 8
>>      even though
>>             (null:String).length throws an NPE ?
>
> Because Scala has views as explained above.

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: null + null = ??

Null is not a theoretically sound feature in any guise. Tony Hoare,
its creator, calls it his "billion dollar mistake", during recent
presentations.

There is no object null. In JVM terms, there is no heap allocated
object on the other end of the null reference. This is in contrast to
Ruby, which does have such an object (you can even redefine the
methods on this, see the "Whiny Nil" in Rails for an interesting
application).

null is an expression, that has the type Null, which can be used just
about everywhere thanks to the subtyping relationship between Null and
AnyRef descendents.

Scala tames the problems of nulls by offering a superior alternative,
not in the language but in the library: scala.Option. It doesn't go so
far as to outlaw null, as this would make Java interop really awkward.

-jason

On Fri, Dec 10, 2010 at 3:26 PM, H. Peter Gumm
wrote:
> I agree fully with the first sentence.  Yet my interest is not that of a
> system engineer, but academic. My question is, whether Scala manages to tame
> the ugly null reference via an object null:Null or rather lots of objects
> nulls:T, one for each reference class T, and whether its an advantage or a
> disadvantage. I am still undecided, and since my frequent plights for a docu
> have never been answered, I am starting to believe that in Scala, the whole
> Null business is more of an experimental thing than a theoretically sound
> feature.

Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

On Fri, Dec 10, 2010 at 3:44 PM, Jason Zaugg wrote:
> No views in this case, just some compiler trickery that equates to the
> same thing.
>
> Conceptually, however, views behave the same, and qualifiers pointing
> at a null reference can happily be passed as an argument to the
> implicit conversion, which is not obliged to raise a NPE.

Ah, learned something. Good to know that the practical implementation
is more complicated than what to expect from theory.

So, as a reminder, what is this Predef.any2stringadd method for?

Gumm
Joined: 2010-07-17,
User offline. Last seen 2 years 1 week ago.
Re: Re: null + null = ??

On 10.12.2010 15:39, Johannes Rudolph wrote:
> Scala allows to "extend Classes" by using views, i.e. if a method is
> not found for a value of a type T, all the implicit definitions in the
Sorry, but I now feel obliged to state to everybody to please not
explain implicits to me any more. I have read most of the Scala Papers
from EPFL and I have known implicits for ages.

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Re: null + null = ??
On Fri, Dec 10, 2010 at 7:31 AM, H. Peter Gumm <gumm@mathematik.uni-marburg.de> wrote:
I believed, we had closed this discussion, after I filed bug report, "#4057". I am surprised that after leaving your comments bugTrac, you reopen the discussion in the list. Well then, I repeat my questions and concerns here. My question has never been, how the compiler does these things - my question has always been why Scala does these things even though they are so conterintuitive.

  - Is  (null:String) a String ?
    If yes, why does (null:String).toString throw an NPE ?
    If no, what is it, and why is it different from e.g. null:List[Char] ?

It has the type of a string, but there is no instantiated object there.  It's null.  That's _exactly what it says_.
  (null     // This says NO OBJECT THERE
  :String)  // This says THE TYPE IS String
I don't understand why this isn't blatantly obvious.  Let's try it another way.

  val x: String = null

Surely you agree that x has type String but that there is no instantiated object.

Well, (null: String) is _exactly the same thing_ except without explicitly specifying a name.
 
  - Why is
           ((null:String)+(null:String)).length == 8 
     even though
            (null:String).length throws an NPE ?

Because the + operator _creates a new instance_, of course.  More on this later.
 
  - Why does
         (null:Null) == (null:String)
    yield true, even though they are obviously different ?

They're not different.  The content is the same.  The _types_ are different, but equality in Scala and Java does not check the type explicitly (type signature is "equals(Object o)").  It would be really weird to do this, because of

  class A { val x = 7 }
  class B extends A { val y = 9 }
  val b = new B
  val as = List[A](b)
  as.head == b      // It's the same item!  You want to return false on this?!

 
    E.g.                      (null:String).+(null:Null) == "nullnull"
    whereas              (null:Null).+(null:String) --> NPE

You understand implicits, and this is acting as if there's an implicit involved.  So you should be comfortable with the first.  Implicits get evoked based on the type, not based upon the content of the instance.

The second is weird, because the Null type is _not_ searched for implicits (and AFAICT the Scala Language Spec does not document this behavior).  Nothing should not be searched (because it isn't actually there), but Null _can_ be there and it is not searched.

Anything else (e.g. (null: List[Option[Float]]).+(null: String)) will work, thanks to any2stringadd in Predef performing the implicit conversion (including handling null safely).
 
I have asked repeatedly for a pointer to any document where the many null values of Scala are specified.

Search for the keyword "null" in the Scala Language Specification.  Page 75 is particularly relevant.

1. Null is a class, and null: Null. So null is an object (the sole object) of Null?
   (This is the understanding I get from "Programming in Scala", 2nd ed. §11.3
   The spec (§ 6.3) talks of a  '... special "null" object....'  without elaborating the
   adjective 'special')
   Is that true ?

Yes.  Null is a subtype of every* reference type, so a reference to any instance of a class can contain null according to the type system.
 

2. Clearly null:String behaves different from null:Null.
   Does that mean, that each reference class has an extra object null ?  In particular:
           Is null:String a String?  Is null:List[Char]  a List[Char] ?
   That would mean that methods are in general partially defined. E.g.
            (null:String). length
    is not defined, just as most other String methods, except "+" is defined.
   Is that correct?

Yes and no.  No method defined in the String class will work (instead it will throw a NPE).  But + is not a method defined in the String class; it acts like an implicit conversion.

The Scala spec is not entirely clear on this (p. 144):

"For Scala clients the class is taken
to support in each case a method
def + (that: Any): String
which concatenates its left operand with the textual representation of its right
operand."

This doesn't really address the issue of whether + acts like an implicit conversion or like a method.  If you are complaining that it is "sort of both", that's fair enough, but you really should complain exactly about the problem, not about all the random stuff you're complaining about.

I would argue that the present version is sensible, since the textual representation of null ought to be "null", and it is not the intent of a string concatenation function to have a different domain for its left and right arguments.

However, it is kind of weird because it actually turns into a method on StringBuilder when invoked on a string.  (It uses normal implicits when invoked on any other object.)


3. A language is not a formal system. Agreed. But I expect it to have a formal semantics,
   preferably an easy one, and preferably adhering to established notational conventions.
   In the example we are talking about, I have
       ((null:String) + (null:String)).length = 8,
   whereas
      (null:String).length
   does not exist. Therefore, Strings  with + and length in Scala do not reflect my
   ( and I dare to say the well established) understanding of a String  datatype.
   This makes formal reasoning difficult. In particular I cannot rely on simple laws such as,
   e.g.
              (s1 + s2).length = s1.length + s2.length,
   or the like.

Yes, that's exactly right.  You were hoping that strings could not be null.  But Scala, for Java compatibility if nothing else, allows null as a bottom type.  If you cannot abide the existence of this feature, you ought not use Scala.

  --Rex

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: null + null = ??

On Fri, 10 Dec 2010 16:21:38 +0100, H. Peter Gumm wrote:

> On 10.12.2010 15:39, Johannes Rudolph wrote:
>> Scala allows to "extend Classes" by using views, i.e. if a method is
>> not found for a value of a type T, all the implicit definitions in the
> Sorry, but I now feel obliged to state to everybody to please not
> explain implicits to me any more. I have read most of the Scala Papers
> from EPFL and I have known implicits for ages.

Your questions don't reflect it, and you have never before mentioned
implicits; that's why people are explaining them to you. If you have
known implicits for ages, then why do you continue to ask why an NPE
isn't thrown when an *implicit* method is invoked, since there is no
reason to expect an NPE in that case, since null is not the receiver in
that case? Given the code

implicit def myNameDoesNotMatter(a: Any) = new { def noNPE { println
("bite me, NPE") } }
val x:String = null
x.noNPE

you seem to expect or want an NPE, even though that is not at all what
should or can happen in Scala. You have talked about the compiler acting
according to a set of defined rules, but you don't seem to include
implicits in those rules. You say you taught Java students for years that
x.foo throws an NPE when x is null ... but Java doesn't have implicits,
so what you taught about it is irrelevant to Scala. And then you go on
and on about Scala being inconsistent and so on, *as if* you are quite
ignorant of the defined set of rules it follows that include implicits.
Very odd behavior, that.

The fact is that Scala's (*specified*) treatment of null is quirky
because null is imposed upon it by JVM/Java compatibility. So Null is a
subclass of every reference class, *but* every method of those
superclasses other than an explicitly specified set (==, isInstanceOf,
etc.) is disallowed for Null. That's why null + "" is a compile-time
error but (null:String) + "" or (null:List[Int]) + "" is not. And the
latter does not produce an NPE because null is not the receiver of the
`+` method, an instance of runtime.StringAdd is. So you see, all of the
questions you have asked are readily answered in terms of a set of
defined rules -- including those for implicits -- given in the SLS, with
the exception of (String:null) + "", and the problem in that case is
language in the SLS that says that `+` is "taken to be" a method of
String; removing that language would mean that the rule for implicits
governs (String: null) + "", in which case null would not be the
receiver, an instance of runtime.StringAdd would be, due to the rules for
implicits, and thus no NPE. So while you may have known of implicits for
ages, you seem not to grasp what they imply, and thus the explanation.

Jim Balter
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: null + null = ??

Jason Zaugg wrote:

> Null is not a theoretically sound feature in any guise. Tony Hoare,
> its creator, calls it his "billion dollar mistake", during recent
> presentations.
>
> There is no object null.

That is incorrect; every value in Scala, including null and (), is an object

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