Skip to content

Instantly share code, notes, and snippets.

@chockenberry
Created July 16, 2024 23:20
Show Gist options
  • Save chockenberry/d6c08e9916442d11a0c69fb01454c063 to your computer and use it in GitHub Desktop.
Save chockenberry/d6c08e9916442d11a0c69fb01454c063 to your computer and use it in GitHub Desktop.
Ugly Swift
import UIKit
enum Name {
case foo(Foo)
case bar(Bar)
struct Foo {
let name: String
}
struct Bar {
let count: Int
}
}
let names = [Name.foo(Name.Foo(name: "hello")), Name.bar(Name.Bar(count: 123)), Name.bar(Name.Bar(count: 999))]
// The goal: to get the first Name.Bar item from names, and more importantly, to make the code readable.
func firstBar_TakeOne(in names: [Name]) -> Name.Bar? {
if case let .bar(bar) = names.first(where: { name in
if case .bar(_) = name {
return true
}
return false
}) {
return bar
}
return nil
}
func firstBar_TakeTwo(in names: [Name]) -> Name.Bar? {
let initialResult: Name.Bar? = nil
let result = names.reduce(into: initialResult) { result, name in
guard result == nil else { return }
if case let .bar(bar) = name {
result = bar
}
}
return result
}
if let bar = firstBar_TakeOne(in: names) {
bar.count
}
if let bar = firstBar_TakeTwo(in: names) {
bar.count
}
@chriskrycho
Copy link

I would tend to reach for something like this:

let firstBar = names
    .lazy
    .compactMap({
        switch $0 {
        case let .bar(bar): bar
        default: nil
        }
    })
    .first;

The combination of .lazy and .first should mean you only iterate as far through the collection as you need to, and the result is an Optional<Name.Bar>.

@ezfe
Copy link

ezfe commented Jul 17, 2024

If you use the asBar or barValue helper values others have contributed above, you could then write it as:

return names.lazy.compactMap(\.asBar).first

and still get nearly optimal performance. A regular for loop will probably be marginally faster for small collections though but not by much.

@pyrtsa
Copy link

pyrtsa commented Jul 17, 2024

Watch out, the performance of that construct may surprise you: https://forums.swift.org/t/adding-firstas-to-sequence/36665/17

@chriskrycho
Copy link

Ahhhh, overloads fun. 🙃 The first(where: { _ in true }) hack is terrible, too 😂 but if abstracted over and provided with a very good explanatory comment, I guess I could live with it. 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment