Skip to content

Instantly share code, notes, and snippets.

@paulofaria
Last active January 24, 2017 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save paulofaria/f48d0b847a0fb7c125d163d0e349500a to your computer and use it in GitHub Desktop.
Save paulofaria/f48d0b847a0fb7c125d163d0e349500a to your computer and use it in GitHub Desktop.

Problem

ModuleA

extension String {
    public func capitalized() -> String {
        return "ModuleA"
    }
}

ModuleB

extension String {
    public func capitalized() -> String {
        return "ModuleB"
    }
}

ModuleC

import ModuleA
import ModuleB

let capitalized = "hello swift".capitalized()
print(capitalized)

Output

error: ambiguous use of 'capitalized()'
let capitalized = "hello swift".capitalized()
                  ^
ModuleA.String:2:17: note: found this candidate
    public func capitalized() -> String
                ^
ModuleB.String:2:17: note: found this candidate
    public func capitalized() -> String
                ^

Proposal #2

ModuleC

import ModuleA precedence 100 // to avoid a new keyword we can use the existing "precedence" keyword, but precendece is not the best word to describe what's happening here.
import ModuleB // default precedence is 0.

let capitalizedA = "hello swift".capitalized() // will default to the higher precedence implementation.
print(capitalizedA) // prints "ModuleA".

let capitalizedB = "hello swift".capitalized() from ModuleB // if we want to override the default we can use "from" keyword to disambiguate.
print(capitalizedB) // prints "ModuleB".

Proposal #3

ModuleC

import ModuleA priority 100 // better, because its priority is explicit.
import ModuleB // default priority is 0.

let capitalizedA = "hello swift".capitalized() // will default to the higher priority implementation.
print(capitalizedA) // prints "ModuleA".

let capitalizedB = "hello swift".capitalized() from ModuleB // if we want to override the default we can use "from" keyword to disambiguate. 
print(capitalizedB) // prints "ModuleB".

Proposal #4

ModuleC

import ModuleA // there's no default implementation or priority concept.
import ModuleB // all usages of ambigous properties/methods have to be disambiguated on call site.

let capitalizedA = "hello swift".capitalized() from ModuleA // use "from" keyword to disambiguate. 
print(capitalizedA) // prints "ModuleA".

let capitalizedB = "hello swift".capitalized() from ModuleB // use "from" keyword to disambiguate. 
print(capitalizedB) // prints "ModuleB".

Proposal #5

ModuleC

import ModuleA // there's no default implementation or priority concept.
import ModuleB // all usages of ambigous properties/methods have to be disambiguated on call site.

let capitalizedA = "hello swift".capitalized()@ModuleA // use @ symbol to disambiguate. 
print(capitalizedA) // prints "ModuleA".

let capitalizedB = "hello swift".capitalized()@ModuleB // use @ symbol to disambiguate. 
print(capitalizedB) // prints "ModuleB".

Chaining

ModuleC

import ModuleA
import ModuleB

// the application of "from" keyword in chaining would be the same as the "as" keyword.
let stringB = ("hello swift".capitalized() from ModuleB).lowercased()
print(stringB) // prints "moduleb".

let stringB = "hello swift".capitalized()@ModuleB.lowercased()
print(stringB) // prints "moduleb".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment