Scala for the Impatients---(2)Control Structures and Functions

An expression has a value; a statement carries out an action.

Conditional Expressions: IF-ELSE

In Scala, an if / else has a value. For example: if (x > 0) 1 else -1 or val s = if (x > 0) 1 else -1 has a value of 1 or -1 , depending on the value of x . 

Java and C++ have a ?: operator for this purpose: x > 0 ? 1 : -1

In Scala, every expression has a type. For example:

if (x > 0) 1 else -1 has a type of Int.

if (x > 0) "positive" else -1 has a type of Any.

if (x > 0) 1 has a type of Int or Unit(no value).

Statement Termination

if you want to have more than one statement on a single line, you need to separate them with semicolons, else semicolons are optional. For example

if (n > 0) { r = r * n; n -= 1 }

Block Expressions and Assignments

In Scala, a { } block contains a sequence of expressions, and the result is also an expression. The value of the block is the value of the last expression. For example: val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }. The value of the { } block is the last expression, shown here in bold.

However, since in Scala, assignments have no value or a Unit value, so a block that ends with an assignment statement, such as { r = r * n; n -= 1 } has a Unit value. Therefore, x = y = 1 is wrong!

Input and Output

scala> println("Answer: " + 42)
Answer: 42

Loops

WHILE:

FOR: traverse Integers

where 1 to n equals to 1.to(n). For a Scala collection, such as a Range , the loop makes i assume each value in turn.

FOR: traverse Strings

 

OR

In Scala, loops are not used as often as in other languages. You can often process the values in a sequence by applying a function to all of them, which can be done with a single method call.

Advanced for Loops and for Comprehensions

(1)multipe generators in FOR separated by semicolons.

scala> for (i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ")
11 12 13 21 22 23 31 32 33

(2)Each generator can have a guard.

scala> for (i <- 1 to 3; j <- 1 to 3 if i != j) print((10 * i + j) + " ")//if i!=j is a guard
12 13 21 23 31 32 

(3)You can have any number of definitions, introducing variables that can be used inside the loop.

scala> for (i <- 1 to 3; from = 4 - i; j <- from to 3) print((10 * i + j) + " ")
13 22 23 31 32 33 

(4)If starts with yield , then the loop constructs a collection of values.

scala> for (i <- 1 to 10) yield i % 3
res36: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)

This type of loop is called a for comprehension. The generated collection is compatible with the first generator. Like

scala> for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar
res37: String = HIeflmlmop

scala> for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar
res38: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p)

Functions

Scala has functions in addition to methods. A method operates on an object【1.to(0)这里的to就operates on a Int object】, but a function doesn’t【a function 像java中的static 方法,遵循functional programming的思想】. 

(1)You must specify the types of all parameters: def abs(x: Double) = if (x >= 0) x else -x

(2)The last expression of the block becomes the value that the function returns:

 

(3)If the function is a recursive function, you must specify the return type:  def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1).  Otherwise Scala compiler couldn’t verify that the type of n * fac(n - 1) is an Int.

Default and Named Arguments(参数默认值)

def decorate(str: String, left: String = "[", right: String = "]") =left + str + right

You can also specify the parameter names when you supply the arguments:decorate(left = "<<<", str = "Hello", right = ">>>"). Note that the named arguments need not be in the same order as the parameters.

Variable Arguments: the number of arguments is not fixed

def sum(args: Int*) = {
var result = 0
for (arg <- args) result += arg
result
}

You can call this function with as many arguments as you like: val s = sum(1, 4, 9, 16, 25)

If you already have a sequence of values, you cannot pass it directly to such a function: val s = sum(1 to 5) // Error. But

val s = sum(1 to 5: _*) // Consider 1 to 5 as an argument sequence

Procedures

Procedure differentiates from function in that a procedure has no = symbol. 

You call it for its side effect. For example, the following procedure prints a string inside a box, like 

-------
|Hello|
-------

def box(s : String) { // Look carefully: no =
val border = "-" * s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}

Lazy Values

When a val is declared as lazy , its initialization is deferred until it is accessed for the first time. For example, 

lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString

If the program never accesses words , the file is never opened.

You can think of lazy values as halfway between val and def . Compare

val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString // Evaluated as soon as words is defined

lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString // Evaluated the first time words is used

def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString // Evaluated every time words is used

Exceptions

 

posted on 2016-04-18 13:56  chaseblack  阅读(158)  评论(0编辑  收藏  举报

导航