0516.判斷式迴圈(Loop)

Loop
「Scala 中的 for 表達式對於迭代就像一把瑞士軍刀」- Martin Odersky
  • foreach( )
    • 用於對容器提供內置迭代器
  • for 表達式
    • for()
    • for-yield
    • for { }
  • if( )
與 Java 等不同的是,Scala 中有產生器(generator)的概念
  • 1 to 10
  • 1 until 10

for( )



scala> for ( i <- 1 to 3) { println("Ho " + i) }
Ho 1
Ho 2
Ho 3


for([pattern <- generator; definition*]+; filter*)
  [yield] expression


for-yield


yield 關鍵字,用於將 for 迭代過程內容, 合成一個集合保存起來,語法:

for {子句} yield {循環體}


scala> val result = for ( i <- 1 to 10 ) i + 2      
result: Unit = ()

scala> val result = for ( i <- 1 to 10 ) yield i + 2
result: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

scala> val f = for ( x <- 2 to 9; y <- 2 to 9 ) yield x * y
f: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 6, 8, 10, 12, 14, 16, 18, 6, 9, 12, 15, 18, 21, 24, 27, 8, 12, 16, 20, 24, 28, 32, 36, 10, 15, 20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42, 48, 54, 14, 21, 28, 35, 42, 49, 56, 63, 16, 24, 32, 40, 48, 56, 64, 72, 18, 27, 36, 45, 54, 63, 72, 81)




list comprehension

對值空器的如同 SQL 查詢, 在 FP 中稱之.

map( ) / filter( )

scala> val result = (1 to 10).map( _ + 2)
result: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

scala> val doubleEven = for ( i <- 1 to 10 ; if i % 2 == 0 ) 
     | yield i * 2
doubleEven: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 8, 12, 16, 20)

scala> val d = (1 to 10).filter( _ % 2 == 0 ).map( _ * 2)
d: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 8, 12, 16, 20)



for { }


scala> val d = 
     | for {
     | i <- 1 to 10
     | if i % 2 == 0
     | }    
     | yield i * 2
d: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 8, 12, 16, 20)








if (boolean)
  true
  false

if (Boolean) true else false

if (Boolean) {
  true ...
} else {
  false
}



  • while ( ) { }
  • if ( ) { }


Loop with while, decide with if

You write while loops in Scala in much the same way you do in Java. Try out a while by typing the following into a file name printargs.scala:

var i = 0
while (i < args.length) {
println(args(i))
i += 1
}

This script starts with a variable definition, var i = 0. Type inference gives i the type scala.Int, because that is the type of its initial value, 0. The while construct on the next line causes the block (the code between the curly braces) to be repeatedly executed until the boolean expression i < args.length is false. args.length gives the length of the args array, similar to the way you get the length of an array in Java. The block contains two statements, each indented two spaces, the recommended indentation style for Scala. The first statement, println(args(i)), prints out the ith command line argument. The second statement, i += 1, increments i by one. Note that Java's ++i and i++ don't work in Scala. To increment in Scala, you need to say either i = i + 1 or i += 1. Run this script with the following command:

>scala printargs.scala Scala is fun

And you should see:

Scala
is
fun

For even more fun, type the following code into a new file named echoargs.scala:

var i = 0
while (i < args.length) {
if (i != 0)
print(" ")
print(args(i))
i += 1
}
println()

In this version, you've replaced the println call with a print call, so that all the arguments will be printed out on the same line. To make this readable, you've inserted a single space before each argument except the first via the if (i != 0) construct. Since i != 0 will be false the first time through the while loop, no space will get printed before the initial argument. Lastly, you've added one more println to the end, to get a line return after printing out all the arguments. Your output will be very pretty indeed.

If you run this script with the following command:

>scala echoargs.scala Scala is even more fun

You'll get:

Scala is even more fun

Note that in Scala, as in Java, you must put the boolean expression for a while or an if in parentheses. (In other words, you can't say in Scala things like if i < 10 as you can in a language such as Ruby. You must say if (i < 10) in Scala.) Another similarity to Java is that if a block has only one statement, you can optionally leave off the curly braces, as demonstrated by the if statement in echoargs.scala. And although you haven't seen many of them, Scala does use semi-colons to separate statements as in Java, except that in Scala the semi-colons are very often optional, giving some welcome relief to your right pinky finger. If you had been in a more verbose mood, therefore, you could have written the echoargs.scala script as follows:

var i = 0;
while (i < args.length) {
if (i != 0) {
print(" ");
}
print(args(i));
i += 1;
}
println();

If you type the previous code into a new file named echoargsverbosely.scala, and run it with the command:

> scala echoargsverbosely.scala In Scala semicolons are often optional

You should see the output:

In Scala semicolons are often optional

Note that because you had no parameters to pass to the println method, you could have left off the parentheses and the compiler would have been perfectly happy. But given the style guideline that you should always use parentheses when calling methods that may have side effects—coupled with the fact that by printing to the standard output, println will indeed have side effects—you specified the parentheses even in the concise echoargs.scala version.

One of the benefits of Scala that you can begin to see with these examples, is that Scala gives you the conciseness of a scripting language such as Ruby or Python, but without requiring you to give up the static type checking of more verbose languages like Java or C++. Scala's conciseness comes not only from its ability to infer both types and semicolons, but also its support for the functional programming style, which is discussed in the next step.

Comments