If I have a match expression, how can I make it automatically ignore a non-match without explicitly doing case _ =>? Is there a way to create a function that does something like this maybe?
You need a generic way to handle "ignoring". Options, among other classes, provide this (among other things). So you can:
val i = 7
Some(i) collect {
case 3 => "Yay!"
case 5 => "Boo!"
}
to get None (typed as an Option[String]). So basically, if you change x match to Some(x) collect you get the functionality you want. It is better to do this when one is comfortable with handling options.
Write a generic matcher:
object Match {
def default: PartialFunction[Any, Unit] = { case _ => }
def apply[T](x: T)(body: PartialFunction[T, Unit]) = (body orElse default)(x)
}
Example:
scala> 1 to 5 foreach (Match(_) {
| case 2 => println("two")
| case 3 => println("three")
| }
| )
two
three
You might be interested too in PartialFunction's companion object's methods cond and condOpt.
Any match block that can't handle all possible input values forms a Partial Function, which is absolutely possible to define and use in Scala.
PartialFunction is a subclass of Function, and adds the isDefinedAt method, which returns true if it has a defined match for the supplied value. Partial Functions are best used in places that test for definition, such as catch blocks or the collect method in the 2.8 collections API. Otherwise, you'll get an exception if you try to call it with a value that isn't defined as an input.
Related
I have this two functions
def pattern(s: String): Option[Pattern] =
try {
Some(Pattern.compile(s))
} catch {
case e: PatternSyntaxException => None
}
and
def mkMatcher(pat: String): Option[String => Boolean] =
pattern(pat) map (p => (s: String) => p.matcher(s).matches)
Map is the higher-order function that applies a given function to each element of a list.
Now I am not getting that how map is working here as per above statement.
Map is the higher-order function that applies a given function to each element of a list.
This is an uncommonly restrictive definition of map.
At any rate, it works because it was defined by someone who did not hold to that.
For example, that someone wrote something akin to
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case Some(value) => Some(f(value))
case None => None
}
}
as part of the standard library. This makes map applicable to Option[A]
It was defined because it makes sense to map many kinds of data structures not just lists.
Mapping is a transformation applied to the elements held by the data structure.
It applies a function to each element.
Option[A] can be thought of as a trivial sequence. It either has zero or one elements. To map it means to apply the function on its element if it has one.
Now it may not make much sense to use this facility all of the time, but there are cases where it is useful.
For example, it is one of a few distinct methods that, when present enable enable For Expressions to operate on a type. Option[A] can be used in for expressions which can be convenient.
For example
val option: Option[Int] = Some(2)
val squared: Option[Int] = for {
n <- option
if n % 2 == 0
} yield n * n
Interestingly, this implies that filter is also defined on Option[A].
If you just have a simple value it may well be clearer to use a less general construct.
Map is working the same way that it does with other collections types like List and Vector. It applies your function to the contents of the collection, potentially changing the type but keeping the collection type the same.
In many cases you can treat an Option just like a collection with either 0 or 1 elements. You can do a lot of the same operations on Option that you can on other collections.
You can modify the value
var opt = Option(1)
opt.map(_ + 3)
opt.map(_ * math.Pi)
opt.filter(_ == 1)
opt.collect({case i if i > 0 => i.toString })
opt.foreach(println)
and you can test the value
opt.contains(3)
opt.forall(_ > 0)
opt.exists(_ > 0)
opt.isEmpty
Using these methods you rarely need to use a match statement to unpick an Option.
I wrote the following use case in scala:
val wordShortcut = Map("volume" -> "vol", "report" -> "rpt", ...)
object WordShortcutCase {
def unapply(key: String): Option[String] = wordShortcut.get(key)
}
val pluralR = "(.+)s".r
def encodeToken(token: String) = token match {
case WordShortcutCase(short) => short
case pluralR(singular) => singular
case _ => token
}
if scala Map would implement unapply, I wouldn't need the extra WordShortcutCase object (i could use case wordShortcut(short) => short instead`). This seems a common pattern to me.
And so the question is why scala Map does not implement the unapply method?
Map doesn't implement unapply because there is no sensible implementation that has the same characteristics as other collections.
In particular, you seem to want apply and unapply to do basically the same thing. But that's not how other collections work; they bind variables to contents and expect that the list is exhaustive (in the absence of a binding to "the rest"):
val xs = List("fish")
val ys = List("fish", "dish")
def iam(zs: List[String]) = zs match {
case List(x) => println(s"I am a $x")
case _ => println("Who am I??")
}
iam(xs) // Prints 'I am a fish'
iam(ys) // Prints 'Who am I??'
If Map were not a collection it would be free to implement unapply as another way to do an apply, more like regex does (though there, note that the key feature is being able to bind multiple variables to parts of the regex match). But since it is, having a regex-like unapply would be highly confusing because of the difference from other collections; and because maps are unordered and unapplySeq is ordered, having the same unapply as other collections would also be confusing. So it just doesn't have one.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Scala: short form of pattern matching that returns Boolean
In my scala code I'm finding myself often writing things like the following:
x match{
case Type(params) => doStuffWith(params)
case _ => /* do nothing*/
}
Is there already some predefined operator to do this? I think it would be much clearer if I could write things like:
if( x match Type(params)) {
doStuffWith(params)
}
essentially avoiding the weird otherwise case. I've also had other situations where being able to verify if something matches a pattern in an inline fashion would save me an extra pair of braces.
I know this sort of thing might only be more useful when writing more iterative code, but Scala seems to have so many hidden features I was wondering whether someone has a simple solution for this.
You could lifta partial function from Any to A into a function from Any to Option[A].
To make the syntax nice first define an helper function:
def lifted[A]( pf: PartialFunction[Any,A] ) = pf.lift
Then, make profit:
val f = lifted {
case Type(i) => doStuff(i)
}
scala> f(2)
res15: Option[Int] = None
scala> f(Type(4))
res16: Option[Int] = Some(8)
The doStuff method will be called only if the argument matches. And you can have several case clauses.
The shortest way I can think of is to wrap the value in an option and use the collect method:
Option(x).collect { case Type(params) => doStuffWith(params) }
Using the link that #phant0m gave, to spell it out:
import PartialFunction.condOpt
condOpt(x){ case Type(params) => doStuffWith(params) }
If this pattern appears often in your code, you should consider turning doSomeStuff into a method of Type. Case classes in Scala are normal classes, and you should use the object-oriented features when they make sense.
Otherwise, you could add a method at the top of your hierarchy, assuming all your case classes extend a common trait. For example:
class Base {
def whenType(f: (T1, T2) => Unit): Unit = this match {
case Type(t1, t2) => f(t1, t2)
case _ => ()
}
}
and then you can use x whenType doSomeStuff
Let's say I want to handle multiple return values from a remote service using the same code. I don't know how to express this in Scala:
code match {
case "1" => // Whatever
case "2" => // Same whatever
case "3" => // Ah, something different
}
I know I can use Extract Method and call that, but there's still repetition in the call. If I were using Ruby, I'd write it like this:
case code
when "1", "2"
# Whatever
when "3"
# Ah, something different
end
Note that I simplified the example, thus I don't want to pattern match on regular expressions or some such. The match values are actually complex values.
You can do:
code match {
case "1" | "2" => // whatever
case "3" =>
}
Note that you cannot bind parts of the pattern to names - you can't do this currently:
code match {
case Left(x) | Right(x) =>
case null =>
}
The other answer correctly says that currently there is no way to pattern-match multiple alternatives while extracting values at the same time.
I'd like to share a coding pattern with you that comes close to doing this.
Scala allows you to pattern-match alternatives without extracting values, e.g. case Dog(_, _) | Cat(_, _) => ... is legal. Using this, you can simply extract the values yourself within the case block.
Here's a somewhat contrived example:
abstract class Animal
case class Dog(age: Int, barkLevel: Int) extends Animal
case class Cat(apparentAge: Int, cutenessLevel: Int) extends Animal
val pet: Animal = Dog(42, 100)
// Assume foo needs to treat the age of dogs and the apparent age
// of cats the same way.
// Same holds for bark and cuteness level.
def foo(pet: Animal): Unit = pet match {
case animal#(Dog(_, _) | Cat(_, _)) =>
// #unchecked suppresses the Scala warning about possibly
// non-exhaustiveness even though this match is exhaustive
val (agelike, level) = (animal: #unchecked) match {
case Dog(age, barkLevel) => (age, barkLevel)
case Cat(apparentAge, cutenessLevel) => (apparentAge, cutenessLevel)
}
???
}
Assume that ??? actually stands for doing something that is equal for dogs and cats. Without this coding pattern, you would need to have two cases, one for dogs and one for cats, forcing you to duplicate code or at least to outsorce code into a function.
Generally, the coding pattern above is suitable if you have sibling case classes that share fields that behave identically only for some algorithms. In those cases, you cannot extract those fields to a common superclass. Still, you would like to pattern-match in a uniform way on those fields in the algorithms that treat them equally. This you can do as shown above.
PartialFunctions
In Scala, a PartialFunction is, in short, a function that additionally defines an isDefinedAt method.
It is easy to define partial functions with a series of case statement. A trivial example would be, e.g.:
scala> val pf: PartialFunction[Int, Unit] = {
| case 42 => ()
| }
pf: PartialFunction[Int,Unit] = <function1>
scala> pf.isDefinedAt(42)
res0: Boolean = true
scala> pf.isDefinedAt(0)
res1: Boolean = false
isDefinedAt is automatically generated from the list of cases defining the partial function.
Context
The Lift framework makes use of partial functions in many places, e.g. to define whether a request should be processed by Lift's engine or served directly from a file on disk, as is. and sometimes, I find myself wanting to write a case statement that matches all input parameters and only later decide if I want to return a value or not. This means that the initial series of cases is not enough any more to determine if my function is defined at a given value or not
For instance, in Lift, I want to add a rule that all html and htm files are served directly, and that files with the “lift” extension should be processed. It would look easy to do something like this:
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) => extension match {
case "html" | "htm" => false
case "lift" => true
}
}
Unfortunately, in this case, the compiler thinks that my partial function is defined everywhere, as the first case always matches. It's the nested match that may not match all incoming requests. And, is a request is not matched, a MatchError is thrown.
Question
Is there a simple way to make the compiler consider nested match statements when defining a partial function, or is the only way to do it to inline all nested conditionals like this?
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
In this example, it's largely doable, but the readability is decreased, and I've faced cases where inlining all checks looks very ugly.
In this case, you may want to write
LiftRules.liftRequest.prepend {
case Req(path, "html" | "htm", tpe) => false
case Req(path, "lift", tpe) => true
}
For more complicated cases, you’ll need to define your own extractor which you’ll have to use instead of a nested case statement.
object CheckExtension {
def unapply(ext: String) = ext match {
case "lift" => Some(true)
case "html" | "htm" => Some(false)
case _ => None
}
}
LiftRules.liftRequest.prepend {
case Req(path, CheckExtension(valid), tpe) => valid
}
This will only match if your predefined unapply function returns Some and assign the value of Some to the free variable valid. If unapply returns None, no match is being generated.