> On Nov 28, 2017, at 8:35 PM, Chris Lattner <[email protected]> wrote:
> 
> We’ve had a lot of discussions over the years about how to balance simplicity 
> vs power, implicitness vs explicitness, intentionality vs accidental 
> behavior, etc.  For example, in very early discussions about Swift generics, 
> some folks where strong proponents of protocol conformance being fully 
> implicit: satisfying all the requirements of a protocol meant that you 
> conformed to it, even if you didn’t explicitly “inherit” from it.
> 
> This is obviously not the design we went with over the long term, and I’m 
> glad we didn’t.

I get that, but an attribute in particular would be just as explicit as a 
protocol conformance.

> I think that DynamicMemberLookup requiring conformance is the same thing: it 
> makes it explicit that the behavior is intentional, and it allows somewhat 
> better error checking (if you conform to the protocol but don’t implement the 
> (implicitly known) requirement, you DO get an error).  That said, this is 
> just my opinion.  

So you envision that the compiler knows that 
`DynamicMemberLookupProtocol`-conforming types ought to have 
`subscript(dynamicMember:)` members, and these members ought to have certain 
traits (unary, ExpressibleByStringLiteral parameter, etc.), and it should 
enforce those traits, even though there's no matching requirement in the 
protocol?

That seems like a lot of compiler magic to attach to a particular protocol. A 
`@dynamicMember` attribute would have a similar amount of magic, but people 
*expect* that kind of magic from an attribute. For instance, the `@objc` 
attribute places lots of conditions on the types of parameters, etc., and 
nobody is surprised by that.

Other reasons to prefer an attribute:

* I can't think of a use case where you would want dynamic members but not want 
to make the subscript itself accessible. If `@dynamicMember` could be applied 
to any subscript, then you could use any label (or no label) for sugar-free use 
of the dynamic functionality. For instance, the JSON example could decorate its 
existing subscript instead of introducing a redundant one:

        extension JSON {
          var stringValue : String? {
            if case .StringValue(let str) = self {
              return str
            }
            return nil
          }
          subscript(index: Int) -> JSON? {
            if case .ArrayValue(let arr) = self {
              return index < arr.count ? arr[index] : nil
            }
            return nil
          }
          @dynamicMember subscript(key: String) -> JSON? {
            if case .DictionaryValue(let dict) = self {
              return dict[key]
            }
            return nil
          }
        }

* If we eventually want to support multiple subscripts with different types 
(either by using different return types, or by later supporting 
non-`ExpressibleByStringLiteral` fixed attribute sets), allowing multiple 
subscripts to be annotated by `@dynamicMember` is more natural than allowing 
multiple `subscript(dynamicMember:)` members to simultaneously satisfy a single 
protocol pseudo-requirement.

The only thing you're using the `DynamicMemberLookupProtocol` for is to mark 
the type for the compiler to recognize; you're not using any of the other 
capabilities of protocols. That would be okay if you were proposing something 
that wouldn't touch the compiler if implemented with a protocol, but this 
feature definitely requires significant compiler work. It'd be okay if all you 
needed to do was mark a type, but this feature also requires you to implement 
certain members, following certain conventions, which happen to be difficult to 
express through protocols. It'd be okay if a type needed many members to meet 
the requirements, but it only needs one. It'd be okay if you needed to 
constrain generic calls to require conformance to the type, but there's no need 
for that here.

Basically, you're using a hammer to drive a screw. Why not use a screwdriver 
instead?

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to