Is There an Kotlin Equivalent 'With' Function in Swift

Is there an Kotlin equivalent `with` function in Swift?

Unfortunately, no such functionality so far in Swift. However, similar functionality can be reached with the power of extensions:

protocol ScopeFunc {}
extension ScopeFunc {
@inline(__always) func apply(block: (Self) -> ()) -> Self {
block(self)
return self
}
@inline(__always) func with<R>(block: (Self) -> R) -> R {
return block(self)
}
}

This protocol and extension provides two inline functions, where one can be served to return processed object, and the other is strictly similar to with in Kotlin and other languages (Visual Basic supported in 90s).

Usage

Specify types which these functions should apply to:

extension NSObject: ScopeFunc {} 

apply:

let imageView = UIImageView().apply {
$0.contentMode = .scaleAspectFit
$0.isOpaque = true
}

Here we create an object and once the closure is executed, modified object is returned.

with:

imageView.with {
$0.isHidden = true
}

Works equal to with in Kotlin.

Originaly based on this source code.

NOTE:

Swift compiler is generally regarded as smart enough to decide whether or not a function should be inlined. Quite likely, these two would be inlined due to their relative compactness even without strictly specifying @inline (__always). Either way, you should know that this keyword does not affect the logic and the result of these, because inlining is about optimizing the program.

Kotlin collection functions equivalent in swift

Consider

var arr = [1,2,3]
let res = arr[0...1] // [1,2] sublist in kotlin
let fir = arr.first // optional(1) first in kotlin

Swift: Closure with receiver like kotlin equivalent?

I'm not familiar with Kotlin's lambda with receiver, but as far as I read Kotlin docs,

  • There's no direct equivalent in Swift
  • Same functionality can be achieved by adding a parameter or currying

But, in Swift, you cannot define an extension function on generic T where T is any type. So, something like your T.apply needs to be a global function with two arguments.

With currying, apply in Swift would be something like this:

func apply<T>(_ this: T, block: (T)->()->T) -> T {
return block(this)()
}

You can use it like this:

var result = apply("Abc") {this in {this.uppercased()+this.lowercased()}}
print(result) //->ABCabc

Kotlin takeIf statement equivalent in swift?

There isn't something like that in Swift, so we need to find a way to write a takeIf function ourselves.

In Kotlin, takeIf is available on everything, as an extension function on all T:

inline fun <T> T.takeIf(predicate: (T) -> Boolean): T?

In Swift, you can't write an extension on Any, so we can only make a global function:

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 })

If you are creative enough to think of an operator, you can turn this into an infix operator, similar to how the Kotlin takeIf is in between the receiver and the predicate.

// 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 }

Is there a Kotlin equivalent `object` in Swift?

It's a task of "make and forget" type. Just create the class and use it everywhere you need a singleton:

class Singleton {
private static var uniqueInstance: Singleton?

public static var instance: Singleton {
if Singleton.uniqueInstance == nil {
Singleton.uniqueInstance = self.init()
}

return Singleton.uniqueInstance!
}

required init() {}
}

class MyClass : Singleton {
var param: Int = 0
}

let instanceOfMyClass: MyClass = MyClass.instance as! MyClass
print(instanceOfMyClass.param) // prints 0

instanceOfMyClass.param = 5

let anotherInstanceOfMyClass: MyClass = MyClass.instance as! MyClass
print(anotherInstanceOfMyClass.param) // prints 5


Related Topics



Leave a reply



Submit