Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call ambiguous method?

Tags:

swift

xcode6

given this code

extension Array {
    func filter(includeElement: (T) -> Bool) -> T[] {
        var ret = T[]()
        for e in self {
            if includeElement(e) {
                ret += e
            }
        }
        return ret
    }
}

var a = [1,2]
var b = a.filter() {i in print(i); return true}

it can't compile with error message

error: ambiguous use of 'filter'
var b = a.filter() {i in print(i); return true}
        ^
Swift.Array<T>:84:8: note: found this candidate
  func filter(includeElement: (T) -> Bool) -> Array<T>
       ^
<REPL>:30:10: note: found this candidate
    func filter(includeElement: (T) -> Bool) -> T[] {
         ^

so looks like I am allowed to create extension method with duplicated method and signature, but I somehow need a special way to call it


BTW, default Array.filter is broken, it calls the closure twice for each element and crashes REPL or give your rubbish result in playground if the result is inconsistent

xiliangchen-imac:~ xiliangchen$ xcrun swift
Welcome to Swift!  Type :help for assistance.
  1> let arr = [1,2,3,4,5]
arr: Int[] = size=5 {
  [0] = 1
  [1] = 2
  [2] = 3
  [3] = 4
  [4] = 5
}
  2> var i = 0
i: Int = 0
  3> let arr2 = arr.filter() {
  4.         println($0)
  5.         return i++ < 5
  6. }   
Segmentation fault: 11
like image 623
Bryan Chen Avatar asked Oct 31 '22 22:10

Bryan Chen


1 Answers

There is no problem with defining ambiguous methods, I think. The problem arises when you import 2 ambiguos methods from different modules. Unfortunately, there is no way how to exclude the Array.filter from being imported.

I did some tests and it appears to me the behavior for ambigious definitions is not well defined, for example:

extension NSString {
    func hasPrefix(aString: String!) -> Bool {
        return false
    }
}

let string: NSString = "test"

var hasPrefix = string.hasPrefix("t")
println("Has prefix: \(hasPrefix)") //prints "true"

var method = string.hasPrefix
hasPrefix = method("t")

println("Has prefix: \(hasPrefix)") //prints "false"

The behavior could be different for obj-c classes...

For functions, it appears the definition from current module is preferred:

func NSStringFromCGPoint(point: CGPoint) -> String! {
    return "My method"
}

var point = CGPoint(x: 10.0, y: 10.0)

println("Point: \(NSStringFromCGPoint(point))") //Prints "My method"
println("Point: \(UIKit.NSStringFromCGPoint(point))") //Prints "{10, 10}"
like image 86
Sulthan Avatar answered Nov 23 '22 04:11

Sulthan