I would like to simplify this:
var countA: Int = 0
var countB: Int = 0
if (validItem) {
if (region.equalsIgnoreCase( "US" )) {
if (itemList > 0) {
countB = 1
} else {
countA = 1
}
} else {
countB = 1
}
} else {
countA = 1
}
How do I use ternary operator in scala.
You should not need to use a ternary operator in Scala. In Scala, if is an expression not a statement, you can say val x = if (b) 1 else 2.
The usage of var in your example also points to a problem, because you can usually avoid this when you use the if as an expression.
Let's try to break down the code to avoid the var, i.e. first remove all if statements that are not expressions with a corresponding else and always provide both values:
var countA: Int = ???
var countB: Int = ???
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) {
countA = 0
countB = 1
} else {
countA = 1
countB = 0
}
} else {
countA = 0
countB = 1
}
} else {
countA = 1
countB = 0
}
Now we can define the condition for which either of countA and countB is one:
val isUS = region.equalsIgnoreCase("US")
val hasItems = itemList > 0
val isA = !validItem || (isUS && !hasItems)
val isB = !isA
// or: val isB = validItem && (!isUS || hasItems)
and then:
val countA = if (isA) 1 else 0
val countB = if (isB) 1 else 0
I think the short answer is that in Scala there is no ?: ternary operator. Although you can imitate the syntax using implicits (see #jwvh's answer), I think it doesn't really simplify anything.
There are a couple of important properties of the conventional ?:
it always has two branches
following from the previous property, the ternary operator always returns a value (this is mostly the point of using ?:)
val result: Int = if (true) 1 else 2
// result is 1
branches are evaluated lazily
if (true) 1 else (0/0) // returns 1
if (false) 0/0 else 2 // returns 2
// i.e. 0/0 is not evaluated
As you see, in Scala if-else (with else) construction satisfies these properties. This is not the case for if-else construction in some other languages, like C or Java, because it doesn't return a value.
So the bottom line is that in Scala you don't need a ternary operator, because you can just use if-else.
UPDATE
As Alexey Romanov mentions in the comments, if statement without else actually satisfies the first condition as well. When you write
val result = if (true) 1
it actually means if (true) 1 else (), so result will have type AnyVal instead of Int, because the return type of the if expression is the lowest common bound of the both branches (Int and Unit in this case).
This might be a bit confusing for a "newbie", but you could attach a ternary method to the Boolean class like so.
implicit class Ternary[T](condition: Boolean) {
def ??(a: => T, b: => T): T = if (condition) a else b
}
Usage:
(4 == 4)??("yes","no") // res0: String = yes
("abc".length < 2).??(1,0) // res1: Int = 0
List('c').isEmpty.??('X','+') // res2: Char = +
To expand on #0__'s answer (if that is his/her real name), you can also use tuples to assign to two variables at once.
val (countA, countB) =
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) (0,1) else (1,0)
} else {
(0,1)
}
} else {
(1,0)
}
This is an old question and I'm taking a break from a current problem, so I thought I'd leave a basic pattern match solution.
val (countA, countB) =
(validItem, region.equalsIgnoreCase("US"), itemList > 0) match {
case (true, true, false) | (false, _, _) => (1, 0)
case _ => (0, 1)
}
Related
I am writing a recursive function to check if a non-negative Integer is Prime in SCALA. My function takes two inputs to do so. Here is my code:
import io.StdIn._
def isPrime (x:Int, i:Int): Boolean = {
if (i < 3) {
true
}else if (x % i == 0) {
false
}else{
isPrime(x,i-1)
}
}
print("Enter a number to check if it is a prime number: " )
val num1 = readInt()
println(isPrime(num1,num1-1))
My question is that is there a way for me to take one input as the parameter for the function? The code has to use a recursive function. I know that there are more effective ways to check if a number is prime (using iteration perhaps), but I'm just doing this as a practice problem.
It is perfectly fine, I'd say even standard practice, to wrap recursive functions with a calling function. For example:
def isPrime( x:Int ) = {
def recIsP( n:Int, i:Int ) : Boolean = i == n || n % i != 0 && recIsP(n, i + 1)
recIsP(x,2)
}
isPrime(3301)
One option is to make an inner method
def isPrime(x:Int): Boolean = {
def loop(i: Int): Boolean =
if (i<3 ) {
true
} else if (x % i==0) {
false
} else {
isPrime(x,i-1)
}
loop(x, x - 1)
}
another option is to make a default parameter. Those can't refer back to the previous parameter, so you'll have to use a workaround. Here I pass some j, and make i = x - j, so I can just increment j starting from 1
def isPrime(x: Int, j: Int = 1): Boolean = {
val i = x - j
if (i < 3) {
true
} else if (x % i==0) {
false
} else {
isPrime(x, j + 1)
}
}
Unrelatedly, there is a bug in your code: 4 should not be prime.
I have this function that counts the number of adjacent repeated chars inside a String.
def adjacentCount( s: String ) : Int = {
var cont = 0
for (a <- s.sliding(2)) {
if (a(0) == a(1)) cont = cont + 1
}
cont
}
}
But I'm supposed to create a function that does exactly the same, but using only immutable variables or loop instructions, in a "purely" functional way.
You can just use the count method on the Iterator:
val s = "aabcddd"
s.sliding(2).count(p => p(0) == p(1))
// res1: Int = 3
I'm new to scala and i'm trying to implement a do while loop but I cannot seem to get it to stop. Im not sure what i'm doing wrong. If someone could help me out that would be great. Its not the best loop I know that but I am new to the language.
Here is my code below:
def mnuQuestionLast(f: (String) => (String, Int)) ={
var dataInput = true
do {
print("Enter 1 to Add Another 0 to Exit > ")
var dataInput1 = f(readLine)
if (dataInput1 == 0){
dataInput == false
} else {
println{"Do the work"}
}
} while(dataInput == true)
}
You're comparing a tuple type (Tuple2[String, Int] in this case) to 0, which works because == is defined on AnyRef, but doesn't make much sense when you think about it. You should be looking at the second element of the tuple:
if (dataInput1._2 == 0)
Or if you want to enhance readability a bit, you can deconstruct the tuple:
val (line, num) = f(readLine)
if (num == 0)
Also, you're comparing dataInput with false (dataInput == false) instead of assigning false:
dataInput = false
Your code did not pass the functional conventions.
The value that the f returns is a tuple and you should check it's second value of your tuple by dataInput1._2==0
so you should change your if to if(dataInput1._2==0)
You can reconstruct your code in a better way:
import util.control.Breaks._
def mnuQuestionLast(f: (String) => (String, Int)) = {
breakable {
while (true) {
print("Enter 1 to Add Another 0 to Exit > ")
f(readLine) match {
case (_, 0) => break()
case (_,1) => println( the work"
case _ => throw new IllegalArgumentException
}
}
}
}
If Java I could legally do this...
int num = 5;
final boolean isPositive;
if(five > 0) {
isPositive = true;
} else {
isPositive = false;
}
System.out.println("Is positive: " + isPositive); // Prints "Is positive: true"
I call these delayed definition constants.
Is there a way to create delayed definition constants in Scala?
In scala you can't delay the definition. If you wanted to do something similar then you would typically achieve this by assigning it to the result of the if statement.
val isPositive = if(num > 0) true else false
or even just
val isPositive = num > 0
You can do something like this:
val isPositive = num > 0
or (when num is hard to compute and might not be called - then you can delay computation)
lazy val isPositive = num > 0
if the num is a variable then you can write:
def isPositive = num > 0
In Scala it's perfectly OK to write short functions as one liners.
I did it like this...
val num = 5
val isPositive: Boolean = {
if(num > 0) { true }
else { false }
}
println("Is positive: " + isPositive) // Prints "Is positive: true"
Some algorithms execute a while loop with condition true and will (for sure) end at some point with a return statement inside the body of the while loop. E.g.:
def foo: Int = {
while(true) {
// At some time, the while loop will do a return statement inside its body
if( ... )
return 0
}
}
Simple example (without semantic sense):
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
}
The Scala compiler complains about a type mismatch, because the while loop has type Unit and the compiler does not know, that the while loop will at some point return a value. We could fix this with a workaround like:
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
0 // !
}
But this looks ugly. Is there a better workaround ? Or even a better solution for this kind of problem ?
You could throw an exception:
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
throw new IllegalStateException("This should never happen")
}
The compiler will stop complaining about the type mismatch, and since the while loop always returns something, the exception will never be thrown. And if it is, you will quickly find out where you did something wrong :).
There are other ways to write this loop which are more idomatic and Scala-esque, but given the code you provided, this will get the job done in a clear and simple way.
Maybe you should just use tail recursion instead. It should end up compiling down to very similar bytecode:
import scala.annotation.tailrec
def foo: Int = {
#tailrec def bar(i: Int): Int = {
val j = i + 1
if (j == 10) return 0
else bar(j)
}
bar(0)
}
You might even want to make use of the default parameter value support:
#tailrec def foo(i: Int = 0): Int = {
val j = i + 1
if (j == 10) return 0
else foo(j)
}
Note that this way requires you to call the function as foo() not foo since it has an argument.
A more idiomatic way would be to use recursion. Something like this:
def foo: Int = {
import scala.annotation.tailrec
#tailrec def whileUnderTen(i: Int):Int = if ( i < 10) whileUnderTen(i+1) else 0
whileUnderTen(0)
}
For just these occasions, I have a "forever" construct defined in my personal standard library.
forever{
}
is in all ways equivalent to
while(true){
}
except that forever has type Nothing while the equivalent while construct has type Unit. Just one of those small extension capabilities that makes Scala such a joy.