Usability of InlineArray<let N: Int, ...>, StaticString

I'm playing around with InlineArray now that the kind folks helped me to get it working and I ran into some challenges in usability. For context, I'm making a postgresql extension which should run in the order of microseconds – hence the optimizations.

What I'd like to do is this:

query<3>("SELECT some, sql, columns FROM wherever")

... where 3 is the number of columns selected. Let's start with that simple case.

To define this function I need something like this:

func query<let N: Int>(_ query: StaticString) -> AnyIterator<InlineArray<N, PGDatum>> {
     ...

    return AnyIterator {
          let row = InlineArray<N, PGDatum> { ... }
          return row
     }
}

The issue is, that doesn't build. It's not allowed to specify 3 in query<3>("...").

What I can do instead is call query as let result: AnyIterator<InlineArray<3, PGDatum?>> = query(...) – but that's not very usable.


I then considered the option of using an InlineArray to specify the columns in the SQL statement: query("SELECT", ["some", "sql", "columns"], "FROM ...")

That in theory allows me to use type inference to get the number of columns – even better! But then I'm stuck with the issue of StaticString – there's no reasonable way to concatenate them at compile time. So I'd be stuck with concatenating them at runtime for every iteration of the query – that's probably worse than simply using Array in the first place.

Any ideas?

Along the same lines as the ubiquitous type: T.Type arguments, I wonder if you could say

typealias NumberGeneric<let n: Int> = InlineArray<n, Never> // or define an empty struct instead of a typealias

func query<let n: Int>(_ query: StaticString, columnCount: NumberGeneric<n>.Type) -> AnyIterator<InlineArray<n, PGDatum>> {
  ...
}


query(..., columnCount: NumberGeneric<3>.self)

names subject to bikeshedding of course, but is that approach workable?

2 Likes

Thanks, with that approach I made the following typealias which cleans up both the function definitions and the call sites enough to be usable for now.

typealias Cursor<let N_COLS: Int> = AnyIterator<InlineArray<N_COLS, PGDatum>>?

It would be nice to be able to just call query<7> in future, and it would be nice to have a solution for concatenating StaticStrings statically, but can live with this for now!

2 Likes

There was recently this pitch by @harlanhaskins [Pitch] Lifting restriction on explicit specialization in function calls

5 Likes