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

2017-12-03 Thread David Hart via swift-evolution


> On 3 Dec 2017, at 18:42, Matthew Johnson  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Dec 3, 2017, at 10:40 AM, David Hart  > wrote:
> 
>> 
>> 
>>> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Dec 2, 2017, at 7:40 PM, Chris Lattner >> > wrote:
>>> 
 On Dec 2, 2017, at 2:13 PM, Matthew Johnson > wrote:
>> For all those reasons, we really do need something like AnyObject 
>> dispatch if we care about working with dynamically typed languages.  The 
>> design I’m suggesting carefully cordons this off into its own struct 
>> type, so it doesn’t infect the rest of the type system, and is 
>> non-invasive in the compiler.
> 
> I am quite familiar with dynamic languages and agree that this is 
> necessary if we are going to fully open up access to these languages from 
> Swift.
 
 Ok, then it appears you agree that something like anyobject dispatch is 
 necessary for effective dynamic language interop.
 
>>> I strongly urge you to reconsider the decision of that dynamic members 
>>> must be made available with no indication at usage sites.  An 
>>> indication of dynamic lookup at usage sites aligns very well (IMO) with 
>>> the rest of Swift (AnyObject lookup aside) by calling attention to code 
>>> that requires extra care to get right.
>> 
>> I don’t understand this.  The proposal is fully type safe, and this 
>> approach is completely precedented by AnyObject.  Swift’s type system 
>> supports many ways to express fallibility, and keeping those decisions 
>> orthogonal to this proposal is the right thing to do, because it allows 
>> the author of the type to decide what model makes sense for them.
> 
> Allowing the author of the type to choose whether the mechanism is hidden 
> or visible is exactly what I don’t want to allow.  I think you have the 
> right design regarding types and semantics - the author chooses.  But I 
> don’t want these calls to look like ordinary member lookup when I’m 
> reading code.  
> 
> They inherently have a much greater chance of failure than ordinary 
> member lookup.  Further, authors are likely to choose immediate traps or 
> nil IUO as failure modes as forcing users to deal with Optional on every 
> call is likely to be untenable.  I believe this behavior should be 
> represented by some kind of syntax at the usage site.  I don’t believe it 
> is an undue burden.  It would make the dynamic lookup semantic clear to 
> all readers and would help to discourage abuse.
 
 I believe that adding explicit syntax would be counterproductive to your 
 goals, and would not make dynamic lookup syntax more clear.  I assume that 
 you would also want the same thing for DynamicCallable too, and operator 
 overloads, subscripts, and every other operation you perform on these 
 values, since they all have the exact same behavior.
 
 If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
 that change would turn this (which uses runtime failing or IUO return 
 values like AnyObject):
 
let np = Python.import("numpy")
let x = np.array([6, 7, 8])
let y =  np.arange(24).reshape(2, 3, 4)

let a = np.ones(3, dtype: np.int32)
let b = np.linspace(0, pi, 3)
let c = a+b
let d = np.exp(c)
print(d)
 
 into:
 
let np = Python.import("numpy")
let b = np^.array^([6, 7, 8])
let y =  np^.arange^(24)^.reshape^(2, 3, 4)

let a = np^.ones^(3, dtype: np^.int32)
let b = np^.linspace^(0, pi, 3)
let c = a+^b
let d = np^.exp^(c)
 
 This does not improve clarity of code, it merely serves to obfuscate 
 logic.  It is immediately apparent from the APIs being used, the API 
 style, and the static types (in Xcode or through static declarations) that 
 this is all Python stuff.  
>>> 
>>> It may be immediately apparent when the types involved are obviously 
>>> dynamic, such as in this example where Python.import is explicitly used.  
>>> However, my concern is less about the intended use case of dynamic language 
>>> interop than I am that this feature will be generally available to all 
>>> types in Swift.  
>>> 
>>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>>> types and contexts that are not necessarily obviously using dynamic lookup, 
>>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>>> still think it’s a legitimate concern.
>> 
>> If dynamism if restricted 

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

2017-12-03 Thread Letanyan Arumugam via swift-evolution

> On 04 Dec 2017, at 07:47, Joe DeCapo  wrote:
> 
> 
>> On Dec 3, 2017, at 11:35 PM, Letanyan Arumugam via swift-evolution 
>> > wrote:
>> 
>> I‘m not always the only one writing code (I could inherit a code base). I’ve 
>> used languages with only dynamic lookup before and knowing about something 
>> doesn’t always help especially when the documentation isn’t clear. Which is 
>> very possible in this case were libraries could be made by third parties.
> 
> I find it very hard to believe that Swift libraries are going to end up 
> exposing this as a public api en masse. And if you inherit a code base where 
> it's used internally, then it's fully within your power to wrap these dynamic 
> calls in more strongly typed wrappers (you could even do this with third 
> party libraries if necessary). You could just as easily inherit a code base 
> where force unwrapping or IUOs are used irresponsibly, but this doesn't mean 
> that these language features have no legitimate use. The solution is to 
> refactor the code to use these idioms in the correct way.

The whole point of this proposal is to get more people into Swift. People who 
are from a very dynamic field so who’s to say what path new library vendors 
will go down. Getting people into Swift that only end up working in this 
dynamic world that is on par with our current world would serve no benefit to 
anyone.

Is it really as likely to inherit a code base that uses features that from day 
one Swift made clear was not the ideal way to go. Versus something that has 
nothing to differentiate it from “normal" Swift members.

What it means to be “normal" here could be a sticking point between us because 
I don’t think dynamic member lookups should be a thing that is common place to 
do and should be discouraged in some way not a lot but enough to make people 
think I should do this differently. ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-03 Thread Joe DeCapo via swift-evolution

> On Dec 3, 2017, at 11:35 PM, Letanyan Arumugam via swift-evolution 
>  wrote:
> 
> I‘m not always the only one writing code (I could inherit a code base). I’ve 
> used languages with only dynamic lookup before and knowing about something 
> doesn’t always help especially when the documentation isn’t clear. Which is 
> very possible in this case were libraries could be made by third parties.

I find it very hard to believe that Swift libraries are going to end up 
exposing this as a public api en masse. And if you inherit a code base where 
it's used internally, then it's fully within your power to wrap these dynamic 
calls in more strongly typed wrappers (you could even do this with third party 
libraries if necessary). You could just as easily inherit a code base where 
force unwrapping or IUOs are used irresponsibly, but this doesn't mean that 
these language features have no legitimate use. The solution is to refactor the 
code to use these idioms in the correct way.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-03 Thread Letanyan Arumugam via swift-evolution

> 
> 1. a+b is also is a dynamic method call in this example. How would you 
> explain to a programmer that they have to use single quotes around some 
> expressions but not others?

Operators already have dynamic behaviour with operator overloads. Operators 
like + fail without warning as well, this is precedent in the language. Swift 
has decided to make the default for operators simple while safer usage comes at 
the cost of more explicit operators: &+ and the likes

> 2. Having this kind of special syntax would feel very arbitrary to the 
> programmer, and hard to look up. Fixits would of course be able to help here, 
> but if the compiler already knows what you should write, why does it require 
> it? Which brings me to my third point:
For the reasons I mention above. Yes it’s arbitrary but it conveys meaning just 
like ! conveys meaning.

"let x: Int” vs “let x: Int!” have vastly different behaviours

> 3. This feels like punishment, like Python making a special syntax for static 
> language bridges where they have to use the phrase 
> "static_typing_is_for_losers" in front of every method call.

Getting Python into the language is a goal for this proposal not the proposal. 
The actual proposal has far reaching changes. Theres a reason why we don’t 
explicitly let any string subscripts of an object be accepted as members on 
objects like JavaScript.

I have nothing against Python and think it would be fine without any markings 
as I mention in the end of my last email. This is because it has a precedent of 
being dynamic and anyone choosing to use it knowns exactly what they’re in for. 
Choosing to use Python in Swift would be a calculated decision by someone with 
prior experience in Python. Anyone coming into a Swift codebase with Python 
should be made aware of this before accepting the task (for example in a job 
description, requires Swift and Python knowledge).

However for things that are not obvious that they should be dynamic should tell 
the reader that what I’m doing here is different from just getting members from 
my well defined object. I’m accessing dynamic information which by its very 
nature is dynamic and might exist in some situations or might change over time. 
I need this information to be sure that when I’m debugging that the pitfalls of 
dynamic members are made aware to me. You might say that's what protocol 
conformance tells me. But right now I’m debugging and I don’t know what's going 
to trigger my aha moment. Constant reminders of here lie dragons of dynamic 
code certainly helps.

> 
> It's not like dynamic method calls will appear in your code if you don't use 
> these kind of bridges, and even if you do, it will only be when you call 
> methods on that bridge's types. When you call a method on an object, you 
> already have to know what that object does, or you will be in trouble.

I‘m not always the only one writing code (I could inherit a code base). I’ve 
used languages with only dynamic lookup before and knowing about something 
doesn’t always help especially when the documentation isn’t clear. Which is 
very possible in this case were libraries could be made by third parties.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-03 Thread Joe DeCapo via swift-evolution
+1 to Paul's comments

Many of the concerns about typos causing runtime bugs scream out to me, "I want 
to write code that is completely untested and only validated by the compiler". 
But this is just as bad for a strong, statically typed language as it is for a 
weak, dynamically typed language (and honestly, in my experience, dynamic 
language communities seem to be way better about writing tests due to the fact 
that statically typed communities tend to rely way more on the compiler). At 
the very least, I would expect a programmer to run a happy path to make sure 
the code they wrote actually works. And if they don't, and it isn't then caught 
by QA, then there are much larger issues at hand than the language design. I'm 
not sure if people are concerned about the debug cycle or production issues due 
to these proposed changes. There's simply no way around the fact that writing 
code for a dynamic programming model is going to result in more time spent 
verifying, testing, and debugging runtime issues; no matter the amount of 
effort expended on gathering the maximal amount of type information available 
from the dynamic language, or the call site symbols the programmer is required 
to enter to get the code to compile.

> On Dec 3, 2017, at 8:06 PM, Paul Cantrell via swift-evolution 
>  wrote:
> 
> 
> 
>> On Dec 3, 2017, at 1:26 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> On Dec 3, 2017, at 11:03 AM, Magnus Ahltorp  wrote:
>>> 
 4 Dec. 2017 02:40 Chris Lattner via swift-evolution 
  wrote:
 
 That’s a good principle.  However, a dynamic member lookup is just a 
 member lookup.  By that principle, it should look like a member lookup :-)
 
 Further, I incorporated some of the conversation with Matthew into the 
 proposal, showing how adding even a single sigil to dynamic member lookup 
 to distinguish it is problematic:
 https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
 
 Further, adding something like .dynamic would completely undermind the 
 proposal.  You can already write:
 
x.get(“foo”).get(“bar”)
 
 having to write:
 
x.dynamic.foo.dynamic.bar
 
 has no point.
>>> 
>>> This example shows what many on this list don't believe: that any Swift 
>>> method or member access can fail. If the return value of this "get" method 
>>> is an IUO, or not an Optional at all, and doesn't throw, then the 
>>> expression would have to fail hard if "foo" didn't resolve to something 
>>> meaningful.
>>> 
>>> The most common argument against this proposal is that someone could make 
>>> an API using Dynamic Member Lookup that could fail even though it is not 
>>> apparent to the caller. But, as we see in the example, this is just as 
>>> possible today.
>> 
>> Correct.  The argument also fails to recognize that (when bridging to a 
>> dynamic language):
>> 
>>  x+y
>> 
>> Is a completely dynamic method call which can fail (or return IUO), as is:
>> 
>>  x[i]
>> 
>> And that this is true with no changes to Swift.  The claim that such a thing 
>> is counter to the design of Swift is completely perplexing to me.
> 
> Chris, having myself nursed this sense that Swift is somehow “especially 
> safe” in a way that feels closer to ML than C, you’ve prompted me to consider 
> _why_ I feel that way.
> 
> Sentiments like this subjectively fit the _experience_ of using Swift. When 
> using the language in practice, it’s fairly clear to a mindful developer 
> which operations carry some inherent level of danger, what kind of danger 
> that is, how to reason about it, and how to mitigate it. (Usually, anyway.)
> 
> Having all had this pleasant experience, I think we may be too quick to look 
> for the explanation in the design of the language itself. We fail to notice 
> that it comes not from the language alone, but from the whole ecosystem that 
> surrounds it: standard library design, naming conventions, tools, libraries, 
> culture, Erica’s books, etc.
> 
> Optionals present themselves as a specially privileged part of the language; 
> `withUnsafeBytes` presents itself as a library call using existing language 
> features. But both share a similar definitively Swift-ish aesthetic in how 
> they guide our attention, and how they circumscribe programmer error while 
> leaving the language ergonomic and situationally adaptable.
> 
> Your reminder is a good one: Swift already does not have, and never has had, 
> a sense of safety that depends on Haskell-like strictness in the language 
> itself. The design question at hand in this thread thus becomes not “how can 
> we prevent dynamic dispatch from ruining everything” but rather “how can we 
> introduce this new element in a way that does not disrupt the ecosystem.” In 
> considering that, we’d do well to remember 

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

2017-12-03 Thread Magnus Ahltorp via swift-evolution
> 4 Dec. 2017 11:17 Letanyan Arumugam via swift-evolution 
>  wrote:
> 
> The most minimal way of marking expressions in a way I could think of that 
> would also remove anyones notion of "this code is fully supported static 
> Swift code” would be to use the currently reserved ‘ (Single quote).
> 
> Using the code example from another conversation:
> 
> let np = Python.import("numpy")
> let x = np.array([6, 7, 8])
> let y =  np.arange(24).reshape(2, 3, 4)
>   
> let a = np.ones(3, dtype: np.int32)
> let b = np.linspace(0, pi, 3)
> let c = a+b
> let d = np.exp(c)
> print(d)
> 
> Would become:
> 
> let np = Python.import("numpy")
> let x = 'np.array([6, 7, 8])'
> let y = 'np.arrange(24).reshape(2, 3, 4)'
> 
> let a = 'np.ones(3, dtype: np.int32)'
> let b = 'np.linespace(0, pi, 3)'
> let c = a+b
> let d = 'np.exp(c)’
> print(d)

1. a+b is also is a dynamic method call in this example. How would you explain 
to a programmer that they have to use single quotes around some expressions but 
not others?
2. Having this kind of special syntax would feel very arbitrary to the 
programmer, and hard to look up. Fixits would of course be able to help here, 
but if the compiler already knows what you should write, why does it require 
it? Which brings me to my third point:
3. This feels like punishment, like Python making a special syntax for static 
language bridges where they have to use the phrase 
"static_typing_is_for_losers" in front of every method call.

It's not like dynamic method calls will appear in your code if you don't use 
these kind of bridges, and even if you do, it will only be when you call 
methods on that bridge's types. When you call a method on an object, you 
already have to know what that object does, or you will be in trouble.

/Magnus

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


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

2017-12-03 Thread Letanyan Arumugam via swift-evolution
Hi

I’ve very much been teetering on my preference of having dynamic member lookup 
sites marked or not and have landed on the side of having it marked. This is 
for a few reasons:

1. There needs to be some way of conveying that this is not a ‘blessed’ way of 
writing things.
2. It’s a different paradigm and would benefit a reader by having that 
documented.
3. It’s weird that code completion, jump to and other code insights stop 
working for valid members. I’m not worried about having these insights not 
working though, just the inconsistency. Along with my mental model of my code 
not working with my tools meaning theres something wrong with my code.

The most minimal way of marking expressions in a way I could think of that 
would also remove anyones notion of "this code is fully supported static Swift 
code” would be to use the currently reserved ‘ (Single quote).

Using the code example from another conversation:

let np = Python.import("numpy")
let x = np.array([6, 7, 8])
let y =  np.arange(24).reshape(2, 3, 4)

let a = np.ones(3, dtype: np.int32)
let b = np.linspace(0, pi, 3)
let c = a+b
let d = np.exp(c)
print(d)

Would become:

let np = Python.import("numpy")
let x = 'np.array([6, 7, 8])'
let y = 'np.arrange(24).reshape(2, 3, 4)'

let a = 'np.ones(3, dtype: np.int32)'
let b = 'np.linespace(0, pi, 3)'
let c = a+b
let d = 'np.exp(c)’
print(d)

If that is still too heavy a single quote only at the beginning of the 
expression could be used:

let np = Python.import("numpy")
let x = 'np.array([6, 7, 8])
let y = 'np.arrange(24).reshape(2, 3, 4)

let a = 'np.ones(3, dtype: 'np.int32)
let b = 'np.linespace(0, pi, 3)
let c = a+b
let d = 'np.exp(c)
print(d)


I’m aware that Python is a dynamic language and would be fine with not having 
lookups marked if it were just dynamic language wrappers that this proposal 
affected. A way to get around this could be to use Option 2 of "Reducing 
Potential Abuse” in the proposal along with having non blessed types require 
markings or would that be too much of an inconsistency?

FWIW I really hope this proposal goes through, even if it were as is, just for 
the reason of getting Swift more people. 
Another reason I have to wanting this dynamic feature to be more explicit is 
that I (like I suspect many others) have been burnt by dynamic features in the 
past and have run to Swift as a home away from it :)


-Letanyan



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


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

2017-12-03 Thread Paul Cantrell via swift-evolution


> On Dec 3, 2017, at 1:26 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> On Dec 3, 2017, at 11:03 AM, Magnus Ahltorp  wrote:
>> 
>>> 4 Dec. 2017 02:40 Chris Lattner via swift-evolution 
>>>  wrote:
>>> 
>>> That’s a good principle.  However, a dynamic member lookup is just a member 
>>> lookup.  By that principle, it should look like a member lookup :-)
>>> 
>>> Further, I incorporated some of the conversation with Matthew into the 
>>> proposal, showing how adding even a single sigil to dynamic member lookup 
>>> to distinguish it is problematic:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
>>> 
>>> Further, adding something like .dynamic would completely undermind the 
>>> proposal.  You can already write:
>>> 
>>> x.get(“foo”).get(“bar”)
>>> 
>>> having to write:
>>> 
>>> x.dynamic.foo.dynamic.bar
>>> 
>>> has no point.
>> 
>> This example shows what many on this list don't believe: that any Swift 
>> method or member access can fail. If the return value of this "get" method 
>> is an IUO, or not an Optional at all, and doesn't throw, then the expression 
>> would have to fail hard if "foo" didn't resolve to something meaningful.
>> 
>> The most common argument against this proposal is that someone could make an 
>> API using Dynamic Member Lookup that could fail even though it is not 
>> apparent to the caller. But, as we see in the example, this is just as 
>> possible today.
> 
> Correct.  The argument also fails to recognize that (when bridging to a 
> dynamic language):
> 
>   x+y
> 
> Is a completely dynamic method call which can fail (or return IUO), as is:
> 
>   x[i]
> 
> And that this is true with no changes to Swift.  The claim that such a thing 
> is counter to the design of Swift is completely perplexing to me.

Chris, having myself nursed this sense that Swift is somehow “especially safe” 
in a way that feels closer to ML than C, you’ve prompted me to consider _why_ I 
feel that way.

Sentiments like this subjectively fit the _experience_ of using Swift. When 
using the language in practice, it’s fairly clear to a mindful developer which 
operations carry some inherent level of danger, what kind of danger that is, 
how to reason about it, and how to mitigate it. (Usually, anyway.)

Having all had this pleasant experience, I think we may be too quick to look 
for the explanation in the design of the language itself. We fail to notice 
that it comes not from the language alone, but from the whole ecosystem that 
surrounds it: standard library design, naming conventions, tools, libraries, 
culture, Erica’s books, etc.

Optionals present themselves as a specially privileged part of the language; 
`withUnsafeBytes` presents itself as a library call using existing language 
features. But both share a similar definitively Swift-ish aesthetic in how they 
guide our attention, and how they circumscribe programmer error while leaving 
the language ergonomic and situationally adaptable.

Your reminder is a good one: Swift already does not have, and never has had, a 
sense of safety that depends on Haskell-like strictness in the language itself. 
The design question at hand in this thread thus becomes not “how can we prevent 
dynamic dispatch from ruining everything” but rather “how can we introduce this 
new element in a way that does not disrupt the ecosystem.” In considering that, 
we’d do well to remember the long-established language features that have so 
far failed to ruin everything despite their impurity.

• • •

On this thread, there’s a lot of the tired old reflexive sneering at dynamic 
languages — I’ll spare my thoughts on that here — and a fear that creeping 
dynamism will ruin the whole neighborhood and destroy all we hold dear. I don’t 
think that will happen. I see Chris’s other examples, and the line of thought 
above, as an optimistic answer to that fear: Swift’s Swiftiness has _always_ 
depended on good judgement. It has always depended on an ecosystem that extends 
beyond the language features, and in some particular cases even pushes toward 
mindfulness and safety _in spite of_ language features. A language feature 
alone will not erase the good sense of the language’s stewards, or poison its 
community.

I think — incurring universal flaming in this discussion, I’m sure — there is a 
place for dynamic dispatch in Swift. There are a few problems, like the Python 
interop, where it is the right answer. And I’m sure that the ecosystem can 
integrate it in a way that does not fundamentally alter what we like about 
Swift. This is a language that’s managed to integrate **raw memory access**, 
for heaven’s sake, and still “feel closer to ML than C!” If it can do that, it 
can certainly withstand the far smaller disturbance in the force of what Chris 
is proposing here.

Cheers,

Paul


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

2017-12-03 Thread Chris Lattner via swift-evolution
On Dec 3, 2017, at 3:47 PM, Jonathan Hull  wrote:
>> That’s a good principle.  However, a dynamic member lookup is just a member 
>> lookup.  By that principle, it should look like a member lookup :-)
> 
> The behavior is different though (the invisible guard rails which we normally 
> rely on to prevent mistakes are missing), so it should look similar without 
> being identical.

Member lookup is already entirely API author defined.  You can define computed 
properties that do anything on get and set.  There is nothing fundamentally new 
here at all.

-Chris


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


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

2017-12-03 Thread Benjamin G via swift-evolution
On Mon, Nov 27, 2017 at 8:03 PM, Chris Lattner via swift-evolution <
swift-evolution@swift.org> wrote:

> On Nov 27, 2017, at 8:57 AM, Mathew Huusko V  wrote:
> > You're saying that there is universally no inherent difference, and that
> all calls "determine if you have called it" correctly, but then picked one
> of only a handful of cases in current practice where that is actually true.
> Yes "+" (/other math operators) and array access are unsafe, but most other
> things in Swift are safe by default, and you have to opt into un-safety
> (e.g. forcing or checking an optional or throwing call) — this is a main
> tenant of the language.
>
> There is nothing unsafe about this proposal.  It is fully type safe and
> supports failable operations (by having the properties typed as
> optionals).  This is shows by example in the proposal.
>
> Your explanation above is so confusing to me.  The closest analog to this
> feature is AnyObject dynamic lookup, which *is* completely unsafe, and is
> pervasively tangled throughout the compiler.   Maybe you’re confusing the
> two.
>


I've seen people in this thread mention AnyObject dynamic lookup as
something similar to the proposal. But there's something i don't understand
:
var a: AnyObject
a.anyFunc()

is a compiler error.

Whereas
var a: PyObject (or anything conforming to DynamicLookup depending on the
option from the proposal)
a.anyFunc()

would be perfectly fine. What's the part i didn't get ?



>
> -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] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Matthew Johnson via swift-evolution

> On Dec 3, 2017, at 5:40 PM, Chris Lattner  wrote:
> 
> 
> 
>> On Dec 3, 2017, at 3:39 PM, Matthew Johnson > > wrote:
>> 
 If that's the concern, then it would be pretty straightforward to restrict 
 dynamic protocols for stdlib internal use only and expose only PyVal. The 
 trade-off is that all such bridging code would have to be shipped with 
 Swift itself.
>>> 
>>> Right, this is specifically mentioned as option #2 in the proposal:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>>>  
>>> 
>>> 
>>> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
>>> alternative when it comes up for review.
>> 
>> FWIW, another thought along these lines which would go even further in 
>> addressing my concerns would be to isolate PyVal and other dynamic types 
>> provided as part of Swift itself in a separate module which must be imported 
>> and linked against.  That would give teams an easy way to opt-out of these 
>> types being available in their code base in a centralized fashion.  
> 
> Matthew,
> 
> We have already had many directly analogous discussions, e.g. people who want 
> to forbid the force-unwrap operator and IUOs.  The conclusion, which has 
> worked well enough in the community for multiple years now, is to relegate 
> these kinds of coding standard to third party linter tools.

I view interoperability with dynamic languages as being independent of the core 
language so I don’t see that precedent as being necessarily applicable here.  
Interoperability with C is entirely different because it is the lingua franca 
of interoperability in general and predominant operating systems specifically.  
Further, force-unwrap and IUO are core parts of the language and not a library 
feature that could be provided in a separate module.  One could reasonably ask 
what makes dynamic language interoperability more central to the language than 
the facilities provided by Foundation?  We have to draw the line for the 
standard library somewhere and it isn’t as obvious to me as it sounds like it 
is to you that dynamic language interoperability should ship as part of the 
standard library.

That said, I don’t feel so strongly about this to debate it further.  It was 
just another suggestion that I thought might be palatable to you.  Apparently I 
was wrong.  :)

> 
> -Chris
> 

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


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

2017-12-03 Thread Jonathan Hull via swift-evolution

> On Dec 3, 2017, at 9:39 AM, Chris Lattner  wrote:
> 
> On Dec 3, 2017, at 5:45 AM, Jonathan Hull  > wrote:
>> Hi Chris,
>> 
>> I am definitely in favor of providing dynamic features in Swift, and of 
>> being able to interoperate easily with dynamic languages. I really like the 
>> idea overall.
> 
> Great!
> 
>> 
>> I was about to write up a different idea I had for partially mitigating some 
>> of the issues around being able to mistype method names, etc…, but then I 
>> remembered a usability principle that I first heard from members of the Lisa 
>> team (discovered the hard way): Things which behave the same should look the 
>> same, and things which behave differently need to look different.
> 
> That’s a good principle.  However, a dynamic member lookup is just a member 
> lookup.  By that principle, it should look like a member lookup :-)

The behavior is different though (the invisible guard rails which we normally 
rely on to prevent mistakes are missing), so it should look similar without 
being identical.

If Swift were entirely dynamic, there wouldn’t be an issue here, because 
developers would have strategies for dealing with it. It is the rarity of use 
that causes the issue here.  Swift developers have built up trust in the system 
to catch their typing mistakes, so if we make it so that the system can 
silently fail, there will be an increased error rate (above what you would have 
in a purely dynamic system).

Let me give a non-computer analogy. There are lots of arguments about whether 
the toilet seat should always be put down for the next user or just be left in 
it’s current position.  Some households have them randomly up or down based on 
who used them last. This equates to the dynamic case because no trust can be 
built that the seat will be down, so everyone learns to check before sitting. 
Let’s say we add a foot pedal though, which raises the seat when you step on 
it, and lowers it when it is not pressed (like a garbage can lid).  Now 
everyone can reason about the state of the system and can trust that it will be 
down unless they step on the pedal.  As a result, over time, people will be 
able to just sit without checking.  This is great, but if we re-introduce a 
little bit of dynamism (let’s say someone can lift the seat without using the 
pedal and it will stay up)… now the people who have built trust in the system, 
and just sit, will fall in.

The end result is that either some trust is lost in the system as a whole 
(people use the dynamic way of thinking when they don’t need to) or they 
continue to have errors when dealing with the rare dynamic cases.

I also like Paul’s suggestion of different syntax coloring for the dynamic 
calls.  In the toilet seat analogy, it is like one of those little lights you 
can buy that turns green or red depending on whether the seat is up or down.


> Further, I incorporated some of the conversation with Matthew into the 
> proposal, showing how adding even a single sigil to dynamic member lookup to 
> distinguish it is problematic:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
>  
> 
> 
> Further, adding something like .dynamic would completely undermind the 
> proposal.  You can already write:
> 
>   x.get(“foo”).get(“bar”)
> 
> having to write:
> 
>   x.dynamic.foo.dynamic.bar
> 
> has no point.

Oh no, I meant a single ‘dynamic’ would enable dynamic lookup for the entire 
chain, so it would be:

x.dynamic.foo.bar

This is different than requiring a sigil for each lookup.


>> What this means is that it is easy to wrap commonly used calls in a normal 
>> swift method:
>> 
>>  func addTrick(_ name:String) {
>>  self.dynamic.add_trick(name)
>>  }
> 
> This would require wrapping all calls for them to be usable.

I don’t think that chaining with ‘dynamic' is too large of a burden (when it 
works for the entire chain), so that would be the fallback for calls that 
haven’t been wrapped. Even if calls are never wrapped, I think this is workable.

My expectation though is that frequently used calls would end up getting 
wrapped eventually, and the wrappers would covert to/from Swift types.  
Basically, I want a system which encourages people to thoughtfully Swift-ify™ 
the interface for working with python code incrementally over time. Python 
coders may have no incentive to do this, but Swift users of that code sure do.

I guess what I am arguing is that we should prioritize/optimize the ease of 
creating that translation layer at the cost of making pure/direct calls into 
Python require an extra word of typing.  Two birds, one stone.

Thanks,
Jon


___
swift-evolution mailing list
swift-evolution@swift.org

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

2017-12-03 Thread Matthew Johnson via swift-evolution

> On Dec 3, 2017, at 5:38 PM, Chris Lattner  wrote:
> 
> 
> 
>> On Dec 3, 2017, at 3:34 PM, Matthew Johnson > > wrote:
>> 
>>> 
>>> On Dec 3, 2017, at 5:14 PM, Chris Lattner >> > wrote:
>>> 
>>> 
 On Dec 3, 2017, at 2:44 PM, Xiaodi Wu > wrote:
 
> 
> and you don’t realize that PyVal’s are involved.  However, if you are 
> actively writing the code, you have access to code completion and other 
> things that tell you these types, and if it is important for the clarity 
> of the code, you write this instead:
> 
>   let x :PyVal = foo()[“someKey”]
> 
> There is nothing specific to this proposal about this issue.
 
 See above.  In the case of PyVal specifically the concern is somewhat 
 mitigated by the name of the type.  That won’t necessarily always be the 
 case.
 
 If that's the concern, then it would be pretty straightforward to restrict 
 dynamic protocols for stdlib internal use only and expose only PyVal. The 
 trade-off is that all such bridging code would have to be shipped with 
 Swift itself.
>>> 
>>> Right, this is specifically mentioned as option #2 in the proposal:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>>>  
>>> 
>>> 
>>> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
>>> alternative when it comes up for review.
>> 
>> This would certainly address the majority of my concerns while still 
>> addressing the motivating use case.  I don’t think it’s an ideal solution 
>> but it’s one I could live with and perhaps it is the best tradeoff.  It 
>> would certainly focus the proposal more directly on the use case you care 
>> most about leaving the distraction of conformances by user-defined Swift 
>> types as a separate conversation.
> 
> 
>> If would had to choose an alternative is this preferable to you over some 
>> kind of usage-site annotation?
> 
> Yes, vastly.  This does not completely defeat the purpose of the proposal in 
> the first place.
> 
> 
> You miss my point.  My point is that AnyObject lookup was carefully 
> considered, has stood the test of time, and is the *right* answer.  Swift 
> 1 would not have been nearly as successful without it.
 
 I don’t think I do.  I was trying to agree with exactly the point that it 
 was the right answer in the early days of Swift and getting it right then 
 was essential to Swift’s success.  
>>> 
>>> Ok, but the “early days of Swift” are directly analogous to the present 
>>> days of other dynamic languages.
>> 
>> On a technical level that is true in many respects, but on a social level 
>> certainly not.  You would obviously know a lot better than I, but I imagine 
>> that Swift’s success at displacing Objective-C in the Apple world was not at 
>> all a foregone conclusion in the earliest days.  It is now a well 
>> established language with a significant user base that isn’t going anywhere.
> 
> Correct.  Similarly, it is also not a forgone conclusion that the Python and 
> Javascript communities will care.  Python and Javascript have at least a 
> couple orders of magnitude more programmers than Swift does. Swift is a toy 
> by comparison.

Understood, and the goal of attracting them is a worthy one!

> 
> -Chris
> 

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


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

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


> On Dec 3, 2017, at 3:39 PM, Matthew Johnson  wrote:
> 
>>> If that's the concern, then it would be pretty straightforward to restrict 
>>> dynamic protocols for stdlib internal use only and expose only PyVal. The 
>>> trade-off is that all such bridging code would have to be shipped with 
>>> Swift itself.
>> 
>> Right, this is specifically mentioned as option #2 in the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>>  
>> 
>> 
>> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
>> alternative when it comes up for review.
> 
> FWIW, another thought along these lines which would go even further in 
> addressing my concerns would be to isolate PyVal and other dynamic types 
> provided as part of Swift itself in a separate module which must be imported 
> and linked against.  That would give teams an easy way to opt-out of these 
> types being available in their code base in a centralized fashion.  

Matthew,

We have already had many directly analogous discussions, e.g. people who want 
to forbid the force-unwrap operator and IUOs.  The conclusion, which has worked 
well enough in the community for multiple years now, is to relegate these kinds 
of coding standard to third party linter tools.

-Chris

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


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

2017-12-03 Thread Matthew Johnson via swift-evolution

> On Dec 3, 2017, at 5:14 PM, Chris Lattner  wrote:
> 
> 
>> On Dec 3, 2017, at 2:44 PM, Xiaodi Wu > > wrote:
>> 
>>> 
>>> and you don’t realize that PyVal’s are involved.  However, if you are 
>>> actively writing the code, you have access to code completion and other 
>>> things that tell you these types, and if it is important for the clarity of 
>>> the code, you write this instead:
>>> 
>>> let x :PyVal = foo()[“someKey”]
>>> 
>>> There is nothing specific to this proposal about this issue.
>> 
>> See above.  In the case of PyVal specifically the concern is somewhat 
>> mitigated by the name of the type.  That won’t necessarily always be the 
>> case.
>> 
>> If that's the concern, then it would be pretty straightforward to restrict 
>> dynamic protocols for stdlib internal use only and expose only PyVal. The 
>> trade-off is that all such bridging code would have to be shipped with Swift 
>> itself.
> 
> Right, this is specifically mentioned as option #2 in the proposal:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>  
> 
> 
> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
> alternative when it comes up for review.

FWIW, another thought along these lines which would go even further in 
addressing my concerns would be to isolate PyVal and other dynamic types 
provided as part of Swift itself in a separate module which must be imported 
and linked against.  That would give teams an easy way to opt-out of these 
types being available in their code base in a centralized fashion.  

> 
>>> You miss my point.  My point is that AnyObject lookup was carefully 
>>> considered, has stood the test of time, and is the *right* answer.  Swift 1 
>>> would not have been nearly as successful without it.
>> 
>> I don’t think I do.  I was trying to agree with exactly the point that it 
>> was the right answer in the early days of Swift and getting it right then 
>> was essential to Swift’s success.  
> 
> Ok, but the “early days of Swift” are directly analogous to the present days 
> of other dynamic languages.  
> 
>> 
>> Aside from the historical necessity of AnyObject, it is also a very specific 
>> and widely know type that doesn’t have any statically available members at 
>> all and only looks up @objc members.  These properties help to reduce the 
>> risk that somebody misunderstands what is going on.
>> 
>> I imagine we could restrict all such dynamic types from having any 
>> statically available members without losing much.
> 
> This isn’t practical.  We need some traditionally defined members so that 
> PyVal can conform to standard protocols, like ExpressibleByIntegerLiteral and 
> many others.
> 
> -Chris
> 

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


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

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


> On Dec 3, 2017, at 3:34 PM, Matthew Johnson  wrote:
> 
>> 
>> On Dec 3, 2017, at 5:14 PM, Chris Lattner > > wrote:
>> 
>> 
>>> On Dec 3, 2017, at 2:44 PM, Xiaodi Wu >> > wrote:
>>> 
 
 and you don’t realize that PyVal’s are involved.  However, if you are 
 actively writing the code, you have access to code completion and other 
 things that tell you these types, and if it is important for the clarity 
 of the code, you write this instead:
 
let x :PyVal = foo()[“someKey”]
 
 There is nothing specific to this proposal about this issue.
>>> 
>>> See above.  In the case of PyVal specifically the concern is somewhat 
>>> mitigated by the name of the type.  That won’t necessarily always be the 
>>> case.
>>> 
>>> If that's the concern, then it would be pretty straightforward to restrict 
>>> dynamic protocols for stdlib internal use only and expose only PyVal. The 
>>> trade-off is that all such bridging code would have to be shipped with 
>>> Swift itself.
>> 
>> Right, this is specifically mentioned as option #2 in the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>>  
>> 
>> 
>> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
>> alternative when it comes up for review.
> 
> This would certainly address the majority of my concerns while still 
> addressing the motivating use case.  I don’t think it’s an ideal solution but 
> it’s one I could live with and perhaps it is the best tradeoff.  It would 
> certainly focus the proposal more directly on the use case you care most 
> about leaving the distraction of conformances by user-defined Swift types as 
> a separate conversation.


> If would had to choose an alternative is this preferable to you over some 
> kind of usage-site annotation?

Yes, vastly.  This does not completely defeat the purpose of the proposal in 
the first place.


 You miss my point.  My point is that AnyObject lookup was carefully 
 considered, has stood the test of time, and is the *right* answer.  Swift 
 1 would not have been nearly as successful without it.
>>> 
>>> I don’t think I do.  I was trying to agree with exactly the point that it 
>>> was the right answer in the early days of Swift and getting it right then 
>>> was essential to Swift’s success.  
>> 
>> Ok, but the “early days of Swift” are directly analogous to the present days 
>> of other dynamic languages.
> 
> On a technical level that is true in many respects, but on a social level 
> certainly not.  You would obviously know a lot better than I, but I imagine 
> that Swift’s success at displacing Objective-C in the Apple world was not at 
> all a foregone conclusion in the earliest days.  It is now a well established 
> language with a significant user base that isn’t going anywhere.

Correct.  Similarly, it is also not a forgone conclusion that the Python and 
Javascript communities will care.  Python and Javascript have at least a couple 
orders of magnitude more programmers than Swift does. Swift is a toy by 
comparison.

-Chris

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


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

2017-12-03 Thread Matthew Johnson via swift-evolution

> On Dec 3, 2017, at 5:14 PM, Chris Lattner  wrote:
> 
> 
>> On Dec 3, 2017, at 2:44 PM, Xiaodi Wu > > wrote:
>> 
>>> 
>>> and you don’t realize that PyVal’s are involved.  However, if you are 
>>> actively writing the code, you have access to code completion and other 
>>> things that tell you these types, and if it is important for the clarity of 
>>> the code, you write this instead:
>>> 
>>> let x :PyVal = foo()[“someKey”]
>>> 
>>> There is nothing specific to this proposal about this issue.
>> 
>> See above.  In the case of PyVal specifically the concern is somewhat 
>> mitigated by the name of the type.  That won’t necessarily always be the 
>> case.
>> 
>> If that's the concern, then it would be pretty straightforward to restrict 
>> dynamic protocols for stdlib internal use only and expose only PyVal. The 
>> trade-off is that all such bridging code would have to be shipped with Swift 
>> itself.
> 
> Right, this is specifically mentioned as option #2 in the proposal:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
>  
> 
> 
> It sounds like Matthew’s concerns can be addressed by him +1’ing that 
> alternative when it comes up for review.

This would certainly address the majority of my concerns while still addressing 
the motivating use case.  I don’t think it’s an ideal solution but it’s one I 
could live with and perhaps it is the best tradeoff.  It would certainly focus 
the proposal more directly on the use case you care most about leaving the 
distraction of conformances by user-defined Swift types as a separate 
conversation.  If would had to choose an alternative is this preferable to you 
over some kind of usage-site annotation?

> 
>>> You miss my point.  My point is that AnyObject lookup was carefully 
>>> considered, has stood the test of time, and is the *right* answer.  Swift 1 
>>> would not have been nearly as successful without it.
>> 
>> I don’t think I do.  I was trying to agree with exactly the point that it 
>> was the right answer in the early days of Swift and getting it right then 
>> was essential to Swift’s success.  
> 
> Ok, but the “early days of Swift” are directly analogous to the present days 
> of other dynamic languages.

On a technical level that is true in many respects, but on a social level 
certainly not.  You would obviously know a lot better than I, but I imagine 
that Swift’s success at displacing Objective-C in the Apple world was not at 
all a foregone conclusion in the earliest days.  It is now a well established 
language with a significant user base that isn’t going anywhere.

>  
> 
>> 
>> Aside from the historical necessity of AnyObject, it is also a very specific 
>> and widely know type that doesn’t have any statically available members at 
>> all and only looks up @objc members.  These properties help to reduce the 
>> risk that somebody misunderstands what is going on.
>> 
>> I imagine we could restrict all such dynamic types from having any 
>> statically available members without losing much.
> 
> This isn’t practical.  We need some traditionally defined members so that 
> PyVal can conform to standard protocols, like ExpressibleByIntegerLiteral and 
> many others.
> 
> -Chris
> 

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


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

2017-12-03 Thread Benjamin G via swift-evolution
On Sun, Dec 3, 2017 at 8:26 PM, Chris Lattner via swift-evolution <
swift-evolution@swift.org> wrote:

> On Dec 3, 2017, at 11:03 AM, Magnus Ahltorp  wrote:
> >
> >> 4 Dec. 2017 02:40 Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> That’s a good principle.  However, a dynamic member lookup is just a
> member lookup.  By that principle, it should look like a member lookup :-)
> >>
> >> Further, I incorporated some of the conversation with Matthew into the
> proposal, showing how adding even a single sigil to dynamic member lookup
> to distinguish it is problematic:
> >> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae54
> 38#increasing-visibility-of-dynamic-member-lookups
> >>
> >> Further, adding something like .dynamic would completely undermind the
> proposal.  You can already write:
> >>
> >>  x.get(“foo”).get(“bar”)
> >>
> >> having to write:
> >>
> >>  x.dynamic.foo.dynamic.bar
> >>
> >> has no point.
> >
> > This example shows what many on this list don't believe: that any Swift
> method or member access can fail. If the return value of this "get" method
> is an IUO, or not an Optional at all, and doesn't throw, then the
> expression would have to fail hard if "foo" didn't resolve to something
> meaningful.
> >
> > The most common argument against this proposal is that someone could
> make an API using Dynamic Member Lookup that could fail even though it is
> not apparent to the caller. But, as we see in the example, this is just as
> possible today.
>
> Correct.  The argument also fails to recognize that (when bridging to a
> dynamic language):
>
> x+y
>
> Is a completely dynamic method call which can fail (or return IUO), as is:
>
> x[i]
>
> And that this is true with no changes to Swift.  The claim that such a
> thing is counter to the design of Swift is completely perplexing to me.
>

I think the argument basically is "let's not add another footgun" (because
the design of Swift , for example regarding null handling, is to have less
footguns than other languages). The fact that there are footguns in swift
isn't an argument for adding new ones.



>
> -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] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

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

> On Dec 3, 2017, at 2:44 PM, Xiaodi Wu  wrote:
> 
>> 
>> and you don’t realize that PyVal’s are involved.  However, if you are 
>> actively writing the code, you have access to code completion and other 
>> things that tell you these types, and if it is important for the clarity of 
>> the code, you write this instead:
>> 
>>  let x :PyVal = foo()[“someKey”]
>> 
>> There is nothing specific to this proposal about this issue.
> 
> See above.  In the case of PyVal specifically the concern is somewhat 
> mitigated by the name of the type.  That won’t necessarily always be the case.
> 
> If that's the concern, then it would be pretty straightforward to restrict 
> dynamic protocols for stdlib internal use only and expose only PyVal. The 
> trade-off is that all such bridging code would have to be shipped with Swift 
> itself.

Right, this is specifically mentioned as option #2 in the proposal:
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#reducing-potential-abuse
 


It sounds like Matthew’s concerns can be addressed by him +1’ing that 
alternative when it comes up for review.

>> You miss my point.  My point is that AnyObject lookup was carefully 
>> considered, has stood the test of time, and is the *right* answer.  Swift 1 
>> would not have been nearly as successful without it.
> 
> I don’t think I do.  I was trying to agree with exactly the point that it was 
> the right answer in the early days of Swift and getting it right then was 
> essential to Swift’s success.  

Ok, but the “early days of Swift” are directly analogous to the present days of 
other dynamic languages.  

> 
> Aside from the historical necessity of AnyObject, it is also a very specific 
> and widely know type that doesn’t have any statically available members at 
> all and only looks up @objc members.  These properties help to reduce the 
> risk that somebody misunderstands what is going on.
> 
> I imagine we could restrict all such dynamic types from having any statically 
> available members without losing much.

This isn’t practical.  We need some traditionally defined members so that PyVal 
can conform to standard protocols, like ExpressibleByIntegerLiteral and many 
others.

-Chris

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


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

2017-12-03 Thread Xiaodi Wu via swift-evolution
On Sun, Dec 3, 2017 at 2:16 PM, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Dec 3, 2017, at 11:36 AM, Chris Lattner  wrote:
>
> On Dec 2, 2017, at 7:11 PM, Matthew Johnson 
> wrote:
>
>
> This does not improve clarity of code, it merely serves to obfuscate
> logic.  It is immediately apparent from the APIs being used, the API style,
> and the static types (in Xcode or through static declarations) that this is
> all Python stuff.
>
>
> It may be immediately apparent when the types involved are obviously
> dynamic, such as in this example where Python.import is explicitly used.
> However, my concern is less about the intended use case of dynamic language
> interop than I am that this feature will be generally available to all
> types in Swift.
>
> This is big change from AnyObject dispatch.  It opens up the dynamism to
> types and contexts that *are not *necessarily obviously using dynamic
> lookup, callable, etc.  Maybe this won’t turn out to be a problem in
> practice but I still think it’s a legitimate concern.
>
>
> Sure, it is a legit concern, but it is also nothing new.  This is the
> standard concern with type inference.
>
>
> The concern for me is orthogonal to type inference.  The name of a type
> supporting dynamic lookup will not necessarily provide any indication that
> the type supports dynamic lookup.
>
>
> While there are weird cases, in practice, values do not get magicked out
> of no-where.  They most commonly are either root values like:
>
> let np = Python.import(“foo”)
> let pyInt = PyVal(42)
>
> or they come for parameters:
>
> func f(x : PyVal) {
>
> The place that is potentially surprising is when the type gets buried
> because you’re working with some API that returns a [String, PyVal]
> dictionary or something:
>
>
> let x = foo()[“someKey”]
>
> and you don’t realize that PyVal’s are involved.  However, if you are
> actively writing the code, you have access to code completion and other
> things that tell you these types, and if it is important for the clarity of
> the code, you write this instead:
>
> let x :PyVal = foo()[“someKey”]
>
> There is nothing specific to this proposal about this issue.
>
>
> See above.  In the case of PyVal specifically the concern is somewhat
> mitigated by the name of the type.  That won’t necessarily always be the
> case.
>

If that's the concern, then it would be pretty straightforward to restrict
dynamic protocols for stdlib internal use only and expose only PyVal. The
trade-off is that all such bridging code would have to be shipped with
Swift itself.


> I’m uncertain what the right answer is.  I’m still not really comfortable
> with opening up dynamic lookup to any user-defined type without some way to
> indicate to readers that dynamic lookup is happening in a piece of code.
> Maybe there is a less localized annotation that would indicate dynamic
> lookup is in effect for a larger chunk of code.
>
>
> You seem to be extremely concerned that people will adopt
> DynamicMemberLookup for types where it doesn’t make sense and abuse the
> feature.  I am having a real problem understanding what your concern is, so
> I’d really love for you to explain some theoretical examples of the bad
> thing that happens: why someone (non-maliciously) adopts the protocol, what
> code gets written, and what harm actually comes from it.
>
> Let me use a made up tale from a parallel universe to illustrate why I
> don’t understand your concern.  Imagine if Swift didn’t already
> interoperate with C, and did not already have IUOs.  Someone who cared
> about C language interoperability would quickly realize that the ergonomics
> of importing everything as strong optionals is a non-starter, jeopardizing
> the usability of C interop, and would propose IUOs as a feature.
>
> We’d then have a long and drawn out conversation about the various options
> on how to model this, the pros and cons of each, and would settle on IUO as
> the least bad design (as an aside, in our universe, when we went through
> the design process that led to IUOs, this is exactly what happened, we even
> considered syntaxing them as interobangs :-).
>
> At that point, there would be a general uproar because IUOs have high
> potential for abuse: Swift is “all about” strong types and safety, which
> IUOs undermine.  Strong optionals are considered a pain to use by some
> people and widely misunderstood (I think they are the biggest challenge in
> learning Swift in practice), and so it is a reasonable feature that people
> could pervasively adopt IUOs, leading to a much worse world all around.
>
>
> This made up parallel universe is exactly analogous to what is happening
> now.  DynamicMemberLookup is no more dangerous and harmful than IUOs are.
> They will be one more tool in the toolbox.  While it is possible that
> someone will abuse it, this will not be widespread.  People who are
> particularly worried will build a 

Re: [swift-evolution] [RFC] Associated type inference

2017-12-03 Thread Jens Persson via swift-evolution
Would this help sorting out the behavior of typealiases in constrained
extensions?

If not, please ignore the following and accept my apologies for posting OT.

Typealiases in constrained extensions are - and have been, for a long time
- very broken.
The following program (which is clearly crazy in several ways) compiles and
runs using the latest version of the compiler:

struct S {
  var v: This
}
extension S where T == Int {
  typealias This = Is
}
extension S where T == Bool {
  typealias Is = Fine
}
extension S where T == String {
  typealias Fine = T
}
let x = S(v: "uh")
print(x.v) // uh

( SR-5440 )
The current behavior is so allowing and strange that I'm having trouble
seeing what the correct behavior would be if things worked as intended.
For example should the following program still compile, and if so, should
the last line also compile (if uncommented)?

protocol P {
associatedtype A = Int
associatedtype B = Bool
typealias C = Float
}
extension P where B == A {
typealias C = String
}
struct S : P {
var v: (A, B, C)
}
extension S where A == Int, B == Bool {
typealias C = [String]
}
let s1 = S(v: (1, true, [""]))
// let s2 = S(v: ("a", "b", "c")) // Not (currently) ok.

Again, sorry for the noise if this is unrelated to the discussion.
/Jens


On Sun, Dec 3, 2017 at 6:23 AM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Nov 30, 2017, at 2:28 PM, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hello Swift community,
>
> Associated type inference, which is the process by which the Swift
> compiler attempts to infer typealiases to satisfy associated-type
> requirements based on other requirements, has caused both implementation
> problems and user confusion for a long time. Some of you might remember a
> previous (failed) attempt to remove this feature from the Swift language,
> in SE-0108 “Remove associated type inference”.
> 
>
>
> I’m not sure we can remove this feature outright (i.e., the concerns that
> sank that proposal are still absolutely valid), because it is so very
> convenient and a lot of user code likely depends on it in some form or
> other. So, here I’d like to describe the uses of the feature, its current
> (very problematic) implementation approach, and a half-baked proposal to
> narrow the scope of associated type inference to something that I think is
> more tractable. I need help with the design of this feature, because I feel
> like it’s going to be a delicate balance between implementability and
> expressiveness.
>
>
> Aloha, Doug!
>
>
> *A Motivating Example*
> As a motivating example, let’s consider a “minimal” random access
> collection:
>
> struct MyCollection {
> var contents: [T]
> }
>
> extension MyCollection: RandomAccessCollection {
> var startIndex: Int { return contents.startIndex }
> var endIndex: Int { return contents.endIndex }
> subscript(index: Int) -> T { return contents[index] }
> }
>
>
> This is actually pretty awesome: by providing just two properties and a
> subscript, we get the full breadth of the random access collection API!
> This is relying heavily on associated type inference (for associated type
> requirements) and default implementations specified on protocol extensions.
> Without associated type inference, we would have had to write:
>
>
> extension MyCollection: RandomAccessCollection {
> *typealias Element = T*
> *typealias Index = Int*
> *typealias Indices = CountableRange*
> *typealias Iterator = IndexingIterator*
> *typealias SubSequence = RandomAccessSlice*
>
> var startIndex: Int { return contents.startIndex }
> var endIndex: Int { return contents.endIndex }
> subscript(index: Int) -> T { return contents[index] }
> }
>
> where the bolded typealiases are currently inferred. It was worse back
> when we reviewed SE-0108, because IIRC there were a few underscored
> associated types (e.g., _Element) that have since been removed. Still,
> that’s a bit of additional work to define a “minimal” collection, and
> requires quite a bit more understanding: how do I know to choose
> IndexingIterator, and CountableRange, and RandomAccessSlice?
>
> The issue would get worse with, e.g., SE-0174 “Change filter to return an
> associated type”
> ,
> which adds an associated type Filtered that almost nobody will ever
> customize, and isn’t really fundamental to the way collections work. Adding
> Filtered to the standard library would be a source-breaking change, because
> users would have to write a typealias giving it its default.
>
> *Associated Type Defaults*
> One of the ways in which we avoid having to specify typealiases is to use
> associated type defaults. For example, the standard library 

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

2017-12-03 Thread Xiaodi Wu via swift-evolution
On Sun, Dec 3, 2017 at 2:20 PM, Karl Wagner via swift-evolution <
swift-evolution@swift.org> wrote:

>
> I believe that adding explicit syntax would be counterproductive to your
> goals, and would not make dynamic lookup syntax more clear.  I assume that
> you would also want the same thing for DynamicCallable too, and operator
> overloads, subscripts, and every other operation you perform on these
> values, since they all have the exact same behavior.
>
> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”,
> that change would turn this (which uses runtime failing or IUO return
> values like AnyObject):
>
> let np = Python.import("numpy")
> let x = np.array([6, 7, 8])
> let y =  np.arange(24).reshape(2, 3, 4)
> let a = np.ones(3, dtype: np.int32)
> let b = np.linspace(0, pi, 3)
> let c = a+b
> let d = np.exp(c)
> print(d)
>
> into:
>
> let np = Python.import("numpy")
> let b = np^.array^([6, 7, 8])
> let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>
> let a = np^.ones^(3, dtype: np^.int32)
> let b = np^.linspace^(0, pi, 3)
> let c = a+^b
> let d = np^.exp^(c)
>
> This does not improve clarity of code, it merely serves to obfuscate
> logic.  It is immediately apparent from the APIs being used, the API style,
> and the static types (in Xcode or through static declarations) that this is
> all Python stuff.  When you start mixing in use of native Swift types like
> dictionaries (something we want to encourage because they are typed!) you
> end up with an inconsistent mismash where people would just try adding
> syntax or applying fixits continuously until the code builds.
>
>
> That’s not Swift. You just wrote a bunch of Python. For example, Swift has
> a native Int32.+ operator which fails on overflow - does your example also
> do that? Anybody’s guess! Does your numpy array conform to Collection? I
> guess not, because it’s an opaque Python value.
>
> That’s exactly the kind of stuff I, as a user of the language, really
> don't want to see mixed together with real Swift. I appreciate the need to
> use functionality from libraries written in Python, but I don’t appreciate
> it being so invisible and pervasive throughout the language. If you have a
> bunch of Python logic, I’d prefer you wrote as much of it as possible in
> Python, with as few bridging points to Swift as you can get away with. I
> remain convinced that this design encourages the opposite - because, as you
> said earlier, it’s “too good”.
>

The use case that Chris is solving here is precisely how to enable the
writing of this type of code in Swift. Put another way, how do I interface
with libraries written in Python without writing my own code in Python?
"That's exactly the kind of stuff I really don't want to see mixed together
with real Swift" and "I'd prefer you wrote as much of it as possible in
Python" is not an answer; it's rejecting the legitimacy of the use case in
the first place.

As for the point about Swift already including non-marked,
> potentially-crashing operations (like the + operator, or Array
> subscripting): nobody likes that behaviour!
>

I, for one, very much like that behavior. Swift has many non-marked,
potentially-crashing operations because that is both performant and safe.
There is a common misconception that crashing is unsafe, with corresponding
misconceptions such as avoiding "!". This is simply incorrect.


> Whenever I come to a new Swift codebase, I almost universally find that
> people have written their own “safe” Array accessor which integrates
> bounds-checking and returns an Optional. The issue has come up here many,
> many times for inclusion in the standard library. I certainly would not use
> it as justification for adding more of those kinds of unmarked,
> potentially-unsafe operations. Also, enough Swift developers know about the
> Array subscript behaviour that the square brackets almost become a marker,
> like “!”, of a potentially-failing operation. The same is not true of the
> dot operator, in general.
>
> I also don’t agree with the comparisons to Objective-C/AnyObject dispatch.
> It’s true that it’s unsafe to an extent, but it’s also orders of magnitude
> safer than this sort of dispatch. Clang is integrated in to the compiler,
> and can at least perform some rudimentary checking of method
> signatures/selectors. This sort of dispatch provides absolutely no
> protections whatsoever — is “arange” really a function? Is it not really a
> typo for “arrange”? That’s something I need to Google. With regular Swift I
> can assume that if the compiler allows it, there is a function called
> “arange” somewhere, and all I need to worry about is whether the erased
> AnyObject is of the correct type to respond to that message. And as I said
> earlier, AnyObject is incredibly rare in practice anyway. So no, I don’t
> agree that we should just keep lowering the safeguards; it’s like
> demolishing your house because of one draughty door.
>
> What I *could* support, would be some kind of 

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

2017-12-03 Thread Thorsten Seitz via swift-evolution
+1

-Thorsten


> Am 03.12.2017 um 21:20 schrieb Karl Wagner via swift-evolution 
> :
> 
>> 
>> I believe that adding explicit syntax would be counterproductive to your 
>> goals, and would not make dynamic lookup syntax more clear.  I assume that 
>> you would also want the same thing for DynamicCallable too, and operator 
>> overloads, subscripts, and every other operation you perform on these 
>> values, since they all have the exact same behavior.
>> 
>> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
>> that change would turn this (which uses runtime failing or IUO return values 
>> like AnyObject):
>> 
>>  let np = Python.import("numpy")
>>  let x = np.array([6, 7, 8])
>>  let y =  np.arange(24).reshape(2, 3, 4)
>>  
>>  let a = np.ones(3, dtype: np.int32)
>>  let b = np.linspace(0, pi, 3)
>>  let c = a+b
>>  let d = np.exp(c)
>>  print(d)
>> 
>> into:
>> 
>>  let np = Python.import("numpy")
>>  let b = np^.array^([6, 7, 8])
>>  let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>>  
>>  let a = np^.ones^(3, dtype: np^.int32)
>>  let b = np^.linspace^(0, pi, 3)
>>  let c = a+^b
>>  let d = np^.exp^(c)
>> 
>> This does not improve clarity of code, it merely serves to obfuscate logic.  
>> It is immediately apparent from the APIs being used, the API style, and the 
>> static types (in Xcode or through static declarations) that this is all 
>> Python stuff.  When you start mixing in use of native Swift types like 
>> dictionaries (something we want to encourage because they are typed!) you 
>> end up with an inconsistent mismash where people would just try adding 
>> syntax or applying fixits continuously until the code builds.
> 
> That’s not Swift. You just wrote a bunch of Python. For example, Swift has a 
> native Int32.+ operator which fails on overflow - does your example also do 
> that? Anybody’s guess! Does your numpy array conform to Collection? I guess 
> not, because it’s an opaque Python value.
> 
> That’s exactly the kind of stuff I, as a user of the language, really don't 
> want to see mixed together with real Swift. I appreciate the need to use 
> functionality from libraries written in Python, but I don’t appreciate it 
> being so invisible and pervasive throughout the language. If you have a bunch 
> of Python logic, I’d prefer you wrote as much of it as possible in Python, 
> with as few bridging points to Swift as you can get away with. I remain 
> convinced that this design encourages the opposite - because, as you said 
> earlier, it’s “too good”.
> 
> As for the point about Swift already including non-marked, 
> potentially-crashing operations (like the + operator, or Array subscripting): 
> nobody likes that behaviour! Whenever I come to a new Swift codebase, I 
> almost universally find that people have written their own “safe” Array 
> accessor which integrates bounds-checking and returns an Optional. The issue 
> has come up here many, many times for inclusion in the standard library. I 
> certainly would not use it as justification for adding more of those kinds of 
> unmarked, potentially-unsafe operations. Also, enough Swift developers know 
> about the Array subscript behaviour that the square brackets almost become a 
> marker, like “!”, of a potentially-failing operation. The same is not true of 
> the dot operator, in general.
> 
> I also don’t agree with the comparisons to Objective-C/AnyObject dispatch. 
> It’s true that it’s unsafe to an extent, but it’s also orders of magnitude 
> safer than this sort of dispatch. Clang is integrated in to the compiler, and 
> can at least perform some rudimentary checking of method 
> signatures/selectors. This sort of dispatch provides absolutely no 
> protections whatsoever — is “arange” really a function? Is it not really a 
> typo for “arrange”? That’s something I need to Google. With regular Swift I 
> can assume that if the compiler allows it, there is a function called 
> “arange” somewhere, and all I need to worry about is whether the erased 
> AnyObject is of the correct type to respond to that message. And as I said 
> earlier, AnyObject is incredibly rare in practice anyway. So no, I don’t 
> agree that we should just keep lowering the safeguards; it’s like demolishing 
> your house because of one draughty door.
> 
> What I could support, would be some kind of optional syntax, possibly with 
> some kind of associated scope which allows you omit it. Something like:
> 
> // Normally, optionals are required.
> let result: PythonObject? = pythonObj.someProperty?.someFunction(1, 2, 3)
> 
> // Within a special scope, you can omit them. The scope will bail at the 
> first lookup failure and return nil.
> let result: PythonObject? = Python {
> return pythonObj.someProperty.someFunction(1, 2, 3)
> }
> 
> Perhaps the “Python” object could conform to a protocol with an associated 
> type for the objects it can 

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

2017-12-03 Thread Thorsten Seitz via swift-evolution

> Am 03.12.2017 um 20:08 schrieb Magnus Ahltorp :
> 
>> 4 Dec. 2017 03:54 Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> The difference is that IUOs are marked by a "!“ whereas dynamic member 
>> lookups look just like normal member lookups but unlike them can fail.
> 
> IUOs are not marked with an "!" by the caller, that's what makes them 
> implicit. They *are* marked at the declaration, but so would dynamic member 
> lookups be.

You are right, my mistake. 

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


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

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

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

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

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


**someModule.swift***

public protocol JustAnotherProtocol: DynamicCallable {...}


**myModule.swif***

struct JSVal: JustAnotherProtocol {...}



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

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

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


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



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


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

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


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

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


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


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

2017-12-03 Thread Karl Wagner via swift-evolution
> 
> I believe that adding explicit syntax would be counterproductive to your 
> goals, and would not make dynamic lookup syntax more clear.  I assume that 
> you would also want the same thing for DynamicCallable too, and operator 
> overloads, subscripts, and every other operation you perform on these values, 
> since they all have the exact same behavior.
> 
> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, that 
> change would turn this (which uses runtime failing or IUO return values like 
> AnyObject):
> 
>   let np = Python.import("numpy")
>   let x = np.array([6, 7, 8])
>   let y =  np.arange(24).reshape(2, 3, 4)
>   
>   let a = np.ones(3, dtype: np.int32)
>   let b = np.linspace(0, pi, 3)
>   let c = a+b
>   let d = np.exp(c)
>   print(d)
> 
> into:
> 
>   let np = Python.import("numpy")
>   let b = np^.array^([6, 7, 8])
>   let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>   
>   let a = np^.ones^(3, dtype: np^.int32)
>   let b = np^.linspace^(0, pi, 3)
>   let c = a+^b
>   let d = np^.exp^(c)
> 
> This does not improve clarity of code, it merely serves to obfuscate logic.  
> It is immediately apparent from the APIs being used, the API style, and the 
> static types (in Xcode or through static declarations) that this is all 
> Python stuff.  When you start mixing in use of native Swift types like 
> dictionaries (something we want to encourage because they are typed!) you end 
> up with an inconsistent mismash where people would just try adding syntax or 
> applying fixits continuously until the code builds.

That’s not Swift. You just wrote a bunch of Python. For example, Swift has a 
native Int32.+ operator which fails on overflow - does your example also do 
that? Anybody’s guess! Does your numpy array conform to Collection? I guess 
not, because it’s an opaque Python value.

That’s exactly the kind of stuff I, as a user of the language, really don't 
want to see mixed together with real Swift. I appreciate the need to use 
functionality from libraries written in Python, but I don’t appreciate it being 
so invisible and pervasive throughout the language. If you have a bunch of 
Python logic, I’d prefer you wrote as much of it as possible in Python, with as 
few bridging points to Swift as you can get away with. I remain convinced that 
this design encourages the opposite - because, as you said earlier, it’s “too 
good”.

As for the point about Swift already including non-marked, potentially-crashing 
operations (like the + operator, or Array subscripting): nobody likes that 
behaviour! Whenever I come to a new Swift codebase, I almost universally find 
that people have written their own “safe” Array accessor which integrates 
bounds-checking and returns an Optional. The issue has come up here many, many 
times for inclusion in the standard library. I certainly would not use it as 
justification for adding more of those kinds of unmarked, potentially-unsafe 
operations. Also, enough Swift developers know about the Array subscript 
behaviour that the square brackets almost become a marker, like “!”, of a 
potentially-failing operation. The same is not true of the dot operator, in 
general.

I also don’t agree with the comparisons to Objective-C/AnyObject dispatch. It’s 
true that it’s unsafe to an extent, but it’s also orders of magnitude safer 
than this sort of dispatch. Clang is integrated in to the compiler, and can at 
least perform some rudimentary checking of method signatures/selectors. This 
sort of dispatch provides absolutely no protections whatsoever — is “arange” 
really a function? Is it not really a typo for “arrange”? That’s something I 
need to Google. With regular Swift I can assume that if the compiler allows it, 
there is a function called “arange” somewhere, and all I need to worry about is 
whether the erased AnyObject is of the correct type to respond to that message. 
And as I said earlier, AnyObject is incredibly rare in practice anyway. So no, 
I don’t agree that we should just keep lowering the safeguards; it’s like 
demolishing your house because of one draughty door.

What I could support, would be some kind of optional syntax, possibly with some 
kind of associated scope which allows you omit it. Something like:

// Normally, optionals are required.
let result: PythonObject? = pythonObj.someProperty?.someFunction(1, 2, 3)

// Within a special scope, you can omit them. The scope will bail at the first 
lookup failure and return nil.
let result: PythonObject? = Python {
return pythonObj.someProperty.someFunction(1, 2, 3)
}

Perhaps the “Python” object could conform to a protocol with an associated type 
for the objects it can implicitly unwrap. There would be some additional 
compiler work, for sure, but that’s secondary to a good language model IMO 
(easy for me to say, I know).


- Karl___
swift-evolution mailing list

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

2017-12-03 Thread Matthew Johnson via swift-evolution

> On Dec 3, 2017, at 11:36 AM, Chris Lattner  wrote:
> 
> On Dec 2, 2017, at 7:11 PM, Matthew Johnson  > wrote:
>>> 
>>> This does not improve clarity of code, it merely serves to obfuscate logic. 
>>>  It is immediately apparent from the APIs being used, the API style, and 
>>> the static types (in Xcode or through static declarations) that this is all 
>>> Python stuff.  
>> 
>> It may be immediately apparent when the types involved are obviously 
>> dynamic, such as in this example where Python.import is explicitly used.  
>> However, my concern is less about the intended use case of dynamic language 
>> interop than I am that this feature will be generally available to all types 
>> in Swift.  
>> 
>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>> types and contexts that are not necessarily obviously using dynamic lookup, 
>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>> still think it’s a legitimate concern.
> 
> Sure, it is a legit concern, but it is also nothing new.  This is the 
> standard concern with type inference.

The concern for me is orthogonal to type inference.  The name of a type 
supporting dynamic lookup will not necessarily provide any indication that the 
type supports dynamic lookup.

> 
> While there are weird cases, in practice, values do not get magicked out of 
> no-where.  They most commonly are either root values like:
> 
>   let np = Python.import(“foo”)
>   let pyInt = PyVal(42)
> 
> or they come for parameters:
> 
>   func f(x : PyVal) {
> 
> The place that is potentially surprising is when the type gets buried because 
> you’re working with some API that returns a [String, PyVal] dictionary or 
> something:
> 
> 
>   let x = foo()[“someKey”]
> 
> and you don’t realize that PyVal’s are involved.  However, if you are 
> actively writing the code, you have access to code completion and other 
> things that tell you these types, and if it is important for the clarity of 
> the code, you write this instead:
> 
>   let x :PyVal = foo()[“someKey”]
> 
> There is nothing specific to this proposal about this issue.

See above.  In the case of PyVal specifically the concern is somewhat mitigated 
by the name of the type.  That won’t necessarily always be the case.

> 
> 
>> I’m uncertain what the right answer is.  I’m still not really comfortable 
>> with opening up dynamic lookup to any user-defined type without some way to 
>> indicate to readers that dynamic lookup is happening in a piece of code.  
>> Maybe there is a less localized annotation that would indicate dynamic 
>> lookup is in effect for a larger chunk of code.  
> 
> You seem to be extremely concerned that people will adopt DynamicMemberLookup 
> for types where it doesn’t make sense and abuse the feature.  I am having a 
> real problem understanding what your concern is, so I’d really love for you 
> to explain some theoretical examples of the bad thing that happens: why 
> someone (non-maliciously) adopts the protocol, what code gets written, and 
> what harm actually comes from it.
> 
> Let me use a made up tale from a parallel universe to illustrate why I don’t 
> understand your concern.  Imagine if Swift didn’t already interoperate with 
> C, and did not already have IUOs.  Someone who cared about C language 
> interoperability would quickly realize that the ergonomics of importing 
> everything as strong optionals is a non-starter, jeopardizing the usability 
> of C interop, and would propose IUOs as a feature.
> 
> We’d then have a long and drawn out conversation about the various options on 
> how to model this, the pros and cons of each, and would settle on IUO as the 
> least bad design (as an aside, in our universe, when we went through the 
> design process that led to IUOs, this is exactly what happened, we even 
> considered syntaxing them as interobangs :-).
> 
> At that point, there would be a general uproar because IUOs have high 
> potential for abuse: Swift is “all about” strong types and safety, which IUOs 
> undermine.  Strong optionals are considered a pain to use by some people and 
> widely misunderstood (I think they are the biggest challenge in learning 
> Swift in practice), and so it is a reasonable feature that people could 
> pervasively adopt IUOs, leading to a much worse world all around.
> 
> 
> This made up parallel universe is exactly analogous to what is happening now. 
>  DynamicMemberLookup is no more dangerous and harmful than IUOs are.  They 
> will be one more tool in the toolbox.  While it is possible that someone will 
> abuse it, this will not be widespread.  People who are particularly worried 
> will build a single new rule into their linters (which already flag uses of 
> x!), and the world will keep revolving.

There is an important difference between IUOs and dynamic lookup in my mind.  
In the case of 

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

2017-12-03 Thread Joe DeCapo via swift-evolution

> On Dec 3, 2017, at 12:54 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> The difference is that IUOs are marked by a "!“ whereas dynamic member 
> lookups look just like normal member lookups but unlike them can fail.

We don't even need to bring up IUOs for it to be possible to write code that 
can fail without visibility at the call site. A contrived example:

func convertToInt(_ val: String) -> Int {
return Int(val)!
}

let val = "something"
// ... a bunch of code
let i = convertToInt(val) // Fatal error: Unexpectedly found nil while 
unwrapping an Optional value

This is trivially easy to do, and has been since Swift 1, but it's not 
something that has become a widespread issue.

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


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

2017-12-03 Thread Chris Lattner via swift-evolution
On Dec 3, 2017, at 11:03 AM, Magnus Ahltorp  wrote:
> 
>> 4 Dec. 2017 02:40 Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> That’s a good principle.  However, a dynamic member lookup is just a member 
>> lookup.  By that principle, it should look like a member lookup :-)
>> 
>> Further, I incorporated some of the conversation with Matthew into the 
>> proposal, showing how adding even a single sigil to dynamic member lookup to 
>> distinguish it is problematic:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
>> 
>> Further, adding something like .dynamic would completely undermind the 
>> proposal.  You can already write:
>> 
>>  x.get(“foo”).get(“bar”)
>> 
>> having to write:
>> 
>>  x.dynamic.foo.dynamic.bar
>> 
>> has no point.
> 
> This example shows what many on this list don't believe: that any Swift 
> method or member access can fail. If the return value of this "get" method is 
> an IUO, or not an Optional at all, and doesn't throw, then the expression 
> would have to fail hard if "foo" didn't resolve to something meaningful.
> 
> The most common argument against this proposal is that someone could make an 
> API using Dynamic Member Lookup that could fail even though it is not 
> apparent to the caller. But, as we see in the example, this is just as 
> possible today.

Correct.  The argument also fails to recognize that (when bridging to a dynamic 
language):

x+y

Is a completely dynamic method call which can fail (or return IUO), as is:

x[i]

And that this is true with no changes to Swift.  The claim that such a thing is 
counter to the design of Swift is completely perplexing to me.

-Chris

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


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

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

> On Dec 3, 2017, at 10:54 AM, Thorsten Seitz  wrote:
> 
>> 
>> At that point, there would be a general uproar because IUOs have high 
>> potential for abuse: Swift is “all about” strong types and safety, which 
>> IUOs undermine.  Strong optionals are considered a pain to use by some 
>> people and widely misunderstood (I think they are the biggest challenge in 
>> learning Swift in practice), and so it is a reasonable feature that people 
>> could pervasively adopt IUOs, leading to a much worse world all around.
>> 
>> 
>> This made up parallel universe is exactly analogous to what is happening 
>> now.  DynamicMemberLookup is no more dangerous and harmful than IUOs are.  
> 
> The difference is that IUOs are marked by a "!“ whereas dynamic member 
> lookups look just like normal member lookups but unlike them can fail.

Matthew was primarily concerned about point of use, in which IUO dereferencing 
is completely implicit and invisible.

-Chris

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


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

2017-12-03 Thread Magnus Ahltorp via swift-evolution
> 4 Dec. 2017 03:54 Thorsten Seitz via swift-evolution 
>  wrote:
> 
> The difference is that IUOs are marked by a "!“ whereas dynamic member 
> lookups look just like normal member lookups but unlike them can fail.

IUOs are not marked with an "!" by the caller, that's what makes them implicit. 
They *are* marked at the declaration, but so would dynamic member lookups be.

/Magnus

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


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

2017-12-03 Thread Magnus Ahltorp via swift-evolution
> 4 Dec. 2017 02:40 Chris Lattner via swift-evolution 
>  wrote:
> 
> That’s a good principle.  However, a dynamic member lookup is just a member 
> lookup.  By that principle, it should look like a member lookup :-)
> 
> Further, I incorporated some of the conversation with Matthew into the 
> proposal, showing how adding even a single sigil to dynamic member lookup to 
> distinguish it is problematic:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
> 
> Further, adding something like .dynamic would completely undermind the 
> proposal.  You can already write:
> 
>   x.get(“foo”).get(“bar”)
> 
> having to write:
> 
>   x.dynamic.foo.dynamic.bar
> 
> has no point.

This example shows what many on this list don't believe: that any Swift method 
or member access can fail. If the return value of this "get" method is an IUO, 
or not an Optional at all, and doesn't throw, then the expression would have to 
fail hard if "foo" didn't resolve to something meaningful.

The most common argument against this proposal is that someone could make an 
API using Dynamic Member Lookup that could fail even though it is not apparent 
to the caller. But, as we see in the example, this is just as possible today.

Another example where potential failure is not apparent to the caller:

struct Foo { 
var bar: Int
} 

struct Example { 
var n: Int 
var foo: Foo { return Foo(bar: n + 1) } 
} 

let a = Example(n: Int.max) 
a.foo.bar

Swift doesn't save the caller in this case, so together with Chris' example, I 
don't really understand the "not apparent to the caller" argument. Crashability 
is totally in the hands of the implementor of a method or member access, now 
and with the proposal.

/Magnus

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


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

2017-12-03 Thread Thorsten Seitz via swift-evolution

> Am 03.12.2017 um 18:36 schrieb Chris Lattner via swift-evolution 
> :
> 
> On Dec 2, 2017, at 7:11 PM, Matthew Johnson  > wrote:
>>> 
>>> This does not improve clarity of code, it merely serves to obfuscate logic. 
>>>  It is immediately apparent from the APIs being used, the API style, and 
>>> the static types (in Xcode or through static declarations) that this is all 
>>> Python stuff.  
>> 
>> It may be immediately apparent when the types involved are obviously 
>> dynamic, such as in this example where Python.import is explicitly used.  
>> However, my concern is less about the intended use case of dynamic language 
>> interop than I am that this feature will be generally available to all types 
>> in Swift.  
>> 
>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>> types and contexts that are not necessarily obviously using dynamic lookup, 
>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>> still think it’s a legitimate concern.
> 
> Sure, it is a legit concern, but it is also nothing new.  This is the 
> standard concern with type inference.
> 
> While there are weird cases, in practice, values do not get magicked out of 
> no-where.  They most commonly are either root values like:
> 
>   let np = Python.import(“foo”)
>   let pyInt = PyVal(42)
> 
> or they come for parameters:
> 
>   func f(x : PyVal) {
> 
> The place that is potentially surprising is when the type gets buried because 
> you’re working with some API that returns a [String, PyVal] dictionary or 
> something:
> 
> 
>   let x = foo()[“someKey”]
> 
> and you don’t realize that PyVal’s are involved.  However, if you are 
> actively writing the code, you have access to code completion and other 
> things that tell you these types, and if it is important for the clarity of 
> the code, you write this instead:
> 
>   let x :PyVal = foo()[“someKey”]
> 
> There is nothing specific to this proposal about this issue.
> 
> 
>> I’m uncertain what the right answer is.  I’m still not really comfortable 
>> with opening up dynamic lookup to any user-defined type without some way to 
>> indicate to readers that dynamic lookup is happening in a piece of code.  
>> Maybe there is a less localized annotation that would indicate dynamic 
>> lookup is in effect for a larger chunk of code.  
> 
> You seem to be extremely concerned that people will adopt DynamicMemberLookup 
> for types where it doesn’t make sense and abuse the feature.  I am having a 
> real problem understanding what your concern is, so I’d really love for you 
> to explain some theoretical examples of the bad thing that happens: why 
> someone (non-maliciously) adopts the protocol, what code gets written, and 
> what harm actually comes from it.
> 
> Let me use a made up tale from a parallel universe to illustrate why I don’t 
> understand your concern.  Imagine if Swift didn’t already interoperate with 
> C, and did not already have IUOs.  Someone who cared about C language 
> interoperability would quickly realize that the ergonomics of importing 
> everything as strong optionals is a non-starter, jeopardizing the usability 
> of C interop, and would propose IUOs as a feature.
> 
> We’d then have a long and drawn out conversation about the various options on 
> how to model this, the pros and cons of each, and would settle on IUO as the 
> least bad design (as an aside, in our universe, when we went through the 
> design process that led to IUOs, this is exactly what happened, we even 
> considered syntaxing them as interobangs :-).
> 
> At that point, there would be a general uproar because IUOs have high 
> potential for abuse: Swift is “all about” strong types and safety, which IUOs 
> undermine.  Strong optionals are considered a pain to use by some people and 
> widely misunderstood (I think they are the biggest challenge in learning 
> Swift in practice), and so it is a reasonable feature that people could 
> pervasively adopt IUOs, leading to a much worse world all around.
> 
> 
> This made up parallel universe is exactly analogous to what is happening now. 
>  DynamicMemberLookup is no more dangerous and harmful than IUOs are.  

The difference is that IUOs are marked by a "!“ whereas dynamic member lookups 
look just like normal member lookups but unlike them can fail.
With the exception of corner cases like indexed lookups or arithmetic overflow 
Swift marks places where something can fail with "!“ or "Unsafe“ prefixes or 
"try“ or "?“. The latter examples are even protected from runtime failure 
(crashes) because the type system enforces handling the failing case. 
Nonetheless we put the "try“ and "?“ to mark those places (and with good 
reason). 
One might even say that indexed lookups are marked by special syntax ("[…]“).

Now DynamicMemberLookup would introduce a new possibility where something can 
fail 

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

2017-12-03 Thread Paul Cantrell via swift-evolution


> On Dec 3, 2017, at 11:36 AM, Chris Lattner via swift-evolution 
>  wrote:
> 
> On Dec 2, 2017, at 7:11 PM, Matthew Johnson  > wrote:
>>> 
>>> This does not improve clarity of code, it merely serves to obfuscate logic. 
>>>  It is immediately apparent from the APIs being used, the API style, and 
>>> the static types (in Xcode or through static declarations) that this is all 
>>> Python stuff.  
>> 
>> It may be immediately apparent when the types involved are obviously 
>> dynamic, such as in this example where Python.import is explicitly used.  
>> However, my concern is less about the intended use case of dynamic language 
>> interop than I am that this feature will be generally available to all types 
>> in Swift.  
>> 
>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>> types and contexts that are not necessarily obviously using dynamic lookup, 
>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>> still think it’s a legitimate concern.
> 
> Sure, it is a legit concern, but it is also nothing new.  This is the 
> standard concern with type inference.
> 
> While there are weird cases, in practice, values do not get magicked out of 
> no-where.  They most commonly are either root values like:
> 
>   let np = Python.import(“foo”)
>   let pyInt = PyVal(42)
> 
> or they come for parameters:
> 
>   func f(x : PyVal) {
> 
> The place that is potentially surprising is when the type gets buried because 
> you’re working with some API that returns a [String, PyVal] dictionary or 
> something:
> 
> 
>   let x = foo()[“someKey”]
> 
> and you don’t realize that PyVal’s are involved.  However, if you are 
> actively writing the code, you have access to code completion and other 
> things that tell you these types, and if it is important for the clarity of 
> the code, you write this instead:
> 
>   let x :PyVal = foo()[“someKey”]
> 
> There is nothing specific to this proposal about this issue.

Going with this line of thought: a lot of these concerns could be a job for 
static analysis. Autocomplete, linters, refactoring tools, etc. can all help us 
reason wisely about dynamism where it appears.

One important factor in the success of Swift’s type inference is that modern 
dev tools are up to the task of working with it. Xcode (and AppCode for that 
matter) have, shall we say, a long way to go to realize their potential — but 
even with their warts, the fact is that a developer today can reasonably expect 
real-time feedback about code structure that is not explicitly surfaced in the 
syntax itself.

It’s worth asking why Java didn’t add Swift-like type inference 20 years ago. 
Java is a language whose type system at the time (no function types, no 
generics even!) would if anything have made inference much easier to implement, 
and for developers to reason about. I don’t think this was just down to 
Gosling’s taste, though; language designers can assume some ready availability 
of static analysis at edit time in a way they couldn’t back in the 90s.

• • •

What do I mean by this in practice? Well:

I agree with Chris that this syntax is…yucky:

let y = np^.arange^(24)^.reshape^(2, 3, 4)

…but an editor could use syntax coloring to differentiate dynamic dispatches:

let y = np.arange(24).reshape(2, 3, 4)

Teams worried about their abuse or inadvertent use could make them bold and 
red. This would achieve the same purpose as the separate syntax, sans yuckiness.

Refactoring tools could flag •potential• name matches in dynamic dispatches 
much the same they currently do for comments.

For those teams concerned about abuse of the feature, a lint tool could enable 
individual project to either prohibit dynamic calls or limit them to certain 
files or comment-fenced code sections.

Most of the concerns I’ve heard expressed in this thread could be addressed by 
sensible developers and good tools. The latter are feasible; the former no 
language can enforce.

> 
> 
>> I’m uncertain what the right answer is.  I’m still not really comfortable 
>> with opening up dynamic lookup to any user-defined type without some way to 
>> indicate to readers that dynamic lookup is happening in a piece of code.  
>> Maybe there is a less localized annotation that would indicate dynamic 
>> lookup is in effect for a larger chunk of code.  
> 
> You seem to be extremely concerned that people will adopt DynamicMemberLookup 
> for types where it doesn’t make sense and abuse the feature.  I am having a 
> real problem understanding what your concern is, so I’d really love for you 
> to explain some theoretical examples of the bad thing that happens: why 
> someone (non-maliciously) adopts the protocol, what code gets written, and 
> what harm actually comes from it.
> 
> Let me use a made up tale from a parallel universe to illustrate why I don’t 
> understand your 

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

2017-12-03 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Dec 3, 2017, at 10:40 AM, David Hart  wrote:
> 
> 
> 
>> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>> On Dec 2, 2017, at 7:40 PM, Chris Lattner  wrote:
>>> 
>>> On Dec 2, 2017, at 2:13 PM, Matthew Johnson  wrote:
> For all those reasons, we really do need something like AnyObject 
> dispatch if we care about working with dynamically typed languages.  The 
> design I’m suggesting carefully cordons this off into its own struct 
> type, so it doesn’t infect the rest of the type system, and is 
> non-invasive in the compiler.
 
 I am quite familiar with dynamic languages and agree that this is 
 necessary if we are going to fully open up access to these languages from 
 Swift.
>>> 
>>> Ok, then it appears you agree that something like anyobject dispatch is 
>>> necessary for effective dynamic language interop.
>>> 
>> I strongly urge you to reconsider the decision of that dynamic members 
>> must be made available with no indication at usage sites.  An indication 
>> of dynamic lookup at usage sites aligns very well (IMO) with the rest of 
>> Swift (AnyObject lookup aside) by calling attention to code that 
>> requires extra care to get right.
> 
> I don’t understand this.  The proposal is fully type safe, and this 
> approach is completely precedented by AnyObject.  Swift’s type system 
> supports many ways to express fallibility, and keeping those decisions 
> orthogonal to this proposal is the right thing to do, because it allows 
> the author of the type to decide what model makes sense for them.
 
 Allowing the author of the type to choose whether the mechanism is hidden 
 or visible is exactly what I don’t want to allow.  I think you have the 
 right design regarding types and semantics - the author chooses.  But I 
 don’t want these calls to look like ordinary member lookup when I’m 
 reading code.  
 
 They inherently have a much greater chance of failure than ordinary member 
 lookup.  Further, authors are likely to choose immediate traps or nil IUO 
 as failure modes as forcing users to deal with Optional on every call is 
 likely to be untenable.  I believe this behavior should be represented by 
 some kind of syntax at the usage site.  I don’t believe it is an undue 
 burden.  It would make the dynamic lookup semantic clear to all readers 
 and would help to discourage abuse.
>>> 
>>> I believe that adding explicit syntax would be counterproductive to your 
>>> goals, and would not make dynamic lookup syntax more clear.  I assume that 
>>> you would also want the same thing for DynamicCallable too, and operator 
>>> overloads, subscripts, and every other operation you perform on these 
>>> values, since they all have the exact same behavior.
>>> 
>>> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
>>> that change would turn this (which uses runtime failing or IUO return 
>>> values like AnyObject):
>>> 
>>> let np = Python.import("numpy")
>>> let x = np.array([6, 7, 8])
>>> let y =  np.arange(24).reshape(2, 3, 4)
>>> 
>>> let a = np.ones(3, dtype: np.int32)
>>> let b = np.linspace(0, pi, 3)
>>> let c = a+b
>>> let d = np.exp(c)
>>> print(d)
>>> 
>>> into:
>>> 
>>> let np = Python.import("numpy")
>>> let b = np^.array^([6, 7, 8])
>>> let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>>> 
>>> let a = np^.ones^(3, dtype: np^.int32)
>>> let b = np^.linspace^(0, pi, 3)
>>> let c = a+^b
>>> let d = np^.exp^(c)
>>> 
>>> This does not improve clarity of code, it merely serves to obfuscate logic. 
>>>  It is immediately apparent from the APIs being used, the API style, and 
>>> the static types (in Xcode or through static declarations) that this is all 
>>> Python stuff.  
>> 
>> It may be immediately apparent when the types involved are obviously 
>> dynamic, such as in this example where Python.import is explicitly used.  
>> However, my concern is less about the intended use case of dynamic language 
>> interop than I am that this feature will be generally available to all types 
>> in Swift.  
>> 
>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>> types and contexts that are not necessarily obviously using dynamic lookup, 
>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>> still think it’s a legitimate concern.
> 
> If dynamism if restricted to subclasses of a DynamicObject type, like Xiaodi 
> suggested earlier, then we can protect ourselves from this dynamic dispatch 
> being generally available to all types in Swift.

Chris has good reasons for not wanting to use a class.  More generally, designs 
that require subclassing a specific 

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

2017-12-03 Thread Chris Lattner via swift-evolution
On Dec 3, 2017, at 5:45 AM, Jonathan Hull  wrote:
> Hi Chris,
> 
> I am definitely in favor of providing dynamic features in Swift, and of being 
> able to interoperate easily with dynamic languages. I really like the idea 
> overall.

Great!

> 
> I was about to write up a different idea I had for partially mitigating some 
> of the issues around being able to mistype method names, etc…, but then I 
> remembered a usability principle that I first heard from members of the Lisa 
> team (discovered the hard way): Things which behave the same should look the 
> same, and things which behave differently need to look different.

That’s a good principle.  However, a dynamic member lookup is just a member 
lookup.  By that principle, it should look like a member lookup :-)

Further, I incorporated some of the conversation with Matthew into the 
proposal, showing how adding even a single sigil to dynamic member lookup to 
distinguish it is problematic:
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
 


Further, adding something like .dynamic would completely undermind the 
proposal.  You can already write:

x.get(“foo”).get(“bar”)

having to write:

x.dynamic.foo.dynamic.bar

has no point.

> What this means is that it is easy to wrap commonly used calls in a normal 
> swift method:
> 
>   func addTrick(_ name:String) {
>   self.dynamic.add_trick(name)
>   }

This would require wrapping all calls for them to be usable.

-Chris

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


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

2017-12-03 Thread Chris Lattner via swift-evolution
On Dec 2, 2017, at 7:11 PM, Matthew Johnson  wrote:
>> 
>> This does not improve clarity of code, it merely serves to obfuscate logic.  
>> It is immediately apparent from the APIs being used, the API style, and the 
>> static types (in Xcode or through static declarations) that this is all 
>> Python stuff.  
> 
> It may be immediately apparent when the types involved are obviously dynamic, 
> such as in this example where Python.import is explicitly used.  However, my 
> concern is less about the intended use case of dynamic language interop than 
> I am that this feature will be generally available to all types in Swift.  
> 
> This is big change from AnyObject dispatch.  It opens up the dynamism to 
> types and contexts that are not necessarily obviously using dynamic lookup, 
> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
> still think it’s a legitimate concern.

Sure, it is a legit concern, but it is also nothing new.  This is the standard 
concern with type inference.

While there are weird cases, in practice, values do not get magicked out of 
no-where.  They most commonly are either root values like:

let np = Python.import(“foo”)
let pyInt = PyVal(42)

or they come for parameters:

func f(x : PyVal) {

The place that is potentially surprising is when the type gets buried because 
you’re working with some API that returns a [String, PyVal] dictionary or 
something:


let x = foo()[“someKey”]

and you don’t realize that PyVal’s are involved.  However, if you are actively 
writing the code, you have access to code completion and other things that tell 
you these types, and if it is important for the clarity of the code, you write 
this instead:

let x :PyVal = foo()[“someKey”]

There is nothing specific to this proposal about this issue.


> I’m uncertain what the right answer is.  I’m still not really comfortable 
> with opening up dynamic lookup to any user-defined type without some way to 
> indicate to readers that dynamic lookup is happening in a piece of code.  
> Maybe there is a less localized annotation that would indicate dynamic lookup 
> is in effect for a larger chunk of code.  

You seem to be extremely concerned that people will adopt DynamicMemberLookup 
for types where it doesn’t make sense and abuse the feature.  I am having a 
real problem understanding what your concern is, so I’d really love for you to 
explain some theoretical examples of the bad thing that happens: why someone 
(non-maliciously) adopts the protocol, what code gets written, and what harm 
actually comes from it.

Let me use a made up tale from a parallel universe to illustrate why I don’t 
understand your concern.  Imagine if Swift didn’t already interoperate with C, 
and did not already have IUOs.  Someone who cared about C language 
interoperability would quickly realize that the ergonomics of importing 
everything as strong optionals is a non-starter, jeopardizing the usability of 
C interop, and would propose IUOs as a feature.

We’d then have a long and drawn out conversation about the various options on 
how to model this, the pros and cons of each, and would settle on IUO as the 
least bad design (as an aside, in our universe, when we went through the design 
process that led to IUOs, this is exactly what happened, we even considered 
syntaxing them as interobangs :-).

At that point, there would be a general uproar because IUOs have high potential 
for abuse: Swift is “all about” strong types and safety, which IUOs undermine.  
Strong optionals are considered a pain to use by some people and widely 
misunderstood (I think they are the biggest challenge in learning Swift in 
practice), and so it is a reasonable feature that people could pervasively 
adopt IUOs, leading to a much worse world all around.


This made up parallel universe is exactly analogous to what is happening now.  
DynamicMemberLookup is no more dangerous and harmful than IUOs are.  They will 
be one more tool in the toolbox.  While it is possible that someone will abuse 
it, this will not be widespread.  People who are particularly worried will 
build a single new rule into their linters (which already flag uses of x!), and 
the world will keep revolving.


>> Even the behavior of AnyObject was carefully designed and considered, and 
>> were really really good reasons for it returning IUO.
> 
> I am not trying to call into question the choices made in the past.  Swift 
> wouldn’t be the great language with a bright future that it is today without 
> an incredibly successful migration of a large user base from Objective-C to 
> Swift.  This is a huge accomplishment and couldn’t have happened without 
> making really good decisions about some really hard tradeoffs.

You miss my point.  My point is that AnyObject lookup was carefully considered, 
has stood the test of time, and is the *right* answer.  Swift 1 would not have 
been nearly as 

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

2017-12-03 Thread Joe DeCapo via swift-evolution
I like Chris's addition to the proposal about only allowing conformance on the 
original type definition, rather than requiring a class type.

https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 


> In the discussion cycle, there was significant concern about abuse of this 
> feature, particularly if someone retroactively conforms a type to 
> DynamicMemberLookupProtocol. For this reason, the compiler only permits 
> conformance of this protocol on the original type definition, not extensions. 
> While the potential for abuse has never been a strong guiding principle for 
> Swift features (and many features can be abused, e.g. operator overloading, 
> emoji identifiers, AnyObject lookup, ImplicitlyUnwrappedOptional, and many 
> more) there is a strong argument that dynamic behavior is a core property of 
> a type that should be part of its declaration. If for some reason there 
> becomes a reason to relax this requirement, we can evaluate that as a 
> separate proposal based on its own merits. See the "Alternatives Considered" 
> section below for further ways to reduce potential for abuse.

It would be a shame if structs were excluded from these capabilities.

> On Dec 3, 2017, at 11:18 AM, Jose Cheyo Jimenez via swift-evolution 
>  wrote:
> 
> 
> 
> On Dec 3, 2017, at 8:41 AM, David Hart via swift-evolution 
> > wrote:
> 
>> 
>> 
>>> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Dec 2, 2017, at 7:40 PM, Chris Lattner >> > wrote:
>>> 
 On Dec 2, 2017, at 2:13 PM, Matthew Johnson > wrote:
>> For all those reasons, we really do need something like AnyObject 
>> dispatch if we care about working with dynamically typed languages.  The 
>> design I’m suggesting carefully cordons this off into its own struct 
>> type, so it doesn’t infect the rest of the type system, and is 
>> non-invasive in the compiler.
> 
> I am quite familiar with dynamic languages and agree that this is 
> necessary if we are going to fully open up access to these languages from 
> Swift.
 
 Ok, then it appears you agree that something like anyobject dispatch is 
 necessary for effective dynamic language interop.
 
>>> I strongly urge you to reconsider the decision of that dynamic members 
>>> must be made available with no indication at usage sites.  An 
>>> indication of dynamic lookup at usage sites aligns very well (IMO) with 
>>> the rest of Swift (AnyObject lookup aside) by calling attention to code 
>>> that requires extra care to get right.
>> 
>> I don’t understand this.  The proposal is fully type safe, and this 
>> approach is completely precedented by AnyObject.  Swift’s type system 
>> supports many ways to express fallibility, and keeping those decisions 
>> orthogonal to this proposal is the right thing to do, because it allows 
>> the author of the type to decide what model makes sense for them.
> 
> Allowing the author of the type to choose whether the mechanism is hidden 
> or visible is exactly what I don’t want to allow.  I think you have the 
> right design regarding types and semantics - the author chooses.  But I 
> don’t want these calls to look like ordinary member lookup when I’m 
> reading code.  
> 
> They inherently have a much greater chance of failure than ordinary 
> member lookup.  Further, authors are likely to choose immediate traps or 
> nil IUO as failure modes as forcing users to deal with Optional on every 
> call is likely to be untenable.  I believe this behavior should be 
> represented by some kind of syntax at the usage site.  I don’t believe it 
> is an undue burden.  It would make the dynamic lookup semantic clear to 
> all readers and would help to discourage abuse.
 
 I believe that adding explicit syntax would be counterproductive to your 
 goals, and would not make dynamic lookup syntax more clear.  I assume that 
 you would also want the same thing for DynamicCallable too, and operator 
 overloads, subscripts, and every other operation you perform on these 
 values, since they all have the exact same behavior.
 
 If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
 that change would turn this (which uses runtime failing or IUO return 
 values like AnyObject):
 
let np = Python.import("numpy")
let x = np.array([6, 7, 8])
let y =  np.arange(24).reshape(2, 3, 4)

let a = np.ones(3, dtype: np.int32)
let b = 

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

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


> On Dec 3, 2017, at 8:41 AM, David Hart via swift-evolution 
>  wrote:
> 
> 
> 
>> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>> On Dec 2, 2017, at 7:40 PM, Chris Lattner  wrote:
>>> 
>>> On Dec 2, 2017, at 2:13 PM, Matthew Johnson  wrote:
> For all those reasons, we really do need something like AnyObject 
> dispatch if we care about working with dynamically typed languages.  The 
> design I’m suggesting carefully cordons this off into its own struct 
> type, so it doesn’t infect the rest of the type system, and is 
> non-invasive in the compiler.
 
 I am quite familiar with dynamic languages and agree that this is 
 necessary if we are going to fully open up access to these languages from 
 Swift.
>>> 
>>> Ok, then it appears you agree that something like anyobject dispatch is 
>>> necessary for effective dynamic language interop.
>>> 
>> I strongly urge you to reconsider the decision of that dynamic members 
>> must be made available with no indication at usage sites.  An indication 
>> of dynamic lookup at usage sites aligns very well (IMO) with the rest of 
>> Swift (AnyObject lookup aside) by calling attention to code that 
>> requires extra care to get right.
> 
> I don’t understand this.  The proposal is fully type safe, and this 
> approach is completely precedented by AnyObject.  Swift’s type system 
> supports many ways to express fallibility, and keeping those decisions 
> orthogonal to this proposal is the right thing to do, because it allows 
> the author of the type to decide what model makes sense for them.
 
 Allowing the author of the type to choose whether the mechanism is hidden 
 or visible is exactly what I don’t want to allow.  I think you have the 
 right design regarding types and semantics - the author chooses.  But I 
 don’t want these calls to look like ordinary member lookup when I’m 
 reading code.  
 
 They inherently have a much greater chance of failure than ordinary member 
 lookup.  Further, authors are likely to choose immediate traps or nil IUO 
 as failure modes as forcing users to deal with Optional on every call is 
 likely to be untenable.  I believe this behavior should be represented by 
 some kind of syntax at the usage site.  I don’t believe it is an undue 
 burden.  It would make the dynamic lookup semantic clear to all readers 
 and would help to discourage abuse.
>>> 
>>> I believe that adding explicit syntax would be counterproductive to your 
>>> goals, and would not make dynamic lookup syntax more clear.  I assume that 
>>> you would also want the same thing for DynamicCallable too, and operator 
>>> overloads, subscripts, and every other operation you perform on these 
>>> values, since they all have the exact same behavior.
>>> 
>>> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
>>> that change would turn this (which uses runtime failing or IUO return 
>>> values like AnyObject):
>>> 
>>> let np = Python.import("numpy")
>>> let x = np.array([6, 7, 8])
>>> let y =  np.arange(24).reshape(2, 3, 4)
>>> 
>>> let a = np.ones(3, dtype: np.int32)
>>> let b = np.linspace(0, pi, 3)
>>> let c = a+b
>>> let d = np.exp(c)
>>> print(d)
>>> 
>>> into:
>>> 
>>> let np = Python.import("numpy")
>>> let b = np^.array^([6, 7, 8])
>>> let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>>> 
>>> let a = np^.ones^(3, dtype: np^.int32)
>>> let b = np^.linspace^(0, pi, 3)
>>> let c = a+^b
>>> let d = np^.exp^(c)
>>> 
>>> This does not improve clarity of code, it merely serves to obfuscate logic. 
>>>  It is immediately apparent from the APIs being used, the API style, and 
>>> the static types (in Xcode or through static declarations) that this is all 
>>> Python stuff.  
>> 
>> It may be immediately apparent when the types involved are obviously 
>> dynamic, such as in this example where Python.import is explicitly used.  
>> However, my concern is less about the intended use case of dynamic language 
>> interop than I am that this feature will be generally available to all types 
>> in Swift.  
>> 
>> This is big change from AnyObject dispatch.  It opens up the dynamism to 
>> types and contexts that are not necessarily obviously using dynamic lookup, 
>> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
>> still think it’s a legitimate concern.
> 
> If dynamism if restricted to subclasses of a DynamicObject type, like Xiaodi 
> suggested earlier, then we can protect ourselves from this dynamic dispatch 
> being generally available to all types in Swift.

I like the idea of a class type as the marker. 

If we did expose the protocols that DynamicObject conform to, 

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

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


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

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

-Chris


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


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

2017-12-03 Thread Joe DeCapo via swift-evolution
One common criticism people keep bringing up is that people will misuse this 
and end up exposing dynamic api's into general use (and without notation at the 
call site that draws attention to this, the user may accidentally invoke 
something dynamic they didn't intend to). I feel like there is enough prior art 
in current Swift libraries to disabuse us of this notion. Basically every 
library I've seen goes out of its way to provide a safe api and leverage 
Swift's strong type system in their public api's. We don't see libraries using 
force unwraps willy nilly to hide the fact that a non-optional return type is 
actually coming from an optional value, but this is something that has been 
possible since day one and is trivially easy to do.

There are essentially 2 "bad" use cases for consumers of these dynamic 
features: 1) as the consumer of a library that exposes these dynamic features 
as public api; and 2) as the creator of a library/executable that uses them 
irresponsibly internally. For (1) it's a very easy decision to simply not use a 
Swift library that exposes dynamic features like this externally if you object 
to it, and instead use an alternative. I highly doubt this would become 
idiomatic in the Swift community, because the enthusiasm for Swift is mostly 
based on the strong typing it provides. For (2) it is within the creator's 
complete control to refactor the code to work the preferred way. The moment 
there's an unintended invocation of a dynamic call, it can simply be wrapped in 
a more strongly typed Swift wrapper.

As for the autocompletion and jump-to-definition capabilities of the state of 
the art in Python, I've been working on a Python project for a few years and 
until recently only used Atom, which provided code completion with a plug-in, 
but I could have gotten by without it. I recently started using PyCharm, and 
although it has jump-to-definition capabilities, the dynamic nature of the 
language means that there's almost always multiple different possible matches, 
and most often the top choices are the wrong ones. I don't see how Swift could 
improve on this situation, and for the case of providing quick help, it may 
actively provide the wrong information. This is not to say that autocompletion 
and the like aren't worthwhile goals, but I don't think they're really an 
important barrier to initial adoption of a way to call into dynamic languages.

I get the sense that this is a minor syntactic sugar feature that would 
probably mostly be used by implementers of library wrappers to provide Swifty 
api's that call into dynamic language api's. So the concerns about 
autocompletion and pervasive exposure of these dynamic aspects more generally 
really feel misplaced. When writing a wrapper around a REST api, I get zero 
autocompletion when specifying the JSON models, but that in no way hampers my 
ability to wrap these api's. Sure, there may be more runtime bugs that I have 
to sort out when initially implementing things, but that's inherent in the 
nature of dealing with a dynamic programming model. I imagine it will be the 
same for Swift libraries wrapping dynamic language libraries.


> On Dec 3, 2017, at 10:41 AM, David Hart via swift-evolution 
>  wrote:
> 
> 
> 
>> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Dec 2, 2017, at 7:40 PM, Chris Lattner > > wrote:
>> 
>>> On Dec 2, 2017, at 2:13 PM, Matthew Johnson >> > wrote:
> For all those reasons, we really do need something like AnyObject 
> dispatch if we care about working with dynamically typed languages.  The 
> design I’m suggesting carefully cordons this off into its own struct 
> type, so it doesn’t infect the rest of the type system, and is 
> non-invasive in the compiler.
 
 I am quite familiar with dynamic languages and agree that this is 
 necessary if we are going to fully open up access to these languages from 
 Swift.
>>> 
>>> Ok, then it appears you agree that something like anyobject dispatch is 
>>> necessary for effective dynamic language interop.
>>> 
>> I strongly urge you to reconsider the decision of that dynamic members 
>> must be made available with no indication at usage sites.  An indication 
>> of dynamic lookup at usage sites aligns very well (IMO) with the rest of 
>> Swift (AnyObject lookup aside) by calling attention to code that 
>> requires extra care to get right.
> 
> I don’t understand this.  The proposal is fully type safe, and this 
> approach is completely precedented by AnyObject.  Swift’s type system 
> supports many ways to express fallibility, and keeping those decisions 
> orthogonal to this proposal is the right thing to do, because it 

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

2017-12-03 Thread David Hart via swift-evolution


> On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Dec 2, 2017, at 7:40 PM, Chris Lattner  > wrote:
> 
>> On Dec 2, 2017, at 2:13 PM, Matthew Johnson > > wrote:
 For all those reasons, we really do need something like AnyObject dispatch 
 if we care about working with dynamically typed languages.  The design I’m 
 suggesting carefully cordons this off into its own struct type, so it 
 doesn’t infect the rest of the type system, and is non-invasive in the 
 compiler.
>>> 
>>> I am quite familiar with dynamic languages and agree that this is necessary 
>>> if we are going to fully open up access to these languages from Swift.
>> 
>> Ok, then it appears you agree that something like anyobject dispatch is 
>> necessary for effective dynamic language interop.
>> 
> I strongly urge you to reconsider the decision of that dynamic members 
> must be made available with no indication at usage sites.  An indication 
> of dynamic lookup at usage sites aligns very well (IMO) with the rest of 
> Swift (AnyObject lookup aside) by calling attention to code that requires 
> extra care to get right.
 
 I don’t understand this.  The proposal is fully type safe, and this 
 approach is completely precedented by AnyObject.  Swift’s type system 
 supports many ways to express fallibility, and keeping those decisions 
 orthogonal to this proposal is the right thing to do, because it allows 
 the author of the type to decide what model makes sense for them.
>>> 
>>> Allowing the author of the type to choose whether the mechanism is hidden 
>>> or visible is exactly what I don’t want to allow.  I think you have the 
>>> right design regarding types and semantics - the author chooses.  But I 
>>> don’t want these calls to look like ordinary member lookup when I’m reading 
>>> code.  
>>> 
>>> They inherently have a much greater chance of failure than ordinary member 
>>> lookup.  Further, authors are likely to choose immediate traps or nil IUO 
>>> as failure modes as forcing users to deal with Optional on every call is 
>>> likely to be untenable.  I believe this behavior should be represented by 
>>> some kind of syntax at the usage site.  I don’t believe it is an undue 
>>> burden.  It would make the dynamic lookup semantic clear to all readers and 
>>> would help to discourage abuse.
>> 
>> I believe that adding explicit syntax would be counterproductive to your 
>> goals, and would not make dynamic lookup syntax more clear.  I assume that 
>> you would also want the same thing for DynamicCallable too, and operator 
>> overloads, subscripts, and every other operation you perform on these 
>> values, since they all have the exact same behavior.
>> 
>> If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, 
>> that change would turn this (which uses runtime failing or IUO return values 
>> like AnyObject):
>> 
>>  let np = Python.import("numpy")
>>  let x = np.array([6, 7, 8])
>>  let y =  np.arange(24).reshape(2, 3, 4)
>>  
>>  let a = np.ones(3, dtype: np.int32)
>>  let b = np.linspace(0, pi, 3)
>>  let c = a+b
>>  let d = np.exp(c)
>>  print(d)
>> 
>> into:
>> 
>>  let np = Python.import("numpy")
>>  let b = np^.array^([6, 7, 8])
>>  let y =  np^.arange^(24)^.reshape^(2, 3, 4)
>>  
>>  let a = np^.ones^(3, dtype: np^.int32)
>>  let b = np^.linspace^(0, pi, 3)
>>  let c = a+^b
>>  let d = np^.exp^(c)
>> 
>> This does not improve clarity of code, it merely serves to obfuscate logic.  
>> It is immediately apparent from the APIs being used, the API style, and the 
>> static types (in Xcode or through static declarations) that this is all 
>> Python stuff.  
> 
> It may be immediately apparent when the types involved are obviously dynamic, 
> such as in this example where Python.import is explicitly used.  However, my 
> concern is less about the intended use case of dynamic language interop than 
> I am that this feature will be generally available to all types in Swift.  
> 
> This is big change from AnyObject dispatch.  It opens up the dynamism to 
> types and contexts that are not necessarily obviously using dynamic lookup, 
> callable, etc.  Maybe this won’t turn out to be a problem in practice but I 
> still think it’s a legitimate concern.

If dynamism if restricted to subclasses of a DynamicObject type, like Xiaodi 
suggested earlier, then we can protect ourselves from this dynamic dispatch 
being generally available to all types in Swift.

>> When you start mixing in use of native Swift types like dictionaries 
>> (something we want to encourage because they are typed!) you end up with an 
>> inconsistent mismash where people would just try adding syntax or applying 
>> fixits 

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

2017-12-03 Thread Michel Fortin via swift-evolution
> Le 2 déc. 2017 à 12:20, Chris Lattner via swift-evolution 
>  a écrit :
> 
>> *At worst*, you invoke the tool from the command line to build the Swift 
>> module that corresponds to a given Python module.
>> 
>>  py2swift 
>> 
>> We could absolutely introduce tooling hooks to make the compiler initiate 
>> that step.
> 
> This would have to be integrated into the swift compiler to provide a usable 
> experience IMO, because otherwise it won’t work with Playgrounds.

I'm not sure if that's what Doug was aiming at, but I read it to mean we could 
add a new import syntax like this one:

import py2swift("DogModule")

Instead of looking for a module in the _module search path_, the compiler would 
run a command-line tool called `py2swift` found in an _import tool search 
path_. The tool generates the module on the fly before returning the module 
path to the compiler, who can then continue with compiling.

In the case above, the `py2swift` script would receive "DogModule" as its 
argument, introspect the Python module, generate bindings, and output the path 
to the generated binding module for the Swift compiler to use. The generated 
code for the binding module could look like this:

import PyRuntimeGlue

final class Dog {
private let pyVal: PyVal
init(_ pyVal: PyVal) { self.pyVal = pyVal }
init(_ name: String) { pyVal = pyRuntimeNew(class: "Dog", name) 
}
func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, 
"add_trick", trick) }
}

and below the import line the usage would be the same as in your proposal:

import py2swift("DogModule") // auto-generate bindings module

let dog = Dog("Brianna")
dog.add_trick("Roll over")
let dog2 = Dog(Kaylee").add_trick("snore")

Except now `Dog` is a real type instead of a variable masquerading as a type, 
auto-completion will work the way you'd expect, and you'll get a compile-time 
error if there is no Python method with that name on that type.

There's still one problem though: Python functions returning a Dog will 
actually return you something of type PyVal. That'll force you to rewrap the 
value into the right type everywhere. Example:

let dog = Dog(owner.dog)
dog.add_trick("snore") // Dog.add_trick gets called

The binding generator could take the AnyObject approach and have the binding 
module insert extensions for all methods in addition to the type:

import PyRuntimeGlue

final class Dog {
private let pyVal: PyVal
init(_ pyVal: PyVal) { self.pyVal = pyVal }
init(_ name: String) { pyVal = pyRuntimeNew(class: "Dog", name) 
}
func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, 
"add_trick", trick) }
}
extension PyVal {
func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, 
"add_trick", trick) }
}

and now you can do:

let dog = owner.dog
dog.add_trick("snore") // PyVal.add_trick gets called

Does that makes sense?

-- 
Michel Fortin
https://michelf.ca

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


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

2017-12-03 Thread C. Keith Ray via swift-evolution
I *don't* want dynamic calls to stand out. I want seamless interoperability.

let arrayOfDogs = [ Python.Module(dog).Dog("Brianna"), 
Python.Module(dog).Dog("Kevin") ] // Swift array of Python objects
let b = arrayOfDogs.sorted() // use Swift 'sort' function on Python objects 
(invoking Python '<' and '==' operators)
let c = arrayOfDogs.forEach { $0.bark() } // Swift 'forEach' calling Python 
'bark'
etc.


--
C. Keith Ray

* https://leanpub.com/wepntk <- buy my book?
* http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf
* http://agilesolutionspace.blogspot.com/

> On Dec 3, 2017, at 6:57 AM, Tino Heth via swift-evolution 
>  wrote:
> 
> 
>> What do you think about having a special method ‘dynamic' defined in this 
>> protocol, such that the compiler magic lookup behavior is only available 
>> when chained after that method?
> I guess „dynamic“ isn’t a common property name, but imho such magic doesn’t 
> feel right, even when there are no collisions in real-world code.
> 
>>  let y =  np^.arange?^(24)?^.reshape^?(2, 3, 4)!
> 
> That looks quite ugly… but imho that’s at least partially because of the 
> choice of character
> let y = np:arange?:reshape?:(2, 3, 4)!
> doesn’t seem to be as bad as the use of carets.
> 
> But still, you would have to jump through some hoops to use both kinds of 
> dispatch side by side (because you always have to think about how to call a 
> method).
> On the other hand, we also have  and try, which makes some 
> things less convenient — and I’d say that dynamic dispatch is somehow 
> comparable to inout-parameters (both shouldn’t be used if you can get around 
> it).
> 
> So, why do people want differentiate?
> I can see two major motivations for a different syntax:
> 
> a) you want to dynamic calls to stand out — which also could be done by tools:
>> let y =  np.arange?(24)?.reshape?(2, 3, 4)! // let the editor use a 
>> different font/color for non-static stuff
> 
> 
> b) you want to be sure that in a given situation, no dynamic dispatch is used 
> — which could be solved by keeping the dot as general way to call something, 
> and add an alternative that will only use static lookup
> 
> No matter what direction is taken here, imho this whole story has a really 
> gigantic impact on the shape of Swift, and I have strong concerns if the two 
> changes are reviewed in a normal way and added this year… there’s no 
> experience with the proposed changes yet, and afaics, it has become quite 
> hard to correct additions that turn out to be not as positive as expected.
> 
> - Tino
> 
> ___
> 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] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Tino Heth via swift-evolution

> What do you think about having a special method ‘dynamic' defined in this 
> protocol, such that the compiler magic lookup behavior is only available when 
> chained after that method?
I guess „dynamic“ isn’t a common property name, but imho such magic doesn’t 
feel right, even when there are no collisions in real-world code.

>   let y =  np^.arange?^(24)?^.reshape^?(2, 3, 4)!

That looks quite ugly… but imho that’s at least partially because of the choice 
of character
let y = np:arange?:reshape?:(2, 3, 4)!
doesn’t seem to be as bad as the use of carets.

But still, you would have to jump through some hoops to use both kinds of 
dispatch side by side (because you always have to think about how to call a 
method).
On the other hand, we also have  and try, which makes some 
things less convenient — and I’d say that dynamic dispatch is somehow 
comparable to inout-parameters (both shouldn’t be used if you can get around 
it).

So, why do people want differentiate?
I can see two major motivations for a different syntax:

a) you want to dynamic calls to stand out — which also could be done by tools:
> let y =  np.arange?(24)?.reshape?(2, 3, 4)! // let the editor use a different 
> font/color for non-static stuff


b) you want to be sure that in a given situation, no dynamic dispatch is used — 
which could be solved by keeping the dot as general way to call something, and 
add an alternative that will only use static lookup

No matter what direction is taken here, imho this whole story has a really 
gigantic impact on the shape of Swift, and I have strong concerns if the two 
changes are reviewed in a normal way and added this year… there’s no experience 
with the proposed changes yet, and afaics, it has become quite hard to correct 
additions that turn out to be not as positive as expected.

- Tino

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


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

2017-12-03 Thread Jonathan Hull via swift-evolution
Hi Chris,

I am definitely in favor of providing dynamic features in Swift, and of being 
able to interoperate easily with dynamic languages. I really like the idea 
overall.

I was about to write up a different idea I had for partially mitigating some of 
the issues around being able to mistype method names, etc…, but then I 
remembered a usability principle that I first heard from members of the Lisa 
team (discovered the hard way): Things which behave the same should look the 
same, and things which behave differently need to look different.

I like that the change in behavior is really limited in scope by this proposal, 
but there still isn’t really any indication other than the type (which might be 
inferred) that the normal checking behavior is offline.  When in a fully 
dynamic environment, this isn’t really a big problem because you use different 
debugging strategies,  but I worry that the free mixture of static and dynamic 
without any indicators showing the difference will lead to much more frequent 
errors.

What do you think about having a special method ‘dynamic' defined in this 
protocol, such that the compiler magic lookup behavior is only available when 
chained after that method?  Thus:

dog.add_trick(“sit”)

would have to be:

dog.dynamic.add_trick(“sit”)


Now, I know that sounds like a pain in the butt, but it also buys you an extra 
ability (in addition to the extra cue that we have to watch out for dynamic 
issues).  Because the dynamic lookup only happens for calls chained after 
dynamic, we now have normal swift lookup for all of the other 
methods/properties defined on the type (with autocomplete support, etc…).

What this means is that it is easy to wrap commonly used calls in a normal 
swift method:

func addTrick(_ name:String) {
self.dynamic.add_trick(name)
}

Now the user can say the following with full autocomplete support, type 
checking, etc…

addTrick(“sit”)

…and if they misspell it, they will get an error from the compiler.  Error 
handling could also optionally be added to a wrapper.  Most importantly, 
conversion to/from swift return types and parameters can easily be built into 
the wrappers.

The end result is a system where python code can be up and running in Swift 
very quickly (by using chaining with .dynamic), and then made more native Swift 
friendly incrementally over time (by adding wrappers/extensions for 
common/important calls).  The only extra cost is having to type an extra word 
for dynamic calls without wrappers.

Thoughts?

Thanks,
Jon

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


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

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

> Beyond that, it is counterproductive to your goals, because it means that 
> people are far less likely to use to use optional returns.  Doing so (which 
> produces a safer result) would cause a double tax in syntax, and would be a 
> confusing jumble.  I can’t bring myself to do the whole example above, one 
> line - just converting member lookup syntax but not callable syntax - would 
> end up:
> 
>   let y =  np^.arange?^(24)^.reshape^?(2, 3, 4)
> 
> If you made DynamicCallable also return optional it would be:
> 
>   let y =  np^.arange?^(24)?^.reshape^?(2, 3, 4)!
> 
> or something.  This is such madness that no one would do that.

Optional is not the only swift error handling pattern. But I agree that making 
the dynamic fonction throw would also induce a readable cost due to the 
necessity to add try at each call site.


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


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

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


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

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

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

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


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