Scala for循环中<-与=的差异及报错原因解析
完整代码整理
先把你的代码整理成可阅读的格式,方便分析:
主代码:
class user(var name:String,var id:Int, var gender:Option[String]) { override def toString="("+ name+","+id+","+gender+")" } object a { def main(args:Array[String]):Unit={ var mm=Map(1-> new user("jh",189,Some("Male")),2->new user("gh",12,None),3 ->new user("io",100,Some("Female"))) def getkey(i:Int)= { mm.get(i) }
代码1(嵌入main方法):
var b=for{ h<-getkey(1) i<-h.gender } yield i print(b) // 推测你这里应该是print(b),i是推导式内的局部变量 } }
代码2(嵌入main方法):
var b=for{ h<-getkey(1) i=h.gender } yield i print(b) } }
1. 为什么代码1和代码2输出不同?
核心差异在于Scala for推导式中**<-和=的本质区别**:
- 代码1里的
i<-h.gender:<-是对h.gender(类型为Option[String])做生成器遍历,相当于调用flatMap——它会“剥开”Option的外壳,提取里面的实际值(也就是"Male")。最终yield i得到的是Option[String],即Some("Male"),打印出来就是Some(Male)。 - 代码2里的
i=h.gender:=只是普通赋值,直接把h.gender这个Option[String]原样赋值给i。外层的h<-getkey(1)已经是Option[user]的遍历,所以yield i会把Option[String]再包装一层Option,最终得到Option[Option[String]],也就是Some(Some("Male"))。
简单说:<-会处理Option的结构,取出内部值;=只是原样传递,不会改变结构。
2. 把getkey(1)前的<-换成=会报错的原因?
getkey(1)返回的是Option[user]类型。如果写成h=getkey(1),那么h的类型就是Option[user],而不是user对象本身。
接下来你尝试访问h.gender时,Option[user]这个类并没有gender属性——gender是user类的成员,所以编译器会直接报错,提示找不到gender这个符号。
3. for循环中<-的作用是什么?
在Scala的for推导式里,<-被称为生成器(Generator),核心作用有这些:
- 遍历所有支持“展开”的结构(比如
Option、List、Set、Future等实现了Monad特性的类型); - 把结构内部的元素提取出来,供推导式后续代码使用;
- 对
Option这类单元素结构来说,<-相当于安全解包:如果是Some(x),就取出x继续执行;如果是None,整个推导式直接返回None,不会走后续逻辑。
本质上,<-是map、flatMap、filter这些函数式方法的语法糖,让代码看起来像传统循环,同时保留函数式编程的安全性和简洁性。
内容的提问来源于stack exchange,提问作者Therii
相关产品推荐
相关产品推荐

