Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Cheyo Jose Jimenez via swift-evolution

> On Dec 3, 2017, at 12:44 PM, Jean-Daniel  wrote:
> 
> 
> 
>> Le 3 déc. 2017 à 09:29, Jose Cheyo Jimenez > > a écrit :
>> 
>> 
>> 
>> On Dec 2, 2017, at 11:46 PM, Jean-Daniel > > wrote:
>> 
>>> 
>>> 
 Le 3 déc. 2017 à 04:58, Jose Cheyo Jimenez via swift-evolution 
 > a écrit :
 
 Hi Chris, 
 
 Thank you for pushing this forward.
 
 My only comment is that on the declaration side it would be great to also 
 have an attribute to communicate that compiler magic is happening.
 
 Currently it is surprising that a regular looking protocol is providing me 
 so much power.
 
 Suggestions: 
 
 @dynamic
 struct PyVal : MemberLookupProtocol {...}
 
 @dynamic
 struct ParameterSummer : DynamicCallable {...}
 
 // Error: This type needs the @dynamic attribute.
 class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}
 
 By requiring @dynamic (Or other attribute name), people can know that this 
 is a compiler dynamic declaration and not just some random protocol whose 
 name starts with Dynamic*. :)
 
>>> 
>>> I’m not fond of the idea of an attribute. This introduce redundancy.
>> 
>>> What a declaration means if the attribute is missing ?  
>> Won’t compile?
>> 
>>> What this attribute will mean on an other declaration ?
>> Won’t compile?
>> 
>> It would be similar to the swift 4 mode where @objc is required in some 
>> declarations. 
> 
> No it isn’t.
> Like with @NSManagedObject, the very same declaration can exist with or 
> without the @objc attribute depending the context, and the behavior of the 
> function change. Neither is true with the @dynamic proposal.

This is assuming that the protocol is what triggers the compiler to treat this 
type differently (Current draft implementation).

Currently in the draft there are 2-3 protocols that give the dynamic behavior 
to a type. These protocols can be typealias'ed, conformed by other protocols 
with different names etc. 


**someModule.swift***

public protocol JustAnotherProtocol: DynamicCallable {...}


**myModule.swif***

struct JSVal: JustAnotherProtocol {...}



How do I know JustAnotherProtocol is dynamic in a git diff?

Having a common sigil like @IamDynamic can make all these declarations 
explicit. Clearer to the reader. All other related dynamic protocols can share 
the same umbrella sigil. 

Chris added it to the list of potential solutions.
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
 


"
We could add an attribute or use some other way to make conformance to 
DynamicMemberLookupProtocol more visible, e.g.:
@dynamic
struct PyVal : DynamicCallable {...}
"



___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Jean-Daniel via swift-evolution


> Le 3 déc. 2017 à 09:29, Jose Cheyo Jimenez  a écrit :
> 
> 
> 
> On Dec 2, 2017, at 11:46 PM, Jean-Daniel  > wrote:
> 
>> 
>> 
>>> Le 3 déc. 2017 à 04:58, Jose Cheyo Jimenez via swift-evolution 
>>> > a écrit :
>>> 
>>> Hi Chris, 
>>> 
>>> Thank you for pushing this forward.
>>> 
>>> My only comment is that on the declaration side it would be great to also 
>>> have an attribute to communicate that compiler magic is happening.
>>> 
>>> Currently it is surprising that a regular looking protocol is providing me 
>>> so much power.
>>> 
>>> Suggestions: 
>>> 
>>> @dynamic
>>> struct PyVal : MemberLookupProtocol {...}
>>> 
>>> @dynamic
>>> struct ParameterSummer : DynamicCallable {...}
>>> 
>>> // Error: This type needs the @dynamic attribute.
>>> class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}
>>> 
>>> By requiring @dynamic (Or other attribute name), people can know that this 
>>> is a compiler dynamic declaration and not just some random protocol whose 
>>> name starts with Dynamic*. :)
>>> 
>> 
>> I’m not fond of the idea of an attribute. This introduce redundancy.
> 
>> What a declaration means if the attribute is missing ?  
> Won’t compile?
> 
>> What this attribute will mean on an other declaration ?
> Won’t compile?
> 
> It would be similar to the swift 4 mode where @objc is required in some 
> declarations. 

No it isn’t.
Like with @NSManagedObject, the very same declaration can exist with or without 
the @objc attribute depending the context, and the behavior of the function 
change. Neither is true with the @dynamic proposal.


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Chris Lattner via swift-evolution


> On Dec 2, 2017, at 7:58 PM, Jose Cheyo Jimenez  wrote:
> 
> Hi Chis, 
> 
> Thank you for pushing this forward.
> 
> My only comment is that on the declaration side it would be great to also 
> have an attribute to communicate that compiler magic is happening.
> 
> Currently it is surprising that a regular looking protocol is providing me so 
> much power.
> 
> Suggestions: 
> 
> @dynamic
> struct PyVal : MemberLookupProtocol {...}
> 
> @dynamic
> struct ParameterSummer : DynamicCallable {...}
> 
> // Error: This type needs the @dynamic attribute.
> class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}
> 
> By requiring @dynamic (Or other attribute name), people can know that this is 
> a compiler dynamic declaration and not just some random protocol whose name 
> starts with Dynamic*. :)

I’m not a huge fan of this (because it is redundant as Jean-Daniel mentions 
downthread), but it is definitely possible.  I’ll add it to the alternatives 
section so that people consider it during review.

-Chris


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Jose Cheyo Jimenez via swift-evolution


> On Dec 2, 2017, at 11:46 PM, Jean-Daniel  wrote:
> 
> 
> 
>> Le 3 déc. 2017 à 04:58, Jose Cheyo Jimenez via swift-evolution 
>>  a écrit :
>> 
>> Hi Chris, 
>> 
>> Thank you for pushing this forward.
>> 
>> My only comment is that on the declaration side it would be great to also 
>> have an attribute to communicate that compiler magic is happening.
>> 
>> Currently it is surprising that a regular looking protocol is providing me 
>> so much power.
>> 
>> Suggestions: 
>> 
>> @dynamic
>> struct PyVal : MemberLookupProtocol {...}
>> 
>> @dynamic
>> struct ParameterSummer : DynamicCallable {...}
>> 
>> // Error: This type needs the @dynamic attribute.
>> class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}
>> 
>> By requiring @dynamic (Or other attribute name), people can know that this 
>> is a compiler dynamic declaration and not just some random protocol whose 
>> name starts with Dynamic*. :)
>> 
> 
> I’m not fond of the idea of an attribute. This introduce redundancy.

> What a declaration means if the attribute is missing ?  
Won’t compile?

> What this attribute will mean on an other declaration ?
Won’t compile?

It would be similar to the swift 4 mode where @objc is required in some 
declarations. 


> If this attribute must be used with the declaration and it can’t be used with 
> an other one, then what is the point of having an attribute but to exercice 
> the compiler fixit feature 
> 
>> @NSManagedObject is another example I like from Core Data.
>> https://useyourloaf.com/blog/core-data-code-generation/
> 
> @NSManageObject apply to normal declarations that have a different meaning 
> when this attribute is not present.
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-02 Thread Jean-Daniel via swift-evolution


> Le 3 déc. 2017 à 04:58, Jose Cheyo Jimenez via swift-evolution 
>  a écrit :
> 
> Hi Chis, 
> 
> Thank you for pushing this forward.
> 
> My only comment is that on the declaration side it would be great to also 
> have an attribute to communicate that compiler magic is happening.
> 
> Currently it is surprising that a regular looking protocol is providing me so 
> much power.
> 
> Suggestions: 
> 
> @dynamic
> struct PyVal : MemberLookupProtocol {...}
> 
> @dynamic
> struct ParameterSummer : DynamicCallable {...}
> 
> // Error: This type needs the @dynamic attribute.
> class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}
> 
> By requiring @dynamic (Or other attribute name), people can know that this is 
> a compiler dynamic declaration and not just some random protocol whose name 
> starts with Dynamic*. :)
> 

I’m not fond of the idea of an attribute. This introduce redundancy. What a 
declaration means if the attribute is missing ?  What this attribute will mean 
on an other declaration ?
If this attribute must be used with the declaration and it can’t be used with 
an other one, then what is the point of having an attribute but to exercice the 
compiler fixit feature 

> @NSManagedObject is another example I like from Core Data.
> https://useyourloaf.com/blog/core-data-code-generation/ 
> 
@NSManageObject apply to normal declarations that have a different meaning when 
this attribute is not present.


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-12-02 Thread Jose Cheyo Jimenez via swift-evolution
Hi Chis, 

Thank you for pushing this forward.

My only comment is that on the declaration side it would be great to also have 
an attribute to communicate that compiler magic is happening.

Currently it is surprising that a regular looking protocol is providing me so 
much power.

Suggestions: 

@dynamic
struct PyVal : MemberLookupProtocol {...}

@dynamic
struct ParameterSummer : DynamicCallable {...}

// Error: This type needs the @dynamic attribute.
class ParamWinter : MyCustomCallableProtocolOrClassOrTypeAlias {...}

By requiring @dynamic (Or other attribute name), people can know that this is a 
compiler dynamic declaration and not just some random protocol whose name 
starts with Dynamic*. :)

@NSManagedObject is another example I like from Core Data.
https://useyourloaf.com/blog/core-data-code-generation/ 


- Cheyo



> On Nov 28, 2017, at 8:35 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Nov 27, 2017, at 6:21 PM, Brent Royal-Gordon > > wrote:
>> 
>>> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>>> > wrote:
>>> 
>>> Just to talk to myself a bit here, but I’ve come to realize that the right 
>>> design really is to have a simple empty marker protocol like this:
>> 
>> If you're reaching this point. why have a marker protocol at all? Why not 
>> treat `subscript(dynamicMember:)` specially on any type that has it, or have 
>> an `@dynamicMember subscript(_:)` attribute, or introduce an entire new 
>> `dynamicMember(_:)` declaration?
> 
> 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.  That said, if we did, then all of the “ExpressibleBy” 
> protocols wouldn’t  need to exist: we’d probably just say that it was enough 
> to implement the requirements to get the behavior and elide the protocol 
> declaration entirely.
> 
> 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.  
> 
> Do you feel strongly enough about this that you’d like to make a strong 
> argument for changing the behavior?
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Richard Wei via swift-evolution


> On Nov 29, 2017, at 07:25, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Nov 29, 2017, at 12:46 AM, Brent Royal-Gordon  
>> wrote:
>> 
>>> On Nov 28, 2017, at 8:35 PM, Chris Lattner  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.
> 
> Sure, I’m not attached to spelling.  I think that conformance is the right 
> way to do this (following the pattern of the other ExpressibleBy etc types), 
> but if you have a compelling argument for some specific spelling, I’m more 
> than happy to discuss it.

I completely agree that protocol conformance is the right away to do it. One 
similar approach is Scala’s Dynamic 
 
protocol.

I can’t think of a good “-able” word for this. "DynamicMemberLookupProtocol" is 
probably good enough IMO.

-Richard

> 
>>> 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?
> 
> Yes, this is implemented in the patch, it is a straight-forward additional 
> check in protocol conformance.
> 
> Keep in mind that the compiler has other similar things for features that are 
> not expressible in the Swift type system, e.g. the type(of:) function.
> 
>> 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.
> 
> I don’t really think that’s the case.  Attributes have their place, for sure, 
> but there in high precedent for Protocols providing exposing language 
> features to types.
> 
>> 
>> 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:
> 
> I see the small advantage, but isn’t precedented at all.  The ExpressibleBy 
> protocols require redeclaring redundant methods just like this.
> 
>> * If we eventually want to support multiple subscripts with different types 
>> (either by using different return types, 
> 
> This is already supported in the patch, and the patch includes a test case.
> 
>> Basically, you're using a hammer to drive a screw. Why not use a screwdriver 
>> instead?
> 
> I don’t see a connection between this rhetorical mechanic and the topic at 
> hand :-)
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Chris Lattner via swift-evolution

> On Nov 29, 2017, at 12:46 AM, Brent Royal-Gordon  
> wrote:
> 
>> On Nov 28, 2017, at 8:35 PM, Chris Lattner  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.

Sure, I’m not attached to spelling.  I think that conformance is the right way 
to do this (following the pattern of the other ExpressibleBy etc types), but if 
you have a compelling argument for some specific spelling, I’m more than happy 
to discuss it.

>> 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?

Yes, this is implemented in the patch, it is a straight-forward additional 
check in protocol conformance.

Keep in mind that the compiler has other similar things for features that are 
not expressible in the Swift type system, e.g. the type(of:) function.

> 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.

I don’t really think that’s the case.  Attributes have their place, for sure, 
but there in high precedent for Protocols providing exposing language features 
to types.

> 
> 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:

I see the small advantage, but isn’t precedented at all.  The ExpressibleBy 
protocols require redeclaring redundant methods just like this.

> * If we eventually want to support multiple subscripts with different types 
> (either by using different return types, 

This is already supported in the patch, and the patch includes a test case.

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

I don’t see a connection between this rhetorical mechanic and the topic at hand 
:-)

-Chris

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Chris Lattner via swift-evolution

> On Nov 29, 2017, at 2:21 AM, Jonathan Hull  wrote:
> 
> I noticed all of the examples return the same type as they are defined on 
> (JSON has a subscript that returns JSON).  Is there an example of where this 
> is not the case?

Yes, they exist, there is one in the Python interop layer that I’m working on: 
it is a separate type that vends all the Python builtins.  It returns them as 
PyVal's.

-Chris



> 
> 
>> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> On Nov 20, 2017, at 10:36 PM, Chris Lattner > > wrote:
>>> Hi all,
>>> 
>>> I’ve significantly revised the ‘dynamic member lookup’ pitch, here’s the 
>>> second edition:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>>> 
>>> 
>>> I’ve incorporated some minor changes to it:
>>> - I’ve made it possible to provide read-only dynamic members.
>>> - I’ve added an example JSON use-case which uses read-only dynamic members.
>>> - Minor wording changes.
>> 
>> Just to talk to myself a bit here, but I’ve come to realize that the right 
>> design really is to have a simple empty marker protocol like this:
>> 
>> /// Types type conform to this protocol have the behavior that member lookup 
>> -
>> /// accessing `someval.member` will always succeed.  Failures to find 
>> normally
>> /// declared members of `member` will be turned into subscript references 
>> using
>> /// the `someval[dynamicMember: member]` member.
>> ///
>> public protocol DynamicMemberLookupProtocol {
>>   // Implementations of this protocol must have a subscript(dynamicMember:)
>>   // implementation where the keyword type is some type that is
>>   // ExpressibleByStringLiteral.  It can be get-only or get/set which defines
>>   // the mutability of the resultant dynamic properties.
>>   
>>   // subscript
>>   //  (dynamicMember name: KeywordType) -> LookupValue { get }
>> }
>> 
>> 
>> A design like this can almost work:
>> 
>> public protocol DynamicMemberLookupProtocol {
>>   associatedtype DynamicMemberLookupKeyword : ExpressibleByStringLiteral
>>   associatedtype DynamicMemberLookupValue
>>   
>>   subscript(dynamicMember name: DynamicMemberLookupKeyword)
>> -> DynamicMemberLookupValue { get }
>> }
>> 
>> The problem is that now everything that conforms to 
>> DynamicMemberLookupProtocol is a PAT, so it doesn’t work with existentials.  
>> We could almost make due with a generic subscript:
>> 
>> public protocol DynamicMemberLookupProtocol {
>>   subscript
>> (dynamicMember name: KeywordType) -> LookupValue { get }
>> }
>> 
>> but it turns out that while you can declare that, nothing can actually 
>> conform to it with concrete types (I filed SR-6473, but it isn’t clear that 
>> it ever can work given how our generics system works).
>> 
>> Defining this as an empty marker protocol has several advantages:
>>  - Only one protocol is required
>>  - Suddenly you can define mutating getters and nonmutating setters
>>  - Existentials work as well as concrete types.
>> 
>> -Chris
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Jonathan Hull via swift-evolution
I noticed all of the examples return the same type as they are defined on (JSON 
has a subscript that returns JSON).  Is there an example of where this is not 
the case?


> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> On Nov 20, 2017, at 10:36 PM, Chris Lattner  > wrote:
>> Hi all,
>> 
>> I’ve significantly revised the ‘dynamic member lookup’ pitch, here’s the 
>> second edition:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>> 
>> 
>> I’ve incorporated some minor changes to it:
>> - I’ve made it possible to provide read-only dynamic members.
>> - I’ve added an example JSON use-case which uses read-only dynamic members.
>> - Minor wording changes.
> 
> Just to talk to myself a bit here, but I’ve come to realize that the right 
> design really is to have a simple empty marker protocol like this:
> 
> /// Types type conform to this protocol have the behavior that member lookup -
> /// accessing `someval.member` will always succeed.  Failures to find normally
> /// declared members of `member` will be turned into subscript references 
> using
> /// the `someval[dynamicMember: member]` member.
> ///
> public protocol DynamicMemberLookupProtocol {
>   // Implementations of this protocol must have a subscript(dynamicMember:)
>   // implementation where the keyword type is some type that is
>   // ExpressibleByStringLiteral.  It can be get-only or get/set which defines
>   // the mutability of the resultant dynamic properties.
>   
>   // subscript
>   //  (dynamicMember name: KeywordType) -> LookupValue { get }
> }
> 
> 
> A design like this can almost work:
> 
> public protocol DynamicMemberLookupProtocol {
>   associatedtype DynamicMemberLookupKeyword : ExpressibleByStringLiteral
>   associatedtype DynamicMemberLookupValue
>   
>   subscript(dynamicMember name: DynamicMemberLookupKeyword)
> -> DynamicMemberLookupValue { get }
> }
> 
> The problem is that now everything that conforms to 
> DynamicMemberLookupProtocol is a PAT, so it doesn’t work with existentials.  
> We could almost make due with a generic subscript:
> 
> public protocol DynamicMemberLookupProtocol {
>   subscript
> (dynamicMember name: KeywordType) -> LookupValue { get }
> }
> 
> but it turns out that while you can declare that, nothing can actually 
> conform to it with concrete types (I filed SR-6473, but it isn’t clear that 
> it ever can work given how our generics system works).
> 
> Defining this as an empty marker protocol has several advantages:
>  - Only one protocol is required
>  - Suddenly you can define mutating getters and nonmutating setters
>  - Existentials work as well as concrete types.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Brent Royal-Gordon via swift-evolution
> On Nov 28, 2017, at 8:35 PM, Chris Lattner  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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-28 Thread Chris Lattner via swift-evolution

> On Nov 27, 2017, at 7:31 PM, Xiaodi Wu  wrote:
> 
> Better yet, since we previously started to require “@objc dynamic” instead of 
> “dynamic” with the notion that perhaps there would be some future non-ObjC 
> dynamism, we *could* have it spelt “dynamic member(_:)”.

I’m super open the changing the spelling of anything in the proposal.  That 
said, if you really mean to suggest that we introduce some new syntactic form, 
I’d be wary of that.  It increases the scope of the proposal and makes the 
cost/benefit tradeoff harder to justify.  One of the things that I think is 
compelling about this is that the cost of it is very low (it really does fit 
naturally into the existing architecture of the compiler), which means that the 
narrow benefit is justifiable (IMO).

> But this is all just spelling now; I think the overall design is compelling 
> in its elegance and power.

I’m glad to hear that, thanks!

-Chris

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-28 Thread Chris Lattner via swift-evolution

> On Nov 27, 2017, at 6:21 PM, Brent Royal-Gordon  
> wrote:
> 
>> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> Just to talk to myself a bit here, but I’ve come to realize that the right 
>> design really is to have a simple empty marker protocol like this:
> 
> If you're reaching this point. why have a marker protocol at all? Why not 
> treat `subscript(dynamicMember:)` specially on any type that has it, or have 
> an `@dynamicMember subscript(_:)` attribute, or introduce an entire new 
> `dynamicMember(_:)` declaration?

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.  That said, if we did, then all of the “ExpressibleBy” protocols 
wouldn’t  need to exist: we’d probably just say that it was enough to implement 
the requirements to get the behavior and elide the protocol declaration 
entirely.

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.  

Do you feel strongly enough about this that you’d like to make a strong 
argument for changing the behavior?

-Chris

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-27 Thread Xiaodi Wu via swift-evolution
Better yet, since we previously started to require “@objc dynamic” instead
of “dynamic” with the notion that perhaps there would be some future
non-ObjC dynamism, we *could* have it spelt “dynamic member(_:)”.

But this is all just spelling now; I think the overall design is compelling
in its elegance and power.
On Mon, Nov 27, 2017 at 20:22 Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:

> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Just to talk to myself a bit here, but I’ve come to realize that the right
> design really is to have a simple empty marker protocol like this:
>
>
> If you're reaching this point. why have a marker protocol at all? Why not
> treat `subscript(dynamicMember:)` specially on any type that has it, or
> have an `@dynamicMember subscript(_:)` attribute, or introduce an entire
> new `dynamicMember(_:)` declaration?
>
> --
> Brent Royal-Gordon
> Architechies
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-27 Thread Brent Royal-Gordon via swift-evolution
> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> Just to talk to myself a bit here, but I’ve come to realize that the right 
> design really is to have a simple empty marker protocol like this:

If you're reaching this point. why have a marker protocol at all? Why not treat 
`subscript(dynamicMember:)` specially on any type that has it, or have an 
`@dynamicMember subscript(_:)` attribute, or introduce an entire new 
`dynamicMember(_:)` declaration?

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-25 Thread Chris Lattner via swift-evolution
On Nov 20, 2017, at 10:36 PM, Chris Lattner  wrote:
> Hi all,
> 
> I’ve significantly revised the ‘dynamic member lookup’ pitch, here’s the 
> second edition:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> 
> I’ve incorporated some minor changes to it:
> - I’ve made it possible to provide read-only dynamic members.
> - I’ve added an example JSON use-case which uses read-only dynamic members.
> - Minor wording changes.

Just to talk to myself a bit here, but I’ve come to realize that the right 
design really is to have a simple empty marker protocol like this:

/// Types type conform to this protocol have the behavior that member lookup -
/// accessing `someval.member` will always succeed.  Failures to find normally
/// declared members of `member` will be turned into subscript references using
/// the `someval[dynamicMember: member]` member.
///
public protocol DynamicMemberLookupProtocol {
  // Implementations of this protocol must have a subscript(dynamicMember:)
  // implementation where the keyword type is some type that is
  // ExpressibleByStringLiteral.  It can be get-only or get/set which defines
  // the mutability of the resultant dynamic properties.
  
  // subscript
  //  (dynamicMember name: KeywordType) -> LookupValue { get }
}


A design like this can almost work:

public protocol DynamicMemberLookupProtocol {
  associatedtype DynamicMemberLookupKeyword : ExpressibleByStringLiteral
  associatedtype DynamicMemberLookupValue
  
  subscript(dynamicMember name: DynamicMemberLookupKeyword)
-> DynamicMemberLookupValue { get }
}

The problem is that now everything that conforms to DynamicMemberLookupProtocol 
is a PAT, so it doesn’t work with existentials.  We could almost make due with 
a generic subscript:

public protocol DynamicMemberLookupProtocol {
  subscript
(dynamicMember name: KeywordType) -> LookupValue { get }
}

but it turns out that while you can declare that, nothing can actually conform 
to it with concrete types (I filed SR-6473, but it isn’t clear that it ever can 
work given how our generics system works).

Defining this as an empty marker protocol has several advantages:
 - Only one protocol is required
 - Suddenly you can define mutating getters and nonmutating setters
 - Existentials work as well as concrete types.

-Chris

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-21 Thread David Hart via swift-evolution
I’m very happy with this new version of the proposal. Splitting into two 
protocols makes a lot of sense - the JSON example alone is argument enough.

To bike-shedding: while I understand the need to keep the identifier names 
verbose, I would prefer the subscript label to be more representative by 
renaming it to dynamicMember - lookup can be interpreted as a verb, which is 
odd in a label.

> On 21 Nov 2017, at 07:36, Chris Lattner via swift-evolution 
>  wrote:
> 
> Hi all,
> 
> I’ve significantly revised the ‘dynamic member lookup’ pitch, here’s the 
> second edition:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> 
> I’ve incorporated some minor changes to it:
> - I’ve made it possible to provide read-only dynamic members.
> - I’ve added an example JSON use-case which uses read-only dynamic members.
> - Minor wording changes.
> 
> That said, this is significantly similar to the earlier draft.  I welcome 
> suggestions for improvements to the proposal, and insight into anything that 
> is unclear or insufficiently motivated.
> 
> Thanks!
> 
> -Chris
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution