- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在处理字符串,遇到了Regex or Wildcard答案:可以使用自定义类覆盖等号将正则表达式放入when
语句中。虽然这确实有效地使用了类型系统将语法糖插入when
语句中,但我发现以下情况非常丑陋,并且永远不会在我打算与其他开发人员共享的代码中这样做(引用travis):
import kotlin.text.regex
when (RegexWhenArgument(uri)) {
Regex(/* pattern */) -> /* do stuff */
Regex(/* pattern */) -> /* do stuff */
/* etc */
}
class RegexWhenArgument (val whenArgument: CharSequence) {
operator fun equals(whenEntry: Regex) = whenEntry.matches(whenArgument)
override operator fun equals(whenEntry: Any?) = (whenArgument == whenEntry)
}
when
然后引用对arg类型进行操作的函数将更具可读性。举一个人为的例子:
// local declaration
val startsWithFn: (String) -> Boolean = {s -> s.startsWith("fn:")}
when(givenString) {
::startsWithHelp -> printHelp()
startsWithFn -> println("Hello, ${givenString.substring(3)}!")
}
// package level function
fun startsWithHelp(s:String) = s.startsWith("help", true)
最佳答案
您的问题有很多解决方案。我将从简单的开始,然后继续讨论更复杂的部分。
没有争论的时候
Kotlin documentation说:
when
can also be used as a replacement for anif
-else if
chain. If no argument is supplied, the branch conditions are simply boolean expressions, and a branch is executed when its condition is true
when {
startsWithHelp(givenString) -> printHelp()
startsWithFn(givenString) -> println("Hello, ${givenString.substring(3)}!")
}
(givenString)
RegexWhenArgument
,但是不检查
Regex
而是调用
(String) -> Boolean
。
String
没什么特别的,所以我将使用
<T>
。
fun <T> whenArg(arg: T) = object {
override fun equals(other: Any?) =
if (other is Function1<*, *>)
(other as Function1<T, Boolean>)(arg)
else arg == other
}
when (whenArg(givenString)) {
::startsWithHelp -> printHelp()
startsWithFn -> println("Hello, ${givenString.substring(3)}!")
}
when
分支中使用infix fun <T> ((T) -> Boolean).and(other: ((T) -> Boolean)) = { it: T -> invoke(it) && other(it) }
infix fun <T> ((T) -> Boolean).or(other: ((T) -> Boolean)) = { it: T -> invoke(it) || other(it) }
operator fun <T> ((T) -> Boolean).not() = { it: T -> !invoke(it) }
when
模拟
@DslMarker
annotation class WhichDsl
// This object is used for preventing client code from creating nested
// branches. You can omit it if you need them, but I highly recommend
// not to do this because nested branches may be confusing.
@WhichDsl
object WhichCase
// R type parameter represents a type of expression result
@WhichDsl
class Which<T, R>(val arg: T) {
// R? is not used here because R can be nullable itself
var result: Holder<R>? = null
inline operator fun ((T) -> Boolean).invoke(code: WhichCase.() -> R) {
if (result == null && invoke(arg)) result = Holder(code(WhichCase))
}
// else analog
inline fun other(code: WhichCase.() -> R) = result?.element ?: code(WhichCase)
}
data class Holder<out T>(val element: T)
inline fun <T, R> which(arg: T, @BuilderInference code: Which<T, R>.() -> R) =
Which<T, R>(arg).code()
which(givenString) {
::startsWithHelp { printHelp() }
startsWithFn { println("Hello, ${givenString.substring(3)}!") }
}
val int = which(givenString) {
::startsWithHelp { 0 }
startsWithFn { 1 }
other { error("Unknown command: $givenString") }
}
@BuilderInference
的用法(可以用用于表达式的显式类型声明和用于语句的单独方法代替)inline fun <R> Which<*, R>.orThrow(message: () -> String) =
other { throw NoWhenBranchMatchedException(message()) }
val <R> Which<*, R>.orThrow get() = orThrow { "No branch matches to $arg" }
inline fun <T, R> Which<T, R>.branch(condition: (T) -> Boolean, code: WhichCase.() -> R) =
condition(code)
inline fun <T, R> Which<T, R>.case(value: T, code: WhichCase.() -> R) =
branch({ it == value }, code)
fun <T : CharSequence, R> Which<T, R>.regex(regex: Regex, code: WhichCase.() -> R) =
branch({ regex.matches(it) }, code)
fun <T : Comparable<T>, R> Which<T, R>.range(range: ClosedRange<T>, code: WhichCase.() -> R) =
branch({ it in range }, code)
inline fun <T> Which<T, *>.sideBranch(condition: (T) -> Boolean, code: WhichCase.() -> Unit) {
if (condition(arg)) code(WhichCase)
}
fun <T> Which<T, *>.sideCase(value: T, code: WhichCase.() -> Unit) =
sideBranch({ it == value }, code)
inline fun <R> Which<*, R>.dropResult(condition: WhichCase.(R) -> Boolean = { _ -> true }) {
result?.let { (element) ->
if (WhichCase.condition(element)) result = null
}
}
inline fun <T, R> Which<T, R>.subWhich(condition: (T) -> Boolean, code: Which<T, R>.() -> R) =
branch(condition) {
which(this@subBranch.arg, code)
}
关于kotlin - 在Kotlin `when`语句(或其他分支构造)中将函数或lambda作为条件包括在内的最简洁方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58001124/
我正在用 C# 编写动态语言的解释器,并将原始函数实现为具有虚拟 Apply 方法的抽象类 Primitive,其中每个实际原始函数都是重写 Apply 的子类。 (另一种方法是只拥有类 Primit
我正在用 C# 编写动态语言的解释器,并将原始函数实现为具有虚拟 Apply 方法的抽象类 Primitive,其中每个实际原始函数都是重写 Apply 的子类。 (另一种方法是只拥有类 Primit
我是 Dapper 的新手我正在尝试了解它实际上是如何映射事物的。我有以下数据库结构: calendar | Id | Name | meeting_room | Id | Calendar_id
抱歉问题标题很糟糕。有没有办法在一行中做到这一点: Button button = (Button)Gridview.Cells[0].FindControl("controlname"); butt
在 Java 中在声明点和使用点声明列表/数组文字的tersest方法是什么? 作为次要问题,我更喜欢一种不会导致编译时警告或要求抑制警告的方法。 注意:就我个人而言,这是针对Java 8ish on
什么是现代、简洁、快速的方法来测试节点是否有任何与给定选择器匹配的子节点? “简洁”是指类似于 jQuery 或函数式风格,例如避免循环。我知道本地选择器越来越多地使用这种类型的东西,但没有跟上发展的
getFirstNotNullResult 执行函数列表,直到其中一个函数返回非空值。 如何更优雅/简洁地实现 getNotNullFirstResult? object A { def main
根据 stackoverflow 上某人的推荐,我使用了 jquery succint https://github.com/micjamking/Succinct截断我在 php 网站上的帖子。 它
我是一名优秀的程序员,十分优秀!