# SE-0310: Effectful Read-only Properties

**URL:** <https://forums.swift.org/t/se-0310-effectful-read-only-properties/47401>\
**Category:** Proposal Reviews\
**Created:** [April 13, 2021, 10:18pm UTC](https://forums.swift.org/t/se-0310-effectful-read-only-properties/47401 "2021-04-13T22:18:32Z")\
**Posts on this page:** 1\
**Showing post:** 38

<div class="post-metadata">

**Author:** ![kavon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kavon/32/9774_2.png) [@kavon](https://forums.swift.org/u/kavon)\
**Post date:** [April 15, 2021, 6:40pm UTC](https://forums.swift.org/t/se-0310-effectful-read-only-properties/47401/38 "2021-04-15T18:40:33Z")

</div>

I'd like to shed some light on my reasoning for the syntax chosen in this proposal.

First, let's consider some of places for effects specifiers that have been discussed or considered for a [computed property](https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#grammar_variable-declaration):

```swift
<A> var prop: Type <B> {
  <C> get <D> { }
}

```

- **Position A** is primarily used by access modifiers like `private(set)` or declaration modifiers like `override`. The more "effecty" `mutating`/`nonmutating` is only allowed in Position C, which precedes the accessor declaration, just like a method within a struct. Also, I don't think there's a happy ordering of effects specifiers and the other modifiers in Position A: neither `override async throws var prop` nor `async throws override var prop` reads well to me. For functions, the effects specifiers appear _after_ the subject, not before it.

- **Position B** doesn't make any sense to me, because effects are only carried as part of a function type, not other types. I think it would be very confusing, leading people to think `Int async throws` is a type, when that is not. Strega had suggested we use an arrow syntax, such as `var prop async throws -> Bool { }`, but the arrow would suggest that accessing the property yields a function, when it will be a boolean. This gets even more confusing for properties that _are_ functions. At first glance, `var predicate async throws -> ((Int) async throws -> Bool) { }` looks like it returns a curried function.

- **Position C** is not bad; it's only occupied by `mutating`/`nonmutating`, but placing effects specifiers here is not consistent with the positioning for functions, which is after the subject. Since Position D is available, it makes more sense to use that instead of Position C.

- **Position D** is an unused place in the grammar, places the effects on the _accessor_ and not the variable or its type, and is consistent with where effects go on a function declaration, after the subject: `get throws` and `get async throws`, where `get` is the subject. In addition, this position is away from the variable so it prevents confusion between the _accessor's effects_ and the effects of a function being returned:

```swift
  var predicate: (Int) async throws -> Bool {
    get throws { /* ... */ }
}

```

The access of `predicate` may throw, but if it doesn't, it results in a function that is `async throws`. I can understand the desire to take advantage of the implicit-getter shorthand:

```swift
  var predicate: (Int) async throws -> Bool { /* ... */ }

```

but there's no good place for effects specifiers here, and I think that's OK. It's a short-hand / syntactic sugar, which necessarily has to trade some of its flexibility for conciseness. The full syntax for computed properties explicitly defines its accessors.

Now, let's move onto subscripts. I'll skip right to the major difference for subscripts, which is that they have a method-like header and support the implicit-getter short-hand, so that it resembles a method too:

```swift
class C {
  subscript(_ : InType) <E> -> RetType { /* ... */ }
}

```

**Position E** is a tempting place for effects specifiers for a subscript, but _subscripts are not methods_. They cannot be accessed a first-class function value with `c.subscript`, nor called with `c.subscript(0)`; they use an indexing syntax `c[0]`. Methods cannot be assigned to, but subscript index expressions can be. Thus, they are closer to properties that can accept an argument.

Much like the short-hand for get-only properties, I think trying to find a position for effects specifiers on the short-hand form of get-only subscripts (whether its Position E or otherwise) will trap us in a corner once writable subscripts can support effects. Why? Position E a logically valid spot in the full-syntax and the short-hand syntax, and creating an inconsistency between the two would be bad. Then, using Position E + the full syntax creates an opportunity for confusion in situations like this:

```swift
  subscript(_ i : Int) throws -> Bool {
    get async { }
    set { }
 }

```

Here, the only logical interpretation is that `set` is `throws` and `get` is `async throws`. The programmer needs to look in multiple places to add up the effects in their head when trying to determine what effects are allowed in an accessor. This may not seem so bad in this short example, but consider having to skip over a large `get` accessor definition to learn about _all_ of the effects the `set` accessor is allowed to have for this subscript, when you do not need to do that for a computed property.

So, I think that Position D should be the one true place where you can look to see whether there are effects for that type of accessor, both for subscripts and computed properties.

---

_[View the full topic](https://forums.swift.org/t/se-0310-effectful-read-only-properties/47401)._
