Hello, your answer is in your question. Swift does not allow to switch scopes.
Result builders (formerly function builders) do not change this: SwiftUI works because import SwiftUI
puts Text
, Image
etc in the global scope.
(Personal opinion on the topic follows)
Because they live in the global scope, SwiftUI types become "reserved": Text
or Image
are not only defined inside the body of view builders, and you can't use those identifiers for other purposes. If we were to design a result builder for SQL tables, we'd have to wonder if it is desirable to "lock" the Column
and PrimaryKey
types for table definition. For example:
import SwiftSQL
buildSqlTable(...) {
// In the table builder scope
Column("name", .string)
PrimaryKey(...)
}
// Out of the table builder scope
Column(...) // the same Column
PrimaryKey(...) // the same PrimaryKey
An SQL DSL usually has two facets, schema definition (CREATE ...), and query generation (SELECT ..., INSERT...). They share some concepts: "table", "column", "primary key", etc. It is not always true that a single type such as Column
can fulfill the needs of both facets. Given that the schema definition API is usually much less used, in an application, than the query generation API, is it desirable to lock Column
for schema definition, making it unavailable for query generation? Your call.
Faced with the same question, I decided that the schema definition DSL of GRDB would not hinder the query generation api, and would not use the same types. It uses dedicated types named like ColumnDefinition
. Those types are public, but they would not look good in user's code. So it eventually looks like:
try db.create(table: "player") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name", .text).notNull()
t.column("score", .text).notNull().defaults(to: 0)
t.column("teamID", .integer)
.notNull()
.indexed()
.references("team", onDelete: .cascade)
}
The t.
prefix is a very small visual pollution. Some will prefer $0
. That's the best I could come up with in the current state of Swift.