所以我有这个非常简单的代码:
#include <iostream>
int hcf(int n1, int n2);
int main() {
int n1, n2, n3;
std::cout << " Insert 3 numbers: ";
std::cin >> n1 >> n2 >> n3;
std::cout << "HCF = " << hcf(n1, hcf(n2, n3));
return 0;
}
int hcf(int n1, int n2) {
while (n1 != n2) {
if (n1 > n2)
n1 -= n2;
else
n2 -= n1;
}
return n1;
}
而intellij说:
val a:() -> String = a@ {
while(true){
return@a "hello"
}
}
现在,如果我在函数中有相同的东西
Type mismatch.
Required: String
Found: Unit
完全没问题。
我也不能使用fun b():String {
while(true){
return "hello"
}
}
Callable
相同错误。我可以将其转换为对象清理:
val c : Callable<String> = Callable<String> {
while(true){
return@Callable "hello"
}
}
,并且有效。为什么在使用lambda时不起作用?
答案 0 :(得分:3)
原因是按照惯例,lambda的last语句是隐式返回,因此您的第一个块被视为类似这样的:
function a(): String {
return while (true) {
return "hello"
}
}
基本上可以理解为“返回while块的结果”,并被视为单位。
您可以改用匿名函数绕过此约定:
val a = fun(): String {
while (true) {
return "hello"
}
}
答案 1 :(得分:0)
在具有非Unit
返回类型的lambda中,最后一条语句必须为表达式。 while
不是表达式,因此Kotlin推断出代码块
while(true){
return@Callable "hello"
}
旨在返回Unit
。编译器不会做更深入的分析来推断这是一个带有非本地return语句的无限循环。
这样,您必须确保lambda的最后一行是类型String
的表达式。
我曾经为需要某种 type 但没有值的场景构建了一个辅助函数:
fun <T> declval(): T = throw IllegalStateException("Code should be unreachable")
它是根据C++ std::declval()建模的。因此,您的lambda可能是:
val a:() -> String = a@ {
while(true){
return@a "hello"
}
declval<String>()
}
但是,如果仅更改无限循环的控制流以产生一个退出点(例如,使用break
),可能会更容易理解。