Scala - Pattern Matching with Caution!- Is it a bug?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Scala - Pattern Matching with Caution!- Is it a bug?

Tarun Kumar
Hi,

I am struggling to understand why the two snippets below will behave differently or 'null' is the problem here?. One executes successfully and other throws the runtime scala.MatchError.

Snippet 1: 

 val str = "HELP"

val perfectTuple: (String, String) = str match {
 
  case "NO-HELP" => ("First Help", "Second Help")
  case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
  case "HELP" => (null,"Single Help")
  case _ => throw new NoSuchMethodException
 
  }


==================

Snippet 2:

val str = "HELP"

val (firstPart:String, secondPart:String) = str match {
 
  case "NO-HELP" => ("First Help", "Second Help")
  case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
  case "HELP" => (null,"Single Help")
  case _ => throw new NoSuchMethodException
 
  }

======================

As we can see that there is a little difference between the two snippets , one storing the result in a tuple 2 value and the other is extracting the value out of tuple 2 and storing them in two values. Snippet1 executes successfully but snippet 2 throws the runtime error , below:

Exception in thread "main" scala.MatchError: (null,Single Help) (of class scala.Tuple2)
at com.trn.scala.problems.P05$.delayedEndpoint$com$trn$scala$problems$P05$1(P05.scala:10)
at com.trn.scala.problems.P05$delayedInit$body.apply(P05.scala:6)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at com.trn.scala.problems.P05$.main(P05.scala:6)
at com.trn.scala.problems.P05.main(P05.scala)

I have executed this on scala 2.10.5 as well as 2.11.7 .P05 is my object name above. 

Please advise if i am missing the obvious here?

Thanks
Tarun

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

Oliver Ruebenacker

     Hello,

  Can be boiled down to:

scala> val (x: String, y: String) = (null, "Yo"): (String, String)
scala.MatchError: (null,Yo) (of class scala.Tuple2)
  ... 33 elided

  The notation val (..., ...) = ... is trying to match Tuple2, and null is not a String.

     Best, Oliver

On Mon, Feb 22, 2016 at 11:16 AM, Tarun Kumar <[hidden email]> wrote:
Hi,

I am struggling to understand why the two snippets below will behave differently or 'null' is the problem here?. One executes successfully and other throws the runtime scala.MatchError.

Snippet 1: 

 val str = "HELP"

val perfectTuple: (String, String) = str match {
 
  case "NO-HELP" => ("First Help", "Second Help")
  case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
  case "HELP" => (null,"Single Help")
  case _ => throw new NoSuchMethodException
 
  }


==================

Snippet 2:

val str = "HELP"

val (firstPart:String, secondPart:String) = str match {
 
  case "NO-HELP" => ("First Help", "Second Help")
  case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
  case "HELP" => (null,"Single Help")
  case _ => throw new NoSuchMethodException
 
  }

======================

As we can see that there is a little difference between the two snippets , one storing the result in a tuple 2 value and the other is extracting the value out of tuple 2 and storing them in two values. Snippet1 executes successfully but snippet 2 throws the runtime error , below:

Exception in thread "main" scala.MatchError: (null,Single Help) (of class scala.Tuple2)
at com.trn.scala.problems.P05$.delayedEndpoint$com$trn$scala$problems$P05$1(P05.scala:10)
at com.trn.scala.problems.P05$delayedInit$body.apply(P05.scala:6)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at com.trn.scala.problems.P05$.main(P05.scala:6)
at com.trn.scala.problems.P05.main(P05.scala)

I have executed this on scala 2.10.5 as well as 2.11.7 .P05 is my object name above. 

Please advise if i am missing the obvious here?

Thanks
Tarun

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.



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

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

Seth Tisue
at it's heart, the issue is that

scala> null.isInstanceOf[String]
res0: Boolean = false

yet this is neither a compile-time nor a run-time error:

scala> val x: String = null
x: String = null

so null both is and isn't a String, depending on how you pose the question. this is standard on the JVM; Java behaves the same way.

in Scala, we try to avoid ever using null at all, unless we're interoperating with legacy Java code. so in normal, idiomatic Scala code, the issue never arises.

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

Tarun Kumar
Thanks Oliver, Seth

so this would lead me to compliment my earlier question with the following :

if i need to return Multiple values (ie. Tuple N) from pattern matching and that too may be containing java objects (which can return null), Would it be advisable to receive them in the Tuple N definition ( like in perfectTuple Example above) and then use the values like :

perfectTuple._1, perfectTuple._2 and so on ...

instead of assigning them into different variables like in the snippet posted which is failing?

because referring to your example, i can use like the below to extract the value

val x: (String, String) = (null, "Yo"): (String, String)

x._1
x._2

...

So the assumption of using 'val x: (String, String)' always will hold true, as it will always protect from null's?

then where the other kind of 'val (x: String, y: String)' would be useful ?

Thanks
Tarun

On 22 February 2016 at 18:09, Seth Tisue <[hidden email]> wrote:
at it's heart, the issue is that

scala> null.isInstanceOf[String]
res0: Boolean = false

yet this is neither a compile-time nor a run-time error:

scala> val x: String = null
x: String = null

so null both is and isn't a String, depending on how you pose the question. this is standard on the JVM; Java behaves the same way.

in Scala, we try to avoid ever using null at all, unless we're interoperating with legacy Java code. so in normal, idiomatic Scala code, the issue never arises.

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

Adriaan Moors-5
The null check stems from the type test in the pattern on the RHS of your assignment. In patterns, (p: String) implies p's type is String, as well as that p is not null.

It's possible to return null in a tuple and immediately match on it to get them out -- here are some variations on this theme:


scala> val (null1, null2) = (null: String, null: Any)
null1: String = null
null2: Any = null


scala> val (1::rest, null2) = (List(1,2,3), null: Any)
rest: List[Int] = List(2, 3)
null2: Any = null

For extra credit/fun:
scala> val (foo@(_: String | null), bar) = (null: String, null: Any)
foo: String = null
bar: Any = null



More generally, a `val (x1@p1, ... xN@pN) = e` desugars to something like

val res = e match { case (x1@p1, ... xN@pN) =>  (x1,... xN) } 
val x1 = res._1

val xN = res._N

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

som-snytt

So it really is true that the pattern matcher guy has more fun.

On Monday, February 22, 2016 at 10:37:15 AM UTC-8, Adriaan Moors wrote:
The null check stems from the type test in the pattern on the RHS of your assignment. In patterns, (p: String) implies p's type is String, as well as that p is not null.

It's possible to return null in a tuple and immediately match on it to get them out -- here are some variations on this theme:


scala> val (null1, null2) = (null: String, null: Any)
null1: String = null
null2: Any = null


scala> val (1::rest, null2) = (List(1,2,3), null: Any)
rest: List[Int] = List(2, 3)
null2: Any = null

For extra credit/fun:
scala> val (foo@(_: String | null), bar) = (null: String, null: Any)
foo: String = null
bar: Any = null



More generally, a `val (x1@p1, ... xN@pN) = e` desugars to something like

val res = e match { case (x1@p1, ... xN@pN) =>  (x1,... xN) } 
val x1 = res._1

val xN = res._N

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

Alan Burlison
In reply to this post by Adriaan Moors-5
On 22/02/2016 18:36, Adriaan Moors wrote:

> The null check stems from the type test in the pattern on the RHS of your
> assignment. In patterns, (p: String) implies p's type is String, as well as
> that p is not null.

Isn't a better option to wrap the possibly null string in an Option, and
match on that?

scala> def giveMeNull(hitMe: Boolean) = if (hitMe) null else "hello"
giveMeNull: (hitMe: Boolean)String

scala> Option(giveMeNull(false)) match { case None => "was null"; case
Some(s) => s }
res3: String = hello

scala> Option(giveMeNull(true)) match { case None => "was null"; case
Some(s) => s }
res4: String = was null

That's my default way of dealing with possibly-null-returning Java APIs,
because Option helpfully maps Option(null) onto None.

scala> Option(null)
res5: Option[Null] = None

--
Alan Burlison
--

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Scala - Pattern Matching with Caution!- Is it a bug?

som-snytt

There was just a StackOverflow question that turned on what null.asInstanceOf[A] means when A is inferred Nothing. (That was in a default arg expression.)

The answer had some difficulty reasoning about that expr, but less difficulty if the expr were Option[A] instead of A. (Because None vs Nothing)

On Wednesday, February 24, 2016 at 5:32:23 AM UTC-8, Alan Burlison wrote:
On 22/02/2016 18:36, Adriaan Moors wrote:

> The null check stems from the type test in the pattern on the RHS of your
> assignment. In patterns, (p: String) implies p's type is String, as well as
> that p is not null.

Isn't a better option to wrap the possibly null string in an Option, and
match on that?

scala> def giveMeNull(hitMe: Boolean) = if (hitMe) null else "hello"
giveMeNull: (hitMe: Boolean)String

scala> Option(giveMeNull(false)) match { case None => "was null"; case
Some(s) => s }
res3: String = hello

scala> Option(giveMeNull(true)) match { case None => "was null"; case
Some(s) => s }
res4: String = was null

That's my default way of dealing with possibly-null-returning Java APIs,
because Option helpfully maps Option(null) onto None.

scala> Option(null)
res5: Option[Null] = None

--
Alan Burlison
--

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.