Introduction to Scala Programming Functions (3)

Function definition and call

When defining a function in Scala, you need to define the function name, parameters, and function body of the function.

Our first function looks like this:

def sayHello(name: String, age: Int) = {
  if (age > 18) { printf("hi %s, you are a big boy\n", name); age } 
  else { printf("hi %s, you are a little boy\n", name); age 
}
sayHello("leo", 30)

Scala requires that the types of all parameters must be given, but not necessarily the type of the return value of the function. As long as the function body on the right does not contain recursive statements, Scala can infer the return type by itself based on the expression on the right.

Defining a function body with a multi-line statement in a code block

One-line function: def sayHello(name: String) = print(“Hello, ” + name)

If there are multiple lines of code in the function body, you can use a code block to wrap the multiple lines of code, and the return value of the last line in the code block is the return value of the entire function. Unlike in Java, the return value is not used.

For example, the following function implements the accumulation function:

def sum(n: Int) = {
  var sum = 0;
  for(i <- 1 to n) sum += i
  sum
}

Recursive functions and return types

If the function itself is called recursively within the function body, the return type of the function must be given manually.

For example, to implement the classic Fibonacci sequence:

9 + 8; 8 + 7 + 7 + 6; 7 + 6 + 6 + 5 + 6 + 5 + 5 + 4; ....

def fab(n: Int): Int = {
  if(n <= 1) 1
  else fab(n - 1) + fab(n - 2)
}

default parameters

In Scala, sometimes when we call some functions, we do not want to give the specific value of the parameter, but want to use the default value of the parameter itself. In this case, we define the default parameter when defining the function.

def sayHello(firstName: String, middleName: String = "William", lastName: String = "Croft") = firstName + " " + middleName + " " + lastName 

If insufficient parameters are given, the parameters will be applied in order from the action to the right.

The difference between Java and Scala implementation of default parameters

Java:

public void sayHello(String name, int age) {
  if(name == null) {
    name = "defaultName"
  }
  if(age == 0) {
    age = 18
  }
}
sayHello(null, 0)

Scala:

def sayHello(name: String, age: Int = 20) {
  print("Hello, " + name + ", your age is " + age)
}
sayHello("leo")

named parameter

When calling a function, you can also pass parameters not in the order of the parameters defined by the function, but by using named parameters.

sayHello(firstName = "Mick", lastName = "Nina", middleName = "Jack") 

It is also possible to mix unnamed and named parameters, but unnamed parameters must come before named parameters.

sayHello("Mick", lastName = "Nina", middleName = "Jack")

variable length parameter

In Scala, sometimes we need to define a function as a form with variable number of parameters, then we can use variable-length parameters to define functions.

def sum(nums: Int*) = {
  var res = 0
  for (num <- nums) res += num
  res
}

sum(1, 2, 3, 4, 5)

Using Sequence Calls with Variable Length Arguments

If you want to directly call a variable-length parameter function with an existing sequence, it is wrong. For example val s = sum(1 to 5). At this point, you need to use Scala's special syntax to define parameters as sequences, so that the Scala interpreter can recognize them. This syntax is very useful! It must be a good idea to use it a lot in spark's source code.

val s = sum(1 to 5: _*)

Case: Accumulation using recursive function

def sum2(nums: Int*): Int = {
  if (nums.length == 0) 0
  else nums.head + sum2(nums.tail: _*)
}

Process

In Scala, when defining a function, if the function body is directly wrapped in curly braces without using = connection, the return value type of the function is Unit. Such functions are called procedures. Procedures are often used for functions that do not need to return a value.

There is another way to write the procedure, which is to define the return value type of the function as Unit.

def sayHello(name: String) = "Hello, " + name
def sayHello(name: String) { print("Hello, " + name); "Hello, " + name }
def sayHello(name: String): Unit = "Hello, " + name

lazy value

In Scala, the feature of lazy value is provided, that is, if a variable is declared as lazy, the expression corresponding to the variable will only be evaluated when the variable is used for the first time. This feature is especially useful for particularly time-consuming computing operations, such as opening files for IO, doing network IO, etc.

import scala.io.Source._
lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString

Even if the file does not exist, no error will be reported, only the first time the variable is used will report an error, which proves the lazy nature of expression calculation.

val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
def lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString

abnormal

In Scala, the exception handling and catching mechanism is very similar to Java.

try {
  throw new IllegalArgumentException("x should not be negative")
} catch {
  case _: IllegalArgumentException => println("Illegal Argument!")
} finally {
  print("release resources!")
}

try {
  throw new IOException("user defined exception")
} catch {
  case e1: IllegalArgumentException => println("illegal argument")
  case e2: IOException => println("io exception")
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325946562&siteId=291194637