@dynamicMemberLookup on protocols


(Alex Semenikhine) #1
// @dynamicMemberLookup // Currently not allowed, does not compile
protocol IsDynamic {
    subscript(dynamicMember member: String) -> String { get }
}

@dynamicMemberLookup
struct DynamicStruct: IsDynamic {
    subscript(dynamicMember member: String) -> String {
        return "ok"
    }
}

var someObject: IsDynamic = DynamicStruct()
// var desiredValue = someObject.test // Would compile if IsDynamic could be @dynamicMemberLookup
var currentValue = someObject[dynamicMember: "test"]

This would allow a base generic class with a model such as class ViewController<Model: IsDynamic> to have the nice dot syntax of model.someValue, rather than model[dynamicMember: "someValue"]

 class ViewController<Model: IsDynamic>: UIViewController {
        var model: [Model] = []

        func tableViewMethod(row: Int) -> String {
            //return model[row].name // Desired result
            return model[row][dynamicMember: "name"] // Current result
        }
    }

(Dan Zheng) #2

Thanks for pointing this out!

That @dynamicMemberLookup doesn't work for protocols is known and a bug in my opinon. I believe @Chris_Lattner3 agreed that it's a bug but I can't find the post where he stated that.

Here's a previous post illustrating the problem and an ineffective workaround.

I believe @dynamicMemberLookup (and @dynamicCallable) should be declarable on protocols.
Method resolution for dynamic member lookups and dynamic calls should work just like resolution for protocol requirements.

I'm currently working on the @dynamicCallable implementation and intend to fix @dynamicMemberLookup for protocols at some point (before Swift 5).


(Dan Zheng) #3

Also, it's contentious whether or not a general "DynamicMemberLookup" protocol is a good idea.
The original proposal for @dynamicMemberLookup used such a protocol, instead of an attribute.

However, protocols define semantic behavior, and "dynamic member lookup" doesn't have any inherent meaning: the semantics are use-case specific and implementation defined.

In any case, declaring @dynamicMemberLookup on protocols should be supported by the language.
For your use case, I might suggest renaming your IsDynamic protocol with a semantically clear name (something like DynamicDataModel - I'm not sure about your exact use case).