3

I'm only interested in results with .success type that come from my query.

How can I set a filter to only pass through .success results from Result<Value> enum?

public enum Result<Value> {
    case success(Value)
    case failure(Error)
}


query.filter{ (result: Result<Double>) in
                switch result {
                case .success:
                    return true
                case .failure:
                    return false
                }
            }

I want to do shorthand check for success only, but compiler does not allow this.

.filter{result in
    return result == .success
}
Alex Stone
  • 46,408
  • 55
  • 231
  • 407
  • 1
    This is an unfortunate current shortcoming when working with enums with associated values – a common solution is to add a computed property to the enum to test for a given case. See for example https://stackoverflow.com/q/46005134/2976878. There have been a couple of fairly recent pitches looking to improve the situation: https://forums.swift.org/t/automatically-derive-properties-for-enum-cases/10843 and https://forums.swift.org/t/pitch-auto-synthesize-cases-for-enums/10075 – Hamish Sep 02 '18 at 13:28

1 Answers1

13

Here's a one-liner, not as short as you described, but shorter than the switch:

if case .success = result { return true } else { return false }

Enums with associated values need pattern matching, thus you need an if/switch/for/while to make that happen.

Alternatively, if you use this kind of filtering in multiple places, you could extend Result:

extension Result {
    var isSuccess: Bool { if case .success = self { return true } else { return false } }

    var isError: Bool {  return !isSuccess  }
}

, and use this extension:

query.filter { $0.isSuccess }

Or a functional approach, where isSuccess an isError are global functions:

func isSuccess<T>(_ result: Result<T>) -> Bool {
    if case .success = result { return true } else { return false }
}

func isError<T>(_ result: Result<T>) -> Bool {
    return !isSuccess(result)
}

// later in the code
query.filter(isSuccess)

The latter approach comes with a small performance benefit, as the compiler doesn't need to create another closure every time, and will use the one stored under the isSuccess name. Though it doesn't fully complies with the Swift conventions that recommend adding member functions instead of free ones.

Cristik
  • 30,989
  • 25
  • 91
  • 127