简体   繁体   中英

Why does Swift's reduce function throw an error of 'Type of expression ambigious without more context' when all types are properly defined?

var nums = [1,2,3]

let emptyArray : [Int] = []
let sum1 = nums.reduce(emptyArray){ $0.append($1)}
let sum2 = nums.reduce(emptyArray){ total, element in
    total.append(element)
}
let sum3 = nums.reduce(emptyArray){ total, element in
    return total.append(element)
}

For all three approaches I'm getting the following error:

Type of expression ambiguous without more context

But looking at documentation and the method signature of reduce:

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

You can see that both the Result and Element can be correctly inferred. Result is obviously of type [Int] and Element is of type [Int] .

So I'm not sure what's wrong. I also saw here but that doesn't help either

You're right that you're passing the correct types to be inferred. The error is misleading .

Had you instead wrote:

func append<T>(_ element: T, to array: [T]) -> [T]{
    let newArray = array.append(element)
    return newArray
} 

Then the compiler would have given the correct error:

Cannot use mutating member on immutable value: 'array' is a 'let' constant

So now we know what the correct error should have been:

That is both the Result and the Element are immutable within the closure. You have to think of it just like a normal func add(a:Int, b:Int) -> Int where a & b are both immutable.

If you want it to work you just need a temporary variable:

let sum1 = nums.reduce(emptyArray){
    let temp = $0
    temp.append($1)
    return temp
}

Also note that the following is is wrong!

let sum3 = nums.reduce(emptyArray){ total, element in
    var _total = total
    return _total.append(element)
}

Why?

Because the type of _total.append(element) is Void it's a function. Its type is not like the type of 5 + 3 ie Int or [5] + [3] ie [Int]

Hence you have to do:

let sum3 = nums.reduce(emptyArray){ total, element in
    var _total = total
    _total.append(element)
    return _total
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM