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

2017-11-30 Thread Gwendal Roué via swift-evolution

> Le 1 déc. 2017 à 08:38, Gwendal Roué  a écrit :
> 
> In this context, I too am concerned with retroactive conformance. If it were 
> forbidden, it would make it very clear where the dynamic scope starts and 
> ends:


In Chris's playground, it is very clear that you have to import PythonGlue in 
order to activate the retroactive conformance on Int, Double, etc.

This is very fine to me. Sorry for expressing a useless concern.

Gwendal

___
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-11-30 Thread Gwendal Roué via swift-evolution

> Le 1 déc. 2017 à 00:54, Xiaodi Wu via swift-evolution 
>  a écrit :
> 
> As I wrote in the earlier thread, I think this is the wrong way to reason 
> about the use case--and a counterproductive one that effectively rejects the 
> legitimacy of dynamic language interop support instead of working towards an 
> optimal solution for it. Along those lines, some replies to your message 
> literally question whether the user case is worthwhile to support at all, 
> which I think entirely misses the mark.
> 
> As Chris writes in his proposal, there are several areas (such as data 
> science) where, to put it plainly, Python or another dynamic language is 
> significantly better than Swift due to a much larger ecosystem of libraries, 
> tools, and user communities, with sometimes decades of lead time. It is 
> nonsensical to talk about how Swift is "supposed to be better" in any way 
> whatsoever in that context. As diehard Swift users, we may be confident that 
> the virtues of Swift's syntax, static typing, compiler smarts, protocol-based 
> design, or whatever else offer opportunities for, say, data science libraries 
> and tools to be better in the future, eventually. But to make this even 
> possible involves first making Swift a viable language in which to work with 
> current data science tools. Your top bullet point here reasons that one key 
> flaw of Chris's proposal is that he has not somehow figured out how to make 
> dynamic Python calls give compile-time Swift errors. If this is the minimum 
> bar for Python interop, then as far as I can tell, it seems isomorphic to 
> rejecting interop with dynamic languages altogether.

Hello, I agree with this reasoning.

Unless I miss the point, I see C. Lattner's proposals, function calls and 
member lookup,  as a very restricted interface to dynamic languages. They do 
not aim at embedding dynamic languages into Swift at all, and let users write 
long Python/Ruby/JS programs in Swift.

For example, "real" python would need list comprehension, generators, 
async/await, etc. Such features are clearly out of scope of the proposals.

We can thus expect serious programs that use those features to process in three 
steps: 1 turn Swift values in foreign values, 2. process foreign values with a 
restricted foreign API, 3. turn computed foreign values into Swift values. It's 
all about using good tools when needed.

In this context, I too am concerned with retroactive conformance. If it were 
forbidden, it would make it very clear where the dynamic scope starts and ends:

// Input
let swiftInt: Int = 12

// Enter Python
let pyInt = Python.Value(swiftInt)

// Python code
let pyResult = pyInt.someFunc()

// Back to Swift
if let swiftResult = Int(pyResult) {
// proceed
}

Gwendal Roué

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Martin Waitz via swift-evolution
Hello,

> The collection is a subject which has elements, and we are asking for one of 
> them at random.

it has elements, sure.
And because of its structure, it has a first and a last element and whatever.
But that random element is not an inherent property of the collection.

I find it much more natural to use the random number generator to draw random 
elements from collections than the other way round.
That approach also completely side-steps the problem with having to define 
default arguments. The user can just use any random number generator she has. 
Obviously, it makes sense to provide a default one named `random` to make it 
easily accessible.

>>> var list = [1,2,3,4]
>>> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
>>> one of the elements
>> 
>> Instead I would prefer to have something like:
>> 
>> let a = random.draw(from: list)
> 
> But now the RNG has to understand the concept of collections. I would argue 
> it is much cleaner to write an extension on Collection.
> 
> func randomElement(using source: RandomSource = .default) -> Element? {
>   guard !isEmpty else {return nil}
>   let idx = Int.random(in: 0…(count - 1), using: source)
>   return self[idx]
> }

But then the Collection has to understand the concept of random numbers. ;-)
Well both approaches are equally clean from this point of view:

extension RandomFoo {
func draw(from urn: T) -> T.Element? {
guard !urn.isEmpty else { return nil }
let idx = draw(from: urn.indices)
return urn[idx]
}
}

We just have to define one base protocol for such extensions. Every random 
number generator then automatically knows how to draw elements from ranges and 
collections.

— Martin
___
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-11-30 Thread Chris Lattner via swift-evolution
> On Nov 30, 2017, at 3:54 PM, Xiaodi Wu  wrote:
> While we shouldn’t necessarily avoid a feature simply because it can be used 
> distastefully, consider something like this:
> 
>   public extension NSObject :  DynamicMemberLookupProtocol, 
> DynamicCallableProtocol { … }
> 
> that goes directly to the Objective-C runtime to resolve member lookups and 
> calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly 
> convenient, and one could imagine some mixed Objective-C/Swift code bases 
> where this would save a lot of typing (of code)… at the cost of losing static 
> typing in the language. The presence of that one extension means I can no 
> longer rely on the safety guarantees Swift normally provides, for any project 
> that imports that extension and uses a subclass of NSObject. At best, we as a 
> community decide “don’t do that”; at worse, some nontrivial fraction of the 
> community decides that the benefits outweigh the costs (for this type or some 
> other), and we can no longer say that Swift is a strong statically-typed 
> language without adding “unless you’re using something that adopts 
> DynamicMemberLookupProtocol”.
> 
> I agree that the prospect above seems not ideal at all. On reading Chris's 
> proposal, it never occurred to me that the intention was to support such 
> retroactive conformance to these special protocols. Admittedly, such 
> retroactive conformance is possible with all protocols--with the notable 
> exception of those that require compiler synthesis of requirements. But 
> Chris's protocols seemed magical enough (in the gut feeling sense) that I 
> naturally assumed that retroactive conformance was never on the table. We 
> would be justified in making that prohibition here, I think, although I'm not 
> sure if Chris as proposal author feels the same way.

FWIW, if retroactive conformance itself is a concern, then I’d be perfectly 
fine restricting the proposal a bit, and just say that DynamicMemberLookup has 
to be declared on a *primary type declaration* and not an extension.  That 
seems perfectly reasonable, and I agree that “Dynamic behavior” could be 
considered part of the primary behavior of a type that shouldn't be 
retroactively added.

> Alternatively--and perhaps more elegantly--we could address this concern 
> head-on by having, instead of `DynamicMemberLookupProtocol` and 
> `DynamicCallable`, a magical class `DynamicObject` which all dynamic types 
> must inherit from. It would then be clear by design that Swift types cannot 
> be _retroactively dynamic_ in the sense that Chris proposes. I *think* the 
> vast majority of bridged use cases can tolerate being `final class` types 
> instead of `struct` types. I could be wrong though.

I’d really like to use this thing with structs, so it seems better to limit it 
to primary declarations to solve this concern.

> As Chris writes in his proposal, there are several areas (such as data 
> science) where, to put it plainly, Python or another dynamic language is 
> significantly better than Swift due to a much larger ecosystem of libraries, 
> tools, and user communities, with sometimes decades of lead time. It is 
> nonsensical to talk about how Swift is "supposed to be better" in any way 
> whatsoever in that context. As diehard Swift users, we may be confident that 
> the virtues of Swift's syntax, static typing, compiler smarts, protocol-based 
> design, or whatever else offer opportunities for, say, data science libraries 
> and tools to be better in the future, eventually. But to make this even 
> possible involves first making Swift a viable language in which to work with 
> current data science tools. Y

This is a really great summary - and an example of the challenge of 
swift-evolution, whose members far over-represent “current” swift users, and 
far under-represents “future” ones. :-)

-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-11-30 Thread Chris Lattner via swift-evolution
> On Nov 30, 2017, at 10:31 PM, Chris Lattner  wrote:
> 
> The Objective-C runtime does not track the type of members or methods.

Ok, this statement isn’t factually true: I’ll admit that there are two related 
things to this: the GNU ObjC runtime does track some method types, and ObjC 
does have @encode strings, which encode a subset of the ObjC type system.  

While both are true, neither are used by Swift AnyObject lookup, so the rest of 
the points still hold.

-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-11-30 Thread Chris Lattner via swift-evolution

> On Nov 30, 2017, at 10:26 PM, Slava Pestov  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 10:23 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> The difference between it and AnyObject lookup is that AnyObject lookup is:
>> 
>> b) type unsafe
> 
> Can you explain in what sense AnyObject lookup is type unsafe where your 
> proposal is type safe? Both seem type safe in the sense that your program 
> will not hit undefined behavior at runtime and instead trap if you access a 
> non-existent member; both are type unsafe in the sense that you cannot reason 
> statically about whether any specific member lookup will succeed. What is the 
> distinguishing characteristic between the two that makes one safe and the 
> other not?

The Objective-C runtime does not track the type of members or methods.  The 
Clang importer uses the same heuristic approach that Objective-C/Clang/GCC do.  
If you have something of type “id” named “x”, when you write “x.foo” if there 
is a declaration of “foo” in some class in some imported header, it will assume 
it has the type of that declaration.  While this is an important heuristic, 
this is not always the case, and does in fact cause bugs in users code.

In contrast, the DynamicMemberLookup proposal itself is fully type safe (three 
fully type safe implementation approaches are explained in it) and the Python 
interop layer I’m prototyping uses it.

-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-11-30 Thread Slava Pestov via swift-evolution


> On Nov 30, 2017, at 10:23 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> The difference between it and AnyObject lookup is that AnyObject lookup is:
> 
> b) type unsafe

Can you explain in what sense AnyObject lookup is type unsafe where your 
proposal is type safe? Both seem type safe in the sense that your program will 
not hit undefined behavior at runtime and instead trap if you access a 
non-existent member; both are type unsafe in the sense that you cannot reason 
statically about whether any specific member lookup will succeed. What is the 
distinguishing characteristic between the two that makes one safe and the other 
not?

Slava
___
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-11-30 Thread Chris Lattner via swift-evolution
> On Nov 30, 2017, at 6:15 AM, Matthew Johnson  wrote:
>> 
>> I think better interoperability with Python (and other OO languages in 
>> widespread use) is a good goal, and I agree that the implementation of the 
>> feature described is straight-forward and not terribly invasive in the 
>> compiler.
>> 
>> However, I do not think this proposal is going in the right direction for 
>> Swift. I have objections on several different grounds.
> 
> +1 to everything Doug says here.  He articulates the concerns I tried to 
> voice in an earlier thread more clearly and more thoroughly.  

Doug’s email was pretty confusing, so I’ll try to clear up some of the 
misconceptions here.  I also updated the proposal with a new section at the 
end, please check it out.

> This design introduces a significant hole in the type system which is 
> contrary to the spirit of Swift.

There is no “hole” in the type system.  The proposal is fully type safe. 

Further, the addition is absolutely in the spirit of Swift, because it is 
directly analogous to an existing feature: AnyObject lookup.  The difference 
between it and AnyObject lookup is that AnyObject lookup is:

a) specific to Objective-C interop
b) type unsafe
c) massively invasive on the rest of the compiler.

We’ve made many attempts to narrow the scope of AnyObject lookup, but it is 
difficult to do so given backwards compatibility constraints and the limited 
nature of Objective-C metadata.

>  It doesn’t just make dynamic language interop easy, it also changes the 
> semantics of any type which conforms to DynamicMemberLookupProtocol.  That is 
> not something that is locally visible when looking at a piece of code.  
> Worse, it does so in a way that trivial mistakes such as a typo can turn into 
> runtime errors.  Worst of all, as Doug points out it is possible to use 
> retroactive conformance to change the semantics of vast quantities of widely 
> used types in one fell swoop.

This is a feature, like many others, which can be misused.  This has not been 
the metric we have used to judge what should go into Swift.  I can elaborate if 
my response to Doug wasn’t clear.

> One additional concern that I don’t believe has been mentioned is that of 
> evolution.  When a library is imported from a dynamic language and the 
> library makes breaking changes Swift code written using this feature will 
> break without notice until a runtime error occurs.  Is that acceptable?  That 
> may be what users of dynamic languages are accustomed to but can we do better 
> in Swift?  If we can make the process of upgrading dependencies less a less 
> harrowing experience perhaps that could be a major selling point in moving 
> them to Swift.  But we won’t accomplish that with this design.

How would you this to work with *any* interoperability approach?  Dynamic 
languages are in fact dynamic, and need the ability to do dynamic lookups 
somehow.  Those dynamic lookups will all have the problem you observe.

> Interop with dynamic languages is a worthy goal, but we should do it in a way 
> that has no potential impact on code that does not need the feature.  A 
> semantic variant of “don’t pay for what you don’t use” should apply here.  If 
> we add this feature everyone will pay for it every time they read unfamiliar 
> Swift code.  They will have to contend with the potential for conformances to 
> this protocol, even on standard library types.  That feels like a pretty high 
> cost to me, especially for programmers who aren’t using the dynamic language 
> interop features themselves.

You seem to fear that people will pervasively adopt this and use it for weird 
things.  While that is possible, that would be simply one way to misuse Swift.  
What makes it more likely for someone to do this than to use unsafe features 
incorrectly, providing an apparently type safe API that actually isn’t?

> Further, a consistent theme has been the desire to avoid things like compiler 
> flags that could fragment the community.  I fear this feature has the 
> potential to do that, especially if it is really successful at attracting 
> people from the dynamic language community.  

I really fail to see how this concern relates here.  This has nothing to do 
with compiler flags.  This has the potential to expand the community, not 
fragment it.

-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-11-30 Thread Chris Lattner via swift-evolution
On Nov 30, 2017, at 3:46 AM, Matt Diephouse 
 wrote:
> The examples in the proposal are very shallow, highlighting single lookups. 
> But what are the types of the returned values?

The Python example is recursive: PyVal is returned and is the source of 
dynamism, so it chains arbitrarily.

I encourage you to check out the Playground I sent out on Nov 19 to 
swift-evolution which shows how all this works in more detail.

> I think the proposal should include a more complete example that demonstrates 
> how meaningful interop code could be written.

The proposal is independent of any specific bridge, I covered one possible way 
that Python could be bridged in that playground.  That said, the actual design 
of a Python bridge will itself be a follow-on proposal.

> 2. The JavaScript example will be popular, but isn’t actually that useful
> 
> Swift already has `Codable`, which provides more automatic and more type-safe 
> (in that it encourages all-or-nothing decoding) JSON decoding. 

This only helps you if you control the JSON format or if it has a principled 
structure that maps nicely to Swift.  If you’re working with some existing 
service which is poorly structured and inconsistent, then it is very useful.

That said, the JSON example is simply an example to illustrate the ideas in the 
proposal, it is not part of the proposal itself.

-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-11-30 Thread Chris Lattner via swift-evolution
Hi Doug,

Thank you for the detailed email.  I have been traveling today, so I haven’t 
had a chance to respond until now.  I haven’t read the down-thread emails, so I 
apologize if any of this was already discussed:

> I think better interoperability with Python (and other OO languages in 
> widespread use) is a good goal, and I agree that the implementation of the 
> feature described is straight-forward and not terribly invasive in the 
> compiler.

Fantastic, I’m really pleased to hear that!  I only care about solving the 
problem, so if we can find a good technical solution to the problems than I’ll 
be happy.

A funny thing about swift-evolution is that it is populated with lots of people 
who already use Swift and want to see incremental improvements, but the people 
who *aren’t* using Swift yet (but should be) aren’t represented here.  As you 
know, I’m perhaps the biggest proponent of Swift spreading into new domains and 
earning the love of new users.

> However, I do not think this proposal is going in the right direction for 
> Swift. I have objections on several different grounds.

Thanks for being up front about this.  It turns out that a majority of the 
points you raise were brought up early in the pitch phases of the discussion, 
but I screwed up by not capturing that discussion into the alternatives section 
of the proposal.

Better late than never I guess: I just significantly revised the proposal, 
adding a new “Alternative Python Interoperability Approaches” section.  I’d 
appreciate it if you could read it and comment if you find any part 
disagreeable:
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#alternative-python-interoperability-approaches
 


Many of the points you make are discussed there, but I’ll respond 
point-by-point below as well:

> Philosophy
> Swift is, unabashedly, a strong statically-typed language.

That’s factually incorrect.

> We don’t allow implicit down casting, we require “as?” so you have to cope 
> with the possibility of failure (or use “as!” and think hard about the “!”). 
> Even the gaping hole that is AnyObject dispatch still requires the existence 
> of an @objc declaration and produces an optional lookup result, so the user 
> must contend with the potential for dynamic failure.

AnyObject dispatch is one of the gaping holes for sure.  You don’t mention it, 
but its lookup results are represented as *ImplicitlyUnwrappedOptional* 
results, which do not force the user to contend with dynamic failure.  Further, 
unlike my proposal (which is fully type safe), AnyObject lookup is not type 
safe at all.  It is also far more invasively intertwined throughout the 
compiler.

More problematically for your argument: your preferred approach requires the 
introduction of (something like) DynamicMemberLookupProtocol or something like 
AnyObject-For-Python, so your proposal would be additive on top of solving the 
core problem I’m trying to solve.  It isn’t an alternative approach at all.

> Whenever we discuss adding more dynamic features to Swift, there’s a strong 
> focus on maintaining that strong static type system.

Which this does, by providing full type safety - unlike AnyObject lookup.

> IMO, this proposal is a significant departure from the fundamental character 
> of Swift, because it allows access to possibly-nonexistent members (as well 
> as calls with incorrect arguments, in the related proposal) without any 
> indication that the operation might fail.

The only way your claim is correct is if someone implements the protocol wrong. 
 What you describe is true of AnyObject lookup though, so I understand how you 
could be confused by that.

> It’s easy to fall through these cracks for any type that supports 
> DynamicMemberLookupProtocol—a single-character typo when using a 
> DynamicMemberLookupProtocol-capable type means you’ve fallen out of the 
> safety that Swift provides.

Since you seem to be latching on to this, I’ll say it again: the proposal is 
fully type safe :-)

That said, the “simple typo” problem is fundamental to the problem of working 
with a dynamically typed language: unless you can eradicate all “fundamental 
dynamism” from the language, you cannot prevent this.

That said, since this is a problem inherent with these languages, it is 
something people are already very familiar with, and something that everyone 
using those APIs has had to deal with.  This is also not our problem to solve, 
and people in the Python community have been discussing and working on it over 
a large part of its 25 year history.  I find your belief that we could solve 
this for Python better than the Python community itself has both idealistic and 
a bit naive.
> 
> While we shouldn’t necessarily avoid a feature simply because it can be used 
> distastefully, consider something like this:
> 
>   public extension NSObject 

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

2017-11-30 Thread Greg Titus via swift-evolution
Hi Doug,

> On Nov 30, 2017, at 4:28 PM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> I think this approach is more predictable and more implementable than the 
> current model. I’m curious whether the above makes sense to someone other 
> than me, and whether it covers existing use cases well enough. Thoughts?

I don’t have a lot to add here, except to say: Yes, this makes sense to me, and 
is much easier to reason about. The three new rough rules covers all of the 
Swift protocol code I can think of that I’ve written, and seems complete for 
any reasonable set of thought experiments I’ve come up with so far.

Thanks!
- Greg___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Nate Cook via swift-evolution

> On Nov 30, 2017, at 6:20 PM, Xiaodi Wu  wrote:
> 
> On Thu, Nov 30, 2017 at 5:24 PM, Nate Cook  wrote:
>>> On Nov 30, 2017, at 4:30 PM, Xiaodi Wu via swift-evolution 
>>>  wrote:
>>> 
 On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
  wrote:
 
 
> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I would personally go with:
> 
>   Int.random //Returns a random Int
 
 “Type.random” is so rarely used as to not be worth the addition, IMO. If 
 you really need a random element from the *entire* domain, then I think 
 you should have to manually create the ClosedRange yourself.
 
>   Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
> result from the closed range. Closed Range is never empty.
 
 This is redundant. In order to pick a random element, you’re saying I 
 should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
 have to specify Int twice: once for the “.random” call, and again for the 
 type of the range. We can do better than that.
>> 
>> I don’t see how this is redundant—do you mean that you’d need to write out 
>> the type name instead of writing `(0..<10).random()!`? I continue to be of 
>> the opinion that picking a random integer/floating-point value/Boolean and 
>> picking a random element from a collection are two different operations. 
>> Yes, there’s overlap between the two, but they’re different enough that 
>> having two ways to choose an integer between 0 and 10 would be fine.
> 
> As I wrote elsewhere, if they're sufficiently different enough, then they 
> ought to have distinct names. If they are not, then there ought to be only 
> one of them. I'm no longer sure myself of which one I'd prefer, but in no 
> case should there be two things named "random."
> 
> If the proposal to make `IndexDistance == Int` is accepted, then ranges 
> cannot conform to Collection and we encounter some interesting difficulties 
> attempting to index into such a collection to pick a random value.
> 
>   [0,2,3].randomElement //Returns a random element from the collection
 
 I strongly believe this should be a method, not a property. Properties, 
 like .first and .last, are expected to return the same value each time you 
 access them. “.random” inherently breaks that.
>>>  
>>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>>> conclusions above, and for substantially the same reasons.
> 
> Then a version of each with a ‘using:’ parameter which takes a 
> generator/source:
> 
>   Int.random(using: RandomSource) //Returns a random Int using the given 
> source of randomness
>   Int.random(in: ClosedRange, using: RandomSource)
>   [0,2,3].randomElement(using: RandomSource)
> 
> In my own RandomSource & RandomSourceCreatable protocols, I frequently 
> use random colors and sizes as well.  The issue there is that you really 
> want a closed range for each dimension. I wish Swift had a better notion 
> of dimensionality baked into the language. 
> 
> What I ended up doing was having a “constraints” parameter which took an 
> array of constraints which corresponded to various dimensions.  It works 
> for me, but it might be a bit complex for something in the standard 
> library.
> 
> Honestly, given the current capabilities of Swift what this really calls 
> for is custom initializers/functions for dimensional types:
> 
>   UIColor.random //This comes from the protocol
>   UIColor.random(hue: ClosedRange = 0…1, saturation: 
> ClosedRange = 0…1, brightness: ClosedRange = 0…1, 
> alpha: ClosedRange = 1…1)
>   //…and of course the same as above, but with ‘using:'
> 
> Then you can easily get random colors which look like they belong 
> together:
>   
>   let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
> 
> There would probably also be a convenience version taking CGFloats and 
> passing them to the real function as ranges:
> 
>   let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
> 
> 
> This means that our default RandomSource needs to be publicly available, 
> so that the custom functions can use it as the default…
>>> 
>>> It does not. Having actually implemented some version of these APIs, it's 
>>> readily apparent now to me that all custom types can simply call 
>>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>>> whatever else we want to have in the standard library) to get random values 
>>> from the default RNG for any built-in type and size. The actual default 
>>> random need never be exposed publicly, and since its functions are strictly 
>>> redundant 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 4:11 PM, Xiaodi Wu  wrote:
> 
> On Thu, Nov 30, 2017 at 5:29 PM, Jonathan Hull  > wrote:
> 
>> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu > > wrote:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
>> 
>>> [0,2,3].randomElement //Returns a random element from the collection
>> 
>> I strongly believe this should be a method, not a property. Properties, like 
>> .first and .last, are expected to return the same value each time you access 
>> them. “.random” inherently breaks that.
>>  
>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>> conclusions above, and for substantially the same reasons.
>>> 
>>> Then a version of each with a ‘using:’ parameter which takes a 
>>> generator/source:
>>> 
>>> Int.random(using: RandomSource) //Returns a random Int using the given 
>>> source of randomness
>>> Int.random(in: ClosedRange, using: RandomSource)
>>> [0,2,3].randomElement(using: RandomSource)
>>> 
>>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>>> random colors and sizes as well.  The issue there is that you really want a 
>>> closed range for each dimension. I wish Swift had a better notion of 
>>> dimensionality baked into the language. 
>>> 
>>> What I ended up doing was having a “constraints” parameter which took an 
>>> array of constraints which corresponded to various dimensions.  It works 
>>> for me, but it might be a bit complex for something in the standard library.
>>> 
>>> Honestly, given the current capabilities of Swift what this really calls 
>>> for is custom initializers/functions for dimensional types:
>>> 
>>> UIColor.random //This comes from the protocol
>>> UIColor.random(hue: ClosedRange = 0…1, saturation: 
>>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>>> ClosedRange = 1…1)
>>> //…and of course the same as above, but with ‘using:'
>>> 
>>> Then you can easily get random colors which look like they belong together:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>> 
>>> There would probably also be a convenience version taking CGFloats and 
>>> passing them to the real function as ranges:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>> 
>>> 
>>> This means that our default RandomSource needs to be publicly available, so 
>>> that the custom functions can use it as the default…
>> 
>> 
>> It does not. Having actually implemented some version of these APIs, it's 
>> readily apparent now to me that all custom types can simply call 
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>> whatever else we want to have in the standard library) to get random values 
>> from the default RNG for any built-in type and size. The actual default 
>> random need never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
> 
> I have also implemented some version of these APIs, both for Random and 
> RepeatablyRandom sources.
> 
> I get what you are saying about just being able to use the constructs from 
> Int, etc…, but we still need a public default.  Let me give a concrete 
> example of CGSize.  Yes, we want to just use CGFloat’s random, but if we 
> don’t have a publicly available way to call the default then we have to 
> implement the same algorithm twice, which is problematic. (Code written in 
> Mail)
> 
> static func random(width widthRange: ClosedRange, height 
> heightRange: 

Re: [swift-evolution] [Review] SE-0191: Eliminate IndexDistance from Collection

2017-11-30 Thread Xiaodi Wu via swift-evolution
On Wed, Nov 29, 2017 at 10:46 AM, Ben Cohen  wrote:

> You can argue the current status is a bug, but…
>
> Welcome to Apple Swift version 4.0.1 (swiftlang-900.0.67 clang-900.0.38).
> Type :help for assistance.
>   1> CountableRange.IndexDistance.self
> $R0: Int.Type = Int
>   2> (Int64.min.. Execution interrupted. Enter code to recover and continue.
>
>
I do believe that, in the source code, this is marked with a "FIXME(ABI)"
comment.

(I dearly wish that we could have a primitive `Int1` available on which to
base a type such as `Int65` in the same manner as we implement
`DoubleWidth`. It would solve this use case beautifully.)

On Nov 29, 2017, at 4:04 AM, Xiaodi Wu  wrote:
>
> So that we are all clear on the implications of this, if IndexDistance
> becomes Int, ranges of integers will stop conforming to Collection, because
> Int.min.. potentially many more.
>
> This would entail nontrivial source breakage.
>
>
> On Mon, Nov 27, 2017 at 22:02 Ben Cohen via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> My suggestion would be: don’t have your Collection-like type conform to
>> Collection. Give it collection-like methods if you want them, like an
>> indexing and slicing subscript that takes an Int64. It can still conform to
>> Sequence.
>>
>> In practice, these “huge” collections will be mostly used concretely, so
>> their Collection conformance doesn’t buy you much. The reality is that very
>> few generic uses on these types will succeed. You get a few things like
>> .first, .last etc. for free. But very few algorithms are written to handle
>> > Int.max lengths (several in the std lib don’t) – it just isn’t practical.
>> And meanwhile, this is a huge burden on many other use cases.
>>
>> The existence of the memory mapped file case is hypothetical. I canvassed
>> a bit on twitter for some use cases. The only one I got back was where
>> someone was using IndexDistance to stash other information: but this isn’t
>> really a legal use of IndexDistance, since it must be numerically castable
>> to other integer types when needed which would be a lossy operation so at
>> best, it would just be an optimization.
>>
>> On Nov 27, 2017, at 19:29, Nevin Brackett-Rozinsky via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> The proposal mentions one reasonable situation where a larger-than-Int
>> type would be useful, namely a Collection wrapping a memory-mapped file,
>> being used on 32-bit systems.
>>
>> Is there a recommended migration strategy for this scenario?
>>
>> Nevin
>>
>>
>> On Mon, Nov 27, 2017 at 8:34 PM, Douglas Gregor via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Hello Swift community,
>>>
>>> The review of SE-0191 "Eliminate IndexDistance from Collection" begins
>>> now and runs through December 3, 2017. The proposal is available here:
>>>
>>> https://github.com/apple/swift-evolution/blob/master/
>>> proposals/0191-eliminate-indexdistance.md
>>>
>>> Reviews are an important part of the Swift evolution process. All
>>> reviews should be sent to the swift-evolution mailing list at
>>>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>> or, if you would like to keep your feedback private, directly to the
>>> review manager. When replying, please try to keep the proposal link at the
>>> top of the message:
>>>
>>> Proposal link:
>>>
>>> https://github.com/apple/swift-evolution/blob/master/
>>> proposals/0191-eliminate-indexdistance.md
>>>
>>> Reply text
>>>
>>> Other replies
>>>
>>> What
>>> goes into a review?
>>>
>>> The goal of the review process is to improve the proposal under review
>>> through constructive criticism and, eventually, determine the direction of
>>> Swift. When writing your review, here are some questions you might want to
>>> answer in your review:
>>>
>>>- What is your evaluation of the proposal?
>>>- Is the problem being addressed significant enough to warrant a
>>>change to Swift?
>>>- Does this proposal fit well with the feel and direction of Swift?
>>>- If you have used other languages or libraries with a similar
>>>feature, how do you feel that this proposal compares to those?
>>>- How much effort did you put into your review? A glance, a quick
>>>reading, or an in-depth study?
>>>
>>> More information about the Swift evolution process is available at
>>>
>>> https://github.com/apple/swift-evolution/blob/master/process.md
>>>
>>> Thank you,
>>>
>>> -Doug
>>>
>>> Review Manager
>>>
>>> ___
>>> 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
>>
>>
>> 

[swift-evolution] [RFC] Associated type inference

2017-11-30 Thread Douglas Gregor via swift-evolution
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.

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 contains associated 
type defaults for Indices, Iterator, and SubSequence. Let’s focus on Indices:

protocol Collection : Sequence {
  associatedtype Indices = DefaultIndices
  // ...
}

protocol BidirectionalCollection : Collection {
  associatedtype Indices = DefaultBidirectionalIndices
  // ...
}

protocol RandomAccessCollection : BidirectionalCollection {
  associatedtype Indices = DefaultRandomAccessIndices
  // ...
}

The basic idea here is that different protocols in the hierarchy provide 
different defaults, and you presumably want the default from the most specific 
protocol. If I define a type and make it conform to BidirectionalCollection, 
I’d expect to get DefaultBidirectionalIndices for Indices. If a define a 
type and make it conform to RandomAccessIterator, I’d expect to get 
DefaultRandomAccessIndices.

(Aside: DefaultRandomAccessIndices and DefaultBidirectionalIndices got 
collapsed into DefaultIndices now that we have conditional conformances for the 
standard library , but the issues 
I’m describing remain).

Associated type defaults seem like a reasonable feature that fits well enough 
into the design. However, it’s not the only thing in place with our 
MyCollection example, for which Indices was inferred to CountableRange. How’s 
that happen?

Associated Type Inference
Associated type inference attempts to look at the requirements of a protocol, 
and then looks into the conforming type for declarations that might satisfy 
those requirements, and infers associated types from the types of those 
declarations. Let’s look at some examples. RandomAccessCollection 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Xiaodi Wu via swift-evolution
On Thu, Nov 30, 2017 at 5:24 PM, Nate Cook  wrote:

> On Nov 30, 2017, at 4:30 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>>
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> I would personally go with:
>>
>> Int.random //Returns a random Int
>>
>>
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If
>> you really need a random element from the *entire* domain, then I think you
>> should have to manually create the ClosedRange yourself.
>>
>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a
>> result from the closed range. Closed Range is never empty.
>>
>>
>> This is redundant. In order to pick a random element, you’re saying I
>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I
>> have to specify Int twice: once for the “.random” call, and again for the
>> type of the range. We can do better than that.
>>
>
> I don’t see how this is redundant—do you mean that you’d need to write out
> the type name instead of writing `(0..<10).random()!`? I continue to be of
> the opinion that picking a random integer/floating-point value/Boolean and
> picking a random element from a collection are two different operations.
> Yes, there’s overlap between the two, but they’re different enough that
> having two ways to choose an integer between 0 and 10 would be fine.
>

As I wrote elsewhere, if they're sufficiently different enough, then they
ought to have distinct names. If they are not, then there ought to be only
one of them. I'm no longer sure myself of which one I'd prefer, but in no
case should there be two things named "random."

If the proposal to make `IndexDistance == Int` is accepted, then ranges
cannot conform to Collection and we encounter some interesting difficulties
attempting to index into such a collection to pick a random value.

[0,2,3].randomElement //Returns a random element from the collection
>>
>>
>> I strongly believe this should be a method, not a property. Properties,
>> like .first and .last, are expected to return the same value each time you
>> access them. “.random” inherently breaks that.
>>
>
> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's
> conclusions above, and for substantially the same reasons.
>
>>
>> Then a version of each with a ‘using:’ parameter which takes a
>> generator/source:
>>
>> Int.random(using: RandomSource) //Returns a random Int using the given
>> source of randomness
>> Int.random(in: ClosedRange, using: RandomSource)
>> [0,2,3].randomElement(using: RandomSource)
>>
>> In my own RandomSource & RandomSourceCreatable protocols, I frequently
>> use random colors and sizes as well.  The issue there is that you really
>> want a closed range for each dimension. I wish Swift had a better notion of
>> dimensionality baked into the language.
>>
>> What I ended up doing was having a “constraints” parameter which took an
>> array of constraints which corresponded to various dimensions.  It works
>> for me, but it might be a bit complex for something in the standard library.
>>
>> Honestly, given the current capabilities of Swift what this really calls
>> for is custom initializers/functions for dimensional types:
>>
>> UIColor.random //This comes from the protocol
>> UIColor.random(hue: ClosedRange = 0…1, saturation:
>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha:
>> ClosedRange = 1…1)
>> //…and of course the same as above, but with ‘using:'
>>
>> Then you can easily get random colors which look like they belong
>> together:
>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6)
>>
>> There would probably also be a convenience version taking CGFloats and
>> passing them to the real function as ranges:
>>
>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>
>>
>> This means that our default RandomSource needs to be publicly available,
>> so that the custom functions can use it as the default…
>>
>>
> It does not. Having actually implemented some version of these APIs, it's
> readily apparent now to me that all custom types can simply call
> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or
> whatever else we want to have in the standard library) to get random values
> from the default RNG for any built-in type and size. The actual default
> random need never be exposed publicly, and since its functions are strictly
> redundant to these other APIs (which, of course, are the "currency" APIs
> that our purpose here is to design and make public), the default random is
> required only for internal implementation of the "currency" APIs and (a) is
> better off *not* exposed; (b) doesn't need to be of the same type as other
> RNGs, conform to the same protocols, or for that matter, does not even need
> to be a type or 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution
> On Nov 30, 2017, at 3:46 PM, Martin Waitz  wrote:
> 
> Hello Jonathan,
> 
>> For collections, I think we should call returning a random element 
>> -randomElement, and choosing a random element without replacement 
>> -popRandomElement
> 
> I disagree because I don’t think that the random data is a property of the 
> collection.
> The collection is not the subject which has random elements, it’s more the 
> object which is used when drawing an element.

The collection is a subject which has elements, and we are asking for one of 
them at random.


>> var list = [1,2,3,4]
>> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
>> one of the elements
> 
> Instead I would prefer to have something like:
> 
> let a = random.draw(from: list)

But now the RNG has to understand the concept of collections. I would argue it 
is much cleaner to write an extension on Collection.

func randomElement(using source: RandomSource = .default) -> Element? {
guard !isEmpty else {return nil}
let idx = Int.random(in: 0…(count - 1), using: source)
return self[idx]
}

> 
>> let b:Int? = list.popRandomElement //Now list contains all the elements 
>> except the one in ‚b’
> 
> we already have remove(at:), this can be used trivially:
> 
> let b = list.remove(at: random.draw(from: list.indices))
> 
> a little bit more verbose, but easily understandable.
> It uses well known building blocks and does not increase the API surface of 
> collections.

True.  But you could make the same argument for popLast().

I think both are common enough use-cases that they warrant the convenience 
method.  If not though, I can just add it myself for my own code.

Thanks,
Jon


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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread TellowKrinkle via swift-evolution
Another common reason to use a custom RNG is to be able to use a seed for 
repeatability, which would (I think) work properly here.

> 2017/11/30 18:11、Xiaodi Wu のメール:
> 
> On Thu, Nov 30, 2017 at 5:29 PM, Jonathan Hull  > wrote:
> 
>> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu > > wrote:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
>> 
>>> [0,2,3].randomElement //Returns a random element from the collection
>> 
>> I strongly believe this should be a method, not a property. Properties, like 
>> .first and .last, are expected to return the same value each time you access 
>> them. “.random” inherently breaks that.
>>  
>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>> conclusions above, and for substantially the same reasons.
>>> 
>>> Then a version of each with a ‘using:’ parameter which takes a 
>>> generator/source:
>>> 
>>> Int.random(using: RandomSource) //Returns a random Int using the given 
>>> source of randomness
>>> Int.random(in: ClosedRange, using: RandomSource)
>>> [0,2,3].randomElement(using: RandomSource)
>>> 
>>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>>> random colors and sizes as well.  The issue there is that you really want a 
>>> closed range for each dimension. I wish Swift had a better notion of 
>>> dimensionality baked into the language. 
>>> 
>>> What I ended up doing was having a “constraints” parameter which took an 
>>> array of constraints which corresponded to various dimensions.  It works 
>>> for me, but it might be a bit complex for something in the standard library.
>>> 
>>> Honestly, given the current capabilities of Swift what this really calls 
>>> for is custom initializers/functions for dimensional types:
>>> 
>>> UIColor.random //This comes from the protocol
>>> UIColor.random(hue: ClosedRange = 0…1, saturation: 
>>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>>> ClosedRange = 1…1)
>>> //…and of course the same as above, but with ‘using:'
>>> 
>>> Then you can easily get random colors which look like they belong together:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>> 
>>> There would probably also be a convenience version taking CGFloats and 
>>> passing them to the real function as ranges:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>> 
>>> 
>>> This means that our default RandomSource needs to be publicly available, so 
>>> that the custom functions can use it as the default…
>> 
>> 
>> It does not. Having actually implemented some version of these APIs, it's 
>> readily apparent now to me that all custom types can simply call 
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>> whatever else we want to have in the standard library) to get random values 
>> from the default RNG for any built-in type and size. The actual default 
>> random need never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
> 
> I have also implemented some version of these APIs, both for Random and 
> RepeatablyRandom sources.
> 
> I get what you are saying about just being able to use the constructs from 
> Int, etc…, but we still need a public default.  Let me give a concrete 
> example of CGSize.  Yes, we want to just use CGFloat’s random, but if we 
> don’t have a publicly available way to call the default then we have to 
> implement the same algorithm twice, which is 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 5:02 PM, Jonathan Hull  wrote:
> 
> 
>> On Nov 30, 2017, at 3:52 PM, Dave DeLong > > wrote:
>> 
>> What is the useful distinction between generating a random value, and 
>> choosing a random element from a collection of all possible values?
> 
> I don’t have to generate (or keep in memory) that collection.  
> 
> I gave an example before of an easy to add API for random colors which allow 
> their saturation, lightness, and alpha to be fixed.  I use something very 
> similar all the time in some graphics code I have (varying only the hue or 
> saturation).  I also do the same with Sizes and CGVectors.  How would you 
> represent that as a collection to choose an element from?

You’re not picking a random color. You’re picking a random hue or a random 
saturation, and then constructing a color based off that. In other words, 
you’re choosing a value from 0…1:

let color = UIColor(hue: (0…1.0).random(), saturation: knownSaturationValue, 
brightness: knownBrightnessValue, alpha: knownAlphaValue)

Dave

> Also, for most of my use cases, I *need* to be able to plug in a repeatably 
> random source… otherwise pixels will start jumping around the screen when 
> people resize things.

That’s cool; I’m totally in favor of the RandomSource API as a way to model 
different distributions or algorithms or whatever. I just don’t thing 
“Foo.random” is a good idea.

Cheers

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 3:52 PM, Dave DeLong  wrote:
> 
> What is the useful distinction between generating a random value, and 
> choosing a random element from a collection of all possible values?

I don’t have to generate (or keep in memory) that collection.  

I gave an example before of an easy to add API for random colors which allow 
their saturation, lightness, and alpha to be fixed.  I use something very 
similar all the time in some graphics code I have (varying only the hue or 
saturation).  I also do the same with Sizes and CGVectors.  How would you 
represent that as a collection to choose an element from?

Also, for most of my use cases, I *need* to be able to plug in a repeatably 
random source… otherwise pixels will start jumping around the screen when 
people resize things.

Thanks,
Jon___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Martin Waitz via swift-evolution
Hi,

>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
> 
> I don’t see how this is redundant—do you mean that you’d need to write out 
> the type name instead of writing `(0..<10).random()!`? I continue to be of 
> the opinion that picking a random integer/floating-point value/Boolean and 
> picking a random element from a collection are two different operations.

Well, I don‘t see a big difference beteeen ranges and collections here. We can 
support both with the same syntax:

let a = random.draw(from: 1...3)
let b = random.draw(from: [1, 2, 3])

— Martin___
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-11-30 Thread Xiaodi Wu via swift-evolution
On Thu, Nov 30, 2017 at 2:24 AM, Douglas Gregor via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I’d like to formally propose the inclusion of user-defined dynamic member
> lookup types.
>
> Here is my latest draft of the proposal:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> https://github.com/apple/swift-evolution/pull/768
>
> An implementation of this design is available here:
> https://github.com/apple/swift/pull/13076
>
> The implementation is straight-forward and (IMO) non-invasive in the
> compiler.
>
>
>
> I think better interoperability with Python (and other OO languages in
> widespread use) is a good goal, and I agree that the implementation of the
> feature described is straight-forward and not terribly invasive in the
> compiler.
>
> However, I do not think this proposal is going in the right direction for
> Swift. I have objections on several different grounds.
>
> *Philosophy*
> Swift is, unabashedly, a strong statically-typed language. We don’t allow
> implicit down casting, we require “as?” so you have to cope with the
> possibility of failure (or use “as!” and think hard about the “!”). Even
> the gaping hole that is AnyObject dispatch still requires the existence of
> an @objc declaration and produces an optional lookup result, so the user
> must contend with the potential for dynamic failure. Whenever we discuss
> adding more dynamic features to Swift, there’s a strong focus on
> maintaining that strong static type system.
>
> IMO, this proposal is a significant departure from the fundamental
> character of Swift, because it allows access to possibly-nonexistent
> members (as well as calls with incorrect arguments, in the related
> proposal) without any indication that the operation might fail. It’s easy
> to fall through these cracks for any type that supports
> DynamicMemberLookupProtocol—a single-character typo when using a
> DynamicMemberLookupProtocol-capable type means you’ve fallen out of the
> safety that Swift provides. I think that’s a poor experience for the Python
> interoperability case, but more on that in the Tooling section below.
>
> While we shouldn’t necessarily avoid a feature simply because it can be
> used distastefully, consider something like this:
>
> public extension NSObject :  DynamicMemberLookupProtocol,
> DynamicCallableProtocol { … }
>
> that goes directly to the Objective-C runtime to resolve member lookups
> and calls—avoiding @objc, bridging headers, and so on. It’s almost
> frighteningly convenient, and one could imagine some mixed
> Objective-C/Swift code bases where this would save a lot of typing (of
> code)… at the cost of losing static typing in the language. The presence of
> that one extension means I can no longer rely on the safety guarantees
> Swift normally provides, for any project that imports that extension and
> uses a subclass of NSObject. At best, we as a community decide “don’t do
> that”; at worse, some nontrivial fraction of the community decides that the
> benefits outweigh the costs (for this type or some other), and we can no
> longer say that Swift is a strong statically-typed language without adding
> “unless you’re using something that adopts DynamicMemberLookupProtocol”.
>

There are several commenters below to whom I would have liked to respond in
the fullness of time, but time constraints would make doing so prohibitive.
Since your message set off an abundance of discussion, I'll reply to the
points you make here and, along the way, ask your forbearance to bring up
and respond to some related concerns raised by others.

I agree that the prospect above seems not ideal at all. On reading Chris's
proposal, it never occurred to me that the intention was to support such
retroactive conformance to these special protocols. Admittedly, such
retroactive conformance is possible with all protocols--with the notable
exception of those that require compiler synthesis of requirements. But
Chris's protocols seemed magical enough (in the gut feeling sense) that I
naturally assumed that retroactive conformance was never on the table. We
would be justified in making that prohibition here, I think, although I'm
not sure if Chris as proposal author feels the same way.

Alternatively--and perhaps more elegantly--we could address this concern
head-on by having, instead of `DynamicMemberLookupProtocol` and
`DynamicCallable`, a magical class `DynamicObject` which all dynamic types
must inherit from. It would then be clear by design that Swift types cannot
be _retroactively dynamic_ in the sense that Chris proposes. I *think* the
vast majority of bridged use cases can tolerate being `final class` types
instead of `struct` types. I could be wrong though.

Now, as to the possibility of failure: I agree also that eliding the
possibility of lookup failure at the callsite requires further
consideration. Some 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 4:46 PM, Jonathan Hull  wrote:
> 
>> 
>> On Nov 30, 2017, at 3:19 PM, Dave DeLong > > wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull >> > wrote:
>>> 
>>> 
 On Nov 30, 2017, at 1:58 PM, Dave DeLong > wrote:
 
 
 
> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
> > wrote:
> 
> I would personally go with:
> 
>   Int.random //Returns a random Int
 
 “Type.random” is so rarely used as to not be worth the addition, IMO. If 
 you really need a random element from the *entire* domain, then I think 
 you should have to manually create the ClosedRange yourself.
>>> 
>>> What evidence do you have that this will not be used often?  There are many 
>>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, 
>>> for example, would definitely require Bool.Random.  I certainly use the 
>>> full range of UInt and UInt8 on a regular basis (less so with Int).
>> 
>> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
>> “[true, false].random()”
> 
> I suppose you can do that, but [true, false].randomElement() is much less 
> efficient than Bool.random().  You are creating an array each time you need a 
> Bool, which in some of my use-cases, is pretty often.

So… keep the array around in memory so you don’t have to recreate it… 

> 
> 
>> As for evidence… my own experience. Other than small-value types (like 
>> Bool), it is *exceptionally* rare to come across a situation where you need 
>> a random from the entire range. Random colors  are interesting, but are rare 
>> because they can’t guarantee design aesthetic. Random Dates are nonsensical. 
>> Random Ints are maybe useful, but again, you almost always need a random Int 
>> from a range of possible values.
> 
> The fact that you haven’t needed it in your personal use cases isn’t evidence 
> that others don’t need it.

Yes, of course. But no where on this thread have I seen a compelling example of 
generating a random value from all possible values. Have I missed one?

> 
> 
>>> I think it is important to have Type.random as the base because there are 
>>> many types which would conform (not just Int & Double).  For example, I 
>>> might have an enum which returns a random case from MyEnum.random.  How 
>>> would you do that if random(in:) was the required base?
>> 
>> I actually don’t think there should be a static “random()” method. I think 
>> it should be a member function, not a type function.
> 
> I don’t understand this.  What would 1.random() do?

Well, if such an API existed, it would return “1”. However, since “1” isn’t a 
collection or range or whatever, this API wouldn’t even exist.

> 
> 
>> As for picking a random enum, see the previous bit about picking a random 
>> bool. And that will get even easier once we get the patch where enums have a 
>> static value listing all their cases, such as “CardSuits.allValues.random()”.
> 
> This would use .randomElement().  I think it is important to have a different 
> name for generating a random value and picking a random element from a 
> collection to avoid conflating the two.

What is the useful distinction between generating a random value, and choosing 
a random element from a collection of all possible values?

Dave

> 
> 
>   Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
> result from the closed range. Closed Range is never empty.
 
 This is redundant. In order to pick a random element, you’re saying I 
 should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
 have to specify Int twice: once for the “.random” call, and again for the 
 type of the range. We can do better than that.
>>> 
>>> You didn’t have to specify it twice.  You used integer literals for the 
>>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>>> that we require a closed range, which would mean you would have to do 
>>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>>> empty.
>> 
>> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes 
>> it easier to change the type, and it doesn’t require me to know a priori the 
>> type of the range I’m dealing with.
> 
> 
> I think you could have both Int.random(in: 0…9) and (0…9).randomElement() 
> without issue.  You could even argue for conditionally conforming ranges and 
> allowing (0…9).random(), though it might be a harder sell.
> 
> Note that Int.random(in:) returns an ‘Int', and Range.randomElement() 
> returns an ‘Int?'
> 
> Thanks,
> Jon

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

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 3:19 PM, Dave DeLong  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull > > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 1:58 PM, Dave DeLong >> > wrote:
>>> 
>>> 
>>> 
 On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
 > wrote:
 
 I would personally go with:
 
Int.random //Returns a random Int
>>> 
>>> “Type.random” is so rarely used as to not be worth the addition, IMO. If 
>>> you really need a random element from the *entire* domain, then I think you 
>>> should have to manually create the ClosedRange yourself.
>> 
>> What evidence do you have that this will not be used often?  There are many 
>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
>> example, would definitely require Bool.Random.  I certainly use the full 
>> range of UInt and UInt8 on a regular basis (less so with Int).
> 
> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
> “[true, false].random()”

I suppose you can do that, but [true, false].randomElement() is much less 
efficient than Bool.random().  You are creating an array each time you need a 
Bool, which in some of my use-cases, is pretty often.


> As for evidence… my own experience. Other than small-value types (like Bool), 
> it is *exceptionally* rare to come across a situation where you need a random 
> from the entire range. Random colors  are interesting, but are rare because 
> they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
> Ints are maybe useful, but again, you almost always need a random Int from a 
> range of possible values.

The fact that you haven’t needed it in your personal use cases isn’t evidence 
that others don’t need it.


>> I think it is important to have Type.random as the base because there are 
>> many types which would conform (not just Int & Double).  For example, I 
>> might have an enum which returns a random case from MyEnum.random.  How 
>> would you do that if random(in:) was the required base?
> 
> I actually don’t think there should be a static “random()” method. I think it 
> should be a member function, not a type function.

I don’t understand this.  What would 1.random() do?


> As for picking a random enum, see the previous bit about picking a random 
> bool. And that will get even easier once we get the patch where enums have a 
> static value listing all their cases, such as “CardSuits.allValues.random()”.

This would use .randomElement().  I think it is important to have a different 
name for generating a random value and picking a random element from a 
collection to avoid conflating the two.


Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
 result from the closed range. Closed Range is never empty.
>>> 
>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
>> 
>> You didn’t have to specify it twice.  You used integer literals for the 
>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>> that we require a closed range, which would mean you would have to do 
>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>> empty.
> 
> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
> easier to change the type, and it doesn’t require me to know a priori the 
> type of the range I’m dealing with.


I think you could have both Int.random(in: 0…9) and (0…9).randomElement() 
without issue.  You could even argue for conditionally conforming ranges and 
allowing (0…9).random(), though it might be a harder sell.

Note that Int.random(in:) returns an ‘Int', and Range.randomElement() 
returns an ‘Int?'

Thanks,
Jon



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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Martin Waitz via swift-evolution
Hello Jonathan,

> For collections, I think we should call returning a random element 
> -randomElement, and choosing a random element without replacement 
> -popRandomElement

I disagree because I don’t think that the random data is a property of the 
collection.
The collection is not the subject which has random elements, it’s more the 
object which is used when drawing an element.

> var list = [1,2,3,4]
> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
> one of the elements

Instead I would prefer to have something like:

let a = random.draw(from: list)

> let b:Int? = list.popRandomElement //Now list contains all the elements 
> except the one in ‚b’

we already have remove(at:), this can be used trivially:

let b = list.remove(at: random.draw(from: list.indices))

a little bit more verbose, but easily understandable.
It uses well known building blocks and does not increase the API surface of 
collections.

— Martin

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread TellowKrinkle via swift-evolution
Don’t forget that if you already know the type, you can leave out the type 
name, so for example, to supply a random bool a function, you could just use 
`.random()` instead of `Bool.random()`, which removes a lot of the extra 
redundant type names.

> 2017/11/30 17:19、Dave DeLong のメール:
> 
> 
> 
>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull > > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 1:58 PM, Dave DeLong >> > wrote:
>>> 
>>> 
>>> 
 On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
 > wrote:
 
 I would personally go with:
 
Int.random //Returns a random Int
>>> 
>>> “Type.random” is so rarely used as to not be worth the addition, IMO. If 
>>> you really need a random element from the *entire* domain, then I think you 
>>> should have to manually create the ClosedRange yourself.
>> 
>> What evidence do you have that this will not be used often?  There are many 
>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
>> example, would definitely require Bool.Random.  I certainly use the full 
>> range of UInt and UInt8 on a regular basis (less so with Int).
> 
> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
> “[true, false].random()”
> 
> As for evidence… my own experience. Other than small-value types (like Bool), 
> it is *exceptionally* rare to come across a situation where you need a random 
> from the entire range. Random colors  are interesting, but are rare because 
> they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
> Ints are maybe useful, but again, you almost always need a random Int from a 
> range of possible values.
> 
>> 
>> I think it is important to have Type.random as the base because there are 
>> many types which would conform (not just Int & Double).  For example, I 
>> might have an enum which returns a random case from MyEnum.random.  How 
>> would you do that if random(in:) was the required base?
> 
> I actually don’t think there should be a static “random()” method. I think it 
> should be a member function, not a type function.
> 
> As for picking a random enum, see the previous bit about picking a random 
> bool. And that will get even easier once we get the patch where enums have a 
> static value listing all their cases, such as “CardSuits.allValues.random()”.
> 
>> 
>> 
>>> 
Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
 result from the closed range. Closed Range is never empty.
>>> 
>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
>> 
>> You didn’t have to specify it twice.  You used integer literals for the 
>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>> that we require a closed range, which would mean you would have to do 
>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>> empty.
> 
> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
> easier to change the type, and it doesn’t require me to know a priori the 
> type of the range I’m dealing with.
> 
> Dave

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu  wrote:
> 
> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
> > wrote:
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>> I would personally go with:
>> 
>>  Int.random //Returns a random Int
> 
> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
> really need a random element from the *entire* domain, then I think you 
> should have to manually create the ClosedRange yourself.
> 
>>  Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>> result from the closed range. Closed Range is never empty.
> 
> This is redundant. In order to pick a random element, you’re saying I should 
> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
> specify Int twice: once for the “.random” call, and again for the type of the 
> range. We can do better than that.
> 
>>  [0,2,3].randomElement //Returns a random element from the collection
> 
> I strongly believe this should be a method, not a property. Properties, like 
> .first and .last, are expected to return the same value each time you access 
> them. “.random” inherently breaks that.
>  
> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
> conclusions above, and for substantially the same reasons.
>> 
>> Then a version of each with a ‘using:’ parameter which takes a 
>> generator/source:
>> 
>>  Int.random(using: RandomSource) //Returns a random Int using the given 
>> source of randomness
>>  Int.random(in: ClosedRange, using: RandomSource)
>>  [0,2,3].randomElement(using: RandomSource)
>> 
>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>> random colors and sizes as well.  The issue there is that you really want a 
>> closed range for each dimension. I wish Swift had a better notion of 
>> dimensionality baked into the language. 
>> 
>> What I ended up doing was having a “constraints” parameter which took an 
>> array of constraints which corresponded to various dimensions.  It works for 
>> me, but it might be a bit complex for something in the standard library.
>> 
>> Honestly, given the current capabilities of Swift what this really calls for 
>> is custom initializers/functions for dimensional types:
>> 
>>  UIColor.random //This comes from the protocol
>>  UIColor.random(hue: ClosedRange = 0…1, saturation: 
>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>> ClosedRange = 1…1)
>>  //…and of course the same as above, but with ‘using:'
>> 
>> Then you can easily get random colors which look like they belong together:
>>  
>>  let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>> 
>> There would probably also be a convenience version taking CGFloats and 
>> passing them to the real function as ranges:
>> 
>>  let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>> 
>> 
>> This means that our default RandomSource needs to be publicly available, so 
>> that the custom functions can use it as the default…
> 
> 
> It does not. Having actually implemented some version of these APIs, it's 
> readily apparent now to me that all custom types can simply call 
> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or whatever 
> else we want to have in the standard library) to get random values from the 
> default RNG for any built-in type and size. The actual default random need 
> never be exposed publicly, and since its functions are strictly redundant to 
> these other APIs (which, of course, are the "currency" APIs that our purpose 
> here is to design and make public), the default random is required only for 
> internal implementation of the "currency" APIs and (a) is better off *not* 
> exposed; (b) doesn't need to be of the same type as other RNGs, conform to 
> the same protocols, or for that matter, does not even need to be a type or be 
> written in Swift.

I have also implemented some version of these APIs, both for Random and 
RepeatablyRandom sources.

I get what you are saying about just being able to use the constructs from Int, 
etc…, but we still need a public default.  Let me give a concrete example of 
CGSize.  Yes, we want to just use CGFloat’s random, but if we don’t have a 
publicly available way to call the default then we have to implement the same 
algorithm twice, which is problematic. (Code written in Mail)

static func random(width widthRange: ClosedRange, height heightRange: 
ClosedRange, using source: RandomSource = .default) -> CGSize {
let w = CGFloat.random(in: widthRange, using: source)
let h = CGFloat.random(in: heightRange, using: source)
return CGSize(width: w, height: h)
}

Without the default I would have to have a second version which used 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Nate Cook via swift-evolution
> On Nov 30, 2017, at 4:30 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
> > wrote:
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>> I would personally go with:
>> 
>>  Int.random //Returns a random Int
> 
> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
> really need a random element from the *entire* domain, then I think you 
> should have to manually create the ClosedRange yourself.
> 
>>  Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>> result from the closed range. Closed Range is never empty.
> 
> This is redundant. In order to pick a random element, you’re saying I should 
> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
> specify Int twice: once for the “.random” call, and again for the type of the 
> range. We can do better than that.

I don’t see how this is redundant—do you mean that you’d need to write out the 
type name instead of writing `(0..<10).random()!`? I continue to be of the 
opinion that picking a random integer/floating-point value/Boolean and picking 
a random element from a collection are two different operations. Yes, there’s 
overlap between the two, but they’re different enough that having two ways to 
choose an integer between 0 and 10 would be fine.

>>  [0,2,3].randomElement //Returns a random element from the collection
> 
> I strongly believe this should be a method, not a property. Properties, like 
> .first and .last, are expected to return the same value each time you access 
> them. “.random” inherently breaks that.
>  
> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
> conclusions above, and for substantially the same reasons.
>> 
>> Then a version of each with a ‘using:’ parameter which takes a 
>> generator/source:
>> 
>>  Int.random(using: RandomSource) //Returns a random Int using the given 
>> source of randomness
>>  Int.random(in: ClosedRange, using: RandomSource)
>>  [0,2,3].randomElement(using: RandomSource)
>> 
>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>> random colors and sizes as well.  The issue there is that you really want a 
>> closed range for each dimension. I wish Swift had a better notion of 
>> dimensionality baked into the language. 
>> 
>> What I ended up doing was having a “constraints” parameter which took an 
>> array of constraints which corresponded to various dimensions.  It works for 
>> me, but it might be a bit complex for something in the standard library.
>> 
>> Honestly, given the current capabilities of Swift what this really calls for 
>> is custom initializers/functions for dimensional types:
>> 
>>  UIColor.random //This comes from the protocol
>>  UIColor.random(hue: ClosedRange = 0…1, saturation: 
>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>> ClosedRange = 1…1)
>>  //…and of course the same as above, but with ‘using:'
>> 
>> Then you can easily get random colors which look like they belong together:
>>  
>>  let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>> 
>> There would probably also be a convenience version taking CGFloats and 
>> passing them to the real function as ranges:
>> 
>>  let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>> 
>> 
>> This means that our default RandomSource needs to be publicly available, so 
>> that the custom functions can use it as the default…
> 
> 
> It does not. Having actually implemented some version of these APIs, it's 
> readily apparent now to me that all custom types can simply call 
> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or whatever 
> else we want to have in the standard library) to get random values from the 
> default RNG for any built-in type and size. The actual default random need 
> never be exposed publicly, and since its functions are strictly redundant to 
> these other APIs (which, of course, are the "currency" APIs that our purpose 
> here is to design and make public), the default random is required only for 
> internal implementation of the "currency" APIs and (a) is better off *not* 
> exposed; (b) doesn't need to be of the same type as other RNGs, conform to 
> the same protocols, or for that matter, does not even need to be a type or be 
> written in Swift.

Assuming we have two versions of whatever new random operations we add, where 
one takes an RNG as a parameter and the other uses the default, how would I add 
functionality that matches this pattern in my own code? The standard library 
would look have code like this:

extension MutableCollection {
func shuffle(using rng: RNG) {
// shuffle the elements
}

   

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

2017-11-30 Thread Benjamin G via swift-evolution
On Thu, Nov 30, 2017 at 10:48 PM, Paul Cantrell via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 30, 2017, at 3:40 PM, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Nov 30, 2017, at 1:01 PM, Zach Wolfe 
> wrote:
>
> Doug and others have brought up some great points, and I think Doug’s idea
> of a common infrastructure for importing declarations from other languages
> is _extremely_ attractive for the long-term future of Swift.
>
> However, unlike this proposal, that will (I imagine as a non-compiler
> engineer) be a colossal undertaking, and as such it’s not going to make it
> into Swift 5, or possibly even 6 or 7. I understand, then, Chris’s (and
> other’s) desire to start interfacing with Python code now, not later. For
> me, far and away the biggest problem with this proposal (and the only
> outright deal-breaker) is that dynamic member lookups do not differentiate
> themselves in any way from statically-checked member lookups syntactically.
> I don’t object as strongly as others to the idea of adding this kind of
> dynamism to the language, but if it’s going to be there, it should not be
> possible to slightly misspell a static member name and end up with an
> unexpectedly dynamic member that may or may not fail at compile-time.
>
>
> As noted at the end of my message, I think one can write a Swift library
> to make working with the Python runtime much easier, and write a wrapper
> generator that produces Swift APIs from Python code that use said Swift
> library.
>
>
> That might be true for Python; I’m quite certain it’s not the case for
> Ruby or JS as they exist in the wild. However…
>
> At the risk of stating a universally unpopular opinion, beyond interop
> with dynamic languages such as Python, there’s also value in dynamic member
> lookup for •purely Swift-centric• reasons.
>
> I say this with mixed feelings. I share Douglas’s concerns about breaking
> Swift’s safety bubble. I like it that the language generally makes it clear
> •at the point of use• which language features have runtime pitfalls that
> the compiler cannot check. The points where this is not true of the
> language (e.g. array subscripts) always feel a bit gritty between the teeth.
>
> There can, however, be great value in constructing type membership at
> runtime. The ergonomic access to JSON that’s been discussed in this
> proposal is nothing to sneeze at. Dynamic languages make for lovely DSLs in
> a way that fully statically type checked languages never do. Things like
> Rails’s programmatically generated named routes (e.g. “user_post_path(id)”
> because routing configuration created a user resource with nested posts)
> are possible to approximate with statically typed approaches — but only
> clumsily, never with the same expressiveness and concision.
>

I'm sorry but, no. Please, don't bring ruby magic and "lovely DSL"  found
in dynamic languages into swift right now. I've had my share of dynamic
programming as well, mostly python and javascript, and i think it's now
pretty clear they make wonderful 20 lines scripts, but horrible 20 folders
projects languages. Typescript and python type annotations aren't taking
off for no reason (and if you look even further, in the case of client-side
javascript, the "hype" is going to language even stricter like elm).

The "JSON parsing" example given in the proposal is actually a perfect
example of what could go wrong if we were to add that to swift : people
will have the choice of declaring an actual struct as well as parsing
annotations (and by doing so, create an actual *documentation* and
"contract", somewhere, of what to expect). Or they'll just use dynamic
magic, and spread field accesss looking like real properties a little
everywhere in the code. And i know very well what choice they'll take.

On the other hand, if we wanted to add some "magic like" behavior, i have
an intuition (but that's just what it is, since i'm not coding compilers
for a living), that having a proper macro systems, or higher order types,
as well as good enough tooling to generate bridges to other languages, we
could be both type safe, and terse.

Actually, if people really feel the urge the interface with dynamic
language with a "dynamic feel", i'm not even sure something like a
"SwiftScript" fork wouldn't be a better idea than just try to cram python
behaviors into a statically typed language.



>
> I don’t mean to sneeze at the downside of dynamic typing either. They too
> are nothing to sneeze at. I’ve spent many years on both sides of the
> dynamic divide, and all I see is difficult tradeoffs.
>
> Swift so far has said that dynamism isn’t worth the tradeoffs; it’s
> aggressively avoided even robust runtime reflection, much less dynamic
> dispatch. That may indeed be the right call for the language — but I’m not
> easily convinced there isn’t room to open the door wider.
>
> I think of Chris’s post back in the early 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 4:08 PM, Jonathan Hull  wrote:
> 
> 
>> On Nov 30, 2017, at 1:58 PM, Dave DeLong > > wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
> 
> What evidence do you have that this will not be used often?  There are many 
> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
> example, would definitely require Bool.Random.  I certainly use the full 
> range of UInt and UInt8 on a regular basis (less so with Int).

Bool doesn’t necessarily need “Bool.random”. You just just as easily do “[true, 
false].random()”

As for evidence… my own experience. Other than small-value types (like Bool), 
it is *exceptionally* rare to come across a situation where you need a random 
from the entire range. Random colors  are interesting, but are rare because 
they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
Ints are maybe useful, but again, you almost always need a random Int from a 
range of possible values.

> 
> I think it is important to have Type.random as the base because there are 
> many types which would conform (not just Int & Double).  For example, I might 
> have an enum which returns a random case from MyEnum.random.  How would you 
> do that if random(in:) was the required base?

I actually don’t think there should be a static “random()” method. I think it 
should be a member function, not a type function.

As for picking a random enum, see the previous bit about picking a random bool. 
And that will get even easier once we get the patch where enums have a static 
value listing all their cases, such as “CardSuits.allValues.random()”.

> 
> 
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
> 
> You didn’t have to specify it twice.  You used integer literals for the 
> range, which you could also do for Double or CGFloat.  Also, I am proposing 
> that we require a closed range, which would mean you would have to do 
> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
> empty.

“0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
easier to change the type, and it doesn’t require me to know a priori the type 
of the range I’m dealing with.

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Erica Sadun via swift-evolution
I agree that the RNG should be public. GameplayKit uses customizable 
distributions including normal and uniform.

https://developer.apple.com/library/content/documentation/General/Conceptual/GameplayKit_Guide/RandomSources.html

-- E

> On Nov 30, 2017, at 4:03 PM, TellowKrinkle via swift-evolution 
>  wrote:
> 
> Whether or not it’s possible to hide, I think that the default RNG should be 
> exposed publicly, so that functions like `CustomType.random(using:)` will 
> take a RandomSource property instead of just using the system RNG, allowing 
> someone to specify a different RNG (maybe a seedable PRNG for example) to 
> suit their needs.
> 
>> 2017/11/30 16:30、Xiaodi Wu > >のメール:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
>> 
>>> [0,2,3].randomElement //Returns a random element from the collection
>> 
>> I strongly believe this should be a method, not a property. Properties, like 
>> .first and .last, are expected to return the same value each time you access 
>> them. “.random” inherently breaks that.
>>  
>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>> conclusions above, and for substantially the same reasons.
>>> 
>>> Then a version of each with a ‘using:’ parameter which takes a 
>>> generator/source:
>>> 
>>> Int.random(using: RandomSource) //Returns a random Int using the given 
>>> source of randomness
>>> Int.random(in: ClosedRange, using: RandomSource)
>>> [0,2,3].randomElement(using: RandomSource)
>>> 
>>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>>> random colors and sizes as well.  The issue there is that you really want a 
>>> closed range for each dimension. I wish Swift had a better notion of 
>>> dimensionality baked into the language. 
>>> 
>>> What I ended up doing was having a “constraints” parameter which took an 
>>> array of constraints which corresponded to various dimensions.  It works 
>>> for me, but it might be a bit complex for something in the standard library.
>>> 
>>> Honestly, given the current capabilities of Swift what this really calls 
>>> for is custom initializers/functions for dimensional types:
>>> 
>>> UIColor.random //This comes from the protocol
>>> UIColor.random(hue: ClosedRange = 0…1, saturation: 
>>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>>> ClosedRange = 1…1)
>>> //…and of course the same as above, but with ‘using:'
>>> 
>>> Then you can easily get random colors which look like they belong together:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>> 
>>> There would probably also be a convenience version taking CGFloats and 
>>> passing them to the real function as ranges:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>> 
>>> 
>>> This means that our default RandomSource needs to be publicly available, so 
>>> that the custom functions can use it as the default…
>> 
>> 
>> It does not. Having actually implemented some version of these APIs, it's 
>> readily apparent now to me that all custom types can simply call 
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>> whatever else we want to have in the standard library) to get random values 
>> from the default RNG for any built-in type and size. The actual default 
>> random need never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
>> 
>> 
>>  
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
 On Nov 27, 2017, at 10:14 AM, 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution
Agreed.  Type.random should call Type.random(using:) with the (publicly 
available) default.  In fact, if we wanted to make it Type.random() it should 
basically be the default value of ‘using:’

Thanks,
Jon


> On Nov 30, 2017, at 3:03 PM, TellowKrinkle  wrote:
> 
> Whether or not it’s possible to hide, I think that the default RNG should be 
> exposed publicly, so that functions like `CustomType.random(using:)` will 
> take a RandomSource property instead of just using the system RNG, allowing 
> someone to specify a different RNG (maybe a seedable PRNG for example) to 
> suit their needs.
> 
>> 2017/11/30 16:30、Xiaodi Wu > >のメール:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
>> 
>>> [0,2,3].randomElement //Returns a random element from the collection
>> 
>> I strongly believe this should be a method, not a property. Properties, like 
>> .first and .last, are expected to return the same value each time you access 
>> them. “.random” inherently breaks that.
>>  
>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>> conclusions above, and for substantially the same reasons.
>>> 
>>> Then a version of each with a ‘using:’ parameter which takes a 
>>> generator/source:
>>> 
>>> Int.random(using: RandomSource) //Returns a random Int using the given 
>>> source of randomness
>>> Int.random(in: ClosedRange, using: RandomSource)
>>> [0,2,3].randomElement(using: RandomSource)
>>> 
>>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>>> random colors and sizes as well.  The issue there is that you really want a 
>>> closed range for each dimension. I wish Swift had a better notion of 
>>> dimensionality baked into the language. 
>>> 
>>> What I ended up doing was having a “constraints” parameter which took an 
>>> array of constraints which corresponded to various dimensions.  It works 
>>> for me, but it might be a bit complex for something in the standard library.
>>> 
>>> Honestly, given the current capabilities of Swift what this really calls 
>>> for is custom initializers/functions for dimensional types:
>>> 
>>> UIColor.random //This comes from the protocol
>>> UIColor.random(hue: ClosedRange = 0…1, saturation: 
>>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>>> ClosedRange = 1…1)
>>> //…and of course the same as above, but with ‘using:'
>>> 
>>> Then you can easily get random colors which look like they belong together:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>> 
>>> There would probably also be a convenience version taking CGFloats and 
>>> passing them to the real function as ranges:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>> 
>>> 
>>> This means that our default RandomSource needs to be publicly available, so 
>>> that the custom functions can use it as the default…
>> 
>> 
>> It does not. Having actually implemented some version of these APIs, it's 
>> readily apparent now to me that all custom types can simply call 
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>> whatever else we want to have in the standard library) to get random values 
>> from the default RNG for any built-in type and size. The actual default 
>> random need never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
>> 
>> 
>>  
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
 On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 1:58 PM, Dave DeLong  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>> I would personally go with:
>> 
>>  Int.random //Returns a random Int
> 
> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
> really need a random element from the *entire* domain, then I think you 
> should have to manually create the ClosedRange yourself.

What evidence do you have that this will not be used often?  There are many 
types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
example, would definitely require Bool.Random.  I certainly use the full range 
of UInt and UInt8 on a regular basis (less so with Int).

I think it is important to have Type.random as the base because there are many 
types which would conform (not just Int & Double).  For example, I might have 
an enum which returns a random case from MyEnum.random.  How would you do that 
if random(in:) was the required base?


> 
>>  Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>> result from the closed range. Closed Range is never empty.
> 
> This is redundant. In order to pick a random element, you’re saying I should 
> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
> specify Int twice: once for the “.random” call, and again for the type of the 
> range. We can do better than that.

You didn’t have to specify it twice.  You used integer literals for the range, 
which you could also do for Double or CGFloat.  Also, I am proposing that we 
require a closed range, which would mean you would have to do Int.random(0…9).  
Otherwise we have to deal with ranges which are possibly empty.

> 
>>  [0,2,3].randomElement //Returns a random element from the collection
> 
> I strongly believe this should be a method, not a property. Properties, like 
> .first and .last, are expected to return the same value each time you access 
> them. “.random” inherently breaks that.

I don’t have a strong opinion on this. I would be ok with methods.

> 
>> 
>> Then a version of each with a ‘using:’ parameter which takes a 
>> generator/source:
>> 
>>  Int.random(using: RandomSource) //Returns a random Int using the given 
>> source of randomness
>>  Int.random(in: ClosedRange, using: RandomSource)
>>  [0,2,3].randomElement(using: RandomSource)
>> 
>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>> random colors and sizes as well.  The issue there is that you really want a 
>> closed range for each dimension. I wish Swift had a better notion of 
>> dimensionality baked into the language. 
>> 
>> What I ended up doing was having a “constraints” parameter which took an 
>> array of constraints which corresponded to various dimensions.  It works for 
>> me, but it might be a bit complex for something in the standard library.
>> 
>> Honestly, given the current capabilities of Swift what this really calls for 
>> is custom initializers/functions for dimensional types:
>> 
>>  UIColor.random //This comes from the protocol
>>  UIColor.random(hue: ClosedRange = 0…1, saturation: 
>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>> ClosedRange = 1…1)
>>  //…and of course the same as above, but with ‘using:'
>> 
>> Then you can easily get random colors which look like they belong together:
>>  
>>  let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>> 
>> There would probably also be a convenience version taking CGFloats and 
>> passing them to the real function as ranges:
>> 
>>  let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>> 
>> 
>> This means that our default RandomSource needs to be publicly available, so 
>> that the custom functions can use it as the default…
> 
>  
> 
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>> > wrote:
>>> 
>>> You say that all the `.random`s have different semantics, but to me (at 
>>> least), they are all very similar.  All the methods can be summarized as 
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> `Int.random` has no range, but selects a single element from the collection 
>>> of all ints (equivalent to if the above method had a default value for its 
>>> range)
>>> So to me these are all doing the same operation, just with different types 
>>> of inputs
>>> 
 2017/11/24 20:07、Alejandro Alonso >のメール:
 
 
 - Alejandro
 
 -- Forwarded message --
 From: Xiaodi Wu 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread TellowKrinkle via swift-evolution
Whether or not it’s possible to hide, I think that the default RNG should be 
exposed publicly, so that functions like `CustomType.random(using:)` will take 
a RandomSource property instead of just using the system RNG, allowing someone 
to specify a different RNG (maybe a seedable PRNG for example) to suit their 
needs.

> 2017/11/30 16:30、Xiaodi Wu のメール:
> 
> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
> > wrote:
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>> I would personally go with:
>> 
>>  Int.random //Returns a random Int
> 
> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
> really need a random element from the *entire* domain, then I think you 
> should have to manually create the ClosedRange yourself.
> 
>>  Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>> result from the closed range. Closed Range is never empty.
> 
> This is redundant. In order to pick a random element, you’re saying I should 
> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
> specify Int twice: once for the “.random” call, and again for the type of the 
> range. We can do better than that.
> 
>>  [0,2,3].randomElement //Returns a random element from the collection
> 
> I strongly believe this should be a method, not a property. Properties, like 
> .first and .last, are expected to return the same value each time you access 
> them. “.random” inherently breaks that.
>  
> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
> conclusions above, and for substantially the same reasons.
>> 
>> Then a version of each with a ‘using:’ parameter which takes a 
>> generator/source:
>> 
>>  Int.random(using: RandomSource) //Returns a random Int using the given 
>> source of randomness
>>  Int.random(in: ClosedRange, using: RandomSource)
>>  [0,2,3].randomElement(using: RandomSource)
>> 
>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>> random colors and sizes as well.  The issue there is that you really want a 
>> closed range for each dimension. I wish Swift had a better notion of 
>> dimensionality baked into the language. 
>> 
>> What I ended up doing was having a “constraints” parameter which took an 
>> array of constraints which corresponded to various dimensions.  It works for 
>> me, but it might be a bit complex for something in the standard library.
>> 
>> Honestly, given the current capabilities of Swift what this really calls for 
>> is custom initializers/functions for dimensional types:
>> 
>>  UIColor.random //This comes from the protocol
>>  UIColor.random(hue: ClosedRange = 0…1, saturation: 
>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>> ClosedRange = 1…1)
>>  //…and of course the same as above, but with ‘using:'
>> 
>> Then you can easily get random colors which look like they belong together:
>>  
>>  let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>> 
>> There would probably also be a convenience version taking CGFloats and 
>> passing them to the real function as ranges:
>> 
>>  let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>> 
>> 
>> This means that our default RandomSource needs to be publicly available, so 
>> that the custom functions can use it as the default…
> 
> 
> It does not. Having actually implemented some version of these APIs, it's 
> readily apparent now to me that all custom types can simply call 
> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or whatever 
> else we want to have in the standard library) to get random values from the 
> default RNG for any built-in type and size. The actual default random need 
> never be exposed publicly, and since its functions are strictly redundant to 
> these other APIs (which, of course, are the "currency" APIs that our purpose 
> here is to design and make public), the default random is required only for 
> internal implementation of the "currency" APIs and (a) is better off *not* 
> exposed; (b) doesn't need to be of the same type as other RNGs, conform to 
> the same protocols, or for that matter, does not even need to be a type or be 
> written in Swift.
> 
> 
>  
> 
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>> > wrote:
>>> 
>>> You say that all the `.random`s have different semantics, but to me (at 
>>> least), they are all very similar.  All the methods can be summarized as 
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> 

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

2017-11-30 Thread Matthew Johnson via swift-evolution

> On Nov 30, 2017, at 3:48 PM, Paul Cantrell via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 3:40 PM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 1:01 PM, Zach Wolfe >> > wrote:
>>> 
>>> Doug and others have brought up some great points, and I think Doug’s idea 
>>> of a common infrastructure for importing declarations from other languages 
>>> is _extremely_ attractive for the long-term future of Swift. 
>>> 
>>> However, unlike this proposal, that will (I imagine as a non-compiler 
>>> engineer) be a colossal undertaking, and as such it’s not going to make it 
>>> into Swift 5, or possibly even 6 or 7. I understand, then, Chris’s (and 
>>> other’s) desire to start interfacing with Python code now, not later. For 
>>> me, far and away the biggest problem with this proposal (and the only 
>>> outright deal-breaker) is that dynamic member lookups do not differentiate 
>>> themselves in any way from statically-checked member lookups syntactically. 
>>> I don’t object as strongly as others to the idea of adding this kind of 
>>> dynamism to the language, but if it’s going to be there, it should not be 
>>> possible to slightly misspell a static member name and end up with an 
>>> unexpectedly dynamic member that may or may not fail at compile-time.
>> 
>> As noted at the end of my message, I think one can write a Swift library to 
>> make working with the Python runtime much easier, and write a wrapper 
>> generator that produces Swift APIs from Python code that use said Swift 
>> library.
> 
> That might be true for Python; I’m quite certain it’s not the case for Ruby 
> or JS as they exist in the wild. However…
> 
> At the risk of stating a universally unpopular opinion, beyond interop with 
> dynamic languages such as Python, there’s also value in dynamic member lookup 
> for •purely Swift-centric• reasons.
> 
> I say this with mixed feelings. I share Douglas’s concerns about breaking 
> Swift’s safety bubble. I like it that the language generally makes it clear 
> •at the point of use• which language features have runtime pitfalls that the 
> compiler cannot check. The points where this is not true of the language 
> (e.g. array subscripts) always feel a bit gritty between the teeth.
> 
> There can, however, be great value in constructing type membership at 
> runtime. The ergonomic access to JSON that’s been discussed in this proposal 
> is nothing to sneeze at. Dynamic languages make for lovely DSLs in a way that 
> fully statically type checked languages never do. Things like Rails’s 
> programmatically generated named routes (e.g. “user_post_path(id)” because 
> routing configuration created a user resource with nested posts) are possible 
> to approximate with statically typed approaches — but only clumsily, never 
> with the same expressiveness and concision.
> 
> I don’t mean to sneeze at the downside of dynamic typing either. They too are 
> nothing to sneeze at. I’ve spent many years on both sides of the dynamic 
> divide, and all I see is difficult tradeoffs.
> 
> Swift so far has said that dynamism isn’t worth the tradeoffs; it’s 
> aggressively avoided even robust runtime reflection, much less dynamic 
> dispatch. That may indeed be the right call for the language — but I’m not 
> easily convinced there isn’t room to open the door wider.
> 
> I think of Chris’s post back in the early days of this list about the 
> “programmer model” the language creates, and wonder if there’s a way we can’t 
> make a model that leaves the door open to this kind of dynamic dispatch where 
> it makes sense for the people and situation at hand, while still staying true 
> to the language’s spirit of “compile-time safety by default, exceptions to 
> that by intent at point of use.”
> 
> Opening the door to dynamism might take some of the flavor of the way the 
> language currently handles unsafe memory access: it’s possible and even 
> reasonably ergonomic, but you always know when you’ve crossed the Rubicon 
> into Dangerland.

I would really like to see Swift gain more dynamic capabilities eventually.  I 
wrote a lot of Ruby years ago and really enjoyed some aspects of it. 

On the other hand, I do want to see us be very deliberate about adding them and 
do it in the right way and only when we are confident that we have identified 
the right feature(s) and designs for them.  If that means waiting a while I 
would rather wait than have regrets later.  If we can identify a design that 
feels appropriate for Swift and decide now is the time to introduce it I will 
be happy with that, but the timeline shouldn’t be prioritized higher than 
getting the design right.

The absolute minimum criteria I have for something I would consider worth 
taking a close look at is making dynamic member lookup clear at the call 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Xiaodi Wu via swift-evolution
On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I would personally go with:
>
> Int.random //Returns a random Int
>
>
> “Type.random” is so rarely used as to not be worth the addition, IMO. If
> you really need a random element from the *entire* domain, then I think you
> should have to manually create the ClosedRange yourself.
>
> Int.random(in: ClosedRange) //Works for Comparable types. Gives a
> result from the closed range. Closed Range is never empty.
>
>
> This is redundant. In order to pick a random element, you’re saying I
> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I
> have to specify Int twice: once for the “.random” call, and again for the
> type of the range. We can do better than that.
>
> [0,2,3].randomElement //Returns a random element from the collection
>
>
> I strongly believe this should be a method, not a property. Properties,
> like .first and .last, are expected to return the same value each time you
> access them. “.random” inherently breaks that.
>

FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's
conclusions above, and for substantially the same reasons.

>
> Then a version of each with a ‘using:’ parameter which takes a
> generator/source:
>
> Int.random(using: RandomSource) //Returns a random Int using the given
> source of randomness
> Int.random(in: ClosedRange, using: RandomSource)
> [0,2,3].randomElement(using: RandomSource)
>
> In my own RandomSource & RandomSourceCreatable protocols, I frequently use
> random colors and sizes as well.  The issue there is that you really want a
> closed range for each dimension. I wish Swift had a better notion of
> dimensionality baked into the language.
>
> What I ended up doing was having a “constraints” parameter which took an
> array of constraints which corresponded to various dimensions.  It works
> for me, but it might be a bit complex for something in the standard library.
>
> Honestly, given the current capabilities of Swift what this really calls
> for is custom initializers/functions for dimensional types:
>
> UIColor.random //This comes from the protocol
> UIColor.random(hue: ClosedRange = 0…1, saturation:
> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha:
> ClosedRange = 1…1)
> //…and of course the same as above, but with ‘using:'
>
> Then you can easily get random colors which look like they belong together:
> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6)
>
> There would probably also be a convenience version taking CGFloats and
> passing them to the real function as ranges:
>
> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>
>
> This means that our default RandomSource needs to be publicly available,
> so that the custom functions can use it as the default…
>
>
It does not. Having actually implemented some version of these APIs, it's
readily apparent now to me that all custom types can simply call
Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or
whatever else we want to have in the standard library) to get random values
from the default RNG for any built-in type and size. The actual default
random need never be exposed publicly, and since its functions are strictly
redundant to these other APIs (which, of course, are the "currency" APIs
that our purpose here is to design and make public), the default random is
required only for internal implementation of the "currency" APIs and (a) is
better off *not* exposed; (b) doesn't need to be of the same type as other
RNGs, conform to the same protocols, or for that matter, does not even need
to be a type or be written in Swift.



>
>
> Thanks,
> Jon
>
>
> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> You say that all the `.random`s have different semantics, but to me (at
> least), they are all very similar.  All the methods can be summarized as
> selecting a single random element from a collection
> `[0, 2, 3].random` selects a single element from the given collection
> `Int.random(in: 0…8)` selects a single element from the given range
> `Int.random` has no range, but selects a single element from the
> collection of all ints (equivalent to if the above method had a default
> value for its range)
> So to me these are all doing the same operation, just with different types
> of inputs
>
> 2017/11/24 20:07、Alejandro Alonso のメール:
>
>
> - Alejandro
>
> -- Forwarded message --
> *From:* Xiaodi Wu 
> *Date:* Nov 24, 2017, 3:05 PM -0600
> *To:* Alejandro Alonso 
> *Cc:* Brent Royal-Gordon , Steve Canon via
> swift-evolution 
> *Subject:* Re: [swift-evolution] [Proposal] Random Unification
>
> On Fri, Nov 24, 2017 at 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Dave DeLong via swift-evolution
On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution  wrote:I would personally go with:	Int.random //Returns a random Int“Type.random” is so rarely used as to not be worth the addition, IMO. If you really need a random element from the *entire* domain, then I think you should have to manually create the ClosedRange yourself.	Int.random(in: ClosedRange) //Works for Comparable types. Gives a result from the closed range. Closed Range is never empty.This is redundant. In order to pick a random element, you’re saying I should have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to specify Int twice: once for the “.random” call, and again for the type of the range. We can do better than that.	[0,2,3].randomElement //Returns a random element from the collectionI strongly believe this should be a method, not a property. Properties, like .first and .last, are expected to return the same value each time you access them. “.random” inherently breaks that.Then a version of each with a ‘using:’ parameter which takes a generator/source:	Int.random(using: RandomSource) //Returns a random Int using the given source of randomness	Int.random(in: ClosedRange, using: RandomSource)	[0,2,3].randomElement(using: RandomSource)In my own RandomSource & RandomSourceCreatable protocols, I frequently use random colors and sizes as well.  The issue there is that you really want a closed range for each dimension. I wish Swift had a better notion of dimensionality baked into the language. What I ended up doing was having a “constraints” parameter which took an array of constraints which corresponded to various dimensions.  It works for me, but it might be a bit complex for something in the standard library.Honestly, given the current capabilities of Swift what this really calls for is custom initializers/functions for dimensional types:	UIColor.random //This comes from the protocol	UIColor.random(hue: ClosedRange = 0…1, saturation: ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: ClosedRange = 1…1)	//…and of course the same as above, but with ‘using:'Then you can easily get random colors which look like they belong together:		let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) There would probably also be a convenience version taking CGFloats and passing them to the real function as ranges:	let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)This means that our default RandomSource needs to be publicly available, so that the custom functions can use it as the default… Thanks,JonOn Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution  wrote:You say that all the `.random`s have different semantics, but to me (at least), they are all very similar.  All the methods can be summarized as selecting a single random element from a collection`[0, 2, 3].random` selects a single element from the given collection`Int.random(in: 0…8)` selects a single element from the given range`Int.random` has no range, but selects a single element from the collection of all ints (equivalent to if the above method had a default value for its range)So to me these are all doing the same operation, just with different types of inputs2017/11/24 20:07、Alejandro Alonso のメール:







- Alejandro


-- Forwarded message --
From: Xiaodi Wu 
Date: Nov 24, 2017, 3:05 PM -0600
To: Alejandro Alonso 
Cc: Brent Royal-Gordon , Steve Canon via swift-evolution 
Subject: Re: [swift-evolution] [Proposal] Random Unification


On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso 
 wrote:





Regarding naming too many things “random”, I’ve talked to many developers on my end and they all don’t find it confusing. This proposal is aimed to make it obvious what the operation is doing when regarding random. I still agree that the proposed solution does
 just that and in practice feels good to write.




I must disagree quite strongly here. The various facilities you name "random" have different semantics, and differences in semantics should be reflected in differences in names. It doesn't matter that some people don't find it confusing; it is objectively
 the case that you have named multiple distinct facilities with the same name, which leads to confusion. I, for one, get confused, and you can see on this list that people are using arguments about one property named "random" to discuss another property named
 "random". This is quite an intolerable situation.





I disagree that sample is the correct naming to use here. Getting a sample is a verb in this context which would make it break API guidelines just as well as `pick()`. To sample is to “take a sample or samples of (something) for analysis.” I can agree
 to use `sampling()` which follows API guidelines. This would result in the following grammar for 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution
For collections, I think we should call returning a random element 
-randomElement, and choosing a random element without replacement 
-popRandomElement

var list = [1,2,3,4]
let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains one 
of the elements
let b:Int? = list.popRandomElement //Now list contains all the elements except 
the one in ‘b’

Thanks,
Jon

> On Nov 30, 2017, at 10:15 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Right—again, this is yet another difference between two things both named 
> “random” in this proposal. Almost always, when we say “give me two random 
> integers,” we want independent random samples from the set of all integers. 
> But for collections, a very common (and probably more common operation) is to 
> _sample without replacement_. Conflating the two is how hard-to-detect errors 
> arise.
> 
> On Thu, Nov 30, 2017 at 10:29 Martin Waitz via swift-evolution 
> > wrote:
> Hi Erica,
> 
> > Doesn't `choose` usually take two arguments, the `count` to choose 
> > (presumably defaulting to 1) and the collection to choose `from`?
> 
> This might be useful for collections, when you want to draw several elements 
> without drawing the same element twice.
> For ranges of random numbers you usually need independent numbers and just 
> call the generator multiple times.
> Both use cases could be provided as overloads (a default argument would 
> require that the return value has the same type, which would be unfortunate 
> here).
> 
> --
> Martin
> ___
> 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

___
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-11-30 Thread Paul Cantrell via swift-evolution


> On Nov 30, 2017, at 3:40 PM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 1:01 PM, Zach Wolfe > > wrote:
>> 
>> Doug and others have brought up some great points, and I think Doug’s idea 
>> of a common infrastructure for importing declarations from other languages 
>> is _extremely_ attractive for the long-term future of Swift. 
>> 
>> However, unlike this proposal, that will (I imagine as a non-compiler 
>> engineer) be a colossal undertaking, and as such it’s not going to make it 
>> into Swift 5, or possibly even 6 or 7. I understand, then, Chris’s (and 
>> other’s) desire to start interfacing with Python code now, not later. For 
>> me, far and away the biggest problem with this proposal (and the only 
>> outright deal-breaker) is that dynamic member lookups do not differentiate 
>> themselves in any way from statically-checked member lookups syntactically. 
>> I don’t object as strongly as others to the idea of adding this kind of 
>> dynamism to the language, but if it’s going to be there, it should not be 
>> possible to slightly misspell a static member name and end up with an 
>> unexpectedly dynamic member that may or may not fail at compile-time.
> 
> As noted at the end of my message, I think one can write a Swift library to 
> make working with the Python runtime much easier, and write a wrapper 
> generator that produces Swift APIs from Python code that use said Swift 
> library.

That might be true for Python; I’m quite certain it’s not the case for Ruby or 
JS as they exist in the wild. However…

At the risk of stating a universally unpopular opinion, beyond interop with 
dynamic languages such as Python, there’s also value in dynamic member lookup 
for •purely Swift-centric• reasons.

I say this with mixed feelings. I share Douglas’s concerns about breaking 
Swift’s safety bubble. I like it that the language generally makes it clear •at 
the point of use• which language features have runtime pitfalls that the 
compiler cannot check. The points where this is not true of the language (e.g. 
array subscripts) always feel a bit gritty between the teeth.

There can, however, be great value in constructing type membership at runtime. 
The ergonomic access to JSON that’s been discussed in this proposal is nothing 
to sneeze at. Dynamic languages make for lovely DSLs in a way that fully 
statically type checked languages never do. Things like Rails’s 
programmatically generated named routes (e.g. “user_post_path(id)” because 
routing configuration created a user resource with nested posts) are possible 
to approximate with statically typed approaches — but only clumsily, never with 
the same expressiveness and concision.

I don’t mean to sneeze at the downside of dynamic typing either. They too are 
nothing to sneeze at. I’ve spent many years on both sides of the dynamic 
divide, and all I see is difficult tradeoffs.

Swift so far has said that dynamism isn’t worth the tradeoffs; it’s 
aggressively avoided even robust runtime reflection, much less dynamic 
dispatch. That may indeed be the right call for the language — but I’m not 
easily convinced there isn’t room to open the door wider.

I think of Chris’s post back in the early days of this list about the 
“programmer model” the language creates, and wonder if there’s a way we can’t 
make a model that leaves the door open to this kind of dynamic dispatch where 
it makes sense for the people and situation at hand, while still staying true 
to the language’s spirit of “compile-time safety by default, exceptions to that 
by intent at point of use.”

Opening the door to dynamism might take some of the flavor of the way the 
language currently handles unsafe memory access: it’s possible and even 
reasonably ergonomic, but you always know when you’ve crossed the Rubicon into 
Dangerland.

Cheers,

Paul

> 
>   - Doug
> 
>> 
>> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>>> 
>>> 
 On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
 > wrote:
 
 I’d like to formally propose the inclusion of user-defined dynamic member 
 lookup types.
 
 Here is my latest draft of the proposal:
 https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
 
 https://github.com/apple/swift-evolution/pull/768 
 
 
 An implementation of this design is available here:
 https://github.com/apple/swift/pull/13076 
 
 
 The implementation is straight-forward and (IMO) non-invasive in the 
 compiler.
>>> 
>>> 
>>> I think better interoperability 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Jonathan Hull via swift-evolution
I would personally go with:

Int.random //Returns a random Int
Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
result from the closed range. Closed Range is never empty.
[0,2,3].randomElement //Returns a random element from the collection

Then a version of each with a ‘using:’ parameter which takes a generator/source:

Int.random(using: RandomSource) //Returns a random Int using the given 
source of randomness
Int.random(in: ClosedRange, using: RandomSource)
[0,2,3].randomElement(using: RandomSource)

In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
random colors and sizes as well.  The issue there is that you really want a 
closed range for each dimension. I wish Swift had a better notion of 
dimensionality baked into the language. 

What I ended up doing was having a “constraints” parameter which took an array 
of constraints which corresponded to various dimensions.  It works for me, but 
it might be a bit complex for something in the standard library.

Honestly, given the current capabilities of Swift what this really calls for is 
custom initializers/functions for dimensional types:

UIColor.random //This comes from the protocol
UIColor.random(hue: ClosedRange = 0…1, saturation: 
ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
ClosedRange = 1…1)
//…and of course the same as above, but with ‘using:'

Then you can easily get random colors which look like they belong together:

let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 

There would probably also be a convenience version taking CGFloats and passing 
them to the real function as ranges:

let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)


This means that our default RandomSource needs to be publicly available, so 
that the custom functions can use it as the default...

Thanks,
Jon


> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>  wrote:
> 
> You say that all the `.random`s have different semantics, but to me (at 
> least), they are all very similar.  All the methods can be summarized as 
> selecting a single random element from a collection
> `[0, 2, 3].random` selects a single element from the given collection
> `Int.random(in: 0…8)` selects a single element from the given range
> `Int.random` has no range, but selects a single element from the collection 
> of all ints (equivalent to if the above method had a default value for its 
> range)
> So to me these are all doing the same operation, just with different types of 
> inputs
> 
>> 2017/11/24 20:07、Alejandro Alonso > >のメール:
>> 
>> 
>> - Alejandro
>> 
>> -- Forwarded message --
>> From: Xiaodi Wu >
>> Date: Nov 24, 2017, 3:05 PM -0600
>> To: Alejandro Alonso >
>> Cc: Brent Royal-Gordon > >, Steve Canon via swift-evolution 
>> >
>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>> 
>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >> > wrote:
>>> Regarding naming too many things “random”, I’ve talked to many developers 
>>> on my end and they all don’t find it confusing. This proposal is aimed to 
>>> make it obvious what the operation is doing when regarding random. I still 
>>> agree that the proposed solution does just that and in practice feels good 
>>> to write.
>>> 
>>> I must disagree quite strongly here. The various facilities you name 
>>> "random" have different semantics, and differences in semantics should be 
>>> reflected in differences in names. It doesn't matter that some people don't 
>>> find it confusing; it is objectively the case that you have named multiple 
>>> distinct facilities with the same name, which leads to confusion. I, for 
>>> one, get confused, and you can see on this list that people are using 
>>> arguments about one property named "random" to discuss another property 
>>> named "random". This is quite an intolerable situation.
>>> 
>>> I disagree that sample is the correct naming to use here. Getting a sample 
>>> is a verb in this context which would make it break API guidelines just as 
>>> well as `pick()`. To sample is to “take a sample or samples of (something) 
>>> for analysis.” I can agree to use `sampling()` which follows API 
>>> guidelines. This would result in the following grammar for `[“hi”, “hello”, 
>>> “hey”].sampling(2)`, “From array, get a sampling of 2"
>>> 
>>> "Sampling" is fine.
>>> 
>>> 
>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
 On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso 

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

2017-11-30 Thread Douglas Gregor via swift-evolution


> On Nov 30, 2017, at 1:01 PM, Zach Wolfe  wrote:
> 
> Doug and others have brought up some great points, and I think Doug’s idea of 
> a common infrastructure for importing declarations from other languages is 
> _extremely_ attractive for the long-term future of Swift. 
> 
> However, unlike this proposal, that will (I imagine as a non-compiler 
> engineer) be a colossal undertaking, and as such it’s not going to make it 
> into Swift 5, or possibly even 6 or 7. I understand, then, Chris’s (and 
> other’s) desire to start interfacing with Python code now, not later. For me, 
> far and away the biggest problem with this proposal (and the only outright 
> deal-breaker) is that dynamic member lookups do not differentiate themselves 
> in any way from statically-checked member lookups syntactically. I don’t 
> object as strongly as others to the idea of adding this kind of dynamism to 
> the language, but if it’s going to be there, it should not be possible to 
> slightly misspell a static member name and end up with an unexpectedly 
> dynamic member that may or may not fail at compile-time.

As noted at the end of my message, I think one can write a Swift library to 
make working with the Python runtime much easier, and write a wrapper generator 
that produces Swift APIs from Python code that use said Swift library.

- Doug

> 
> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
> > wrote:
> 
>> 
>> 
>>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>> > wrote:
>>> 
>>> I’d like to formally propose the inclusion of user-defined dynamic member 
>>> lookup types.
>>> 
>>> Here is my latest draft of the proposal:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>>> 
>>> https://github.com/apple/swift-evolution/pull/768 
>>> 
>>> 
>>> An implementation of this design is available here:
>>> https://github.com/apple/swift/pull/13076 
>>> 
>>> 
>>> The implementation is straight-forward and (IMO) non-invasive in the 
>>> compiler.
>> 
>> 
>> I think better interoperability with Python (and other OO languages in 
>> widespread use) is a good goal, and I agree that the implementation of the 
>> feature described is straight-forward and not terribly invasive in the 
>> compiler.
>> 
>> However, I do not think this proposal is going in the right direction for 
>> Swift. I have objections on several different grounds.
>> 
>> Philosophy
>> Swift is, unabashedly, a strong statically-typed language. We don’t allow 
>> implicit down casting, we require “as?” so you have to cope with the 
>> possibility of failure (or use “as!” and think hard about the “!”). Even the 
>> gaping hole that is AnyObject dispatch still requires the existence of an 
>> @objc declaration and produces an optional lookup result, so the user must 
>> contend with the potential for dynamic failure. Whenever we discuss adding 
>> more dynamic features to Swift, there’s a strong focus on maintaining that 
>> strong static type system.
>> 
>> IMO, this proposal is a significant departure from the fundamental character 
>> of Swift, because it allows access to possibly-nonexistent members (as well 
>> as calls with incorrect arguments, in the related proposal) without any 
>> indication that the operation might fail. It’s easy to fall through these 
>> cracks for any type that supports DynamicMemberLookupProtocol—a 
>> single-character typo when using a DynamicMemberLookupProtocol-capable type 
>> means you’ve fallen out of the safety that Swift provides. I think that’s a 
>> poor experience for the Python interoperability case, but more on that in 
>> the Tooling section below.
>> 
>> While we shouldn’t necessarily avoid a feature simply because it can be used 
>> distastefully, consider something like this:
>> 
>>  public extension NSObject :  DynamicMemberLookupProtocol, 
>> DynamicCallableProtocol { … }
>> 
>> that goes directly to the Objective-C runtime to resolve member lookups and 
>> calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly 
>> convenient, and one could imagine some mixed Objective-C/Swift code bases 
>> where this would save a lot of typing (of code)… at the cost of losing 
>> static typing in the language. The presence of that one extension means I 
>> can no longer rely on the safety guarantees Swift normally provides, for any 
>> project that imports that extension and uses a subclass of NSObject. At 
>> best, we as a community decide “don’t do that”; at worse, some nontrivial 
>> fraction of the community decides that the benefits outweigh the costs (for 
>> this type or some other), and we can no longer say that Swift is a strong 

Re: [swift-evolution] array splatting for variadic parameters

2017-11-30 Thread Cao, Jiannan via swift-evolution
What happened with this proposal? This looks easy to implement.

func sumOf(numbers: Int...) -> Int {
  ...
  }
typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])

> Hello everyone.
> 
> I understand that topic has already been discussed in the past, but I failed 
> to get any information on its current state of affairs.
> 
> I guess the subject of this mail is explicit, but to make sure I’m clear, 
> here's a small snippet that illustrates the problem:
> 
> func f(args: Int…) {
>   // Some implementation ...
> }
> // Now it's impossible to call f without explicitly naming its parameters.
> 
> For many use-cases, this problem can be solved by overloading f so that it 
> explicitly accepts an array.
> 
> func f(_ args: [Int]) {
>   // Some implementation ...
> }
> 
> func f(_ args: Int…) {
>   f(args)
> }
> 
> Some people also advocate (myself generally included) that one should prefer 
> the signature explicitly marking args as an array, as the syntactic overhead 
> of wrapping the arguments with “[]” when calling f is arguably bearable. 
> However, in some other situations, this approach might not be applicable. For 
> instance, one may simply not be able to modify the original function. Another 
> use-case may be a function that should forward its own variadic parameters.
> 
> In a variety of other languages, there exists a way to do this. For instance, 
> Python can “unpack” (or splat) a list into function arguments by prefixing it 
> with *:
> 
> def f(*args):
>   # Some implementation …
> 
> f(*[1, 2, 3]) # == f(1, 2, 3)
> 
> I was wondering if such feature could be supported by Swift, and if not, why.
> 
> Syntactically, I like the use of “…”, which would mirror function signatures:
> 
> f(…[1, 2, 3]) // == f(1, 2, 3)
> 
> Thanks.
> 
> --
> Dimitri Racordon

___
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-11-30 Thread Zach Wolfe via swift-evolution
Doug and others have brought up some great points, and I think Doug’s idea of a 
common infrastructure for importing declarations from other languages is 
_extremely_ attractive for the long-term future of Swift. 

However, unlike this proposal, that will (I imagine as a non-compiler engineer) 
be a colossal undertaking, and as such it’s not going to make it into Swift 5, 
or possibly even 6 or 7. I understand, then, Chris’s (and other’s) desire to 
start interfacing with Python code now, not later. For me, far and away the 
biggest problem with this proposal (and the only outright deal-breaker) is that 
dynamic member lookups do not differentiate themselves in any way from 
statically-checked member lookups syntactically. I don’t object as strongly as 
others to the idea of adding this kind of dynamism to the language, but if it’s 
going to be there, it should not be possible to slightly misspell a static 
member name and end up with an unexpectedly dynamic member that may or may not 
fail at compile-time.

With all that being said, for people who are opposed to this proposal, how 
would the idea of an alternate, clearly opt-in syntax for dynamic member 
lookups change your views, if at all? I’m not sure what might provide the best 
balance of clarity and  ergonomics, but we could always revive “->”, right? :P

> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> I’d like to formally propose the inclusion of user-defined dynamic member 
>> lookup types.
>> 
>> Here is my latest draft of the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>> https://github.com/apple/swift-evolution/pull/768
>> 
>> An implementation of this design is available here:
>> https://github.com/apple/swift/pull/13076
>> 
>> The implementation is straight-forward and (IMO) non-invasive in the 
>> compiler.
> 
> 
> I think better interoperability with Python (and other OO languages in 
> widespread use) is a good goal, and I agree that the implementation of the 
> feature described is straight-forward and not terribly invasive in the 
> compiler.
> 
> However, I do not think this proposal is going in the right direction for 
> Swift. I have objections on several different grounds.
> 
> Philosophy
> Swift is, unabashedly, a strong statically-typed language. We don’t allow 
> implicit down casting, we require “as?” so you have to cope with the 
> possibility of failure (or use “as!” and think hard about the “!”). Even the 
> gaping hole that is AnyObject dispatch still requires the existence of an 
> @objc declaration and produces an optional lookup result, so the user must 
> contend with the potential for dynamic failure. Whenever we discuss adding 
> more dynamic features to Swift, there’s a strong focus on maintaining that 
> strong static type system.
> 
> IMO, this proposal is a significant departure from the fundamental character 
> of Swift, because it allows access to possibly-nonexistent members (as well 
> as calls with incorrect arguments, in the related proposal) without any 
> indication that the operation might fail. It’s easy to fall through these 
> cracks for any type that supports DynamicMemberLookupProtocol—a 
> single-character typo when using a DynamicMemberLookupProtocol-capable type 
> means you’ve fallen out of the safety that Swift provides. I think that’s a 
> poor experience for the Python interoperability case, but more on that in the 
> Tooling section below.
> 
> While we shouldn’t necessarily avoid a feature simply because it can be used 
> distastefully, consider something like this:
> 
>   public extension NSObject :  DynamicMemberLookupProtocol, 
> DynamicCallableProtocol { … }
> 
> that goes directly to the Objective-C runtime to resolve member lookups and 
> calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly 
> convenient, and one could imagine some mixed Objective-C/Swift code bases 
> where this would save a lot of typing (of code)… at the cost of losing static 
> typing in the language. The presence of that one extension means I can no 
> longer rely on the safety guarantees Swift normally provides, for any project 
> that imports that extension and uses a subclass of NSObject. At best, we as a 
> community decide “don’t do that”; at worse, some nontrivial fraction of the 
> community decides that the benefits outweigh the costs (for this type or some 
> other), and we can no longer say that Swift is a strong statically-typed 
> language without adding “unless you’re using something that adopts 
> DynamicMemberLookupProtocol”.
> 
> Tooling
> The Python interoperability enabled by this proposal *does* look fairly nice 
> when you look at a small, correctly-written example. However, absolutely none 
> of the tooling assistance we rely on when writing such code will 

[swift-evolution] [Accepted] SE-0189 - Restrict Cross-module Struct Initializers

2017-11-30 Thread Ted Kremenek via swift-evolution
Hello Swift Community,

The review of of “SE-189: Restrict Cross-module Struct Initializers” ran from 
November 14 to 21, 2017.

This proposal has been accepted.

During the review, most of the feedback voiced support that this was a 
necessary change for the library evolution (API resilience) story in Swift.  
There was some concern about the migration impact, as the change is 
source-breaking.  Some options were discussed on the review thread to possibly 
mitigate the migration impact in some cases.  Further, the thought process is 
that by having a warning in Swift 4.1 we can assess the impact of the change 
and soft message it, or if feedback is strong, re-evaluate the change.

Thanks to everyone who participated in the review.

Ted
Review Manager___
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-11-30 Thread Vladimir.S via swift-evolution

On 30.11.2017 17:15, Matthew Johnson via swift-evolution wrote:



Sent from my iPad

On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution > wrote:





On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution > wrote:


I’d like to formally propose the inclusion of user-defined dynamic member 
lookup types.

Here is my latest draft of the proposal:
https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
https://github.com/apple/swift-evolution/pull/768

An implementation of this design is available here:
https://github.com/apple/swift/pull/13076

The implementation is straight-forward and (IMO) non-invasive in the compiler.



I think better interoperability with Python (and other OO languages in widespread use) is a good goal, and I agree 
that the implementation of the feature described is straight-forward and not terribly invasive in the compiler.


However, I do not think this proposal is going in the right direction for Swift. I have objections on several 
different grounds.


+1 to everything Doug says here.  He articulates the concerns I tried to voice in an earlier thread more clearly and 
more thoroughly.


This design introduces a significant hole in the type system which is contrary to the spirit of Swift.  It doesn’t just 
make dynamic language interop easy, it also changes the semantics of any type which conforms to 
DynamicMemberLookupProtocol.  That is not something that is locally visible when looking at a piece of code.  Worse, it 
does so in a way that trivial mistakes such as a typo can turn into runtime errors.  Worst of all, as Doug points out it 
is possible to use retroactive conformance to change the semantics of vast quantities of widely used types in one fell 
swoop.


One additional concern that I don’t believe has been mentioned is that of evolution.  When a library is imported from a 
dynamic language and the library makes breaking changes Swift code written using this feature will break without notice 
until a runtime error occurs.  Is that acceptable?  That may be what users of dynamic languages are accustomed to but 
can we do better in Swift?  If we can make the process of upgrading dependencies less a less harrowing experience 
perhaps that could be a major selling point in moving them to Swift.  But we won’t accomplish that with this design.


Interop with dynamic languages is a worthy goal, but we should do it in a way that has no potential impact on code that 
does not need the feature.  A semantic variant of “don’t pay for what you don’t use” should apply here.  If we add this 
feature everyone will pay for it every time they read unfamiliar Swift code.  They will have to contend with the 
potential for conformances to this protocol, even on standard library types.  That feels like a pretty high cost to me, 
especially for programmers who aren’t using the dynamic language interop features themselves.


Further, a consistent theme has been the desire to avoid things like compiler flags that could fragment the community. 
  I fear this feature has the potential to do that, especially if it is really successful at attracting people from the 
dynamic language community.  I think we should consider carefully the following questions:


* Do we want to encourage these programmers to continue writing code in an extremely dynamic style when they come to 
Swift or do we want to encourage them to embrace the advantages of relying on the type system?

* If we want them to embrace the type system but that would keep them away from 
Swift how do we feel about that?



FWIW +1 for Doug, Matthew and others said.

I believe it is not possible to express each variation of other language's syntax/behavior in Swift - in any case 
languages will differ in some details, function/properties calling/assignment rules etc. Also, we need to remember Swift 
exceptions, proposed 'async' feature, KeyPaths etc and map these to features of selected dynamic language. In result 
we'll have not-Swift-not-Python/whatever frankenstein code :-)


Probably it is better just to allow Python/other code inside swift code, be able to pass Swift instances and return some 
"result" from that code to Swift and be able to convert it then to standard Swift types.


// special syntax for other language's code
// raw dynamic language's code after "in" and before last bracket
// can have IDE/editor support for that language with all features standard for 
that language, like autocomplete
let code = {(name: String)->[Int] throws in @language(Python)
// some raw Python code, indent is required
}
let result = try? code(name: "John")

or at least

// special syntax for other language's code
// raw dynamic language's code  after "\\**PYTHON" line and before "**//"
// can have IDE/editor support for that language with all features standard for 
that language
// 

Re: [swift-evolution] Remove AnyObject Constraint for Objective-C Lightweight Generics

2017-11-30 Thread Philippe Hausler via swift-evolution


> On Nov 29, 2017, at 2:07 PM, Riley Testut  wrote:
> 
> 
>> On Nov 9, 2017, at 9:01 AM, Philippe Hausler > > wrote:
>> 
>> I have personally filed a few bugs on this; and I definitely consider it a 
>> bug that we cannot store Any in generics for objc. There are however some 
>> problem areas that might be worth considering while fixing this bug. 
>> 
>> 1) We need to ensure this does not cause source churn - I would expect swift 
>> 4 to be source compatible with swift 5.
> 
> Agreed. I'd be surprised if this would cause churn though, since this is 
> effectively just loosening a restriction, and all existing use cases would 
> still be allowed.
> 
>> 
>> 2) There are a few cases that might be a bit cagey - you claim NSCache, but 
>> would it be surprising that the boxed object having no refs gets purged? How 
>> bout NSPointerArray? 
> 
> I agree there are certain cases where true reference semantics are important, 
> and off the top of my head I can think of two (relatively easy) ways we could 
> accommodate this:
> 
> 1) The Objective-C class declaration explicitly specifies an upper-bound of 
> NSObject (or NSObjectProtocol).
> 2) Add a new keyword (similar to existing __covariant and __contravariant 
> keywords) such as __reference (where the final name would of course be 
> bike-shedded)
> 
> I’m leaning towards an approach similar to 2) since 1) might be confusing to 
> newcomers due to it seemingly have no purpose considering the NSObject 
> constraint would implicitly there where using the generic class from 
> Objective-C code.

Option 2 may take a lot of effort just as a heads up since that will mean that 
we would need to audit the entire macOS, iOS, tvOS, and watchOS SDKs and find 
any edge cases (my guess is very very few and perhaps only Foundation)

> 
> I’m not familiar with NSCache’s internals, so I wasn’t aware references play 
> a role in whether or not NSCache purges an object. That being said, I don’t 
> think it would be surprising if NSCache purged a large Data value under 
> memory pressure, as long as it didn’t affect any “copies” I had retrieved and 
> was currently using. 
> 
> As for NSPointerArray, we’d still need to get Objective-C generics for it 
> first  Though assuming that is added, the generic parameter would need to 
> explicitly say it requires a reference.

NSMapTable or NSHashTable might be better examples; if the key or value is 
weakly stored the translated reference will drop off if the held structure is 
mutated.
e.g.

var m = NSMapTable(keyOptions: [.copyIn, .objectPersonality], 
valueOptions: [.weakMemory, .objectPersonality])

var key = "hello" as NSString
var value = Data(bytes: [0, 1, 2, 3]) as NSData

m.setObject(value, forKey: key)

assert(m.object(forKey: key) != nil)

That works as expected - so lets change it to a structure

var m = NSMapTable(keyOptions: [.copyIn, .objectPersonality], 
valueOptions: [.weakMemory, .objectPersonality])

var key = "hello"
var value = Data(bytes: [0, 1, 2, 3])

m.setObject(value, forKey: key) // after here there are no more references to 
value so it is destroyed

assert(m.object(forKey: key) != nil) // this now fails

In that second example even if you had a usage of value past the setObject 
method call that was a mutation it would also fail the assert because the 
backing reference would have changed.

I guess what I am saying is there are edge cases that we have to be careful 
with.

> 
>> 3) Since Foundation is likely the most impact here I think it would be 
>> useful to audit the results of this before pushing it out; specifically the 
>> Foundation internal builds so that we can make sure the things we are 
>> working on function correctly.
>> 
>> Do you have implementations in the works yet? I really think this is 
>> important for us to get in (especially before the ABI gets locked down cause 
>> it could have impact there…)
> 
> 
> No I don’t, but would be open to digging into it and seeing what I could do 
> as a proof-of-concept (I just don’t know where I’d start looking to 
> accomplish this).


Dont get me wrong; I think this is a great idea and vastly improves the state 
of affairs – imho it is very well worth doing and getting this done before we 
cannot change it.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Xiaodi Wu via swift-evolution
Right—again, this is yet another difference between two things both named
“random” in this proposal. Almost always, when we say “give me two random
integers,” we want independent random samples from the set of all integers.
But for collections, a very common (and probably more common operation) is
to _sample without replacement_. Conflating the two is how hard-to-detect
errors arise.

On Thu, Nov 30, 2017 at 10:29 Martin Waitz via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi Erica,
>
> > Doesn't `choose` usually take two arguments, the `count` to choose
> (presumably defaulting to 1) and the collection to choose `from`?
>
> This might be useful for collections, when you want to draw several
> elements without drawing the same element twice.
> For ranges of random numbers you usually need independent numbers and just
> call the generator multiple times.
> Both use cases could be provided as overloads (a default argument would
> require that the return value has the same type, which would be unfortunate
> here).
>
> --
> Martin
> ___
> 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] Random Unification

2017-11-30 Thread Martin Waitz via swift-evolution
Hi Erica,

> Doesn't `choose` usually take two arguments, the `count` to choose 
> (presumably defaulting to 1) and the collection to choose `from`?

This might be useful for collections, when you want to draw several elements 
without drawing the same element twice.
For ranges of random numbers you usually need independent numbers and just call 
the generator multiple times.
Both use cases could be provided as overloads (a default argument would require 
that the return value has the same type, which would be unfortunate here).

-- 
Martin
___
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-11-30 Thread Thorsten Seitz via swift-evolution
+1 to the concerns voiced by Doug, Matthew and others. I , too, would prefer a 
generator which generates a statically typed bridge instead of the dynamic 
lookup ature proposed which effectively undermines Swift's static type system.

-Thorsten

> Am 30.11.2017 um 15:15 schrieb Matthew Johnson via swift-evolution 
> :
> 
> 
> 
> Sent from my iPad
> 
>> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>>  wrote:
>>> 
>>> I’d like to formally propose the inclusion of user-defined dynamic member 
>>> lookup types.
>>> 
>>> Here is my latest draft of the proposal:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>>> https://github.com/apple/swift-evolution/pull/768
>>> 
>>> An implementation of this design is available here:
>>> https://github.com/apple/swift/pull/13076
>>> 
>>> The implementation is straight-forward and (IMO) non-invasive in the 
>>> compiler.
>> 
>> 
>> I think better interoperability with Python (and other OO languages in 
>> widespread use) is a good goal, and I agree that the implementation of the 
>> feature described is straight-forward and not terribly invasive in the 
>> compiler.
>> 
>> However, I do not think this proposal is going in the right direction for 
>> Swift. I have objections on several different grounds.
> 
> +1 to everything Doug says here.  He articulates the concerns I tried to 
> voice in an earlier thread more clearly and more thoroughly.  
> 
> This design introduces a significant hole in the type system which is 
> contrary to the spirit of Swift.  It doesn’t just make dynamic language 
> interop easy, it also changes the semantics of any type which conforms to 
> DynamicMemberLookupProtocol.  That is not something that is locally visible 
> when looking at a piece of code.  Worse, it does so in a way that trivial 
> mistakes such as a typo can turn into runtime errors.  Worst of all, as Doug 
> points out it is possible to use retroactive conformance to change the 
> semantics of vast quantities of widely used types in one fell swoop.
> 
> One additional concern that I don’t believe has been mentioned is that of 
> evolution.  When a library is imported from a dynamic language and the 
> library makes breaking changes Swift code written using this feature will 
> break without notice until a runtime error occurs.  Is that acceptable?  That 
> may be what users of dynamic languages are accustomed to but can we do better 
> in Swift?  If we can make the process of upgrading dependencies less a less 
> harrowing experience perhaps that could be a major selling point in moving 
> them to Swift.  But we won’t accomplish that with this design.
> 
> Interop with dynamic languages is a worthy goal, but we should do it in a way 
> that has no potential impact on code that does not need the feature.  A 
> semantic variant of “don’t pay for what you don’t use” should apply here.  If 
> we add this feature everyone will pay for it every time they read unfamiliar 
> Swift code.  They will have to contend with the potential for conformances to 
> this protocol, even on standard library types.  That feels like a pretty high 
> cost to me, especially for programmers who aren’t using the dynamic language 
> interop features themselves.
> 
> Further, a consistent theme has been the desire to avoid things like compiler 
> flags that could fragment the community.  I fear this feature has the 
> potential to do that, especially if it is really successful at attracting 
> people from the dynamic language community.  I think we should consider 
> carefully the following questions:
> 
> * Do we want to encourage these programmers to continue writing code in an 
> extremely dynamic style when they come to Swift or do we want to encourage 
> them to embrace the advantages of relying on the type system?  
> * If we want them to embrace the type system but that would keep them away 
> from Swift how do we feel about that?  
> 
> Matthew
> 
>> 
>> Philosophy
>> Swift is, unabashedly, a strong statically-typed language. We don’t allow 
>> implicit down casting, we require “as?” so you have to cope with the 
>> possibility of failure (or use “as!” and think hard about the “!”). Even the 
>> gaping hole that is AnyObject dispatch still requires the existence of an 
>> @objc declaration and produces an optional lookup result, so the user must 
>> contend with the potential for dynamic failure. Whenever we discuss adding 
>> more dynamic features to Swift, there’s a strong focus on maintaining that 
>> strong static type system.
>> 
>> IMO, this proposal is a significant departure from the fundamental character 
>> of Swift, because it allows access to possibly-nonexistent members (as well 
>> as calls with incorrect arguments, in the related proposal) without any 
>> indication that the 

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

2017-11-30 Thread Karl Wagner via swift-evolution


> On 30. Nov 2017, at 09:24, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>> I’d like to formally propose the inclusion of user-defined dynamic member 
>> lookup types.
>> 
>> Here is my latest draft of the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>> 
>> https://github.com/apple/swift-evolution/pull/768
>> 
>> An implementation of this design is available here:
>> https://github.com/apple/swift/pull/13076
>> 
>> The implementation is straight-forward and (IMO) non-invasive in the 
>> compiler.
> 
> 
> Even the gaping hole that is AnyObject dispatch still requires the existence 
> of an @objc declaration and produces an optional lookup result, so the user 
> must contend with the potential for dynamic failure. Whenever we discuss 
> adding more dynamic features to Swift, there’s a strong focus on maintaining 
> that strong static type system.
> 

...


> How Should Python Interoperability Work?
> Going back to the central motivator for this proposal, I think that providing 
> something akin to the Clang Importer provides the best interoperability 
> experience: it would turn Python declarations into *real* Swift declarations, 
> so that we get the various tooling benefits of having a strong 
> statically-typed language.


AnyObject doesn’t really come up too often in real-world Swift (in my 
experience, at least) exactly because of the Clang importer and the fact that 
Objective-C has adopted lots of annotations to make that importing experience 
better.

We can’t expect other languages to do that, but IMO we’ll still need some kind 
of importer/wrapper generator. When Swift was first opened to the public, 
people started porting their Objective-C code and asking themselves the 
philosophical question: “Is this Swift?” - i.e. are you using Swift’s features, 
or are you basically writing Objective-C code using a wrapper language?

Personally, I feel this system is designed to let you write Python, using Swift 
as a wrapper language - except unlike with Objective-C, it doesn’t have any 
static information about what you can do or not. It can’t provide the “safe by 
default” guarantees are other core principles and set Swift apart from other 
languages. When we consider interoperability with other languages, it should be 
from the perspective of mapping their features to Swift’s philosophies. This 
proposal takes the reverse approach, and makes Swift like Python, so I’m 
against it.

- Karl___
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-11-30 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> I’d like to formally propose the inclusion of user-defined dynamic member 
>> lookup types.
>> 
>> Here is my latest draft of the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>> https://github.com/apple/swift-evolution/pull/768
>> 
>> An implementation of this design is available here:
>> https://github.com/apple/swift/pull/13076
>> 
>> The implementation is straight-forward and (IMO) non-invasive in the 
>> compiler.
> 
> 
> I think better interoperability with Python (and other OO languages in 
> widespread use) is a good goal, and I agree that the implementation of the 
> feature described is straight-forward and not terribly invasive in the 
> compiler.
> 
> However, I do not think this proposal is going in the right direction for 
> Swift. I have objections on several different grounds.

+1 to everything Doug says here.  He articulates the concerns I tried to voice 
in an earlier thread more clearly and more thoroughly.  

This design introduces a significant hole in the type system which is contrary 
to the spirit of Swift.  It doesn’t just make dynamic language interop easy, it 
also changes the semantics of any type which conforms to 
DynamicMemberLookupProtocol.  That is not something that is locally visible 
when looking at a piece of code.  Worse, it does so in a way that trivial 
mistakes such as a typo can turn into runtime errors.  Worst of all, as Doug 
points out it is possible to use retroactive conformance to change the 
semantics of vast quantities of widely used types in one fell swoop.

One additional concern that I don’t believe has been mentioned is that of 
evolution.  When a library is imported from a dynamic language and the library 
makes breaking changes Swift code written using this feature will break without 
notice until a runtime error occurs.  Is that acceptable?  That may be what 
users of dynamic languages are accustomed to but can we do better in Swift?  If 
we can make the process of upgrading dependencies less a less harrowing 
experience perhaps that could be a major selling point in moving them to Swift. 
 But we won’t accomplish that with this design.

Interop with dynamic languages is a worthy goal, but we should do it in a way 
that has no potential impact on code that does not need the feature.  A 
semantic variant of “don’t pay for what you don’t use” should apply here.  If 
we add this feature everyone will pay for it every time they read unfamiliar 
Swift code.  They will have to contend with the potential for conformances to 
this protocol, even on standard library types.  That feels like a pretty high 
cost to me, especially for programmers who aren’t using the dynamic language 
interop features themselves.

Further, a consistent theme has been the desire to avoid things like compiler 
flags that could fragment the community.  I fear this feature has the potential 
to do that, especially if it is really successful at attracting people from the 
dynamic language community.  I think we should consider carefully the following 
questions:

* Do we want to encourage these programmers to continue writing code in an 
extremely dynamic style when they come to Swift or do we want to encourage them 
to embrace the advantages of relying on the type system?  
* If we want them to embrace the type system but that would keep them away from 
Swift how do we feel about that?  

Matthew

> 
> Philosophy
> Swift is, unabashedly, a strong statically-typed language. We don’t allow 
> implicit down casting, we require “as?” so you have to cope with the 
> possibility of failure (or use “as!” and think hard about the “!”). Even the 
> gaping hole that is AnyObject dispatch still requires the existence of an 
> @objc declaration and produces an optional lookup result, so the user must 
> contend with the potential for dynamic failure. Whenever we discuss adding 
> more dynamic features to Swift, there’s a strong focus on maintaining that 
> strong static type system.
> 
> IMO, this proposal is a significant departure from the fundamental character 
> of Swift, because it allows access to possibly-nonexistent members (as well 
> as calls with incorrect arguments, in the related proposal) without any 
> indication that the operation might fail. It’s easy to fall through these 
> cracks for any type that supports DynamicMemberLookupProtocol—a 
> single-character typo when using a DynamicMemberLookupProtocol-capable type 
> means you’ve fallen out of the safety that Swift provides. I think that’s a 
> poor experience for the Python interoperability case, but more on that in the 
> Tooling section below.
> 
> While we shouldn’t necessarily avoid a feature simply because it can be used 
> distastefully, 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-30 Thread Karl Wagner via swift-evolution


> On 28. Nov 2017, at 00:20, Martin Waitz via swift-evolution 
>  wrote:
> 
> Hello,
> 
>> Maybe we call the default RNG instance `random`, and then give the 
>> `random(in:)` methods another name, like `choose(in:)`?
>> 
>>  let diceRoll = random.choose(in: 1...6)
>>  let card = random.choose(in: deck)
>>  let isHeads = random.choose(in: [true, false])
>>  let probability = random.choose(in: 0.0...1.0)
>>  
>>  let diceRoll = rng.choose(in: 1...6)
>>  let card = rng.choose(in: deck)
>>  let isHeads = rng.choose(in: [true, false])
>>  let probability = rng.choose(in: 0.0...1.0)
> 
> I like this design a lot. After all, `random` is not a property of some type 
> or instance, but we want to generate a new random element within some 
> range/based on some given set.
> Modeling that as methods of the RNG seems to be much more natural.
> 
> -- 
> Martin
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

+1. This discussion seems to have been going on for a long time and I haven’t 
kept up with all of the arguments, but to me, “random” only makes sense when 
you’re talking about selecting something from a group.

Some data types, like Int and Bool, have a natural set of all discrete, allowed 
values, so there is some natural group to talk about which can serve as a 
reasonable default. Basically, they are similar to enums (remember the 
discussions we’ve been having about an “allCases” collection for enums? Is 
there possibly some unifying abstraction between these and types such as Int or 
Bool?). So I can only really see it looking more or less like this:

protocol RandomNumberGenerator {
func random(from: C) -> C.Element? where C: Collection
}

// I don’t know; there is probably a real compsci/maths/stats name for this. 
See ‘enum' discussion.

protocol ClosedValueSet {
static var allValues: AnyCollection { get } 
}

extension RandomNumberGenerator {
func random() -> T? where T: ClosedValueSet {
return random(from: T.allValues)
}
}

extension Int: ClosedValueSet {
static var allValues: AnyCollection { return 
AnyCollection(Int.min..

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

2017-11-30 Thread Benjamin G via swift-evolution
On Thu, Nov 30, 2017 at 9:24 AM, Douglas Gregor via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I’d like to formally propose the inclusion of user-defined dynamic member
> lookup types.
>
> Here is my latest draft of the proposal:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> https://github.com/apple/swift-evolution/pull/768
>
> An implementation of this design is available here:
> https://github.com/apple/swift/pull/13076
>
> The implementation is straight-forward and (IMO) non-invasive in the
> compiler.
>
>
>
> I think better interoperability with Python (and other OO languages in
> widespread use) is a good goal, and I agree that the implementation of the
> feature described is straight-forward and not terribly invasive in the
> compiler.
>
> However, I do not think this proposal is going in the right direction for
> Swift. I have objections on several different grounds.
>
> *Philosophy*
> Swift is, unabashedly, a strong statically-typed language. We don’t allow
> implicit down casting, we require “as?” so you have to cope with the
> possibility of failure (or use “as!” and think hard about the “!”). Even
> the gaping hole that is AnyObject dispatch still requires the existence of
> an @objc declaration and produces an optional lookup result, so the user
> must contend with the potential for dynamic failure. Whenever we discuss
> adding more dynamic features to Swift, there’s a strong focus on
> maintaining that strong static type system.
>
> IMO, this proposal is a significant departure from the fundamental
> character of Swift, because it allows access to possibly-nonexistent
> members (as well as calls with incorrect arguments, in the related
> proposal) without any indication that the operation might fail. It’s easy
> to fall through these cracks for any type that supports
> DynamicMemberLookupProtocol—a single-character typo when using a
> DynamicMemberLookupProtocol-capable type means you’ve fallen out of the
> safety that Swift provides. I think that’s a poor experience for the Python
> interoperability case, but more on that in the Tooling section below.
>
> While we shouldn’t necessarily avoid a feature simply because it can be
> used distastefully, consider something like this:
>
> public extension NSObject :  DynamicMemberLookupProtocol,
> DynamicCallableProtocol { … }
>
> that goes directly to the Objective-C runtime to resolve member lookups
> and calls—avoiding @objc, bridging headers, and so on. It’s almost
> frighteningly convenient, and one could imagine some mixed
> Objective-C/Swift code bases where this would save a lot of typing (of
> code)… at the cost of losing static typing in the language. The presence of
> that one extension means I can no longer rely on the safety guarantees
> Swift normally provides, for any project that imports that extension and
> uses a subclass of NSObject. At best, we as a community decide “don’t do
> that”; at worse, some nontrivial fraction of the community decides that the
> benefits outweigh the costs (for this type or some other), and we can no
> longer say that Swift is a strong statically-typed language without adding
> “unless you’re using something that adopts DynamicMemberLookupProtocol”.
>
> *Tooling*
> The Python interoperability enabled by this proposal *does* look fairly
> nice when you look at a small, correctly-written example. However,
> absolutely none of the tooling assistance we rely on when writing such code
> will work for Python interoperability. Examples:
>
> * As noted earlier, if you typo’d a name of a Python entity or passed the
> wrong number of arguments to it, the compiler will not tell you: it’ll be a
> runtime failure in the Python interpreter. I guess that’s what you’d get if
> you were writing the code in Python, but Swift is supposed to be *better*
> than Python if we’re to convince a community to use Swift instead.
> * Code completion won’t work, because Swift has no visibility into
> declarations written in Python
> * Indexing/jump-to-definition/lookup documentation/generated interface
> won’t ever work. None of the IDE features supported by SourceKit will work,
> which will be a significant regression for users coming from a
> Python-capable IDE.
>
> Statically-typed languages should be a boon for tooling, but if a user
> coming from Python to Swift *because* it’s supposed to be a better
> development experience actually sees a significantly worse development
> experience, we’re not going to win them over. It’ll just feel inconsistent.
>
> *Dynamic Typing Features*
> It’s possible that the right evolutionary path for Swift involves some
> notion of dynamic typing, which would have a lot of the properties sought
> by this proposal (and the DynamicCallableProtocol one). If that is true—and
> I’m not at all convinced that it is—we shouldn’t accidentally fall into a
> 

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

2017-11-30 Thread David Sweeris via swift-evolution


Sent from my iPhone

> On Nov 30, 2017, at 00:24, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> I’d like to formally propose the inclusion of user-defined dynamic member 
>> lookup types.
>> 
>> Here is my latest draft of the proposal:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
>> https://github.com/apple/swift-evolution/pull/768
>> 
>> An implementation of this design is available here:
>> https://github.com/apple/swift/pull/13076
>> 
>> The implementation is straight-forward and (IMO) non-invasive in the 
>> compiler.
> 
> 
> I think better interoperability with Python (and other OO languages in 
> widespread use) is a good goal, and I agree that the implementation of the 
> feature described is straight-forward and not terribly invasive in the 
> compiler.
> 
> However, I do not think this proposal is going in the right direction for 
> Swift. I have objections on several different grounds.
> 
> Philosophy
> Swift is, unabashedly, a strong statically-typed language. We don’t allow 
> implicit down casting, we require “as?” so you have to cope with the 
> possibility of failure (or use “as!” and think hard about the “!”). Even the 
> gaping hole that is AnyObject dispatch still requires the existence of an 
> @objc declaration and produces an optional lookup result, so the user must 
> contend with the potential for dynamic failure. Whenever we discuss adding 
> more dynamic features to Swift, there’s a strong focus on maintaining that 
> strong static type system.
> 
> IMO, this proposal is a significant departure from the fundamental character 
> of Swift, because it allows access to possibly-nonexistent members (as well 
> as calls with incorrect arguments, in the related proposal) without any 
> indication that the operation might fail. It’s easy to fall through these 
> cracks for any type that supports DynamicMemberLookupProtocol—a 
> single-character typo when using a DynamicMemberLookupProtocol-capable type 
> means you’ve fallen out of the safety that Swift provides. I think that’s a 
> poor experience for the Python interoperability case, but more on that in the 
> Tooling section below.
> 
> While we shouldn’t necessarily avoid a feature simply because it can be used 
> distastefully, consider something like this:
> 
>   public extension NSObject :  DynamicMemberLookupProtocol, 
> DynamicCallableProtocol { … }
> 
> that goes directly to the Objective-C runtime to resolve member lookups and 
> calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly 
> convenient, and one could imagine some mixed Objective-C/Swift code bases 
> where this would save a lot of typing (of code)… at the cost of losing static 
> typing in the language. The presence of that one extension means I can no 
> longer rely on the safety guarantees Swift normally provides, for any project 
> that imports that extension and uses a subclass of NSObject. At best, we as a 
> community decide “don’t do that”; at worse, some nontrivial fraction of the 
> community decides that the benefits outweigh the costs (for this type or some 
> other), and we can no longer say that Swift is a strong statically-typed 
> language without adding “unless you’re using something that adopts 
> DynamicMemberLookupProtocol”.
> 
> Tooling
> The Python interoperability enabled by this proposal *does* look fairly nice 
> when you look at a small, correctly-written example. However, absolutely none 
> of the tooling assistance we rely on when writing such code will work for 
> Python interoperability. Examples:
> 
> * As noted earlier, if you typo’d a name of a Python entity or passed the 
> wrong number of arguments to it, the compiler will not tell you: it’ll be a 
> runtime failure in the Python interpreter. I guess that’s what you’d get if 
> you were writing the code in Python, but Swift is supposed to be *better* 
> than Python if we’re to convince a community to use Swift instead.
> * Code completion won’t work, because Swift has no visibility into 
> declarations written in Python
> * Indexing/jump-to-definition/lookup documentation/generated interface won’t 
> ever work. None of the IDE features supported by SourceKit will work, which 
> will be a significant regression for users coming from a Python-capable IDE.
> 
> Statically-typed languages should be a boon for tooling, but if a user coming 
> from Python to Swift *because* it’s supposed to be a better development 
> experience actually sees a significantly worse development experience, we’re 
> not going to win them over. It’ll just feel inconsistent.
> 
> Dynamic Typing Features
> It’s possible that the right evolutionary path for Swift involves some notion 
> of dynamic typing, which would have a lot of the properties sought by this 
> proposal (and the DynamicCallableProtocol one). If 

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

2017-11-30 Thread Douglas Gregor via swift-evolution


> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> I’d like to formally propose the inclusion of user-defined dynamic member 
> lookup types.
> 
> Here is my latest draft of the proposal:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438
> https://github.com/apple/swift-evolution/pull/768
> 
> An implementation of this design is available here:
> https://github.com/apple/swift/pull/13076
> 
> The implementation is straight-forward and (IMO) non-invasive in the compiler.


I think better interoperability with Python (and other OO languages in 
widespread use) is a good goal, and I agree that the implementation of the 
feature described is straight-forward and not terribly invasive in the compiler.

However, I do not think this proposal is going in the right direction for 
Swift. I have objections on several different grounds.

Philosophy
Swift is, unabashedly, a strong statically-typed language. We don’t allow 
implicit down casting, we require “as?” so you have to cope with the 
possibility of failure (or use “as!” and think hard about the “!”). Even the 
gaping hole that is AnyObject dispatch still requires the existence of an @objc 
declaration and produces an optional lookup result, so the user must contend 
with the potential for dynamic failure. Whenever we discuss adding more dynamic 
features to Swift, there’s a strong focus on maintaining that strong static 
type system.

IMO, this proposal is a significant departure from the fundamental character of 
Swift, because it allows access to possibly-nonexistent members (as well as 
calls with incorrect arguments, in the related proposal) without any indication 
that the operation might fail. It’s easy to fall through these cracks for any 
type that supports DynamicMemberLookupProtocol—a single-character typo when 
using a DynamicMemberLookupProtocol-capable type means you’ve fallen out of the 
safety that Swift provides. I think that’s a poor experience for the Python 
interoperability case, but more on that in the Tooling section below.

While we shouldn’t necessarily avoid a feature simply because it can be used 
distastefully, consider something like this:

public extension NSObject :  DynamicMemberLookupProtocol, 
DynamicCallableProtocol { … }

that goes directly to the Objective-C runtime to resolve member lookups and 
calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly 
convenient, and one could imagine some mixed Objective-C/Swift code bases where 
this would save a lot of typing (of code)… at the cost of losing static typing 
in the language. The presence of that one extension means I can no longer rely 
on the safety guarantees Swift normally provides, for any project that imports 
that extension and uses a subclass of NSObject. At best, we as a community 
decide “don’t do that”; at worse, some nontrivial fraction of the community 
decides that the benefits outweigh the costs (for this type or some other), and 
we can no longer say that Swift is a strong statically-typed language without 
adding “unless you’re using something that adopts DynamicMemberLookupProtocol”.

Tooling
The Python interoperability enabled by this proposal *does* look fairly nice 
when you look at a small, correctly-written example. However, absolutely none 
of the tooling assistance we rely on when writing such code will work for 
Python interoperability. Examples:

* As noted earlier, if you typo’d a name of a Python entity or passed the wrong 
number of arguments to it, the compiler will not tell you: it’ll be a runtime 
failure in the Python interpreter. I guess that’s what you’d get if you were 
writing the code in Python, but Swift is supposed to be *better* than Python if 
we’re to convince a community to use Swift instead.
* Code completion won’t work, because Swift has no visibility into declarations 
written in Python
* Indexing/jump-to-definition/lookup documentation/generated interface won’t 
ever work. None of the IDE features supported by SourceKit will work, which 
will be a significant regression for users coming from a Python-capable IDE.

Statically-typed languages should be a boon for tooling, but if a user coming 
from Python to Swift *because* it’s supposed to be a better development 
experience actually sees a significantly worse development experience, we’re 
not going to win them over. It’ll just feel inconsistent.

Dynamic Typing Features
It’s possible that the right evolutionary path for Swift involves some notion 
of dynamic typing, which would have a lot of the properties sought by this 
proposal (and the DynamicCallableProtocol one). If that is true—and I’m not at 
all convinced that it is—we shouldn’t accidentally fall into a suboptimal 
design by taking small, easy, steps. If we’re to include dynamic-typing 
facilities, we should look at more existing practice—C# ‘dynamic' is one such 
approach, but more promising would be some form