0515.反覆迭代(Iterate)

反覆迭代(Iterate)

Scala 的 for 語句同樣也是一個 函數  ! - WisdomFish.ORG

反覆一個容器(Container)內容, 在 Java 我們大多數的時間使用者 for 迴圈來處理, 事實上 Scala 在這方面更優於 Java,
  1. Scala 善用本身的類型推論(Type Inference)本能來簡化您的思維
  2. Scala 除了讓您可以使用傳統的 for 迴圈, 更可以使用俱 FP(函數編程) 的技巧來迭代容器內容.


for (arg <- args)


for循環並不是語法,而是被定義為稱作 for-comprehension 的語法蜜糖,最後被轉換成 map 和 filter 等方法的組合。

fish 在此被視為創建一個 val 而不是 var, 在 <- 右邊是一個連績值 產出器表達式(Generator Expression), 每次都連績性產出一個 val 來進行初始化, 
for (fish <- 1 to 5) {
println(fish)
}

for (fish <- 1 to 5) println(fish)

for (fish <- 1 to 5)
    println(fish)

for (i <- List(1, 2)) {
    println(i)
}





foreach


foreach( ) 是 Range 類的方法

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

args.foreach( arg -> println(arg) )

List(1, 2) foreach { i => println(i) }

scala> (1 to 10) foreach(i => print(i))
12345678910




map / yield


scala> List(1, 2) map { i => i + 10 }
res12: List[Int] = List(11, 12)

scala> for (i <- List(1, 2)) yield {         
     | i + 10                                
     | }
res13: List[Int] = List(11, 12)


Effective Method



Lambda and closure

foreach :: map :: reduce :: flatMap :: filter

Search

groupBy :: distinct :: exists :: forall :: contains

Sort

sortBy

Partition

grouped :: partition :: slice :: splitAt

Operation

max :: maxBy :: min :: minBy :: count :: sum

Option

find :: headOption 

String

mkString

Examples








Iterate with foreach and for

Although you may not have realized it, when you wrote the while loops in the previous step, you were programming in an imperative style. In the imperative style, which is the style you would ordinarily use with languages like Java, C++, and C, you give one imperative command at a time, iterate with loops, and often mutate state shared between different functions or methods. Scala enables you to program imperatively, but as you get to know Scala better, you'll likely often find yourself programming in a more functional style. In fact, one of the main aims of the Scalazine will be to help you become as competent at functional programming as you are at imperative programming, using Scala as a vehicle.

One of the main characteristics of a functional language is that functions are first class constructs, and that's very true in Scala. For example, another (far more concise) way to print each command line argument is:

args.foreach(arg => println(arg))

In this code, you call the foreach method on args, and pass in a function. In this case, you're passing in an anonymous function (one with no name), which takes one parameter named arg. The code of the anonymous function is println(arg). If you type the above code into a new file named pa.scala, and execute with the command:

scala pa.scala Concise is nice

You should see:

Concise
is
nice

In the previous example, the Scala interpreter infers type of arg to be String, since Strings are what the array on which you're calling foreach is holding. If you'd prefer to be more explicit, you can mention the type name, but when you do you'll need to wrap the argument portion in parentheses (which is the normal form of the syntax anyway). Try typing this into a file named epa.scala.

args.foreach((arg: String) => println(arg))

Running this script has the same behavior as the previous one. With the command:

scala epa.scala Explicit can be nice too

You'll get:

Explicit
can
be
nice
too

If instead of an explicit mood, you're in the mood for even more conciseness, you can take advantage of a special case in Scala. If an anonymous function consists of one method application that takes a single argument, you need not explicitly name and specify the argument. Thus, the following code also works:

args.foreach(println)

To summarize, the syntax for an anonymous function is a list of named parameters, in parentheses, a right arrow, and then the body of the function. This syntax is illustrated in Figure 1.



Figure 1. The syntax of a Scala anonymous function.

Now, by this point you may be wondering what happened to those trusty for loops you have been accustomed to using in imperative languages such as Java. In an effort to guide you in a functional direction, only a functional relative of the imperative for (called a for comprehension) is available in Scala. While you won't see their full power and expressiveness in this article, we will give you a glimpse. In a new file named forprintargs.scala, type the following:

for (arg <- args)
println(arg)

The parentheses after the for in this for comprehension contain arg <- args. To the left of the <- symbol, which you can say as 「in」, is a declaration of a new \@val@ (not a \@var@) named arg. To the right of <- is the familiar args array. When this code executes, arg will be assigned to each element of the args array and the body of the for, println(arg), will be executed. Scala's for comprehensions can do much more than this, but this simple form is similar in functionality to Java 5's:

// ...
for (String arg : args) { // Remember, this is Java, not Scala
System.out.println(arg);
}
// ...

or Ruby's

for arg in ARGV   # Remember, this is Ruby, not Scala
puts arg
end

When you run the forprintargs.scala script with the command:

scala forprintargs.scala for is functional

You should see:

for
is
functional


Comments