This chapter focuses on Scala’s basic operators and operations flow.
Unlike Java, Scala’s operators can be overloaded. The alternative, the loop branch, has been changed quite dramatically in Scala, for example by removing the old Switch branch from Scala; The for loop can be used to collect elements…… And so on.
Scala’s flexibility and complexity has been evident since this chapter. Perhaps because Scala is so flexible, it has a harder barrier to entry than Java, and not many developers are willing to embrace the language. For example, most programmers in China still use Java to develop Spark projects.
This proves the “there is no such thing as a free lunch” theorem: a flexible language inevitably makes it harder to get started.
Scala operator.
Regardless of programming language, operators fall into three categories: arithmetic operators, assignment operators, and relational operators, So does Scala.
% and /
I sometimes confuse the difference between the two symbols…… The % sign is the remainder and the/is the quotient (rounded down).
/ is also called the div operation and % is also called the mod operation.
println(10 / 3) / / = = 3
println(10 % 3) / / = = 1
Copy the code
Scala does not have ++ and —
The ++ and — operators have been removed from Scala for unknown reasons, but at least the question of ++ I or I ++ is no longer a question.
To implement the increment operation, you can only use the retro +=1 to solve the problem:
var i = 3
// wrong : i++
i += 1
Copy the code
Note: While there are no ++ and — operations in Scala, we can artificially overload these operators. There is the overloading section, which we will cover in a later section.
Scala removes the ternary operator
Scala also cancels the original 😕 The trinary operator is instead expressed by the more understandable if-else branch:
var a = 3
//b = (a > 2) ? 2:3
val b = if(a > 2) 2 else 3
Copy the code
In other words, Scala uses if-else selection branches instead of the trinary operator because Scala’s if-else has a return value. So it’s perfectly possible to write a more complicated if-else branch to determine the assignment of B! At this point, the traditional 😕 You can’t achieve the same effect.
val b = if(a > 2) 2 else if(a ==2) 3 else 4
Copy the code
Learn a little about Scala’s input statements
How to implement scanf function like C language? Simply import scala.io.StdIn and call the readXXX function of StdIn.
import scala.io.StdIn
val msg = StdIn.readLine()
// Prints a string as a $sign.
println(s"get message + $msg")
Copy the code
[Important]Scala control flow
The selected branch of Scala
As mentioned earlier, every branch within Scala’s if-else has a return value.
Of course, this does not mean that we will necessarily use the return value. If your judgment branch does not need the return value, you can ignore it. In this case, each default branch returns a Unit. (Unit is similar to void in Scala.)
The if-else branch itself also returns a Unit when the program runs and finds that none of the branches satisfy the condition.
if (a > 3) {
println("a > 3")}else if (a < 3) {
println("a < 3")}else {
println("a == 3")}Copy the code
The if-else defaults to the last statement in each branch that has a return value. You can also use return to display declarations (but this is not necessary). In the following code block, for example, b is assigned a different value depending on how a compares with 3.
Since each branch returns a value of type Int, the Scala compiler can automatically infer that b is also of type Int.
val b = if (a > 3) {
println("a > 3")
//return 4
4
} else if (a < 3) {
println("a < 3")
//return 2
2
} else {
println("a == 3")
//return 3
3
}
//b is of type int.
println(b.getClass)
Copy the code
In other words, if each branch returns a different type, there’s nothing the compiler can do. It can only assume that B is an uptransition object of type Any.
val b : Any = if (a > 3) {
println("a > 3")
//return a Int value
4
} else if (a < 3) {
println("a < 3")
//return a String
"2"
} else {
println("a == 3")
//return a Double value
3.00
}
//b can be Double,Int, or String belonging to Any.
println(b.getClass)
Copy the code
Scala does away with the “old” switch branch
It was made obsolete by Scala for the same reason 😕 Same thing: Scala itself has a very robust and complex pattern matching that perfectly replaces switch functionality. Pattern matching covers a lot of ground, and it’s too early to cover it. Therefore, the author chooses to introduce it in a later chapter.
The Scala loop branch – for loop
In general, Scala’s for loop is a fairly substantial change and wrapper over the original Java for loop. The details are covered in this section.
Scala’s for loop is a direct mashup of Java’s for-each enhancement for loop idea: you can iterate with elements as well as subscripts.
We will cover arrays and collections in a later section.
val arr: Array[Int] = Array[Int] (1.2.3.4.5)
// Equivalent to the For-each loop in Java.
for(i <- arr) println(i)
Copy the code
It takes just a few lines to print out all the elements in the ARR array. Where, I < -arr represents: each element I in the arR array.
1. The to and until
We can intuitively express from… by using to and until. to(until)… Without the need for I =0; i<(=)… ; i… This is the three-paragraph formula.
The difference between “to” and “until” is whether the last element is included. In the case of the previous for loop, this is the difference between < (until) and <= (to).
for(i <- 1 to 10) println(i) // output 1 to 10, equivalent to I =1; i<=10; i++
for(i <- 1 until 10) println(i) // output 1 to 9, equivalent to I =1; i<10; 1 + +
Copy the code
Why doesn’t the compiler highlight to and until? Because to and until are actually methods that Scala already implements for you, they belong to a RichInt final class.
2. Iterate over elements by array subscript
In some cases, we want to know the number of subscripts the element is in as we iterate. In older versions of the for loop, we didn’t really worry about this, because most of the for loop was traversed directly using subscripts:
// What we do in Java
int[] arr = {1.2.3.4.5.6};
for(int i = 0 ; i< arr.length; i++)
{
System.out.println(arr[i]);
}
Copy the code
In Scala, arrays provide a indices method to return a subscript:
//arr.indices fetch the indices of arrays, not the elements.
for(index <- arr.indices) println(S "the first${index}A location:${arr(index)}")
Copy the code
Indices is essentially a wrapper for 0 until Length, where length is the length of each array.
3. Scala’s for loop does not continue
Instead of a continue, Scala has the concept of a loop guard: an if judgment is inserted before executing a for loop. The structure of the for loop is executed only if all expressions following it are true, and not otherwise.
For example, print even numbers between 0 and 10:
// Print an even number between 0 and 10.
for(i <- 0 to 10 if i % 2= =0) { println(i)}
Copy the code
The introduction of loop guard makes it possible to use the shortest possible statement to realize the function of judgment + loop.
4. Scala’s nested for loop can be folded
We occasionally use nested for loops to solve problems, such as bubbling sort.
// A cluttered int array
int[] arr = {3.7.6.8.1.4.2};
// Bubble sort to small -> large sort
for(int i = 0 ; i< arr.length; i++)
{
for (int j = 0; j<arr.length-i-1; j++)
{
if (arr[j] > arr[j+1]) {int temp = arr[j];
arr[j] =arr[j+1];
arr[j+1] = temp; }}}/ / output
for (int i : arr){ System.out.println(i); }
Copy the code
The logic is actually executed only in the innermost nested loop. So in Scala, we can simplify as follows:
for (i <- arr.indices; j <- 0 until arr.length - i - 1 if arr(j)>arr(j+1)) {
val temp = arr(j)
arr(j) = arr(j+1)
arr(j+1) = temp
}
Copy the code
In addition, when the for loop has a large number of conditional statements, cramming them all into one () can be bad for code reading. So the above code can also be rewritten as follows:
for {
i <- arr.indices
j <- 0 until arr.length - i - 1
if arr(j)>arr(j+1)
}{
val temp = arr(j)
arr(j) = arr(j+1)
arr(j+1) = temp
}
Copy the code
5. Use the Range class for step size iteration
I =0 cannot be used in Scala; i<10; I +2 for step iteration; So use a Range class for auxiliary construction:
The Range constructor looks like this, and constructs a [start,end] Range.
Range(start:Int,end:Int,step:Int)
// Generate an arithmetic sequence of step by starting subscript, ending subscript and step size. Notice that the generated sequence does not contain end, but start.
Copy the code
Try to generate odd numbers between 1 and 11:
//1,3,5,7,9, but not 11.
for(i <- Range(1.10.2)){
println(i)
}
Copy the code
Range is essentially belongs to the scala. Collection. Immutable under an immutable collection.
6. Use yield to collect elements
Like the if-else branch, the for loop branch has a return value. We can use yield to gather these elements together.
// Load each element I into the list.
val ints: immutable.IndexedSeq[Int] = for(i <- Range(1.10.3)) yield i
Copy the code
Yield actually accepts a block of statements. Similarly, Yield collects elements based on the last statement with a return value and returns an entire set of IndexSeq types.
7. Scala implements break by throwing an exception
Not only does Scala discard the continue keyword, but so does break. If you want to implement the interrupt function, you need to do so by actively throwing an exception.
Before this, we first need to introduce import scala. Util. Control. Breaks. _. _ represents everything that is brought into the Breaks class.
We then use breakable(()=>{… }) wrapped up. The break() statement is then called where the break is needed. This is equivalent to the break keyword.
// Breakable is a control abstraction. Internally execute a function ()=>Unit.
breakable(() => {
var i = 0
while (i < 10) {
if (i == 5) break()
i += 1}})Copy the code
The breakable is essentially a control abstraction that takes a function of type ()=>Unit and allocates the statements inside that function to a thread for execution. I’ll cover higher-order functions and control abstractions in a follow-up section called “Advanced Functions in Scala.”
Scala retains the while/do-while loop
Scala has a while/do-while loop similar to Java, where a while loop is used when a step size cannot be used as a termination condition to control the branch of the loop.
However, Martin Odsky, the designer of Scala, does not advocate while, and instead uses for loops whenever possible. The reason: both the if branch and the for loop can return a value (the for loop requires yield), while the while loop does not. So if you want to save a variable, or judge a condition, you will inevitably use external variables. According to Martin, internal code should not change external content.
The most obvious example: In Java 8, attempts to change external values within a lambda expression will result in an error.