【问题标题】:Scala for comprehension vs. foreachScala 用于理解与 foreach
【发布时间】:2012-08-28 11:17:09
【问题描述】:

在 Scala shell 中我这样做了:

import java.util._
import scala.collection.JavaConversions._

val t: SortedMap[String,Int] = new TreeMap[String,Int] () // produces an empty java.util.SortedMap

t("a") = 1; t("b") = 2; t("A") = 3; t("0") = 4

t // prints: res35: java.util.SortedMap[String,Int] = {0=4, A=3, a=1, b=2}, as expected

t foreach println // also prints the (k,v) pairs in the same TreeMap sorted order

但是,以下语句并未按排序顺序打印对,它似乎按哈希桶顺序打印它们,(0,4) (b,2) (A,3) (a,1):

for ((k,v) <- t) printf("(%s,%d)%n", k, v)

在与 for 和 foreach 相关的其他答案中,似乎 for 理解应该转化为 foreach 的使用,如下所示:

"a for-comprehension for (p e0 }"

但这似乎不是这里发生的事情。

请注意,如果我从 scala TreeMap 创建一个 scala SortedMap,那么 foreach 和 for 都会按照我的预期按排序顺序生成 (k,v) 对. Java TreeMap 转换为 scala 的方式似乎有所不同。

关于为什么会出现这种差异的任何 cmets 或想法?

【问题讨论】:

    标签: scala


    【解决方案1】:

    嗯,p(k,v) 不是一回事。您的理解翻译如下:

    t.filter{
      case (k, v) => true
      case _      => false
    }.map {
      case (k, v) => printf("(%s,%d)$n")
    }
    

    一旦filter 将它的手放在 java 集合上,它就会变成 Scala 集合,并且不再排序。

    附带说明,在 Scala 2.10 上,上述内容不再适用,因为它在编译时检测到静态类型中没有不是 (k,v) 的元素,并且不生成过滤器。这里:

    scala> for ((k,v) <- t) printf("(%s,%d)%n", k, v)
    <console>:15: warning: dead code following this construct
                  for ((k,v) <- t) printf("(%s,%d)%n", k, v)
                             ^
    (0,4)
    (A,3)
    (a,1)
    (b,2)
    
    scala> import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe._
    
    scala> reify{for ((k,v) <- t) printf("(%s,%d)%n", k, v)}
    res4: reflect.runtime.universe.Expr[Unit] =
    Expr[Unit](scala.collection.JavaConversions.mapAsScalaMap(t).foreach(((x$1) => x$1: @unchecked match {
      case scala.Tuple2((k @ _), (v @ _)) => scala.this.Predef.printf("(%s,%d)%n", k, v)
    })))
    

    PS:比起JavaConversions,更喜欢JavaConverters

    【讨论】:

    • 谢谢,丹尼尔,很好的回答!
    • @BobYacobellis 我只是让它变得更好。 :-)
    • 我看到我真正想要的语句是这样的:for (kv &lt;- t) printf("(%s,%d)%n", kv._1, kv._2)
    • 更好的说法是for (kv &lt;- t) println(kv)
    猜你喜欢
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 2014-11-03
    • 2011-11-16
    • 1970-01-01
    • 2017-07-18
    相关资源
    最近更新 更多