我试图将对象列表映射到另一种类型的对象列表,然后过滤该列表,然后映射到第三种类型的列表,就像我通过在Java 8+中链接流一样(更改了类和变量名以使其更有意义,但结构与我的代码相同)
val results: List<AccountDto> = listOfPersons
.map { person -> getPersonAccount(person) }
.filter { account ->
if(validateAccount(account)){ // validateAccount is a function with boolean return type
// do something here like logging
return true
}
// do something else...
return false
}
.map { account ->
toDto(account) // returns an AccountDto
}
我在过滤器lambda内的return true
和return false
语句上收到编译器错误:
Error:(217, 32) Kotlin: The boolean literal does not conform to the expected type List<AccountDto>
如果我对过滤谓词使用匿名函数,则可以正常编译:
.filter (fun(account):Boolean{
if(validateAccount(account)){
// do something here like logging
return true
}
// do something else...
return false
})
为什么在这种情况下类型推断会失败?
是否可以使我仅使用lambda起作用?
答案 0 :(得分:9)
return
从最近的封闭函数或匿名函数(格式为fun(a1: T1, ..., an: TN): TR = ...
)返回。助记符是不合格的return
到最近的fun
。 Lambda不是匿名函数,因此return
实际上是从包含整个map
/ filter
表达式的函数返回的。您可以使用带有标签的退货:
val results: List<AccountDto> = listOfPersons
.map(::getPersonAccount)
.filter { account ->
if(validateAccount(account)){
// etc.
return@filter true
}
// etc.
return@filter false
}
.map(::toDto)
lambda表达式使用传递给它的函数隐式标记,因此您无需显式添加标签。如果您希望拥有它,可以:
val results: List<AccountDto> = listOfPersons
.map(::getPersonAccount)
.filter lam@{ account ->
if(validateAccount(account)){
// etc.
return@lam true
}
// etc.
return@lam false
}
.map(::toDto)
但是if
/ else
本身就是一个表达式,因此只要没有return
就足够了。
val results: List<AccountDto> = listOfPersons
.map(::getPersonAccount)
.filter { account ->
if(validateAccount(account)) {
// etc.
true
} else {
// etc.
false
}
}
.map(::toDto)
答案 1 :(得分:4)
之所以会出现此错误,是因为lambda中的普通return
往往会从最外面的范围(函数本身)返回。
Lambda期望隐式返回(每个执行路径上的最后一个表达式)或显式标记返回return@filter
。
删除return
或用return@filter
替换将修复错误。