I would like to propose a change to the default access modifier within an 
enclosing scope.  The default for top level definitions would stay internal, 
but anything within a scope would by default have the same visibility as it’s 
enclosing scope.

The main reason for this is readability/maintainability, and having the 
intention clearly stand out.  It would also reduce a great amount of 
boilerplate.  It also matches the mental model of how scopes normally work 
regarding inheritance of visibility/properties (which means less to teach 
newbies).

Right now if I want to make a type and all of it’s vars/methods public, I have 
to mark each individual var/method public, which leads to a lot of 
boilerplate/noise and makes everything harder to read:

        public struct MyStruct {
                public var a:Int
                public var b:Int
                private var c:Int
                public var d:Int
        }

Notice that the private var doesn’t really stand out as such very well.  Also, 
it is exceedingly rare (at least in my own coding style) that I actually want 
an internal variable unless the type itself is internal, and in those cases, I 
would like that choice to stand out as deliberate the same way I want ‘private' 
to stand out.  As it stands, I wait until I think I am done modifying a type to 
mark it public because of the extra noise generated.  I also make a point to 
write ‘internal' for things that I explicitly want to restrict to internal.

Consider the alternative:

        public struct MyStruct {
                var a:Int
                var b:Int
                private var c:Int
                var d:Int
        }

Now the fact that I have chosen to make ‘c’ private really stands out much 
better.  When revisiting the code in 6 months, the struct is much more 
“glance-able” (as a friend of mine likes to say).

Note also the nuance that I didn’t say that those vars were marked public (or 
had the same modifier), I said that they had the SAME VISIBILITY as the 
enclosing scope (which in this case happens to be public).  This is a concept 
which is hard to express currently, and IIRC this is what we had to do to make 
the edge cases of swift 3’s private modifier work properly.  

Basically, it already works this way for ‘private’, ‘fileprivate’, & 
‘internal’, just not for ‘public’ or ‘open’… which can be surprising, 
especially since you don’t discover these differences until you are working 
across modules.  We should just extend that mental model up to include public 
and open.  Migration would just take internal variables of public/open types 
and mark them explicitly with the word ‘internal'.

Thanks,
Jon

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to