I find using match more readable than if. If I have a boolean value, can I use it with match?
I usually do
if(!authorised) {...} else {..}
But I am unable to do
authorised match {
case ??? //what here??
}
You just need to use boolean literals:
authorised match {
case true => /*true case*/
case false => /*false case*/
}
Alternatively to pattern match, consider mouse which provides extension methods for booleans, for example, consider fold
authorised.fold("It is true", "It is false")
You can do this using
authorised match {
case true => ...
case false => ...
}
Note that pattern matching on boolean values is not very idiomatic in Scala, and you'd probably be better off using the standard if/else expression. The compiler will actually not manage to generate the same efficient code for the pattern match, as discussed in this answer. It's very common for Scala beginners to get over-enthusiastic with pattern matching and start using it everywhere, but in the case of plain booleans, it really makes sense to stick with if/else.
Side-note: Other answers have mentioned using a default clause like
authorised match {
case true => /*true case*/
case false => /*false case*/
case _ => /* default case */
}
This is unnecessary, as Boolean can only ever be true or false. Like all primitive types, they cannot be assigned null so the additional clause is useless and the compiler will justifiably warn you about it.
warning: unreachable code
case _ => /* default case */
You can simply write:
authorised match {
case true => ...
case false => ...
}
Although intellij suggests refactoring to if statement.
You can do like this:
authorised match {
case true => // true case
case false => // false case
case _ => // other case for exception or null
}
Related
As in most languages, Scala has an if statement. However, using pattern matching I can achieve the exact (?) same result using code of the form:
(condition) match {
case true => { /* handle the true case */ }
case false => { /* handle the false case */ }
}
This feels like an abuse of the mechanism, but I find it hard to explain why. Can wiser heads help me understand the position?
I wouldn't normally use it, although yes, it's a matter of taste. But there are cases where I might resort to this construction. For example when I need to send as argument a higher order function that reveives a Boolean value (using Scala's PartialFunction syntax):
future.onSuccess {
case true => ???
case false => ???
}
Or when there are extra conditions, something along these lines:
value match {
case true if condition1 => ???
case true if condition2 => ???
case true if condition3 => ???
case false => ???
}
The match compiles to the equivalent of
val scrutinee = condition
if (scrutinee == true) /* handle success case */
else if (scrutinee == false) /* handle failure case */
else throw new MatchException()
so it's semantically identical. But why would you? It's more verbose, more syntax-heavy, and less clear than the if expression.
The below code takes the first two character of string and check if pattern is "de" or None it returns None else it returns the Test("Found")
val s =Option("abc")
val t = s.map(_.take(2))
case class Test(id:String)
t match {
case Some("de") => None
case None => None
case _ => Test("Found")
}
Can anyone suggest a efficient solution for case matching
I think I get what you're asking so let me try this:
val condition = Option("abc").exists(_.toLower.take(2) == "de")
val output: Any = if(condition) Test("found") else None
The first portion returns false if the Option is None. It also returns false if the first two letters of the string are "de" in a case insensitive way.
The second portion returns either a None or a Test object. However, I want to point out that this results in an Any. Did you mean for it to return a Option[Test] type instead?
I assume, you meant Some(Test("Found")) in the last line of your snippet, judging from your comment to the other answer.
If so, this is what you are looking for:
t.filterNot(_.take(2) == "de").map(_ => Test("Found"))
If I have optionA, and optionB, how can I return optionA if both are defined and optionB is both are not defined.
Basically, I am trying to rewrite this
val result: Option[Long] =
if(optionA.isDefined && optionB.isDefined)
optionA
else
optionB
No, optionA.orElse(optionB) is not the same and broke our test cases. BOTH options must be defined and we want to use optionA. IF optionA is defined and optionB is not defined, we want None.
Someone marked my question as a duplicate which it is not. I was having trouble but finally stumbled upon the answer....
ok, I think I got it and I definitely think it is less human readable
optionA.flatMap { aId =>
optionB.map(bId => bId).orElse(Some(aId))
}
for added clarity. our truth table is thus
optionA.isDefined optionB.isDefined resultNeeded
None None None
Some(a) None None
None Some(b) Some(b)
Some(a) Some(b) Some(a)
thanks
You can use pattern matching :
(optionA, optionB) match {
case (Some(_), Some(_)) => optionA
case _ => optionB
}
Your truth table implies that you only return Some when optionB is defined, so we can start our evaluation with mapping over that option. Inside the map function we know we have a b. Then we check if we have an a too and just return that, otherwise just use our b.
optionB.map(b => optionA.getOrElse(b))
I think the cleanest way to express what you want is this, if you're familiar with standard monadic operations:
optionB.flatMap(_ => optionA orElse optionB)
But very clear--and very fast because it avoids any object creation!--would be just to say in logic exactly what you want, i.e., what you already wrote:
if (optionA.isDefined && optionB.isDefined) optionA else optionB
That's what you said ("if both are defined, I want A, else I want B")--so just write it out as code.
Using higher-level methods is not always the way to go when it reduces both clarity and speed.
Try this:
(optionA,optionB) match {
case (Some(v1) , Some(v2)) => Some(v1)
case (_ , a:Option) => a
}
Say I am using a match expression to test a value that may or may not be in a Map object as follows:
map.get(key) match {
case Some(value) if (cond1(value)) => res1(value)
case Some(value) if (cond2(value)) => res2()
case None => res2()
case _ => // None of the above
}
As you can see I want to call the res2 in either case where I have a value for my key and it meets condition 2 or I have no value for key. Can anyone suggest a better construct that would avoid the duplicate calls to res2() in the sample above?
Thanks
Des
* Sorry I realised that the code sample was not quite correct and have updated accordingly. I only want to call res2 in the case where the value for the key meets cond2 OR there is NO entry for key.
I believe what you want is:
map.get(key) match {
case Some(value) if (cond1(value)) => res1(value)
case o: Option[String] if ( o.forall(cond2) ) => res2()
case _ =>
}
replacing [String] with whatever the type of key is.
The names of the methods on Option aren't always the most obvious; in maintaining functional purity they sacrifice clarity for us illiterati. In this case, the scaladoc for Option tells us that forall:
Returns true if this option is empty or the predicate p returns true
when applied to this scala.Option's value.
Without gard if that are only possibilities:
case Some(value) => if (cond1(value) ) res1(value) else res2()
I am looking for a way to do pattern matching based on the result of a function evaluation rather than the type of the val. For example,
def f1(x:String):Boolean = if (x contains ("Helllo")) true else false
val caller="Hello"
caller match
{
case f1(caller) => println ("caller said hello")
case _ => println ("caller did not say hello")
}
any idea ?
You want to use pattern guards:
caller match
{
case x if f1(x) => println ("caller said hello")
case _ => println ("caller did not say hello")
}
I would prefer to do it without guard, that would a bit faster and cleaner:
f1(caller) match {
case true => ....
case false => ....
}
but for Boolean better to use if/else expression, that would be cleaner in byte code and a bit faster