0

I have a lazy sequence I do some operations on and want to return from a function

func getSeq() -> ??? {
  let a = array.lazy
      ./* ... operations like map, filter, etc */
}

The final type of a is:

LazyMapSequence<FlattenSequence<LazyMapSequence<LazyFilterSequence<LazySequence<[[ComponentId] : ArchetypeId]>.Elements>.Elements, Zip2Sequence<Zip2Sequence<[C1], [C2]>, [C3]>>>, (C1, C2, C3)>

now how do I return a without having to specify the return type as that long type?

Jomy
  • 514
  • 6
  • 22

1 Answers1

2

Opaque result types were created for exactly this purpose. They were added in Swift 5.1. You'll see them often in SwiftUI, where view contents are expressed as some View, meaning the result is some complex generic type (whose particular type is hidden from the user code), so long as it conforms to View.

For your particular case here, you would need to them in conjunction with primary associated types, to express exactly what kind of elements the resulting sequence should produce, like so:

func getSeq() -> some Sequence<Element> {
    return array.lazy
        ./* ... operations like map, filter, etc */
}

Primary associated types were only recently introduced in Swift 5.7. As far as I can tell, they're a purely compile-time feature, so they don't require any specific OS version at runtime.

If Apple dropped support for your Mac and you can't run the necessary Xcode version for Swift 5.7, your next best bet is to do what we used to do: Use a type-eraser to erase the concrete type. For cases like yours, the standard library provides two type erasers, AnySequence and AnyCollection. This limits the type information to work with, so it might not optimize as nicely, but it works well enough.

func getSeq() -> AnySequence<Element> {
    return AnySequence(
        array.lazy
            ./* ... operations like map, filter, etc */
    )
}
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • When I do that, I get `Cannot specialize non-generic type 'Sequence'` – Jomy Feb 04 '23 at 18:21
  • 1
    It requires Swift 5.7 https://github.com/apple/swift-evolution/blob/main/proposals/0358-primary-associated-types-in-stdlib.md – Alexander Feb 04 '23 at 18:22
  • Any way to do this in earlier Swift versions as well? – Jomy Feb 04 '23 at 18:26
  • 1
    I’d suggest upgrading if your Xcode and macOS version support it. This is a compile-time only feature as far as I remember, so there’s no runtime OS version requirement. If not, you can workaround this by “erasing” the type using AnySequence or AnyCollection. It works well enough, but it poses a bit more of a barrier to optimization (because the compiler loses the details of the concrete type being returned) – Alexander Feb 04 '23 at 18:44
  • alight, I'll have to look into upgrading – Jomy Feb 04 '23 at 18:47