Static dynamicMemberLookup

Currently dynamic member lookup only applies to the instances of annotated types, but it's not applicable to types, though static subscripts are possible in general. That seems to create a disbalance in the sense that instance properties are balanced by dynamic member lookup, but static properties are not.

So the question/suggestion is how feasible it would be to extend dynamic member lookup to be static?

@dynamicMemberLookup works with static subscripts just fine when I have used it. Are you able to share your code to get some help?

Here are some examples where I got it working.
With ExpressibleByStringLiteral

@dynamicMemberLookup
struct Foo {
    static subscript(dynamicMember member: String) -> String {
        "Dynamic: \(member)"
    }
}

print(Foo.a) // "Dynamic: a"
print(Foo.b) // "Dynamic: b"

With KeyPath

@dynamicMemberLookup
struct Bar {
    static subscript(dynamicMember keyPath: KeyPath<[Int], Int>) -> Int {
        let array = [1, 2, 3]
        return array[keyPath: keyPath]
    }
}

print(Bar.count) // "3"
print(Bar.capacity) // "3"

Indeed, it seems to be working with explicit type, so it seems to be a combination of other factors that does not allow it to work in my case. Here is a close snippet to my code where it does not work as I would expect:

@dynamicMemberLookup
struct Foo {
    static subscript(dynamicMember member: String) -> Foo { Foo() }
}

prefix operator /
prefix func /(_ lhs: Foo) -> Foo {
    return lhs
}

let _: Foo = Foo.foo will work as expected, but let _: Foo = /.foo results in error Type 'Foo' has no member 'foo'. So it properly infers the type, but can't infer the call to subscript. Same with let _: Foo = .foo
UPD: And with static var foo: Foo { Foo() } all three variants work fine.

1 Like

Interesting. I’ll have to look at it when I get back to my computer and see if I can find a solution for that case.

Maybe static dynamic member lookup doesn’t work for unprefixed “dot” syntax? If I remember correctly you have to do self.dynamicMember Not just dynamicMember for the instance version.

static dynamic member lookup doesn’t work for unprefixed “dot” syntax

This seems to be the case here. It works with regular static properties though. On the other hand regular static subscripts don't work without specifying the type as well, so maybe this is an expected behaviour for dynamic member lookup too.
In my case it would be a nice thing to have as it would allow to have a nice syntax for url builder I'm working on, i.e. /.repo/.string that would match "/repo/apple" url path. Without that I have to do a workaround by adding an empty path component (using ExpressibleByStringLiteral) to "lift" it from type to instance: ""/.repo/.string.

2 Likes

I'd just like to add that autocomplete doesn't work for static dynamicMember subscripts even if you specify the type name.