我有一个我要创建的Chicken
和Egg
的列表。它们被定义为:
class Chicken (val name: String, e: => Egg) { lazy val child = e }
class Egg (val name: String, c: => Chicken) { lazy val parent = c }
并且必须懒惰地实例化一对,因为它们包含循环引用:
def fillBarn {
lazy val chicken: Chicken = new Chicken("abc", egg)
lazy val egg: Egg = new Egg("def", chicken)
}
我有一个我要创建的鸡肉/鸡蛋名称列表。不幸的是,以下内容无法编译:
val names = List("C1 E1", "C2 E2", "C3 E3")
val list = for {
Array(cn, en) <- names.map(_.split(" "))
lazy c: Chicken = new Chicken(cn, e)
lazy e: Egg = new Egg(en, c)
} yield (c, e)
但没有糖:
val list = names.map(_.split(" ")).map {
case Array(cn, en) =>
lazy val c: Chicken = new Chicken(cn, e)
lazy val e: Egg = new Egg(en, c)
(c, e)
}
现在可以说,在这个简单的情况下,如果没有for-expression,它会更好,但如果我确实想使用for-expression,我可以吗?
我也意识到,在这个简单的案例中,我可以在Chicken
块内构建Egg
和yield
个实例,但这通常不会成立,如果我想要根据实例做一些额外的过滤和映射。
答案 0 :(得分:5)
好吧,在这个(也可以说是在更高级的情况下),你总是可以调整fillBarn
方法来准确地提供你需要的东西(这是理解这种方法的唯一方法):< / p>
def fillBarn(c: String, e: String) = {
lazy val chicken: Chicken = new Chicken(c, egg)
lazy val egg: Egg = new Egg(e, chicken)
(chicken, egg)
}
然后
val list = for {
Array(cn, en) <- names.map(_.split(" "))
(c, e) = fillBarn(cn, en)
} yield (c, e)
当然,如果您愿意,则无需定义fillBarn
方法。你也可以在线进行:
val list = for {
Array(cn, en) <- names.map(_.split(" "))
(c, e) = {
lazy val chicken: Chicken = new Chicken(cn, egg)
lazy val egg: Egg = new Egg(en, chicken)
(chicken, egg)
}
} yield (c, e)
Scala中for
语句的一般结构是固定的。只有flatMap
/ map
/ foreach
与<-
或直接分配给新的变量名称,以便稍后与=
一起使用。但是在这些语句的右侧,只要此块返回适当的对象,您就可以在块中放置任何您喜欢的内容。