scala - 如何组成一个零参数函数?
问题描述
我想要实现的是将 2 个函数(其中一个是无 arg 函数)组合为一个。
这是一个示例,可以让您了解我在做什么:
object Test extends App {
val zeroArgFunc = () => 10
val intArgFunc = (i: Int) => s"hello $i"
val stringArgFunc = (s: String) => println(s)
// This line works perfectly fine.
val intAndThenString: Int => Unit = stringArgFunc compose intArgFunc
// But this line fails with 'type mismatch' compilation error.
val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
}
编译错误:
[error] found : () => Int
[error] required: ? => Int
[error] val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
[error] ^
[error] one error found
知道有什么问题吗?
[UPD] Scala 版本是 2.13.1(如果重要的话)。
解决方案
脱糖() => 10
我们有
new Function0[Int] { def apply() = 10 }
并且Function0
没有compose
orandThen
方法
trait Function0[... +R] extends ... { ...
def apply(): R
override def toString(): String = "<function0>"
}
所以它似乎Function0
无法组成。
另一方面(i: Int) => s"hello $i"
,(s: String) => println(s)
对应于Function1
哪个确实compose
定义了方法,因此可以组合它们。
考虑更改() => 10
to (_: Unit) => 10
which 将类型从 更改Function0
为Function1
,然后
(intArgFunc compose zeroArgFunc)()
输出res4: String = hello 10
。
解决@Duelist 的评论,恕我直言Function0[T]
,在语义上不等同于Function1[Unit, T]
. 例如,给定
val f = () => 10
val g = (_: Unit) => 10
然后
f()
g()
确实输出
res7: Int = 10
res8: Int = 10
然而
f(println("woohoo")) // error: no arguments allowed for nullary method apply
g(println("woohoo")) // OK!
我们看到两者的行为不同。不过,如果您想将它们视为等价的,也许您可以定义一个扩展方法Function0
并明确转换,例如
implicit class Fun0ToFun1[A, B](f: () => A) {
def toFun1: Unit => A = (_: Unit) => f()
}
将允许以下语法
(intArgFunc compose zeroArgFunc.toFun1)()
解决@egordoe 的评论,开箱compose
即用只为 定义Function1
,因此Function2
,Function3
等不能像Function0
. 但是我们可以在函数上定义扩展composeN
方法,例如,假设我们想用 组合Function1
,Function0
那么
implicit class ComposeFun1WithFun0[A, B](f1: A => B) {
def compose0(f2: () => A): () => B = () => f1(f2())
}
给
(intArgFunc compose0 zeroArgFunc)()
推荐阅读
- typescript - 为什么在使用 then 和 catch 的 Promise 链接中不会捕获错误
- eigen - 具有不完整 Cholesky 预处理器的共轭梯度返回 Eigen 库的错误
- python - 使用条件合并日期范围内日期的两个数据框
- android - navigateUp() 和 navigate(action_id) 未按预期工作
- c++ - 编译期间我的项目中缺少 DLL
- oracle - 如何优化需要超过 200 秒的两个 3 秒查询的 Oracle UNION ALL ......即使使用 rownum
- postgresql - 在 PG 12 或 PG 13 中声明系统触发器名称
- android - 如何将 Firestore 中的数据与 2 个设备连接在 1 个集合中同步?
- c# - 如何检查我正在覆盖的单个异步 C# 任务的布尔返回值?
- javascript - 添加 IceCandidate 是强制性的吗?