Scala---For語句段

For語句段
語法:
Expr1 ::= for (( Enumerators ) | { Enumerators
}) {nl} [yield] Expr
Enumerators ::= Generator {semi Enumerator}
Enumerator ::= Generator
| Guard
| val Pattern1 = Expr
Generator ::= Pattern1 <- Expr [Guard]
Guard ::= if PostfixExpr
for語句段for (enums) yield e對於由枚舉器enums產生的每個綁定求值表達式e。一個枚舉器序列總是由一個產生器開始;然後可跟其他產生器,值定義,或守衛。一個產生器 p <- e從一個與模式p匹配的表達式e產生綁定。值定義val p = e將值名稱p(或模式p中的數個名稱)綁定到表達式e的求值結果上。守衛if e包含一個布爾表達式,限制了枚舉出來的綁定。產生器和守衛的精確含義通過翻譯爲四個方法的調用來定義:map filter flatMap和foreach。這些方法可以針對不同的攜帶類型具有不同的實現。
翻譯框架如下。在第一步裏,每個產生器p <- e,對於e的類型被替換爲如下形式,p不是不可反駁的(§8.1):
p <- e.filter { case p => true; case _ => false }
然後,以下規則將重複應用,直到所有的語句段都消耗完畢。
for語句段 for (p <- e) yield e被翻譯爲e.map { case p => e }
for語句段 for (p <- e) e 被翻譯爲e.foreach { case p => e }
for語句段 for (p <- e; p <- e ...) yield e, 這裏...是一個產生器或守衛序列(可能爲空),該語句段翻譯爲 e.flatMap { case p => for(p <- e ...) yield e }
for語句段 for (p <- e; p <- e ...) e
這裏... 是一個產生器或守衛序列(可能爲空),該語句段翻譯爲 e.foreach { case p => for (p <- e ...) e }
後跟守衛if g的產生器p <- e翻譯爲單個產生器p <- e.filter((x1,...,xn) => g),這裏x1,...,xn是p的自由變量。
後跟值定義val p = e的產生器 p <- e翻譯爲以下值對產生器,這裏的x和x是新名稱: val (p, p) <- for (x@p <- e) yield { val x@p = e; (x, x) }
示例6.19.1 以下代碼產生1到n-1間所有和爲素數的數值對
for { i <- 1 until n
j <- 1 until i
if isPrime(i+j)
} yield (i, j)
該for語句段翻譯爲:
(1 until n)
.flatMap {
case i => (1 until i)
.filter { j => isPrime(i+j) }
.map { case j => (i, j) }
示例6.19.2 for語句段可以用來簡明地描述向量和矩陣算法。比如以下就是一個函數來計算給定矩陣的轉置:
def transpose[A](xss: Array[Array[A]]) = {
for (i <- Array.range(0, xss(0).length)) yield
for (xs <- xss) yield xs(i)
}
以下是一個函數,用來計算兩個向量的無向量積:
def scalprod(xs: Array[Double], ys: Array[Double]) = {
var acc = 0.0
for ((x, y) <- xs zip ys) acc = acc + x * y
acc
}
最後,這是一個求兩個矩陣的積的函數。可以與示例 6.15.1中的常見版本做一個比較
def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]] = {
val ysst = transpose(yss)
for (xs <- xss) yield
for (yst <- ysst) yield
scalprod(xs, yst)
}

以上代碼使用了類scala.Array中已有定義的成員map, flatMap, filter和foreach。

更多精彩內容請關注:http://bbs.superwu.cn 

關注超人學院微信二維碼:

關注超人學院java免費學習交流羣:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章