I don't understand the return type of Array.generator() at all

26 views
Skip to first unread message

Jason Stokes

unread,
Dec 18, 2014, 12:27:45 AM12/18/14
to swift-l...@googlegroups.com
I have an implementation of fold right (not intended to be maximally efficient or anything):

Extension Array {
    private func foldrImp<U>(var iter: IndexingGenerator<Array<T>>, combine: (U, T) -> U, val: U) -> U {
        let next = iter.next()
        switch next {
        case .None:
            return val
        case .Some(let elm):
            return combine(foldrImp(iter, combine: combine, val:val), elm)
        }
    }
   
    func foldr<U>(initial: U, combine: (U, T) -> U) -> U {
        return foldrImp(self.generate(), combine: combine, val: initial)
    }
}

Two issues:

In the signature to foldrImp, why can't I write?:

    private func foldrImp<U>(var iter: GeneratorOf<T>, combine: (U, T) -> U, val: U) -> U

Which is what i tried first. I do not understand the return type of Array.generate() at all, it looks like it iterates through arrays of T, not T elements themselves. How can I write a generic function if the type of Array.generate() doesn't conform to GeneratorOf<T>? I assume I've misunderstood somewhere the purpose of GeneratorOf?

Second, why does the following:

        case .Some(let elm as T):
            return combine(foldrImp(iter, combine: combine, val:val), elm)
        }

Trigger a compiler /error/, and not a warning, that "'is' test is always true."

I /know/ it's always true, sometimes I might want to just be clear about what type it is we're dealing with. Also, why does the compiler call it an 'is' test when it's clearly an 'as' test!?

Jens Ayton

unread,
Dec 19, 2014, 9:07:36 AM12/19/14
to Jason Stokes, swift-l...@googlegroups.com
On 18 Dec 2014, at 06:27, 'Jason Stokes' via Swift Language <swift-l...@googlegroups.com> wrote:
>
> I have an implementation of fold right (not intended to be maximally efficient or anything):
>
> Extension Array {
> private func foldrImp<U>(var iter: IndexingGenerator<Array<T>>, combine: (U, T) -> U, val: U) -> U {
> let next = iter.next()
> switch next {
> case .None:
> return val
> case .Some(let elm):
> return combine(foldrImp(iter, combine: combine, val:val), elm)
> }
> }
>
> func foldr<U>(initial: U, combine: (U, T) -> U) -> U {
> return foldrImp(self.generate(), combine: combine, val: initial)
> }
> }
>
> Two issues:
>
> In the signature to foldrImp, why can't I write?:
>
> private func foldrImp<U>(var iter: GeneratorOf<T>, combine: (U, T) -> U, val: U) -> U

You could do it this way, but then the caller would have to explicitly pass GeneratorOf(self.generate()). The easiest option is "var iter: Array.Generator". Generator is an associated type in the GeneratorType protocol, which is (typically) inferred as the result type of the generate() function, i.e. precisely what you want here.

--
Jens Ayton

Reply all
Reply to author
Forward
0 new messages