I'm trying to use a partial function for some validations, lets take an example of a string:
def isLengthValid: PartialFunction[String, Option[String]] ={
case s:String if s.length > 5 => Some("Invalid")
}
def isStringValid: PartialFunction[String, Option[String]] ={
case s: String if s == "valid" => Some("Valid")
}
isLengthValid("valid") orElse isStringValid("valid")
expected output => Some("Valid")
But I'm getting a match Error:
scala.MatchError: valid (of class java.lang.String)
Could anyone help that what is going wrong here, because as per my understanding .isDefinedAt is called internally and is should not give matchError.
P.S ignore the inputs, this is just an example.
Your understanding is wrong. The ScalaDocs page clearly states, "It is the responsibility of the caller to call isDefinedAt before calling apply ...".
Your code isn't calling isDefinedAt, which is causing the exception, so you have to explicitly call it or you can employ other methods that hide the isDefinedAt internally.
Seq("valid") collect (isLengthValid orElse isStringValid)
//res0: Seq[Option[String]] = List(Some(Valid))
Seq("vlad") collect (isLengthValid orElse isStringValid)
//res1: Seq[Option[String]] = List()
This works as intended if you write the last line as
(isLengthValid orElse isStringValid)("valid")
I suspect the problem is that your version desugars to
(isLengthValid.apply("valid")).orElse(isStringValid.apply("valid"))
This means the apply is calculated before the orElse takes place, which means the partial function is treated as a total function and a match error is thrown as Valy Dia's answer explains. The orElse is actually being called on the result output, not the partial function.
The error message comes from the first expression - isLengthValid.
It is define only for string with a length stricly greater than 5. Hence when it is applied to a the string "valid" of length 5, it throws a MatchError:
scala>"valid".length
res5: Int = 5
isLengthValid("valid")
scala.MatchError: valid (of class java.lang.String)
If the method isLengthValid defined this way instead (Note the greater than equal sign), it wouldn't throw the MatchError :
def isLengthValid: PartialFunction[String, Option[String]] ={
case s:String if s.length >= 5 => Some("Invalid")
}
scala>isLengthValid("valid")
res8: Option[String] = Some("Invalid")
And the original expression would return an Option:
scala>isLengthValid("valid") orElse isStringValid("valid")
res9: Option[String] = Some("Invalid")
What you could do here as well as explained in this question, is to use this definition instead:
val isLengthValid = new PartialFunction[String, Option[String]] {
def isDefinedAt(x: String) = x.length > 5
def apply(x: String) = Some("Invalid")
}
scala>isLengthValid("valid")
res13: Some[String] = Some("Invalid")
Related
What happens in line nine below that makes the result variable accessible on line ten?
The example is from the Akka documentation on testing. The Ask in line eight returns a scala.concurrent.Future. The Future.value() returns an Option[Try[T]], which will either be Some(Success(t)) or Some(Failure(error)). Then Some.get is called, which should either return the t or the error, depending the result of the Try.
It seems like whether or not the value of future.value.get is an error in line nine, it is attempting to instantiate a new Success, which is defined as a case class in Try, with the return value from Some.get. The Success on line nine is not used directly, but instead the case class constructor parameter result somehow makes it into scope so it can be used in line ten. What is this called in Scala? Where can I find out more about how this syntax works?
1. import akka.testkit.TestActorRef
2. import scala.concurrent.duration._
3. import scala.concurrent.Await
4. import akka.pattern.ask
5.
6. val actorRef = TestActorRef(newMyActor)
7. // hypothetical message stimulating a '42' answer
8. val future = actorRef ? Say42
9. val Success( result: Int ) = future.value.get
10. result should be (42)
val Success( result: Int ) = future.value.get is a pattern match. You can use pattern-matching to assign values to identifiers when declaring a val. It's about the same as writing:
val result: Int = future.value.get match {
case Success(r: Int) => r
}
Notice how this is not an exhaustive match, though, and if future.value.get is a Failure, then a MatchError will be thrown. In the context of unit tests, I use pattern matching like this all the time, since a MatchError would be another indication of failure.
Here are a few examples of similar (safer) pattern-matching assignments:
val (a, b) = (1, 2)
case class Test(i: Int, j: String)
val test = Test(1, "a")
val (i, j) = test
val list = List(1, 2, 3, 4)
val List(first, second, _*) = list // though this will fail if the List has less than 3 elements
That's just pattern matching. For instance:
scala> val Some(a) = Some(5)
a: Int = 5
scala> val Some(a) = None: Option[Int]
scala.MatchError: None (of class scala.None$)
... 33 elided
is equivalent to:
scala> val a = Some(5) match {case Some(a) => a}
a: Int = 5
scala> val a = (None: Option[Int]) match {case Some(a) => a}
scala.MatchError: None (of class scala.None$)
... 33 elided
in both cases Some.unapply method (which is part of companion-object, generated automatically for case class) is called.
In general, for an expression like val Extractor(a, Extractor(b, c)) = input scala-compiler internally generates (you may check it with macros) special synthetic expressions:
val tuple = input match { //synthetic value here
Extractor(a, Extractor(b, c)) => (a,b,c)
}
val a = tuple._1
val b = tuple._2
val c = tuple._3
This is called Pattern Matching.
This question already has answers here:
Map versus FlatMap on String
(5 answers)
Closed 5 years ago.
Can anyone teach me property use cases of map and flatMap?
In Option case, I know these two methods have each signature, def map(A => B): Option[B] and def flatMap(A => Option[B]): Option[B].
So, I can get some value by two ways:
scala> val a = Some(1).map(_ + 2)
a: Option[Int] = Some(3)
scala> val a2 = Some(1).flatMap(n => Some(n + 2))
a2: Option[Int] = Some(3)
When I write a method: def plusTwo(n: Int), is there any difference between
def plusTwo(n: Int): Int = n + 2
Some(1).map(plusTwo)
and
def plusTwo(n: Int): Option[Int] = Some(n + 2)
Some(1).flatMap(plusTwo)
flatMap can convert to for-comprehension, and is it better that almost all methods return value Option wrapped?
Let's say you have a List:
val names = List("Benny", "Danna", "Tal")
names: List[String] = List(Benny, Danna, Tal)
Now let's go with your example. Say we have a function that returns an Option:
def f(name: String) = if (name contains "nn") Some(name) else None
The map function works by applying a function to each element in the list:
names.map(name => f(name))
List[Option[String]] = List(Some(Benny), Some(Danna), None)
In the other hand, flatMap applies a function that returns a sequence for each element in the list, and flattens the results into the original list
names.flatMap(name => f(name))
List[String] = List(Benny, Danna)
As you can see, the flatMap removed the Some/None layer and kept only the original list.
Your function plusTwo returns valid results for all input since you can add 2 to any Int.
There is no need to define that it returns Option[Int] because None value is never returned. That's why for such functions you use Option.map
But not all functions have meaningful result for every input. For example if your function divide some number by function parameter then it makes no sense to pass zero to that function.
Let's say we have a function:
def divideTenBy(a: Int): Double
When you invoke it with zero then ArithmeticException is thrown. Then you have to remember to catch this exception so it's better to make our function less error prone.
def divideTenBy(a: Int): Option[Double] = if (a == 0) None else Some(10 / a)
With such functions you can use flatMap since you can have 'None' value in optional (left operand) or given function can return None.
Now you can safely map this function on any value:
scala> None.flatMap(divideTenBy)
res9: Option[Double] = None
scala> Some(2).flatMap(divideTenBy)
res10: Option[Double] = Some(5.0)
scala> Some(0).flatMap(divideTenBy)
res11: Option[Double] = None
What happens in line nine below that makes the result variable accessible on line ten?
The example is from the Akka documentation on testing. The Ask in line eight returns a scala.concurrent.Future. The Future.value() returns an Option[Try[T]], which will either be Some(Success(t)) or Some(Failure(error)). Then Some.get is called, which should either return the t or the error, depending the result of the Try.
It seems like whether or not the value of future.value.get is an error in line nine, it is attempting to instantiate a new Success, which is defined as a case class in Try, with the return value from Some.get. The Success on line nine is not used directly, but instead the case class constructor parameter result somehow makes it into scope so it can be used in line ten. What is this called in Scala? Where can I find out more about how this syntax works?
1. import akka.testkit.TestActorRef
2. import scala.concurrent.duration._
3. import scala.concurrent.Await
4. import akka.pattern.ask
5.
6. val actorRef = TestActorRef(newMyActor)
7. // hypothetical message stimulating a '42' answer
8. val future = actorRef ? Say42
9. val Success( result: Int ) = future.value.get
10. result should be (42)
val Success( result: Int ) = future.value.get is a pattern match. You can use pattern-matching to assign values to identifiers when declaring a val. It's about the same as writing:
val result: Int = future.value.get match {
case Success(r: Int) => r
}
Notice how this is not an exhaustive match, though, and if future.value.get is a Failure, then a MatchError will be thrown. In the context of unit tests, I use pattern matching like this all the time, since a MatchError would be another indication of failure.
Here are a few examples of similar (safer) pattern-matching assignments:
val (a, b) = (1, 2)
case class Test(i: Int, j: String)
val test = Test(1, "a")
val (i, j) = test
val list = List(1, 2, 3, 4)
val List(first, second, _*) = list // though this will fail if the List has less than 3 elements
That's just pattern matching. For instance:
scala> val Some(a) = Some(5)
a: Int = 5
scala> val Some(a) = None: Option[Int]
scala.MatchError: None (of class scala.None$)
... 33 elided
is equivalent to:
scala> val a = Some(5) match {case Some(a) => a}
a: Int = 5
scala> val a = (None: Option[Int]) match {case Some(a) => a}
scala.MatchError: None (of class scala.None$)
... 33 elided
in both cases Some.unapply method (which is part of companion-object, generated automatically for case class) is called.
In general, for an expression like val Extractor(a, Extractor(b, c)) = input scala-compiler internally generates (you may check it with macros) special synthetic expressions:
val tuple = input match { //synthetic value here
Extractor(a, Extractor(b, c)) => (a,b,c)
}
val a = tuple._1
val b = tuple._2
val c = tuple._3
This is called Pattern Matching.
Can someone explain how and when to use the triple caret ^^^ (vs the double caret ^^) when designing scala parser combinators? And also when / how to use the parser.into() method (>>).
I'll begin with an example using Scala's Option type, which is similar in some important ways to Parser, but can be easier to reason about. Suppose we have the following two values:
val fullBox: Option[String] = Some("13")
val emptyBox: Option[String] = None
Option is monadic, which means (in part) that we can map a function over its contents:
scala> fullBox.map(_.length)
res0: Option[Int] = Some(2)
scala> emptyBox.map(_.length)
res1: Option[Int] = None
It's not uncommon to care only about whether the Option is full or not, in which case we can use map with a function that ignores its argument:
scala> fullBox.map(_ => "Has a value!")
res2: Option[String] = Some(Has a value!)
scala> emptyBox.map(_ => "Has a value!")
res3: Option[String] = None
The fact that Option is monadic also means that we can apply to an Option[A] a function that takes an A and returns an Option[B] and get an Option[B]. For this example I'll use a function that attempts to parse a string into an integer:
def parseIntString(s: String): Option[Int] = try Some(s.toInt) catch {
case _: Throwable => None
}
Now we can write the following:
scala> fullBox.flatMap(parseIntString)
res4: Option[Int] = Some(13)
scala> emptyBox.flatMap(parseIntString)
res5: Option[Int] = None
scala> Some("not an integer").flatMap(parseIntString)
res6: Option[Int] = None
This is all relevant to your question because Parser is also monadic, and it has map and flatMap methods that work in very similar ways to the ones on Option. It also has a bunch of confusing operators (which I've ranted about before), including the ones you mention, and these operators are just aliases for map and flatMap:
(parser ^^ transformation) == parser.map(transformation)
(parser ^^^ replacement) == parser.map(_ => replacement)
(parser >> nextStep) == parser.flatMap(nextStep)
So for example you could write the following:
object MyParser extends RegexParsers {
def parseIntString(s: String) = try success(s.toInt) catch {
case t: Throwable => err(t.getMessage)
}
val digits: Parser[String] = """\d+""".r
val numberOfDigits: Parser[Int] = digits ^^ (_.length)
val ifDigitsMessage: Parser[String] = digits ^^^ "Has a value!"
val integer: Parser[Int] = digits >> parseIntString
}
Where each parser behaves in a way that's equivalent to one of the Option examples above.
I don't think this code should work, but it does (in Scala 2.10):
scala> ((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| }): PartialFunction[Int,String]
res0: PartialFunction[Int,String] = <function1>
// other interactions omitted
scala> res0.orElse(PartialFunction((i: Int) => i.toString))
res5: PartialFunction[Int,String] = <function1>
scala> res5(1)
res6: String = 1
How does it work? I would expect a MatchError to be thrown inside res0.
The Scala language specification does not seem to explicitly document how res0 should be interpreted.
The trick is that the compiler is not interpreting your definition as a total function converted to a partial function -- it's actually creating a partial function in the first place. You can verify by noting that res0.isDefinedAt(1) == false.
If you actually convert a total function to a partial function, you will get the behavior you expected:
scala> PartialFunction((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| })
res0: PartialFunction[Int,String] = <function1>
scala> res0 orElse ({ case i => i.toString }: PartialFunction[Int, String])
res1: PartialFunction[Int,String] = <function1>
scala> res1(1)
scala.MatchError: 1 (of class java.lang.String)
// ...
In this example, PartialFunction.apply treats its argument as a total function, so any information about where it's defined is lost.
orElse is defined on PartialFunction so that the argument is treated as a fallback for the cases when the original is not defined. See the API.
You say that if res0 does not match, you want to try your other pf instead. How this essentially works is:
if (res0.isDefinedAt(1)) {
res0(1)
} else {
other(1)
}
The orElse call creates an instance of OrElse, which inherits from PartialFunction: https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L159
When you now call apply on this OrElse, it will call f1.applyOrElse(x, f2): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L162
This will call if (isDefinedAt(x)) apply(x) else f2(x): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L117-L118
Therefore you will only get a MatchError, when neither of the pf's matches.