Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Slava Pestov via swift-evolution


> On Nov 27, 2017, at 3:38 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> You are effectively proposing that in this very narrow case we perform 
> overload resolution on a symbol in a generic type context *after* the generic 
> type has been replaced with a concrete type. 

Keep in mind that in general, this would require runtime support — we don’t 
always know the concrete substitution for a generic parameter at compile time, 
especially in the presence of separate compilation (but even without, for 
instance when optimizations are not enabled or unable to recover concrete type 
information).

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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Slava Pestov via swift-evolution
Hi Tony,

So if my understanding is correct, the basic proposal is the following:

func id(t: T ?= T.defaultValue) { return t }

extension Int { static var defaultValue = 0 }

extension String { static var defaultValue = “” }

id() as Int // returns 0
id() as String // returns “”
id() as SomeRandomType // fails to type check — no default argument

I don’t understand what would happen if the caller is itself generic though, 
for example:

callsID(_ t: T) {
  _ = id() as T
}

It appears that body of callsID() itself cannot type check without knowledge of 
the concrete T that will be used with this function.

Slava

> On Nov 27, 2017, at 4:10 PM, Tony Allevato via swift-evolution 
>  wrote:
> 
> I totally agree that that's a good rule in general—I'm not 100% comfortable 
> making an exception to it for this, but I wanted to start a discussion about 
> a different approach than had been considered so far.
> 
> The idea of forcing the user to acknowledge the explicitness of SFINAE with a 
> strawman syntax `=?` instead of `=` was a thought experiment to bridge the 
> wild-west-C++ world of templates and Swift's stricter generics, but I can 
> definitely understand if even that kind of approach is something that the 
> core team (who are far more familiar with the C++ side of that coin than I 
> am) doesn't wish to support. As was pointed out, it's not something Swift 
> supports anywhere else today.
> 
> If we look at it from that point of view, where such a semantic treatment of 
> generics would not be supported, I think it becomes a lot harder to 
> rationalize treating this as "default arguments". What you really do have 
> (and what writing it as constrained extensions makes clear) is additional 
> overloads, because they only apply to certain subsets of types. If that's the 
> case, maybe it's the wrong approach to try to turn overloads into "partial 
> default values".

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


Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-27 Thread Kelvin Ma via swift-evolution
On Mon, Nov 27, 2017 at 9:43 PM, Xiaodi Wu  wrote:

> On Mon, Nov 27, 2017 at 5:56 PM, Kelvin Ma  wrote:
>
>>
>>
>> On Mon, Nov 27, 2017 at 4:21 PM, Xiaodi Wu  wrote:
>>
>>> On Mon, Nov 27, 2017 at 15:46 Taylor Swift  wrote:
>>>
 they use packed buffers of floats, which for type safety are better
 rebound to a structured type. right now (Float, Float, Float) works because
 the tuple is laid out contiguously and the GPU can’t tell the difference
 but it’s not guaranteed. also you’re ignoring all the CPU stages that occur
 before anything even gets sent to the GPU.

>>>
>>> Precisely, there is no guarantee of performance if you call these APIs
>>> with an array of Swift tuples.
>>>
>>
>> which is exactly why i support a dedicated language-level vector type
>> which guarantees contiguous, fixed storage, and which the compiler knows
>> about so it can vectorize operations on them.
>>
>
> That's an entirely separate discussion.
>
>
>> tuples right now try to fill too many roles and that makes life difficult
>> for both the compiler and the programmer. however, until then, we need some
>> kind of common, fixed layout currency type for vector data, and by
>> implementation-detail, *tuples are our best option* since for some
>> reason everyone is so opposed to the simple solution of baking vec2, vec3,
>> … vec5 into the language and the generic integer Vector
>> solution everyone wants likely isn’t going to materialize for the
>> foreseeable future.
>>
>
> Disagree. If you want a particular memory layout, define your type in C.
> Swift's interop story is very good, and your type will have a fixed layout
> forever.
>

“*write it in c and import it*” is *not* a solution,, it is a workaround.
plus since it lives across the module boundary, it’s effectively opaque to
compiler optimizations.
___
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-27 Thread Magnus Ahltorp via swift-evolution
> 28 Nov. 2017 00:57 Mathew Huusko V  wrote:
> 
> You're saying that there is universally no inherent difference, and that all 
> calls "determine if you have called it" correctly, but then picked one of 
> only a handful of cases in current practice where that is actually true. Yes 
> "+" (/other math operators) and array access are unsafe, but most other 
> things in Swift are safe by default, and you have to opt into un-safety (e.g. 
> forcing or checking an optional or throwing call) — this is a main tenant of 
> the language.
> 
> Perhaps I was not totally clear while mixing and matching my 
> observations/interpretations of safety and fallibility in compile vs. runtime 
> and readability vs. writability in my initial email, but I believe the spirit 
> of my concern was clear: there is obviously a difference between dynamic and 
> static languages/calls, and having the syntax the same is misleading in a 
> language centered around static safety, perhaps to a degree where it is 
> ergonomically counter productive.

You can never expect everything that is type safe to be non-failing. Also, the 
only two alternatives I feel would be acceptable to you is to either require 
that all return values from dynamic languages are optionals or to require a 
fully name and type specified layer between the dynamic language and Swift.

The first one would be non-ergonomic, since unwrapping would have to be done 
for every call and member access, maybe with the exception of direct use of 
implicitly unwrapped ones. This would likely be rejected by most users, since 
the need to check the existence of a member every time will seem unnecessary to 
them.

The second one will either place the burden of writing that layer on the API 
provider (which likely doesn't care about Swift) or the user of the API (which 
likely just wants to use the API without spending the time studying the API in 
that amount of detail and then writing the required code/rules).

Neither of these seem like acceptable alternatives to me.

Also, if the bridge author wants to return optionals all the time, that is 
possible, right?

/Magnus

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


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

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


> On Nov 27, 2017, at 5:58 PM, Guillaume Lessard via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 27, 2017, at 18:34, Douglas Gregor via swift-evolution 
>>  wrote:
>> 
>> Hello Swift community,
>> 
>> The review of SE-0191 "Eliminate IndexDistance from Collection" begins now 
>> and runs through December 3, 2017. 
> [snip]
>> • What is your evaluation of the proposal?
> 
> I approve heartily.
> I previously complained about this on the swift-users list, making mostly the 
> same arguments against the idea of not using Int. The best argument against 
> that I know is a file-mapping collection on a 32-bit platform; if this 
> matters, IndexDistance could simply be Int64 instead of Int.

I’d like to point out that using Int64 would likely cause just as much 
numericCast'ing around as IndexDistance, so I don’t think that’s a viable 
alternative.

(Thanks for the review!)

- Doug

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


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

2017-11-27 Thread Ben Cohen via swift-evolution
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 
>  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 
> > 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 mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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

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

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


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

2017-11-27 Thread Nevin Brackett-Rozinsky via swift-evolution
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


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

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

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

-- 
Brent Royal-Gordon
Architechies

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


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

2017-11-27 Thread Guillaume Lessard via swift-evolution


> On Nov 27, 2017, at 18:34, Douglas Gregor via swift-evolution 
>  wrote:
> 
> Hello Swift community,
> 
> The review of SE-0191 "Eliminate IndexDistance from Collection" begins now 
> and runs through December 3, 2017. 
[snip]
> • What is your evaluation of the proposal?

I approve heartily.
I previously complained about this on the swift-users list, making mostly the 
same arguments against the idea of not using Int. The best argument against 
that I know is a file-mapping collection on a 32-bit platform; if this matters, 
IndexDistance could simply be Int64 instead of Int.


> • Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes! This mystery type does not justify the difficulty it engenders.

> • Does this proposal fit well with the feel and direction of Swift?

I think so.

> • If you have used other languages or libraries with a similar feature, how 
> do you feel that this proposal compares to those?

This is getting pretty swift-specific.

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

This proposal resonates with my experience with programming generic Collection 
code in Swift.

Cheers,
Guillaume Lessard

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


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

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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Tony Allevato via swift-evolution
On Mon, Nov 27, 2017 at 3:38 PM Matthew Johnson 
wrote:

> On Nov 27, 2017, at 4:55 PM, Tony Allevato 
> wrote:
>
>
>
> On Mon, Nov 27, 2017 at 2:39 PM Matthew Johnson 
> wrote:
>
>> On Nov 27, 2017, at 4:25 PM, Tony Allevato 
>> wrote:
>>
>>
>>
>> On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson 
>> wrote:
>>
>>> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> Really like Tony’s suggestion, much cleaner than yet another annotation
>>> rammed into the signature. Also the idea of a static factory that could
>>> accept previously initialized arguments would be very powerful.
>>>
>>>
>>> It is syntactically cleaner at the site of the function declaration for
>>> sure.  Wouldn’t you agree that it is semantically less clear though?  Both
>>> are important, but which is more important?  If not semantics, why not?
>>>
>>> It’s also worth noting that it would be more verbose in at least some
>>> use cases (when a declaration such as `defaultConfiguration()` is used in
>>> the conditional default expression and is not otherwise necessary).
>>>
>>
>> (Apologies for the earlier blank reply—why is Cmd+Enter a keyboard
>> shortcut for Send something someone would think is a good idea?)
>>
>> That verbosity is kind of a feature of my design, in the sense that it
>> describes exactly what's going on at the location in code where someone
>> expects to see default values. If anything, the default factory name is an
>> opportunity to add context where normally there might be none.
>>
>> It's also worth noting that this design works well if you have multiple
>> methods that need to share the same defaults. Instead of repeating the same
>> annotations for each method that needs them, you just define the functions
>> once and refer to them everywhere. (Could you do the same with the
>> annotation based method? Probably, if you allow arbitrary expressions
>> within them. But that seems less obvious compared to this approach.)
>>
>>
>> You make a really good point here.  The annotations would need to be
>> applied to every declaration that uses them whereas your proposed syntax
>> would just rely on overload resolution succeeding or failing in a given
>> type context.  The use case I have would benefit in this respect as the
>> conditional defaults would be shared by several declarations.
>>
>> Howard’s idea of restricting conditional defaults to only use
>> declarations in the same file seems somewhat arbitrary but it would go a
>> long way towards helping an author understand clearly what the provided
>> defaults are as the rest of the module and imported symbols would not need
>> to be considered.  I wonder if this approach could be refined a bit so it
>> feels less arbitrary.  Users would probably need to rely on tooling to
>> discover defaults but I think I’m ok with that.  I am mostly concerned with
>> the ability of an author to reason locally about the API contract they are
>> publishing.  Do you have any ideas on how to refine Howard's idea?
>>
>
> I mentioned earlier in the thread (with a few messed up details) that
> there are already some restrictions on default arguments that I think
> already work well here. Declarations referenced in the default value
> expression of a function today must be accessible within the scope of the
> declaration being defined, so I'm not sure if we need to go further than
> that.
>
> Here's an example that I'll admit is completely contrived, but should I be
> prevented from doing this? Let's say I define an "Identities" module with
> this type:
>
> ```
> enum Identities {
>   func identity() -> Int { return 0 }  // let's ignore additive vs.
> multiplicative for a moment
>   func identity() -> Double { return 0.0 }
>   func identity() -> () { return () }
>   func identity() -> String { return "" }
>   func identity() -> (T) -> Void { return { _ in } }
>   // and so on
> }
> ```
>
> Then somewhere I want to define a conditional default, using those
> identities:
>
> ```
> import Identities
>
> func someWeirdThing( ...contrived args..., defaultValue: T =?
> Identities.identity()) { ... }
> ```
>
> Swift today already allows this with regular default value expressions, so
> the problem of tooling being needed to discover defaults already exists and
> this hypothetical construct doesn't change that. We *could* restrict such
> defaults to same file or same module and it seems reasonable to do so, but
> should we? If the defaults I want happen to live elsewhere, why not let me
> use them? Or, if it's a serious concern, why not lock down all default
> expressions the same way?
>
>
> You make a really good point about the current behavior default value
> expressions that I hadn’t fully considered.  It is currently possible for a
> new, more specific declaration to be introduced that would be selected.  It
> is 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 4:55 PM, Tony Allevato  wrote:
> 
> 
> 
> On Mon, Nov 27, 2017 at 2:39 PM Matthew Johnson  > wrote:
>> On Nov 27, 2017, at 4:25 PM, Tony Allevato > > wrote:
>> 
>> 
>> 
>> On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson > > wrote:
>>> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution 
>>> > wrote:
>>> 
>>> Really like Tony’s suggestion, much cleaner than yet another annotation 
>>> rammed into the signature. Also the idea of a static factory that could 
>>> accept previously initialized arguments would be very powerful. 
>> 
>> It is syntactically cleaner at the site of the function declaration for 
>> sure.  Wouldn’t you agree that it is semantically less clear though?  Both 
>> are important, but which is more important?  If not semantics, why not?
>> 
>> It’s also worth noting that it would be more verbose in at least some use 
>> cases (when a declaration such as `defaultConfiguration()` is used in the 
>> conditional default expression and is not otherwise necessary).
>> 
>> (Apologies for the earlier blank reply—why is Cmd+Enter a keyboard shortcut 
>> for Send something someone would think is a good idea?)
>> 
>> That verbosity is kind of a feature of my design, in the sense that it 
>> describes exactly what's going on at the location in code where someone 
>> expects to see default values. If anything, the default factory name is an 
>> opportunity to add context where normally there might be none.
>> 
>> It's also worth noting that this design works well if you have multiple 
>> methods that need to share the same defaults. Instead of repeating the same 
>> annotations for each method that needs them, you just define the functions 
>> once and refer to them everywhere. (Could you do the same with the 
>> annotation based method? Probably, if you allow arbitrary expressions within 
>> them. But that seems less obvious compared to this approach.)
> 
> You make a really good point here.  The annotations would need to be applied 
> to every declaration that uses them whereas your proposed syntax would just 
> rely on overload resolution succeeding or failing in a given type context.  
> The use case I have would benefit in this respect as the conditional defaults 
> would be shared by several declarations.
> 
> Howard’s idea of restricting conditional defaults to only use declarations in 
> the same file seems somewhat arbitrary but it would go a long way towards 
> helping an author understand clearly what the provided defaults are as the 
> rest of the module and imported symbols would not need to be considered.  I 
> wonder if this approach could be refined a bit so it feels less arbitrary.  
> Users would probably need to rely on tooling to discover defaults but I think 
> I’m ok with that.  I am mostly concerned with the ability of an author to 
> reason locally about the API contract they are publishing.  Do you have any 
> ideas on how to refine Howard's idea?
> 
> I mentioned earlier in the thread (with a few messed up details) that there 
> are already some restrictions on default arguments that I think already work 
> well here. Declarations referenced in the default value expression of a 
> function today must be accessible within the scope of the declaration being 
> defined, so I'm not sure if we need to go further than that.
> 
> Here's an example that I'll admit is completely contrived, but should I be 
> prevented from doing this? Let's say I define an "Identities" module with 
> this type:
> 
> ```
> enum Identities {
>   func identity() -> Int { return 0 }  // let's ignore additive vs. 
> multiplicative for a moment
>   func identity() -> Double { return 0.0 }
>   func identity() -> () { return () }
>   func identity() -> String { return "" }
>   func identity() -> (T) -> Void { return { _ in } }
>   // and so on
> }
> ```
> 
> Then somewhere I want to define a conditional default, using those identities:
> 
> ```
> import Identities
> 
> func someWeirdThing( ...contrived args..., defaultValue: T =? 
> Identities.identity()) { ... }
> ```
> 
> Swift today already allows this with regular default value expressions, so 
> the problem of tooling being needed to discover defaults already exists and 
> this hypothetical construct doesn't change that. We *could* restrict such 
> defaults to same file or same module and it seems reasonable to do so, but 
> should we? If the defaults I want happen to live elsewhere, why not let me 
> use them? Or, if it's a serious concern, why not lock down all default 
> expressions the same way?

You make a really good point about the current behavior default value 
expressions that I hadn’t fully considered.  It is currently possible for a 
new, more specific 

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

2017-11-27 Thread Martin Waitz via swift-evolution
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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Tony Allevato via swift-evolution
On Mon, Nov 27, 2017 at 2:39 PM Matthew Johnson 
wrote:

> On Nov 27, 2017, at 4:25 PM, Tony Allevato 
> wrote:
>
>
>
> On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson 
> wrote:
>
>> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Really like Tony’s suggestion, much cleaner than yet another annotation
>> rammed into the signature. Also the idea of a static factory that could
>> accept previously initialized arguments would be very powerful.
>>
>>
>> It is syntactically cleaner at the site of the function declaration for
>> sure.  Wouldn’t you agree that it is semantically less clear though?  Both
>> are important, but which is more important?  If not semantics, why not?
>>
>> It’s also worth noting that it would be more verbose in at least some use
>> cases (when a declaration such as `defaultConfiguration()` is used in the
>> conditional default expression and is not otherwise necessary).
>>
>
> (Apologies for the earlier blank reply—why is Cmd+Enter a keyboard
> shortcut for Send something someone would think is a good idea?)
>
> That verbosity is kind of a feature of my design, in the sense that it
> describes exactly what's going on at the location in code where someone
> expects to see default values. If anything, the default factory name is an
> opportunity to add context where normally there might be none.
>
> It's also worth noting that this design works well if you have multiple
> methods that need to share the same defaults. Instead of repeating the same
> annotations for each method that needs them, you just define the functions
> once and refer to them everywhere. (Could you do the same with the
> annotation based method? Probably, if you allow arbitrary expressions
> within them. But that seems less obvious compared to this approach.)
>
>
> You make a really good point here.  The annotations would need to be
> applied to every declaration that uses them whereas your proposed syntax
> would just rely on overload resolution succeeding or failing in a given
> type context.  The use case I have would benefit in this respect as the
> conditional defaults would be shared by several declarations.
>
> Howard’s idea of restricting conditional defaults to only use declarations
> in the same file seems somewhat arbitrary but it would go a long way
> towards helping an author understand clearly what the provided defaults are
> as the rest of the module and imported symbols would not need to be
> considered.  I wonder if this approach could be refined a bit so it feels
> less arbitrary.  Users would probably need to rely on tooling to discover
> defaults but I think I’m ok with that.  I am mostly concerned with the
> ability of an author to reason locally about the API contract they are
> publishing.  Do you have any ideas on how to refine Howard's idea?
>

I mentioned earlier in the thread (with a few messed up details) that there
are already some restrictions on default arguments that I think already
work well here. Declarations referenced in the default value expression of
a function today must be accessible within the scope of the declaration
being defined, so I'm not sure if we need to go further than that.

Here's an example that I'll admit is completely contrived, but should I be
prevented from doing this? Let's say I define an "Identities" module with
this type:

```
enum Identities {
  func identity() -> Int { return 0 }  // let's ignore additive vs.
multiplicative for a moment
  func identity() -> Double { return 0.0 }
  func identity() -> () { return () }
  func identity() -> String { return "" }
  func identity() -> (T) -> Void { return { _ in } }
  // and so on
}
```

Then somewhere I want to define a conditional default, using those
identities:

```
import Identities

func someWeirdThing( ...contrived args..., defaultValue: T =?
Identities.identity()) { ... }
```

Swift today already allows this with regular default value expressions, so
the problem of tooling being needed to discover defaults already exists and
this hypothetical construct doesn't change that. We *could* restrict such
defaults to same file or same module and it seems reasonable to do so, but
should we? If the defaults I want happen to live elsewhere, why not let me
use them? Or, if it's a serious concern, why not lock down all default
expressions the same way?

I think the bigger concern is the other one Xiaodi mentioned—we probably
don't want people to be able to retroactively add overloads that would
introduce a default where previously there was none. (This wouldn't be
possible for global functions in different modules, but could be for
non-private type members.) This might be something that Just Works Out™
depending on how and when the compiler resolves such expressions—but I
don't know the compiler deeply enough to say for sure without investigating
more.



>
>
>
>
>>
>> -- Howard.
>>
>> 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 4:25 PM, Tony Allevato  wrote:
> 
> 
> 
> On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson  > wrote:
>> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution 
>> > wrote:
>> 
>> Really like Tony’s suggestion, much cleaner than yet another annotation 
>> rammed into the signature. Also the idea of a static factory that could 
>> accept previously initialized arguments would be very powerful. 
> 
> It is syntactically cleaner at the site of the function declaration for sure. 
>  Wouldn’t you agree that it is semantically less clear though?  Both are 
> important, but which is more important?  If not semantics, why not?
> 
> It’s also worth noting that it would be more verbose in at least some use 
> cases (when a declaration such as `defaultConfiguration()` is used in the 
> conditional default expression and is not otherwise necessary).
> 
> (Apologies for the earlier blank reply—why is Cmd+Enter a keyboard shortcut 
> for Send something someone would think is a good idea?)
> 
> That verbosity is kind of a feature of my design, in the sense that it 
> describes exactly what's going on at the location in code where someone 
> expects to see default values. If anything, the default factory name is an 
> opportunity to add context where normally there might be none.
> 
> It's also worth noting that this design works well if you have multiple 
> methods that need to share the same defaults. Instead of repeating the same 
> annotations for each method that needs them, you just define the functions 
> once and refer to them everywhere. (Could you do the same with the annotation 
> based method? Probably, if you allow arbitrary expressions within them. But 
> that seems less obvious compared to this approach.)

You make a really good point here.  The annotations would need to be applied to 
every declaration that uses them whereas your proposed syntax would just rely 
on overload resolution succeeding or failing in a given type context.  The use 
case I have would benefit in this respect as the conditional defaults would be 
shared by several declarations.

Howard’s idea of restricting conditional defaults to only use declarations in 
the same file seems somewhat arbitrary but it would go a long way towards 
helping an author understand clearly what the provided defaults are as the rest 
of the module and imported symbols would not need to be considered.  I wonder 
if this approach could be refined a bit so it feels less arbitrary.  Users 
would probably need to rely on tooling to discover defaults but I think I’m ok 
with that.  I am mostly concerned with the ability of an author to reason 
locally about the API contract they are publishing.  Do you have any ideas on 
how to refine Howard's idea?


> 
> 
>> 
>> -- Howard.
>> 
>> On 26 Nov 2017, at 9:25 am, Tony Allevato via swift-evolution 
>> > wrote:
>> 
>>> On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu >> > wrote:
>>> On Sat, Nov 25, 2017 at 15:06 Matthew Johnson >> > wrote:
 On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution 
 > wrote:
 
 On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution 
 > wrote:
 
 
 
 It's kludgy, but we could have something like:
 
 ```
 @defaultArgument(configuration = (), where R.Configuration == Void)
 @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
 func makeResource(with configuration: R.Configuration, actionHandler: 
 @escaping (R.Action) -> Void) -> R { ... }
 ```
 
 I don't like that we'd be setting a default argument on something 
 lexically before even encountering it in the declaration, but it's 
 serviceable.
 
 
 What if we could take advantage of the fact that you can have non-constant 
 expressions in default arguments? Overload resolution could already do 
 most of the job—what we need on top of that is a way for the author to say 
 that “if no overload matches, then it’s not an error—just don’t have a 
 default argument in that case”. Something like SFINAE in C++, but more 
 explicit.
 
 I’m imagining something like this:
 
 func defaultConfiguration() -> Void {
   return ()
 }
 
 func defaultActionHandler() -> (Never) -> Void {
   return { _ in }
 }
 
 struct ResourceDescription {
   func makeResource(
 with configuration: R.Configuration =? defaultConfiguration(),
 actionHandler: @escaping (R.Action) -> Void =? defaultActionHandler()
   ) -> 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Tony Allevato via swift-evolution
On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson 
wrote:

> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Really like Tony’s suggestion, much cleaner than yet another annotation
> rammed into the signature. Also the idea of a static factory that could
> accept previously initialized arguments would be very powerful.
>
>
> It is syntactically cleaner at the site of the function declaration for
> sure.  Wouldn’t you agree that it is semantically less clear though?  Both
> are important, but which is more important?  If not semantics, why not?
>
> It’s also worth noting that it would be more verbose in at least some use
> cases (when a declaration such as `defaultConfiguration()` is used in the
> conditional default expression and is not otherwise necessary).
>

(Apologies for the earlier blank reply—why is Cmd+Enter a keyboard shortcut
for Send something someone would think is a good idea?)

That verbosity is kind of a feature of my design, in the sense that it
describes exactly what's going on at the location in code where someone
expects to see default values. If anything, the default factory name is an
opportunity to add context where normally there might be none.

It's also worth noting that this design works well if you have multiple
methods that need to share the same defaults. Instead of repeating the same
annotations for each method that needs them, you just define the functions
once and refer to them everywhere. (Could you do the same with the
annotation based method? Probably, if you allow arbitrary expressions
within them. But that seems less obvious compared to this approach.)


>
> -- Howard.
>
> On 26 Nov 2017, at 9:25 am, Tony Allevato via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu  wrote:
>
>> On Sat, Nov 25, 2017 at 15:06 Matthew Johnson 
>> wrote:
>>
>>> On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> It's kludgy, but we could have something like:

 ```
 @defaultArgument(configuration = (), where R.Configuration == Void)
 @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
 func makeResource(with configuration: R.Configuration, actionHandler:
 @escaping (R.Action) -> Void) -> R { ... }
 ```

 I don't like that we'd be setting a default argument on something
 lexically before even encountering it in the declaration, but it's
 serviceable.

>>>
>>>
>>> What if we could take advantage of the fact that you can have
>>> non-constant expressions in default arguments? Overload resolution could
>>> already do most of the job—what we need on top of that is a way for the
>>> author to say that “if no overload matches, then it’s not an error—just
>>> don’t have a default argument in that case”. Something like SFINAE in C++,
>>> but more explicit.
>>>
>>> I’m imagining something like this:
>>>
>>> func defaultConfiguration() -> Void {
>>>   return ()
>>> }
>>> func defaultActionHandler() -> (Never) -> Void {
>>>   return { _ in }
>>> }
>>> struct ResourceDescription {
>>>   func makeResource(
>>> with configuration: R.Configuration *=?* defaultConfiguration(),
>>> actionHandler: @escaping (R.Action) -> Void *=?* defaultActionHandler()
>>>   ) -> R {
>>> // create a resource using the provided configuration
>>> // connect the action handler
>>> // return the resource
>>>   }
>>> }
>>>
>>> The main difference here is the strawman =? syntax, which would
>>> indicate that “the default argument exists if there is a way the RHS can be
>>> satisfied for some instances of the generic arguments; otherwise, there is
>>> no default”, instead of today’s behavior where it would be an error. There
>>> could be multiple overloads of defaultConfiguration and
>>> defaultActionHandler (even ones that are themselves generic) and it
>>> would do the right thing when there are matches and when there aren’t.
>>>
>>> I like this approach because it mostly takes advantage of existing
>>> language features and is fairly lightweight in terms of how it’s expressed
>>> in code compared to regular default arguments—we’d just need to design the
>>> new operator and type-checker logic around it.
>>>
>>> This is an interesting approach.  One advantage to something in this
>>> direction is that it could support defining different defaults for the same
>>> argument under different constraints by overloading the default argument
>>> factories on their return type.
>>>
>>> One concern I have is that it doesn’t allows us to clearly define under
>>> which constraints a default argument is available.  I suspect this might be
>>> problematic especially for public interfaces where source compatibility is

[swift-evolution] [Accepted]

2017-11-27 Thread Ben Cohen via swift-evolution
Hello Swift Community,

The review of of “SE-0188: Make stdlib index types Hashable” ran from November 
8th to 14th, 2017. This proposal has been accepted.

During the review, the only point of discussion was whether to go one step 
further and make conformance to Hashable a requirement for all Collection 
indices. While this would be a source-breaking change, the core team are 
receptive to this proposal being pitched and discussed as a separate evolution 
proposal if it covered the handling of the source compatibility issues.

Thanks to everyone who participated in the review.

Ben
Review Manager

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0189: Restrict Cross-module Struct Initializers

2017-11-27 Thread T.J. Usiyan via swift-evolution
+1 from me.

I have, all along, wished that we could use the designated/convenience
initializer patterns with structs. This moves us a little bit closer, at
least.



On Mon, Nov 27, 2017 at 11:05 AM, Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 27, 2017, at 11:04 AM, Ben Langmuir  wrote:
>
>
>
> On Nov 17, 2017, at 5:59 PM, Slava Pestov  wrote:
>
>
>
> On Nov 17, 2017, at 8:57 PM, Jordan Rose via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Nov 17, 2017, at 15:20, Ben Langmuir  wrote:
>
> Hi Jordan,
>
> First off, this is clearly the model we should have had all along ;-)
>  That said, I have a concern about source-compat and our ability to
> automatically migrate code impacted by this change.
>
> Source compatibility
>
> This makes existing code invalid in Swift 5, which is a source
> compatibility break.
>
> It's not just a source compatibility break, it's a break that cannot
> necessarily be fixed if you don't control the module that vended the
> struct.  If a library doesn't expose an appropriate initializer, there is
> no way for the client to invent one.  Similarly, this isn't going to be
> very amenable to automatic migration, since
> a) there may not be a memberwise initializer to use
> b) even if there is, it may change the semantics to use it
>
> There are two classes that we could theoretically migrate automatically:
> 1) C structs, since we know the initializer and its semantics
> 2) when we are migrating the code that defines the struct at the same time
>
> The latter case might be tricky though, since it requires more global
> knowledge than we have in today's migrator.
>
> Any thoughts?  Do we have an idea how common this is or what kinds of
> places it comes up in most often (in a single codebase with multiple
> modules vs external dependencies vs C structs vs )?
>
>
> This is good to bring up, but I think "this can't be migrated" is the
> correct answer for Swift structs. It's equivalent in my mind to when
> someone was passing 'nil' to something that wasn't annotated for
> nullability and now is marked '_Nonnull': it's source-breaking, and what
> you had before might even have worked, but there's no guarantee that it
> would keep working in the future. That's harder to sell for multi-module
> projects or even test targets, though. I don't have a great answer there,
> but I don't think it's worth bending over backwards to handle the "I
> migrate everything at once" case.
>
> The C case is a bit harder to sell, which is why I made sure there were
> fix-its to suggest inserting `self.init()` (the zeroing initializer) in
> most cases (both in Swift 4 mode and Swift 5 mode). Not all C structs
> *have* that initializer (specifically, if they have a member marked
> _Nonnull), but nearly all do, and that's something the migrator could
> insert fairly easily, as you note.
>
> The mitigating factor I'm hoping for is that these become warnings in
> Swift 4.1, which is planned to ship in a mid-year Xcode (can I admit that
> publicly, swift-evolution?), and that therefore many people will have
> cleaned up their code well before they even think of switching to Swift 5.
> But yes, this is a breaking, non-migratable language change that's only
> strictly necessary for libraries with binary compatibility, which most
> libraries today are not, and that has to be acknowledged.
>
>
> The migrator could also detect special cases, for example:
>
> - there is a public member wise initializer — instead of initializing the
> fields directly, it could suggest adding a call to that instead
>
>
> Are you suggesting we do this even when we don't know the semantics of the
> init we would be calling (e.g. it might introduce new side effects)?  I was
> thinking this would be unsafe to transform automatically, or at least we'd
> want to draw the developer's attention to it to verify it didn't change the
> behaviour.
>
> - there is a public no-argument initializer — here it might be sufficient
> to insert a call to self.init() prior to initializing fields
>
>
> Good point about being able to use the no-arg init, although with the same
> caveat as the previous case I think.
>
>
> Yeah in general the amount of existing code that would be affected by this
> is an open question. This is why we wanted to stage the warning into 4.1
> and see if people complain first.
>
> Slava
>
>
> Ben
>
>
> Slava
>
>
> Jordan___
> 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] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Tony Allevato via swift-evolution
On Mon, Nov 27, 2017 at 2:19 PM Matthew Johnson 
wrote:

> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Really like Tony’s suggestion, much cleaner than yet another annotation
> rammed into the signature. Also the idea of a static factory that could
> accept previously initialized arguments would be very powerful.
>
>
> It is syntactically cleaner at the site of the function declaration for
> sure.  Wouldn’t you agree that it is semantically less clear though?  Both
> are important, but which is more important?  If not semantics, why not?
>
> It’s also worth noting that it would be more verbose in at least some use
> cases (when a declaration such as `defaultConfiguration()` is used in the
> conditional default expression and is not otherwise necessary).
>
>
> -- Howard.
>
> On 26 Nov 2017, at 9:25 am, Tony Allevato via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu  wrote:
>
>> On Sat, Nov 25, 2017 at 15:06 Matthew Johnson 
>> wrote:
>>
>>> On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> It's kludgy, but we could have something like:

 ```
 @defaultArgument(configuration = (), where R.Configuration == Void)
 @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
 func makeResource(with configuration: R.Configuration, actionHandler:
 @escaping (R.Action) -> Void) -> R { ... }
 ```

 I don't like that we'd be setting a default argument on something
 lexically before even encountering it in the declaration, but it's
 serviceable.

>>>
>>>
>>> What if we could take advantage of the fact that you can have
>>> non-constant expressions in default arguments? Overload resolution could
>>> already do most of the job—what we need on top of that is a way for the
>>> author to say that “if no overload matches, then it’s not an error—just
>>> don’t have a default argument in that case”. Something like SFINAE in C++,
>>> but more explicit.
>>>
>>> I’m imagining something like this:
>>>
>>> func defaultConfiguration() -> Void {
>>>   return ()
>>> }
>>> func defaultActionHandler() -> (Never) -> Void {
>>>   return { _ in }
>>> }
>>> struct ResourceDescription {
>>>   func makeResource(
>>> with configuration: R.Configuration *=?* defaultConfiguration(),
>>> actionHandler: @escaping (R.Action) -> Void *=?* defaultActionHandler()
>>>   ) -> R {
>>> // create a resource using the provided configuration
>>> // connect the action handler
>>> // return the resource
>>>   }
>>> }
>>>
>>> The main difference here is the strawman =? syntax, which would
>>> indicate that “the default argument exists if there is a way the RHS can be
>>> satisfied for some instances of the generic arguments; otherwise, there is
>>> no default”, instead of today’s behavior where it would be an error. There
>>> could be multiple overloads of defaultConfiguration and
>>> defaultActionHandler (even ones that are themselves generic) and it
>>> would do the right thing when there are matches and when there aren’t.
>>>
>>> I like this approach because it mostly takes advantage of existing
>>> language features and is fairly lightweight in terms of how it’s expressed
>>> in code compared to regular default arguments—we’d just need to design the
>>> new operator and type-checker logic around it.
>>>
>>> This is an interesting approach.  One advantage to something in this
>>> direction is that it could support defining different defaults for the same
>>> argument under different constraints by overloading the default argument
>>> factories on their return type.
>>>
>>> One concern I have is that it doesn’t allows us to clearly define under
>>> which constraints a default argument is available.  I suspect this might be
>>> problematic especially for public interfaces where source compatibility is
>>> a concern.
>>>
>>
>> It's certainly an interesting idea but it would suggest that the
>> constraints under which a default argument is available can change at
>> runtime. I'm concerned, like you, that this is difficult to reason about.
>> It is still unclear to me how widespread the underlying issue is that
>> requires conditional default arguments, but the conversation thus far has
>> been about compile-time constraints and Tony's design seems to envision
>> much more than that.
>>
>
> This runtime/reasoning problem *already exists* today with default
> arguments, because you can write something like this:
>
> struct Foo {
>   static var defaultExponent = 2.0
>
>   func raise(_ x: Double, to exponent: Double = defaultExponent) {
> print(pow(x, exponent))
>   }
> }
> Foo().raise(4)  // "16.0"Foo.defaultExponent = 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 3:56 PM, Howard Lovatt via swift-evolution 
>  wrote:
> 
> Really like Tony’s suggestion, much cleaner than yet another annotation 
> rammed into the signature. Also the idea of a static factory that could 
> accept previously initialized arguments would be very powerful. 

It is syntactically cleaner at the site of the function declaration for sure.  
Wouldn’t you agree that it is semantically less clear though?  Both are 
important, but which is more important?  If not semantics, why not?

It’s also worth noting that it would be more verbose in at least some use cases 
(when a declaration such as `defaultConfiguration()` is used in the conditional 
default expression and is not otherwise necessary).

> 
> -- Howard.
> 
> On 26 Nov 2017, at 9:25 am, Tony Allevato via swift-evolution 
> > wrote:
> 
>> On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu > > wrote:
>> On Sat, Nov 25, 2017 at 15:06 Matthew Johnson > > wrote:
>>> On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution 
>>> > wrote:
>>> 
>>> On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
>>> It's kludgy, but we could have something like:
>>> 
>>> ```
>>> @defaultArgument(configuration = (), where R.Configuration == Void)
>>> @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
>>> func makeResource(with configuration: R.Configuration, actionHandler: 
>>> @escaping (R.Action) -> Void) -> R { ... }
>>> ```
>>> 
>>> I don't like that we'd be setting a default argument on something lexically 
>>> before even encountering it in the declaration, but it's serviceable.
>>> 
>>> 
>>> What if we could take advantage of the fact that you can have non-constant 
>>> expressions in default arguments? Overload resolution could already do most 
>>> of the job—what we need on top of that is a way for the author to say that 
>>> “if no overload matches, then it’s not an error—just don’t have a default 
>>> argument in that case”. Something like SFINAE in C++, but more explicit.
>>> 
>>> I’m imagining something like this:
>>> 
>>> func defaultConfiguration() -> Void {
>>>   return ()
>>> }
>>> 
>>> func defaultActionHandler() -> (Never) -> Void {
>>>   return { _ in }
>>> }
>>> 
>>> struct ResourceDescription {
>>>   func makeResource(
>>> with configuration: R.Configuration =? defaultConfiguration(),
>>> actionHandler: @escaping (R.Action) -> Void =? defaultActionHandler()
>>>   ) -> R {
>>> // create a resource using the provided configuration
>>> // connect the action handler
>>> // return the resource
>>>   }
>>> }
>>> The main difference here is the strawman =? syntax, which would indicate 
>>> that “the default argument exists if there is a way the RHS can be 
>>> satisfied for some instances of the generic arguments; otherwise, there is 
>>> no default”, instead of today’s behavior where it would be an error. There 
>>> could be multiple overloads of defaultConfiguration and 
>>> defaultActionHandler (even ones that are themselves generic) and it would 
>>> do the right thing when there are matches and when there aren’t.
>>> 
>>> I like this approach because it mostly takes advantage of existing language 
>>> features and is fairly lightweight in terms of how it’s expressed in code 
>>> compared to regular default arguments—we’d just need to design the new 
>>> operator and type-checker logic around it.
>>> 
>> 
>> This is an interesting approach.  One advantage to something in this 
>> direction is that it could support defining different defaults for the same 
>> argument under different constraints by overloading the default argument 
>> factories on their return type.
>> 
>> One concern I have is that it doesn’t allows us to clearly define under 
>> which constraints a default argument is available.  I suspect this might be 
>> problematic especially for public interfaces where source compatibility is a 
>> concern.  
>> 
>> It's certainly an interesting idea but it would suggest that the constraints 
>> under which a default argument is available can change at runtime. I'm 
>> concerned, like you, that this is difficult to reason about. It is still 
>> unclear to me how widespread the underlying issue is that requires 
>> conditional default arguments, but the conversation thus far has been about 
>> compile-time constraints and Tony's design seems to envision much more than 
>> that.
>> 
>> This runtime/reasoning problem already exists today with default arguments, 
>> because you can write something like this:
>> 
>> struct Foo {
>>   static var defaultExponent = 2.0
>> 
>>   func raise(_ x: Double, to exponent: Double = defaultExponent) {

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Howard Lovatt via swift-evolution
You could even restrict to the same file, like extension access to private. 

-- Howard.

> On 26 Nov 2017, at 9:44 am, Tony Allevato via swift-evolution 
>  wrote:
> 
>> On Sat, Nov 25, 2017 at 2:35 PM Xiaodi Wu  wrote:
>>> On Sat, Nov 25, 2017 at 4:25 PM, Tony Allevato  
>>> wrote:
>> 
 On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu  wrote:
>>> 
 On Sat, Nov 25, 2017 at 15:06 Matthew Johnson  
 wrote:
>> On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution 
>>  wrote:
>> 
>> On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>>> It's kludgy, but we could have something like:
>>> 
>>> ```
>>> @defaultArgument(configuration = (), where R.Configuration == Void)
>>> @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
>>> func makeResource(with configuration: R.Configuration, actionHandler: 
>>> @escaping (R.Action) -> Void) -> R { ... }
>>> ```
>>> 
>>> I don't like that we'd be setting a default argument on something 
>>> lexically before even encountering it in the declaration, but it's 
>>> serviceable.
>> 
>> 
>> What if we could take advantage of the fact that you can have 
>> non-constant expressions in default arguments? Overload resolution could 
>> already do most of the job—what we need on top of that is a way for the 
>> author to say that “if no overload matches, then it’s not an error—just 
>> don’t have a default argument in that case”. Something like SFINAE in 
>> C++, but more explicit.
>> 
>> I’m imagining something like this:
>> 
>> func defaultConfiguration() -> Void {
>>   return ()
>> }
>> 
>> func defaultActionHandler() -> (Never) -> Void {
>>   return { _ in }
>> }
>> 
>> struct ResourceDescription {
>>   func makeResource(
>> with configuration: R.Configuration =? defaultConfiguration(),
>> actionHandler: @escaping (R.Action) -> Void =? defaultActionHandler()
>>   ) -> R {
>> // create a resource using the provided configuration
>> // connect the action handler
>> // return the resource
>>   }
>> }
>> The main difference here is the strawman =? syntax, which would indicate 
>> that “the default argument exists if there is a way the RHS can be 
>> satisfied for some instances of the generic arguments; otherwise, there 
>> is no default”, instead of today’s behavior where it would be an error. 
>> There could be multiple overloads of defaultConfiguration and 
>> defaultActionHandler (even ones that are themselves generic) and it 
>> would do the right thing when there are matches and when there aren’t.
>> 
>> I like this approach because it mostly takes advantage of existing 
>> language features and is fairly lightweight in terms of how it’s 
>> expressed in code compared to regular default arguments—we’d just need 
>> to design the new operator and type-checker logic around it.
>> 
> 
> This is an interesting approach.  One advantage to something in this 
> direction is that it could support defining different defaults for the 
> same argument under different constraints by overloading the default 
> argument factories on their return type.
> 
> One concern I have is that it doesn’t allows us to clearly define under 
> which constraints a default argument is available.  I suspect this might 
> be problematic especially for public interfaces where source 
> compatibility is a concern.  
 
 It's certainly an interesting idea but it would suggest that the 
 constraints under which a default argument is available can change at 
 runtime. I'm concerned, like you, that this is difficult to reason about. 
 It is still unclear to me how widespread the underlying issue is that 
 requires conditional default arguments, but the conversation thus far has 
 been about compile-time constraints and Tony's design seems to envision 
 much more than that.
>>> 
>>> This runtime/reasoning problem already exists today with default arguments, 
>>> because you can write something like this:
>>> 
>>> struct Foo {
>>>   static var defaultExponent = 2.0
>>> 
>>>   func raise(_ x: Double, to exponent: Double = defaultExponent) {
>>> print(pow(x, exponent))
>>>   }
>>> }
>>> 
>>> Foo().raise(4)  // "16.0"
>>> Foo.defaultExponent = 3.0
>>> Foo().raise(4)  // "64.0"
>>> Swift lets you write a default value expression that references static (but 
>>> not instance) vars of the enclosing type, as well as anything else that’s 
>>> visible from that expression’s scope. Should people do this? Probably not, 
>>> for the reasons that you described.

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 3:27 PM, Tony Allevato  wrote:
> 
> On Mon, Nov 27, 2017 at 12:49 PM Matthew Johnson  > wrote:
>> On Nov 27, 2017, at 1:24 PM, Tony Allevato > > wrote:
>> 
>> 
>> 
>> On Mon, Nov 27, 2017 at 11:12 AM Matthew Johnson via swift-evolution 
>> > wrote:
>>> On Nov 27, 2017, at 12:50 PM, Douglas Gregor >> > wrote:
>>> 
>>> 
>>> 
 On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
 > wrote:
 
 As mentioned in my prior message, I currently have a PR open to update the 
 generics manifesto (https://github.com/apple/swift/pull/13012 
 ).  I removed one topic from 
 that update at Doug Gregor’s request that it be discussed on the list 
 first.  
 
 The idea is to add the ability to make default arguments conditional (i.e. 
 depend on generic constraints).  It is currently possible to emulate 
 conditional default arguments using an overload set.  This is verbose, 
 especially when several arguments are involved.  Here is an example use 
 case using the overload method to emulate this feature:
 
 ```swift
 protocol Resource {
   associatedtype Configuration
   associatedtype Action
 }
 struct ResourceDescription {
   func makeResource(with configuration: R.Configuration, actionHandler: 
 @escaping (R.Action) -> Void) -> R {
 // create a resource using the provided configuration
 // connect the action handler
 // return the resource
   }
 }
 
 extension ResourceDescription where R.Configuration == Void {
   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
 return makeResource(with: (), actionHandler: actionHandler)
   }
 }
 
 extension ResourceDescription where R.Action == Never {
   func makeResource(with configuration: R.Configuration) -> R {
 return makeResource(with: configuration, actionHandler: { _ in })
   }
 }
 
 extension ResourceDescription where R.Configuration == Void, R.Action == 
 Never {
   func makeResource() -> R {
 return makeResource(with: (), actionHandler: { _ in })
   }
 }
 
 ```
 
 Adding language support for defining these more directly would eliminate a 
 lot of boilerplate and reduce the need for overloads.
>>> 
>>> If one could refer to `self` in a default argument (which is not a big 
>>> problem), you could turn the default into a requirement itself… although it 
>>> doesn’t *quite* work with your example as written because it would always 
>>> need to be implemented somehow:
>>> 
 protocol Resource {
   associatedtype Configuration
   associatedtype Action
>>> func defaultConfiguration() -> Configuration
>>> func defaultHandler() -> ((R.Action) -> Void)
 }
>> 
>> This won’t work on its own for this use case because there is only a valid 
>> default in relatively narrow (but common) cases.  For most values of 
>> Configuration and Action an argument must be provided by the caller.  
>> Xiaodi’s proposed syntax is the best fit (so far) for the use case I had in 
>> mind.  
>> 
>> Out of curiosity, what part of my proposed syntax misses the mark for your 
>> use case?
> 
> I think it’s important that we be clear about when a default is and is not 
> available.  Your syntax makes the availability of a default non-local.
> 
> That's certainly true. It can be mitigated somewhat by placing the 
> definitions as close to the declaration as possible, but it's still up to the 
> user to do the right thing here:
> 
> ```
> struct ResourceDescription {
>   func defaultConfiguration() -> Void { return () }
>   func defaultActionHandler() -> (Never) -> Void { return _ in }
>   func makeResource(...) {
> ...
>   }
> }
> ```
> 
> It's worth noting that this problem does exist somewhat in the language 
> today, if you replace "makes the availability of a default non-local" with 
> "makes the value of a default non-local”.

Non-locality of the value doesn’t bother me.  The availability of the default 
is part of the API contract, the specific value need not be.

> 
>  
> 
>> 
>> The parts that I think are somewhat unfortunate are losing a small bit of 
>> reference locality and the introduction of a new operator to distinguish 
>> between "default argument not present if no match found" vs. “com pile time 
>> error", definitely. However, one unfortunate trend I've noticed when new 
>> features are proposed is that there's a tendency to end up with "let's 
>> invent @yet_another_attribute" and that just doesn't seem scalable or clean 
>> if we can 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Howard Lovatt via swift-evolution
Really like Tony’s suggestion, much cleaner than yet another annotation rammed 
into the signature. Also the idea of a static factory that could accept 
previously initialized arguments would be very powerful. 

-- Howard.

> On 26 Nov 2017, at 9:25 am, Tony Allevato via swift-evolution 
>  wrote:
> 
>> On Sat, Nov 25, 2017 at 1:16 PM Xiaodi Wu  wrote:
>> On Sat, Nov 25, 2017 at 15:06 Matthew Johnson  wrote:
 On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution 
  wrote:
 
 On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution 
  wrote:
 
 
 
> It's kludgy, but we could have something like:
> 
> ```
> @defaultArgument(configuration = (), where R.Configuration == Void)
> @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
> func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R { ... }
> ```
> 
> I don't like that we'd be setting a default argument on something 
> lexically before even encountering it in the declaration, but it's 
> serviceable.
 
 
 What if we could take advantage of the fact that you can have non-constant 
 expressions in default arguments? Overload resolution could already do 
 most of the job—what we need on top of that is a way for the author to say 
 that “if no overload matches, then it’s not an error—just don’t have a 
 default argument in that case”. Something like SFINAE in C++, but more 
 explicit.
 
 I’m imagining something like this:
 
 func defaultConfiguration() -> Void {
   return ()
 }
 
 func defaultActionHandler() -> (Never) -> Void {
   return { _ in }
 }
 
 struct ResourceDescription {
   func makeResource(
 with configuration: R.Configuration =? defaultConfiguration(),
 actionHandler: @escaping (R.Action) -> Void =? defaultActionHandler()
   ) -> R {
 // create a resource using the provided configuration
 // connect the action handler
 // return the resource
   }
 }
 The main difference here is the strawman =? syntax, which would indicate 
 that “the default argument exists if there is a way the RHS can be 
 satisfied for some instances of the generic arguments; otherwise, there is 
 no default”, instead of today’s behavior where it would be an error. There 
 could be multiple overloads of defaultConfiguration and 
 defaultActionHandler (even ones that are themselves generic) and it would 
 do the right thing when there are matches and when there aren’t.
 
 I like this approach because it mostly takes advantage of existing 
 language features and is fairly lightweight in terms of how it’s expressed 
 in code compared to regular default arguments—we’d just need to design the 
 new operator and type-checker logic around it.
 
>>> 
>>> This is an interesting approach.  One advantage to something in this 
>>> direction is that it could support defining different defaults for the same 
>>> argument under different constraints by overloading the default argument 
>>> factories on their return type.
>>> 
>>> One concern I have is that it doesn’t allows us to clearly define under 
>>> which constraints a default argument is available.  I suspect this might be 
>>> problematic especially for public interfaces where source compatibility is 
>>> a concern.  
>> 
>> It's certainly an interesting idea but it would suggest that the constraints 
>> under which a default argument is available can change at runtime. I'm 
>> concerned, like you, that this is difficult to reason about. It is still 
>> unclear to me how widespread the underlying issue is that requires 
>> conditional default arguments, but the conversation thus far has been about 
>> compile-time constraints and Tony's design seems to envision much more than 
>> that.
> 
> This runtime/reasoning problem already exists today with default arguments, 
> because you can write something like this:
> 
> struct Foo {
>   static var defaultExponent = 2.0
> 
>   func raise(_ x: Double, to exponent: Double = defaultExponent) {
> print(pow(x, exponent))
>   }
> }
> 
> Foo().raise(4)  // "16.0"
> Foo.defaultExponent = 3.0
> Foo().raise(4)  // "64.0"
> Swift lets you write a default value expression that references static (but 
> not instance) vars of the enclosing type, as well as anything else that’s 
> visible from that expression’s scope. Should people do this? Probably not, 
> for the reasons that you described.
> 
> But the point is that my example is no more harmful or difficult to reason 
> about than default arguments in the language today. My proposed solution in 
> no way changes the runtime behavior of default argument expressions. I’m not 
> 

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

2017-11-27 Thread Greg Parker via swift-evolution

> On Nov 22, 2017, at 8:55 PM, Alejandro Alonso via swift-evolution 
>  wrote:
> 
> I pushed some updates to the proposal with a reflected API, but I do not 
> agree that we should rid the API of T.random just because some users will 
> misuse it. I think the correct solution here is to include T.random(in:) 
> (which does not return an optional making it not a second typing of (min ... 
> max).random). Like Jonathon said, autocomplete will display both of these and 
> users will be able to select random(in:). I also disagree that T.random is 
> _always_ followed by modulo because if we look at arc4random() it’s range is 
> the whole domain of UInt32. Users don’t put a modulo here because they know 
> the correct way to do it is through arc4random_uniform(), either through 
> online tutorials, or by reading documentation.

What evidence do you have that "users…know the correct way to do it"?

I searched for arc4random and arc4random_uniform in a large Apple codebase.
723 files used arc4random.
296 files used arc4random_uniform.

By eyeball, at least 80% of the arc4random() uses were of the form
arc4random() % something
or 
(some_float_type)arc4random() / something
which are non-uniform ways to get a random integer and floating-point values, 
respectively.

Few calls to arc4random() were obviously initializing random bytes for purposes 
like crypto or networking, but much of Apple's crypto code would likely have 
used other API like arc4random_buf() or CCRandomCopyBytes() so that may not be 
a good estimate.


-- 
Greg Parker gpar...@apple.com  Runtime 
Wrangler


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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-27 Thread Tony Allevato via swift-evolution
On Mon, Nov 27, 2017 at 12:49 PM Matthew Johnson 
wrote:

> On Nov 27, 2017, at 1:24 PM, Tony Allevato 
> wrote:
>
>
>
> On Mon, Nov 27, 2017 at 11:12 AM Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On Nov 27, 2017, at 12:50 PM, Douglas Gregor  wrote:
>>
>>
>>
>> On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> As mentioned in my prior message, I currently have a PR open to update
>> the generics manifesto (https://github.com/apple/swift/pull/13012).  I
>> removed one topic from that update at Doug Gregor’s request that it be
>> discussed on the list first.
>>
>> The idea is to add the ability to make default arguments conditional
>> (i.e. depend on generic constraints).  It is currently possible to emulate
>> conditional default arguments using an overload set.  This is verbose,
>> especially when several arguments are involved.  Here is an example use
>> case using the overload method to emulate this feature:
>>
>> ```swift
>> protocol Resource {
>>   associatedtype Configuration
>>   associatedtype Action
>> }
>> struct ResourceDescription {
>>   func makeResource(with configuration: R.Configuration, actionHandler:
>> @escaping (R.Action) -> Void) -> R {
>> // create a resource using the provided configuration
>> // connect the action handler
>> // return the resource
>>   }
>> }
>>
>> extension ResourceDescription where R.Configuration == Void {
>>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
>> return makeResource(with: (), actionHandler: actionHandler)
>>   }
>> }
>>
>> extension ResourceDescription where R.Action == Never {
>>   func makeResource(with configuration: R.Configuration) -> R {
>> return makeResource(with: configuration, actionHandler: { _ in })
>>   }
>> }
>>
>> extension ResourceDescription where R.Configuration == Void, R.Action ==
>> Never {
>>   func makeResource() -> R {
>> return makeResource(with: (), actionHandler: { _ in })
>>   }
>> }
>>
>> ```
>>
>> Adding language support for defining these more directly would eliminate
>> a lot of boilerplate and reduce the need for overloads.
>>
>>
>> If one could refer to `self` in a default argument (which is not a big
>> problem), you could turn the default into a requirement itself… although it
>> doesn’t *quite* work with your example as written because it would always
>> need to be implemented somehow:
>>
>> protocol Resource {
>>   associatedtype Configuration
>>   associatedtype Action
>>
>> func defaultConfiguration() -> Configuration
>> func defaultHandler() -> ((R.Action) -> Void)
>>
>> }
>>
>>
>> This won’t work on its own for this use case because there is only a
>> valid default in relatively narrow (but common) cases.  For most values of
>> Configuration and Action an argument must be provided by the caller.
>> Xiaodi’s proposed syntax is the best fit (so far) for the use case I had in
>> mind.
>>
>
> Out of curiosity, what part of my proposed syntax misses the mark for your
> use case?
>
>
> I think it’s important that we be clear about when a default is and is not
> available.  Your syntax makes the availability of a default non-local.
>

That's certainly true. It can be mitigated somewhat by placing the
definitions as close to the declaration as possible, but it's still up to
the user to do the right thing here:

```
struct ResourceDescription {
  func defaultConfiguration() -> Void { return () }
  func defaultActionHandler() -> (Never) -> Void { return _ in }
  func makeResource(...) {
...
  }
}
```

It's worth noting that this problem does exist somewhat in the language
today, if you replace "makes the availability of a default non-local" with
"makes the value of a default non-local".



>
>
> The parts that I think are somewhat unfortunate are losing a small bit of
> reference locality and the introduction of a new operator to distinguish
> between "default argument not present if no match found" vs. “com pile time
> error", definitely. However, one unfortunate trend I've noticed when new
> features are proposed is that there's a tendency to end up with "let's
> invent @yet_another_attribute" and that just doesn't seem scalable or clean
> if we can strive to better integrate it into the syntax of the language.
>
>
> Xiaodi acknowledged that his suggestion is a bit clunky but I’m not sure
> we can do better while preserving clarity and making the defaults part of
> the function declaration.  If we added this feature it would be relatively
> advanced and usually used by library developers.  While I would be pleased
> with more elegant syntax I’m not sure there is a better solution.  I prefer
> semantic clarity to syntactic elegance.
>

Why not both? Hopefully we can get some more input from folks who might
have other ideas about how to bring the two ideas together.

For me, grafting on a second 

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

2017-11-27 Thread Chris Lattner via swift-evolution
Thanks David,

-Chris

> On Nov 27, 2017, at 11:43 AM, David Owens  wrote:
> 
> I like the proposal. I think it’s simple and straight forward and provides 
> some really nice ergonomics for working with dynamic data.
> 
> I appreciate the option to change the names too.
> 
> If I understand it correctly, you could also call “add_trick” via:
> 
> dog.addTrick("Roll over");
> 
> And simply update the subscript implementation to provide additional name 
> look-ups. Cool!
> 
> And I like that the DynamicCallable provides the next level that I want to 
> make the API more “Swift-like” and make use of named parameters:
> 
> dog.add(trick: "Roll over");
> 
> Or maybe more appropriate:
> 
> dog.addTrick("Roll over”, favorite: true);
> 
> I didn’t look at the implementation details, but I think the overall 
> approach. I’d like it better if we have provisions to create these types of 
> tools outside of the compiler, but that’s another topic.
> 
> -David
> 
>> 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.
>> 
>> -Chris
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

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


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

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

> On Nov 27, 2017, at 12:54 PM, Dave DeLong  wrote:
> 
> Hi Chris,
> 
> Some questions:
> 
> 1️⃣ How does the subscript approach work for dynamically passing in multiple 
> parameters? For example, what would “dog.addTrick(“Roll Over”, favorite: 
> true)” be when expressed as a subscript method? The subscript syntax only 
> really seems to suit property-style invocations, unless I’m missing something 
> obvious.
> 
> 2️⃣ It seems like “dog.add_trick(…)” would have a dynamic lookup name of 
> “add_trick”. What would the lookup name of “dog.add(trick: …)” be? Or in 
> other words, how do named parameters affect the lookup name?

Hi Dave,

Both of these questions are really about the other proposal, the 
DynamicCallable proposal:
https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d 


It isn’t as refined as the DynamicMemberLookup proposal, but the two do work 
together.

DynamicMemberLookup is only about changing how “x.y” resolves.


> 3️⃣ Can I implement the subscript method multiple times, or is only a single 
> implementation allowed?

Multiple implementations are allowed and are resolved through standard overload 
resolution. Here’s an extract from the test case in the patch:


// References to overloads are resolved just like normal subscript lookup:
+// they are either contextually disambiguated or are invalid.
+struct Ambiguity : DynamicMemberLookupProtocol {
+  subscript(dynamicMember member: String) -> Int {
+return 42
+  }
+  subscript(dynamicMember member: String) -> Float {
+return 42
+  }
+}
+
+func testAmbiguity(a : Ambiguity) {
+  let _ : Int = a.flexibility
+  let _ : Float = a.dynamism
+  _ = a.dynamism  // expected-error {{ambiguous use of 
'subscript(dynamicMember:)'}}
+}
+

> For example, in the JSON example, there’s currently only a dynamic member 
> subscript implementation that returns “JSON?”. Could I add another one that 
> returns “String?” and have the type checker choose the appropriate one based 
> on type inference?

Yes.  It is tricky to actually use such APIs, but they are definitely possible 
and work exactly like current overloads in Swift do.

> As far as naming goes, I’d propose “DynamicMemberForwarding”. In my mind, 
> “Lookup” and “Resolve” are inappropriate, because you’re not actually 
> “looking up” or “resolving” to a particular implementation. In Objective-C, 
> the “+resolveInstanceMethod” stuff expects you to *provide* a method 
> implementation (an IMP). On the other hand, if there isn’t a method 
> implementation (which is the case here), you end up in the 
> “-forwardInvocation:” path, where you can just introspect the NSInvocation 
> and do whatever it is you’re doing to do. So, it seems like this proposal 
> sounds a lot more like ObjC's “invocation forwarding” rather than the method 
> resolution; hence my preference for using “Forwarding” in the name for naming 
> consistency.

Sure, I’m not strongly attached to any of the names in the proposal.

-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-27 Thread Dave DeLong via swift-evolution
Hi Chris,

Some questions:

1️⃣ How does the subscript approach work for dynamically passing in multiple 
parameters? For example, what would “dog.addTrick(“Roll Over”, favorite: true)” 
be when expressed as a subscript method? The subscript syntax only really seems 
to suit property-style invocations, unless I’m missing something obvious.

2️⃣ It seems like “dog.add_trick(…)” would have a dynamic lookup name of 
“add_trick”. What would the lookup name of “dog.add(trick: …)” be? Or in other 
words, how do named parameters affect the lookup name?

3️⃣ Can I implement the subscript method multiple times, or is only a single 
implementation allowed? For example, in the JSON example, there’s currently 
only a dynamic member subscript implementation that returns “JSON?”. Could I 
add another one that returns “String?” and have the type checker choose the 
appropriate one based on type inference?

As far as naming goes, I’d propose “DynamicMemberForwarding”. In my mind, 
“Lookup” and “Resolve” are inappropriate, because you’re not actually “looking 
up” or “resolving” to a particular implementation. In Objective-C, the 
“+resolveInstanceMethod” stuff expects you to *provide* a method implementation 
(an IMP). On the other hand, if there isn’t a method implementation (which is 
the case here), you end up in the “-forwardInvocation:” path, where you can 
just introspect the NSInvocation and do whatever it is you’re doing to do. So, 
it seems like this proposal sounds a lot more like ObjC's “invocation 
forwarding” rather than the method resolution; hence my preference for using 
“Forwarding” in the name for naming consistency.

Dave

> On Nov 26, 2017, at 11: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.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 1:24 PM, Tony Allevato  wrote:
> 
> 
> 
> On Mon, Nov 27, 2017 at 11:12 AM Matthew Johnson via swift-evolution 
> > wrote:
>> On Nov 27, 2017, at 12:50 PM, Douglas Gregor > > wrote:
>> 
>> 
>> 
>>> On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
>>> As mentioned in my prior message, I currently have a PR open to update the 
>>> generics manifesto (https://github.com/apple/swift/pull/13012 
>>> ).  I removed one topic from 
>>> that update at Doug Gregor’s request that it be discussed on the list 
>>> first.  
>>> 
>>> The idea is to add the ability to make default arguments conditional (i.e. 
>>> depend on generic constraints).  It is currently possible to emulate 
>>> conditional default arguments using an overload set.  This is verbose, 
>>> especially when several arguments are involved.  Here is an example use 
>>> case using the overload method to emulate this feature:
>>> 
>>> ```swift
>>> protocol Resource {
>>>   associatedtype Configuration
>>>   associatedtype Action
>>> }
>>> struct ResourceDescription {
>>>   func makeResource(with configuration: R.Configuration, actionHandler: 
>>> @escaping (R.Action) -> Void) -> R {
>>> // create a resource using the provided configuration
>>> // connect the action handler
>>> // return the resource
>>>   }
>>> }
>>> 
>>> extension ResourceDescription where R.Configuration == Void {
>>>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
>>> return makeResource(with: (), actionHandler: actionHandler)
>>>   }
>>> }
>>> 
>>> extension ResourceDescription where R.Action == Never {
>>>   func makeResource(with configuration: R.Configuration) -> R {
>>> return makeResource(with: configuration, actionHandler: { _ in })
>>>   }
>>> }
>>> 
>>> extension ResourceDescription where R.Configuration == Void, R.Action == 
>>> Never {
>>>   func makeResource() -> R {
>>> return makeResource(with: (), actionHandler: { _ in })
>>>   }
>>> }
>>> 
>>> ```
>>> 
>>> Adding language support for defining these more directly would eliminate a 
>>> lot of boilerplate and reduce the need for overloads.
>> 
>> If one could refer to `self` in a default argument (which is not a big 
>> problem), you could turn the default into a requirement itself… although it 
>> doesn’t *quite* work with your example as written because it would always 
>> need to be implemented somehow:
>> 
>>> protocol Resource {
>>>   associatedtype Configuration
>>>   associatedtype Action
>> func defaultConfiguration() -> Configuration
>> func defaultHandler() -> ((R.Action) -> Void)
>>> }
> 
> This won’t work on its own for this use case because there is only a valid 
> default in relatively narrow (but common) cases.  For most values of 
> Configuration and Action an argument must be provided by the caller.  
> Xiaodi’s proposed syntax is the best fit (so far) for the use case I had in 
> mind.  
> 
> Out of curiosity, what part of my proposed syntax misses the mark for your 
> use case?

I think it’s important that we be clear about when a default is and is not 
available.  Your syntax makes the availability of a default non-local.

> 
> The parts that I think are somewhat unfortunate are losing a small bit of 
> reference locality and the introduction of a new operator to distinguish 
> between "default argument not present if no match found" vs. “com pile time 
> error", definitely. However, one unfortunate trend I've noticed when new 
> features are proposed is that there's a tendency to end up with "let's invent 
> @yet_another_attribute" and that just doesn't seem scalable or clean if we 
> can strive to better integrate it into the syntax of the language.

Xiaodi acknowledged that his suggestion is a bit clunky but I’m not sure we can 
do better while preserving clarity and making the defaults part of the function 
declaration.  If we added this feature it would be relatively advanced and 
usually used by library developers.  While I would be pleased with more elegant 
syntax I’m not sure there is a better solution.  I prefer semantic clarity to 
syntactic elegance.

> 
> I'm particularly interested in this because I hit a use case that's similar 
> to yours in my own code base. I wanted a generic type that could be 
> instantiated with a disjoint type set—either a RawRepresentable whose 
> RawValue is Int, or an Int itself. This could have been solved by having Int 
> retroactively conform to RawRepresentable, but doing that to a fundamental 
> built-in type Feels Dirty™, so I made it work by not constraining the generic 
> type at all and moving the public initializers to constrained extensions so 
> that the only way you could *instantiate* the type is if you 

Re: [swift-evolution] [Review] SE-0190: Target environment platform condition

2017-11-27 Thread Graydon Hoare via swift-evolution

> On Nov 20, 2017, at 4:17 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I think the functionality is good, but I would like to see some thought on 
> what future values could be to see if this is the best name/structure.

As mentioned in a bit more detail in the other email I just posted, this 
proposal is to reflect values that occur in the "environment" field of the 
target triple; therefore possible future values would only be those that occur 
in practice in different toolchain variants: different libcs, different ABIs, 
similar miscellaneous variation within a given arch-vendor-os triple.

> If it is just going to be the concept of a simulator, then something like 
> isSimulated() might be better.  In the current form, I think we should have 
> both ‘Simulator’ and ‘Device’ as options.

Ah yes, I forgot to mention this in the "alternatives considered" section. An 
earlier draft did indeed include "device" as a synonym for non-simulator, but 
this was noted as conflicting with the way the environment field of triples 
actually works: it's optional and may be either empty or one of several 
specific values, of which 'device' is not an option. I.e. one does not specify 
non-simulator by saying arm64-apple-tvos-device, one simply says 
arm64-apple-tvos, and omits the -simulator 4th field.

> I would also like to see something shorter than targetEnvironment(), but it 
> is somewhat infrequently used, so it isn’t that big a deal.  It is just 
> compared to os() and arch(), this is kind of a beast.  It is a power user 
> thing, so maybe something like ‘env()’ would work?  I normally try to avoid 
> abbreviations, but we have arch() as precedent.  The word ‘Simulator’ should 
> be what stands out...

As mentioned in the "alternatives considered" section, "env" or "environment" 
was considered, but several people noted this is very easily confused as a 
means to access environment variables in the compilation process, which this 
proposal is not.

> Would Testing be a possible future environment?

I do not believe so, it's not a way people presently use the environment field 
of a target triple.

-Graydon

>> Is the problem being addressed significant enough to warrant a change to 
>> Swift?
>> 
> Yes, Definitely!
> 
>> Does this proposal fit well with the feel and direction of Swift?
>> 
> Yes.
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
> I guess Objective C had something like this as well, which was more powerful, 
> but also more messy.
>> How much effort did you put into your review? A glance, a quick reading, or 
>> an in-depth study?
>> 
> Quick Read
> 
> ___
> 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] [Review] SE-0190: Target environment platform condition

2017-11-27 Thread Graydon Hoare via swift-evolution
Sorry I was away last week, didn't see these review questions until now.

> On Nov 20, 2017, at 2:58 PM, Rod Brown via swift-evolution 
>  wrote:
>> What is your evaluation of the proposal?
>> 
> I think it’s good in theory, but I am concerned that there is currently only 
> one example case of “simulator”, which also seems somewhat limited to Apple 
> Platforms. Would another case “device” make sense?
> 
> Also a few questions I have:
> How would this be extended to make sense for each platform? Say on platforms 
> that actually have an emulator (rather than a simulator) how would this apply 
> to those cases?
> How does it make sense for the desktop where we could compile on the 
> platform, and there would *be* no simulator?
> Could there be other relevant cases we can add at other times?
> Would these cases only make sense for Platform Vendors or IDEs to manage?

The proposal is to track the "environment" field of target triples directly, as 
the existing platform conditions track the arch and os fields. Therefore I'll 
answer these questions -- in the context of this proposal -- in terms of target 
triples, which are typically defined and managed a few steps outside the Swift 
language, at the level of platform toolchains (i.e. including the C and C++ 
compiler, linker, runtime libraries, SDKs, etc.)

At present, many but not all details of target triples are surfaced in Swift 
platform conditions. For example, the difference between "arm" (32bit) and 
"arm64" is surfaced in values accepted by the the "arch()" platform condition 
of Swift, but the difference between various 32bit arm sub-architectures (eg. 
armv7s vs. armv7k) is not surfaced. In theory this could be, but I think it 
hasn't come up as a requirement for anyone yet to build Swift code that's 
conditional on that difference (and not conditional on a more salient 
difference, like OS).

The "environment" field of the target triple is used, in practice, to mean many 
different things; it's an "optional disambiguation" field when there are two or 
more targets that are meaningfully-different at a toolchain level (eg. separate 
SDKs, target libraries, runtimes or such) but that are not otherwise 
differentiated in the first 3 fields of the triple (arch, vendor, OS).

So, for example, with respect to question #1, if one has a platform that 
supports "emulator" as an environment component of the triple, and users had 
any interest in inspecting or switching on it, Swift could meaningfully surface 
that value here in the future.

The current set of values used in the environment field _in LLVM_ is a bit of a 
grab bag of "not otherwise specified" dimensions of target variation: ABI 
specifications ("eabi" vs. "gnueabihf"), runtime libraries ("musl"), execution 
engines ("opencl", "coreclr"), or other miscellaneous software-environment 
switching ("gnu", "android", "cygnus"). It's also used in some contexts to 
switch between different object file formats. There is not presently a target 
environment that uses "emulator" and I suspect if one wanted to start, they 
might recycle "simulator" just to avoid adding near-synonyms.

In any case, I don't expect all of these to need to surface as values in the 
proposed targetEnvironment platform condition, but if any were to need to 
surface, the idea would be to just pass the name of the environment field 
through to the condition, as with "simulator".

With respect to question #2, the behaviour of Swift code that's conditional on 
"#if targetEnvironment(simulator)" would be the same on a target with no 
simulator variants as it would be when targeting the non-simulator variant of a 
target that has a simulator variant: the condition would evaluate to false, 
since the 4th (environment) field of the triple would not be equal to 
"simulator". Note that independent of this proposal, not every combination of 
fields in a triple is meaningful: one cannot (say) compile for 
s390x-unknown-PS4 because despite all 3 fields being piecewise valid, no such 
combined target exists (to my knowledge), or certainly not in any toolchain 
I've seen. The behaviour will depend on whether or not toolchain support 
actually exists for some target in question; and at the Swift level, it is 
equally legal to compose a platform condition that will never be true on a 
given toolchain -- eg. "#if arch(s390x) && os(PS4)" -- because it specifies a 
combination of target triple values that isn't supported.

With respect to #3, yes, other values could surface, I think I actually 
addressed this above.

Finally with respect to #4, this proposal isn't intended to dictate who or what 
adds new fields to triples, merely provide an outlet for such values to be 
surfaced (and to surface one that users are already switching on). The values 
that wind up in the "environment" field of a triple are determined by means 
outside the scope of this proposal (typically platform vendors submitting 
support for an 

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

2017-11-27 Thread David Owens via swift-evolution
I like the proposal. I think it’s simple and straight forward and provides some 
really nice ergonomics for working with dynamic data.

I appreciate the option to change the names too.

If I understand it correctly, you could also call “add_trick” via:

dog.addTrick("Roll over");

And simply update the subscript implementation to provide additional name 
look-ups. Cool!

And I like that the DynamicCallable provides the next level that I want to make 
the API more “Swift-like” and make use of named parameters:

dog.add(trick: "Roll over");

Or maybe more appropriate:

dog.addTrick("Roll over”, favorite: true);

I didn’t look at the implementation details, but I think the overall approach. 
I’d like it better if we have provisions to create these types of tools outside 
of the compiler, but that’s another topic.

-David

> 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.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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

> On Nov 27, 2017, at 12:50 PM, Douglas Gregor  wrote:
> 
> 
> 
>> On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> As mentioned in my prior message, I currently have a PR open to update the 
>> generics manifesto (https://github.com/apple/swift/pull/13012 
>> ).  I removed one topic from that 
>> update at Doug Gregor’s request that it be discussed on the list first.  
>> 
>> The idea is to add the ability to make default arguments conditional (i.e. 
>> depend on generic constraints).  It is currently possible to emulate 
>> conditional default arguments using an overload set.  This is verbose, 
>> especially when several arguments are involved.  Here is an example use case 
>> using the overload method to emulate this feature:
>> 
>> ```swift
>> protocol Resource {
>>   associatedtype Configuration
>>   associatedtype Action
>> }
>> struct ResourceDescription {
>>   func makeResource(with configuration: R.Configuration, actionHandler: 
>> @escaping (R.Action) -> Void) -> R {
>> // create a resource using the provided configuration
>> // connect the action handler
>> // return the resource
>>   }
>> }
>> 
>> extension ResourceDescription where R.Configuration == Void {
>>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
>> return makeResource(with: (), actionHandler: actionHandler)
>>   }
>> }
>> 
>> extension ResourceDescription where R.Action == Never {
>>   func makeResource(with configuration: R.Configuration) -> R {
>> return makeResource(with: configuration, actionHandler: { _ in })
>>   }
>> }
>> 
>> extension ResourceDescription where R.Configuration == Void, R.Action == 
>> Never {
>>   func makeResource() -> R {
>> return makeResource(with: (), actionHandler: { _ in })
>>   }
>> }
>> 
>> ```
>> 
>> Adding language support for defining these more directly would eliminate a 
>> lot of boilerplate and reduce the need for overloads.
> 
> If one could refer to `self` in a default argument (which is not a big 
> problem), you could turn the default into a requirement itself… although it 
> doesn’t *quite* work with your example as written because it would always 
> need to be implemented somehow:
> 
>> protocol Resource {
>>   associatedtype Configuration
>>   associatedtype Action
> func defaultConfiguration() -> Configuration
> func defaultHandler() -> ((R.Action) -> Void)
>> }

This won’t work on its own for this use case because there is only a valid 
default in relatively narrow (but common) cases.  For most values of 
Configuration and Action an argument must be provided by the caller.  Xiaodi’s 
proposed syntax is the best fit (so far) for the use case I had in mind.  

That said, the ability to refer to self in default arguments is complementary 
as it would expand the cases where conditional default arguments could be 
provided.  For example, in the example above it would allow a resource to 
provide a nontrivial default configuration.

> 
>>  Doug mentioned that it may also help simplify associated type inference 
>> (https://github.com/apple/swift/pull/13012#discussion_r152124535 
>> ).
> 
> Oh, I thought this was something related to choosing a defaults for 
> associated types, which might have helped with my current 
> associated-type-inference quandary. The topic you actually wanted to discuss 
> is disjoint (sorry).

I was wondering how it was related and wondered if it was somehow due to 
reduction in the size of the overload set.  If you have any ideas on changes 
that might help guide the inference algorithm somehow please start a new 
thread.  Even if you’re only able to describe the challenges it might be worth 
a thread if it’s possible others might have useful ideas.  Improving the 
reliability and predictability of inference is a very important topic!

> 
>   - Doug
> 
> 

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0189: Restrict Cross-module Struct Initializers

2017-11-27 Thread Slava Pestov via swift-evolution


> On Nov 27, 2017, at 11:04 AM, Ben Langmuir  wrote:
> 
> 
> 
>> On Nov 17, 2017, at 5:59 PM, Slava Pestov > > wrote:
>> 
>> 
>> 
>>> On Nov 17, 2017, at 8:57 PM, Jordan Rose via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
 On Nov 17, 2017, at 15:20, Ben Langmuir > wrote:
 
 Hi Jordan,
 
 First off, this is clearly the model we should have had all along ;-)  
 That said, I have a concern about source-compat and our ability to 
 automatically migrate code impacted by this change.
> Source compatibility
> 
> This makes existing code invalid in Swift 5, which is a source 
> compatibility break.
> 
 It's not just a source compatibility break, it's a break that cannot 
 necessarily be fixed if you don't control the module that vended the 
 struct.  If a library doesn't expose an appropriate initializer, there is 
 no way for the client to invent one.  Similarly, this isn't going to be 
 very amenable to automatic migration, since
 a) there may not be a memberwise initializer to use
 b) even if there is, it may change the semantics to use it
 
 There are two classes that we could theoretically migrate automatically:
 1) C structs, since we know the initializer and its semantics
 2) when we are migrating the code that defines the struct at the same time
 
 The latter case might be tricky though, since it requires more global 
 knowledge than we have in today's migrator.
 
 Any thoughts?  Do we have an idea how common this is or what kinds of 
 places it comes up in most often (in a single codebase with multiple 
 modules vs external dependencies vs C structs vs )?
>>> 
>>> This is good to bring up, but I think "this can't be migrated" is the 
>>> correct answer for Swift structs. It's equivalent in my mind to when 
>>> someone was passing 'nil' to something that wasn't annotated for 
>>> nullability and now is marked '_Nonnull': it's source-breaking, and what 
>>> you had before might even have worked, but there's no guarantee that it 
>>> would keep working in the future. That's harder to sell for multi-module 
>>> projects or even test targets, though. I don't have a great answer there, 
>>> but I don't think it's worth bending over backwards to handle the "I 
>>> migrate everything at once" case.
>>> 
>>> The C case is a bit harder to sell, which is why I made sure there were 
>>> fix-its to suggest inserting `self.init()` (the zeroing initializer) in 
>>> most cases (both in Swift 4 mode and Swift 5 mode). Not all C structs have 
>>> that initializer (specifically, if they have a member marked _Nonnull), but 
>>> nearly all do, and that's something the migrator could insert fairly 
>>> easily, as you note.
>>> 
>>> The mitigating factor I'm hoping for is that these become warnings in Swift 
>>> 4.1, which is planned to ship in a mid-year Xcode (can I admit that 
>>> publicly, swift-evolution?), and that therefore many people will have 
>>> cleaned up their code well before they even think of switching to Swift 5. 
>>> But yes, this is a breaking, non-migratable language change that's only 
>>> strictly necessary for libraries with binary compatibility, which most 
>>> libraries today are not, and that has to be acknowledged.
>> 
>> The migrator could also detect special cases, for example:
>> 
>> - there is a public member wise initializer — instead of initializing the 
>> fields directly, it could suggest adding a call to that instead
> 
> Are you suggesting we do this even when we don't know the semantics of the 
> init we would be calling (e.g. it might introduce new side effects)?  I was 
> thinking this would be unsafe to transform automatically, or at least we'd 
> want to draw the developer's attention to it to verify it didn't change the 
> behaviour.
> 
>> - there is a public no-argument initializer — here it might be sufficient to 
>> insert a call to self.init() prior to initializing fields
> 
> Good point about being able to use the no-arg init, although with the same 
> caveat as the previous case I think.

Yeah in general the amount of existing code that would be affected by this is 
an open question. This is why we wanted to stage the warning into 4.1 and see 
if people complain first.

Slava

> 
> Ben
> 
>> 
>> Slava
>> 
>>> 
>>> Jordan___
>>> 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] [swift-evolution-announce] [Review] SE-0189: Restrict Cross-module Struct Initializers

2017-11-27 Thread Ben Langmuir via swift-evolution


> On Nov 17, 2017, at 5:59 PM, Slava Pestov  wrote:
> 
> 
> 
>> On Nov 17, 2017, at 8:57 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On Nov 17, 2017, at 15:20, Ben Langmuir >> > wrote:
>>> 
>>> Hi Jordan,
>>> 
>>> First off, this is clearly the model we should have had all along ;-)  That 
>>> said, I have a concern about source-compat and our ability to automatically 
>>> migrate code impacted by this change.
 Source compatibility
 
 This makes existing code invalid in Swift 5, which is a source 
 compatibility break.
 
>>> It's not just a source compatibility break, it's a break that cannot 
>>> necessarily be fixed if you don't control the module that vended the 
>>> struct.  If a library doesn't expose an appropriate initializer, there is 
>>> no way for the client to invent one.  Similarly, this isn't going to be 
>>> very amenable to automatic migration, since
>>> a) there may not be a memberwise initializer to use
>>> b) even if there is, it may change the semantics to use it
>>> 
>>> There are two classes that we could theoretically migrate automatically:
>>> 1) C structs, since we know the initializer and its semantics
>>> 2) when we are migrating the code that defines the struct at the same time
>>> 
>>> The latter case might be tricky though, since it requires more global 
>>> knowledge than we have in today's migrator.
>>> 
>>> Any thoughts?  Do we have an idea how common this is or what kinds of 
>>> places it comes up in most often (in a single codebase with multiple 
>>> modules vs external dependencies vs C structs vs )?
>> 
>> This is good to bring up, but I think "this can't be migrated" is the 
>> correct answer for Swift structs. It's equivalent in my mind to when someone 
>> was passing 'nil' to something that wasn't annotated for nullability and now 
>> is marked '_Nonnull': it's source-breaking, and what you had before might 
>> even have worked, but there's no guarantee that it would keep working in the 
>> future. That's harder to sell for multi-module projects or even test 
>> targets, though. I don't have a great answer there, but I don't think it's 
>> worth bending over backwards to handle the "I migrate everything at once" 
>> case.
>> 
>> The C case is a bit harder to sell, which is why I made sure there were 
>> fix-its to suggest inserting `self.init()` (the zeroing initializer) in most 
>> cases (both in Swift 4 mode and Swift 5 mode). Not all C structs have that 
>> initializer (specifically, if they have a member marked _Nonnull), but 
>> nearly all do, and that's something the migrator could insert fairly easily, 
>> as you note.
>> 
>> The mitigating factor I'm hoping for is that these become warnings in Swift 
>> 4.1, which is planned to ship in a mid-year Xcode (can I admit that 
>> publicly, swift-evolution?), and that therefore many people will have 
>> cleaned up their code well before they even think of switching to Swift 5. 
>> But yes, this is a breaking, non-migratable language change that's only 
>> strictly necessary for libraries with binary compatibility, which most 
>> libraries today are not, and that has to be acknowledged.
> 
> The migrator could also detect special cases, for example:
> 
> - there is a public member wise initializer — instead of initializing the 
> fields directly, it could suggest adding a call to that instead

Are you suggesting we do this even when we don't know the semantics of the init 
we would be calling (e.g. it might introduce new side effects)?  I was thinking 
this would be unsafe to transform automatically, or at least we'd want to draw 
the developer's attention to it to verify it didn't change the behaviour.

> - there is a public no-argument initializer — here it might be sufficient to 
> insert a call to self.init() prior to initializing fields

Good point about being able to use the no-arg init, although with the same 
caveat as the previous case I think.

Ben

> 
> Slava
> 
>> 
>> Jordan___
>> 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-27 Thread Chris Lattner via swift-evolution
On Nov 27, 2017, at 8:57 AM, Mathew Huusko V  wrote:
> You're saying that there is universally no inherent difference, and that all 
> calls "determine if you have called it" correctly, but then picked one of 
> only a handful of cases in current practice where that is actually true. Yes 
> "+" (/other math operators) and array access are unsafe, but most other 
> things in Swift are safe by default, and you have to opt into un-safety (e.g. 
> forcing or checking an optional or throwing call) — this is a main tenant of 
> the language.

There is nothing unsafe about this proposal.  It is fully type safe and 
supports failable operations (by having the properties typed as optionals).  
This is shows by example in the proposal.

Your explanation above is so confusing to me.  The closest analog to this 
feature is AnyObject dynamic lookup, which *is* completely unsafe, and is 
pervasively tangled throughout the compiler.   Maybe you’re confusing the two.

-Chris

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


Re: [swift-evolution] [Pre-pitch] Conditional default arguments

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


> On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> As mentioned in my prior message, I currently have a PR open to update the 
> generics manifesto (https://github.com/apple/swift/pull/13012 
> ).  I removed one topic from that 
> update at Doug Gregor’s request that it be discussed on the list first.  
> 
> The idea is to add the ability to make default arguments conditional (i.e. 
> depend on generic constraints).  It is currently possible to emulate 
> conditional default arguments using an overload set.  This is verbose, 
> especially when several arguments are involved.  Here is an example use case 
> using the overload method to emulate this feature:
> 
> ```swift
> protocol Resource {
>   associatedtype Configuration
>   associatedtype Action
> }
> struct ResourceDescription {
>   func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R {
> // create a resource using the provided configuration
> // connect the action handler
> // return the resource
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void {
>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
> return makeResource(with: (), actionHandler: actionHandler)
>   }
> }
> 
> extension ResourceDescription where R.Action == Never {
>   func makeResource(with configuration: R.Configuration) -> R {
> return makeResource(with: configuration, actionHandler: { _ in })
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void, R.Action == 
> Never {
>   func makeResource() -> R {
> return makeResource(with: (), actionHandler: { _ in })
>   }
> }
> 
> ```
> 
> Adding language support for defining these more directly would eliminate a 
> lot of boilerplate and reduce the need for overloads.

If one could refer to `self` in a default argument (which is not a big 
problem), you could turn the default into a requirement itself… although it 
doesn’t *quite* work with your example as written because it would always need 
to be implemented somehow:

> protocol Resource {
>   associatedtype Configuration
>   associatedtype Action
func defaultConfiguration() -> Configuration
func defaultHandler() -> ((R.Action) -> Void)
> }


>  Doug mentioned that it may also help simplify associated type inference 
> (https://github.com/apple/swift/pull/13012#discussion_r152124535 
> ).

Oh, I thought this was something related to choosing a defaults for associated 
types, which might have helped with my current associated-type-inference 
quandary. The topic you actually wanted to discuss is disjoint (sorry).

- Doug


___
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-27 Thread BJ Homer via swift-evolution
I like the proposal. Having a “magic” protocol isn’t ideal in some ways, but it 
seems like the best option for the moment, considering the other restrictions.

The name “DynamicMemberLookupProtocol” is a bit unwieldy, though. What about 
something like “SupportsDynamicMemberLookup“ or "SupportsDynamicMembers"? I 
know it doesn’t follow the usual protocol naming pattern, but for an empty 
“magic” protocol like this, it reads fairly well as a description of the 
capabilities of the type:

enum JSON: SupportsDynamicMemberLookup {
   // ...
}

Anyway, I like the proposal. The “Supports-“ prefix on the name may be a good 
idea, or may not. Either way, the “JSON” example in the proposal shows how this 
is useful for more than just bridging to dynamic languages, and is quite 
compelling to me.

-BJ


> On Nov 26, 2017, at 11: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.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2017-11-27 Thread Chris Lattner via swift-evolution
On Nov 27, 2017, at 6:37 AM, Mathew Huusko V  wrote:
> I tuned out the initial discussions of this proposal because there seemed to 
> be a lot of noise centered around implementation/maintainability.

There was some noise, but as I believe the patch shows, it was misplaced.

> I'm curious if the actual premise of the syntactic/sugar conversion has been 
> discussed/debated yet? i.e. making dynamic/stringly calls look like normal 
> calls is very clean, but it's also very misleading (by definition; they're 
> not normal/safe/checked calls) with a potential net reduction in ergonomics.

In fact, the calls are fully type safe and checked.  The JSON example shows 
that.

I think what you’re getting at here is that there is opportunity to misuse this 
feature.  It is certainly not something that every one should use commonly on 
their types: it’s a power feature that is extremely important for some narrow 
cases.  

I’ll observe that this is exactly the sort of feature that Swift traditionally 
includes, and there are many examples of this: generalized operator 
overloading, the ability to syntax extend almost everything in the language 
(e.g. literals), user defined pattern matching in switches, etc.  

> Anyway, there's my primary concern. Has this been addressed yet? Has any 
> thought been given to requiring '?'/'!' on these calls (or some other symbol, 
> but this would retain some cleanliness..) to opt into the inherent 
> fallibility and distinguish them visually?

This feature isn’t unsafe at all, I’m not sure why that would be appropriate.

-Chris


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


Re: [swift-evolution] [draft] Add last(where:) and lastIndex(where:) Methods

2017-11-27 Thread Adrian Zubarev via swift-evolution
I like it, but only if the API is symmetric. However this would require the 
break existing API to make `firstIndex(where/of:)`. 

One question:

Can we maybe add retroactively an extra parameter with a default value?

Something like: `func index(where predicate: (Element) throws -> Bool, 
traverseDirection: TraverseDirection = .leftToRight)`

However this comes at a cost of loosing the trailing closure :/


Am 27. November 2017 um 17:31:19, Nate Cook via swift-evolution 
(swift-evolution@swift.org) schrieb:

Hello, Swift Evolution!

This is a revision of a previous proposal for adding methods to 
sequences/collections for searching from the end. Feedback welcome!

Nate


—



Add last(where:) and lastIndex(where:) Methods
Proposal: SE-
Author: Nate Cook
Status: Awaiting review
Review manager: TBD
Implementation: Branch on natecook1000/swift
Related Bug: [SR-1504] RFE: index(of:) but starting from end
Introduction
The standard library should include methods for finding the last element in a 
sequence, and the index of the last element in a collection, that match a given 
predicate.

Swift-evolution thread: [swift-evolution] (Draft) Add last(where:) and 
lastIndex(where:) methods
Motivation
The standard library currently has methods that perform a linear search to find 
an element or the index of an element that matches a predicate:

Swift
let a = [20, 30, 10, 40, 20, 30, 10, 40, 20]
a.first(where: { $0 > 25 }) // 30
a.index(where: { $0 > 25 }) // 1
a.index(of: 10) // 2
Unfortunately, there are no such methods that search from the end. Finding the 
last of a particular kind of element has multiple applications, particularly 
with text, such as wrapping a long string into lines of a maximum length or 
trimming whitespace from the beginning and end of a string.

You can work around this limitation by using the methods above on a reversed 
view of a collection, but the resulting code is frankly appalling. For example, 
to find the corresponding last index to a.index(where: { $0 > 25 }), something 
like this unholy incantation is required:

Swift
(a.reversed().index(where: { $0 > 25 })?.base).map({ a.index(before: $0) })
Proposed solution
The Sequence protocol should add a last(where:) method, and the 
Collectionprotocol should add lastIndex(where:) and lastIndex(of:) methods. 
These new methods create symmetry with the existing forward-searching APIs that 
are already part of Sequence and Collection.

These additions remove the need for searching in a reversed collection and 
allow code like this:

Swift
a.last(where: { $0 > 25 })  // 40
a.lastIndex(where: { $0 > 25 }) // 7
a.lastIndex(of: 10) // 6
Much better!

Detailed design
last(where:) and lastIndex(where:) will be added to the standard library as 
Sequence and Collection protocol requirements, respectively. These methods will 
have default implementations in their respective protocols and in 
BidirectionalCollection, which can provide a more efficient implementation. 
lastIndex(of:) will be provided in Collection and BidirectionalCollection 
extensions constrained to Equatable elements. 

The new APIs are shown here:

Swift
protocol Sequence {
// Existing declarations...

/// Returns the last element of the collection that satisfies the given
/// predicate, or `nil` if no element does. The sequence must be finite.
func last(where predicate: (Element) throws -> Bool)  
rethrows -> Element?
}

protocol Collection {
// Existing declarations...
 
/// Returns the index of the last element of the collection that satisfies  
/// the given predicate, or `nil` if no element does.
func lastIndex(where predicate: (Element) throws -> Bool)  
rethrows -> Index?  
}

extension BidirectionalCollection {
func last(where predicate: (Element) throws -> Bool)  
rethrows -> Element? { ... }

func lastIndex(where predicate: (Element) throws -> Bool)  
rethrows -> Index? { ... }
}

extension Collection where Element: Equatable {
/// Returns the index of the last element equal to the given element, or  
/// no matching element is found.
func lastIndex(of element: Element) -> Index? { ... }
}

extension BidirectionalCollection where Element: Equatable {
func lastIndex(of element: Element) -> Index? { ... }
}
You can explore the usage (but not really the performance) of these methods in 
this Swift sandbox.

Source compatibility
The addition of the last(where:), lastIndex(where:), and lastIndex(of:)methods 
is strictly additive and should have no impact on existing code.

Effect on ABI stability & API resilience
This change does not affect ABI stability or API resilience beyond the addition 
of the new methods.

Alternatives considered
A previous proposal limited the new methods to the BidirectionalCollection 
protocol. This isn't a necessary limitation, as the standard library already 
has methods on sequences and 

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

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

> On Nov 27, 2017, at 2:56 AM, Tino Heth <2...@gmx.de> wrote:
> 
> 
>> The implementation is straight-forward and (IMO) non-invasive in the 
>> compiler.
> At least it’s smaller than I would have expected — but I don’t have the 
> overview to judge the consequences to the compiler.
> 
> However, the impact those two proposals have on Swift is imho huge, and as 
> the whole story is quite special for several reasons, there’s an elephant in 
> the room that shouldn’t be ignored:
> - What would you do if the proposal isn’t accepted?

Circle back and try to solve the problem another way?  It depends on why it 
would be rejected.

> - What does core think you would do in this case?

The core team officially weighs in after the review process, not before.

> - What impact will that speculation have on the decision?

It should be zero.  The point of the review process is to weigh the merits of a 
proposal.

In any case, FWIW, I don’t find your email very helpful, since you’re not 
actually talking about technical merits of the proposal: you’re encouraging 
speculation about politics :-)

-Chris

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


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

2017-11-27 Thread TellowKrinkle via swift-evolution
So why is it more important for the random method on a collection to have a 
special method that guarantees a discrete uniform distribution than it is for 
an Int?  If you’re going to split on guaranteed-discrete-uniform vs 
maybe-discrete-uniform, why not split on discrete-uniform vs 
not-discrete-uniform (note: I would not want either of these)?

Why not just let everything be maybe-discrete-uniform and then specify:
- Things involving discrete sets (including collections and ranges of discrete 
values like ints) return a discrete uniform distribution
- Things involving continuous ranges (including ranges of floating-point types) 
return a continuous uniform distribution
I don’t really see the point in differentiating between a discrete and 
continuous distribution, since it makes no sense to use a continuous 
distribution for things that are discrete, and it also makes no sense to use a 
discrete distribution for things that are continuous.

As for optional vs non-optional, I’d say this is similar to conforming to 
RawRepresentable (where you can implement its `init?(rawValue:)` with an 
`init(rawValue:)` if your type doesn’t ever fail to initialize) where you’re 
simply indicating that for whatever reason, your type is less likely to fail 
than whatever the most likely to fail type is.

Personally, I don’t care whether or not `Int.random` stays, but it’s 
functionally identical to `Int.random(in:)` with a default argument so it 
doesn’t make much of a difference for this decision since removing it wouldn’t 
affect the issue you’re having between `Int.random(in:)` and 
`Collection.random`.

> 2017/11/24 21:39、Xiaodi Wu のメール:
> 
> On Fri, Nov 24, 2017 at 9:05 PM, TellowKrinkle  > wrote:
> You say that all the `.random`s have different semantics, but to me (at 
> least), they are all very similar.
> 
> Of course they are _similar_: this is precisely why it's so important to be 
> clear about the differences in the naming.
>  
> 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
> 
> There are many subtle but important differences. For example:
> 
> `[1, 2, 3].random` is a sampling operation based on a discrete uniform 
> distribution. All operations that choose an element from a Collection would 
> behave similarly: that is, instance `random` guarantees sampling based on a 
> discrete uniform distribution. It does so happen that `Int.random` gives 
> values in a discrete uniform distribution. However, `Float.random` most 
> certainly does not: it would sample from a _continuous_ uniform distribution. 
> In general, static `random` does not guarantee any particular distribution at 
> all. This is a huge semantic distinction.
> 
> Static `random` (e.g., `Int.random`) will always return a value, whereas 
> instance `random` (e.g., `[1, 2, 3].random`) might not. This is because all 
> types that implement static `random` must be instantiable, whereas 
> collections can be empty. One might conclude that it makes sense for static 
> `random` to be of type `T`, whereas instance `random` would be most fittingly 
> of type `T?`. However, because they're both named "random", people have been 
> misled into thinking that they're in fact the same operation and must 
> therefore have the same return type. Alejandro has argued that `[1, 2, 
> 3].random` should be of type `T` *because* it would not be ergonomic for 
> `Int.random` to be of type `T?`. Meanwhile, others have argued that, because 
> `[].random` should be failable, `Int.random` should be as well. This 
> perceived need for the two distinct facilities to return the same type is 
> completely due to them having the same proposed name. However, as described 
> above, one is failable and the other is not *because of their differing 
> semantics*.
> 
> Meanwhile, we have had a debate as to whether `random` should be spelled as a 
> property or a function. Alejandro has argued that `random` is like `first` or 
> `last` and is a property of a collection, while others have argued that 
> `Int.random()` should be spelled like a function because it instantiates a 
> different value each time. Notionally, of course, instance `random` selects 
> one already-existing element from a collection, whereas static `random` 
> creates a new value that doesn't exist yet and truly could be considered like 
> a factory method. However, because again they've both been proposed to have 
> the name "random", people are using arguments about one type of "random" to 
> 

Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-27 Thread Joe Groff via swift-evolution


> On Nov 20, 2017, at 5:43 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Nov 20, 2017, at 5:39 PM, Kelvin Ma via swift-evolution 
>> > wrote:
>> 
>> when SE-185 
>> 
>>  went through swift evolution, it was agreed that the next logical step 
>>  is 
>> synthesizing these conformances for tuple types, though it was left out of 
>> the original proposal to avoid mission creep. I think now is the time to 
>> start thinking about this. i’m also tacking on Comparable to the other two 
>> protocols because there is precedent in the language from SE-15 
>> 
>>  that tuple comparison is something that makes sense to write.
>> 
>> EHC conformance is even more important for tuples than it is for structs 
>> because tuples effectively have no workaround whereas in structs, you could 
>> just manually implement the conformance. 
> 
> In my opinion, you’re approaching this from the wrong direction.  The 
> fundamental problem here is that tuples can’t conform to a protocol.  If they 
> could, synthesizing these conformances would be straight-forward.

It would be a tractable intermediate problem to introduce built-in conformances 
for tuples (and perhaps metatypes) to Equatable/Hashable/Comparable without 
breaching the more general topic of allowing these types to have general 
protocol conformances. I think that would cover the highest-value use cases.

-Joe

___
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-27 Thread Mathew Huusko V via swift-evolution
You're saying that there is universally no inherent difference, and that
all calls "determine if you have called it" correctly, but then picked one
of only a handful of cases in current practice where that is actually true.
Yes "+" (/other math operators) and array access are unsafe, but most other
things in Swift are safe by default, and you have to opt into un-safety
(e.g. forcing or checking an optional or throwing call) — this is a main
tenant of the language.

Perhaps I was not totally clear while mixing and matching my
observations/interpretations of safety and fallibility in compile vs.
runtime and readability vs. writability in my initial email, but I believe
the spirit of my concern was clear: there is obviously a difference between
dynamic and static languages/calls, and having the syntax the same is
misleading in a language centered around static safety, perhaps to a degree
where it is ergonomically counter productive.

On Mon, Nov 27, 2017 at 4:12 PM, Magnus Ahltorp  wrote:

> > 27 Nov. 2017 22:38 Mathew Huusko V via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > I tuned out the initial discussions of this proposal because there
> seemed to be a lot of noise centered around implementation/maintainability.
> I'm curious if the actual premise of the syntactic/sugar conversion has
> been discussed/debated yet? i.e. making dynamic/stringly calls look like
> normal calls is very clean, but it's also very misleading (by definition;
> they're not normal/safe/checked calls) with a potential net reduction in
> ergonomics.
>
> There is nothing that is inherently non-fallible with "normal" Swift
> calls. As far as the caller can tell, any function or method you call can
> fail. There is no difference here; the implementation of the "user-defined
> dynamic member lookup" object will determine if you have called it in a
> proper way or not, in the same way as "+" will determine if you have called
> it in a way that overflows or not.
>
> /Magnus
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [draft] Add last(where:) and lastIndex(where:) Methods

2017-11-27 Thread Nate Cook via swift-evolution
Hello, Swift Evolution!

This is a revision of a previous proposal for adding methods to 
sequences/collections for searching from the end. Feedback welcome!

Nate


—



Add last(where:) and lastIndex(where:) Methods
Proposal: SE- 

Author: Nate Cook 
Status: Awaiting review
Review manager: TBD
Implementation: Branch on natecook1000/swift 

Related Bug: [SR-1504] RFE: index(of:) but starting from end 

Introduction
The standard library should include methods for finding the last element in a 
sequence, and the index of the last element in a collection, that match a given 
predicate.

Swift-evolution thread: [swift-evolution] (Draft) Add last(where:) and 
lastIndex(where:) methods 

Motivation
The standard library currently has methods that perform a linear search to find 
an element or the index of an element that matches a predicate:

Swift
let a = [20, 30, 10, 40, 20, 30, 10, 40, 20]
a.first(where: { $0 > 25 }) // 30
a.index(where: { $0 > 25 }) // 1
a.index(of: 10) // 2
Unfortunately, there are no such methods that search from the end. Finding the 
last of a particular kind of element has multiple applications, particularly 
with text, such as wrapping a long string into lines of a maximum length or 
trimming whitespace from the beginning and end of a string.

You can work around this limitation by using the methods above on a reversed 
view of a collection, but the resulting code is frankly appalling. For example, 
to find the corresponding last index to a.index(where: { $0 > 25 }), something 
like this unholy incantation is required:

Swift
(a.reversed().index(where: { $0 > 25 })?.base).map({ a.index(before: $0) })
Proposed solution
The Sequence protocol should add a last(where:) method, and the 
Collectionprotocol should add lastIndex(where:) and lastIndex(of:) methods. 
These new methods create symmetry with the existing forward-searching APIs that 
are already part of Sequence and Collection.

These additions remove the need for searching in a reversed collection and 
allow code like this:

Swift
a.last(where: { $0 > 25 })  // 40
a.lastIndex(where: { $0 > 25 }) // 7
a.lastIndex(of: 10) // 6
Much better!

Detailed design
last(where:) and lastIndex(where:) will be added to the standard library as 
Sequence and Collection protocol requirements, respectively. These methods will 
have default implementations in their respective protocols and in 
BidirectionalCollection, which can provide a more efficient implementation. 
lastIndex(of:) will be provided in Collection and BidirectionalCollection 
extensions constrained to Equatable elements. 

The new APIs are shown here:

Swift
protocol Sequence {
// Existing declarations...

/// Returns the last element of the collection that satisfies the given
/// predicate, or `nil` if no element does. The sequence must be finite.
func last(where predicate: (Element) throws -> Bool) 
rethrows -> Element?
}

protocol Collection {
// Existing declarations...

/// Returns the index of the last element of the collection that satisfies 
/// the given predicate, or `nil` if no element does.
func lastIndex(where predicate: (Element) throws -> Bool) 
rethrows -> Index? 
}

extension BidirectionalCollection {
func last(where predicate: (Element) throws -> Bool) 
rethrows -> Element? { ... }

func lastIndex(where predicate: (Element) throws -> Bool) 
rethrows -> Index? { ... }
}

extension Collection where Element: Equatable {
/// Returns the index of the last element equal to the given element, or 
/// no matching element is found.
func lastIndex(of element: Element) -> Index? { ... }
}

extension BidirectionalCollection where Element: Equatable {
func lastIndex(of element: Element) -> Index? { ... }
}
You can explore the usage (but not really the performance) of these methods in 
this Swift sandbox 
.

Source compatibility
The addition of the last(where:), lastIndex(where:), and lastIndex(of:)methods 
is strictly additive and should have no impact on existing code.

Effect on ABI stability & API resilience
This change does not affect ABI stability or API resilience beyond the addition 
of the new methods.

Alternatives considered
A previous proposal limited the new methods to the BidirectionalCollection 
protocol. This isn't a necessary limitation, as the standard library already 
has methods on sequences and forward collections with the same performance 
characteristics. 

Another previous proposal included renaming index(of:) and index(where:) to 
firstIndex(of:) and firstIndex(where:), respectively. This version of the 

Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-27 Thread Alejandro Martinez via swift-evolution
>
> Ah. You seem to be unfamiliar with protocol existentials. Protocols
> (currently, only those without Self or associated type requirements, for
> various implementation reasons) are themselves types. For example, you can
> write:
>

A little offtopic, but I've been wanting to ask if it would be
possible to clarify the definition of existentials on the generics
manifesto (or somewhere than can be easily found by newcomers). I'm
sure I'm not the only one that has a vague notion of what it means but
would still appreciate to have a more concrete definition with some
examples. :D



> ```
> protocol P { }
> extension Int : P { }
> let x: P = 42
> ```
>
> In this example, x is of type `P`, not of type `Int`. Let's clarify the
> difference:
>
> ```
> extension Array where Element == P {
>   func hi() {
> print("Hello")
>   }
> }
>
> extension Array where Element : P {
>   func hi() {
> print("World!")
>   }
> }
>
> let y: [P] = [x]
> let z: [Int] = [x as Int]
>
> y.hi() // Prints "Hello"
> z.hi() // Prints "World!"
> ```
>
> Moreover, if we do not write the first `extension Array`, then `y.hi()`
> doesn't compile. This helps to illustrate that P does not conform to itself.
>
>
>>> For a type T : P, a tuple of type (T, T) is not a tuple of type (P, P).
>>> If we can extend tuples, you can write a generic algorithm that works with
>>> any type (T, T) where T : P, and/or you can write an algorithm that works
>>> with concrete type (P, P). Note that there is no overlap between these two
>>> because existential type P does not conform to protocol P.
>>>
>>
>> Mike
>>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>



-- 
Alejandro Martinez
http://alejandromp.com
___
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-27 Thread Magnus Ahltorp via swift-evolution
> 27 Nov. 2017 22:38 Mathew Huusko V via swift-evolution 
>  wrote:
> 
> I tuned out the initial discussions of this proposal because there seemed to 
> be a lot of noise centered around implementation/maintainability. I'm curious 
> if the actual premise of the syntactic/sugar conversion has been 
> discussed/debated yet? i.e. making dynamic/stringly calls look like normal 
> calls is very clean, but it's also very misleading (by definition; they're 
> not normal/safe/checked calls) with a potential net reduction in ergonomics.

There is nothing that is inherently non-fallible with "normal" Swift calls. As 
far as the caller can tell, any function or method you call can fail. There is 
no difference here; the implementation of the "user-defined dynamic member 
lookup" object will determine if you have called it in a proper way or not, in 
the same way as "+" will determine if you have called it in a way that 
overflows or not.

/Magnus

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


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

2017-11-27 Thread Mathew Huusko V via swift-evolution
I tuned out the initial discussions of this proposal because there seemed
to be a lot of noise centered around implementation/maintainability. I'm
curious if the actual premise of the syntactic/sugar conversion has been
discussed/debated yet? i.e. making dynamic/stringly calls look like normal
calls is very clean, but it's also very misleading (by definition; they're
not normal/safe/checked calls) with a potential net reduction in ergonomics.

Cleanliness is a double edged sword, which Swift already suffers at the
hand of. Type inference and overloading are fantastic. Literal convertibles
are magic. Omitting "redundant" types/descriptors from signatures is so
right. But they (especially when combined) lead to a lot of Swift code
ranging from unclear to meaningless at a glance, with a couple
option-clicks per line necessary to extract exactly what's going on from
the all knowing compiler. This is a hindrance in Xcode, and not possible if
you've only got the text (like on GitHub).
But whereas these features only really effect code comprehension, the
proposed syntactic conversion effects code comprehension and writing safe
code. Usually in Swift you have to opt in at the call site to unchecked
behaviour, but with these changes, working in a mixed pure Swift/Pythonic
Swift environment, if you don't pay a good deal of attention to each object
you're writing calls on (whether it conforms to the new protocol), you can
write totally unchecked code by accident. Not to say the code comprehension
itself isn't a problem — with type inferred/descriptor-cleaned code it's
evident the information isn't there, so if something isn't clear there's an
impetus to option-click/check it. With this dynamic-posing-as-checked code,
the truth and the evidence is disguised.

Anyway, there's my primary concern. Has this been addressed yet? Has any
thought been given to requiring '?'/'!' on these calls (or some other
symbol, but this would retain some cleanliness..) to opt into the inherent
fallibility and distinguish them visually?

Thanks,
Mathew

On Mon, Nov 27, 2017 at 6:04 AM, 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.
>
> -Chris
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-27 Thread Tino Heth via swift-evolution

> The implementation is straight-forward and (IMO) non-invasive in the compiler.
At least it’s smaller than I would have expected — but I don’t have the 
overview to judge the consequences to the compiler.

However, the impact those two proposals have on Swift is imho huge, and as the 
whole story is quite special for several reasons, there’s an elephant in the 
room that shouldn’t be ignored:
- What would you do if the proposal isn’t accepted?
- What does core think you would do in this case?
- What impact will that speculation have on the decision?
I can’t see what’s happening behind the scenes (basically, everything beyond 
the ML), but those non-technical questions might have a big impact if people 
construct their own narratives.

Besides that general concern, I think the whole „dynamic Swift“ topic shouldn’t 
be rushed:
How about keeping it in a public branch, so that users of script languages (not 
only Python) can play with it, and use that experience to decide the question 
in the Swift 6 timeframe?___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-27 Thread Tino Heth via swift-evolution
> Why do you need to have this ability to unsafe bitcast? Is interconversion 
> between point types such a common operation that it's a performance 
> bottleneck?
A real-world example: Real-time image processing.
When you have a stream of 4k pictures at 30 fps, you really don’t wont to copy 
buffers just because two filters insist on having their own representation of 
bitmap data.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-27 Thread Tino Heth via swift-evolution

> ps i remember that pitch because i’m pretty sure i was the one that pitched 
> that.
No, I was writing about that one: 
https://www.mail-archive.com/swift-evolution@swift.org/msg30565.html

> consensus seemed it was too high level for inclusion (even though having it 
> at the stdlib level would do wonders for things like SIMD) and everyone got 
> distracted by “integers as generic parameters” (because we love `Vector<3>` 
> ig) because everything on this list always devolves into “but this is really 
> a problem with the generics system” and since no one knows how to fix the 
> generics system everyone calls it a day and forgets about the original issue

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