77
class SomeClass {
  var someProperty: Int {
    throw Err("SNAFU")
  }
}

For code like the above, the swift binary complains 'error is not handled because the enclosing function is not declared 'throws'.

How do I declare that 'someProperty' 'throws' in the above?

class SomeClass {
  var someProperty throws: Int {
  }
}

and

class SomeClass {
  var someProperty: throws Int {
  }
}

and

class SomeClass {
  var someProperty: Int throws {
  }
}

don't seem to work.

math4tots
  • 8,540
  • 14
  • 58
  • 95

3 Answers3

104

This functionality is added for read-only computed properties in Swift 5.5 as part of SE-0310 (included in Xcode 13).

Based on SE-0310, the syntax would be:

class SomeClass {
  var someProperty: Int {
    get throws {
      throw Err("SNAFU")
    }
  }
}

Here is the previous answer for versions of Swift prior to 5.5:

You cannot throw from a computed property. You must use a function if you want to throw. The Declarations section of the Language Reference part at the end of The Swift Programming Language only lists throws (and rethrows) as a keyword for function and initializer declarations.

Charles A.
  • 10,685
  • 1
  • 42
  • 39
  • Thank you for the the language reference; it is pretty convincing. I realize this is not the original issue i asked, but in my scenario, I have a container type and I only want to implement 'hashValue' when each of the elements are themselves hashable. Do you happen to know what I can do to workaround this? – math4tots Oct 02 '15 at 01:59
  • Is it reasonable to make your container a generic type that only works with `Hashable` elements in the same way that swift `Dictionary` keys must be Hashable? If not I suppose you might have to do some work to come up with a hash function in the case that your elements aren't hashable since the `Hashable` `protocol` does not allow for a `nil` response and you can't `throw`. You could also use `fatalError()` if that's appropriate. – Charles A. Oct 02 '15 at 02:01
  • 1
    @math4tots This surely comes too late, but remember you can add extensions that constrain. For example, if you had a container defined like `struct Container {}` you could then add an extension like `extension Container where Element: Hashable {}` and define your computed property in the extension. The computed property will only be available if the `Element` type inside a `Container` instance is `Hashable`. – justinpawela Mar 21 '16 at 16:39
  • I don't think the Swift docs really spell this out, but check out "Type Constraints" and "Where Clauses" sections of the [Generics docs](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html). – justinpawela Mar 21 '16 at 16:40
61

While it's not possible (yet) to throw from computed properties in Swift, I found Chris Lattner himself adresses this very same question on one of Apple Developer Forums threads:

We agree that you should be able to mark the getters and setters as "throws" in subscripts and computed properties, but haven't gotten there yet. We are likely to support this at some time, but it isn't clear if it will make it in time for Swift 2.

paperlib
  • 736
  • 4
  • 6
3

Let me suggest a workaround: a property can be declared as having type of Result<DesiredPropertyType, Error>. This way it can be accessed like this:

do {
    try self.failableProperty.get()
} catch {
    ...
}

get() is a built-in method of Swift's Result.

UPDATE: this is getting addressed in Swift 5.5 with "effectful read-only properties": https://github.com/apple/swift-evolution/blob/main/proposals/0310-effectful-readonly-properties.md.

Nikolay Kasyanov
  • 897
  • 5
  • 14