Null type parameter error by implicit conversion

85 views
Skip to first unread message

Guanjun Wang

unread,
Jul 25, 2014, 5:34:55 AM7/25/14
to scala...@googlegroups.com
Hey,
 
I have tried an implementation for coalesce, i.e. for expression x ?: y , if x is null, return y. but when I tried x ?: null, the compiler gives error. It seems Null type cannot be supported by implicit conversion. But I have no idea why this is the case. Can anybody explain? Thanks.
 
scala>   implicit def elvisOperator[T >: Null <: Any](alt: T) = new {
     |
     |     def ?:[A >: T](pred: A) = if (pred == null) alt else pred
     |
     |   }
elvisOperator: [T >: Null](alt: T)java.lang.Object{def ?:[A >: T](pred: A): A}
scala> null ?: 1
res0: Any = 1
scala> 1 ?: null
<console>:9: error: value ?: is not a member of Null
              1 ?: null
                ^
 

Sonnenschein

unread,
Jul 25, 2014, 7:50:36 AM7/25/14
to scala...@googlegroups.com
That is not related to implicits. You get the same error when writing

null + 1

I believe it's more a precaution by the compiler. Btw., you sure mean eq as opposite to ==, right?

Guanjun Wang

unread,
Jul 25, 2014, 8:49:05 AM7/25/14
to Sonnenschein, scala...@googlegroups.com
I see... Thanks!
So, is there a way to make null + 1 or 1 ?: null succeed in compilation?

--
You received this message because you are subscribed to a topic in the Google Groups "scala-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-user/oRg7bvu-5i8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oliver Ruebenacker

unread,
Jul 25, 2014, 10:43:19 AM7/25/14
to Guanjun Wang, Sonnenschein, scala...@googlegroups.com

     Hello,

  It is related to implicits.

  null + 1 and 1 ?: null fail because null does not have such methods.

  But that's what we have implicit conversions for, so that we can convert a type that does have not have an operation into one that has.

  One problem is that A >: T does not match the type of 1 if T is Null, because 1 is an AnyVal, not an AnyRef, and AnyVal is not s super type of Null.

  Another problem seems to be that the compiler refuses to implicitly convert null to anything, not even if we provide a conversion from Null itself. Not sure whether that should be considered a bug or a feature.

  This works:

scala> implicit def elvisOperator(alt: AnyRef) = new { def ?:(pred: Any) = if (pred == null) alt else pred }
elvisOperator: (alt: AnyRef)AnyRef{def ?:(pred: Any): Any}

scala> 1 ?: (null:AnyRef)
res14: Any = 1

  I'm not sure how useful that is, though. Why don't you just use a method that takes two parameters?

     Best,
     Oliver


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

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



--
Oliver Ruebenacker
Be always grateful, but never satisfied.

Guanjun Wang

unread,
Jul 25, 2014, 11:10:14 AM7/25/14
to Oliver Ruebenacker, Sonnenschein, scala...@googlegroups.com
Thanks a lot !!! @Oliver

I do agree with you about the guess that compiler refuses to implicitly convert null. But we need someone to confirm it.

For A>:T type mismatch for 1, my understanding is that scala will infer A is top type Any, when null is AnyRef and 1 is AnyVal... Thoughts?

Thx!

Som Snytt

unread,
Jul 25, 2014, 12:43:56 PM7/25/14
to Guanjun Wang, Oliver Ruebenacker, Sonnenschein, scala...@googlegroups.com
Kind of guessing, but maybe the behavior is due to:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#the-null-value

> A reference to any other member of the "null" object causes a NullPointerException to be thrown.




Oliver Ruebenacker

unread,
Jul 25, 2014, 3:27:28 PM7/25/14
to Som Snytt, Guanjun Wang, Sonnenschein, scala...@googlegroups.com

     Hello,

On Fri, Jul 25, 2014 at 12:43 PM, Som Snytt <som....@gmail.com> wrote:
Kind of guessing, but maybe the behavior is due to:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#the-null-value

> A reference to any other member of the "null" object causes a NullPointerException to be thrown.

  But this is about runtime behaviour of the value null. The question is whether the type Null can be used in implicit conversions.

scala> import scala.language.implicitConversions
import scala.language.implicitConversions

scala> implicit def null2zero(n : Null) : Int = 0
null2zero: (n: Null)Int

scala> null2zero(null) + 1
res1: Int = 1

scala> null + 1
<console>:12: error: value + is not a member of Null
              null + 1
                   ^

  The part about null.isInstanceOf[T] always returning false made me curious what happens if T is Null:

scala> null.isInstanceOf[Null]
<console>:8: error: type Null cannot be used in a type pattern or isInstanceOf test
              null.isInstanceOf[Null]
                               ^

  On other occasions, Null behaves like a regular type:

scala> val nulls = List(null, null, null)
nulls: List[Null] = List(null, null, null)

Som Snytt

unread,
Jul 25, 2014, 6:06:15 PM7/25/14
to Oliver Ruebenacker, Guanjun Wang, Sonnenschein, scala...@googlegroups.com
FWIW, there's "isAdaptableWithView" that excludes bottom dwellers like null.

To clarify my assumption, if null.foo is supposed to throw an exception, then I don't expect an enchanter to suddenly make it not throw.

(I'm reading Don Quixote, so I see all effects in terms of enchanters.)

The same thing for Nothing.  If I define an implicit Nothing => String, then should ???.length work?  The implicit takes a by-name param, of course.

Reply all
Reply to author
Forward
0 new messages