Kotlin "takeIf"语句等价于swift?



我在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
}
}
}

最新更新