如何将Scala链式操作代码改写为合规的for-comprehension表达式
问题根源分析
你的实现不符合Scala for推导式的语法约定,核心问题有3个:
- 缺少
yield关键字:Scala的for推导式如果需要返回计算结果,必须在代码块末尾加yield声明返回值;不带yield的for推导式会被编译器识别为执行副作用的逻辑,默认调用容器的foreach方法,而foreach返回值为Unit,自然不符合你要获取返回结果的需求。 map方法签名不符合规范:for推导式要求容器类的map方法必须返回相同类型的容器实例,而不是直接返回容器内的原始值。你定义的map直接返回Instance实例,没有用包装类包裹,导致for推导式的类型链断裂,无法正常编译。- 缺少
flatMap方法实现:如果for推导式中存在多行<-绑定操作,编译器会将其转换为flatMap的嵌套调用,你的包装类没有实现flatMap方法,无法支持多步串行绑定。
正确实现方案
首先修改包装类实现,符合Scala容器的函数式签名约定:
// 定义泛型单值包装类,适配for推导式的语法要求 case class Wrapper[A](value: A) { // 标准map签名:输入值转换函数,返回包裹新值的同类型容器 def map[B](f: A => B): Wrapper[B] = Wrapper(f(value)) // 标准flatMap签名:输入返回容器的转换函数,返回扁平化后的同类型容器 def flatMap[B](f: A => Wrapper[B]): Wrapper[B] = f(value) }
之后就可以用for推导式实现你要的串行逻辑:
val resultWrapper = for { instance <- Wrapper(instanceFactory.create()) result <- Wrapper(instance.ackForResult) } yield result // 取出最终计算结果 val result = resultWrapper.value
如果你只是要做简单的两步串行调用,没有异步、错误处理之类的额外需求,不需要额外套for推导式,直接写val result = instanceFactory.create().ackForResult即可。
内容的提问来源于stack exchange,提问作者Jelly
相关产品推荐
相关产品推荐

