Pitch: Fully-Qualified Lookups

My expectation upon reading this is that it would also make the top-level import unnecessary (only for that line). I'm not sure if that's a feature or an anti-feature.

1 Like

Iā€™d like to point out that (import Swift).dump would imply the existence of (import func Swift.dump).


If we made the parentheses optional, then we could avoid the parentheses awkwardness problem:

import func Swift.dump(thing)
let zipSequence = import func Swift.zip(sequence0, sequence1)
1 Like

OK, but isnā€™t this adding too much complexity? The syntax you proposed combines an import declaration and a function call expression into the same construct.

I donā€™t find the second example at all compelling. have two special syntactic features (fully-qualified lookups and module aliases) for this niche problem space feels redundant.

Of the two, fully-qualified lookups seem strictly more powerful, but aliasing (especially if it uses import Foo as Bar syntax) seems easier to understand, especially when stumbling upon it for the first time.

1 Like

@elsh pointed me to an updated proposal for module aliases, which reflects a change in focus for that feature: solving the problem of two upstream SwiftPM packages that export modules with the same name. As such, module aliases are currently envisioned as a SwiftPM feature, not a Swift language feature.

It is a bit complex, yes. More importantly, however, we'd also have to resolve this ambiguity:

import Foundation
import var MyModule.someGlobalVariable // is this accessing this variable or is it just importing it?

We could resolve this (for example, if the statement is at the top of the file and there are no surrounding parentheses, then it just imports), but the solution would probably be too complex.


I still think (module Swift).dump or (import Swift).dump would be the best syntax. While the parentheses are a bit awkward, this feature probably won't be used very often anyways.

I like the brevity of the original suggestion. What about !Swift.dump() as a way to force lookup from the root? Or do you think thatā€™s too much for the ! symbol?

That would create instant and irreconcilable ambiguity the first time it was used to invoke a function that returns Bool.

5 Likes

@elsh pointed me to an updated proposal for module aliases , which reflects a change in focus for that feature: solving the problem of two upstream SwiftPM packages that export modules with the same name. As such, module aliases are currently envisioned as a SwiftPM feature, not a Swift language feature.

Module aliasing in the proposal is more of an infrastructure that involves changes in the language which will allow new syntax such as import X as Y in the future (as described in future directions); SwiftPM will provide a user interface that will allow easier use of module aliasing although a direct invocation of compiler commands will allow it too.

Like most people in the thread I agree that there's a problem to be solved and glad to see it tracked, but am not a fan of _. especially given the established meaning of _ elsewhere in Swift.

What about ^. instead?

With ^ feeling like a nice sygil to represent the "root" / "global namespace" to me :slightly_smiling_face:

^, like many symbols previously suggested, is currently a valid operator character in Swift. In the presence of prefix operator ^, it would not be possible to lexically disambiguate ^.top_level_var from ^.static_member.

Could there be implicit module aliases?

  • Either in the namespace containing all modules.
  • Or as a member of all types, protocols, and functions.
import XCTest

// error: type 'XCTest' has no member 'XCTestCase'
XCTest.XCTestCase.self

// OK
$XCTestModule.XCTestCase.self

// OK
XCTest.$Module.XCTestCase.self

Iā€™m unable to construct a case where a static member access on an operator is syntactically valid; even ^.self isnā€™t valid (and this applies in cases where there are no overloads to consider).

As such, I donā€™t see how this is a serious problem; if static member access on operators becomes desirable in future, we can disambiguate with parentheses or backticks.

@ksluder isn't referring to a static member of an operator; rather:

prefix operator ^

prefix func ^ (x: Float) -> Double {
    return Double(x)
}

^.infinity // Double.infinity

Not only is it possible to write something like this, -.infinity is perhaps the most idiomatic way of writing -inf in Swift.

6 Likes

Aha.

This suffers the same problem as $Root:

1 Like