i have a database model with some CodingKeys that look like:
extension SomeDatabase.SomeModel
{
enum CodingKeys:String
{
case id = "_id"
case address = "a"
}
}
rather than type out
"\(SomeDatabase.SomeModel.CodingKeys.address.rawValue)"
every time i build a query, i would like to use dynamic member lookup to shorten this to something like:
"\(SomeDatabase.SomeModel.address)"
i thought this would work:
extension SomeDatabase.SomeModel
{
static
subscript(dynamicMember:KeyPath<CodingKeys.Type, CodingKeys>) -> String
{
CodingKeys.self[keyPath: dynamicMember].rawValue
}
}
but when i use it, i get the error:
error: dynamic key path member lookup cannot refer to enum case 'address'
what?
Key paths aren't supported for enum cases, maybe try CasePath?
what is CasePath? is it a 5.9 feature?
No it's a library, but you can't use it with @dynamicMemberLookup, I didn't realize that was the question. I don't think there's any current way to forward enum cases with dynamic member lookup without using some hacky workaround.
public enum CodingKeys: String {
case id = "_id"
case address = "a"
public struct Namespace {
var id: CodingKeys { .id }
var address: CodingKeys { .address }
}
}
extension SomeDatabase.SomeModel {
static subscript(dynamicMember member: KeyPath<CodingKeys.Namespace, CodingKeys>) -> String {
CodingKeys.Namespace()[keyPath: member].rawValue
}
}
i ended up just adding a static subscript sugaring API to the model type:
extension Package
{
static
subscript(key:CodingKeys) -> String
{
key.rawValue
}
}
it’s concise enough for me anyway:
$0.stage
{
$0[.unionWith] = .init
{
$0[.collection] = Self.packages
$0[.pipeline] = .init
{
$0.stage
{
$0[.sort] = .init
{
$0[Package[.address]] = (-)
}
}
$0.stage
{
$0[.limit] = 1
}
$0.stage
{
$0[.replaceWith] = .init
{
$0[Package[.id]] = "\(package)"
$0[Package[.address]] = .init
{
$0[.add] = ("$\(Package[.address])", 1)
}
}
}
}
}
}
(this is a mongodb aggregation query)
Could you maybe use a result builder for that?
this is a result builder, it’s just not one of the unkeyed SwiftUI result builders that got added to the language a couple years ago.
like i said, SwiftUI-style result builders are unkeyed, so they’re not really great for the kind of “key-value shaped” things like BSON. this is where subscript assignment really shines in my opinion.
how would you design this DSL?
bbrk24
10
I thought static keypaths weren’t supported at all. I’m surprised the error is what it is, but iirc I tried to get around that with a static protocol extension once and got a much more clear error message.