Scala中如何组合无参函数?无参与有参函数组合报错排查
这个报错的核心原因是Scala中函数类型的层级设计:你用的compose是Function1(单参数函数)的专属方法,它只接受另一个单参数函数作为输入,但你的zeroArgFunc是Function0(无参函数),类型完全不匹配。
具体拆解
先看正常工作的那行代码:
val intAndThenString: Int => Unit = stringArgFunc compose intArgFunc
intArgFunc是Int => String(Function1[Int, String]),stringArgFunc是String => Unit(Function1[String, Unit])。Function1的compose方法逻辑是:把传入的函数的输出,作为当前函数的输入。这里intArgFunc输出String,正好匹配stringArgFunc的输入String,类型完全兼容,所以编译通过。
再看报错的那行:
val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
intArgFunc是Function1[Int, String],它的compose方法要求传入的函数必须是A => Int(也就是某个类型A作为输入、输出Int的单参函数)。但zeroArgFunc是() => Int(Function0[Int]),它没有输入参数,和A => Int的类型签名完全不匹配——编译器找不到符合要求的compose重载方法,所以抛出类型不匹配的错误。
修复方案
最简洁的方式是利用Function0的andThen方法,它专门支持把无参函数的输出传给下一个单参函数:
object Test extends App { val zeroArgFunc = () => 10 val intArgFunc = (i: Int) => s"hello $i" val stringArgFunc = (s: String) => println(s) val intAndThenString: Int => Unit = stringArgFunc compose intArgFunc // 修复后的代码:用andThen替代compose val zeroAndThenInt: () => String = zeroArgFunc andThen intArgFunc // 测试调用 println(zeroAndThenInt()) // 输出:hello 10 }
Function0的andThen方法定义是def andThen[A](g: R => A): () => A,意思是:先执行当前无参函数得到结果R,再把这个结果传给函数g,最终返回一个新的无参函数,执行它就会完成整个串联逻辑。
如果你非要用compose,可以手动把无参函数包装成接受Unit的单参函数(无参函数本质上可以看作接受Unit的函数):
// 把无参函数包装成Unit => Int的单参函数 val zeroAsSingleArg: Unit => Int = _ => zeroArgFunc() // 现在可以用compose了,得到Unit => String val zeroAndThenIntCompose: Unit => String = intArgFunc compose zeroAsSingleArg // 再包装成无参函数 val zeroAndThenInt: () => String = () => zeroAndThenIntCompose(())
不过这种方式多了一层包装,不如直接用andThen简洁。
内容的提问来源于stack exchange,提问作者egordoe

