1

Consider the following code:

typealias PersonRecord = [String : AnyObject]

struct Person {
    let name: String
    let age: Int

    public init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

extension Person {
    init?(record : PersonRecord) {
        guard let name = record["name"] as? String,
        let age = record["age"] as? Int else {
            return nil
        }

        self.name = name
        self.age = age
    }
}

Now I want to create an array of Persons from an array of Records:

let records = // load file from bundle
let persons = records.flatMap(Person.init)

But I get the following error:

error: ambiguous reference to member 'init(name:age:)'

If I move the failable initializer out of the extension, I still get the same error.

What am I missing here, is this not a correct usage of flatMap?

EDIT - solved:

Found the error: the code that read in the records file from disk, returned the wrong type. Once I fixed that, the error went away.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
koen
  • 5,383
  • 7
  • 50
  • 89
  • 1
    Compiles fine for me, assuming `records` is of type `[PersonRecord]`. As with all weird compiler errors, try cleaning your build folder – and if you're in a playground, try it in a full project. – Hamish Oct 22 '16 at 19:22
  • That's good to know; I moved that code to a brand new PlayGround, and no errors. How do I clean the build folder for a playground, if any? – koen Oct 22 '16 at 19:44
  • I don't believe you can (at least not easily) in a playground. Personally, I would avoid using playgrounds to begin with, as they're notoriously buggy – a full project is a much better Swift environment. – Hamish Oct 22 '16 at 19:56
  • Hmm, I moved the whole playground code (of which the above was just a short snippet) to a full project, and am still getting the error. So something else is going on. `Person` actually confirms to a protocol (`Nameable`, which only has one property: `name`), could that interfere? – koen Oct 22 '16 at 20:08
  • Not from what I can tell – although in any case it would be really helpful if you could reduce your code down to a [mcve], and update the question with that example. – Hamish Oct 22 '16 at 20:15
  • Fixed - see my updated question. – koen Oct 22 '16 at 20:25

2 Answers2

3

For this to work

let persons = records.flatMap(Person.init)

the param passed to the flatMap closure must be the same type received by Person.init, so it must be PersonRecord.

Then records must be a list of PersonRecord, something like this

let records: [PersonRecord] = []

Now it works

let persons = records.flatMap(Person.init)    
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
1

Most of the times the Ambiguous reference to member in a map or flatMap is because the return type isn't specified

array.flatMap({ (item) -> ObjectToReturn? in })
Jeremy Piednoel
  • 407
  • 2
  • 5
  • 12