`public(get)`

In my experience, it is fairly common to declare a property which can be publicly read, but only internally modified. This is declared with the fairly lengthy incantation:

public internal(set) var x

I think it would make the intent clearer and more easily understood if we could instead write:

public(get) var x
20 Likes

I like your suggestion better. It also makes it clearer what should happen to modify (when we eventually stabilize it). In the first version, what you probably wanted was that modify is also not public, but it's not super obvious that the compiler will do the right thing (you can certainly hope that it does or go check the documentation!). In the second case, the meaning seems more unambiguous: only get should be public, everything else is not. That said, it's unclear if read is public in the second case. I would guess the answer is yes, but IDK there is some subtlety involved.

2 Likes

For the sake of language consistency, I think it would be a good idea to allow both accesslevel(get) and accesslevel(set). accesslevel alone would continue to implicitly apply for both get and set, though using all three would produce compile-time errors.

public struct Example { // default member access level of internal
  // public(get) public(set)
  public var first = 1

  // public(get) public(set)
  public(get) public(set) var second = 2

  // public(get) private(set)
  private public(get) var third = 3

  // error: ‘private(get)' modifier is redundant for a private property
  // error: 'private(set)' modifier is redundant for a private property
  private private(get) private(set) var fourth = 4

  // error: Internal property cannot have a public setter
  internal public(get) public(set) var fifth = 5

  // error: Property cannot have a private getter and a fileprivate setter
  private(get) fileprivate(set) var sixth = 6
}
4 Likes

+1, using private(set) is not as readable

It would also be great to have something like no(set) that doesn’t allow setting the variable outside of that line.
Because lazy let is not allowed it would allow you to do
private no(set) lazy var foo = “bar”

And then somewhere in the class self.foo = “” would be a compile error

Alternatively
private(get) lazy var foo = "bar" could imply no(set) but I think that’s less clear and less readable.

Isn't that what you really want then here?

1 Like

yes I would really prefer that, but it's not possible, if I remember correctly its because let means the property is set at initialisation and does not change. Whereas a lazy var is not set at init, only when it is first accessed. There are quite a few topic that discuss it better than I can remember

It means to who ? If this is to the user, it can be changed, that why Swift Evolution exists.

If this is to the compiler, it is probably possible to relax the parser to allow let in such case, and still continue to generate the same code than with var (so it would not break any optimiser or codegen assumption).

If we're adding meaning to let, it's probably better to holistically consider how it interacts with modifiers (lazy) and property wrappers (@Binding).

Sorry I’ve diverted the topic to lazy let. Another thread can be created to discuss it, or the previous threads found. This should be about the original post

We definitely need the "public(get)" access level modifier, even just to improve code readability. It is intuitive and won't brake the existing codebase, although it would be nice to have a fixing warning for the ugly "public internal(set)" in Xcode.

I’d be interested in writing an implementation for this, but I’ll need some guidance.

If someone could point me in the right direction for where to get started, I’d appreciate it.