If you really want to, you could always:
prefix operator <-
prefix func <-<T>(_ v: T) -> (T, T) { (v, v) }
prefix func <-<T>(_ v: T) -> (T, T, T) { (v, v, v) }
prefix func <-<T>(_ v: T) -> (T, T, T, T) { (v, v, v, v) }
// (And so on if/as needed …)
which will enable you to eg:
let (a, b, c, d) = <-"hello"
print(a) // "hello"
print(b) // "hello"
print(c) // "hello"
print(d) // "hello"
and more specifically:
let (a, b, c) = <-{ () -> UIStackView in
let sv = UIStackView()
sv.axis = .vertical
sv.distribution = .fillEqually
return sv
}()
And if you add this:
typealias X2<T> = (T, T)
typealias X3<T> = (T, T, T)
// (And so on if/as needed …)
The slightly annoying "() -> UIStackView in
" can be skipped and you can write:
let (a, b, c) : X3<UIStackView> = <-{
let sv = UIStackView()
sv.axis = .vertical
sv.distribution = .fillEqually
return sv
}()
Or, you could add this:
protocol Withable: AnyObject {}
extension Withable {
func with(_ op: (Self) -> Void) -> Self { op(self); return self }
}
extension UIStackView: Withable {}
to be able to just write:
let (a, b, c) = <-UIStackView()
.with { $0.axis = .vertical }
.with { $0.distribution = .fillEqually }
But note that, just as in your original example, all three a
, b
and c
will reference the same UIStackView
instance, ie:
print(a === b, a === c) // true true
This is probably not what you want.
A minor change to the <-
operator (making it take a () -> T
closure instead of a T
value, execute that and return its result) fixes this issue.
So, the complete solution becomes:
// --- These two general tools ---
protocol Withable: AnyObject {}
extension Withable {
func with(_ op: (Self) -> Void) -> Self { op(self); return self }
}
prefix operator <-
prefix func <-<T>(_ g: () -> T) -> (T, T) { (g(), g()) }
prefix func <-<T>(_ g: () -> T) -> (T, T, T) { (g(), g(), g()) }
prefix func <-<T>(_ g: () -> T) -> (T, T, T, T) { (g(), g(), g(), g()) }
// (And so on if/as needed …)
// --- Makes it possible to do this ---
extension UIStackView: Withable {}
let (a, b, c) = <-{
UIStackView()
.with { $0.axis = .vertical }
.with { $0.distribution = .fillEqually }
}