tera
January 5, 2025, 12:13pm
1
I don't want to spam the "Last expression as return value" thread as this is orthogonal.
Could we make the else branch of if expressions optional?
let x: Int? = if condition { 42 }
to mean the same as:
let x: Int? = if condition { 42 } else { nil }
Example:
let items: [Int] = (0 ..< 20).compactMap { i in
if (i % 2) == 0 {
i
}
}
print(items) // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
This change is additive.
3 Likes
You can achieve something similar with an extension on Bool
already now:
extension Bool {
func ifTrue<T>(_ value: @autoclosure () -> T) -> T? {
self ? value() : nil
}
}
With this extension you can write code like
print(true.ifTrue(1)) // Optional(1)
print((4 % 2 == 0).ifTrue("4 is even")) // Optional("4 is even")
print((3 % 2 == 0).ifTrue("3 is even")) // nil
print((3 % 2 == 0).ifTrue("3 is even") ?? "3 is odd") // 3 is odd
Without @autoclosure
you can even create a syntax that's very close to what you propose.
2 Likes
Danny
January 5, 2025, 5:33pm
3
Optionals already have too much special treatment and I wouldn't like them getting even more, but I'd still use this anyway. But only if the conditional operator is divorced from being ternary, as well.
let x: Int? = condition ? 42
tera:
let items: [Int] = (0 ..< 20).compactMap { i in
if (i % 2) == 0 {
i
}
}
print(items) // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
This is filter
.
let items = (0..<20).filter { $0.isMultiple(of: 2) }
Optional.filter
is missing from the standard library.
let x = _?(42).filter(condition)
let items = (0 ..< 20).compactMap {
($0 as _?).filter { $0.isMultiple(of: 2) }
}
public extension Optional {
func filter<Error>(_ isSome: (Wrapped) throws(Error) -> Bool) throws(Error) -> Self {
try flatMap { wrapped throws(Error) in try isSome(wrapped) ? wrapped : nil }
}
func filter(_ isSome: Bool) -> Self {
filter { _ in isSome }
}
}
tera
January 5, 2025, 5:53pm
4
Danny:
This is filter
.
Sure, let's make it more interesting:
let items: [Int] = (0 ..< 20).compactMap { i in
if condition(i) {
transform(i)
}
}
1 Like
Danny
January 5, 2025, 6:17pm
5
Other @SimplyDanny has the right idea but it's expressible as an "?
overload" with different spelling.
let items = (0..<20).compactMap { condition($0) ??? transform($0) }
infix operator ???
func ??? <Wrapped>(isSome: Bool, wrapped: @autoclosure () -> Wrapped) -> Wrapped? {
isSome ? wrapped() : nil
}
1 Like