我在kotlin中有一个非常简单的代码,如果满足某个条件,则返回一个值,或者null
val speed = location.speed.takeIf { it>=0 }
我试图在swift中做同样的事情,但我发现的唯一方法是:
let speed:Double?
if (location.speed>=0){
speed = location.speed
}else{
speed = nil
}
还有更优雅的方法吗?
在Swift中没有这样的东西,所以我们需要自己想办法写一个takeIf
函数。
在Kotlin中,takeIf
可以在所有上使用,作为所有T
的扩展函数:
inline fun <T> T.takeIf(predicate: (T) -> Boolean): T?
在Swift中,你不能在Any
上写扩展,所以我们只能做一个全局函数:
func take<T>(_ value: T, if predicate: (T) throws -> Bool) rethrows -> T? {
try predicate(value) ? value : nil
}
// example usage:
let x = Int.random(in: 0..<10)
let y = take(x, if: { $0 > 5 })
如果你有足够的创造力来考虑一个操作符,你可以把它变成一个中接操作符,类似于KotlintakeIf
在接收者和谓词之间的方式。
// I am not creative enough...
infix operator ???
func ???<T>(value: T, predicate: (T) throws -> Bool) rethrows -> T? {
try predicate(value) ? value : nil
}
let a = Int.random(in: 0..<10)
let b = x ??? { $0 > 5 }
这不是语言内置的,但您可以添加它。
public extension Optional {
/// Transform `.some` into `.none`, if a condition fails.
/// - Parameters:
/// - isSome: The condition that will result in `nil`, when evaluated to `false`.
func filter(_ isSome: (Wrapped) throws -> Bool) rethrows -> Self {
try flatMap { try isSome($0) ? $0 : nil }
}
}
let speed = location.speed.filter { $0 >= 0 }
为什么不试试
let speed: Double? = location.speed >= 0 ? location.speed : nil
Swift仍然支持? :
if检查,像Java一样,Kotlin不支持,除非你写一个if () else
。
注::如果速度为0,您确定要返回一个可选值而不是0吗?
您可以将其作为具有默认实现的协议来实现。那么只要让任何类型都符合这个协议。
protocol Takable {
func takeIf(_ condition: (Self) throws -> Bool) rethrows -> Self?
}
extension Takable {
func takeIf(_ condition: (Self) throws -> Bool) rethrows -> Self? {
try condition(self) ? self : nil
}
}
// Example:
struct Test: Takable {
let val: Int
}
let t = Test(val: 1)
let a = t.takeIf { $0.val == 1 } // not nil
let b = t.takeIf { $0.val == 2 } // nil
你可以为Double做扩展,像这样:
extension Double {
func takeIf() -> Double? {
if self >= 0 {
return self
} else {
return nil
}
}
}