在最近接触Python后,我开始欣赏它的条件表达式的可读性,形式为
当经典的三目运算符?:将条件作为第一个参数时,它感觉像是赋值全部都是关于选择的。当你尝试嵌套多个三目运算符时,它变得很丑陋... 当条件移动到第一个表达式之后时,它更像是函数的数学定义。我发现这有时可以帮助提高代码清晰度。
当您在空格方面有创意时,它甚至会感觉有点类似于Python编程语言。
X if C else Y
。当经典的三目运算符?:将条件作为第一个参数时,它感觉像是赋值全部都是关于选择的。当你尝试嵌套多个三目运算符时,它变得很丑陋... 当条件移动到第一个表达式之后时,它更像是函数的数学定义。我发现这有时可以帮助提高代码清晰度。
作为代码编程训练的一员,我想在Swift中实现Python风格的条件表达式。似乎唯一能给我所需语法的工具是自定义运算符。它们必须由符号组成。Unicode中的数学符号将逻辑中的双turnstile符号标记为TRUE ⊨
,其被划掉的版本是NOT TRUE ⊭
… 所以我选择了==|
和|!=
。到目前为止,在为正确的优先级而斗争了一段时间后,我有了这个:
// Python-like conditional expression
struct CondExpr<T> {
let cond: Bool
let expr: () -> T
}
infix operator ==| : TernaryPrecedence // if/where
infix operator |!= : TernaryPrecedence // else
func ==|<T> (lhs: @autoclosure () -> T, rhs: CondExpr<T>) -> T {
return rhs.cond ? lhs() : rhs.expr()
}
func |!=<T> (lhs: Bool, rhs: @escaping @autoclosure () -> T) -> CondExpr<T> {
return CondExpr<T>(cond: lhs, expr: rhs)
}
我知道结果看起来不太流畅或易读,但好的一面是,即使表达式跨越多行,这些运算符也能正常工作。
let e = // is 12 (5 + 7)
1 + 3 ==| false |!=
5 + 7 ==| true |!=
19 + 23
当您在空格方面有创意时,它甚至会感觉有点类似于Python编程语言。
let included =
Set(filters) ==| !filters.isEmpty |!=
Set(precommitTests.keys) ==| onlyPrecommit |!=
Set(allTests.map { $0.key })
我不喜欢第二个自动闭包必须进行转义。 Nate Cook在Swift 2中自定义三元运算符的回答使用了柯里化语法,但在Swift 3中已经不再使用... 我猜那也是一个需要转义的闭包。
有没有办法在不使用转义闭包的情况下使其工作?这真的很重要吗?也许Swift编译器足够聪明,在编译时解决它,所以它不会在运行时产生影响?
return rhs ?? lhs()
。 - Martin R