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

2017-11-20 Thread Chris Lattner via swift-evolution
On Nov 20, 2017, at 6:12 PM, Chris Lattner via swift-evolution 
 wrote:
>> Separating method calls from property accesses solves the problem
>> 
>> Brent wrote:
>>> If we had separate subscripts for methods and properties, then the property 
>>> subscript could immediately call the appropriate getters and setters, while 
>>> the method subscript could return a ready-to-call `Method` object.
>> 
>> 
>> Better yet, why bother with the ready-to-call Method-like object? Just call 
>> it! A Ruby binding with separate property and method handling would then 
>> look like this:
>> 
>> extension RubyObj: DynamicMemberLookupProtocol {
>>   func callDynamicMethod(dynamicMethod method: String, args: 
>> [RubyObject]) -> RubyObj {
>> get {
>>   return RubyObject_send(rubyObject, method: member, args: args)
>> }
>>   }
>>   
>>   subscript(dynamicMember member: String) -> RubyObj {
>> get {
>>   return RubyObject_send(rubyObject, method: member, args: [])
>> }
>> set {
>>   RubyObject_send(rubyObject, method: "\(member)=", args: [newValue])
>> }
>>   }
>> }
>> 
>> When Swift sees myObj.name, it uses the getter subscript. When Swift sees 
>> myObj.name(), it uses the method invocation. Both work in Swift just as they 
>> do in Ruby — and more importantly, Ruby APIs wouldn’t feel so very awkward 
>> when used from Swift.
> 
> Right, that should work directly!
> 

I just sent out draft 2 of the DynamicCallable proposal, which directly 
includes support for this.  Thanks for the discussion and insight!

-Chris

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


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

2017-11-20 Thread Chris Lattner via swift-evolution
On Nov 20, 2017, at 7:15 PM, Michel Fortin via swift-evolution 
 wrote:
>>> As in `SupplementalDynamicMemberLookupProtocol` and 
>>> `supplementalDynamicMember` for the subscript.
>> 
>> I’m totally open to suggestions for a better name, but I don’t see what 
>> “Supplemental” is adding here.  Recall that this protocol is compiler 
>> “magic” that is part of an implementation of a type, it isn’t really part of 
>> the user-exposed API of the type.  I wouldn’t expect a user to ever write:
>> 
>>pyVal[dynamicMember: “foo”]
>> 
>> Even though they could.
> 
> I'm not sure why you say it's not part of the user-exposed API. The type 
> conforms to the protocol, and the protocol has this subscript, and there is 
> nothing preventing someone from using it.

Yes, I understand that of course.

> And if for some reason you have the name of the member in a string variable 
> and want to use it, you *have to* use it to get to the variable. So it'll 
> definitely get used.

Not necessarily.  Nothing prevents a *specific* client from implementing a 
better accessor for their specific use, and I’d strongly encourage them to do 
so.  This is a compiler hook - just like ExpressibleByArrayLiteral exposes an 
ArrayLiteralElement associated type and init(arrayLiteral:..) initializer… even 
on Set! 

I have definitely seen user code using these, but that isn’t the intention.  
The best solution to this is either to prevent them from being exported as API 
(my suggestion of something something like a “private conformance” 
implementation detail thing) or by simply marking these members with an 
attribute, so they don’t show up in code completion.

I do care about this sort of thing getting fixed, and I personally prefer the 
attribute+code completion change, but this is an existing problem in swift, 
orthogonal from this proposal.  If you’d like to see if fixed, then by all 
means, please bring this up and fix it.  It is more offensive that Int gets 
weird members like IntegerLiteralType and an integerLiteral initializer 
[[[which show up all the time…. :-( :-(   ]]] than the specific impact this 
proposal will have on a small set of narrow types people hardly interact with.

> Perhaps supplemental isn't the right word, but I wanted to convey that it 
> supplements the Swift-defined methods and does not shadow them. For instance, 
> in your PyVal protocol type there's a member `ownedPyObject` that won't be 
> accessible with `dynamicMember` but will be dispatched through the protocol 
> witness table.

Yes, I understand what you’re saying, but specific naming does matter.  I don’t 
think that ownedPyObject is in huge danger of conflicting with something that 
matters, but if it were, I’d suggest name mangling it to something even less 
likely to conflict, and I’d mark ownedPyObject with the same attribute to hide 
it from code completion, so people don’t see it every time they code complete 
on a PyVal.

-Chris

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


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

2017-11-20 Thread Michel Fortin via swift-evolution
> Le 20 nov. 2017 à 21:22, Chris Lattner  a écrit :
> 
>> On Nov 16, 2017, at 4:49 AM, Michel Fortin via swift-evolution 
>>  wrote:
>> 
>> I think this protocol and its subscript need a better name. From a user of 
>> the class point of view, the subscript looks like you can retrieve the 
>> members of the class, whereas in reality you'll only get the ones you have 
>> manually implemented. Even methods and properties having the `dynamic` 
>> attribute won't be available, even though the subscript name would suggest 
>> that.
>> 
>> I would propose adding the word `supplemental`to the subscript name and the 
>> name of the protocol to make it clearer that this is only for adding members 
>> that are not declared in the class (including the `dynamic` ones).
>> 
>> As in `SupplementalDynamicMemberLookupProtocol` and 
>> `supplementalDynamicMember` for the subscript.
> 
> I’m totally open to suggestions for a better name, but I don’t see what 
> “Supplemental” is adding here.  Recall that this protocol is compiler “magic” 
> that is part of an implementation of a type, it isn’t really part of the 
> user-exposed API of the type.  I wouldn’t expect a user to ever write:
> 
>pyVal[dynamicMember: “foo”]
> 
> Even though they could.

I'm not sure why you say it's not part of the user-exposed API. The type 
conforms to the protocol, and the protocol has this subscript, and there is 
nothing preventing someone from using it. And if for some reason you have the 
name of the member in a string variable and want to use it, you *have to* use 
it to get to the variable. So it'll definitely get used.

Perhaps supplemental isn't the right word, but I wanted to convey that it 
supplements the Swift-defined methods and does not shadow them. For instance, 
in your PyVal protocol type there's a member `ownedPyObject` that won't be 
accessible with `dynamicMember` but will be dispatched through the protocol 
witness table.

> Maybe we need to add private conformances to Swift or something :-)

Maybe, but that's not part of the proposal. :-)

-- 
Michel Fortin
https://michelf.ca

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


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

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

> On Nov 16, 2017, at 4:49 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> I think this protocol and its subscript need a better name. From a user of 
> the class point of view, the subscript looks like you can retrieve the 
> members of the class, whereas in reality you'll only get the ones you have 
> manually implemented. Even methods and properties having the `dynamic` 
> attribute won't be available, even though the subscript name would suggest 
> that.
> 
> I would propose adding the word `supplemental`to the subscript name and the 
> name of the protocol to make it clearer that this is only for adding members 
> that are not declared in the class (including the `dynamic` ones).
> 
> As in `SupplementalDynamicMemberLookupProtocol` and 
> `supplementalDynamicMember` for the subscript.

I’m totally open to suggestions for a better name, but I don’t see what 
“Supplemental” is adding here.  Recall that this protocol is compiler “magic” 
that is part of an implementation of a type, it isn’t really part of the 
user-exposed API of the type.  I wouldn’t expect a user to ever write:

   pyVal[dynamicMember: “foo”]

Even though they could.  Maybe we need to add private conformances to Swift or 
something :-)

-Chris


> 
> 
>> Le 15 nov. 2017 à 2:29, Chris Lattner via swift-evolution 
>> > a écrit :
>> 
>> protocol DynamicMemberLookupProtocol {
>>   associatedtype DynamicMemberLookupValue
>> 
>>   subscript(dynamicMember name: String) -> DynamicMemberLookupValue { get 
>> set }
>> }
>> 
> 
> -- 
> Michel Fortin
> https://michelf.ca 
> ___
> 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] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-20 Thread Chris Lattner via swift-evolution
> On Nov 20, 2017, at 6:06 PM, Paul Cantrell  wrote:
>> 
>> I think you’re missing the idea here: the idea isn’t to provide exactly 
>> syntax mapping of Ruby (or Python) into Swift, it is to expose the 
>> underlying semantic concepts in terms of Swift’s syntax.  In the case of 
>> Python, there is a lot of direct overlap, but there is also some places 
>> where Swift and Python differs (e.g. Python slicing syntax vs Swift ranges). 
>>  In my opinion, Swift syntax wins here, we shouldn’t try to ape a non-native 
>> syntax in Swift.
>> 
>>> For mapping to Swift, I would say that parens are needed; we can’t guess 
>>> whether a `foo.bar` is meant to be asking for the value of attribute bar or 
>>> a reference to method bar.
>> 
>> +1
> 
> Chris, did you follow at all the earlier chain of emails where Brent, 
> Jean-Daniel and I hashed this out at length? You may not have got to it yet….

Perhaps not, I’m just catching up on this thread now.  Keep in mind I know 
almost nothing about Ruby :-)


> An “always use parens” bridge to Ruby has bad ergonomics
> Zero-arg Ruby methods are a mixture of property-like things that would 
> certainly not use parens in Swift, and function-like things that certainly 
> would:
> 
> // Idiomatic Swift:
> post.author.name.reversed()
> 
> // Swift bridging to Ruby…
> 
> // …if no-args methods •must• use parens:
> post.author().name().reverse()
> 
> // …if no-args methods •can’t• use parens:
> post.author.name.reverse
> 
> If the goal is to make Swift mostly feel like Swift even when bridging to 
> Ruby, then the bridge needs to support both access forms.

Ok, that can certainly be implemented by the two proposals I have in flight.  
No obvious problem there.


> Separating method calls from property accesses solves the problem
> 
> Brent wrote:
>> If we had separate subscripts for methods and properties, then the property 
>> subscript could immediately call the appropriate getters and setters, while 
>> the method subscript could return a ready-to-call `Method` object.
> 
> 
> Better yet, why bother with the ready-to-call Method-like object? Just call 
> it! A Ruby binding with separate property and method handling would then look 
> like this:
> 
> extension RubyObj: DynamicMemberLookupProtocol {
>   func callDynamicMethod(dynamicMethod method: String, args: 
> [RubyObject]) -> RubyObj {
> get {
>   return RubyObject_send(rubyObject, method: member, args: args)
> }
>   }
>   
>   subscript(dynamicMember member: String) -> RubyObj {
> get {
>   return RubyObject_send(rubyObject, method: member, args: [])
> }
> set {
>   RubyObject_send(rubyObject, method: "\(member)=", args: [newValue])
> }
>   }
> }
> 
> When Swift sees myObj.name, it uses the getter subscript. When Swift sees 
> myObj.name(), it uses the method invocation. Both work in Swift just as they 
> do in Ruby — and more importantly, Ruby APIs wouldn’t feel so very awkward 
> when used from Swift.

Right, that should work directly!

-Chris


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


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

2017-11-20 Thread Chris Lattner via swift-evolution
> On Nov 15, 2017, at 10:00 PM, Brent Royal-Gordon  
> wrote:
>> On Nov 14, 2017, at 11:29 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> extension PyVal {
>>   subscript(dynamicMember member: String) -> PyVal {
>> get {
>>   let result = PyObject_GetAttrString(borrowedPyObject, member)!
>>   return PyRef(owned: result)  // PyObject_GetAttrString returns +1 
>> result.
>> }
>> set {
>>   PyObject_SetAttrString(borrowedPyObject, member,
>>  newValue.toPython().borrowedPyObject)
>> }
>>   }
>> }
> 
> This looks great for Python, but let's talk about some other languages for a 
> moment.
> 
> * Ruby and Perl don't have the "call a method by fetching a closure property 
> and invoking it" behavior you're relying on here. Instead, Ruby has a syntax 
> for settable "overloads" of methods (i.e. you can write `def someMember` and 
> `def someMember= (newValue)`), while Perl supports lvalue methods (but 
> sometimes uses getter and setter method pairs instead). How do you envision 
> these behaviors being bridged to Swift? I worry that this protocol may not be 
> sufficient, and that we may need a design which can distinguish between 
> looking up methods and looking up properties.

I’m not sure without more description, but it seems like these are both general 
property models which can be implemented with this protocol as is.  The getter 
would call someMember, and the setter would call someMember=.  What 
complication are you anticipating?


> * Ruby looks up members using symbols, which essentially play the same role 
> as selectors in Objective-C—they're uniqued strings which are used for fast 
> member dispatch. In some cases, you might see non-negligible speed 
> improvements by only looking up the symbol once. Is there a way this design 
> could accommodate that? 

Yes, I think that this is very much in scope for the DynamicCallable proposal.  
We talked about this in the context of Squeak (another smalltalky language), 
and it fits naturally with the design.  I’ll add that when I have time to 
revise the pitch.

> * Generally, you've talked about properties (in this proposal) and methods 
> (in the `DynamicCallable` proposal), but what about subscripts? Obviously you 
> can just specify a `subscript(Pythonable) -> PyVal` on `PyVal` for the simple 
> case, but what if the subscript takes multiple indices or has labels? Do we 
> need a `DynamicSubscriptable` protocol?

Subscripts can already be varargs, so the only reason we’d need a 
DynamicSubscriptable proposal is if there were another language that allowed 
keywords on subscript indices.  If so, then yes, we’d need that.

> * Let's step away from bridging entirely and just think about Swift for a 
> moment.  There are cases where we'd like to make *semi*-dynamic proxies which 
> wrap another type and allow operations based on what's statically known about 
> that type. Think, for example, of the appearance proxy in UIKit: This is an 
> object attached to UIView subclasses which lets you (in essence) set default 
> values for all instances. We currently just pretend it's an instance of 
> `Self`, which mostly works because of Objective-C, but a Swift-native version 
> would probably prefer to return a `UIAppearance` object which used its 
> knowledge of `Self` to expose `Self`'s properties on itself. Is there a way 
> we could design this feature, or a related feature, to cover that kind of use 
> case? That is, to allow a limited set of keys—perhaps even key-path-based 
> when you want static control—with a different type for each key, *or* to 
> allow any key with some common type, depending on your type's needs?

I wouldn’t be at all surprised if this was possible, but given that this type 
erases everything that goes through the proxy, and given that it doesn’t 
provide type checking, it isn’t clear to me that you’d get a really great 
answer.

> * Actually, for that matter, let's talk about key paths. In principle, you 
> can already think of member lookup in Swift—or at least property and 
> subscript lookup—as though it always worked by constructing a key path and 
> using `subscript(keyPath:)` to access it. Is there some way we could model 
> this feature as extending the set of keys available on a given type—perhaps 
> in a way that allowed compile-time-limited and strongly-typed sets of keys, 
> like I mention with the `UIAppearance` example, in addition to the 
> open-ended, type-erased sets you need—and then looking things up by key path? 
> (Sorry if this is a little vague—I know very little about how key paths are 
> implemented.)

I don’t know.

> * An implementation-level question about Swift: Internally, the compiler 
> seems to be moving towards thinking of parameter labels as part of the 
> identifier, rather than having them label the individual arguments. How do 
> you see that jibing 

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

2017-11-20 Thread Paul Cantrell via swift-evolution

> On Nov 20, 2017, at 7:47 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Nov 20, 2017, at 1:41 PM, David Waite  
>> wrote:
>> 
>> In ruby, parens are optional. So,
>> 
>> v = foo.value
>> 
>> and
>> 
>> v = foo.value()
>> 
>> are identical.
> 
> Ok, I wasn’t aware of that.  It isn’t clear that we’d want to carry that into 
> a “Ruby APIs when used in Swift” though!  One could definitely argue against 
> the former calling a method, even if that is possible in Ruby APIs.
> 
>> There dot syntax is only used for method invocation, so there is no external 
>> access to instance variables without some twiddling; similarly getting 
>> access to a Proc/lambda/Method requires twiddling in Ruby (although there 
>> are shortcuts in normal use, like Symbol#to_proc)
> 
> I think you’re missing the idea here: the idea isn’t to provide exactly 
> syntax mapping of Ruby (or Python) into Swift, it is to expose the underlying 
> semantic concepts in terms of Swift’s syntax.  In the case of Python, there 
> is a lot of direct overlap, but there is also some places where Swift and 
> Python differs (e.g. Python slicing syntax vs Swift ranges).  In my opinion, 
> Swift syntax wins here, we shouldn’t try to ape a non-native syntax in Swift.
> 
>> For mapping to Swift, I would say that parens are needed; we can’t guess 
>> whether a `foo.bar` is meant to be asking for the value of attribute bar or 
>> a reference to method bar.
> 
> +1

Chris, did you follow at all the earlier chain of emails where Brent, 
Jean-Daniel and I hashed this out at length? You may not have got to it yet….

Key excerpts:

–

An “always use parens” bridge to Ruby has bad ergonomics
Zero-arg Ruby methods are a mixture of property-like things that would 
certainly not use parens in Swift, and function-like things that certainly 
would:

// Idiomatic Swift:
post.author.name.reversed()

// Swift bridging to Ruby…

// …if no-args methods •must• use parens:
post.author().name().reverse()

// …if no-args methods •can’t• use parens:
post.author.name.reverse

If the goal is to make Swift mostly feel like Swift even when bridging to Ruby, 
then the bridge needs to support both access forms.

–

Separating method calls from property accesses solves the problem

Brent wrote:
> If we had separate subscripts for methods and properties, then the property 
> subscript could immediately call the appropriate getters and setters, while 
> the method subscript could return a ready-to-call `Method` object.


Better yet, why bother with the ready-to-call Method-like object? Just call it! 
A Ruby binding with separate property and method handling would then look like 
this:

extension RubyObj: DynamicMemberLookupProtocol {
  func callDynamicMethod(dynamicMethod method: String, args: [RubyObject]) 
-> RubyObj {
get {
  return RubyObject_send(rubyObject, method: member, args: args)
}
  }
  
  subscript(dynamicMember member: String) -> RubyObj {
get {
  return RubyObject_send(rubyObject, method: member, args: [])
}
set {
  RubyObject_send(rubyObject, method: "\(member)=", args: [newValue])
}
  }
}

When Swift sees myObj.name, it uses the getter subscript. When Swift sees 
myObj.name(), it uses the method invocation. Both work in Swift just as they do 
in Ruby — and more importantly, Ruby APIs wouldn’t feel so very awkward when 
used from Swift.


> 
>> More difficult would be the use of ‘=‘, ‘!’, and ‘?’ - all legal in Ruby 
>> method names as suffixes.
> 
> Using those would require backquotes:
> 
> x.`what?`() 
> 
> 
> -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] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-20 Thread Chris Lattner via swift-evolution
On Nov 15, 2017, at 8:35 PM, Paul Cantrell via swift-evolution 
 wrote:
> Interesting! I like the spirit of this proposal a lot.
> 
> One question: presumably this behaves like Ruby’s method_missing in that any 
> natively implemented members shadow the dynamic ones? i.e. Swift looks for a 
> static match first, then uses the dynamicMember only as a fallback?

Right.  I added that to the proposal in the “API resilience section”.

> Q: It seems like this fundamentally alters Swift’s aesthetic of “either an 
> operation is type-safe, or it’s clear at the point of use that it’s not.”  
> Should this use an operator other than a period, e.g. `pickle->loads(blob)`?

AnyObject dispatch is the closest relative to this feature that Swift currently 
has, and is neither type safe nor unsurprising. :-)

It is important to note that implementations of this protocol can definitely 
implement it in terms of optionals, so it is completely type safe.  Consider a 
JSON implementation for example: the dynamic getter would return a type of 
“JSON?”.  That design is fully type safe.

> Q: Why the open-ended `associatedtype DynamicMemberLookupValue`? Seems like 
> it will always just be Self in practice.
> 
> A: It would be Self in the Python and JSON examples in the proposal, but 
> making it an associatedtype adds no implementation burden, does no apparent 
> harm, and adds flexibility. Shifting types on traversal could be particularly 
> useful in creating DSLs (e.g. sepia → Genus, sepia.officinalis → Species).

Not necessarily the same.  Consider a bad use of this for sugaring a string to 
int dictionary.  The string “keys” would be the “dynamicMember", but the 
DynamicMemberLookupValue would be the key type: Int. 


> Q: Is there any special handling for that member name string — to handle ruby 
> method names like `blank?`, for example?

A: Use the standard Swift backquote mechanism:   x.`blank?`()


> Q: Should the subscript also take arg types and/or labels to allow 
> overloading?
> 
> A: Ruby, Python, and JS all resolve members by name alone, and leave it to 
> functions to untangle their own args. Obj-C is the lone oddball here. Relying 
> on the companion proposal to handle the args makes sense.

AFAIK, Swift’s subscript model is already general enough to do what we need it 
to do, but if there is some interesting language that isn’t served by it, we 
can talk about that when it comes up.

-Chris


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


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

2017-11-18 Thread Paul Cantrell via swift-evolution

> On Nov 18, 2017, at 1:44 AM, Jean-Daniel  wrote:
> 
> 
>> …
>> 
>> In Ruby, `myObj.name()` is equivalent to `myObj.name`, and either works. In 
>> Swift, I don’t see that it’s possible to make both work with Chris’s 
>> proposal.
> 
> IIUC, the goal is not to make swift look and behave the same as ruby or 
> python, but to be able to use ruby or python object in a swift way (without 
> indirect call and other nasty constructions). I don’t see requiring the 
> .property syntax and prohibiting the .property() one as an issue. I would 
> even say this is the thing to do, as it would make the swift code more 
> understandable to Swift dev that are not used to Ruby.


It really wouldn’t. Zero-arg Ruby methods are a mixture of property-like things 
that would certainly not use parens in Swift, and function-like things that 
certainly would:

// Idiomatic Swift:
post.author.name.reversed()

// Swift bridging to Ruby…

// …if no-args methods •must• use parens:
post.author().name().reverse()

// …if no-args methods •can’t• use parens:
post.author.name.reverse

If the goal is to make Swift mostly look like Swift even when bridging to Ruby, 
then the bridge needs to support both access forms.

Cheers, P

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


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

2017-11-17 Thread Jean-Daniel via swift-evolution

> …
> 
> In Ruby, `myObj.name()` is equivalent to `myObj.name`, and either works. In 
> Swift, I don’t see that it’s possible to make both work with Chris’s proposal.

IIUC, the goal is not to make swift look and behave the same as ruby or python, 
but to be able to use ruby or python object in a swift way (without indirect 
call and other nasty constructions).

I don’t see requiring the .property syntax and prohibiting the .property() one 
as an issue. I would even say this is the thing to do, as it would make the 
swift code more understandable to Swift dev that are not used to Ruby.


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


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

2017-11-17 Thread Paul Cantrell via swift-evolution
> On Nov 17, 2017, at 12:08 AM, Brent Royal-Gordon  
> wrote:
> 
>> On Nov 16, 2017, at 1:44 PM, Paul Cantrell > > wrote:
>> 
>> In the example you bring up:
>> 
>>> you can write `def someMember` and `def someMember= (newValue)`)
>> 
>> …there is no overloading. The = is _part of the method name_, i.e. there is 
>> a `someMember` method and a `someMember=` method.
> 
> You're right—I was speaking imprecisely when I used the word "overloading". 
> Nevertheless, Ruby doesn't quite directly interpret `x.someMember = y` as 
> `x.someMember= (y)`—it supports operators like `+=`, which do a 
> getter-operation-setter dance.

True, `foo.bar += x` is just sugar for `foo.bar = foo.bar + x`, which in turn 
is sugar for `foo.bar=(foo.bar.+(y))`. But does this pose a problem for a Swift 
→ Ruby bridge? Presumably such a bridge would:

1. define a Swift += operator on RubyObj that does the same expansion as above, 
and

2. forward the property setter for `bar` to Ruby as a `bar=` invocation.

I don’t think there’s a problem here. But maybe I’m missing it?

> 
>> The following are equivalent:
>> 
>> foo.bar = 3  # just sugar
>> foo.bar=(3)
>> foo.send("bar=", 3)
>> 
>> Ruby allows ?, !, and = as the last char of method names, and AFAIK other 
>> than the special sugar around setters, they are just parts of the method 
>> name with no further semantic significance.
> 
> You're correct that, with this design, you could access Ruby accessors from 
> Swift with syntax like:
> 
>   myObj.name()
>   myObj.`name=`("Chris")  // If we loosened the characters 
> allowed in backticks
> 
> My point is simply that this is a poor mapping, for much the same reason 
> `dog["add_trick"].call(…)` is a poor mapping. It's technically correct and 
> exposes the functionality, but it's awkward and doesn't match the user's 
> mental model.

Well sure, that would be awkward, but doesn’t Chris’s proposed protocol allow 
idiomatic access to work too?

extension RubyObj: DynamicMemberLookupProtocol {
  subscript(dynamicMember member: String) -> RubyObj {
get {
  return /* …some deferred callable thing… */
}
set {
  RubyObject_send(rubyObject, method: "\(member)=", args: [newValue])
}
  }
}

That would make `myObj.name = “Chris"` in Swift work as expected. (This is 
using a made-up RubyObj binding, but I think it makes the point.)

What _is_ a bit nasty, as you pointed out, is that `myObj.name` does _not_ work 
as expected. Instead of returning the name, it returns a closure that returns 
the name when called. Yuck.

In Ruby, `myObj.name()` is equivalent to `myObj.name`, and either works. In 
Swift, I don’t see that it’s possible to make both work with Chris’s proposal.

> If we had separate subscripts for methods and properties, then the property 
> subscript could immediately call the appropriate getters and setters, while 
> the method subscript could return a ready-to-call `Method` object.

Hmm, yes, I think you’re right. It seems like that would fix the nastiness 
above. Better yet, why bother with the ready-to-call Method-like object? Just 
call it! A Ruby binding with separate property and method handling would then 
look like this:

extension RubyObj: DynamicMemberLookupProtocol {
  func callDynamicMethod(dynamicMethod method: String, args: [RubyObject]) 
-> RubyObj {
get {
  return RubyObject_send(rubyObject, method: member, args: args)
}
  }
  
  subscript(dynamicMember member: String) -> RubyObj {
get {
  return RubyObject_send(rubyObject, method: member, args: [])
}
set {
  RubyObject_send(rubyObject, method: "\(member)=", args: [newValue])
}
  }
}

When Swift sees myObj.name, it uses the getter subscript. When Swift sees 
myObj.name(), it uses the method invocation. Both work in Swift just as they do 
in Ruby.

Note that for this to work, the Swift compiler itself has to tell the Ruby 
binding whether the member access looks like a property or method access.

• • •

I confess I didn’t follow every detail of your “wall of text,” but I did find 
this example compelling:

> That would work for arbitrary fixed sets of properties, but we can extend 
> this to wrapper types. Imagine you want to write the `UIAppearance` class I 
> mentioned previously. (Actually, we'll call it `UIAppearanceProxy` to avoid 
> names already used in UIKit.) Your basic structure looks like this:
> 
>   class UIAppearanceProxy {
>   let containers: [UIAppearanceContainer.Type]
>   let traits: UITraitCollection
>   
>   var properties: [PartialKeyPath: Any] = [:]
>   }
> 
> Now, to make all properties of the `View` class settable on this class, you 
> can overload the `additionalProperty` subscript to accept `View` keypaths:
> 
> 

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

2017-11-17 Thread Brent Royal-Gordon via swift-evolution
> On Nov 16, 2017, at 10:08 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> So, let me sketch a vague idea of how this might work. This is definitely not 
> fully baked, but it might give you an idea.

Looking at this again, I realize I accidentally generated a giant wall of text. 
tl;dr:

* There is no protocol; this is done through an ad-hoc mechanism to allow 
overloading.

* Use `subscript(additionalProperty:)` to dynamically create a property. The 
parameter type can be any of:

* An arbitrary type: compiler will look for static constants (including 
no-payload cases) of the type accepted by the parameter, and treat them as 
valid properties of `Self`.
* A `KeyPath` type: compiler will look for properties on the KeyPath's 
Root type and treat them as valid properties of `Self`.
* An `ExpressibleByStringLiteral` type: compiler will treat any 
identifier as a valid property.

* Use `subscript(additionalMethod:)` to dynamically create methods. The 
subscript returns a closure which is already bound to `self`, but not to the 
parameters. The parameter type can be any of:

* An arbitrary type: compiler will look for static methods (including 
cases) returning the type accepted by the parameter and whose parameters are 
all metatypes, and will treat them as valid methods of `Self` (after 
transforming all metatypes into plain types).
* A `(Foo) -> (ParamList) -> ReturnValue` type (i.e. an unbound 
method): Compiler will treat all instance methods of `Foo` as valid methods of 
`Self`.
* An `ExpressibleByStringLiteral` type: compiler will treat any 
identifier as a valid method (and will pass both the base name and argument 
labels in a single string).

* The string literal forms cover use cases where you want to accept anything 
and sort it out at runtime. The keypath/unbound method forms cover use cases 
where you're echoing the interface of an underlying type. The arbitrary type 
forms cover use cases where you want to create members based on compact tables 
of information.

tl;dr for the tl;dr: I think we can cover a ton of use cases for automatically 
"creating" properties and methods using minor variations on a single mechanism 
which only vaguely resembles this one.

-- 
Brent Royal-Gordon
Architechies

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


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

2017-11-16 Thread Brent Royal-Gordon via swift-evolution
> On Nov 16, 2017, at 1:44 PM, Paul Cantrell  wrote:
> 
>> On Nov 16, 2017, at 12:00 AM, Brent Royal-Gordon via swift-evolution 
>> > wrote:
>> 
>> * Ruby and Perl don't have the "call a method by fetching a closure property 
>> and invoking it" behavior you're relying on here. Instead, Ruby has a syntax 
>> for settable "overloads" of methods (i.e. you can write `def someMember` and 
>> `def someMember= (newValue)`), while Perl supports lvalue methods (but 
>> sometimes uses getter and setter method pairs instead). How do you envision 
>> these behaviors being bridged to Swift? I worry that this protocol may not 
>> be sufficient, and that we may need a design which can distinguish between 
>> looking up methods and looking up properties.
> 
> I’ve never pried the lid of Ruby’s implementation of method dispatch, but I’m 
> pretty sure that if foo defines a bar method, then
> 
> foo.bar(…args…)
> 
> is fully equivalent to:
> 
> foo.method(:bar).call(…args…)
> 
> IOW, there is an intermediate Method object that would fit the shape of the 
> proposed callable protocol.
> 
> If foo instead doesn’t actually declare the bar method, but instead handles 
> it via method_missing or __send__, then foo.method(:bar) raises an exception. 
> However, it would be trivial to write a deferred invocation wrapper that also 
> fits the shape of the proposed protocols and calls foo.send(“bar”, …args…) at 
> the appropriate time.
> 
> In short, I don’t think there’s a problem here.

True. Ruby doesn't dispatch everything through a Method object…but I guess 
Swift sort of does, and we're bridging semantics into Swift here.

> In the example you bring up:
> 
>> you can write `def someMember` and `def someMember= (newValue)`)
> 
> …there is no overloading. The = is _part of the method name_, i.e. there is a 
> `someMember` method and a `someMember=` method.

You're right—I was speaking imprecisely when I used the word "overloading". 
Nevertheless, Ruby doesn't quite directly interpret `x.someMember = y` as 
`x.someMember= (y)`—it supports operators like `+=`, which do a 
getter-operation-setter dance.

> The following are equivalent:
> 
> foo.bar = 3  # just sugar
> foo.bar=(3)
> foo.send("bar=", 3)
> 
> Ruby allows ?, !, and = as the last char of method names, and AFAIK other 
> than the special sugar around setters, they are just parts of the method name 
> with no further semantic significance.

You're correct that, with this design, you could access Ruby accessors from 
Swift with syntax like:

myObj.name()
myObj.`name=`("Chris")  // If we loosened the characters 
allowed in backticks

My point is simply that this is a poor mapping, for much the same reason 
`dog["add_trick"].call(…)` is a poor mapping. It's technically correct and 
exposes the functionality, but it's awkward and doesn't match the user's mental 
model.

If we had separate subscripts for methods and properties, then the property 
subscript could immediately call the appropriate getters and setters, while the 
method subscript could return a ready-to-call `Method` object. This would 
prevent you from fetching uncalled methods using the `x.method` syntax (as 
opposed to `x.method(_:)`, which could be made to work), but that seems a lot 
better than a mapping that's technically correct but breaks the mental model.

>> * Let's step away from bridging entirely and just think about Swift for a 
>> moment. There are cases where we'd like to make *semi*-dynamic proxies which 
>> wrap another type and allow operations based on what's statically known 
>> about that type. Think, for example, of the appearance proxy in UIKit: This 
>> is an object attached to UIView subclasses which lets you (in essence) set 
>> default values for all instances. We currently just pretend it's an instance 
>> of `Self`, which mostly works because of Objective-C, but a Swift-native 
>> version would probably prefer to return a `UIAppearance` object which 
>> used its knowledge of `Self` to expose `Self`'s properties on itself. Is 
>> there a way we could design this feature, or a related feature, to cover 
>> that kind of use case? That is, to allow a limited set of keys—perhaps even 
>> key-path-based when you want static control—with a different type for each 
>> key, *or* to allow any key with some common type, depending on your type's 
>> needs?
> 
> Per my question about whether native methods shadow dynamic ones, one might 
> be able to achieve some of this using a mix of statically typed, statically 
> declared methods + dynamic members.

So, let me sketch a vague idea of how this might work. This is definitely not 
fully baked, but it might give you an idea.

Imagine you want to write an ORM. Its root class, `Record`, should expose a 
property for each field in a given record. You could make the ORM generate an 
enum like this:

enum 

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

2017-11-16 Thread Paul Cantrell via swift-evolution
[Arg, I keep sending these with the wrong from address and getting bounced! 
Excited for Discourse…]


> On Nov 16, 2017, at 12:00 AM, Brent Royal-Gordon via swift-evolution 
> > wrote:
> 
>> On Nov 14, 2017, at 11:29 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> extension PyVal {
>>   subscript(dynamicMember member: String) -> PyVal {
>> get {
>>   let result = PyObject_GetAttrString(borrowedPyObject, member)!
>>   return PyRef(owned: result)  // PyObject_GetAttrString returns +1 
>> result.
>> }
>> set {
>>   PyObject_SetAttrString(borrowedPyObject, member,
>>  newValue.toPython().borrowedPyObject)
>> }
>>   }
>> }
> 
> This looks great for Python, but let's talk about some other languages for a 
> moment.
> 
> * Ruby and Perl don't have the "call a method by fetching a closure property 
> and invoking it" behavior you're relying on here. Instead, Ruby has a syntax 
> for settable "overloads" of methods (i.e. you can write `def someMember` and 
> `def someMember= (newValue)`), while Perl supports lvalue methods (but 
> sometimes uses getter and setter method pairs instead). How do you envision 
> these behaviors being bridged to Swift? I worry that this protocol may not be 
> sufficient, and that we may need a design which can distinguish between 
> looking up methods and looking up properties.

I’ve never pried the lid of Ruby’s implementation of method dispatch, but I’m 
pretty sure that if foo defines a bar method, then

foo.bar(…args…)

is fully equivalent to:

foo.method(:bar).call(…args…)

IOW, there is an intermediate Method object that would fit the shape of the 
proposed callable protocol.

If foo instead doesn’t actually declare the bar method, but instead handles it 
via method_missing or __send__, then foo.method(:bar) raises an exception. 
However, it would be trivial to write a deferred invocation wrapper that also 
fits the shape of the proposed protocols and calls foo.send(“bar”, …args…) at 
the appropriate time.

In short, I don’t think there’s a problem here.

In the example you bring up:

> you can write `def someMember` and `def someMember= (newValue)`)

…there is no overloading. The = is _part of the method name_, i.e. there is a 
`someMember` method and a `someMember=` method. The following are equivalent:

foo.bar = 3  # just sugar
foo.bar=(3)
foo.send("bar=", 3)

Ruby allows ?, !, and = as the last char of method names, and AFAIK other than 
the special sugar around setters, they are just parts of the method name with 
no further semantic significance.

> * Ruby looks up members using symbols, which essentially play the same role 
> as selectors in Objective-C—they're uniqued strings which are used for fast 
> member dispatch. In some cases, you might see non-negligible speed 
> improvements by only looking up the symbol once. Is there a way this design 
> could accommodate that? For instance, could the type of the index be 
> specified by an associated type, so Ruby could use a RbSymbol instead of a 
> String? Or do you think that would be overkill?

Good question. The language gets its symbol speedup by canonicalizing symbols 
at compile time when possible, and that failing, when symbolicated instead of 
when dispatched:

one_zillion.times { foo.some_long_method_name }  # fastest

# only ~1.5x slower than prev, despite one extra method dispatch:
one_zillion.times { foo.send(:some_long_method_name) }

# performance identical to previous:
symbol = string.to_sym
one_zillion.times { foo.send(symbol) }

# ~2x slower:
one_zillion.times { foo.send(string) }

(Those are based on actual benchmarks.)

Swift should be able to do the same optimizations. Making the method name a 
string would preclude that.

> 
> * Generally, you've talked about properties (in this proposal) and methods 
> (in the `DynamicCallable` proposal), but what about subscripts? Obviously you 
> can just specify a `subscript(Pythonable) -> PyVal` on `PyVal` for the simple 
> case, but what if the subscript takes multiple indices or has labels? Do we 
> need a `DynamicSubscriptable` protocol?
> 
> * Let's step away from bridging entirely and just think about Swift for a 
> moment. There are cases where we'd like to make *semi*-dynamic proxies which 
> wrap another type and allow operations based on what's statically known about 
> that type. Think, for example, of the appearance proxy in UIKit: This is an 
> object attached to UIView subclasses which lets you (in essence) set default 
> values for all instances. We currently just pretend it's an instance of 
> `Self`, which mostly works because of Objective-C, but a Swift-native version 
> would probably prefer to return a `UIAppearance` object which used its 
> knowledge of `Self` to expose `Self`'s properties on itself. Is there 

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

2017-11-16 Thread Michel Fortin via swift-evolution
Key paths could be made to work by implementing the protocol in terms of 
retrieving key paths instead:

protocol SupplementalKeyPathDispatching {
associatedType KP: PartialKeyPath
static func supplementalKeyPath(for name: String) -> KP
}

and in your implementation of PyVal:

extension PyVal: SupplementalKeyPathDispatching {
static func supplementalKeyPath(for name: String) -> KeyPath {
return \PyVal[dynamicMember: name]
}
}

The compiler then implements two transforms:

\PyVal.add_trick
// becomes:
PyVal.supplementalKeyPath(for: "add_trick")
// returns key path \PyVal[dynamicMember: name]

and:

let Dog = Python.import(“DogModule.Dog")
let dog = Dog("Briana")

dog.add_trick("snore")
// becomes:
dog[keyPath: \PyVal.add_trick]("snore")
// or fully expanded:
dog[keyPath: PyVal.supplementalKeypath(for: "add_trick")]("snore")
// calls dog[dynamicMember: name]

You now have one more level of indirection which allows key paths. There's no 
compile time checking however: all imaginable key paths will work.

> Le 16 nov. 2017 à 1:00, Brent Royal-Gordon via swift-evolution 
>  a écrit :
> 
> * Actually, for that matter, let's talk about key paths. In principle, you 
> can already think of member lookup in Swift—or at least property and 
> subscript lookup—as though it always worked by constructing a key path and 
> using `subscript(keyPath:)` to access it. Is there some way we could model 
> this feature as extending the set of keys available on a given type—perhaps 
> in a way that allowed compile-time-limited and strongly-typed sets of keys, 
> like I mention with the `UIAppearance` example, in addition to the 
> open-ended, type-erased sets you need—and then looking things up by key path? 
> (Sorry if this is a little vague—I know very little about how key paths are 
> implemented.)
> 

-- 
Michel Fortin
https://michelf.ca

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


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

2017-11-16 Thread Michel Fortin via swift-evolution
I think this protocol and its subscript need a better name. From a user of the 
class point of view, the subscript looks like you can retrieve the members of 
the class, whereas in reality you'll only get the ones you have manually 
implemented. Even methods and properties having the `dynamic` attribute won't 
be available, even though the subscript name would suggest that.

I would propose adding the word `supplemental`to the subscript name and the 
name of the protocol to make it clearer that this is only for adding members 
that are not declared in the class (including the `dynamic` ones).

As in `SupplementalDynamicMemberLookupProtocol` and `supplementalDynamicMember` 
for the subscript.


> Le 15 nov. 2017 à 2:29, Chris Lattner via swift-evolution 
>  a écrit :
> 
> protocol DynamicMemberLookupProtocol {
>   associatedtype DynamicMemberLookupValue
> 
>   subscript(dynamicMember name: String) -> DynamicMemberLookupValue { get set 
> }
> }
> 

-- 
Michel Fortin
https://michelf.ca

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


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

2017-11-16 Thread Jean-Daniel via swift-evolution


> Le 16 nov. 2017 à 07:00, Brent Royal-Gordon via swift-evolution 
>  a écrit :
> 
>> On Nov 14, 2017, at 11:29 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> extension PyVal {
>>   subscript(dynamicMember member: String) -> PyVal {
>> get {
>>   let result = PyObject_GetAttrString(borrowedPyObject, member)!
>>   return PyRef(owned: result)  // PyObject_GetAttrString returns +1 
>> result.
>> }
>> set {
>>   PyObject_SetAttrString(borrowedPyObject, member,
>>  newValue.toPython().borrowedPyObject)
>> }
>>   }
>> }
> 
> This looks great for Python, but let's talk about some other languages for a 
> moment.
> 
> * Ruby and Perl don't have the "call a method by fetching a closure property 
> and invoking it" behavior you're relying on here. Instead, Ruby has a syntax 
> for settable "overloads" of methods (i.e. you can write `def someMember` and 
> `def someMember= (newValue)`), while Perl supports lvalue methods (but 
> sometimes uses getter and setter method pairs instead). How do you envision 
> these behaviors being bridged to Swift? I worry that this protocol may not be 
> sufficient, and that we may need a design which can distinguish between 
> looking up methods and looking up properties.
> 
> * Ruby looks up members using symbols, which essentially play the same role 
> as selectors in Objective-C—they're uniqued strings which are used for fast 
> member dispatch. In some cases, you might see non-negligible speed 
> improvements by only looking up the symbol once. Is there a way this design 
> could accommodate that? For instance, could the type of the index be 
> specified by an associated type, so Ruby could use a RbSymbol instead of a 
> String? Or do you think that would be overkill?

And how would that works ? The actual proposal introduce a minor change in the 
compiler as it just has to be capable of generating a literal string from an 
identifier. To use something else (RbSymbol), the compiler would have to lean 
how to generate such object from the unresolved identifier.

One generic solution would be to make sure the key is buildable by string 
literal, but what would be the benefit here as it would not be better than 
simply create the RbSymbol directly in the specific subscript implementation.

> 
> * Generally, you've talked about properties (in this proposal) and methods 
> (in the `DynamicCallable` proposal), but what about subscripts? Obviously you 
> can just specify a `subscript(Pythonable) -> PyVal` on `PyVal` for the simple 
> case, but what if the subscript takes multiple indices or has labels? Do we 
> need a `DynamicSubscriptable` protocol?
> 
> * Let's step away from bridging entirely and just think about Swift for a 
> moment. There are cases where we'd like to make *semi*-dynamic proxies which 
> wrap another type and allow operations based on what's statically known about 
> that type. Think, for example, of the appearance proxy in UIKit: This is an 
> object attached to UIView subclasses which lets you (in essence) set default 
> values for all instances. We currently just pretend it's an instance of 
> `Self`, which mostly works because of Objective-C, but a Swift-native version 
> would probably prefer to return a `UIAppearance` object which used its 
> knowledge of `Self` to expose `Self`'s properties on itself. Is there a way 
> we could design this feature, or a related feature, to cover that kind of use 
> case? That is, to allow a limited set of keys—perhaps even key-path-based 
> when you want static control—with a different type for each key, *or* to 
> allow any key with some common type, depending on your type's needs?
> 
> * Actually, for that matter, let's talk about key paths. In principle, you 
> can already think of member lookup in Swift—or at least property and 
> subscript lookup—as though it always worked by constructing a key path and 
> using `subscript(keyPath:)` to access it. Is there some way we could model 
> this feature as extending the set of keys available on a given type—perhaps 
> in a way that allowed compile-time-limited and strongly-typed sets of keys, 
> like I mention with the `UIAppearance` example, in addition to the 
> open-ended, type-erased sets you need—and then looking things up by key path? 
> (Sorry if this is a little vague—I know very little about how key paths are 
> implemented.)
> 
> * An implementation-level question about Swift: Internally, the compiler 
> seems to be moving towards thinking of parameter labels as part of the 
> identifier, rather than having them label the individual arguments. How do 
> you see that jibing with what you're proposing here?
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> 

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

2017-11-15 Thread Brent Royal-Gordon via swift-evolution
> On Nov 14, 2017, at 11:29 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> extension PyVal {
>   subscript(dynamicMember member: String) -> PyVal {
> get {
>   let result = PyObject_GetAttrString(borrowedPyObject, member)!
>   return PyRef(owned: result)  // PyObject_GetAttrString returns +1 
> result.
> }
> set {
>   PyObject_SetAttrString(borrowedPyObject, member,
>  newValue.toPython().borrowedPyObject)
> }
>   }
> }

This looks great for Python, but let's talk about some other languages for a 
moment.

* Ruby and Perl don't have the "call a method by fetching a closure property 
and invoking it" behavior you're relying on here. Instead, Ruby has a syntax 
for settable "overloads" of methods (i.e. you can write `def someMember` and 
`def someMember= (newValue)`), while Perl supports lvalue methods (but 
sometimes uses getter and setter method pairs instead). How do you envision 
these behaviors being bridged to Swift? I worry that this protocol may not be 
sufficient, and that we may need a design which can distinguish between looking 
up methods and looking up properties.

* Ruby looks up members using symbols, which essentially play the same role as 
selectors in Objective-C—they're uniqued strings which are used for fast member 
dispatch. In some cases, you might see non-negligible speed improvements by 
only looking up the symbol once. Is there a way this design could accommodate 
that? For instance, could the type of the index be specified by an associated 
type, so Ruby could use a RbSymbol instead of a String? Or do you think that 
would be overkill?

* Generally, you've talked about properties (in this proposal) and methods (in 
the `DynamicCallable` proposal), but what about subscripts? Obviously you can 
just specify a `subscript(Pythonable) -> PyVal` on `PyVal` for the simple case, 
but what if the subscript takes multiple indices or has labels? Do we need a 
`DynamicSubscriptable` protocol?

* Let's step away from bridging entirely and just think about Swift for a 
moment. There are cases where we'd like to make *semi*-dynamic proxies which 
wrap another type and allow operations based on what's statically known about 
that type. Think, for example, of the appearance proxy in UIKit: This is an 
object attached to UIView subclasses which lets you (in essence) set default 
values for all instances. We currently just pretend it's an instance of `Self`, 
which mostly works because of Objective-C, but a Swift-native version would 
probably prefer to return a `UIAppearance` object which used its 
knowledge of `Self` to expose `Self`'s properties on itself. Is there a way we 
could design this feature, or a related feature, to cover that kind of use 
case? That is, to allow a limited set of keys—perhaps even key-path-based when 
you want static control—with a different type for each key, *or* to allow any 
key with some common type, depending on your type's needs?

* Actually, for that matter, let's talk about key paths. In principle, you can 
already think of member lookup in Swift—or at least property and subscript 
lookup—as though it always worked by constructing a key path and using 
`subscript(keyPath:)` to access it. Is there some way we could model this 
feature as extending the set of keys available on a given type—perhaps in a way 
that allowed compile-time-limited and strongly-typed sets of keys, like I 
mention with the `UIAppearance` example, in addition to the open-ended, 
type-erased sets you need—and then looking things up by key path? (Sorry if 
this is a little vague—I know very little about how key paths are implemented.)

* An implementation-level question about Swift: Internally, the compiler seems 
to be moving towards thinking of parameter labels as part of the identifier, 
rather than having them label the individual arguments. How do you see that 
jibing with what you're proposing here?

-- 
Brent Royal-Gordon
Architechies

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


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

2017-11-15 Thread Brent Royal-Gordon via swift-evolution
> On Nov 15, 2017, at 8:35 PM, Paul Cantrell via swift-evolution 
>  wrote:
> 
> Q: Is there any special handling for that member name string — to handle ruby 
> method names like `blank?`, for example?
> 
> A: This should be the job of a language-specific interop layer.

Swift has the backtick syntax for escaping keywords (`identifier`), but it 
doesn't allow non-identifier characters to be used in identifiers. We might 
explore loosening that.

-- 
Brent Royal-Gordon
Architechies

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


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

2017-11-15 Thread Paul Cantrell via swift-evolution
Interesting! I like the spirit of this proposal a lot.

One question: presumably this behaves like Ruby’s method_missing in that any 
natively implemented members shadow the dynamic ones? i.e. Swift looks for a 
static match first, then uses the dynamicMember only as a fallback?

I found myself asking other questions as I read the proposal, and then agreeing 
with where you landed. Here are those questions in case they touch off useful 
thoughts:

• • •

Q: It seems like this fundamentally alters Swift’s aesthetic of “either an 
operation is type-safe, or it’s clear at the point of use that it’s not.” 
Should this use an operator other than a period, e.g. `pickle->loads(blob)`?

A: This shift in the language does give me pause, but using a different 
operator really undermines the interoperability story. This is probably a job 
for syntax highlighting, not syntax.

• • •

Q: Why the open-ended `associatedtype DynamicMemberLookupValue`? Seems like it 
will always just be Self in practice.

A: It would be Self in the Python and JSON examples in the proposal, but making 
it an associatedtype adds no implementation burden, does no apparent harm, and 
adds flexibility. Shifting types on traversal could be particularly useful in 
creating DSLs (e.g. sepia → Genus, sepia.officinalis → Species).

• • •

Q: OK, then shouldn’t individual dynamic methods be able to return different 
types?

A: And how precisely would that work?

Q: Good point. Question retracted.

• • •

Q: Is there any special handling for that member name string — to handle ruby 
method names like `blank?`, for example?

A: This should be the job of a language-specific interop layer.

• • •

Q: Should the subscript also take arg types and/or labels to allow overloading?

A: Ruby, Python, and JS all resolve members by name alone, and leave it to 
functions to untangle their own args. Obj-C is the lone oddball here. Relying 
on the companion proposal to handle the args makes sense.

Cheers, P


> On Nov 15, 2017, at 1:29 AM, Chris Lattner via swift-evolution 
>  wrote:
> 
> Hi All,
> 
> As a peer to the DynamicCallable proposal 
> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
> ), I’d like 
> to get your feedback on making member lookup dynamically extensible.  My 
> primary motivation is to improve interoperability with dynamic languages like 
> Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
> working with untyped JSON).
> 
> In addition to being a high impact on expressivity of Swift, I believe an 
> implementation can be done in a way with changes that are localized, and thus 
> not have significant impact on the maintainability of the compiler as a 
> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
> be happy to prepare an implementation for consideration.
> 
> In case it is useful, I’m working on cleaning up my current prototype Python 
> bindings.  I’ll share them in the next day or two in case they are useful to 
> provide context.  It is amazingly simple: less than 500 lines of Swift code 
> (plus some small additional C header glue to work around clang importer 
> limitations) enables impressive interoperability.  The only problems are the 
> verbosity addressed by this proposal and the peer DynamicCallable proposal.
> 
> 
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
> 
> 
> A snapshot of the proposal is included below in case it is useful.  Thanks in 
> advance for help improving the proposal!
> 
> -Chris
> 
> 
> Introduce User-defined "Dynamic Member Lookup" Types
> 
> Proposal: SE- 
> 
> Author: Chris Lattner 
> Review Manager: TBD
> Status: Awaiting implementation
>  
> Introduction
> 
> This proposal introduces a new DynamicMemberLookupProtocol type to the 
> standard library. Types that conform to it provide "dot" syntax for arbitrary 
> names which are resolved at runtime. It is simple syntactic sugar which 
> allows the user to write:
> 
> a = someValue.someMember
> someValue.someMember = a
> and have it be interpreted by the compiler as:
> 
>   a = someValue[dynamicMember: "someMember"]
>   someValue[dynamicMember: "someMember"] = a
> Many other languages have analogous features (e.g. the composition of 
> Objective-C's explicit properties 
> 
>  and underlying messaging infrastructure 
> ).
>  This sort of 

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

2017-11-15 Thread Chris Lattner via swift-evolution
On Nov 15, 2017, at 1:38 AM, Andrew Thompson via swift-evolution 
 wrote:
> Hi Chris,
> 
> There are only a few examples in the proposal that demonstrate using dynamic 
> member lookup.
> 
> I suppose that some examples will look like this:
> 
> let foo: PyRef = ...
> foo.bar // translates into foo[dynamic: “bar”]
> foo.bar.baz // translates into foo[dynamic: “bar”][dynamic: “baz”]
> 
> and if we have:
> 
> extension PyRef {
> var one: Int {
> return 1
> }
> }
> 
> foo.bar.one // returns 1, because it translates into foo[dynamic: “bar”].one
> 
> This to me is hinting that dynamic member lookup will only be applied to one 
> property at a time. In order for it to work on multiple levels, the type 
> being returned by the subscript operation must still conform to 
> DynamicMemberLookup. Is this how you envisioned it to work?

The author of the type gets to make that choice.  In the case of the Python 
interop, yes, it will return another PyRef.  In the case of a JSON library, 
that should also return "Self?" so that you can optional chain through an 
access path.

That said, there are other potential use cases where you may only want a single 
level of dynamism.  The proposal allows the API author to specify the element 
type, which means they have flexibility to do what is right for their usecase.

-Chris


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


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

2017-11-15 Thread Chris Lattner via swift-evolution
On Nov 15, 2017, at 2:52 PM, Jean-Daniel via swift-evolution 
 wrote:
> Just a question about what it mean for API resilience. Actually, adding a 
> property to an existing class is not a breaking change. 
> 
> For a class that implements that protocol, as it will be possible to use 
> property accessor with any non existing property. Adding a new property to 
> this class will now change the class behavior in unexpected way as the old 
> client will still call the dynamic lookup method, but new code will use the 
> new accessor method. Is it something that should be mention in the «  Effect 
> on API resilience » section ?

Right.  Sure, I’ll add a mention of that.

-Chris


> 
> 
>> Le 15 nov. 2017 à 08:29, Chris Lattner via swift-evolution 
>> > a écrit :
>> 
>> Hi All,
>> 
>> As a peer to the DynamicCallable proposal 
>> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
>> ), I’d 
>> like to get your feedback on making member lookup dynamically extensible.  
>> My primary motivation is to improve interoperability with dynamic languages 
>> like Python, Perl, Ruby, Javascript, etc, but there are other use cases 
>> (e.g. when working with untyped JSON).
>> 
>> In addition to being a high impact on expressivity of Swift, I believe an 
>> implementation can be done in a way with changes that are localized, and 
>> thus not have significant impact on the maintainability of the compiler as a 
>> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
>> be happy to prepare an implementation for consideration.
>> 
>> In case it is useful, I’m working on cleaning up my current prototype Python 
>> bindings.  I’ll share them in the next day or two in case they are useful to 
>> provide context.  It is amazingly simple: less than 500 lines of Swift code 
>> (plus some small additional C header glue to work around clang importer 
>> limitations) enables impressive interoperability.  The only problems are the 
>> verbosity addressed by this proposal and the peer DynamicCallable proposal.
>> 
>> 
>> Here is the canonical proposal URL:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>> 
>> 
>> A snapshot of the proposal is included below in case it is useful.  Thanks 
>> in advance for help improving the proposal!
>> 
>> -Chris
>> 
>> 
>> Introduce User-defined "Dynamic Member Lookup" Types
>> 
>> Proposal: SE- 
>> 
>> Author: Chris Lattner 
>> Review Manager: TBD
> 
> ___
> 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] Introduce User-defined "Dynamic Member Lookup" Types

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

> On Nov 15, 2017, at 1:12 PM, Nathan Gray via swift-evolution 
>  wrote:
> 
> How would this work for a property access that caused a python exception to 
> be thrown?  Are we assuming that only "good" non-throwing properties will be 
> bridged in this way?
> 
> ```
> >>> x = "hello"
> >>> x.foobar
> Traceback (most recent call last):
>   File "", line 1, in 
> AttributeError: 'str' object has no attribute 'foobar'
> ```

The prototype that I’m working on (which I’ll send out at some point soon) 
defaults to assuming that calls, member lookups, etc are all non-throwing.  
There are multiple ways to model this, and I’m not super attached to this 
approach, but here is how the current prototype works:

If you’d like to write code that is throwing, a modifier is used to get it 
reflected as a Swift optional or error.  e.g.

let x : PyVal = “hello”
x.foobar  // traps.
x.checking.foobar // returns optional.

We could also use a postfix operator to make this nicer if common, e.g.:
x^.foobar

But I’d like to avoid that if at all possible.


The way this works is that there are two types, “PyVal” is the currency type 
for python values.  The “x.checking” invocation returns a “CheckedPyVal” 
wrapper around the PyVal.  Both PyVal and CheckedPyVal conform to the two 
Dynamic* protocols: the former traps on error, the later produces an optional 
or throws (for calls).

-Chris



> 
> 
> On Tue, Nov 14, 2017 at 11:29 PM, Chris Lattner via swift-evolution 
> > wrote:
> Hi All,
> 
> As a peer to the DynamicCallable proposal 
> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
> ), I’d like 
> to get your feedback on making member lookup dynamically extensible.  My 
> primary motivation is to improve interoperability with dynamic languages like 
> Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
> working with untyped JSON).
> 
> In addition to being a high impact on expressivity of Swift, I believe an 
> implementation can be done in a way with changes that are localized, and thus 
> not have significant impact on the maintainability of the compiler as a 
> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
> be happy to prepare an implementation for consideration.
> 
> In case it is useful, I’m working on cleaning up my current prototype Python 
> bindings.  I’ll share them in the next day or two in case they are useful to 
> provide context.  It is amazingly simple: less than 500 lines of Swift code 
> (plus some small additional C header glue to work around clang importer 
> limitations) enables impressive interoperability.  The only problems are the 
> verbosity addressed by this proposal and the peer DynamicCallable proposal.
> 
> 
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
> 
> 
> A snapshot of the proposal is included below in case it is useful.  Thanks in 
> advance for help improving the proposal!
> 
> -Chris
> 
> 
> Introduce User-defined "Dynamic Member Lookup" Types
> 
> Proposal: SE- 
> 
> Author: Chris Lattner 
> Review Manager: TBD
> Status: Awaiting implementation
>  
> Introduction
> 
> This proposal introduces a new DynamicMemberLookupProtocol type to the 
> standard library. Types that conform to it provide "dot" syntax for arbitrary 
> names which are resolved at runtime. It is simple syntactic sugar which 
> allows the user to write:
> 
> a = someValue.someMember
> someValue.someMember = a
> and have it be interpreted by the compiler as:
> 
>   a = someValue[dynamicMember: "someMember"]
>   someValue[dynamicMember: "someMember"] = a
> Many other languages have analogous features (e.g. the composition of 
> Objective-C's explicit properties 
> 
>  and underlying messaging infrastructure 
> ).
>  This sort of functionality is great for implementing dynamic language 
> interoperability, dynamic proxy APIs 
> ,
>  and other APIs (e.g. for JSON processing).
> 
> Swift-evolution thread: Discussion thread topic for that proposal 
> 
>  
> 

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

2017-11-15 Thread Jean-Daniel via swift-evolution

Just a question about what it mean for API resilience. Actually, adding a 
property to an existing class is not a breaking change. 

For a class that implements that protocol, as it will be possible to use 
property accessor with any non existing property. Adding a new property to this 
class will now change the class behavior in unexpected way as the old client 
will still call the dynamic lookup method, but new code will use the new 
accessor method. Is it something that should be mention in the «  Effect on API 
resilience » section ?


> Le 15 nov. 2017 à 08:29, Chris Lattner via swift-evolution 
>  a écrit :
> 
> Hi All,
> 
> As a peer to the DynamicCallable proposal 
> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
> ), I’d like 
> to get your feedback on making member lookup dynamically extensible.  My 
> primary motivation is to improve interoperability with dynamic languages like 
> Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
> working with untyped JSON).
> 
> In addition to being a high impact on expressivity of Swift, I believe an 
> implementation can be done in a way with changes that are localized, and thus 
> not have significant impact on the maintainability of the compiler as a 
> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
> be happy to prepare an implementation for consideration.
> 
> In case it is useful, I’m working on cleaning up my current prototype Python 
> bindings.  I’ll share them in the next day or two in case they are useful to 
> provide context.  It is amazingly simple: less than 500 lines of Swift code 
> (plus some small additional C header glue to work around clang importer 
> limitations) enables impressive interoperability.  The only problems are the 
> verbosity addressed by this proposal and the peer DynamicCallable proposal.
> 
> 
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
> 
> 
> A snapshot of the proposal is included below in case it is useful.  Thanks in 
> advance for help improving the proposal!
> 
> -Chris
> 
> 
> Introduce User-defined "Dynamic Member Lookup" Types
> 
> Proposal: SE- 
> 
> Author: Chris Lattner 
> Review Manager: TBD

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


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

2017-11-15 Thread Nathan Gray via swift-evolution
How would this work for a property access that caused a python exception to
be thrown?  Are we assuming that only "good" non-throwing properties will
be bridged in this way?

```
>>> x = "hello"
>>> x.foobar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'str' object has no attribute 'foobar'
```


On Tue, Nov 14, 2017 at 11:29 PM, Chris Lattner via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi All,
>
> As a peer to the DynamicCallable proposal (https://gist.github.com/
> lattner/a6257f425f55fe39fd6ac7a2354d693d), I’d like to get your feedback
> on making member lookup dynamically extensible.  My primary motivation is
> to improve interoperability with dynamic languages like Python, Perl, Ruby,
> Javascript, etc, but there are other use cases (e.g. when working with
> untyped JSON).
>
> In addition to being a high impact on expressivity of Swift, I believe an
> implementation can be done in a way with changes that are localized, and
> thus not have significant impact on the maintainability of the compiler as
> a whole.  Once the pitch phase of this proposal helps refine the details,
> I’ll be happy to prepare an implementation for consideration.
>
> In case it is useful, I’m working on cleaning up my current prototype
> Python bindings.  I’ll share them in the next day or two in case they are
> useful to provide context.  It is amazingly simple: less than 500 lines of
> Swift code (plus some small additional C header glue to work around clang
> importer limitations) enables impressive interoperability.  The only
> problems are the verbosity addressed by this proposal and the peer
> DynamicCallable proposal.
>
>
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>
> A snapshot of the proposal is included below in case it is useful.  Thanks
> in advance for help improving the proposal!
>
> -Chris
>
>
> Introduce User-defined "Dynamic Member Lookup" Types
>
>- Proposal: SE-
>
>- Author: Chris Lattner 
>- Review Manager: TBD
>- Status: Awaiting implementation
>
>
> 
> Introduction
>
> This proposal introduces a new DynamicMemberLookupProtocol type to the
> standard library. Types that conform to it provide "dot" syntax for
> arbitrary names which are resolved at runtime. It is simple syntactic sugar
> which allows the user to write:
>
> a = someValue.someMember
> someValue.someMember = a
>
> and have it be interpreted by the compiler as:
>
>   a = someValue[dynamicMember: "someMember"]
>   someValue[dynamicMember: "someMember"] = a
>
> Many other languages have analogous features (e.g. the composition of
> Objective-C's explicit properties
> 
>  and
> underlying messaging infrastructure
> ).
> This sort of functionality is great for implementing dynamic language
> interoperability, dynamic proxy APIs
> ,
> and other APIs (e.g. for JSON processing).
>
> Swift-evolution thread: Discussion thread topic for that proposal
> 
>
> Motivation
> and Context
>
> Swift is well known for being exceptional at interworking with existing C
> and Objective-C APIs, but its support for calling APIs written in scripting
> languages like Python, Perl, and Ruby is quite lacking.
>
> C and Objective-C are integrated into Swift by expending a heroic amount
> of effort into integrating Clang ASTs, remapping existing APIs in an
> attempt to feel "Swifty", and by providing a large number of attributes and
> customization points for changing the behavior of this integration when
> writing an Objective-C header. The end result of this massive investment of
> effort is that Swift provides a *better* experience when programming
> against these legacy APIs than Objective-C itself did.
>
> When considering the space of dynamic languages, three things are clear:
> 1) there are several different languages of interest, and they each have
> significant interest in different quarters: for example, Python is big in
> data science and machine learning, Ruby is popular for building server side
> apps, and even Perl is in still widely used. 2) These languages have
> decades of library building behind them, sometimes with significant
> communities  and 3) there are one or two
> orders of magnitude more users of these libraries than 

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

2017-11-15 Thread Alejandro Martinez via swift-evolution
Really interesting proposal,
I don't really have the need for Python interop at the moment so I
would be more interesting on the potential usages of this changes to
improve Swift code like the proxy and json accessors that you mention.
The JSON part I can see it, as you are basically accessing with
strings a keyed data structure.
But I'm having a hard time imagining how a proxy example would work as
there doesn't seem to be a mechanism to access Swift members from the
information received on the subscript. I pressume you can call your
proxied object subscript but that would mean that the proxied objects
need to be also DynamicMemberLookupProtocol and in any case at some
point down the chain somebody will have to dispatch from the "string"
to a member lookup with some switch or similar.
Am I missing something or is this just completely unrelated to the
proposal and I just left my imagination go to far? :P

On Wed, Nov 15, 2017 at 10:58 AM, Stefan Mayer-Popp via
swift-evolution  wrote:
> Hej Rick,
>
> i definitely agree with you. +1
>
> From my personal experience i can say that a good working language 
> interoperability gives us tons of new possibilities.
>
> A big thing i like is that i could for example use already written projects 
> in different languages which are maybe already in production and reuse their 
> proven functionality without the requirement to transform the code to Swift.
> The complexity of the Swift language itself isn't even touched in any area a 
> “casual” developer uses, i personally see no argument of not integrating this 
> feature for Swift.
>
> I for myself can see a lot new possibilities and more reasons (and better 
> arguments) for using Swift in other areas in my company like a normal phone 
> app or some command-line tools.
> Symbiosis is great lets have some fun with Swython, Swuby or SwHP in future.
>
> --
> Stefan Mayer-Popp
>
>
>
>> On 15. Nov 2017, at 11:08, Rick Mann via swift-evolution 
>>  wrote:
>>
>> +1 to both proposals. I don't know enough to comment further, but I know 
>> this would help in the adoption of Swift on my team(s) (we call a lot of 
>> Python, although currently via exec-ing some bash scripts; it's a mess, but 
>> works well in the CLI world the stuff was written for).
>>
>>> On Nov 14, 2017, at 23:29 , Chris Lattner via swift-evolution 
>>>  wrote:
>>>
>>> Hi All,
>>>
>>> As a peer to the DynamicCallable proposal 
>>> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d), I’d 
>>> like to get your feedback on making member lookup dynamically extensible.  
>>> My primary motivation is to improve interoperability with dynamic languages 
>>> like Python, Perl, Ruby, Javascript, etc, but there are other use cases 
>>> (e.g. when working with untyped JSON).
>>>
>>> In addition to being a high impact on expressivity of Swift, I believe an 
>>> implementation can be done in a way with changes that are localized, and 
>>> thus not have significant impact on the maintainability of the compiler as 
>>> a whole.  Once the pitch phase of this proposal helps refine the details, 
>>> I’ll be happy to prepare an implementation for consideration.
>>>
>>> In case it is useful, I’m working on cleaning up my current prototype 
>>> Python bindings.  I’ll share them in the next day or two in case they are 
>>> useful to provide context.  It is amazingly simple: less than 500 lines of 
>>> Swift code (plus some small additional C header glue to work around clang 
>>> importer limitations) enables impressive interoperability.  The only 
>>> problems are the verbosity addressed by this proposal and the peer 
>>> DynamicCallable proposal.
>>>
>>>
>>> Here is the canonical proposal URL:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>>>
>>> A snapshot of the proposal is included below in case it is useful.  Thanks 
>>> in advance for help improving the proposal!
>>>
>>> -Chris
>>>
>>>
>>> Introduce User-defined "Dynamic Member Lookup" Types
>>>
>>>  • Proposal: SE-
>>>  • Author: Chris Lattner
>>>  • Review Manager: TBD
>>>  • Status: Awaiting implementation
>>> Introduction
>>>
>>> This proposal introduces a new DynamicMemberLookupProtocol type to the 
>>> standard library. Types that conform to it provide "dot" syntax for 
>>> arbitrary names which are resolved at runtime. It is simple syntactic sugar 
>>> which allows the user to write:
>>>
>>>a = someValue.someMember
>>>
>>>someValue.
>>> someMember = a
>>> and have it be interpreted by the compiler as:
>>>
>>>  a = someValue[dynamicMember: "someMember"
>>> ]
>>>  someValue[
>>> dynamicMember: "someMember"] = a
>>> Many other languages have analogous features (e.g. the composition of 
>>> Objective-C's explicit properties and underlying messaging infrastructure). 
>>> This sort of functionality is great for implementing dynamic language 
>>> interoperability, dynamic proxy 

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

2017-11-15 Thread Stefan Mayer-Popp via swift-evolution
Hej Rick,

i definitely agree with you. +1

From my personal experience i can say that a good working language 
interoperability gives us tons of new possibilities. 

A big thing i like is that i could for example use already written projects in 
different languages which are maybe already in production and reuse their 
proven functionality without the requirement to transform the code to Swift.
The complexity of the Swift language itself isn't even touched in any area a 
“casual” developer uses, i personally see no argument of not integrating this 
feature for Swift.

I for myself can see a lot new possibilities and more reasons (and better 
arguments) for using Swift in other areas in my company like a normal phone app 
or some command-line tools. 
Symbiosis is great lets have some fun with Swython, Swuby or SwHP in future.

--
Stefan Mayer-Popp



> On 15. Nov 2017, at 11:08, Rick Mann via swift-evolution 
>  wrote:
> 
> +1 to both proposals. I don't know enough to comment further, but I know this 
> would help in the adoption of Swift on my team(s) (we call a lot of Python, 
> although currently via exec-ing some bash scripts; it's a mess, but works 
> well in the CLI world the stuff was written for).
> 
>> On Nov 14, 2017, at 23:29 , Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> Hi All,
>> 
>> As a peer to the DynamicCallable proposal 
>> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d), I’d like 
>> to get your feedback on making member lookup dynamically extensible.  My 
>> primary motivation is to improve interoperability with dynamic languages 
>> like Python, Perl, Ruby, Javascript, etc, but there are other use cases 
>> (e.g. when working with untyped JSON).
>> 
>> In addition to being a high impact on expressivity of Swift, I believe an 
>> implementation can be done in a way with changes that are localized, and 
>> thus not have significant impact on the maintainability of the compiler as a 
>> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
>> be happy to prepare an implementation for consideration.
>> 
>> In case it is useful, I’m working on cleaning up my current prototype Python 
>> bindings.  I’ll share them in the next day or two in case they are useful to 
>> provide context.  It is amazingly simple: less than 500 lines of Swift code 
>> (plus some small additional C header glue to work around clang importer 
>> limitations) enables impressive interoperability.  The only problems are the 
>> verbosity addressed by this proposal and the peer DynamicCallable proposal.
>> 
>> 
>> Here is the canonical proposal URL:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>> 
>> A snapshot of the proposal is included below in case it is useful.  Thanks 
>> in advance for help improving the proposal!
>> 
>> -Chris
>> 
>> 
>> Introduce User-defined "Dynamic Member Lookup" Types
>> 
>>  • Proposal: SE-
>>  • Author: Chris Lattner
>>  • Review Manager: TBD
>>  • Status: Awaiting implementation
>> Introduction
>> 
>> This proposal introduces a new DynamicMemberLookupProtocol type to the 
>> standard library. Types that conform to it provide "dot" syntax for 
>> arbitrary names which are resolved at runtime. It is simple syntactic sugar 
>> which allows the user to write:
>> 
>>a = someValue.someMember
>> 
>>someValue.
>> someMember = a
>> and have it be interpreted by the compiler as:
>> 
>>  a = someValue[dynamicMember: "someMember"
>> ]
>>  someValue[
>> dynamicMember: "someMember"] = a
>> Many other languages have analogous features (e.g. the composition of 
>> Objective-C's explicit properties and underlying messaging infrastructure). 
>> This sort of functionality is great for implementing dynamic language 
>> interoperability, dynamic proxy APIs, and other APIs (e.g. for JSON 
>> processing).
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal
>> 
>> Motivation and Context
>> 
>> Swift is well known for being exceptional at interworking with existing C 
>> and Objective-C APIs, but its support for calling APIs written in scripting 
>> languages like Python, Perl, and Ruby is quite lacking.
>> 
>> C and Objective-C are integrated into Swift by expending a heroic amount of 
>> effort into integrating Clang ASTs, remapping existing APIs in an attempt to 
>> feel "Swifty", and by providing a large number of attributes and 
>> customization points for changing the behavior of this integration when 
>> writing an Objective-C header. The end result of this massive investment of 
>> effort is that Swift provides a better experience when programming against 
>> these legacy APIs than Objective-C itself did.
>> 
>> When considering the space of dynamic languages, three things are clear: 1) 
>> there are several different languages of interest, and they each have 
>> significant interest in different quarters: for example, Python is 

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

2017-11-15 Thread Rick Mann via swift-evolution
+1 to both proposals. I don't know enough to comment further, but I know this 
would help in the adoption of Swift on my team(s) (we call a lot of Python, 
although currently via exec-ing some bash scripts; it's a mess, but works well 
in the CLI world the stuff was written for).

> On Nov 14, 2017, at 23:29 , Chris Lattner via swift-evolution 
>  wrote:
> 
> Hi All,
> 
> As a peer to the DynamicCallable proposal 
> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d), I’d like 
> to get your feedback on making member lookup dynamically extensible.  My 
> primary motivation is to improve interoperability with dynamic languages like 
> Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
> working with untyped JSON).
> 
> In addition to being a high impact on expressivity of Swift, I believe an 
> implementation can be done in a way with changes that are localized, and thus 
> not have significant impact on the maintainability of the compiler as a 
> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
> be happy to prepare an implementation for consideration.
> 
> In case it is useful, I’m working on cleaning up my current prototype Python 
> bindings.  I’ll share them in the next day or two in case they are useful to 
> provide context.  It is amazingly simple: less than 500 lines of Swift code 
> (plus some small additional C header glue to work around clang importer 
> limitations) enables impressive interoperability.  The only problems are the 
> verbosity addressed by this proposal and the peer DynamicCallable proposal.
> 
> 
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> 
> A snapshot of the proposal is included below in case it is useful.  Thanks in 
> advance for help improving the proposal!
> 
> -Chris
> 
> 
> Introduce User-defined "Dynamic Member Lookup" Types
> 
>   • Proposal: SE-
>   • Author: Chris Lattner
>   • Review Manager: TBD
>   • Status: Awaiting implementation
> Introduction
> 
> This proposal introduces a new DynamicMemberLookupProtocol type to the 
> standard library. Types that conform to it provide "dot" syntax for arbitrary 
> names which are resolved at runtime. It is simple syntactic sugar which 
> allows the user to write:
> 
> a = someValue.someMember
> 
> someValue.
> someMember = a
> and have it be interpreted by the compiler as:
> 
>   a = someValue[dynamicMember: "someMember"
> ]
>   someValue[
> dynamicMember: "someMember"] = a
> Many other languages have analogous features (e.g. the composition of 
> Objective-C's explicit properties and underlying messaging infrastructure). 
> This sort of functionality is great for implementing dynamic language 
> interoperability, dynamic proxy APIs, and other APIs (e.g. for JSON 
> processing).
> 
> Swift-evolution thread: Discussion thread topic for that proposal
> 
> Motivation and Context
> 
> Swift is well known for being exceptional at interworking with existing C and 
> Objective-C APIs, but its support for calling APIs written in scripting 
> languages like Python, Perl, and Ruby is quite lacking.
> 
> C and Objective-C are integrated into Swift by expending a heroic amount of 
> effort into integrating Clang ASTs, remapping existing APIs in an attempt to 
> feel "Swifty", and by providing a large number of attributes and 
> customization points for changing the behavior of this integration when 
> writing an Objective-C header. The end result of this massive investment of 
> effort is that Swift provides a better experience when programming against 
> these legacy APIs than Objective-C itself did.
> 
> When considering the space of dynamic languages, three things are clear: 1) 
> there are several different languages of interest, and they each have 
> significant interest in different quarters: for example, Python is big in 
> data science and machine learning, Ruby is popular for building server side 
> apps, and even Perl is in still widely used. 2) These languages have decades 
> of library building behind them, sometimes with significant communities and 
> 3) there are one or two orders of magnitude more users of these libraries 
> than there are people currently using Swift.
> 
> While it is theoretically possible to expend the same level of effort on each 
> of these languages and communities as has been spent on Objective-C, it is 
> quite clear that this would both ineffective as well as bad for Swift: It 
> would be ineffective, because the Swift community has not leverage over these 
> communities to force auditing and annotation of their APIs. It would be bad 
> for Swift because it would require a ton of language-specific support (and a 
> number of third-party dependencies) onto the compiler and runtime, each of 
> which makes the implementation significantly more complex, difficult to 
> reason about, difficult to maintain, and 

[swift-evolution] [Pitch] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-15 Thread Andrew Thompson via swift-evolution
Hi Chris,

There are only a few examples in the proposal that demonstrate using dynamic 
member lookup.

I suppose that some examples will look like this:

let foo: PyRef = ...
foo.bar // translates into foo[dynamic: “bar”]
foo.bar.baz // translates into foo[dynamic: “bar”][dynamic: “baz”]

and if we have:

extension PyRef {
var one: Int {
return 1
}
}

foo.bar.one // returns 1, because it translates into foo[dynamic: “bar”].one

This to me is hinting that dynamic member lookup will only be applied to one 
property at a time. In order for it to work on multiple levels, the type being 
returned by the subscript operation must still conform to DynamicMemberLookup. 
Is this how you envisioned it to work?

Cheers,
Andrew

> Hi All,
> 
> As a peer to the DynamicCallable proposal 
> (https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
> ), I’d like 
> to get your feedback on making member lookup dynamically extensible.  My 
> primary motivation is to improve interoperability with dynamic languages like 
> Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
> working with untyped JSON).
> 
> In addition to being a high impact on expressivity of Swift, I believe an 
> implementation can be done in a way with changes that are localized, and thus 
> not have significant impact on the maintainability of the compiler as a 
> whole.  Once the pitch phase of this proposal helps refine the details, I’ll 
> be happy to prepare an implementation for consideration.
> 
> In case it is useful, I’m working on cleaning up my current prototype Python 
> bindings.  I’ll share them in the next day or two in case they are useful to 
> provide context.  It is amazingly simple: less than 500 lines of Swift code 
> (plus some small additional C header glue to work around clang importer 
> limitations) enables impressive interoperability.  The only problems are the 
> verbosity addressed by this proposal and the peer DynamicCallable proposal.
> 
> 
> Here is the canonical proposal URL:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
> 
> 
> A snapshot of the proposal is included below in case it is useful.  Thanks in 
> advance for help improving the proposal!
> 
> -Chris
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [Pitch] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-14 Thread Chris Lattner via swift-evolution
Hi All,

As a peer to the DynamicCallable proposal 
(https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 
), I’d like 
to get your feedback on making member lookup dynamically extensible.  My 
primary motivation is to improve interoperability with dynamic languages like 
Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when 
working with untyped JSON).

In addition to being a high impact on expressivity of Swift, I believe an 
implementation can be done in a way with changes that are localized, and thus 
not have significant impact on the maintainability of the compiler as a whole.  
Once the pitch phase of this proposal helps refine the details, I’ll be happy 
to prepare an implementation for consideration.

In case it is useful, I’m working on cleaning up my current prototype Python 
bindings.  I’ll share them in the next day or two in case they are useful to 
provide context.  It is amazingly simple: less than 500 lines of Swift code 
(plus some small additional C header glue to work around clang importer 
limitations) enables impressive interoperability.  The only problems are the 
verbosity addressed by this proposal and the peer DynamicCallable proposal.


Here is the canonical proposal URL:
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 


A snapshot of the proposal is included below in case it is useful.  Thanks in 
advance for help improving the proposal!

-Chris


Introduce User-defined "Dynamic Member Lookup" Types

Proposal: SE- 
Author: Chris Lattner 
Review Manager: TBD
Status: Awaiting implementation
 
Introduction

This proposal introduces a new DynamicMemberLookupProtocol type to the standard 
library. Types that conform to it provide "dot" syntax for arbitrary names 
which are resolved at runtime. It is simple syntactic sugar which allows the 
user to write:

a = someValue.someMember
someValue.someMember = a
and have it be interpreted by the compiler as:

  a = someValue[dynamicMember: "someMember"]
  someValue[dynamicMember: "someMember"] = a
Many other languages have analogous features (e.g. the composition of 
Objective-C's explicit properties 

 and underlying messaging infrastructure 
).
 This sort of functionality is great for implementing dynamic language 
interoperability, dynamic proxy APIs 
,
 and other APIs (e.g. for JSON processing).

Swift-evolution thread: Discussion thread topic for that proposal 

 
Motivation
 and Context

Swift is well known for being exceptional at interworking with existing C and 
Objective-C APIs, but its support for calling APIs written in scripting 
languages like Python, Perl, and Ruby is quite lacking.

C and Objective-C are integrated into Swift by expending a heroic amount of 
effort into integrating Clang ASTs, remapping existing APIs in an attempt to 
feel "Swifty", and by providing a large number of attributes and customization 
points for changing the behavior of this integration when writing an 
Objective-C header. The end result of this massive investment of effort is that 
Swift provides a better experience when programming against these legacy APIs 
than Objective-C itself did.

When considering the space of dynamic languages, three things are clear: 1) 
there are several different languages of interest, and they each have 
significant interest in different quarters: for example, Python is big in data 
science and machine learning, Ruby is popular for building server side apps, 
and even Perl is in still widely used. 2) These languages have decades of 
library building behind them, sometimes with significant communities 
 and 3) there are one or two orders of magnitude 
more users of these libraries than there are people currently using Swift.

While it is theoretically possible to expend the same level of effort on each 
of these languages and communities as has been spent on Objective-C, it is 
quite clear that this would both ineffective as well as bad for Swift: It would 
be ineffective, because the Swift community has not leverage over these 
communities to force auditing and annotation of their APIs. It would be bad for 
Swift because it