reduce on Range seems to be broken

Hi


I tried to write a function to produce an array of count indentical elements:


func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T]()) { return $0.append(elem) }
}


Normally with reduce, the 1st param sets the type of the return, here obviously [T], and the successive $1 values come from the type of the element of the sequence, which here is not used. So this looks right to me, for the purpose.


But it gives me an error pointing to the [T](): "Cannot convert value of type '[T]' to expected argument type '[_]'

I don't know why that error is occurring. Can anyone explain this?


TIA

Mark

Accepted Reply

Try this:

func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T]()) {arr,_ in return arr + [elem] }
}

or this:

func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T](), combine: {a0,_ in return a0 + [elem] })
}


And see the reference doc of reduce(_:combine:) method of SequenceType.

reduce(_:combine:)

The `combine` argument takes TWO argument closure. When you write only `$0` in a closure expression, Swift takes it as a single argument closure.


One thing very bad is the error message you have shown, it's a pity that Swift still tends to give us some ununderstandable messages in case of type mismatching.

Replies

Try this:

func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T]()) {arr,_ in return arr + [elem] }
}

or this:

func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T](), combine: {a0,_ in return a0 + [elem] })
}


And see the reference doc of reduce(_:combine:) method of SequenceType.

reduce(_:combine:)

The `combine` argument takes TWO argument closure. When you write only `$0` in a closure expression, Swift takes it as a single argument closure.


One thing very bad is the error message you have shown, it's a pity that Swift still tends to give us some ununderstandable messages in case of type mismatching.

Thanks for the reply, but that didn't change the error.


It should be the first parameter to reduce that detemines the result type. That has been specified. reduce is declared on SequenceType thus:

public func reduce<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> T


So, the initial value, the result of the combine the result of reduce are all the same type, the Self.Generator.Element type is not logically connected.


Any other ideas?

Thanks for the reply, but that didn't change the error.

Have you really tried my code? I cannot generate errors as you described. I have tested my codes in the Playground of Xcode 7.1.1.

Arghh! No, it does work. I had introduced another error, fogetting a space around the + in the array concatenation, but the old error message didn't go away.


The working version is:

func replicateWithReduce<T>(elem: T, count: Int) -> [T]
{
    return (0 ..< count).reduce([T]()) { arr, _ in return arr + [elem] }
}


I don't quite see why, but thanks,

the old error message didn't go away

I see. I have experienced the same behavior of Xcode so many times... Maybe we need to acustomed to such things. Good luck.

Array also has an initializer which does this, if you would prefer to use that.


init(count: Int, repeatedValue: Element)
Construct a Array of count elements, each initialized to repeatedValue.