[swift-evolution] [Draft] scope-based submodules

Brent Royal-Gordon brent at architechies.com
Thu Mar 2 22:08:02 CST 2017


> On Mar 1, 2017, at 11:56 AM, David Hart <david at hartbit.com> wrote:
> 
>> 2. Normally, references within the module to submodule symbols need to be prefixed with the submodule name. (That is, in top-level `Foo` code, you need to write `Bar.Baz` to access `Foo.Bar.Baz`). As a convenience, you can import a submodule, which makes the submodule's symbols available to that file as though they were top-level module symbols.
>> 
>> 3. When you import a submodule, you can mark it with `@exported`; this indicates that the symbols in that submodule should be aliased and, if `public` or `open`, re-exported to other modules.
> 
> Could you explain this in more detail?

Let's say you're writing the `WorldOptimization` module, and you have a `SpimsterWicket` submodule with a public `WicketShell` type. In the main `WorldOptimization` module, you could write:

	class Optimizer: Person {
		var wicketShell: SpimsterWicket.WicketShell?
		…
	}

But if you don't want to write out the name of the `SpimsterWicket` submodule, you could import it:

	import WorldOptimization.SpimsterWicket
	
	class Optimizer: Person {
		var wicketShell: WicketShell?
		…
	}

Outside the `WorldOptimization` module, of course, you'd still need to write `import WorldOptimization.SpimsterWicket` to get access to the `WicketShell` type. (Or perhaps importing `WorldOptimization` would allow you to access it as `SpimsterWicket.WicketShell`--it's an open question.) On the other hand, if `WorldOptimization` instead included:

	@exported import WorldOptimization.SpimsterWicket
	
	class Optimizer: Person {
		var wicketShell: WicketShell?
		…
	}

Then anyone who imported `WorldOptimization` could access `WicketShell` directly, as though they too had explicitly imported `WorldOptimization.SpimsterWicket`.

>> I think we need to go back to first principles here. The reason to introduce a new access level is that we believe that a submodule is a large enough unit of code that it will simultaneously need to encapsulate some of its implementation details from other submodules, *and* have some of its own implementation details encapsulated from the rest of the submodule.
> 
> That's where I disagree. Why would Swift need that level of differentiation and not C# or Java, which have had packages and namespaces without it.

C# has friend assemblies <https://msdn.microsoft.com/en-us/library/0tke9fxk(v=vs.100).aspx>, PublisherIdentityPermission <http://stackoverflow.com/questions/13697390/restricting-the-use-of-an-assembly-from-assemblies-that-are-not-signed>, and similar security mechanisms to restrict access to certain APIs. I have not been able to locate similar features in Java; instead, people seem to recommend circuitous design patterns to make up for it: <http://wiki.apidesign.org/wiki/APIDesignPatterns:FriendPackages>

More broadly, though? Swift is trying to reach to lower levels than C# or (particularly) Java usually do. If we're serious about Swift as a systems language, and we're also serious about the kind of careful layering that Apple's OSes are known for, we need some way to expose SPIs to higher layers. And it'd be good if that were built into the language.

-- 
Brent Royal-Gordon
Architechies



More information about the swift-evolution mailing list