【发布时间】:2021-10-28 18:16:11
【问题描述】:
所以我正在为集合制作正则表达式(所有量词都是所有格)。它看起来像这样(请记住,为了便于阅读,示例被过度简化了):
val mayBeAPerson: Boolean = "totally not a person"
.toList()
.matches { // this: PatternScope
one { it.isUpperCase() } // execution of lambda could end after this method
moreThan(0) { it.isLetter() }
one { it == ' ' }
lessThan(2) { // this: PatternScope
one { it.isUpperCase() }
one { it == '.' }
one { it == ' ' }
}
one { it.isUpperCase() }
moreThan(0) { it.isLetter() }
}
如您所见,传递给 matches 的 lambda 的执行可能会在第一个 one 之后结束,因为传递给它的谓词与 List 中的第一个字符不匹配。它确实结束了。但是,我的解决方案与优雅相反,因为它使用在 one 中抛出异常并在 matches 中捕获它。
fun List<Char>.matches(build: PatternScope.() -> Unit) = try {
val scope = PatternScope(iterator())
scope.build() // may throw MatchFailed
!scope.iterator.hasNext()
} catch (_: MatchFailed) {
false
}
class PatternScope(private val iterator: Iterator<Char>) {
inline fun one(predicate: (element: Char) -> Boolean) {
if (!iterator.hasNext() || !predicate(iterator.next())) {
throw MatchFailed("match failed")
}
}
.
. etc
.
}
它完全有效,但我不禁想知道:有没有更好的方法?我知道抛出这样的异常只是一个花哨的GOTO,我可以将PatternScope 的所有方法包装在ifs 中,如下所示:
class PatternScope(private val iterator: Iterator<Char>) {
private var matchFailed = false
inline fun one(predicate: (element: Char) -> Boolean) {
if (!matchFailed) {
if (!iterator.hasNext() || !predicate(iterator.next())) {
matchFailed = true
}
}
}
inline fun moreThan(n: Int, predicate: (element: Char) -> Boolean) {
if (!matchFailed) {
// logic
}
}
.
. etc
.
}
它更优雅吗?现在我正在调用传递给matches 的lambda 中的所有函数,老实说,我更不喜欢它。
我真正的问题是:有更好的方法吗?从 lambda 返回的一些神奇解决方案我什至没有真正的访问权限?一些非本地返回,但从函数 lambda 甚至还没有看到?
我可以通过调用其体内的某些函数从 lambda 返回吗?
编辑
澄清一下,假设我们有一个 lambda:
val lambda: () -> Unit = {
someMethod() // this should return from lambda (in some cases)
someOtherMethod() // this shouldn't be invoked
}
someMethod 的主体应该是什么样子,这样someOtherMethod 在调用 lambda 时甚至不会执行?除了让someMethod 抛出异常并将lambda 包装在try-catch 块中,还有其他方法吗:
try {
lambda() // throws
} catch (_: SomeThrowableIdk) { }
我没有找到更好的方法,但请证明我错了。
【问题讨论】:
-
请标记所使用的语言。
-
我不太明白你在问什么,但内联函数中有非本地返回,请参阅this
标签: kotlin lambda return higher-order-functions control-flow