Why do the following tests return false in Scala? - scala

Both of the following print false. The desired behaviour is for the first to print true and the second to print false. I'm not sure why false always gets printed.
def myTest(filter: => Boolean) = () => {
if (filter) {
// do something here
true
}
false
}
println(myTest(5 > 3)())
println(myTest(5 > 7)())

This expression:
if (filter) {
true
}
is an expression that returns true when filter evaluates to true or Unit () otherwise.
This block:
{
expr;
false
}
is a block that evaluates expr, discards it, then returns false.
So:
{
if (filter) {
true
}
false
}
always returns false. Think of if (filter) { true } like expr;

huynhjl gives the syntactic reason. The phenomenological reason is that you forgot the else before the false.
scala> def myTest(filter: => Boolean) = () => {
|
| if (filter) {
| // do something here
| true
| }
| else false
| }
myTest: (filter: => Boolean)() => Boolean
scala> println(myTest(5 > 3)())
true
scala> println(myTest(5 > 7)())
false

The last statement is a false, so it returns false, you'd need an else in the if expression to conditionally execute that statement.
Just like to point out that your filter parameter already resolves a boolean so the if expression is entirely redundant, your construction can be rewritten simply as:
def myTest(filter: => Boolean) = () => filter
which may lead to further existential questions.

Related

Using scala.Option functionally

I have an Option, say O, which can either be None or may have some value inside. If it has some value, that value may have a flag, say f. My requirement is that if O is None, then I create an object, say of type MyEntity,but if O has a value with flag as true, I return Nil else I create instance of MyEntity with different value. Java code can be almost as:
if(O.isEmpty) {
MyEntity("x")
} else {
if(O.f) {
Nil
} else {
MyEntity("y") // with different value
}
}
I want to do this in functional style using HoFs provided in scala.Option. What would be best possible way of doing it? I could this so far :
if(O.isEmpty){
MyEntity("x")
} else {
Option.unless(O.exists(_.f))(MyEntity("y"))
}
I misread your question the first go round, so here is attempt #2
This is a great case for pattern matching:
val maybeMyEntity: Option[MyEntity] = option match {
case Some(flagValue) if flagValue => None
// case Some(true) => None (More concise, but does not highlight a handy feature)
case Some(_) => Some(MyEntity("Y"))
case None => Some(MyEntity("X"))
}
Pattern matching is very powerful.
Alternatively, mapping is another option:
mapping of an Option will only occur if its value is not empty, and flatMapping will remove the layer of Option added, from Option[Option[MyEntity]] to Option[MyEntity]
val result: Option[MyEntity] = if (option.isEmpty) {
Some(Entity("X"))
} else {
option.flatMap { flagValue =>
if (flagValue) {
None
} else {
Some(MyEntity("Y"))
}
}
}
As mentioned in the comments, Nil type is a List, and your expression should always return the same type (should really not be Any).
One possibility is to define a "sentinel" value for MyEntity, e.g.:
object MyEntity {
val Nil = MyEntity("")
}
Now you can write:
val result = O.fold(MyEntity("x")) {
case true => MyEntity.Nil
case false => MyEntity("y")
}
case class AnOption(var flag: Boolean = true)
case class MyEntities(name: String)
val myOptionEntityCheck = (someOption: Option[AnOption]) => {
someOption match {
case None => Some(MyEntities("X"))
case Some(aValue: AnOption) if aValue.flag => None
// OR case Some(AnOption(true)) => None
case Some(_) => Some(MyEntities("y"))
}
}

Better way to write cascading if statements in Scala?

In JavaScript we can rewrite:
if (ua.isEmpty()) {
return false;
}
else if (ua.contains('curl')) {
return false;
}
into this for clear code:
switch(true) {
case ua.isEmpty():
return false;
case ua.contains('curl'):
return false;
}
Any suggestion we could do things like this in Scala?
If all you care about is these two conditions you can just have some thing like this
if(ua.isEmpty || ua.contains('curl')) false
if you want to have more cases you can do something like this
ua match{
case _ if(ua.isEmpty) => false
case _ if(ua.contains('curl') => false
case _ => //return whatever you want if none of the above is true
}
or with a traditional if else
if(ua.isEmpty)
false
else if(ua.contains('curl')
false
else
// return whatever you want
Notice that if you don't add the final else or the final case _=> then the return type will be Any and not Boolean
As addition to Dionysis answer:
You can also use the type of the object you want to check - to make it more readable.
In your case if ua is a List:
ua match{
case Nil => false
case l if l.contains('curl') => false
case _ => true
}
As you see I also made some other small adjustments:
parameters () in if are not needed
I prefer to name the matched value and use this name in the if
If you are using Scala, I recommend using Options with ua ua: Option[String].
val ua: Option[String] = // Some("String") or None
val result = ua match {
case Some(x: String) if x.contains("curl") => false
case Some(x) => // What you want
case None => false
case _ => // Error
}
If you want to use if you should use ua: String (not recommended).
val ua: String = // "String" or ""
val result = if (ua.contains('curl') || ua.isEmpty || ua != "") false else // What you want
You should not use val ua: String = null the answer is here

How can i make a for loop with if else and make the good return type

i would like to resolve a problem,
i've done this code and i have this output
found : Unit
[error] required: Boolean
[error] for (data <- category(i)) {
i have to return : (List[String], (List[String], (List[String])
i choose to use the filter method for to realise a compact code.
i don't understand why it doesn't work. Why the code doesn't return a bool but a Unit.
I would like this method to return true if at least 1 element of the list starts with x otherwise the method must return false.
Thanks
def classifiedColumns(columnNames: List[String]): (List[Column], List[Column], List[Column]) = {
val category = List(
List("t01", "t03", "t11", "t1801", "t1803"), // 1
List("t05", "t1805"), // 2
List("t02", "t04", "t06", "t07", "t08", "t09", "t10", "t12", "t13", "t14", "t15", "t16", "t18")) // 3
def get_info(x: String, i: Int, category: List[List[String]]): Boolean = {
for (data <- category(i)) {
if (data.startsWith(x)) true
else false
}
}
(columnNames.filter(x => get_info(x, 1, category)).map(column),
columnNames.filter(x => get_info(x, 2, category)).map(column),
columnNames.filter(x => get_info(x, 3, category)).map(column))
}
classifiedColumns(List("t0201", "t0408", "t0600084"))
Your use of for does not behave as you expect. You're using this for-comprehension:
for (data <- category(i)) {
if (data.startsWith(x)) true
else false
}
This expression "desugars" into (i.e. is shorthand for):
category(i).foreach(data => {
if (data.startsWith(x)) true
else false
})
foreach returns Unit, and therefore the type of this expression (and the type returned from your get_info method, this being the body of the method) is Unit.
It's unclear what you expect to be returned here, I'm assuming you want the method to return true if any of the elements in category(i) start with x. If so, you can implement it as follows:
category(i).exists(_.startsWith(x))
Which returns a Boolean, as expected.

Search for a char in the key of a Map

I would like to make this method high-order function.
The idea is Sending a Map of key value and search for a char "." Dot if exists in key.
def findChar(mymap: Map[String, Any]): Boolean = {
val pattern = "^.*\\..*$".r
mymap.keys.foreach {
case pattern() => return true
case _ => None
}
return false
}
i am calling this function
if (findChar(attributes)) {
DO something
} else {
DO something else }
how can i use the "exsits" method here?
One way to do it, if you explicitly need exists:
map.keys.exists(_.contains("."))

Scala memory use

I've been trying out Scala in a pet project recently and noticed that the following code snippet was eating up memory (I call this method a lot):
private[this] def isConsistent(startLang2: Int, lengthLang2: Int,
startLang1: Int, lengthLang1: Int,
lang2FinalAlignments: ArrayBuffer[ArrayBuffer[Int]]): Boolean = {
(startLang2 to (startLang2 + lengthLang2)) foreach {
i =>
val valueSeq = lang2FinalAlignments(i)
if (valueSeq.size == 0 || valueSeq.exists { value => value < startLang1 || value > (startLang1 + lengthLang1) })
false
}
true
}
When I changed the 'false' to 'return false' the situation seems to have resolved itself:
private[this] def isConsistent(startLang2: Int, lengthLang2: Int,
startLang1: Int, lengthLang1: Int,
lang2FinalAlignments: ArrayBuffer[ArrayBuffer[Int]]): Boolean = {
(startLang2 to (startLang2 + lengthLang2)) foreach {
i =>
val valueSeq = lang2FinalAlignments(i)
if (valueSeq.size == 0 || valueSeq.exists { value => value < startLang1 || value > (startLang1 + lengthLang1) })
return false
}
true
}
When I think about it snippet #2 makes sense with regards to how I expect/want the method to work. Could someone please explain to me what the first snippet is doing?
Let's see what foreach does:
def foreach[U](f: Elem => U): Unit
So it runs f on every element of the collection and discards its result - it doesn't care about the return type of f.
In your case when you call
... foreach {
i => {
...
if (...)
false
}
true
the body of the function return false if the condition is satisfied and Unit otherwise. Their common supertype is Any, so the function passed to foreach is of type Int => Any. It's result is discarded and you traverse the whole collection. (Try giving an explicit type such as foreach[Any] or foreach[Boolean].)
In the second snippet the situation is very different:
... foreach {
i => {
...
if (...)
return false
}
true
Here foreach traverses the range only until the condition is satisfied and then return escapes the foreach execution and makes the main function exit.