scala pattern matching guard condition with or expression (or more preciesly - scala boolean | vs ||) [duplicate] - scala

I just noticed that in Scala Boolean supports both & and &&. Is there a difference between these two operators? The Scala docs use the exact same description for both of them, so I wasn't sure.

& and | are strict while && and || are short-circuiting:
false && (throw new Exception()) => false
false & (throw new Exception()) => ex
true || (throw new Exception()) => true
true | (throw new Exception()) => ex
The full documentation for & and | have a note explaining this behaviour:
This method evaluates both a and b, even if the result is already
determined after evaluating a.

Related

Scala - two operand or/and functions

In Java there are static and/or functions which receive two boolean operands and return the correct result: logicalAnd and logicalOr (both located in java.lang.Boolean) [1]:
public static boolean logicalAnd(boolean a, boolean b)
public static boolean logicalOr(boolean a, boolean b)
I'm looking for a similar concept in the Scala standard library. Is there any?
Edit
I know Scala can call Java functions, but this code won't compile since Java's functions are not high-order, so it's not usable for me:
val op =
if (input == "or") java.lang.Boolean.logicalOr
else java.lang.Boolean.logicalAnd
[1] https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html
You can just use a function literal:
val op: (Boolean, Boolean) => Boolean =
if (input == "or")
_ || _
else
_ && _
The fact that
val op =
if (input == "or") java.lang.Boolean.logicalOr
else java.lang.Boolean.logicalAnd
doesn't compile has nothing to do with those methods being defined in Java or in Scala.
The code you posted actually compiles in Scala 3. In Scala 2 you have to be explicit when you want to turn a method into a function value:
val op =
if (input == "or") java.lang.Boolean.logicalOr _
else java.lang.Boolean.logicalAnd _
In Scala, you can avoid using these methods in lambda processing, using the _ syntax and the bitwise operators:
Boolean::logicalAnd => _ & _
Boolean::logicalOr => _ | _
For example, if you have in Java something like this:
Stream.of(/* .. some objects .. */)
.map(/* some function that returns a boolean */)
.reduce(Boolean::logicalOr);
In Scala is possible to write using _ syntax:
LazyList.fill(/* ... */)
.map(/* ... */)
.reduce(_ & _) // or | or ^

Boolean operators in filter of list

I am trying to filter a list of files by two conditions. And the following code works
import java.io.File
val d = new File("/home/loom/shp")
val dirList = d.listFiles.filter(_.isDirectory).toList
dirList.map({
_.listFiles.filter(f => f.isFile).filter(f => f.getName.endsWith("shp")).toList.map(println)
// !! Inducde an error
// _.listFiles.filter((f => f.isFile) && (f => f.getName.endsWith("shp"))).toList.map(println)
})
However, if I tried to combine both conditions in one filter condition (as it is shown in the commented line), I have received the following error message:
Error:(32, 27) missing parameter type
_.listFiles.filter((f => f.isFile) && (f => f.getName.endsWith("shp"))).toList.map(println)
It claims that I missed the parameter type. What should I correct to make my code work?
You're trying to use the boolean && operator on two functions, which simply won't work. What you want is a function from File to Boolean, which you can write like this:
_.listFiles.filter(f => f.isFile && f.getName.endsWith("shp")).toList.map(println)
f.isFile is a boolean and f.getName.endsWith(...) is a boolean, so && will do what you expect.

How to calculate a value based on certain conditions in Scala

I have implemented a recursive method to check if number of parenthesis in a string is valid or not. Here is the code
def balance(chars: List[Char]): Boolean = {
#tailrec
def isValid(newChars: List[Char], difference: Int): Boolean = {
if (newChars.isEmpty) difference == 0
else if (difference < 0) false
else {
var newDifference = difference // Scala IDE gives warning here
if (newChars.head == '(') newDifference = difference + 1
else if (newChars.head == ')') newDifference = difference - 1
isValid(newChars.tail, newDifference)
}
}
isValid(chars, 0)
}
I tested the above code for the following test cases and it works fine So I am only looking for improving the if/else ladder.
println("Testing parenthesis balancing")
assert(balance("(Sachin is learning (scala) and (spark))".toList))
assert(!balance("(Invalid))(expression)".toList))
assert(balance("".toList))
assert(balance("()()".toList))
assert(!balance("{())}{()}".toList))
As mentioned in the code, Scala IDE complains on that line saying
Avoid mutable local variables
I am not really sure how to compute the value of newDifference without using if/else. Other option I could see is directly call isValid method in if/else ladder with computed values of newDifference.
I am still learning Scala So I want to know what could be the best possible way to write this code without mutating the local variable (or any other warning).
People use pattern match for that. That way you can avoid both mutable variables and the "if/else ladder", that makes for horrible "spaghetti code".
def isValid(chars: List[Char], ps: Int = 0) = (chars, ps) match {
case (Nil, _) => ps == 0
case (_, _) if ps < 0 => false
case ('(' :: tail, ps) => isValid(tail, ps + 1)
case (')' :: tail, ps) => isValid(tail, ps - 1)
case (_ :: tail, ps) => isValid(tail, ps)
}
You can write:
val newDifference =
if (newChars.head == '(') difference + 1
else if (newChars.head == ')') difference - 1
else difference;
as if in Scala is an expression, or use match, which would be considered more idiomatic in this case:
val newDifference = newChars.head match {
case '(' => difference + 1
case ')' => difference - 1
case _ => difference
}
The whole function can be converted into a single match on newChars, but I'll leave that to you. See the first example here for some ideas.

How can do a tuple comparison in coffeescript similar to that in python?

This is a my function
st3 = (x, y) ->
console.log "#{x?}, #{y?}"
if [x?, y?] is [true, true] # <- this is the line
'good'
'bad'
This is the output
true, true
bad
I want to be able to do a tuple comparison like it is in python.
In python, the if can be written roughly as
if (x, y) == (True, False):
return 'good'
The coffescript if loop is translated into javascript as such
if ([x != null, y != null] === [true, true]) {
'good';
}
That's why this will not evaluated to true.
Is there any alternative way to express it in coffeescript?
If you want to check to see if all of your arguments are not None, then I would do this:
def check_all(*args):
return all(arg is not None for arg in args)
If you wanted to check if they're all True (like literally True) then you could use
def check_all(*args):
return all(arg is True for arg in args)
If you wanted to take in a list (instead of variable number of parameters, remove the asterisk.

Does Scala have a library method to build Option-s that takes into account empty strings?

I want to filter out empty strings to put them into an Option. So I quickly built this now:
def StrictOption(s: String) = s match {
case s if s != null && s.trim.length() > 0 => Some(s)
case _ => None
}
Question: is this maybe already somewhere in the standard library?
I don't think there's one single method in the standard library to do this, but you can do this much more tersely than your implementation.
Option(s).filter(_.trim.nonEmpty)
If you care at all about performance then
if (s.trim.isEmpty) None else Some(s)
is only 4 characters longer than Ben James's solution, and runs 3 times faster, in my benchmark (47 vs 141).
Starting Scala 2.13, for those not expecting nulls (non-Java context), Option::unless and Option::when are now an alternative option:
// val str = "hello"
Option.unless(str.isEmpty)(str)
// Option[String] = Some(hello)
Option.when(str.nonEmpty)(str)
// Option[String] = Some(hello)
// val str: String = ""
Option.unless(str.isEmpty)(str)
// Option[String] = None
Option.when(str.nonEmpty)(str)
// Option[String] = None
There's nothing built in; Ben's filter is the best brief version if performance isn't an issue (e.g. you're validating user input). Typically, performance will not be an issue.
Also, note that it's a little strange to use match when you're not actually matching anything; it's just more boilerplate to get an if-else statement. Just say
if (s ne null && s.trim.length > 0) Some(s) else None
which is about as fast and brief as anything, unless you want to write your own is-it-whitespace method. Note that trim uses a peculiar criterion: anything above \u0020 (i.e. ' ') is not trimmed, and anything equal or below is. So you could also write your own trimmed-string-is-empty detector, if performance of this operation was particularly important:
def ContentOption(s: String): Option[String] = {
if (s ne null) {
var i = s.length-1
while (i >= 0) {
if (s.charAt(i) > ' ') return Some(s)
i -= 1
}
}
None
}
This could also be achieved with a for-comprehension
val res = for (v <- Option(s) if s.nonEmpty) yield v
Option("something") produces Some("something")
Option(null) produces None