Re: [swift-evolution] [Review] SE-0194: Derived Collection of Enum Cases

2018-01-11 Thread Howard Lovatt via swift-evolution
I missed that sorry.

I think it will find other uses and therefore should be ValueEnumerable. 

-- Howard.

> On 11 Jan 2018, at 6:36 pm, Paul Cantrell  wrote:
> 
>> On Jan 11, 2018, at 7:28 PM, Howard Lovatt  wrote:
>> 
>> I am in favour of a protocol that you have to explicitly declare, it feels 
>> much more like Swift to me. For example you have to say Equatable 
>> explicitly. 
> 
> Howard — Either you’ve missed something or I have. I didn’t view requiring 
> types to explicitly declare conformance as being up for debate at all.
> 
> The question I was weighing on it — what I thought Chris and Brent were 
> discussing — was whether this new protocol should be used narrowly for cases 
> of enums without associated types (which Chris favors), or whether it should 
> find more broad use to mean “type which can enumerate all of its possible 
> values” (which Brent finds interesting with caveats). This question has a 
> bearing on whether the protocol’s name should be CaseEnumerable or 
> ValueEnumerable.
> 
> In either case, the conformance is always explicitly declared; the compiler 
> merely synthesizes the implementation for enums without associated types.
> 
> I think?
> 
>> As a contra example in Java it feels natural that the compiler just provides 
>> the functionality because that is consistent across the language, you don’t 
>> declare something as equatable and you don’t tell the compiler that you want 
>> the values array generating. 
>> 
>> ‘Horses for courses’, this is what Swift does. 
>> 
>> As a more hard-core example, suppose you want to use statics as an enum like 
>> construct, e.g.:
>> 
>> struct Ex: ValueEnumerable {
>> let x1: Int
>> let x2: Int
>> init(x1: Int, x2: Int) { self.x1 = x1, self.x2 = x2 }
>> static let allValues = [x1, x2]
>> }
>> 
>> Perhaps the above Ex started as an enum but was changed to a struct during 
>> enhancements to the program because the values of x1 and x2 are now read in 
>> rather than constants. 
>> 
>> -- Howard.
>> 
>>> On 11 Jan 2018, at 5:21 pm, Paul Cantrell via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> 
 On Jan 10, 2018, at 10:21 PM, Chris Lattner via swift-evolution 
  wrote:
 
 Brent, thanks for the detailed response, one question about it:
 
> On Jan 10, 2018, at 3:06 AM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> But that's beside the point. What I think the "`allValues` should be 
> allowed to be infinite" suggestion misses is that one of 
> `ValueEnumerable`'s semantics is that it's not only theoretically 
> *possible* to enumerate all the values, but actually *reasonable* to do 
> so.
 ...
> Some types, of course, fall into a gray area. `Int8` is fairly 
> reasonable, but larger integer types get increasingly unreasonable until, 
> by `Int64`, we reach types that would take decades to enumerate. Where 
> the line should be drawn is a matter of opinion. (My opinion, to be 
> clear, is that we shouldn't conform any of them; if someone really wants 
> to do it, they can add a retroactive conformance.)
 
 I’m not sure which way you’re arguing here, but that’s ok. :-)
 
 In my opinion, while I can see where you are coming from (that it could be 
 “reasonable” to allow random types to be ValueEnumerable) I don’t see what 
 the *utility* or *benefit* that would provide.
 
 If we went with a simpler design - one that named this CaseEnumerable and 
 .allCases - we would be heavily biasing the design of the feature towards 
 enum-like applications that do not have associated types.  This is “the” 
 problem to be solved in my opinion, and would lead to a more clear and 
 consistently understood feature that doesn’t have the ambiguity and “gray 
 areas” that you discuss above.  Given this bias, it is clear that infinite 
 sequences are not interesting.
 
 Of course it would certainly be *possible* for someone to conform a 
 non-enum-like type to CaseEnumerable, but that would be an abuse of the 
 feature, and not a "gray area”.  
 
 
 Is there some specific *utility* and *benefit* from creeping this feature 
 beyond “enumerating cases in enums that don’t have associated types”?  Is 
 that utility and benefit large enough to make it worthwhile to water down 
 the semantics of this protocol by making it so abstract?
>>> 
>>> I gave an example in my review of an enumerable thing where the items are 
>>> analogous to cases but are not actually cases, and where I thought 
>>> `allCases` would cause confusion but `allValues` would make sense:
>>> 
> On Jan 10, 2018, at 10:22 AM, Paul Cantrell via swift-evolution 
>  wrote:
> 
 Contra Chris, I slightly prefer ValueEnumerable, because it extends to 
 situations where we still want to enumerate a fixed set of possibilities 
 which don’t strictly correspond to en

Re: [swift-evolution] Handling unknown cases in enums [RE: SE-0192]

2018-01-11 Thread Howard Lovatt via swift-evolution
Well if you are happy to say removal of a case isn’t allowed, why not be 
symmetrical and say adding isn’t allowed and if an API would like to add cases 
then it needs to do so via adding an extended enum, e.g.:

enum Old {
case old1, old2
}
enum New {
case old1 // Note missing old2. 
case new1
}
struct Ex {
func f(old: Old) -> Old { ... }
func f(new: New) -> New { ... }
}

If this approach is taken then it is more work for Apple and less work for 
developers and a cleaner Swift. So overall it might be the best approach. 

-- Howard.

> On 11 Jan 2018, at 11:23 am, Jordan Rose via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 11, 2018, at 05:08, Michel Fortin  wrote:
>> 
>> I think `unknown` should be a modifier for either `case` or `default`. This 
>> would allow:
>> 
>>  unknown default:
>>  unknown case _: // similar to default
>>  unknown case (1, _): // enum in second position
>> 
>> If the case can be reached with statically known enum values, the compiler 
>> generates a warning.
>> 
>> I'd also prefer a more precise term instead of "unknown". What we aim at is 
>> matching cases that do not have a declaration (future cases, 
>> privately-declared cases). So I'd use the word "undeclared" rather than 
>> "unknown":
>> 
>>  undeclared default:
>>  undeclared case _: // similar to default
>>  undeclared case (1, _): // enum in second position
>> 
>> That word has the advantage that enums are also less likely to have a case 
>> named "undeclared", I think.
> 
> I’m not sure I’d agree that most people would think of private cases are 
> “undeclared”, but sure, it’s a reasonable alternative. I still like “unknown” 
> a little better myself.
> 
> Jordan
> 
> 
>> 
 Le 10 janv. 2018 à 23:31, Chris Lattner via swift-evolution 
  a écrit :
 
 
 On Jan 10, 2018, at 10:10 AM, Jordan Rose  wrote:
 
>> 
>> - Matching known cases is a feature, not a limitation, to avoid existing 
>> code changing meaning when you recompile. I'll admit that's not the 
>> strongest motivation, though, since other things can change the meaning 
>> of existing code when you recompile already.
> 
> I’m not sure I understand this. 
> 
> The whole motivation for this feature is to notify people if they are not 
> handling a “newly known” case.  If they don’t care about this, they can 
> just use default.
 
 Notify, yes. Error, no. It's a design goal that adding a new case does not 
 break source compatibility in addition to not breaking binary 
 compatibility (because people don't like editing their dependencies) and 
 therefore the behavior has to be defined when they recompile with no 
 changes.
 
>>> 
>>> Ok, if that’s the desired design, then (IMO) the right way to spell it is 
>>> “unknown default:” and it should have semantics basically aligned with the 
>>> design you laid out in the revision of the proposal.  If this is supposed 
>>> to be an error, then it should be a pattern production.
>>> 
>>> Do you have a sense for whether this is what people want?  We really should 
>>> have a review cycle evaluating exactly this sort of tradeoff.
>>> 
>>> In any case, I’ve said this before off-list, but I find this whole 
>>> discussion (of how to improve diagnostics for unknown cases) to be 
>>> separable from the core issue required to get to ABI stability.  It seems 
>>> to me that we could split this (ongoing) design discussion off into a 
>>> separate SE, allowing you to get on with the relatively uncontroversial and 
>>> critical parts in SE-0192.
>>> 
>>> -Chris
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> 
>> -- 
>> Michel Fortin
>> https://michelf.ca
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0194: Derived Collection of Enum Cases

2018-01-11 Thread Howard Lovatt via swift-evolution
I am in favour of a protocol that you have to explicitly declare, it feels much 
more like Swift to me. For example you have to say Equatable explicitly. 

As a contra example in Java it feels natural that the compiler just provides 
the functionality because that is consistent across the language, you don’t 
declare something as equatable and you don’t tell the compiler that you want 
the values array generating. 

‘Horses for courses’, this is what Swift does. 

As a more hard-core example, suppose you want to use statics as an enum like 
construct, e.g.:

struct Ex: ValueEnumerable {
let x1: Int
let x2: Int
init(x1: Int, x2: Int) { self.x1 = x1, self.x2 = x2 }
static let allValues = [x1, x2]
}

Perhaps the above Ex started as an enum but was changed to a struct during 
enhancements to the program because the values of x1 and x2 are now read in 
rather than constants. 

-- Howard.

> On 11 Jan 2018, at 5:21 pm, Paul Cantrell via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 10, 2018, at 10:21 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> Brent, thanks for the detailed response, one question about it:
>> 
>>> On Jan 10, 2018, at 3:06 AM, Brent Royal-Gordon via swift-evolution 
>>>  wrote:
>>> 
>>> But that's beside the point. What I think the "`allValues` should be 
>>> allowed to be infinite" suggestion misses is that one of 
>>> `ValueEnumerable`'s semantics is that it's not only theoretically 
>>> *possible* to enumerate all the values, but actually *reasonable* to do so.
>> ...
>>> Some types, of course, fall into a gray area. `Int8` is fairly reasonable, 
>>> but larger integer types get increasingly unreasonable until, by `Int64`, 
>>> we reach types that would take decades to enumerate. Where the line should 
>>> be drawn is a matter of opinion. (My opinion, to be clear, is that we 
>>> shouldn't conform any of them; if someone really wants to do it, they can 
>>> add a retroactive conformance.)
>> 
>> I’m not sure which way you’re arguing here, but that’s ok. :-)
>> 
>> In my opinion, while I can see where you are coming from (that it could be 
>> “reasonable” to allow random types to be ValueEnumerable) I don’t see what 
>> the *utility* or *benefit* that would provide.
>> 
>> If we went with a simpler design - one that named this CaseEnumerable and 
>> .allCases - we would be heavily biasing the design of the feature towards 
>> enum-like applications that do not have associated types.  This is “the” 
>> problem to be solved in my opinion, and would lead to a more clear and 
>> consistently understood feature that doesn’t have the ambiguity and “gray 
>> areas” that you discuss above.  Given this bias, it is clear that infinite 
>> sequences are not interesting.
>> 
>> Of course it would certainly be *possible* for someone to conform a 
>> non-enum-like type to CaseEnumerable, but that would be an abuse of the 
>> feature, and not a "gray area”.  
>> 
>> 
>> Is there some specific *utility* and *benefit* from creeping this feature 
>> beyond “enumerating cases in enums that don’t have associated types”?  Is 
>> that utility and benefit large enough to make it worthwhile to water down 
>> the semantics of this protocol by making it so abstract?
> 
> I gave an example in my review of an enumerable thing where the items are 
> analogous to cases but are not actually cases, and where I thought `allCases` 
> would cause confusion but `allValues` would make sense:
> 
>>> On Jan 10, 2018, at 10:22 AM, Paul Cantrell via swift-evolution 
>>>  wrote:
>>> 
>> Contra Chris, I slightly prefer ValueEnumerable, because it extends to 
>> situations where we still want to enumerate a fixed set of possibilities 
>> which don’t strictly correspond to enum cases but still have that sort of 
>> flavor. For example, one might want:
>> 
>> enum SideOfBody
>>   {
>>   case left
>>   case right
>>   }
>> 
>> enum Limb: ValueEnumerable
>>   {
>>   case arm(SideOfBody)
>>   case leg(SideOfBody)
>> 
>>   static let allValues =
>> [
>> arm(.left),
>> arm(.right),
>> leg(.left),
>> leg(.right)
>> ]
>>   }
>> 
>> To my eyes, this code reads better than it would with CaseEnumerable / 
>> allCases.
> 
> This raises a question related to Chris’s: what is the utility of having Limb 
> conform to a protocol instead of just providing allValues ad hoc? Does 
> CaseEnumerable / ValueEnumerable serve any purpose other than triggering 
> special behavior in the compiler? Would the protocol ever be used as the type 
> of something in code?
> 
> My answers, admittedly weak ones, are: (1) conventions are nice and 
> consistency is nice, and (2) you never know how an abstraction might be used, 
> but you do know that people will be angry when it should fit but doesn’t. I 
> can’t come up with a more compelling or specific argument than those.
> 
> Cheers,
> 
> Paul
> 
> _

Re: [swift-evolution] Handling unknown cases in enums [RE: SE-0192]

2018-01-10 Thread Howard Lovatt via swift-evolution
It is a two way street though. An app compiled against an old framework might 
pass a deleted enum case back to the new framework that has been changed under 
it. 

Just as the app has to guard against new cases the framework has to guard 
against old cases!

Both ends need an unknown case. 

-- Howard. 

> On 10 Jan 2018, at 5:40 pm, Jordan Rose  wrote:
> 
> Remember, the goal here is to support both binary and source compatibility. 
> An existing app might be using the enum case that you're trying to remove, 
> but there's no chance that an existing app is using an enum case that you're 
> trying to add.
> 
> Jordan
> 
> 
>> On Jan 10, 2018, at 16:34, Howard Lovatt via swift-evolution 
>>  wrote:
>> 
>> If an enum isn’t final; then what’s the difference in deleting as opposed to 
>> adding?
>> 
>> -- Howard. 
>> 
>>> On 10 Jan 2018, at 4:13 pm, Jean-Daniel  wrote:
>>> 
>>> 
>>> 
>>>> Le 10 janv. 2018 à 23:58, Howard Lovatt via swift-evolution 
>>>>  a écrit :
>>>> 
>>>> Two points:
>>>> 
>>>> 1. I like Chris’s suggestion of #unknown and in particular that it is 
>>>> distinct from default. 
>>>> 
>>>> 2. All the discussion is about a framework adding a case, what about when 
>>>> a framework deletes a case?
>>> 
>>> This is a binary breaking change (just like removing an existing function 
>>> or method).
>>> 
>>> 
>> ___
>> 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] Handling unknown cases in enums [RE: SE-0192]

2018-01-10 Thread Howard Lovatt via swift-evolution
If an enum isn’t final; then what’s the difference in deleting as opposed to 
adding?

-- Howard. 

> On 10 Jan 2018, at 4:13 pm, Jean-Daniel  wrote:
> 
> 
> 
>> Le 10 janv. 2018 à 23:58, Howard Lovatt via swift-evolution 
>>  a écrit :
>> 
>> Two points:
>> 
>> 1. I like Chris’s suggestion of #unknown and in particular that it is 
>> distinct from default. 
>> 
>> 2. All the discussion is about a framework adding a case, what about when a 
>> framework deletes a case?
> 
> This is a binary breaking change (just like removing an existing function or 
> method).
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-users] Discourse forum rollout next week!

2018-01-10 Thread Howard Lovatt via swift-evolution
Great news.

Thanks for putting the effort in. 

-- Howard.

> On 10 Jan 2018, at 1:27 pm, Charles Srstka via swift-evolution 
>  wrote:
> 
> :thumbsup:
> 
> Charles
> 
>> On Jan 10, 2018, at 2:22 PM, Nicole Jacque via swift-users 
>>  wrote:
>> 
>> Hi All-
>> 
>> First of all, a big thank you to everyone who has provided feedback on our 
>> prototype Discourse forum. We are ready to move forward with the transition! 
>>  The schedule will be:
>> 
>> 1/17 ~ 6PM Pacific:  We will be putting the mailing lists into suspend mode 
>> in order to do the final export of data for import to the forums
>> 1/19 (exact time TBD) - forums will be up and in production mode.  We’ll 
>> send out one last email at that time to let everyone know.
>> 
>> During the process, I’ll try to keep some status available at 
>> forums.swift.org, but expect about a day and a half of outage time between 
>> the mailing lists going down and the forums being ready.
>> 
>> If you need to contact the Swift infrastructure team during the outage 
>> period the infrastruct...@swift.org email will continue to work.
>> 
>> Thanks!
>> nicole
>> ___
>> swift-users mailing list
>> swift-us...@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
> 
> ___
> 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] Handling unknown cases in enums [RE: SE-0192]

2018-01-10 Thread Howard Lovatt via swift-evolution
Two points:

1. I like Chris’s suggestion of #unknown and in particular that it is distinct 
from default. 

2. All the discussion is about a framework adding a case, what about when a 
framework deletes a case?

-- Howard.

> On 10 Jan 2018, at 1:41 pm, Dave DeLong via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 10, 2018, at 1:29 PM, Dave DeLong via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>>> On Jan 10, 2018, at 1:05 PM, Jordan Rose via swift-evolution 
>>>  wrote:
>>> 
>>> 
> That said, it sounds like people are happier with `case #unknown` than 
> `unknown case`, and that leaves things a little more consistent if we 
> ever do expand it to other pattern positions, so I'll change the proposal 
> revision to use that spelling. (And if anyone comes up with a nicer 
> spelling, great!)
 
 Thanks!
>>> 
>>> Updated! https://github.com/apple/swift-evolution/pull/777. Also tried to 
>>> clarify some of the points on why I'm leery about #unknown as an arbitrary 
>>> pattern, at least for now.
>> 
>> Hi Jordan,
>> 
>> After a long and hard reading, I will conditionally +1 this:
>> 
>> I agree that this is a problem that “needs" to be solved. (“Needs” is 
>> subjective, because as you correctly point out, there are other languages 
>> that don’t do this and seem to be relatively OK with that)
>> I am ok with the @frozen moniker on enums
>> I am ok with the “#unknown” syntax
>> I am therefore generally ok with the proposed solution
>> 
>> BUT:
>> 
>> I think the application of the warnings is still overly broad. The 
>> frozenness of an enum is only a problem for enums that come from dynamically 
>> linked modules that are external to my built project.
>> 
>> Therefore I’d like to see stuff regarding:
>> 
>> future directions for how we can refine the behavior and tooling around 
>> frozen enums, specifically
>> “statically” linking libraries (ie, the “import Module1 @ 12.1.2” stuff, aka 
>> “version locking"), because statically linking should eliminate frozenness 
>> concerns
>> embedded modules not producing warnings in the future, because embedded 
>> modules only change when the app author decides
>> ruminations on improving tooling for yelling at a developer if they 
>> “unfreeze” an enum in between versions (ie, a reduction of the SemVer 
>> conversation)
>> 
>> Because version locking and knowledge of embedding modules doesn’t currently 
>> exist, we’re forced to deal with the over-applicability of frozenness that 
>> shouldn’t be necessary. Getting those in would go a long way towards getting 
>> this feature scoped down to where it properly belongs in the app development 
>> workflow.
> 
> In other words, the current solution will produce a bunch of false positives, 
> and I’d like to see stuff in the proposal about how those false positives 
> will be addressed.
> 
> Dave
> ___
> 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 0192 - Non-Exhaustive Enums

2018-01-03 Thread Howard Lovatt via swift-evolution
Despite having suggested the @version syntax I do agree with people that have 
said any @annotation is both a burden on the programmer and severely reduces 
readability. 

Therefore a 4th option, carrying on from the numbering in my previous email is:

  4. The compiler issues a description of the public enums in a module. 
Application code that uses the enums knows what version of the enum they were 
compiled against. When the application launches the runtime writes a 
translation between the module enum and the application enum and vice versa. 
When an enum goes into or comes out of the application code to/from the module 
code it goes through the translation functions. EG:

// Module version 1. 
public enum E {
case A, B, C
}
...
switch e {
case A: a()
default: d() // Could alternatively have cases B and C instead of default. 
unknown case: u() // Must have unknown case for a public enum. 
}

// Application code compiled against module version 1. 
// Stored in the code is the description of E having cases A, B, and C. 
switch e {
case A: a()
default: d() // Could alternatively have cases B and C instead of default. 
unknown case: u() // Must have unknown case for a public enum. 
}

The translation functions in each direction are trivial since the two enums 
match and therefore have the same numbering and the same number range. 

Now the module is changed. 

// Module version 2.
public enum E {
case A, C, D // B deleted and D added. 
}
...
// switch as before but now D calls d() and B calls u(). Previously B 
called d() but since B is deleted it is now an unknown case. 

The translation between module 2 code and application compiled against 1 code 
is:

  Module 2 <—> Application 1
  A   <—> A
  U   <—   B
  C   <—> C
  D —> U

IE all the old cases, from the application, are translated into unknown on the 
module side and all the new cases, from the module, are translated to unknown 
on the application side. 

This way neither the module programmer nor the application programmer has to 
version their code since the runtime provides the translation. 

It is source breaking however, since all switches of public enums require an 
unknown case both in the module code and application code. 

-- Howard. 

> On 3 Jan 2018, at 3:54 am, Jason Merchant via swift-evolution 
>  wrote:
> 
> Is it hard to imagine that most everyone can get what they want and keep the 
> syntax clean and streamlined at the same time? Without any "@" signs or other 
> compiler hints?
> 
>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
>> cases without breaking binaries compiled against previous versions"
> 
> When an enum changes, and the change causes the code to break, the user can 
> be presented with migration options from an automated IDE tool. In what 
> specific way does this not solve the issue about having to upgrade your code 
> when using someone else's code library? This very notion implies your 
> disgruntled about doing work when things are upgraded, is that really what 
> this fuss is all about?
> 
> A well written language interpreter and auto-tooling IDE would not need hints 
> embedded in the code syntax itself. Migration hints from version to version 
> should not be a part of either the past or future version of the code library.
> 
> ...
> 
> I don't expect the community to agree on language grammar, but the common 
> sense here on how to achieve the intended goals seems to be out of wack.
> 
> If someone can present a clear logical statement as to how an automated 
> migration tool behind the scenes in the IDE to handle all your versioning 
> worries, does not make this whole discussion about adding more convoluted 
> syntax additions irrelevant, I'd love to hear it.
> 
> ___
> 
> Sincerely,
> Jason
> 
> 
> 
> 
> 
> 
>> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
>>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>>  wrote:
>> 
>>> I think this whole thing has been unnecessarily convoluted. As a result, 
>>> the majority of the replies are rabbit holes.
>>> 
>>> In my opinion, the true root of the concept in question is as follows:
>>> 
>>> A list of something is desired:
>>> 1 - Pancake
>>> 2 - Waffle
>>> 3 - Juice
>>> 
>>> Developer wishes to be able to:
>>> A) Add new things to the list of choices in the future as they come up with 
>>> new ideas
>>> B) Sometimes select one of the choices to be chosen as the normal choice if 
>>> no choice is made by the user
>>> 
>>> A and B are separate desires. In some circumstances a developer may want to 
>>> add a new choice and make it the normal choice when there was no normal 
>>> choice was clarified before.
>> 
>> I don't think this is an accurate summary of the problem being tackled here. 
>> Rather, we are how to enable the vendor of a nonex

Re: [swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Howard Lovatt via swift-evolution
I am not convinced by these arguments, they seem to be a ‘poor man’s’ 
versioning system. For example consider:

// In module. 
public enum E {
case A, B, C
}

// In application. 
switch e {
case A: a()
default: d()
unknown case: u()
}

When e == B or C is u() or d() called? I would expect d() since the application 
programmer obviously intends to handle unexpected differently than default. 

Now when E is modified and case D added by the module programmer I would expect 
B and C to still call d() and D to call u(). 

To achieve the above behaviour the switch encodes that when it compiled default 
was for B and C and therefore D is the new case and therefore it calls u(). 

When the code is recompiled against the new module the behaviour changes. D 
will now call d(). This will be without a warning. Hence I am classing this as 
a ‘poor man’s’ module system. 

Possible solutions include:

  1. You can’t have a default with an extensible enum, but you must have a 
unknown case. This prevents handling default cases at all, you have to list all 
the existing cases separately. 

  2. As described above in 1 the unknown case does very little. Instead just 
use default and don’t introduce unknown. 

  3. Have a versioned module system that requires enum cases and matching 
switch statements to be versioned. EG:

// In module. 
@version(1) public enum E {
case A, B, C
}
@version(1.6) public enum E {
case A, C, D
}

// In application. 
@version(1.5) switch e {
case A: a()
default: d()
unknown case: u()
}

The module system would have to publish which enum cases were available for 
each version including all old versions. Note how the above notation allows 
removal and addition of cases. 

-- Howard. 

> On 3 Jan 2018, at 12:26 am, Kelvin Ma via swift-evolution 
>  wrote:
> 
> 
> 
>> On Tue, Jan 2, 2018 at 11:45 PM, Nevin Brackett-Rozinsky via swift-evolution 
>>  wrote:
>>> On Tue, Jan 2, 2018 at 9:07 PM, Jordan Rose via swift-evolution 
>>>  wrote:
>>> [Proposal: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md]
>>> 
>>> Whew! Thanks for your feedback, everyone. On the lighter side of 
>>> feedback—naming things—it seems that most people seem to like '@frozen', 
>>> and that does in fact have the connotations we want it to have. I like it 
>>> too.
>>> 
>>> More seriously, this discussion has convinced me that it's worth including 
>>> what the proposal discusses as a 'future' case. The key point that swayed 
>>> me is that this can produce a warning when the switch is missing a case 
>>> rather than an error, which both provides the necessary compiler feedback 
>>> to update your code and allows your dependencies to continue compiling when 
>>> you update to a newer SDK. I know people on both sides won't be 100% 
>>> satisfied with this, but does it seem like a reasonable compromise?
>>> 
>>> The next question is how to spell it. I'm leaning towards `unexpected 
>>> case:`, which (a) is backwards-compatible, and (b) also handles "private 
>>> cases", either the fake kind that you can do in C (as described in the 
>>> proposal), or some real feature we might add to Swift some day. `unknown 
>>> case:` isn't bad either.
>>> 
>>> I too would like to just do `unknown:` or `unexpected:` but that's 
>>> technically a source-breaking change:
>>> 
>>> switch foo {
>>> case bar:
>>>   unknown:
>>>   while baz() {
>>> while garply() {
>>>   if quux() {
>>> break unknown
>>>   }
>>> }
>>>   }
>>> }
>>> 
>>> Another downside of the `unexpected case:` spelling is that it doesn't work 
>>> as part of a larger pattern. I don't have a good answer for that one, but 
>>> perhaps it's acceptable for now.
>>> 
>>> I'll write up a revision of the proposal soon and make sure the core team 
>>> gets my recommendation when they discuss the results of the review.
>>> 
>>> ---
>>> 
>>> I'll respond to a few of the more intricate discussions tomorrow, including 
>>> the syntax of putting a new declaration inside the enum rather than 
>>> outside. Thank you again, everyone, and happy new year!
>>> 
>>> Jordan
>> 
>> 
>> +1 to warning instead of error
>> +1 to unknown/unexpected case
>> +1 to “@frozen” or any other reasonable spelling, they are all fine by me.
> 
> +1 to “@tangled” because abi is complicated
>  
>> 
>> The one remaining problem to solve is making sure multi-module apps can 
>> leave out the unknown/unexpected case on enums from modules which are part 
>> of the app itself and thus cannot be updated independently of it. John 
>> McCall’s version-locking plan sounds promising, though we should explore the 
>> available options before finalizing a course.
>> 
>> Perhaps we need a concept of submodules, or supermodules, or some other way 
>> to demarcate the boundaries of a resilience domain.
>> 
>> Nevin
> 
> i would support a proper submodule system over

Re: [swift-evolution] namespacing protocols to other types

2017-12-24 Thread Howard Lovatt via swift-evolution
I would say yes they are different for the example. Definitely something I miss 
is nesting types to given a seperate namespace. 

-- Howard. 

> On 24 Dec 2017, at 9:56 pm, Slava Pestov via swift-evolution 
>  wrote:
> 
> There was a proposal to allow protocols to be nested inside types at one 
> point but it didn’t move forward.
> 
> Basically, if the outer type is a non-generic class, struct or enum, there’s 
> no conceptual difficulty at all.
> 
> If the outer type is a generic type or another protocol, you have a problem 
> where the inner protocol can reference generic parameters or associated types 
> of the outer type. This would either have to be banned, or we would need to 
> come up with coherent semantics for it:
> 
> struct Generic {
>  protocol P {
>func f() -> T
>  }
> }
> 
> struct Conforms : Generic.P {
>  func f() -> Int { … } // Like this?
> }
> 
> let c = Conforms()
> c is Generic.P // is this false? Ie, are Generic.P and 
> Generic.P different protocols?
> 
> Slava
> 
>> On Dec 24, 2017, at 6:53 PM, Kelvin Ma via swift-evolution 
>>  wrote:
>> 
>> is there a reason why it’s not allowed to nest a protocol declaration inside 
>> another type?
>> ___
>> 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] [REVIEW] SE-0193 - Cross-module inlining and specialization

2017-12-24 Thread Howard Lovatt via swift-evolution
I was making two seperate points: 1. Annotating which parts of a public APIs 
are stable should not be necessary and 2. Inlining should be left to the 
compiler. 

Point 1: If you had a module system that was versioned then a public 
declaration should be taken as stable across all minor releases. IE You can 
only add public declarations, not remove or change, for versions 1.x.x compared 
to 1.0.0. 

That way you don’t need to separately annotate which bits of the API are 
stable. All the public API is stable. 

Point 2: Functions that the compiler of a module decrees are potentially 
inlinable should be published using SIL or LLVM so that they can be inlined 
when the module is used either at compile time or runtime. It is important that 
it is something simple like SIL or LLVM to make inlining light weight. That way 
the module compiler can be quite speculative about inlining and make many 
functions available for inlining. In contrast the compiler consuming the 
library can be conservative with a runtime back up if in doubt. IE if the 
function is marginal then don’t inline until runtime has proven that inlining 
is worth while. 

-- Howard. 

> On 24 Dec 2017, at 9:53 pm, Slava Pestov  wrote:
> 
> 
> 
>> On Dec 24, 2017, at 3:04 PM, Howard Lovatt via swift-evolution 
>>  wrote:
>> 
>> Proposal link: 
>> https://github.com/apple/swift-evolution/blob/https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.mdmaster/proposals/0193-cross-module-inlining-and-specialization.md
>> What is your evaluation of the proposal?
>> 
>> -1
>> 
>> The proposal puts all the emphasis on the programmer. It is better for the 
>> compiler to decide if something is to be inclined both across modules and 
>> within modules. 
>> 
>> If something is made public then it should be fixed for a given major 
>> version number. No need for extra annotation. 
>> 
>> A module system that allows versioning is a better solution. 
>> 
>> 
> Can you explain your proposed solution in more detail?
> 
>> No, cluttering up declarations is completely against the clarity of Swift. 
>> For example who other than people on this group will understand 
>> @inline(never) @inlinable. 
>> 
>> 
> We don’t expect this attribute to be used frequently in third-party 
> frameworks. @inline(never) @inlinable is a weird combination, but I hope that 
> @inline(never) is used even less frequently. In fact other than debugging it 
> probably doesn’t have much purpose at all, and it would be nice to deprecate 
> it some day.
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
>> Yes C and C++ and found the equivalent of these annotations problematic. In 
>> Java they eliminated all this and let the compiler do the work. In practice 
>> this works much better. 
>> 
>> 
> The Java approach works because there’s no separate compilation — having a 
> JIT means the optimizer is free to inline across module boundaries without 
> any resilience considerations. This doesn’t fit with Swift’s compilation 
> model though.
> 
> Slava
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [REVIEW] SE-0193 - Cross-module inlining and specialization

2017-12-24 Thread Howard Lovatt via swift-evolution
Proposal link: 
https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
What is your evaluation of the proposal?

-1

The proposal puts all the emphasis on the programmer. It is better for the 
compiler to decide if something is to be inclined both across modules and 
within modules. 

If something is made public then it should be fixed for a given major version 
number. No need for extra annotation. 

A module system that allows versioning is a better solution. 

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

Yes significant but wrong solution 

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

No, cluttering up declarations is completely against the clarity of Swift. For 
example who other than people on this group will understand @inline(never) 
@inlinable. 

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

Yes C and C++ and found the equivalent of these annotations problematic. In 
Java they eliminated all this and let the compiler do the work. In practice 
this works much better. 

Perhaps the compiler should publish the SIL or LLVM for all public functions. 
Analogous to Java’s class files. This sort of system works really will, much 
better than C and C++. 

How much effort did you put into your review? A glance, a quick reading, or an 
in-depth study?

Followed the discussions and read the proposal. The proposal doesn’t seem to 
encompass all the discussions. It would be nice if the proposal had a much more 
extensive summary of alternatives suggested. 
-- Howard. 

> On 20 Dec 2017, at 7:19 pm, Ted Kremenek via swift-evolution 
>  wrote:
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
> Reviews are an important part of the Swift evolution process. All review 
> feedback 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/0193-cross-module-inlining-and-specialization.md
> ...
> Reply text
> ...
> Other replies
> What goes into a review of a proposal?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift. 
> 
> When reviewing a proposal, here are some questions to consider:
> 
> 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?
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-19 Thread Howard Lovatt via swift-evolution
Let me give an example. The recent discussion about filterMap aired in the 
discussion stage misgivings about the name; but it went to review with the name 
filterMap. At the review stage more misgivings were raised, the review was 
returned for amendment. An amended name of compactMap was put forward and this 
was accepted yesterday as a result of the 2nd review. I think that this shows 
how the process can work well. If the discussions were shut down with “already 
covered on Swift Evolution”, then the result wouldn’t be as good.

If an argument has been put forward on Evolution, is in the alternatives 
section, and people are still raising the point; it is probably safe to assume 
that the argument hasn’t carried the day and should be revisited.

-- Howard.

> On 19 Dec 2017, at 6:44 pm, Xiaodi Wu  wrote:
> 
>> On Tue, Dec 19, 2017 at 11:15 PM, Howard Lovatt via swift-evolution 
>>  wrote:
>> As an aside: there seems to be increasingly comments about proposals that 
>> say:
>> 
>>   1. This was discussed at the evaluation stage and rejected. 
>>   2. This is how it is implemented in the patch.
>> 
>> And other comments along those lines. Neither the pre-proposal discussions 
>> nor the proposed implementation are intended to limit the scope of the 
>> review. Therefore I don’t think people should raise this as reasons. You 
>> should remember that the process is deliberately staged this way and 
>> different people may well be commenting (in fact the process rather assumes 
>> that people in the formal review will be a wider set of people).
> 
> No, previous discussion don't limit the scope of review per se, but it's not 
> helpful to rehash the same arguments again. We want to encourage everyone to 
> contribute their most thought-out comments as early in the process as 
> possible to give those who propose ideas the fullest chance to flesh out any 
> revisions. However, everyone has finite time to contribute, and if the same 
> discussions are merely replayed at every stage of review, then the process 
> actively discourages thoughtful early participation. After all, why bother 
> defending ideas at the pre-proposal stage if I'm going to have to spend the 
> time repeating myself in a few months' time anyway?
> 
> Of course, if a wider set of people have _new_ comments, those are welcome at 
> a later stage. But, there seems to be a sense that if _I_ haven't said 
> something already, then _I_ should say it whether or not the same viewpoint 
> has already been aired. In my view, such an approach should be actively 
> discouraged for the reasons above. Although a strong consensus within the 
> community should certainly be accounted for, this list--even at the formal 
> review stage--doesn't even come close to approximating the community of Swift 
> users at large. Thus, review is not a vote-counting exercise to maximize the 
> number of people who chime in, but rather it is meant to maximize the number 
> of ideas and perspectives that are aired. If it's already been said, it 
> doesn't need to be said again, even if _I_ haven't said it myself.
> 
>> 
>> Anyway gripe over. 
>> 
>> Proposal link: 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>> What is your evaluation of the proposal?
>> 
>> +1/2
>> 
>> I only give this a half because whilst it is important I can see three 
>> issues:
>> 
>>   1. It doesn’t seem very Swift like to have a different rule, default 
>> non-exhaustive, for public as opposed to non-public. 
>> 
>>   2. It doesn’t seem very Swift like to have the default the unsafe case. 
>> 
>>   3. Other languages have better solutions - see below under other languages
>> 
>> Is the problem being addressed significant enough to warrant a change to 
>> Swift?
>> 
>> Yes, Swift ABI compatibility going forwards is important
>> 
>> Does this proposal fit well with the feel and direction of Swift?
>> 
>> No. As mentioned above different rules for public and a non-safe default 
>> don’t see that Swift like. 
>> 
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
>> Both Java and Scala have a better solution. In these languages enums (Scala 
>> calls them case classes) can implement protocols and the user of an enum 
>> rarely writes a switch statement, instead they call protocol methods. Enums 
>> in these languages are a fixed set of derived classes; i.e. normal OO 
>> programming rather than functional programming, which works well 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-19 Thread Howard Lovatt via swift-evolution
As an aside: there seems to be increasingly comments about proposals that say:

  1. This was discussed at the evaluation stage and rejected. 
  2. This is how it is implemented in the patch.

And other comments along those lines. Neither the pre-proposal discussions nor 
the proposed implementation are intended to limit the scope of the review. 
Therefore I don’t think people should raise this as reasons. You should 
remember that the process is deliberately staged this way and different people 
may well be commenting (in fact the process rather assumes that people in the 
formal review will be a wider set of people). 

Anyway gripe over. 

Proposal link: 
https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
What is your evaluation of the proposal?

+1/2

I only give this a half because whilst it is important I can see three issues:

  1. It doesn’t seem very Swift like to have a different rule, default 
non-exhaustive, for public as opposed to non-public. 

  2. It doesn’t seem very Swift like to have the default the unsafe case. 

  3. Other languages have better solutions - see below under other languages

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

Yes, Swift ABI compatibility going forwards is important

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

No. As mentioned above different rules for public and a non-safe default don’t 
see that Swift like. 

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

Both Java and Scala have a better solution. In these languages enums (Scala 
calls them case classes) can implement protocols and the user of an enum rarely 
writes a switch statement, instead they call protocol methods. Enums in these 
languages are a fixed set of derived classes; i.e. normal OO programming rather 
than functional programming, which works well in the case of wanting to expand 
later the number of enum cases. 

How much effort did you put into your review? A glance, a quick reading, or an 
in-depth study?

Have followed the discussions. Used enums in Swift and other languages 
extensively. 

-- Howard.

> On 19 Dec 2017, at 12:58 pm, Ted Kremenek  wrote:
> 
> 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/0192-non-exhaustive-enums.md
> ...
> Reply text
> ...
> Other replies
> What goes into a review of a proposal?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift. 
> 
> When reviewing a proposal, here are some questions to consider:
> 
> 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?
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

2017-12-15 Thread Howard Lovatt via swift-evolution
I would say it is an advanced use because it is an optimisation and in addition 
an optimisation that requires a lot of knowledge of the fields to be certain 
that a reduced hash is going to be good enough. 

The optimisation doesn’t have a great history, for example in Java they used to 
hash only the 1st 6 characters of a string. However this was exploited in 
denial of service attacks that generated a vast number of strings with the same 
hash value, i.e same 1st 6 characters, that then overwhelmed the dictionary 
(map in Java) used in the web server software to store logins. 

So it wouldn’t be something I would encourage people to do or even worse do by 
accident. 

-- Howard.

> On 16 Dec 2017, at 3:36 pm, Tony Allevato  wrote:
> 
> 
> 
>> On Fri, Dec 15, 2017 at 6:41 PM Howard Lovatt  
>> wrote:
>> I think that is an advanced use, rather than a common use. I would prefer 
>> that to be something you manually code. 
> 
> But why? Why should implementing a subset of fields for hashValue require a 
> developer to also manually implement == when the default synthesized version 
> would be perfectly fine? The relationship between Equatable and Hashable does 
> not go both ways.
> 
> In fact, requiring that they do so is *more* error prone because now they're 
> being forced to implement something that the compiler would have otherwise 
> generated for them.
> 
>  
>> 
>> 
>> -- Howard.
>> 
>>> On 16 Dec 2017, at 7:08 am, Tony Allevato  wrote:
>>> 
>>> 
>>> 
>>>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
>>>>  wrote:
>>>> +1
>>>> I think the simple solution of if you provide either == or hashValue you 
>>>> have to provide both is the best approach. Good catch of this bug.
>>>> -- Howard.
>>> 
>>> That would be a significant usability hit to a common use case. There are 
>>> times where a value is composed of N fields where N is large-ish, and 
>>> equality is dependent on the values of all N fields but the hash value only 
>>> needs to be "good enough" by considering some subset of those fields (to 
>>> make computing it more efficient).
>>> 
>>> That still satisfies the related relationship between == and hashValue, but 
>>> a user wanting to explicitly implement a more efficient hashValue should 
>>> *not* necessarily be required to explicitly write the same == that would be 
>>> synthesized for them in that case.
>>> 
>>>  
>>>> 
>>>> > On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution 
>>>> >  wrote:
>>>> >
>>>> > +1. The proposal wasn’t explicit enough to have either supported or be 
>>>> > against this IMO. It’s a sensible thing to spell out.
>>>> >
>>>> > Daniel Duan
>>>> > Sent from my iPhone
>>>> >
>>>> >> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution 
>>>> >>  wrote:
>>>> >>
>>>> >> SE-0185 is awesome, and brings the long-awaited ability for the 
>>>> >> compiler to provide a default implementation of `==` and `hashValue` 
>>>> >> when you don't provide one yourself. Doug and I were talking the other 
>>>> >> day and thought of a potential pitfall: what should happen if you 
>>>> >> provide a manual implementation of `==` without also manually writing 
>>>> >> your own `hashValue`? It's highly likely that the default 
>>>> >> implementation of `hashValue` will be inconsistent with `==` and 
>>>> >> therefore invalid in a situation like this:
>>>> >>
>>>> >> struct Foo: Hashable {
>>>> >> // This property is "part of the value"
>>>> >> var involvedInEquality: Int
>>>> >> // This property isn't; maybe it's a cache or something like that
>>>> >> var notInvolvedInEquality: Int
>>>> >>
>>>> >> static func ==(a: Foo, b: Foo) -> Bool {
>>>> >>   return a.involvedInEquality == b.involvedInEquality
>>>> >> }
>>>> >> }
>>>> >>
>>>> >> As currently implemented, the compiler will still give `Foo` the 
>>>> >> default hashValue implementation, which will use both of `Foo`'s 
>>>> >> properties to compute the hash, even though `==` only tests one. This 
>>>> >> could be potentially dangerous. Should we suppress the default 
>>>> >> hashValue derivation when an explicit == implementation is provided?
>>>> >>
>>>> >> -Joe
>>>> >> ___
>>>> >> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

2017-12-15 Thread Howard Lovatt via swift-evolution
In Java they have simple to use var arg library functions that equate and hash 
values. I have written similar in my own code. Something like:

func equate(_ e0: (T0, T0), _ e1: (T1, T1)) -> Bool where T0: 
Equatable, T1: Equatable {
return e0.0 == e0.1 && e1.0 == e1.1
}

Unfortunately in Swift I don’t think a var arg version is possible and the 
library would have to have versions up to some arity, say 7.

But it would mitigate the pain of manually writing hash and equate for the 
cases when the compiler written version isn’t available.

-- Howard.

> On 16 Dec 2017, at 8:11 am, Dave DeLong via swift-evolution 
>  wrote:
> 
> @regexident has a long-standing proposal about how to do hashing better that 
> would address this: 
> 
> https://gist.github.com/regexident/1b8e84974da2243e5199e760508d2d25
> 
> Dave
> 
>> On Dec 15, 2017, at 2:04 PM, T.J. Usiyan via swift-evolution 
>>  wrote:
>> 
>> Can we provide a 'standard' method/function that can be used to combine 
>> ordered hash values (`[Int] -> Int`)? That could make manually implementing 
>> `hashValue` less burdensome.
>> 
>> TJ
>> 
>>> On Fri, Dec 15, 2017 at 12:08 PM, Tony Allevato via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
>>>>  wrote:
>>>> +1
>>>> I think the simple solution of if you provide either == or hashValue you 
>>>> have to provide both is the best approach. Good catch of this bug.
>>>> -- Howard.
>>> 
>>> That would be a significant usability hit to a common use case. There are 
>>> times where a value is composed of N fields where N is large-ish, and 
>>> equality is dependent on the values of all N fields but the hash value only 
>>> needs to be "good enough" by considering some subset of those fields (to 
>>> make computing it more efficient).
>>> 
>>> That still satisfies the related relationship between == and hashValue, but 
>>> a user wanting to explicitly implement a more efficient hashValue should 
>>> *not* necessarily be required to explicitly write the same == that would be 
>>> synthesized for them in that case.
>>> 
>>>  
>>>> 
>>>> > On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution 
>>>> >  wrote:
>>>> >
>>>> > +1. The proposal wasn’t explicit enough to have either supported or be 
>>>> > against this IMO. It’s a sensible thing to spell out.
>>>> >
>>>> > Daniel Duan
>>>> > Sent from my iPhone
>>>> >
>>>> >> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution 
>>>> >>  wrote:
>>>> >>
>>>> >> SE-0185 is awesome, and brings the long-awaited ability for the 
>>>> >> compiler to provide a default implementation of `==` and `hashValue` 
>>>> >> when you don't provide one yourself. Doug and I were talking the other 
>>>> >> day and thought of a potential pitfall: what should happen if you 
>>>> >> provide a manual implementation of `==` without also manually writing 
>>>> >> your own `hashValue`? It's highly likely that the default 
>>>> >> implementation of `hashValue` will be inconsistent with `==` and 
>>>> >> therefore invalid in a situation like this:
>>>> >>
>>>> >> struct Foo: Hashable {
>>>> >> // This property is "part of the value"
>>>> >> var involvedInEquality: Int
>>>> >> // This property isn't; maybe it's a cache or something like that
>>>> >> var notInvolvedInEquality: Int
>>>> >>
>>>> >> static func ==(a: Foo, b: Foo) -> Bool {
>>>> >>   return a.involvedInEquality == b.involvedInEquality
>>>> >> }
>>>> >> }
>>>> >>
>>>> >> As currently implemented, the compiler will still give `Foo` the 
>>>> >> default hashValue implementation, which will use both of `Foo`'s 
>>>> >> properties to compute the hash, even though `==` only tests one. This 
>>>> >> could be potentially dangerous. Should we suppress the default 
>>>> >> hashValue derivation when an explicit == implementation is provided?
>>>> >>
>>>> >> -Joe
>>>> &g

Re: [swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

2017-12-15 Thread Howard Lovatt via swift-evolution
I think that is an advanced use, rather than a common use. I would prefer that 
to be something you manually code. 

-- Howard.

> On 16 Dec 2017, at 7:08 am, Tony Allevato  wrote:
> 
> 
> 
>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
>>  wrote:
>> +1
>> I think the simple solution of if you provide either == or hashValue you 
>> have to provide both is the best approach. Good catch of this bug.
>> -- Howard.
> 
> That would be a significant usability hit to a common use case. There are 
> times where a value is composed of N fields where N is large-ish, and 
> equality is dependent on the values of all N fields but the hash value only 
> needs to be "good enough" by considering some subset of those fields (to make 
> computing it more efficient).
> 
> That still satisfies the related relationship between == and hashValue, but a 
> user wanting to explicitly implement a more efficient hashValue should *not* 
> necessarily be required to explicitly write the same == that would be 
> synthesized for them in that case.
> 
>  
>> 
>> > On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution 
>> >  wrote:
>> >
>> > +1. The proposal wasn’t explicit enough to have either supported or be 
>> > against this IMO. It’s a sensible thing to spell out.
>> >
>> > Daniel Duan
>> > Sent from my iPhone
>> >
>> >> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution 
>> >>  wrote:
>> >>
>> >> SE-0185 is awesome, and brings the long-awaited ability for the compiler 
>> >> to provide a default implementation of `==` and `hashValue` when you 
>> >> don't provide one yourself. Doug and I were talking the other day and 
>> >> thought of a potential pitfall: what should happen if you provide a 
>> >> manual implementation of `==` without also manually writing your own 
>> >> `hashValue`? It's highly likely that the default implementation of 
>> >> `hashValue` will be inconsistent with `==` and therefore invalid in a 
>> >> situation like this:
>> >>
>> >> struct Foo: Hashable {
>> >> // This property is "part of the value"
>> >> var involvedInEquality: Int
>> >> // This property isn't; maybe it's a cache or something like that
>> >> var notInvolvedInEquality: Int
>> >>
>> >> static func ==(a: Foo, b: Foo) -> Bool {
>> >>   return a.involvedInEquality == b.involvedInEquality
>> >> }
>> >> }
>> >>
>> >> As currently implemented, the compiler will still give `Foo` the default 
>> >> hashValue implementation, which will use both of `Foo`'s properties to 
>> >> compute the hash, even though `==` only tests one. This could be 
>> >> potentially dangerous. Should we suppress the default hashValue 
>> >> derivation when an explicit == implementation is provided?
>> >>
>> >> -Joe
>> >> ___
>> >> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

2017-12-15 Thread Howard Lovatt via swift-evolution
+1
I think the simple solution of if you provide either == or hashValue you have 
to provide both is the best approach. Good catch of this bug. 
-- Howard. 

> On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution 
>  wrote:
> 
> +1. The proposal wasn’t explicit enough to have either supported or be 
> against this IMO. It’s a sensible thing to spell out.
> 
> Daniel Duan
> Sent from my iPhone
> 
>> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution 
>>  wrote:
>> 
>> SE-0185 is awesome, and brings the long-awaited ability for the compiler to 
>> provide a default implementation of `==` and `hashValue` when you don't 
>> provide one yourself. Doug and I were talking the other day and thought of a 
>> potential pitfall: what should happen if you provide a manual implementation 
>> of `==` without also manually writing your own `hashValue`? It's highly 
>> likely that the default implementation of `hashValue` will be inconsistent 
>> with `==` and therefore invalid in a situation like this:
>> 
>> struct Foo: Hashable {
>> // This property is "part of the value"
>> var involvedInEquality: Int
>> // This property isn't; maybe it's a cache or something like that
>> var notInvolvedInEquality: Int
>> 
>> static func ==(a: Foo, b: Foo) -> Bool {
>>   return a.involvedInEquality == b.involvedInEquality
>> }
>> }
>> 
>> As currently implemented, the compiler will still give `Foo` the default 
>> hashValue implementation, which will use both of `Foo`'s properties to 
>> compute the hash, even though `==` only tests one. This could be potentially 
>> dangerous. Should we suppress the default hashValue derivation when an 
>> explicit == implementation is provided?
>> 
>> -Joe
>> ___
>> 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] Optional Argument Chaining

2017-12-12 Thread Howard Lovatt via swift-evolution
To me the short syntax should be a ‘macro’ expansion (syntax sugar only), 
therefore option 1 in Nick’s example. I choose the syntax sugar option because 
it is easy to explain. 

-- Howard. 

> On 12 Dec 2017, at 7:03 pm, Nick Keets via swift-evolution 
>  wrote:
> 
> 
> 
>> On Tue, Dec 12, 2017 at 12:42 AM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> I think it gets confusing when you have multiple levels of nested 
>> expressions, eg
>> 
>> foo(bar(x?)) + y?
>> 
>> Slava
> 
> I'm not sure we need to optimize much for complicated nested examples, as I 
> don't think this is something that will happen a lot in practice. I imagine 
> the most common scenario will be a single call with one or more arguments.
> 
> Having said that, we did receive 2 different reasonable answers on what the 
> evaluation order would be for:
>   f(a(), b?)
> 
> (1) It desugars to:
> 
> if let someB = b {
>   f(a(), someB)
> }
> 
> So a() doesn't get called if b is nil.
> 
> (2) "If you were to write this logic out by hand then you would short-circuit 
> it and this is analogous to current chaining behaviour so to me evaluating 
> left to right (as Swift usually does) and stopping at the first failed unwrap 
> would make sense"
> 
> So a() gets called if b is nil.
> 
>  
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-05 Thread Howard Lovatt via swift-evolution
+1 for Thorsten’s `dynamic` and `dynamic?`.

-- Howard. 

> On 6 Dec 2017, at 6:13 am, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>>> Am 03.12.2017 um 20:04 schrieb Magnus Ahltorp via swift-evolution 
>>> :
>>> 
>>> 4 Dec. 2017 02:40 Chris Lattner via swift-evolution 
>>>  wrote:
>>> 
>>> That’s a good principle.  However, a dynamic member lookup is just a member 
>>> lookup.  By that principle, it should look like a member lookup :-)
>>> 
>>> Further, I incorporated some of the conversation with Matthew into the 
>>> proposal, showing how adding even a single sigil to dynamic member lookup 
>>> to distinguish it is problematic:
>>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
>>> 
>>> Further, adding something like .dynamic would completely undermind the 
>>> proposal.  You can already write:
>>> 
>>> x.get(“foo”).get(“bar”)
>>> 
>>> having to write:
>>> 
>>> x.dynamic.foo.dynamic.bar
>>> 
>>> has no point.
>> 
>> This example shows what many on this list don't believe: that any Swift 
>> method or member access can fail. If the return value of this "get" method 
>> is an IUO, or not an Optional at all, and doesn't throw, then the expression 
>> would have to fail hard if "foo" didn't resolve to something meaningful.
>> 
>> The most common argument against this proposal is that someone could make an 
>> API using Dynamic Member Lookup that could fail even though it is not 
>> apparent to the caller. But, as we see in the example, this is just as 
>> possible today.
> 
> I just wanted to add that the single purpose of a static type system is to 
> ensure that the methods being called on a receiver are present at runtime and 
> take arguments of the types known at compile time. Of course the type system 
> does not guarantee that those calls to not fail. Even in Haskell there is no 
> guarantee that a function call does not fail as it allows partial patterns 
> (therefore `head []` crashes). Or a function call might enter an infinite 
> loop. But, to repeat, the type system guarantees that the method or member 
> itself will be present.
> 
> Therefore I cannot follow the argument that it follows from the possible 
> failure of a Swift method or member access that it is ok or even a comparable 
> type of failure if the method or member itself is not present. This would 
> imply that Swift’s static type system is unnecessary. Why check for the 
> presence of a method or member if calling it or accessing it might fail 
> anyway? No, I do not buy that argument. And I do not think that I have to 
> provide examples where a static type system is of help.
> 
> The remaining question therefore is whether it is ok to remove the static 
> type system for certain isolated use cases and that might be the case. But I 
> like others would prefer if those use cases would be isolated somehow 
> visually. Someone proposed to require `dynamic` before expressions containing 
> dynamic member lookups similar to `try`, with the additional option to 
> enclose a whole block into `dynamic { … }` to express the same as prefixing 
> each expression with `dynamic`. I still think this has merit:
> 
> 
> let result = dynamic x.foo.bar  // will crash if foo or bar are not present
> 
> let result = dynamic? x.foo.bar // will return nil if foo or bar are not 
> present
> 
> // will crash if foo or bar are not present
> let result = dynamic {
>   let y = x.foo.bar
>   let z = y.baz(42)
>   return z.zork()
> }
> 
> // will return nil if foo or bar are not present
> let result = dynamic? {
>   let y = x.foo.bar
>   let z = y.baz(42)
>   return z.zork()
> } 
> 
> 
> It allows to clearly demarcate the border between regions which are fully 
> statically type checked and those where the static type system be only 
> partially available (depending on the types of the respective receivers) 
> while not being very intrusive due to the block notation. 
> Of course I can still have a mixture of static and dynamic member accesses 
> _within_ a dynamic block but at least I know that when I am outside of such a 
> block there won’t be any dynamic member accesses. None. Zero.
> 
> -Thorsten
> 
> ___
> 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] [RFC] Associated type inference

2017-12-02 Thread Howard Lovatt via swift-evolution
We also know that the current situation isn’t acceptable to a great proposition 
of the community, that is why we are still discussing the issue!

A notable example of reversal of an evolution decision is String’s conformance 
to Collection. Which I think on the 2nd attempt was a much better decision. 

For requiring typedefs for associated types, a fix it and error would be quite 
successful, e.g. Xcode already suggests the typedefs (which I currently accept 
before letting Xcode insert blanks for the missing methods etc.).

-- Howard. 

> On 3 Dec 2017, at 8:15 am, Xiaodi Wu  wrote:
> 
>> On Sat, Dec 2, 2017 at 2:30 PM, Howard Lovatt via swift-evolution 
>>  wrote:
>> Definitely in favour of doing something, I always define the associated 
>> types since I have had so much trouble with the inference.
>> 
>> Personally I would prefer just 1 and 2 and forget 3. I know this would break 
>> a lot of code, but I think we should do that because it is the lesser of the 
>> evils.
> 
> As Doug wrote, an approach that's essentially that was reviewed and rejected 
> in SE-0108. We already know that it's not acceptable to a great proportion of 
> the community.
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-02 Thread Howard Lovatt via swift-evolution
Definitely in favour of doing something, I always define the associated types 
since I have had so much trouble with the inference. 

Personally I would prefer just 1 and 2 and forget 3. I know this would break a 
lot of code, but I think we should do that because it is the lesser of the 
evils. 

-- Howard. 

> On 1 Dec 2017, at 11:20 pm, Johannes Weiß via swift-evolution 
>  wrote:
> 
> Hi Douglas,
> 
> First of all, thanks very much for looking into this seemingly dark corner of 
> the compiler. This caused us a lot of trouble already.
> 
> Comments inline.
> 
>> On 1 Dec 2017, at 12:28 am, Douglas Gregor via swift-evolution 
>>  wrote:
>> 
>> Hello Swift community,
>> 
>> Associated type inference, which is the process by which the Swift compiler 
>> attempts to infer typealiases to satisfy associated-type requirements based 
>> on other requirements, has caused both implementation problems and user 
>> confusion for a long time. Some of you might remember a previous (failed) 
>> attempt to remove this feature from the Swift language, in SE-0108 “Remove 
>> associated type inference”. 
>> 
>> I’m not sure we can remove this feature outright (i.e., the concerns that 
>> sank that proposal are still absolutely valid), because it is so very 
>> convenient and a lot of user code likely depends on it in some form or 
>> other. So, here I’d like to describe the uses of the feature, its current 
>> (very problematic) implementation approach, and a half-baked proposal to 
>> narrow the scope of associated type inference to something that I think is 
>> more tractable. I need help with the design of this feature, because I feel 
>> like it’s going to be a delicate balance between implementability and 
>> expressiveness.
>> 
>> A Motivating Example
>> As a motivating example, let’s consider a “minimal” random access collection:
>> 
>> struct MyCollection {
>>  var contents: [T]
>> }
>> 
>> extension MyCollection: RandomAccessCollection {
>>  var startIndex: Int { return contents.startIndex }
>>  var endIndex: Int { return contents.endIndex }
>>  subscript(index: Int) -> T { return contents[index] }
>> }
>> 
>> This is actually pretty awesome: by providing just two properties and a 
>> subscript, we get the full breadth of the random access collection API! This 
>> is relying heavily on associated type inference (for associated type 
>> requirements) and default implementations specified on protocol extensions. 
>> Without associated type inference, we would have had to write:
>> 
>> 
>> extension MyCollection: RandomAccessCollection {
>>  typealias Element = T
>>  typealias Index = Int
>>  typealias Indices = CountableRange
>>  typealias Iterator = IndexingIterator>
>>  typealias SubSequence = RandomAccessSlice>
>> 
>>  var startIndex: Int { return contents.startIndex }
>>  var endIndex: Int { return contents.endIndex }
>>  subscript(index: Int) -> T { return contents[index] }
>> }
>> 
>> where the bolded typealiases are currently inferred. It was worse back when 
>> we reviewed SE-0108, because IIRC there were a few underscored associated 
>> types (e.g., _Element) that have since been removed. Still, that’s a bit of 
>> additional work to define a “minimal” collection, and requires quite a bit 
>> more understanding: how do I know to choose IndexingIterator, and 
>> CountableRange, and RandomAccessSlice?
>> 
>> The issue would get worse with, e.g., SE-0174 “Change filter to return an 
>> associated type”, which adds an associated type Filtered that almost nobody 
>> will ever customize, and isn’t really fundamental to the way collections 
>> work. Adding Filtered to the standard library would be a source-breaking 
>> change, because users would have to write a typealias giving it its default.
>> 
>> Associated Type Defaults
>> One of the ways in which we avoid having to specify typealiases is to use 
>> associated type defaults. For example, the standard library contains 
>> associated type defaults for Indices, Iterator, and SubSequence. Let’s focus 
>> on Indices:
>> 
>> protocol Collection : Sequence {
>> associatedtype Indices = DefaultIndices
>> // ...
>> }
>> 
>> protocol BidirectionalCollection : Collection {
>> associatedtype Indices = DefaultBidirectionalIndices
>> // ...
>> }
>> 
>> protocol RandomAccessCollection : BidirectionalCollection {
>> associatedtype Indices = DefaultRandomAccessIndices
>> // ...
>> }
>> 
>> The basic idea here is that different protocols in the hierarchy provide 
>> different defaults, and you presumably want the default from the most 
>> specific protocol. If I define a type and make it conform to 
>> BidirectionalCollection, I’d expect to get DefaultBidirectionalIndices 
>> for Indices. If a define a type and make it conform to RandomAccessIterator, 
>> I’d expect to get DefaultRandomAccessIndices.
>> 
>> (Aside: DefaultRandomAccessIndices and DefaultBidirectionalIndices got 
>> collapsed into DefaultIndices now that we have conditional conformances for 
>> the standa

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

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 
> envisioning anything more than what default arguments can already do except 
> for adding a way to choose different default factor

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

2017-11-22 Thread Howard Lovatt via swift-evolution
You don't necessarily need variadic generics to enable tuples to be nominal
types. Though you do need some changes to the generic type system. One
possibility is:

struct Tuple_0_Int_1_Int: Collection /*where T0: T, T1: T*/
{ // Mangle name. Need covariant generics to enable constraint of T0 and T1.
typealias Element = T
typealias Index = Int
typealias SubSequence = Slice>
var _0_: T/*0*/ // Unique name.
var _1_: T/*1*/ // Unique name.
let startIndex: Int = 0
let endIndex: Int = 2
subscript(position: Int) -> T {
switch position {
case 0: return _0_
case 1: return _1_
default: fatalError("Index out of bounds (must be 0 or 1).")
}
}
func index(after i: Int) -> Int {
return i + 1
}
}

// Ideally:
//   1. Extension on Tuple_0_Int_1_Int (SE-143).
//   2. Collection extension rather than on every Tuple (SE-143 extension).
func == (lhs: Tuple_0_Int_1_Int, rhs: Tuple_0_Int_1_Int) -> Bool
where T: Equatable {
let size = lhs.count
guard size == rhs.count else {
return false
}
for i in 0 ..< size {
guard lhs[i] == rhs[i] else {
return false
}
}
return true
}


The above is valid Swift 4, but I really want to be able to say:

   1. `struct Tuple_0_Int_1_Int: Collection where T0: T, T1: T`,
   i.e. covariant generics.
   2. Ideally SE143+ also, so that I can extend Collection to implement
   Equatable, Hashable, etc.

Note:

   1. Tuples extend Collection, not MutableCollection.
   2. T is the base type of T0 and T1.
   3. A Collection of T is sufficient to write interesting generic
   algorithms; equals, etc.


  -- Howard.

On 23 November 2017 at 11:50, David Sweeris via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Nov 21, 2017, at 22:54, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Nov 21, 2017, at 10:48 PM, David Hart  wrote:
>
>
>
> On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Nov 21, 2017, at 10:37 PM, Chris Lattner  wrote:
>
> On Nov 21, 2017, at 9:25 PM, Douglas Gregor  wrote:
>
> Or alternatively, one could decide to make the generics system *only and
> forever* work on nominal types, and make the syntactic sugar just be sugar
> for named types like Swift.Tuple, Function, and Optional.  Either design
> could work.
>
>
> We don’t have a way to make it work for function types, though, because of
> parameter-passing conventions. Well, assuming we don’t invent something
> that allows:
>
> Function
>
> to exist in the type system. Tuple labels have a similar problem.
>
>
> I’m totally aware of that and mentioned it upthread.
>
>
> Eh, sorry I missed it.
>
>  There are various encoding tricks that could make this work depending on
> how you want to stretch the current generics system…
>
>
> I think it’s straightforward and less ugly to make structural types allow
> extensions and protocol conformances.
>
>
> Can somebody explain to me what is less ugly about that? I would have
> naturally thought that the language would be simpler as a whole if there
> only existed nominal types and all structural types were just sugar over
> them.
>
>
> See Thorsten’s response with, e.g.,
>
>   Function, Param>
>
> which handles “inout” by adding wrappers around the parameter types (which
> one would have to cope with in any user of Function), but still doesn’t
> handle argument labels. To handle argument labels, we would need something
> like strings as generic arguments.
>
>
> Oh, good! A use case for “literals as generic parameters” *other* than
> Vectors and Fixed-Size Arrays!
>
> - Dave Sweeris
>
> ___
> 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] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-22 Thread Howard Lovatt via swift-evolution
I would defend turning tuples into structs (change from structural type to
nominal type). This is a much better story for programmers, compare the two
stories:

   1. Tuples are just syntax sugar for simple structs.
   2. Tuples are sort of like structs but there is a list of things tuples
   can do that structs can't and a list of things structs can do and tuples
   can't.

I think unification can be achieved with some name mangling (Chris Lattner
noted this previously - I am just spelling out one scheme), e.g.:

// var a = (zero: 0, one: 1)
public struct Tuple_zero_Int_one_Int { // Mangle name.
public var zero: Int
public var one: Int
}
var a = Tuple_zero_Int_one_Int(zero: 0, one: 1)
// a.0 = -1
a.zero = -1

// var b = (0, 1)
public struct Tuple_0_Int_1_Int { // Mangle name.
public var _0_: Int // Unique name.
public var _1_: Int // Unique name.
}
var b = Tuple_0_Int_1_Int(_0_: 0, _1_: 1)
// a = b
a = Tuple_zero_Int_one_Int(zero: b._0_, one: b._1_)


Implicit in the above transformation is:

   1. struct and tuple have the same memory layout.
   2. `.0` access the 1st stored property of a struct, `.1` the 2nd, etc.


  -- Howard.

On 22 November 2017 at 18:02, David Hart via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On 22 Nov 2017, at 07:54, Douglas Gregor  wrote:
>
>
>
> On Nov 21, 2017, at 10:48 PM, David Hart  wrote:
>
>
>
> On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Nov 21, 2017, at 10:37 PM, Chris Lattner  wrote:
>
> On Nov 21, 2017, at 9:25 PM, Douglas Gregor  wrote:
>
> Or alternatively, one could decide to make the generics system *only and
> forever* work on nominal types, and make the syntactic sugar just be sugar
> for named types like Swift.Tuple, Function, and Optional.  Either design
> could work.
>
>
> We don’t have a way to make it work for function types, though, because of
> parameter-passing conventions. Well, assuming we don’t invent something
> that allows:
>
> Function
>
> to exist in the type system. Tuple labels have a similar problem.
>
>
> I’m totally aware of that and mentioned it upthread.
>
>
> Eh, sorry I missed it.
>
>  There are various encoding tricks that could make this work depending on
> how you want to stretch the current generics system…
>
>
> I think it’s straightforward and less ugly to make structural types allow
> extensions and protocol conformances.
>
>
> Can somebody explain to me what is less ugly about that? I would have
> naturally thought that the language would be simpler as a whole if there
> only existed nominal types and all structural types were just sugar over
> them.
>
>
> See Thorsten’s response with, e.g.,
>
>   Function, Param>
>
> which handles “inout” by adding wrappers around the parameter types (which
> one would have to cope with in any user of Function), but still doesn’t
> handle argument labels. To handle argument labels, we would need something
> like strings as generic arguments. We’d also need to handle calling
> conventions and anything else we invent for function types.
>
>
> Oh ok, I get. The ugliness comes from trying to shoehorn structural types
> into nominal types.
>
> - Doug
>
>
>
>
> ___
> 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] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-21 Thread Howard Lovatt via swift-evolution
In Scala they just define Tuple1, Tuple2, ... up to 22 (I think). 
Eliminates the need for variadic generics and works fine in practice in Scala. 

In Swift this approach is possibly unacceptable, since having to write:

extension Tuple1 ...
extension Tuple2 ...
...
extension Tuple22 ...

Is a real pain. 

However if we added variadic generics, Tuple, then we would also need a 
tuple to become a Collection (or some minimal subset of), e.g.:

extension Tuple: Equatable where T: Equatable {
static func == (lhs: Tuple, rhs: Tuple) -> Bool {
guard lhs.count == rhs.count else {
return false
}
for i in 0 ..< lhs.count {
guard lhs[i] == rhs[i] else {
return false
}
}
return true
}
}

Note how the tuple is treated like a collection. The compiler magic would be to 
make a Tuple a collection, which is more ‘magic’ than ‘magically’ adding 
Hashable :).

Despite the profusion of magic, variadic generics and Tuple collection 
additions are my favourite option. 

-- Howard. 

> On 21 Nov 2017, at 1:17 pm, Chris Lattner via swift-evolution 
>  wrote:
> 
> Yes, I agree, we need variadic generics before we can have tuples conform :-(
> 
> At the end of the day, you want to be able to treat “(U, V, W)” as sugar for 
> Tuple just like we handle array sugar.  When that is possible, Tuple 
> is just a type like any other in the system (but we need variadics to express 
> it).
> 
> Once you have that, then you could write conformances in general, as well as 
> conditional conformances that depend on (e.g.) all the element types being 
> equatable.
> 
> 
> We also need that to allow functions conform to protocols, because functions 
> aren’t "T1->T2” objects, the actual parameter list is an inseparable part of 
> the function type, and the parameter list needs variadics.
> 
> -Chris
> 
>> On Nov 20, 2017, at 6:10 PM, Slava Pestov  wrote:
>> 
>> Ignoring synthesized conformances for a second, think about how you would 
>> manually implement a conformance of a tuple type to a protocol. You would 
>> need some way to statically “iterate” over all the component types of the 
>> tuple — in fact this is the same as having variadic generics.
>> 
>> If we had variadic generics, we could implement tuples conforming to 
>> protocols, either by refactoring the compiler to allow conforming types to 
>> be non-nominal, or by reworking things so that a tuple is a nominal type 
>> with a single variadic generic parameter.
>> 
>> Slava
>> 
>>> On Nov 20, 2017, at 9:06 PM, Tony Allevato via swift-evolution 
>>>  wrote:
>>> 
>>> This is something I've wanted to look at for a while. A few weeks ago I 
>>> pushed out https://github.com/apple/swift/pull/12598 to extend the existing 
>>> synthesis to handle structs/enums when a field/payload has a tuple of 
>>> things that are Equatable/Hashable, and in that PR it was (rightly) 
>>> observed, as Chris just did, that making tuples conform to protocols would 
>>> be a more general solution that solves the same problem you want to solve 
>>> here.
>>> 
>>> I'd love to dig into this more, but last time I experimented with it I got 
>>> stuck on places where the protocol conformance machinery expects 
>>> NominalTypeDecls, and I wasn't sure where the right place to hoist that 
>>> logic up to was (since tuples don't have a corresponding Decl from what I 
>>> can tell). Any pointers?
>>> 
 On Mon, Nov 20, 2017 at 5:51 PM Chris Lattner via swift-evolution 
  wrote:
> On Nov 20, 2017, at 5:48 PM, Kelvin Ma  wrote:
> the end goal here is to use tuples as a compatible currency type, to that 
> end it makes sense for these three protocols to be handled as “compiler 
> magic” and to disallow users from manually defining tuple conformances 
> themselves. i’m not a fan of compiler magic, but Equatable, Hashable, and 
> Comparable are special because they’re the basis for a lot of standard 
> library functionality so i think the benefits of making this a special 
> supported case outweigh the additional language opacity.
 
 I understand your goal, but that compiler magic can’t exist until there is 
 something to hook it into.  Tuples can’t conform to protocols right now, 
 so there is nothing that can be synthesized.
 
 -Chris
 
 
> 
>> On Mon, Nov 20, 2017 at 8:42 PM, Chris Lattner  
>> 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 p

Re: [swift-evolution] [Pitch] Improving capturing semantics of local functions

2017-11-18 Thread Howard Lovatt via swift-evolution
I think you have changed my mind. Virtually everything I want to do can be
achieved by having a closure as an alternative syntax for a function.
Particularly if you could assign to a `var`. You still need extra syntax
for generics and escaping closures.

On Fri, 17 Nov 2017 at 1:45 pm, Slava Pestov  wrote:

>
> On Nov 16, 2017, at 4:38 PM, Howard Lovatt 
> wrote:
>
> When the user writes:
>
> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
> increment(1) // 2
> increment(1.1) // 2.1
>
>
> This means that ‘increment’ is a *value* with a generic function type.
> Presumably you want to pass generic closures as function parameters and
> results too. This is called higher-rank polymorphism and it introduces
> considerable complexity in type checking and code generation.
>
> Compiler issues global struct as above. Then:
>
> let _int_increment = _Function1__T1__T1__T1__E__Numeric({ $0 + 1
> })
> try _int_increment.call(1) // 2
> let _double_increment = _Function1__T1__T1__T1__E__Numeric({
> $0 + 1 })
> try _double_increment.call(1.1) // 2.1
>
>
> What if I do,
>
> let array = [increment]
>
> What is the type of ‘array’?
>
> Slava
>
>
> The more restrictive form that you suggest (I think this is what you mean
> anyway) of only allowed locally, not globally, is easier to name mangle,
> you just need a unique name, nothing about the name needs to be canonical.
> This would be similar to local functions at present and would be useful
> (though I am not sure how many local *generic* functions there are).
>
>
>
>   -- Howard.
>
> On 17 November 2017 at 10:47, Slava Pestov  wrote:
>
>>
>>
>> On Nov 16, 2017, at 3:07 PM, Howard Lovatt via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Where I am proposing a change is that if a closure with generic arguments
>> is encountered it is transformed into the equivalent struct and the struct
>> is typed as it currently is (or if there is a better implementation
>> something equivalent to this), therefore zero change to the type system.
>>
>>
>> Since we already have local functions that can capture values and be
>> generic, there’s no need to implement a new mechanism for name mangling or
>> handling of captures.
>>
>>
>> The changes proposed are a transformation into a struct and name
>> mangling, e.g.:
>>
>> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
>> let increment = { (n: T) throws -> T where T: Numeric in n + 1 }
>> let increment: (T) throws -> T where T: Numeric = { (n: T)
>> throws -> T where T: Numeric in n + 1 }
>>
>>
>> It sounds like what you’re proposing is essentially a new surface syntax
>> for local functions — since a generic closure would not be a first class
>> value, it could not appear anywhere except for the right hand side of a let
>> binding, right?
>>
>> Slava
>>
>
> --
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Synthesizing Concurrency: A Pitch For High-Level Abstractions & Low-Level Intelligence

2017-11-16 Thread Howard Lovatt via swift-evolution
Sorry I don't get the code. In particular:

// Compiler View - of a Constant Property on a Concurrent type
struct Person: Concurrent {
/* Variable Property */

// Constant Property
let birthday: Date {
get {
internalQueue.async { // Immediately returns on calling thread
return underlying_Birthday_Date_Value_Storage
}
}
}

/* Computed Property */
}

Doesn't make sense `async`'s closure doesn't return anything.

What am I missing?

  -- Howard.

On 17 November 2017 at 10:50, Christopher Heath via swift-evolution <
swift-evolution@swift.org> wrote:

> Good evening all,
>
> I had a little idea and thought I’d pitch it. So here goes!
>
> Synthesizing Concurrency aims to provide a foundation by which, regardless
> of concurrency implementation (however current proposal uses GCD examples
> for design), concurrency can be synthesized by the compiler and remove many
> lines of boilerplate code. Offering benefits to Application, Server and OS
> Developers alike; with easy and intelligent concurrency conformance. Also,
> should the community decide to head in another direction with concurrency
> this should be a relatively mappable idea to any Synchronization Primitive
> with a little work.
>
> Thanks for looking, and I hope you like and want to contribute to the
> discussion of the Synthesizing Concurrency proposal. I’ve added a printout
> below. Please give it a read or check out the gist:
> https://gist.github.com/XNUPlay/a0d6f6c0afdb3286e324c480cb5c4290
>
>- Chris
>
>
> Printout :
> *Synthesizing Concurrency*
>
>- Proposal: SE-
>
>- Author: Christopher Heath: XNUPlay 
>- Review Manager: TBD
>- Status: *Pending Discussion*
>- Implementation: *Awaiting Implementation*
>- Decision Notes: TBD
>
>
> *Introduction*
> Developers have to write large amounts of boilerplate code to support
> concurrency in complex types. This proposal offers a way for the compiler
> to automatically synthesize conformance to a high-level Concurrent protocol
> to reduce concurrent boilerplate code, in a set of scenarios where
> generating the correct implementation is known to be possible.
> Specifically:
>
>- It aims to provide a high-level Swift protocol that offers opt-in
>concurrency support for any conformable type
>- It aims to provide a well-defined set of thread-safe, concurrent
>implementations for types, their properties, and methods.
>- It aims to provide a language/library compatible implementation with
>deadlock prevention.
>
>
> *Motivation*
> Building robust types in Swift can involve writing significant boilerplate
> code to support concurrency. By eliminating the complexity for the users,
> we make Concurrent types much more appealing to users and allow them to use
> their own types in optimized concurrent and parallel environments that
> require thread safety with no added effort on their part (beyond declaring
> the conformance).
> Concurrency is typically not pervasive across many types, and for each one
> users must implement the concurrent code such that it performs some form of
> synchronization to prevent unexpected behavior.
>
> *Note: Due to it's current status in Swift and use in the **Runtime*
> *,
> examples are written in **Grand Central Dispatch*
> 
>
> // Concurrent Protocol - Dispatch Example
> protocol Concurrent {
> // Synthesized Property
> var internalQueue: DispatchQueue { get }
> }
>
> What's worse is that if any functions or properties are added, removed, or
> changed, they must each have their own concurrency code and since it must
> be manually written, it's possible to get it wrong, either by omission or
> typographical error (async vs. sync).
> Likewise, it becomes necessary when one wishes to modify an existing type
> that implements concurrency to do so without introducing bottlenecks or
> different forms of synchronization for some functions and not others, this
> leads to illegible and inefficient code that may defeat the purpose of
> implementing concurrency.
> Crafting high-performance, readable concurrency code can be difficult and
> inconvenient to write.
> Swift already derives conformance to a number of protocols, automatically
> synthesizing their inner-workings when possible. Since there is precedent
> for synthesized conformances in Swift, we propose extending it to
> concurrency in predictable circumstances.
>
>
> *Proposed solution*
> In general, we propose that a type synthesize conformance to Concurrent as
> long as the compiler has reasonable insight into the type. We describe the
> specific conditions under which these conformances are synthesized below,
> followed by the details of how the conformance requirements 

Re: [swift-evolution] [Pitch] Improving capturing semantics of local functions

2017-11-16 Thread Howard Lovatt via swift-evolution
No I am proposing 1st class values via the name mangling. But I made a
mistake in the code posted - cut and past error from an earlier playground
- sorry. Which almost certainly confused you.

Anywhere `(T) throws -> T where T: Numeric` appears it is replaced
by `_Function1__T1__T1__T1__E__Numeric`
and the compiler makes the struct once for each concrete T globally. The
global function is:

struct _Function1__T1__T1__T1__E__Numeric where T: Numeric { //
Mangled name
let call: (T) throws -> T
init(_ call: @escaping (T) throws -> T) { self.call = call }
}

When the user writes:

let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
increment(1) // 2
increment(1.1) // 2.1

Compiler issues global struct as above. Then:

let _int_increment = _Function1__T1__T1__T1__E__Numeric({ $0 + 1 })
try _int_increment.call(1) // 2
let _double_increment = _Function1__T1__T1__T1__E__Numeric({ $0
+ 1 })
try _double_increment.call(1.1) // 2.1

The more restrictive form that you suggest (I think this is what you mean
anyway) of only allowed locally, not globally, is easier to name mangle,
you just need a unique name, nothing about the name needs to be canonical.
This would be similar to local functions at present and would be useful
(though I am not sure how many local *generic* functions there are).


  -- Howard.

On 17 November 2017 at 10:47, Slava Pestov  wrote:

>
>
> On Nov 16, 2017, at 3:07 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Where I am proposing a change is that if a closure with generic arguments
> is encountered it is transformed into the equivalent struct and the struct
> is typed as it currently is (or if there is a better implementation
> something equivalent to this), therefore zero change to the type system.
>
>
> Since we already have local functions that can capture values and be
> generic, there’s no need to implement a new mechanism for name mangling or
> handling of captures.
>
>
> The changes proposed are a transformation into a struct and name mangling,
> e.g.:
>
> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
> let increment = { (n: T) throws -> T where T: Numeric in n + 1 }
> let increment: (T) throws -> T where T: Numeric = { (n: T)
> throws -> T where T: Numeric in n + 1 }
>
>
> It sounds like what you’re proposing is essentially a new surface syntax
> for local functions — since a generic closure would not be a first class
> value, it could not appear anywhere except for the right hand side of a let
> binding, right?
>
> Slava
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Improving capturing semantics of local functions

2017-11-16 Thread Howard Lovatt via swift-evolution
I am not proposing a change to the type system at all. Absolutely no change
whatsoever in any form. I don't know how to say this more clearly.

Therefore your example of:

let f = { x in { y in y } }

Remains illegal and is treated by the compiler exactly like it is currently
treated and like it currently does results in "error: type of expression is
ambiguous without more context".

Where I am proposing a change is that if a closure with generic arguments
is encountered it is transformed into the equivalent struct and the struct
is typed as it currently is (or if there is a better implementation
something equivalent to this), therefore zero change to the type system.

The changes proposed are a transformation into a struct and name mangling,
e.g.:

let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
let increment = { (n: T) throws -> T where T: Numeric in n + 1 }
let increment: (T) throws -> T where T: Numeric = { (n: T) throws
-> T where T: Numeric in n + 1 }

Are all the same and would therefore all become:

struct _Function1__T1__T1__T1__E__Numeric where T: Numeric { //
Mangle name
let call: (T) throws -> T = { $0 + 1 }
}

Which is a trivial transformation; a simple one to one correspondence.

The hard part is actually mangling the name into a canonical form, I
propose:

  1. If the function type has 1 argument its name begins `_Function1_`, 2
arguments; `_Function2_`, etc.
  2. The 1st generic type is called `_T1_`, 2nd; `_T2_`, etc.
  3. A function that doesn't return anything has a return type of `_V_`.
  4. Other types are their normal name pretended with an underscore, i.e.
`Numeric` becomes `_Numeric` in running example.
  5. The function argument types are then listed in order followed by the
return type, i.e. `_T1__T1_` which follows `_Function1_` in example.
  6. Type constraints are converted to the equivalent where clause, e.g.
`let increment: (T) throws -> T` is converted to `let
increment: (T) throws -> T where T: Numeric`.
  7. The where clause is converted to the converted names, e.g. `where T:
Numeric` becomes `where _T1_: _Numeric`.
  8. The where clause is sorted so that constraints on T1 are listed first
etc., e.g. `where _T2_: _Numeric, _T1_: _Numeric` becomes `where _T1_:
_Numeric, _T2_: _Numeric`.
  9. Relationships between types are sorted, e.g. `where _T2_.Element ==
_T1_.Element` becomes `where _T1_.Element == _T2_.Element`.
  10. The `where` keyword and spaces are deleted and `:` becomes `_E_`, `.`
becomes `_D_`, and `,` becomes `_C_`, the final part of the running example
is therefore `_T1__E__Numeric`.

Since the name mangling is the tricky bit this would be the main work to
see if the above scheme is robust.

But wouldn't it be great to have generic closures :).


  -- Howard.

On 15 November 2017 at 19:11, Robert Widmann 
wrote:

>
>
> ~Robert Widmann
>
> 2017/11/14 22:02、Matthew Johnson via swift-evolution <
> swift-evolution@swift.org>のメール:
>
>
>
> Sent from my iPhone
>
> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Having read all the arguments for what to add to local functions it still
> strikes me as a poor use of engineering resources to fix them (though I do
> agree they have problems). A better use of resources would be:
>
>   1. Deprecate local functions.
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.
>   2b. Annotatable with:
> 2bi.  @inline
> 2bii. @escaping
>   2c. Generic.
>
> That would be a similar engineering effort and give a better short term
> result of better closures which would be much more widely applicable as
> well as addressing the issues with local functions.
>
>
> I believe generic closures would require adding higher rank types to
> Swift.  That would be pretty cool but I suspect the engineering effort is
> at least an order of magnitude greater than the changes discussed in this
> thread.
>
>
> 100% correct. Slava raises good points about implementation, I’ll raise
> one about semantics:
>
> Without sufficient restrictions on this kind of polymorphism, type
> checking will become significantly more difficult for little corresponding
> benefit.  Enabling the formation of polymorphic types just because you’re
> near an arrow means all sorts of fun things now get to happen
>
> let f = { x in { y in y } }
>
> This program is illegal without a type signature, but still *typeable *in
> that Swift will try to look for bindings to the tn’s in this signature
>
> f :  (T0) -> (T1) -> T1
>
> This is good - this is the most general unifier for this expression
> promised to us by the “Hindley-Milner-like” label we have in the type
> checker docs.
>
> G

Re: [swift-evolution] [Pitch] Improving capturing semantics of local functions

2017-11-16 Thread Howard Lovatt via swift-evolution
Sorry for the delay in replying - I was called up for jury duty!

For recursive closures the compiler would require two changes; if the
variable is a function type then:

  1. It can reference itself, e.g. `let fact: (Int) -> Int = { $0 < 2 ? 1 :
$0 * fact($0 - 1) }` becomes legal. This is not difficult to do because
`fact` is a pointer and therefore of known size.
  2. When a reference to a function type is made and that function isn't
known, the compiler puts a placeholder in (it knows the size - it is a
pointer) and then comes back and fills in the blank latter (just as it
currently does for functions).

These are not show stoppers, it is what the compiler already does for
functions.

Will respond to generics comments in reply to Robert Widmann email.

  -- Howard.

On 15 November 2017 at 17:01, Slava Pestov  wrote:

>
>
> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.
>
>
> Local functions can also be mutually recursive:
>
> func f() {
>   func foo() { bar() }
>   func bar() { foo() }
> }
>
> This would not work with let bindings, which are not visible before the
> location where they are defined.
>
>   2b. Annotatable with:
> 2bi.  @inline
>
>
> Neither closures nor local functions benefit from being annotated with
> @_inlineable, because they can only be referenced from inside their
> defining function, and not across module boundaries. So the optimizer can
> already inline the function or closure if needed.
>
> 2bii. @escaping
>   2c. Generic.
>
>
> See my other response to this thread.
>
> Slava
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Improving capturing semantics of local functions

2017-11-14 Thread Howard Lovatt via swift-evolution
You can add generic closures with some name mangling and simple
transformations, nothing very hard.

The compiler can emit the following for example:

// User writes
let increment: (T) -> T = { $0 + 1 }
increment(1) // 2
increment(1.1) // 2.1


// Compiler issues
struct _Generic_Increment { // Mangle name
let increment: (T) -> T = { $0 + 1 }
}
_Generic_Increment().increment(1) // 2
_Generic_Increment().increment(1.1) // 2.1


It's plausible that the compiler can do better than the above, but the
above would be sufficient and is easy to do.

  -- Howard.

On 15 November 2017 at 14:02, Matthew Johnson 
wrote:

>
>
> Sent from my iPhone
>
> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Having read all the arguments for what to add to local functions it still
> strikes me as a poor use of engineering resources to fix them (though I do
> agree they have problems). A better use of resources would be:
>
>   1. Deprecate local functions.
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.
>   2b. Annotatable with:
> 2bi.  @inline
> 2bii. @escaping
>   2c. Generic.
>
> That would be a similar engineering effort and give a better short term
> result of better closures which would be much more widely applicable as
> well as addressing the issues with local functions.
>
>
> I believe generic closures would require adding higher rank types to
> Swift.  That would be pretty cool but I suspect the engineering effort is
> at least an order of magnitude greater than the changes discussed in this
> thread.
>
>
> It also gives a better long term result of not having to maintain local
> functions.
>
>
>   -- Howard.
>
> On 15 November 2017 at 09:08, Alex Lynch via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> The inference algebra just suggested was enjoyable to read, but is still
>> a new syntax. Which is interesting and deserving of its own proposal. The
>> purpose of this proposal is simply to introduce the existing capture syntax
>> to local functions. Thanks to everyone's feedback pointing out that the
>> `self` reference analysis is a deeper question than initially realized.
>>
>> Alex
>>
>> On Tue, Nov 14, 2017 at 4:36 PM, Mike Kluev via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> On 14 November 2017 at 21:02, David Hart  wrote:
>>>
>>>>
>>>>
>>>> I’d be very hesitant to introduce this syntax:
>>>>
>>>>
>>>>- it’s new syntax, so it comes with a complexity tax (it isn’t
>>>>naturally obvious what it means for a func to be weak)
>>>>- it’s only sugar for the capture of self
>>>>
>>>> it might cover well over 90% of use cases (by my "pessimistic"
>>> estimate)... if someone has a quick way to scan and analyse, say, github
>>> swift sources we may even know that current percentage number of real life
>>> usage.
>>>
>>>>
>>>>- it doesn’t transpose well to local closures
>>>>
>>>>
>>> the last one - maybe not. follow me:
>>>
>>> let closure = { [weak self, bar] in ... }
>>>
>>> which today can be written as:
>>>
>>> let closure = { [weak self, bar] () -> Int in ... } // full form
>>>
>>> or as:
>>>
>>> let closure: () -> Int = { [weak self, bar] in ... } // full form
>>>
>>> which allows this change:
>>>
>>> let closure:  [weak self, bar] () -> Int = { ... } // full alt form
>>>
>>> or in alternative form:
>>>
>>> let closure:  weak () -> Int = { [bar] in ... } // short hand form
>>>
>>> same can be with functions:
>>>
>>> func fn() -> Int { [weak self, bar] in ... } // full form
>>>
>>> weak func fn() -> Int { [bar] in ... } // short hand form
>>>
>>> the two capture attributes will in practice be "close" to each other:
>>>
>>> weak func fn() {
>>> [bar] in
>>> 
>>> }
>>>
>>> and in majority of cases there will be only weak self:
>>>
>>> weak func fn() {
>>> 
>>> }
>>>
>>> Mike
>>>
>>>
>>> ___
>>> 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
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-14 Thread Howard Lovatt via swift-evolution
The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/
proposals/0189-restrict-cross-module-struct-initializers.md



   -

   What is your evaluation of the proposal?

+1, more an oversight in the original design rather than a change. Funny
how this problem was caught for classes and not structs.

   -

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

Yes, focus is on getting rid of inconsistencies and problems.

   -

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

Yes, Swift is meant to be consistent.

   -

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

No

   -

   How much effort did you put into your review? A glance, a quick reading,
   or an in-depth study?

Glance

  -- Howard.

On 15 November 2017 at 08:24, Jordan Rose via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi, David. This only affects *cross-module* use cases, which means that
> the automatically synthesized initializer doesn’t come into play (because
> it’s not public). Is the clarification you’re looking for something like “a
> 'source-breaking change’ is something that can cause previously compiling
> code in another module to result in compile-time errors”?
>
> Thanks for pointing out the potential for confusion here!
> Jordan
>
>
> On Nov 14, 2017, at 12:55, David Hart  wrote:
>
> I was initially quite confused about the proposal's first sentence:
> "Adding a property to a public struct in Swift ought to not be a
> source-breaking change.” Because I nearly always rely (like many
> developers) on struct automatic initializers, adding a property is pretty
> much always a source-breaking if I don’t write an explicit initializer with
> the same signature as the old automatic. Can something be done to clarify
> the proposal in that regard or is it too late?
>
> David.
>
> On 14 Nov 2017, at 20:31, Ted Kremenek via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> The review of "SE-0189: Restrict Cross-module Struct Initializers" begins
> now and runs through *November 21, 2017*.
>
> The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0189-restrict-cross-module-struct-initializers.md
>
> Reviews are an important part of the Swift evolution process. All review
> feedback 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/0189-restrict-cross-module-struct-initializers.md
> ...
> Reply text
> ...
> Other replies
>
> What goes into a review of a proposal?
>
> The goal of the review process is to improve the proposal under review
> through constructive criticism and, eventually, determine the direction of
> Swift.
>
> When reviewing a proposal, here are some questions to consider:
>
>-
>
>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?
>
> Thanks,
> Ted Kremenek
> 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] Improving capturing semantics of local functions

2017-11-14 Thread Howard Lovatt via swift-evolution
Having read all the arguments for what to add to local functions it still
strikes me as a poor use of engineering resources to fix them (though I do
agree they have problems). A better use of resources would be:

  1. Deprecate local functions.
  2. Allow closures when assigned to a function type to be:
  2a. Recursive.
  2b. Annotatable with:
2bi.  @inline
2bii. @escaping
  2c. Generic.

That would be a similar engineering effort and give a better short term
result of better closures which would be much more widely applicable as
well as addressing the issues with local functions.

It also gives a better long term result of not having to maintain local
functions.


  -- Howard.

On 15 November 2017 at 09:08, Alex Lynch via swift-evolution <
swift-evolution@swift.org> wrote:

> The inference algebra just suggested was enjoyable to read, but is still a
> new syntax. Which is interesting and deserving of its own proposal. The
> purpose of this proposal is simply to introduce the existing capture syntax
> to local functions. Thanks to everyone's feedback pointing out that the
> `self` reference analysis is a deeper question than initially realized.
>
> Alex
>
> On Tue, Nov 14, 2017 at 4:36 PM, Mike Kluev via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On 14 November 2017 at 21:02, David Hart  wrote:
>>
>>>
>>>
>>> I’d be very hesitant to introduce this syntax:
>>>
>>>
>>>- it’s new syntax, so it comes with a complexity tax (it isn’t
>>>naturally obvious what it means for a func to be weak)
>>>- it’s only sugar for the capture of self
>>>
>>> it might cover well over 90% of use cases (by my "pessimistic"
>> estimate)... if someone has a quick way to scan and analyse, say, github
>> swift sources we may even know that current percentage number of real life
>> usage.
>>
>>>
>>>- it doesn’t transpose well to local closures
>>>
>>>
>> the last one - maybe not. follow me:
>>
>> let closure = { [weak self, bar] in ... }
>>
>> which today can be written as:
>>
>> let closure = { [weak self, bar] () -> Int in ... } // full form
>>
>> or as:
>>
>> let closure: () -> Int = { [weak self, bar] in ... } // full form
>>
>> which allows this change:
>>
>> let closure:  [weak self, bar] () -> Int = { ... } // full alt form
>>
>> or in alternative form:
>>
>> let closure:  weak () -> Int = { [bar] in ... } // short hand form
>>
>> same can be with functions:
>>
>> func fn() -> Int { [weak self, bar] in ... } // full form
>>
>> weak func fn() -> Int { [bar] in ... } // short hand form
>>
>> the two capture attributes will in practice be "close" to each other:
>>
>> weak func fn() {
>> [bar] in
>> 
>> }
>>
>> and in majority of cases there will be only weak self:
>>
>> weak func fn() {
>> 
>> }
>>
>> Mike
>>
>>
>> ___
>> 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] Introduce user-defined dynamically "callable" types

2017-11-11 Thread Howard Lovatt via swift-evolution
In Java you can have annotation processors, user supplied compiler extensions, 
that are extensively used for making frameworks easier to use and for general 
interfacing to ‘foreign stuff’.

Would a limited form of user supplied compiler extension be an alternative, an 
import processor. Special import syntax, import beginning with ‘Foreign’, would 
be recognised by the compiler and a user supplied import processor would be 
called, in the case of the example for Python. The import processor would 
generate the glue code. Below is a basic example to give a feel for what I am 
proposing.

(Syntax, names, etc. in code below just the 1st that came into my head!)

  — Howard.

==

import Foreign.Python.Foo // Special import tag `Foreign` calls a user supplied 
compiler extension that parses the imported Python and generates something 
along these lines (its up to the importer the exact code generated!):

protocol _ForeignPythonCallable {
func call(method: Any, arguments: Any...) throws -> Any
}

extension _ForeignPythonCallable {
func call(method: Any, arguments: Any...) throws -> Any {
return "method: \(method), arguments: \(arguments)" // Method lookup 
and calling code for Python.
}
}

class Foo: _ForeignPythonCallable {
// Could override `call` if more efficient than complete general lookup was 
possible.
enum _ForeignPythonMethodNames { // This might be a C struct so that it 
matches perfectly what the python interpreter is expecting.
case bar
}
enum _ForeignPythonMethodBarArguments { // This might be a C struct so that 
it matches perfectly what the python interpreter is expecting.
case x(Any)
case noName1(Any)
case y(Any)
}
func bar(x: Any, _ noName1: Any, y: Any) -> Any {
do {
return try call(method: _ForeignPythonMethodNames.bar, arguments: 
_ForeignPythonMethodBarArguments.x(x), 
_ForeignPythonMethodBarArguments.noName1(noName1), 
_ForeignPythonMethodBarArguments.y(y))
} catch {
fatalError("Method `bar` does not throw, therefore Python importer 
bug.")
}
}
}

// Then the consumer of `Foo` uses as per normal Swift:

let foo = Foo()
foo.bar(x: 1, 23, y: 17)

class TypedFoo: Foo { // For many dynamic languages this wouldn't be possible 
to automatically generate via the import, therefore would have to be hand 
written.
func bar(x: Int, _ noName1: Int, y: Int) -> String {
return super.bar(x: x, noName1, y: y) as! String
}
}
let typedFoo = TypedFoo()
typedFoo.bar(x: 1, 23, y: 17)


> On 12 Nov 2017, at 11:15 am, Andrew Bennett via swift-evolution 
>  wrote:
> 
> HI, this proposal looks really interesting!
> 
> I have a few questions:
> 
> Clarity on the proposal's intent
> Nice cheap bridges, or lowering barriers to bridging?
> 
> I can see this providing a nice quick interface to Python from Swift, but I'm 
> not sure if the exposed interface will be very Swifty (you probably have a 
> much better idea of what is Swifty ;) than I do though). It seems you want it 
> to be possible for everything to be dynamically exposed, I've used similar 
> with Lua's meta methods, and I found it to be very powerful, you could 
> basically implement inheritance in the language, which wasn't necessarily a 
> good thing in retrospect.
> 
> Is it common for the the argument labels in other languages to be open ended, 
> or are labels typically finite? If the answer is finite, why not use a Swift 
> method as the wrapper?
> Do you want duck typing, and would it be better to expose this via a protocol?
> 
> It seems like in almost every case you could do something like this:
> 
> func myMethod(a: X? = 
> nil, b: Y) {
> pythonBridge.call("myMethod", arguments: ["a": X, "b": Y])
> }
> 
> It might be good to add some use-cases (a popular Python library perhaps) to 
> the proposal where this type of bridge would be insufficient :).
> 
> It seems like this proposal pushes the responsibility of Swifty-ness and 
> type-safety to the caller. At some point you'll have to write a type-safe 
> bridging layer, or write your entire program in non-Swifty code ("The most 
> obvious way to write code should also behave in a safe manner"). Is the main 
> goal to lower the barrier to Python and other dynamic languages? or is it to 
> provide a cheap nice Swifty bridge? I have the above concerns about the 
> latter.
> 
> Alternative sugar
> 
> Ruby has Keyword Arguments for similar sugar:
> 
> def foo(regular, hash={})
> puts "the hash: #{hash}"
> 
> 
> I'm sure you're aware of it, but I'll explain for completeness, any trailing 
> argument labels are stored and passed as a hash:
> 
> foo(regular, bar: "hello", bas: 123) # outputs 'the hash: [bar: "hello", bas: 
> 123]'
> Have you considered an alternative like this? For example:
> 
> func myMethod(regular: Int, store: @argcapture [String: PythonConvertible]) 
> -> PythonConvertible
> 
> I'm 

Re: [swift-evolution] [Review] SE-188 Make stdlib index types Hashable

2017-11-09 Thread Howard Lovatt via swift-evolution
Proposal link:
https://github.com/apple/swift-evolution/blob/master/
proposals/0188-stdlib-index-types-hashable.md

• What is your evaluation of the proposal?

+1 but would like it to further and require all index types to be Hashable.

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

It has been a problem for me in the past, however just requiring the
standard library ones to be hashable would solve the problem of third party
libraries, therefore suggest all hashable.

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

Yes, this is the sort of thing that needs finalising before ABI stability
else we will be stuck with a problem.

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

Yes, Java, Scala, etc. Most languages have a hashable index so you can have
a set on indices etc.

• How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

Have read the review and have also implemented my own collections, which
used hashable indices.

  -- Howard.

On 9 November 2017 at 12:55, Ben Cohen via swift-evolution <
swift-evolution@swift.org> wrote:

> Hello, Swift community!
>
> The review of “SE-0188: Make stdlib index types Hashable” begins now and
> runs through November 14th, 2017. The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0188-stdlib-index-types-hashable.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 me as 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/0188-stdlib-index-types-hashable.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
>
>
> As always, thank you for contributing to the evolution of Swift.
>
> Ben Cohen
> 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] Eliminate Collection.IndexDistance associated type

2017-11-08 Thread Howard Lovatt via swift-evolution
+1 it seems like a generic type just for the sake of it. Many languages do 
without a specific type for distance and use Int and it is a better solution 
because it is simpler. 

-- Howard.

> On 9 Nov 2017, at 8:37 am, Ben Cohen via swift-evolution 
>  wrote:
> 
> 
> Hi Swift Evolution,
> 
> A pitch for review, aimed at simplifying generic Collection algorithms.
> 
> Online copy here:
> 
> https://github.com/airspeedswift/swift-evolution/blob/5d1ffda2e83f5b95a88d5ce3948c5fd0d59622f4/proposals/-eliminate-indexdistance.md
> 
> # Eliminate `IndexDistance` from `Collection`
> 
> * Proposal: [SE-](-eliminate-indexdistance.md)
> * Authors: [Ben Cohen](https://github.com/airspeedswift)
> * Review Manager: TBD
> * Status: **Awaiting review**
> * Implementation: 
> [apple/swift#12641](https://github.com/apple/swift/pull/12641)
> 
> ## Introduction
> 
> Eliminate the associated type `IndexDistance` from `Collection`, and modify 
> all uses to the concrete type `Int` instead.
> 
> ## Motivation
> 
> `Collection` allows for the distance between two indices to be any 
> `SignedInteger` type via the `IndexDistance` associated type. While in 
> practice the distance between indices is almost always
> an `Int`, generic algorithms on `Collection` need to either constrain 
> `IndexDistance == Int`, or write their algorithm to be generic over any 
> `SignedInteger`.
> 
> Swift 4.0 introduced the ability to constrain associated types with `where` 
> clauses
> ([SE-142](https://github.com/apple/swift-evolution/blob/master/proposals/0142-associated-types-constraints.md))
>  and will soon allow protocol constraints
> to be recursive 
> ([SE-157](https://github.com/apple/swift-evolution/blob/master/proposals/0157-recursive-protocol-constraints.md)).
>  With these features,
> writing generic algorithms against `Collection` is finally a realistic tool 
> for intermediate Swift programmers. You no longer need to know to
> constrain `SubSequence.Element == Element` or `SubSequence: Collection`, 
> missing constraints that previously led to inexplicable error messages.
> 
> At this point, the presence of `IndexDistance` is of of the biggest hurdles 
> that new users trying to write generic algorithms face. If you want to
> write code that will compile against any distance type, you need to 
> constantly juggle with explicit type annotations (i.e. you need to write `let 
> i:
> IndexDistance = 0` instead of just `let i = 0`), and perform `numericCast` to 
> convert from one distance type to another.
> 
> But these `numericCasts` are hard to use correctly. Given two collections 
> with different index distances, it's very hard to reason about whether your
> `numericCast` is casting from the smaller to larger type correctly. This 
> turns any problem of writing a generic collection algorithm into both a 
> collection _and_
> problem. And chances are you are going to need to interoperate with a method 
> that takes or provides a concrete `Int` anyway (like `Array.reserveCapacity` 
> inside
> `Collection.map`). Much of the generic code in the standard library would 
> trap if ever presented with a collection with a distance greater than 
> `Int.max`.
> Additionally, this generalization makes specialization less likely and 
> increases compile-time work.
> 
> For these reasons, it's common to see algorithms constrained to 
> `IndexDistance == Int`. In fact, the inconvenience of having to deal with 
> generic index
> distances probably encourages more algorithms to be constrained to `Index == 
> Int`, such as [this
> code](https://github.com/airspeedswift/swift-package-manager/blob/472c647dcad3adf4344a06ef7ba91d2d4abddc94/Sources/Basic/OutputByteStream.swift#L119)
>  in
> the Swift Package Manager. Converting this function to work with any index 
> type would be straightforward. Converting it to work with any index distance
> as well would be much trickier.
> 
> The general advice from [The Swift Programming
> Language](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309)
>  when writing Swift code is to encourage users to stick to using `Int` unless 
> they have a special reason not to:
> 
> > Unless you need to work with a specific size of integer, always use `Int` 
> > for integer values in your code. [...] `Int` is preferred, even when the 
> > values to be stored are known to be nonnegative. A consistent use of Int 
> > for integer values aids
> code interoperability, avoids the need to convert between different number 
> types, and matches integer type inference[.]
> 
> There are two main use cases for keeping `IndexDistance` as an associated 
> type rather than concretizing it to be `Int`: tiny collections that might
> benefit from tiny distances, and huge collections that need to address 
> greater than `Int.max` elements. For example, it may seem wasteful to force a
> type that presents the bits in a `UInt` as a col

Re: [swift-evolution] Pitch: Remove default initialization of optional bindings

2017-11-07 Thread Howard Lovatt via swift-evolution
Not a big deal either way, but I prefer the 2nd (nil) form and therefore
would like to see the 1st form go. It would make Swift more consistent,
consider:

let o: Int? // Looks like nil is assigned.
if someTest {
o = 1 // Why isn't this an error? (OK I know why - but it looks odd.)
} else {
o = nil
}


Whilst the above works it is weird because if you are aware that o: Int?
normally assigns nil then the above looks like o, which is a let, is
assigned to twice. If you do the equivalent of the above for a non-optional
it is an error.

  -- Howard.

On 8 November 2017 at 07:54, Adrian Zubarev via swift-evolution <
swift-evolution@swift.org> wrote:

> Same here, but I wouldn’t care much if it were gone.
>
>
> Am 7. November 2017 um 21:40:56, David Hart via swift-evolution (
> swift-evolution@swift.org) schrieb:
>
> Yeah, I use the first form constantly.
>
> > On 6 Nov 2017, at 23:33, Slava Pestov via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > Hi all,
> >
> > Right now, the following two declarations are equivalent:
> >
> > struct S {
> > var x: Int?
> > }
> >
> > struct S {
> > var x: Int? = nil
> > }
> >
> > That is, mutable bindings of sugared optional type (but not
> Optional!) always have a default value of ‘nil’. This feature increases
> the surface area of the language for no good reason, and I would like to
> deprecate it in -swift-version 5 with a short proposal. Does anyone feel
> strongly about giving it up? I suspect most Swift users don’t even know it
> exists.
> >
> > Slava
> > ___
> > 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
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-07 Thread Howard Lovatt via swift-evolution
The review of "SE-0187: Introduce Sequence.filterMap(_:)" begins now and
runs through November 14th, 2017.  The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/
proposals/0187-introduce-filtermap.md


• What is your evaluation of the proposal?
Worthwhile since there is a potential problem. However I am not convinced:

  1. About the name, it sounds like it filters and then maps rather than
what it really does which is map and then filter. Also, what does it
filter? How about mapFilterOptional (which is similar to Haskel name where
Maybe is equivalent of Optional).

  2. There is a more general problem of automatically wrapping a
non-optional in an optional; which this is a symptom off. So rather than
fix up the symptom, why not fix the problem. In particular; why not stop
the automatic conversion of a value to an optional, instead provide a value
to optional operator (the reverse of !). Say a trailing ~, used like 5~ to
mean Optional.some(5). ~ chosen because it is like an S, for some, on it's
side.

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

• Does this proposal fit well with the feel and direction of Swift?
Yes and no - see comments above. In particular automatic conversions are
not common in Swift. The conversion of a value to an optional automatically
therefore stands out.

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

• How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?
Participated in Swift Evolution discussion

  -- Howard.

On 8 November 2017 at 10:23, John McCall  wrote:

> Hello, Swift community!
>
> The review of "SE-0187: Introduce Sequence.filterMap(_:)" begins now and
> runs through November 14th, 2017.  The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0187-introduce-filtermap.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 me as 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/0187-introduce-filtermap.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
>
>
> As always, thank you for contributing to the evolution of Swift.
>
> John McCall
> Review Manager
>
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Making capturing semantics of local

2017-10-27 Thread Howard Lovatt via swift-evolution
I should qualify that I am not proposing removing local functions without
replacing them with closures that have the same power. I don't believe
powerful closures are something the compiler couldn't do, in fact I believe
it is something that is relatively easy. I believe this because there isn't
much difference between a function and a closure and because the function
behaviour is easy to fake and therefore something the compiler could do (in
fact do better than you can fake). Two of the example presented of things
closures can't do are mutual recursion and generics, both are fakable:

var isEven: ((UInt) -> Bool)! = nil // Forward declaration!
var isOdd: ((UInt) -> Bool)! = nil
isEven = { n in
if n == 0 {
return true
} else {
return isOdd(n - 1)
}
}
isOdd = { n in
if n == 0 {
return false;
} else {
return isEven(n - 1)
}
}
isEven(4) // True
isOdd(4) // False

struct GenericIncrement {
let increment = { (n: T) -> T in
n + 1
}
}
let int = GenericIncrement() // Reify increment and name mangle!
int.increment(1) // 2
let double = GenericIncrement()
double.increment(1.1) // 2.1


The reason for showing code above is to demonstrate that the compiler could
do this (in fact it could do better) - I am not suggesting anyone uses the
above!

  -- Howard.

On 28 October 2017 at 10:01, Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

> That sounds like a bug, and it could occur with closure expressions also,
> since at the SILGen level and below they’re basically the same thing.
> Please file a bug if you come up with a reduced test case.
>
> Slava
>
> > On Oct 27, 2017, at 4:00 PM, Jon Gilbert 
> wrote:
> >
> > I have run into nondescript compiler crashes (like segmentation faults,
> etc.) when using local functions to do certain things, like wrapping the
> parent function’s escaping closure arguments in other closures that capture
> variables from the parent function’s local scope, especially when those
> variables themselves are function types that do the wrapping, and therefore
> take closures as arguments. (Of course, all of these closures taking
> generic arguments conforming to protocols with associated types made things
> extra interesting.)
> >
> > I don’t know if this makes local functions actively harmful, or if it
> means function types in capture lists need to support @escaping, but it
> does remind me to go back and try to reproduce those weird issues in a
> sample project or playground page so I can make a bug report to Apple.
> >
> > Jonathan
> >
> >> On Oct 27, 2017, at 12:29, Slava Pestov via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> I mean, we could remove a lot of language features without giving up
> turing completeness. But I’ve personally used local functions in multiple
> languages and found them useful. I certainly don’t see why the feature is
> actively harmful, which is the criteria for introducing a source breaking
> change in Swift 5.
> >
>
> ___
> 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] Making capturing semantics of local

2017-10-26 Thread Howard Lovatt via swift-evolution
> Closures cannot replace all uses of local functions. Local functions can
be recursive, and have a generic parameter list.

My response would be add these featurtes to closures, it will make closures
better.

In terms of recursion you can fiddle it:

struct RecursiveClosure {
var c: C! = nil
}
func factorial(_ n: Int) -> Int {
var recursive = RecursiveClosure<(Int) -> Int>()
recursive.c = { x in
(x == 0) ? 1 : x * recursive.c(x - 1)
}
return recursive.c(n)
}
factorial(5) // 120


  -- Howard.

On 27 October 2017 at 15:53, Slava Pestov  wrote:

>
>
> On Oct 26, 2017, at 9:52 PM, Howard Lovatt 
> wrote:
>
> It would be easy to provide a fixit.
>
>
> That is still a source breaking change that requires migration, though.
>
> How often are they actually used? I rarely use them and all my use cases
> could be a closure instead.
>
> Also see Mike Kluev example; local functions are arguably worse than
> closures in all cases (provided that you can appropriately annotate the
> function type).
>
>
> Closures cannot replace all uses of local functions. Local functions can
> be recursive, and have a generic parameter list.
>
> Slava
>
>
>   -- Howard.
>
> On 27 October 2017 at 12:26, Slava Pestov  wrote:
>
>>
>>
>> On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Rather than expand local function syntax why not deprecate local
>> functions completely
>>
>>
>> I don’t think at this point such a drastic change to the language is
>> likely to happen.
>>
>> Slava
>>
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Making capturing semantics of local

2017-10-26 Thread Howard Lovatt via swift-evolution
It would be easy to provide a fixit. How often are they actually used? I
rarely use them and all my use cases could be a closure instead.

Also see Mike Kluev example; local functions are arguably worse than
closures in all cases (provided that you can appropriately annotate the
function type).

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov  wrote:

>
>
> On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Rather than expand local function syntax why not deprecate local functions
> completely
>
>
> I don’t think at this point such a drastic change to the language is
> likely to happen.
>
> Slava
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Making capturing semantics of local

2017-10-26 Thread Howard Lovatt via swift-evolution
Allow function types that are both let and initialized to be annotated
with @inline.
If closures get more features then we fix the bug pointed out with local
functions and we get better closures. Good bang for the buck.

  -- Howard.

On 27 October 2017 at 12:22, Taylor Swift  wrote:

> i use a lot of local @inline(__always) functions as a sort of weird macro
> so this change would be hugely source breaking. Also can you even annotate
> a function object as force-inlineable?
>
> On Oct 26, 2017, at 6:45 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> The issues raised about local capture by local (inner) functions are
> valid, likewise the discussion about the @nonescaping annotation are also
> valid.
>
> Rather than expand local function syntax why not deprecate local functions
> completely and add the @nonescaping annotation to local closures following
> the argument syntax, e.g. the running example:
>
>
> class A {
> func foo() {
> let local: @nonescaping () -> void = {
> bar() // Capture of self does not need to be explicit in
> the closure because it is non-escaping.
> }
> local()
> }
> func bar() { ... }
> }
>
> This is a simpler and more powerful solution (I think others have pretty
> much suggested the same thing in this forum but have not explicitly said
> get rid of local functions).
>
>   -- Howard.
>
> On 27 October 2017 at 08:16, Mike Kluev via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On 26 October 2017 at 20:24, David Hart  wrote:
>>
>>> I don’t see how this makes any sense or be possible:
>>>
>>> * It doesn’t make sense for me because local is not a member function of
>>> A.
>>> * It would cause ambiguity when trying to call another member function
>>> with the same name as the local function.
>>>
>>
>> in the escaping contexts, "self." is currently required before the
>> instance members (**).
>> the idea is to require it before some local functions as well,
>> recursively analysing what these local functions do (at the compile time).
>>
>> /* local */ foo() {
>> bar()
>> variable = 1
>> }
>>
>> ...
>> self.foo()
>>
>> // self is required because the compiler knows what's inside, and if it
>> were to put the content inline that would be:
>>
>> // inlining foo pseudo code:
>>  self.bar()
>>  self.variable = 1
>>
>> hence the compiler can figure out that in this case "self" is required
>> before foo()
>>
>> on the other hand:
>>
>> /* local */ poo() {
>> print("doesnt not capture anything")
>> }
>>
>> here, if compiler were to use poo in the escaping context it would not
>> require "self." before it.
>>
>> this decision (whether to require "self." on not) can be on the use side.
>>
>> (**) FTM, the normal instance methods that do not capture anything may as
>> well not require "self." before them in escaping contexts:
>>
>> /* non local */ baz() {
>> print("doesn't capture anything")
>> }
>>
>> Mike
>>
>>
>> ___
>> 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] Making capturing semantics of local

2017-10-26 Thread Howard Lovatt via swift-evolution
The issues raised about local capture by local (inner) functions are valid,
likewise the discussion about the @nonescaping annotation are also valid.

Rather than expand local function syntax why not deprecate local functions
completely and add the @nonescaping annotation to local closures following
the argument syntax, e.g. the running example:


class A {
func foo() {
let local: @nonescaping () -> void = {
bar() // Capture of self does not need to be explicit in
the closure because it is non-escaping.
}
local()
}
func bar() { ... }
}

This is a simpler and more powerful solution (I think others have pretty
much suggested the same thing in this forum but have not explicitly said
get rid of local functions).

  -- Howard.

On 27 October 2017 at 08:16, Mike Kluev via swift-evolution <
swift-evolution@swift.org> wrote:

> On 26 October 2017 at 20:24, David Hart  wrote:
>
>> I don’t see how this makes any sense or be possible:
>>
>> * It doesn’t make sense for me because local is not a member function of
>> A.
>> * It would cause ambiguity when trying to call another member function
>> with the same name as the local function.
>>
>
> in the escaping contexts, "self." is currently required before the
> instance members (**).
> the idea is to require it before some local functions as well, recursively
> analysing what these local functions do (at the compile time).
>
> /* local */ foo() {
> bar()
> variable = 1
> }
>
> ...
> self.foo()
>
> // self is required because the compiler knows what's inside, and if it
> were to put the content inline that would be:
>
> // inlining foo pseudo code:
>  self.bar()
>  self.variable = 1
>
> hence the compiler can figure out that in this case "self" is required
> before foo()
>
> on the other hand:
>
> /* local */ poo() {
> print("doesnt not capture anything")
> }
>
> here, if compiler were to use poo in the escaping context it would not
> require "self." before it.
>
> this decision (whether to require "self." on not) can be on the use side.
>
> (**) FTM, the normal instance methods that do not capture anything may as
> well not require "self." before them in escaping contexts:
>
> /* non local */ baz() {
> print("doesn't capture anything")
> }
>
> Mike
>
>
> ___
> 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] [SPM] Roadmap?

2017-10-25 Thread Howard Lovatt via swift-evolution
To clarify. I meant the infrastructure for IDE integration with Xcode as one of 
the IDEs that used that infrastructure. 

-- Howard. 

> On 24 Oct 2017, at 11:26 pm, David James via swift-evolution 
>  wrote:
> 
> I would also +1000 Xcode integration, whoever does it. I’m tired of fighting 
> with command-line mumbo jumbo just to setup and manage dependencies. SPM 
> should pave the way for high-level or junior devs to easily handle their 
> dependencies in the IDE of their choice.
> 
>> On 24 Oct 2017, at 13:46, Adrian Kashivskyy via swift-evolution 
>>  wrote:
>> 
>> I would like Xcode integration 😀
>> 
>> The last thing I want from a platform-agnostic open-source package manager 
>> is built-in integration with a single-platform commercial closed-source IDE. 
>> 😕
>> 
>> I think this should be done independently by DT team, without any special 
>> favouritism by SPM.
>> 
>> ——
>> Adrian Kashivskyy
>> 
>>> On 23 Oct 2017, 19:41 +0200, Jean-Christophe Pastant via swift-evolution 
>>> , wrote:
>>> Hi,
>>> 
>>> Is there any news about features that are willling to be integrated into 
>>> SPM 5?
>>> Those I see the most relevant:
>>> - iOS support
>>> - Some kind of configuration/settings support (debug, release, ...)
>>> 
>>> I'd like to hear about it from maintainers, especially if there's a 
>>> priority order we should follow.
>>> 
>>> Regards,
>>> 
>>> 
>>> ___
>>> 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
> 
> David James
> 
> ___
> 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] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Howard Lovatt via swift-evolution
+1 good idea.

Re. the naming I would suggest `mapFilterNil` since it says what it does
and filter, nil, and map are all understood already in Swift. (I have
sympathy for people wanting `mapFilteringNil`, but Swift chose `filter`.)

The problems I see with `filterMap` are that:

  1. It sounds like it is a merged `filter` and `map` and therefore you
would expect it to have two arguments, one to filter and one to map, i.e.
`filterMap(filter: (T) -> Bool, map: (T) -> R) -> [R]`.
  2. It sounds like it will filter the incoming values (for `nil`, but see
1 above) and then map, i.e. `filterMap(map: (T?) -> R) -> [R]`, note
`T?` *not* `R?`.

  -- Howard.

On 24 October 2017 at 11:56, BJ Homer via swift-evolution <
swift-evolution@swift.org> wrote:

> I agree with Xiaodi; I like ‘filterMap’ more than ‘filteredMap’. But both
> are superior to ‘flatMap’ in this context.
>
> -BJ
>
> On Oct 23, 2017, at 5:22 PM, Max Moiseev  wrote:
>
> It occurred to me that filteringMap(_:) should be even more descriptive,
> still conform to the guidelines, although similarly unprecedented and
> un-googlable.
>
> Max
>
> On Oct 23, 2017, at 3:52 PM, Xiaodi Wu  wrote:
>
> +1 in general. As to the name: since 'map' is used as a term of art,
> 'filterMap' seems superior to 'filteredMap', which half follows naming
> guidelines and half is a term of art; neither is immediately comprehensible
> but 'filterMap' can be googled and has precedents in other languages.
> On Mon, Oct 23, 2017 at 17:24 BJ Homer via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> I strongly agree! In fact, I just started writing up a similar proposal
>> the other day, but hadn’t had time to finish it yet.
>>
>> The current name for this particular filtering variant is not
>> particularly descriptive. It’s certainly not obvious to newcomers that
>> ‘flatMap’ will filter out results. And it’s not true to the existing usage
>> of ‘flatMap' from other languages; you have to really squint at it to see
>> how any “flattening” is happening at all.
>>
>> So yes, a big +1 from me. Thanks!
>>
>> -BJ Homer
>>
>> On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Hi swift-evolution!
>>
>> I would like to propose the following change to the standard library:
>>
>> deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this
>> functionality available under a new name `Sequence.filteredMap(_:)`.
>>
>> The draft is available at https://gist.github.com/moiseev/
>> 2f36376c8ef4c2b1273cff0bfd9c3b95 and is included below for your
>> convenience.
>>
>> Max
>>
>> Introduce Sequence.filteredMap(_:)
>>
>>- Proposal: SE- 
>>- Authors: Max Moiseev 
>>- Review Manager: TBD
>>- Status: Awaiting implementation
>>
>>
>> 
>> Introduction
>>
>> We propose to deprecate the controversial version of a Sequence.flatMap 
>> method
>> and provide the same functionality under a different, and potentially more
>> descriptive, name.
>>
>> 
>> Motivation
>>
>> The Swift standard library currently defines 3 distinct overloads for
>> flatMap:
>>
>> Sequence.flatMap(_: (Element) -> S) -> [S.Element]
>> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
>> U?Sequence.flatMap(_: (Element) -> U?) -> [U]
>>
>> The last one, despite being useful in certain situations, can be (and
>> often is) misused. Consider the following snippet:
>>
>> struct Person {
>>   var age: Int
>>   var name: String
>> }
>> func getAges(people: [Person]) -> [Int] {
>>   return people.flatMap { $0.age }
>> }
>>
>> What happens inside getNames is: thanks to the implicit promotion to
>> Optional, the result of the closure gets wrapped into a .some, then
>> immediately unwrapped by the implementation of flatMap, and appended to
>> the result array. All this unnecessary wrapping and unwrapping can be
>> easily avoided by just using map instead.
>>
>> func getAges(people: [Person]) -> [Int] {
>>   return people.map { $0.age }
>> }
>>
>> It gets even worse when we consider future code modifications, like the
>> one where Swift 4 introduced a Stringconformance to the Collection protocol.
>> The following code used to compile (due to the flatMap overload in
>> question).
>>
>> func getNames(people: [Person]) -> [String] {
>>   return people.flatMap { $0.name }
>> }
>>
>> But it no longer does, because now there is a better overload that does
>> not involve implicit promotion. In this particular case, the compiler error
>> would be obvious, as it would point at the same line where flatMap is
>> used. Imagine however if it was just a let names = people.flatMap { $
>> 0.name } statement, and the names variable were used elsewhere. The
>> compiler error would be misleading.
>>
>> 

Re: [swift-evolution] [SPM] Roadmap?

2017-10-23 Thread Howard Lovatt via swift-evolution
I would like Xcode integration 😀

-- Howard. 

> On 24 Oct 2017, at 4:43 am, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> I’d be happy if we’d get iOS support and submodules :)
> 
> 
> Am 23. Oktober 2017 um 19:41:37, Jean-Christophe Pastant via swift-evolution 
> (swift-evolution@swift.org) schrieb:
> 
>> Hi,
>> 
>> Is there any news about features that are willling to be integrated into SPM 
>> 5?
>> Those I see the most relevant:
>> - iOS support
>> - Some kind of configuration/settings support (debug, release, ...)
>> 
>> I'd like to hear about it from maintainers, especially if there's a priority 
>> order we should follow.
>> 
>> Regards,
>> 
>> 
>> ___
>> 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] [Draft] Rename Sequence.elementsEqual

2017-10-16 Thread Howard Lovatt via swift-evolution
My preferences in order would be:

  1. Split out of Sequence Iterable/ForEachable (whatever the name) and
have Set and Dictionary conform to this new protocol instead of Sequence.
With further protocols splits made to other 'mixin' protocols to keep the
order of iteration undefined.

  2. Rename elementsEqual, iterableOrderEqual and change the definitions of
all the order dependent methods in the 'collections' hierarchy to
explicitly say "based on iteration order" and to explicitly say that "the
method iterates over the collection to produce their result and if the
collection can only iterate once then subsequent calls will cause a fatal
error".

There is only one reason that I can see for rejecting my 1st option - it's
just too much effort. I don't accept the argument of a breaking change in
the true sense of the word breaking because algorithms over Set/Dictionary
that rely on order are broken and there explicitly cause a compile time
error for these is good. Arguing that it isn't good to deliberately break
these algorithms is like saying that if there is a bug in the compiler that
accepts faulty code we shouldn't fix it because that will break someones
code - no a bug should be flagged.

  -- Howard.

On 17 October 2017 at 10:40, Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> To expand on this, Set([1,2,3,4,5]).hasPrefix([1,2,3]) currently returns
> true.  But let’s say a year from now, we change Set to return an ordering
> based on hash values (which is entirely reasonable). Suddenly the same code
> may return true or false.
>
> No guarantees will be broken by doing that, but the result has still
> changed because we are building on top of undefined behavior. Collection
> says nothing about the ordering over different builds of a program.
>
> Thanks,
> Jon
>
> On Oct 16, 2017, at 4:11 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Oct 16, 2017, at 1:05 PM, Xiaodi Wu  wrote:
>
>
> On Mon, Oct 16, 2017 at 10:49 Jonathan Hull  wrote:
>
>>
>> On Oct 16, 2017, at 7:20 AM, Xiaodi Wu  wrote:
>>
>> To start with, the one you gave as an example at the beginning of this
>>> discussion: Two sets with identical elements which have different internal
>>> storage and thus give different orderings as sequences.  You yourself have
>>> argued that the confusion around this is enough of a problem that we need
>>> to make a source-breaking change (renaming it) to warn people that the
>>> results of the ‘elementsEqual’ algorithm are undefined for sets and
>>> dictionaries.
>>>
>>
>> No, I am arguing that the confusion about ‘elementsEqual’ is foremost a
>> problem with its name; the result of this operation is not at all undefined
>> for two sets but actually clearly defined: it returns true if two sets have
>> the same elements in the same iteration order, which is a publicly
>> observable behavior of sets (likewise dictionaries).
>>
>>
>> But that iteration order is undefined and could easily change due to
>> changes in the private/internal structure of sets/dictionaries.  Algorithms
>> that rely on that “publicly observable behavior” (i.e. leaking of
>> internals) will suddenly break.
>>
>
> And an algorithm in which such “sudden breakage” would occur is…?
>
>
> Here are a few off the top of my head:
>
> func hasPrefix(Sequence)->Bool
> func hasSuffix(Sequence)->Bool
> func containsSubsequence(Sequence)->Bool
>
> What do these methods mean with regards to Set’s “publicly observable
> behavior”?
>
>
> You keep claiming that this bug is a feature because it is the current
>> behavior… but that is tautological reasoning.
>>
>> Thanks,
>> Jon
>>
>
> ___
> 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] [Draft] Rename Sequence.elementsEqual

2017-10-13 Thread Howard Lovatt via swift-evolution
I am very glad that this issue is getting some air time since the ‘loose’ 
definitions in `Sequence` are a pain. 

I am in the camp that thinks the best solution is to split `Sequence`. I would 
propose splitting into `Iterable` and `Sequence`, `Sequence` is ordered. `Set` 
and `Dictionary` would implement `Iterable` and a `for` loop would work with 
`Iterable`. That way only already broken code is affected. 

At present we have `Set` and `Dictionary` that are problems in the standard 
library and this justifies the split. 

If other collection types are added to the standard library that require 
further sub-division of sequence then split sequence further at that time. 

-- Howard. 

> On 14 Oct 2017, at 6:41 am, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I would also expect lexicographicallyEquals to sort the elements (or 
> otherwise create/reference a total ordering) before checking for equality.  I 
> would be more surprised by the behavior of a function named this than 
> elementsEqual.
> 
> Given the name, I would expect elementsEqual to return true if two sequences 
> have the same elements, regardless of ordering (this would be a valuable 
> function IMHO).  I would expect lexicographicallyEquals to compare the 
> elements in some lexicographical order defined for the type which overrides 
> the internal ordering of the sequence.
> 
> Kevin is right… the real answer is that the actual intended function really 
> shouldn’t exist on unordered sequences.
> 
> Thanks,
> Jon
> 
>>> On Oct 13, 2017, at 10:12 AM, Kevin Nattinger via swift-evolution 
>>>  wrote:
>>> 
>>> 
 On Oct 13, 2017, at 10:01 AM, Michael Ilseman  wrote:
 
 
 
 On Oct 12, 2017, at 9:57 PM, Kevin Nattinger via swift-evolution 
  wrote:
 
 –∞
 
 1. I strongly object to the proposed name. It doesn't make it more clear 
 to me what the method does, and is misleading at best. Among other issues, 
 "lexicographical" is defined as alphabet order, and (1) this method 
 applies to objects that are not Strings, and (2) this method's behavior 
 isn't any more well-defined for Strings, so that name is even more of a 
 lie than the original.
 
>>> 
>>> FWIW, in the context of String, "lexicographical ordering” does not imply 
>>> human-written-language-alphabetical order at all, as there’s no universal 
>>> alphabetical ordering for human language. I.e., such a concrete notion for 
>>> Strings does not exist, not even theoretically. “Lexicographical” derives 
>>> its meaning from the mathematical usage[1] which uses that term as well as 
>>> “alphabet” without being restricted to human-written-language, in which it 
>>> means some total ordering over a finite set.
>>> 
>>> [1] https://en.wikipedia.org/wiki/Lexicographical_order
>> 
>> I see, apologies for the mistake. 
>> Regardless of the specific type of ordering, lexicographicallyEquals says to 
>> me that the objects should be sorted into lexicographical order and 
>> compared. Precisely the opposite of the proposal.
>> 
>>> 
 2. This is really just a symptom of a bigger problem. The fact that two 
 Sets can compare equal and yet return different results for that method 
 (among too many others) is logically inconsistent and points to a much 
 deeper issue with Set and Sequence. It is probably about 3 releases too 
 late to get this straightened out properly, but I'll outline the real 
 issue in case someone has an idea for fixing it.
 
 The root of the problem is that Set conforms to Sequence, but Sequence 
 doesn't require a well-defined order. Since Set doesn't have a 
 well-defined order, a significant portion of its interface is unspecified. 
 The methods are implemented because they have to be, but they doesn't have 
 well-defined or necessarily consistent results.
 
 A sequence is, by definition, ordered. That is reflected in the fact that 
 over half the methods in the main Sequence definition* make no sense and 
 are not well-defined unless there is a well-defined order to the sequence 
 itself. What does it even mean to `dropFirst()` in a Set? The fact that 
 two objects that compare equal can give different results for a 100% 
 deterministic function is illogical, nonsensical, and dangerous.
 
 * 7/12 by my count, ignoring `_*` funcs but including the `var`
 
 The current contents of Sequence can be cleanly divided into two groups; 
 those that return SubSequence imply a specific ordering, and the rest do 
 not.
 
  I think those should be/should have been two separate protocols:
 
 public protocol Iterable {
   associatedtype Iterator: IteratorProtocol
   func map(...) -> [T] // Iterable where .Iterator.Element == T
   func filter(...) -> [Iterator.Element] // Iterable where 
 .Iterator.Element == Self.Iterator.Element
   func forEach(...)
   func makeIterator() -> Iterato

Re: [swift-evolution] /*Let it be*/ func() -> @discardable Bool {} /*Rather Than*/ @discardableResult func() -> Bool {}

2017-10-09 Thread Howard Lovatt via swift-evolution
Personally I would prefer all the modified to go on the right, so that the 
declaration is sorted from most important to least left to right. EG:

Instead of:

@disguardableResult public async mutating func x() throws -> Bool

I would prefer something like:

func x() -> Bool @ throws disguardableResult public async mutating

Where @ introduces a list of space separated modifiers. 

That’s why I also prefer:

   let x: Int // Swift

over:

   const int x // C

And moving the where clause to the end of the declaration. 

Unfortunately I am not sure this is practical at this stage. 

-- Howard. 

> On 10 Oct 2017, at 5:21 am, Mike Kluev via swift-evolution 
>  wrote:
> 
>> On Sat, 7 Oct 2017 07:48:08 +0100,  wrote:
>> So it would be:
>> 
>> func() -> @discardable Bool { }
>> 
>> Rather than:
>> 
>> @discardableResult func() -> Bool { }
> 
> 
> i'd say:
> 
> func foo() -> discardable Bool {
> ...
> }
> 
> if we were starting from scratch
> 
>> It could be even better if someone could perhaps find a shorter word that
>> is a synonym for the word "discardable", that would be as explicit in
>> intent as the word "discardable" is in such context, yet be written with
>> fewer characters.
> 
>  Mike
> 
> ___
> 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] Standard ReactiveSteam definitions for Swift

2017-09-26 Thread Howard Lovatt via swift-evolution
You wouldn’t normally use Reactive Streams directly, think of them as the
Babel Fish (hitch hikers) of Streams/actors. If Swift actors talked
Reactive Stream and so did some other library, Akka, RxSwift, etc., then
the two could talk to each other. Which would be a big advantage on large
projects with multiple code bases.

On Mon, 25 Sep 2017 at 8:38 am, Benjamin Garrigues via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> > Le 24 sept. 2017 à 21:15, Marc Schlichte via swift-evolution <
> swift-evolution@swift.org> a écrit :
> >
> > I hope we come up with some genuine ideas for ReactiveStreams on Swift.
> >
> > For example instead of onNext()/onError() we could have a single method
> which takes a Result Monad. ARC memory management might require Swift
> specific solutions too.
> >
> > Also on the mindset: Often I see my Android colleagues using Observables
> to wait for the completion of asynchronous requests. But I think these
> control flow scenarios are better handled by async/await instead.
> >
> > Reactive should be used when a component (class / actor) wants to make
> an unsolicited 'upcall'. As such it is firstly a modern variant of
> KVO/NotificatonCenter/Delegates/target-action etc. with the additional
> ability to transform / combine / schedule signals on the way from the
> signal producers to the signal consumers (signal stream processing).
> >
> > As KVO/Delegates probably won't work correctly for Actors (because of
> execution context discrepancy), a reactive replacement working well with
> Actors is definitely needed.
>
> i only had a little bit of rx experience but this one made me curious :
> why would reactive programming be a requirement for "one to one, at most
> once , best effort message delivery" between actors ? ( which iirc should
> be the only guarantee for actor to actor communication).
> Rx is a very broad and generic abstraction for asynchronous
> communications, which brings its own share of novel issues ( at least
> judging by my personnal experience and the horror stories of people around
> me), whereas actors aim at being the most simple and straightforward way to
> handle concurrency and state, by acknowledging where the states should live
> and mutate and which shortcomings in the communication between actors have
> to be expected.
>
>
>
>
>
> >
> > It would be great if a Swift reactive library would allow us to  design
> ViewModels (cf MVVM) as Actors and support 2 way bindings to the UI.
> >
> > Cheers
> > Marc
> >
> >
> >
> >  Ursprüngliche Nachricht
> > Von: swift-evolution@swift.org
> > Gesendet: 24. September 2017 4:36 vorm.
> > An: swift-evolution@swift.org
> > Antworten: mat...@gmail.com
> > Betreff: Re: [swift-evolution] Standard ReactiveSteam definitions for
> Swift
> >
> > Some thoughts as a programmer who has written an atypical reactive
> programming library...
> >
> > You're providing protocols that strongly imply ReactiveX semantics.
> >
> > Some libraries (like my own CwlSignal) look a little like ReactiveX (in
> that CwlSignal implements all of the ReactiveX operators) but have some
> quite different semantics during graph construction and during other
> lifecycle events. For example, CwlSignal doesn't have public Subscriber
> concept (responsibilities are split between the private `SignalHandler` and
> the `SignalSender` interface) and while the core `Signal` class is a
> Publisher-like concept, it is single-use which would make it a very weird
> implementation of this `Publisher` protocol.
> >
> > These differences can make protocols for interoperability a bit of a
> loaded shotgun. Joining two arbitrary libraries together is likely to cause
> problems when the libraries have different expectations.
> >
> > In some respects, it would be better to have a single, standard,
> concrete implementation of a class that takes an event stream input and
> emits an event stream. This is sometimes called a PublishSubject. A
> generalized PublishSubject could act as the glue between different
> libraries on the input and output sides. That way, the semantics of the
> interoperability point are fixed and each library need only ensure they
> support the interoperability point, rather than the semantics of every
> other library that could be on the other side of a protocol.
> >
> > To me, I feel like this would best be implemented as part of Actor model
> concurrency – taking inputs and emitting outputs is fundamentally what
> Actors *do*.
> >
> > As for naming... I would *not* recommend using `Flow` it is far too
> generic, has been used in very different contexts and doesn't match
> terminology in the field. It's fine for a library to break with common
> terminology for its own purposes but an interoperability interface must use
> the established terminology. `Publisher` and `Subscriber` are fairly clear
> in context but can mean very different things *outside* of reactive
> programming. `Observable` and `Observer` are clearer but again, the
> `Observer` 

Re: [swift-evolution] Standard ReactiveSteam definitions for Swift

2017-09-26 Thread Howard Lovatt via swift-evolution
Nothing to stop you having Observables linked to a Reactive Stream library,
the RxJava 2 library has Observables and is built on top of Reactive
Streams.

On Mon, 25 Sep 2017 at 5:15 am, Marc Schlichte via swift-evolution <
swift-evolution@swift.org> wrote:

> I hope we come up with some genuine ideas for ReactiveStreams on Swift.
>
> For example instead of onNext()/onError() we could have a single method
> which takes a Result Monad. ARC memory management might require Swift
> specific solutions too.
>
> Also on the mindset: Often I see my Android colleagues using Observables
> to wait for the completion of asynchronous requests. But I think these
> control flow scenarios are better handled by async/await instead.
>
> Reactive should be used when a component (class / actor) wants to make an
> unsolicited 'upcall'. As such it is firstly a modern variant of
> KVO/NotificatonCenter/Delegates/target-action etc. with the additional
> ability to transform / combine / schedule signals on the way from the
> signal producers to the signal consumers (signal stream processing).
>
> As KVO/Delegates probably won't work correctly for Actors (because of
> execution context discrepancy), a reactive replacement working well with
> Actors is definitely needed.
>
> It would be great if a Swift reactive library would allow us to  design
> ViewModels (cf MVVM) as Actors and support 2 way bindings to the UI.
>
> Cheers
> Marc
>
>
>
>   Ursprüngliche Nachricht
> Von: swift-evolution@swift.org
> Gesendet: 24. September 2017 4:36 vorm.
> An: swift-evolution@swift.org
> Antworten: mat...@gmail.com
> Betreff: Re: [swift-evolution] Standard ReactiveSteam definitions for Swift
>
> Some thoughts as a programmer who has written an atypical reactive
> programming library...
>
> You're providing protocols that strongly imply ReactiveX semantics.
>
> Some libraries (like my own CwlSignal) look a little like ReactiveX (in
> that CwlSignal implements all of the ReactiveX operators) but have some
> quite different semantics during graph construction and during other
> lifecycle events. For example, CwlSignal doesn't have public Subscriber
> concept (responsibilities are split between the private `SignalHandler` and
> the `SignalSender` interface) and while the core `Signal` class is a
> Publisher-like concept, it is single-use which would make it a very weird
> implementation of this `Publisher` protocol.
>
> These differences can make protocols for interoperability a bit of a
> loaded shotgun. Joining two arbitrary libraries together is likely to cause
> problems when the libraries have different expectations.
>
> In some respects, it would be better to have a single, standard, concrete
> implementation of a class that takes an event stream input and emits an
> event stream. This is sometimes called a PublishSubject. A generalized
> PublishSubject could act as the glue between different libraries on the
> input and output sides. That way, the semantics of the interoperability
> point are fixed and each library need only ensure they support the
> interoperability point, rather than the semantics of every other library
> that could be on the other side of a protocol.
>
> To me, I feel like this would best be implemented as part of Actor model
> concurrency – taking inputs and emitting outputs is fundamentally what
> Actors *do*.
>
> As for naming... I would *not* recommend using `Flow` it is far too
> generic, has been used in very different contexts and doesn't match
> terminology in the field. It's fine for a library to break with common
> terminology for its own purposes but an interoperability interface must use
> the established terminology. `Publisher` and `Subscriber` are fairly clear
> in context but can mean very different things *outside* of reactive
> programming. `Observable` and `Observer` are clearer but again, the
> `Observer` pattern in general programming is not the same as a reactive
> programming `Observer` so putting it in the Swift standard library would
> annoy some people. On an aesthetic note, I've always found `Observer` and
> `Observable` difficult to read – they are similar enough that I confuse
> inputs and outputs when I'm tired. This is one of the reasons these terms
> do not appear in my library.
>
> My personal vote is that this topic simply can't be addressed by the
> standard library at this point. This is something where interoperability
> with Swift's Actor Model should be a primary concern and until it's done,
> any action now is only likely to be a headache later.
>
> Cheers,
> Matt Gallagher.
> ___
> 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
>
-- 
-- Howard.
___
swift-evolution m

Re: [swift-evolution] Standard ReactiveSteam definitions for Swift

2017-09-26 Thread Howard Lovatt via swift-evolution
Comments in-line below.


On Sun, 24 Sep 2017 at 12:36 pm, Matt Gallagher via swift-evolution <
swift-evolution@swift.org> wrote:

> Some thoughts as a programmer who has written an atypical reactive
> programming library...
>
> You're providing protocols that strongly imply ReactiveX semantics.


ReactiveX can be built upon Reactive Streams, e.g. RxJava 2.0., but the
idea of Reactive Streams is that the protocol is so low level you don’t
interact directly with them. They seem compatible with many different
styles including actors, e.g. Akka (the Akka people destined Reactive
Streams I think). Reactive Streams are very actor like with one way
communication links that transfer a copy of single items/errors or no
items/error (pure messages).


> Some libraries (like my own CwlSignal) look a little like ReactiveX (in
> that CwlSignal implements all of the ReactiveX operators) but have some
> quite different semantics during graph construction and during other
> lifecycle events. For example, CwlSignal doesn't have public Subscriber
> concept (responsibilities are split between the private `SignalHandler` and
> the `SignalSender` interface) and while the core `Signal` class is a
> Publisher-like concept, it is single-use which would make it a very weird
> implementation of this `Publisher` protocol.


Nothing in the Reactive Stream specification to prevent single use
Publishers, Subscribers, or Processors. The Reactive Stream specification
only talks about the communication and error reporting. As long as your
library has the concept of a subscription of some form you can probably
write translators to the 3 protocols.


> These differences can make protocols for interoperability a bit of a
> loaded shotgun. Joining two arbitrary libraries together is likely to cause
> problems when the libraries have different expectations.


Seems to work OK in the Java world, people use Akka and RxJava together.


> In some respects, it would be better to have a single, standard, concrete
> implementation of a class that takes an event stream input and emits an
> event stream. This is sometimes called a PublishSubject. A generalized
> PublishSubject could act as the glue between different libraries on the
> input and output sides. That way, the semantics of the interoperability
> point are fixed and each library need only ensure they support the
> interoperability point, rather than the semantics of every other library
> that could be on the other side of a protocol.


This is what Reactive Streams are. They just tell you how to hook things
up, how to ask for items, how to report errors, and how to finish with a
connection. They do not dictate the semantics at the other end. For example
your translator could throw fatal exception on an error if your library
didn’t report errors or wrap the error in a Result type if it handled error
in a functional way.


> To me, I feel like this would best be implemented as part of Actor model
> concurrency – taking inputs and emitting outputs is fundamentally what
> Actors *do*.


As I have said they are very actor like and I think it was the Akka people
who came up with the specification therefore I am not sure you are locking
anything out. If the Swift actor model can’t interact with something as
simple as Reactive Streams it will not interact with anything other than
other Swift Actors, which would be very limiting. For example you would
expect the Swift actors to interact with GCD, perhaps via suitable
wrappers.


> As for naming... I would *not* recommend using `Flow` it is far too
> generic, has been used in very different contexts and doesn't match
> terminology in the field. It's fine for a library to break with common
> terminology for its own purposes but an interoperability interface must use
> the established terminology. `Publisher` and `Subscriber` are fairly clear
> in context but can mean very different things *outside* of reactive
> programming. `Observable` and `Observer` are clearer but again, the
> `Observer` pattern in general programming is not the same as a reactive
> programming `Observer` so putting it in the Swift standard library would
> annoy some people. On an aesthetic note, I've always found `Observer` and
> `Observable` difficult to read – they are similar enough that I confuse
> inputs and outputs when I'm tired. This is one of the reasons these terms
> do not appear in my library.
>
> My personal vote is that this topic simply can't be addressed by the
> standard library at this point. This is something where interoperability
> with Swift's Actor Model should be a primary concern and until it's done,
> any action now is only likely to be a headache later.


I would prefer to move forward more quickly, I don’t think there is much
risk since the specification is so low level and flexible. The whitpaper
from Chris Lattner also mentions that it would be desirable for any Actor
system in Swift to be compatible with Reactive Streams, so why not start
now.


>
> 

Re: [swift-evolution] Standard ReactiveSteam definitions for Swift

2017-09-25 Thread Howard Lovatt via swift-evolution
Not quite understanding your concern, perhaps you could elaborate. In
particular:

  1. The names I proposed were on(next:) and on(error:) so there is no
confusion since next and error are still part of the name. I just moved
them inside the brackets like commonly done in Swift.

  2. Neither on(next:) nor on(error:) accept a closure, they take values.

  3. You don’t manually call either on(next:) or on(error:), the only
method you interact with is subscribe. Which in my library I have
overloaded with ~~> so that you don’t call methods at all on reactive
stream objects. See README for
https://github.com/hlovatt/Concurrency-Utilities.

Hello World using this library is:

let helloWorldPublisher = ForEachPublisher(sequence: "Hello, world!".characters)
let helloWorldSubscriber = ReduceSubscriberFuture(into: "") { (result:
inout String, next: Character) in
result.append(next)
}
var helloWorldResult = "Failed!" // Default value for failure, timeout, etc.
helloWorldPublisher ~~> helloWorldSubscriber ~~>? helloWorldResult

Note how the arguments to ForEachProducer and ReduceSubscriberFuture mimic
those to similarly named methods in Swifts Sequence protocol, how Subscriber
's ~~> is evocative of the process that is occurring, and how Future's
~~>? looks
natural and controls execution and error reporting. Fire is another part of
the library, see readme.



On Sun, 24 Sep 2017 at 12:25 am, Dave DeLong via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Sep 23, 2017, at 1:24 AM, Georgios Moschovitis via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Copied from the corresponding Github issue, I would like to hear opinions
> from the broader community on this:
>
> I am wondering if the correct 'translation' to Swift of:
>
> ```
> onNext()
> onError()
> ```
>
> is really:
>
> ```
> on(next:)
> on(error:)
> ```
>
>
> I’ve played around with reactive streams, and one of the main issues with
> this naming convention is that it really confuses the compiler when you try
> to use trailing closure syntax:
>
> aStream.on { nextOrError in
>
> }
>
> The compiler has a really hard time inferring what the type of nextOrError
> is without explicitly typing the parameter or not using trailing closure
> syntax.
>
> Using .onNext { … } or .onError { … } bypasses this problem entirely.
>
> Dave
>
>
> maybe something closer to Foundation's naming conventions would be:
>
> ```
> didReceive(next:) or didReceive(value:)
> didReceive(error:)
> ```
>
> -g.
>
> ___
> 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
>
-- 
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Standard ReactiveSteam definitions for Swift

2017-09-25 Thread Howard Lovatt via swift-evolution
I stuck with the standard names that other languages use. In Java they
enclosed the standard protocol/interface names Process, Publisher,
Subscriber, along with a useful constant inside a namespace Flow, so you
say Flow.Publisher for example.

The same could be done for Swift, it is a matter for the Swift community to
decide.

You could also change the names of the protocols, but that would make
standard documents and code from other languages hard to follow.

On Fri, 22 Sep 2017 at 3:11 am, Georgios Moschovitis <
george.moschovi...@icloud.com> wrote:

> +1
>
> Btw, I kinda like the `Flow` name (or even `Observable`). Don’t like
> `ReactiveStream` at all.
>
> -g.
>
> On 19 Sep 2017, at 3:59 AM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> http://www.reactive-streams.org/
>
>
> --
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0176: Remove ownership keyword support in protocols

2017-09-20 Thread Howard Lovatt via swift-evolution
> review of “SE-0186: Remove ownership keyword support in protocols”

> * What is your evaluation of the proposal?

+1, sensible to remove misleading definitions
> 
> * Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes, could easily lead to bugs. 
> 
> * Does this proposal fit well with the feel and direction of Swift?

Yes, cleaning up Swift is part of the evolution 
> 
> * If you have used other languages or libraries with a similar feature, how 
> do you feel that this proposal compares to those?

No
> 
> * How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?

Quick read. 

-- Howard. 

> On 21 Sep 2017, at 6:11 am, Ted Kremenek  wrote:
> 
> The review of “SE-0186: Remove ownership keyword support in protocols” begins 
> now and runs through September 27.
> 
> The proposal is available here:
> 
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0186-remove-ownership-keyword-support-in-protocols.md
> 
> Reviews are an important part of the Swift evolution process. All review 
> feedback 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/0186-remove-ownership-keyword-support-in-protocols.md
>>  ….
>>  Reply text
>>  ...
>>  Other replies
> 
> 
> ## What goes into a review of a proposal?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift. 
> 
> When reviewing a proposal, here are some questions to consider:
> 
> * 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?
> 
> 
> Thanks,
> Ted Kremenek
> Review Manager
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] Standard ReactiveSteam definitions for Swift

2017-09-18 Thread Howard Lovatt via swift-evolution
In Java 9 they have added standard definitions for Reactive Streams, the
`Flow` class, so that third party libraries, like Akka, can interoperate.
Note they haven't added an implementation of Reactive Streams, just the
type definitions.

A starting point for adding similar to Swift could be:


https://github.com/hlovatt/Concurrency-Utilities/blob/master/Concurrency%20Utilities/ReactiveStream.swift

This would be the Swift equivalent of the Java Flow class in that it
provides definitions but not implementations, which will enable third party
libraries and eventually whatever goes into Swift at language and library
levels to interoperate.

Whereas adding concurrency in general will be a long process, these
definitions could be added now.

Thoughts?

  -- Howard.

PS You can find out about Reactive Steams and the standardization of them
at http://www.reactive-streams.org/
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] async/await + actors

2017-09-10 Thread Howard Lovatt via swift-evolution
Not really certain what async/await adds, using this library (note self
promotion) which is built on top of GCD:

https://github.com/hlovatt/Concurrency-Utilities


You can write:

func doit() {
AsynchronousFuture { // Executes in background and therefore does
not block main
let dataResource  = loadWebResource("dataprofile.txt") //
Returns a future and therefore runs concurrently in background.
let imageResource = loadWebResource("imagedata.dat") // Future
therefore concurrent.
let imageTmp  = decodeImage(dataResource.get ??
defaultText, imageResource.get ?? defaultData) // Handles errors with
defaults easily, including timeout.
let imageResult   = dewarpAndCleanupImage(imageTmp)

Thread.executeOnMain {
self.imageResult = imageResult
}
}
}

So why bother with async/await?

PS I also agree with the comments that there is no point writing the 1st
two lines of the example with async and then calling them with await - you
might as well write serial code.

  -- Howard.

On 10 September 2017 at 10:33, Wallacy via swift-evolution <
swift-evolution@swift.org> wrote:

> This is the only part of the proposal that i can't concur!
>
> ^async^ at call side solve this nicely! And Pierre also showed how common
> people are doing it wrong! And will make this wrong using Futures too.
>
> func doit() async {
> let dataResource = async loadWebResource("dataprofile.txt”)
> let imageResource = async loadWebResource("imagedata.dat”)
> let imageTmp = await decodeImage(dataResource, imageResource)
> self.imageResult = await dewarpAndCleanupImage(imageTmp)
> }
>
> Anyway, we have time to think about it.
>
>
>
> Em sáb, 9 de set de 2017 às 20:30, David Hart via swift-evolution <
> swift-evolution@swift.org> escreveu:
>
>> On 10 Sep 2017, at 00:40, Kenny Leung via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Then isn’t the example functionally equivalent to:
>>
>> func doit() {
>> DispatchQueue.global().async {
>> let dataResource  = loadWebResource("dataprofile.txt")
>> let imageResource = loadWebResource("imagedata.dat")
>> let imageTmp  = decodeImage(dataResource, imageResource)
>> let imageResult   = dewarpAndCleanupImage(imageTmp)
>> DispatchQueue.main.async {
>> self.imageResult = imageResult
>> }
>> }
>> }
>>
>> if all of the API were synchronous? Why wouldn’t we just exhort people to
>> write synchronous API code and continue using libdispatch? What am I
>> missing?
>>
>>
>> There are probably very good optimisations for going asynchronous, but
>> I’m not the right person for that part of the answer.
>>
>> But I can give another answer: once we have an async/await pattern, we
>> can build Futures/Promises on top of them and then we can await on multiple
>> asynchronous calls in parallel. But it won’t be a feature of async/await in
>> itself:
>>
>> func doit() async {
>> let dataResource  = Future({ loadWebResource("dataprofile.txt”) })
>> let imageResource = Future({ loadWebResource("imagedata.dat”) })
>> let imageTmp = await decodeImage(dataResource.get, imageResource.get)
>> self.imageResult = await dewarpAndCleanupImage(imageTmp)
>> }
>>
>> -Kenny
>>
>>
>> On Sep 8, 2017, at 2:33 PM, David Hart  wrote:
>>
>>
>> On 8 Sep 2017, at 20:34, Kenny Leung via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Hi All.
>>
>> A point of clarification in this example:
>>
>> func loadWebResource(_ path: String) async -> Resourcefunc decodeImage(_ r1: 
>> Resource, _ r2: Resource) async -> Imagefunc dewarpAndCleanupImage(_ i : 
>> Image) async -> Image
>> func processImageData1() async -> Image {
>> let dataResource  = await loadWebResource("dataprofile.txt")
>> let imageResource = await loadWebResource("imagedata.dat")
>> let imageTmp  = await decodeImage(dataResource, imageResource)
>> let imageResult   = await dewarpAndCleanupImage(imageTmp)
>> return imageResult
>> }
>>
>>
>> Do these:
>>
>> await loadWebResource("dataprofile.txt")
>>
>> await loadWebResource("imagedata.dat")
>>
>>
>> happen in in parallel?
>>
>>
>> They don’t happen in parallel.
>>
>> If so, how can I make the second one wait on the first one? If not, how
>> can I make them go in parallel?
>>
>> Thanks!
>>
>> -Kenny
>>
>> ___
>> 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] [Concurrency] async/await + actors

2017-09-07 Thread Howard Lovatt via swift-evolution
I would argue that given:

foo()
await bar()
baz()

That foo and baz should run on the same queue (using queue in the GCD
sense) but bar should determine which queue it runs on. I say this because:

   1. foo and baz are running synchronously with respect to each other
   (though they could be running asynchronously with respect to some other
   process if all the lines shown are inside an async function).
   2. bar is running asynchronously relative to foo and baz, potentially on
   a different queue.

I say bar is potentially on a different queue because the user of bar, the
person who wrote these 3 lines above, cannot be presumed to be the writer
of foo, baz, and particularly not bar and therefore have no detailed
knowledge about which queue is appropriate.

Therefore I would suggest either using a Future or expanding async so that
you can say:

func bar() async(qos: .userInitiated) { ... }

You also probably need the ability to specify a timeout and queue type,
e.g.:

   func bar() async(type: .serial, qos: .utility, timeout: .seconds(10))
throws { ... }

If a timeout is specified then await would have to throw to enable the
timeout, i.e. call would become:

   try await bar()

Defaults could be provided for qos (.default works well), timeout (1 second
works well), and type (.concurrent works well).

However a Future does all this already :).

  -- Howard.

On 7 September 2017 at 15:13, David Hart via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> > On 7 Sep 2017, at 07:05, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> >
> >> On Sep 5, 2017, at 7:31 PM, Eagle Offshore via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> OK, I've been watching this thing for a couple weeks.
> >>
> >> I've done a lot of GCD network code.  Invariably my completion method
> starts with
> >>
> >> dispatch_async(queue_want_to_handle_this_on,)
> >>
> >> Replying on the same queue would be nice I guess, only often all I need
> to do is update the UI in the completion code.
> >>
> >> OTOH, I have situations where the reply is complicated and I need to
> persist a lot of data, then update the UI.
> >>
> >> So honestly, any assumption you make about how this is supposed to work
> is going to be wrong about half the time unless
> >>
> >> you let me specify the reply queue directly.
> >>
> >> That is the only thing that works all the time.  Even then, I'm very
> apt to make the choice to do some of the work off the main thread and then
> queue up the minimal amount of work onto the main thread.
> >
> > I (think that I) understand what you’re saying here, but I don’t think
> that we’re talking about the same thing.
> >
> > You seem to be making an argument about what is most *useful* (being
> able to vector a completion handler to a specific queue), but I’m
> personally concerned about what is most *surprising* and therefore
> unnatural and prone to introduce bugs and misunderstandings by people who
> haven’t written the code.  To make this more concrete, shift from the
> “person who writes to code” to the “person who has to maintain someone
> else's code”:
> >
> > Imagine you are maintaining a large codebase, and you come across this
> (intentionally abstract) code:
> >
> >foo()
> >await bar()
> >baz()
> >
> > Regardless of what is the most useful, I’d argue that it is only natural
> to expect baz() to run on the same queue/thread/execution-context as foo
> and bar.  If, in the same model, you see something like:
> >
> >foo()
> >await bar()
> >anotherQueue.async {
> >baz()
> >}
>
> Couldn’t it end up being:
>
> foo()
> await bar()
> await anotherQueue.async()
> // on another queue
>
> > Then it is super clear what is going on: an intentional queue hop from
> whatever foo/bar are run on to anotherQueue.
> >
> > I interpret your email as arguing for something like this:
> >
> >foo()
> >await(anotherQueue) bar()
> >baz()
> >
> > I’m not sure if that’s exactly the syntax you’re arguing for, but
> anything like this presents a number of challenges:
> >
> > 1) it is “just sugar” over the basic model, so we could argue to add it
> at any time (and would argue strongly to defer it out of this round of
> discussions).
> >
> > 2) We’d have to find a syntax that implies that baz() runs on
> anotherQueue, but bar() runs on the existing queue.  The syntax I sketched
> above does NOT provide this indication.
> >
> > -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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swi

Re: [swift-evolution] [Concurrency] Reactive streams as building blocks for actors etc.

2017-09-06 Thread Howard Lovatt via swift-evolution
I have put on Github three concurrency libraries (
https://github.com/hlovatt/Concurrency-Utilities):

  1. Atomic - with `get`, `set`, and `update` methods
  2. Future - with `get`, `cancel`, and `status` methods
  3. Reactive Streams - with protocols `Processor`, `Producer`,
`Subscriber`, and `Subscription`, with implementations of `ForEachProducer`
and `ReduceSubscriber`, and with operator `~>` for subscriptions

For those not familiar, Reactive Streams are a standardised form of a type
of actor that have become popular and are available in multiple languages.

Here is Hello World in the Reactive Stream library:

let helloWorldPublisher = ForEachPublisher(sequence: "Hello,
world!".characters)
let helloWorldSubscriber = ReduceSubscriber(into: "") { (result: inout
String, next: Character) in
result.append(next) // Copy the string a character at a time.
}
helloWorldPublisher ~> helloWorldSubscriber // Subscribe
let helloWorldResult = helloWorldSubscriber.get ?? "Failed!" // Wait
for result and check for error

Note how the arguments to `ForEachProducer` and `ReduceSubscriber` mimic
those to similarly named methods in Swifts `Sequence` protocol, how `~>` is
evocative of the process that is occurring, and how future's `get` controls
execution and error reporting.

If anyone experiments with them and provide feedback :), it would be
greatly appreciated.

Thanks,

 -- Howard.

  -- Howard.

On 3 September 2017 at 17:36, Georgios Moschovitis <
george.moschovi...@icloud.com> wrote:

> That would be definitely a great addition to the language. IMO, Dart gets
> this right:
>
> https://www.dartlang.org/tutorials/language/futures
> https://www.dartlang.org/tutorials/language/streams
>
> In general, I would prefer an async story like this:
>
> - support coroutines / generators (yield)
> - use coroutines to implement Future and Stream/Observable
> - optionally provide async/await as syntax sugar for Future/Stream (or
> just reuse yield)
>
> -g.
>
> On 29 Aug 2017, at 4:56 AM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Many of the currently popular server side frameworks are switching to
> Reactive Streams:
>
> http://en.wikipedia.org/wiki/Reactive_Streams#Adoption
>
> for their underlying communication, including Akka. Reactive Streams are
> also to become builtin to Java, as the Flow class, in version 9.
>
> Would it be wise if Swift 5 also builtin Reactive Stream protocols and
> built its Actor implementation etc. on top of this protocol?
>
>   -- Howard.
>
> More info on Reactive streams:
>
> https://github.com/reactive-streams/reactive-streams-jvm/
> blob/v1.0.1/README.md#specification
>
> http://bryangilbert.com/post/code/scala/akka-reactive-streams/
>
>
> ___
> 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] Contextualizing async coroutines

2017-09-01 Thread Howard Lovatt via swift-evolution
I think you are raising very important concerns. As the proposal stood I was 
concerned that it would lead people to write poor quality code, in particular 
hard to debug deadlock prone code. 

I see the proposal as it stands as exposing the equivalent of a pointer in 
concurrent programming and everyone using it like they do in C with disastrous 
consequences; because it is built in and therefore considered, naively, to be 
the ‘proper’ way to do it. I think that Swift gets it right with UnsafePointer 
etc., perhaps we also need UnsafeAsync etc. to remind people they are playing 
with fire. 

I would also add into the mix:

  1. Timeouts, since these are required to break deadlocks or at least detect 
them.
  2. Cancel; users change there mind.

Glad the proposal is been expanded. 

-- Howard.

> On 1 Sep 2017, at 12:50 pm, Pierre Habouzit via swift-evolution 
>  wrote:
> 
>> On Aug 31, 2017, at 11:35 AM, Joe Groff via swift-evolution 
>>  wrote:
>> 
>> The coroutine proposal as it stands essentially exposes raw delimited 
>> continuations. While this is a flexible and expressive feature in the 
>> abstract, for the concrete purpose of representing asynchronous coroutines, 
>> it provides weak user-level guarantees about where their code might be 
>> running after being resumed from suspension, and puts a lot of pressure on 
>> APIs to be well-behaved in this respect. And if we're building toward 
>> actors, where async actor methods should be guaranteed to run "in the 
>> actor", I think we'll *need* something more than the bare-bones delimited 
>> continuation approach to get there. I think the proposal's desire to keep 
>> coroutines independent of a specific runtime model is a good idea, but I 
>> also think there are a couple possible modifications we could add to the 
>> design to make it easier to reason about what context things run in for any 
>> runtime model that benefits from async/await:
>> 
>> # Coroutine context
>> 
>> Associating a context value with a coroutine would let us thread useful 
>> information through the execution of the coroutine. This is particularly 
>> useful for GCD, so you could attach a queue, QoS, and other attributes to 
>> the coroutine, since these aren't reliably available from the global 
>> environment. It could be a performance improvement even for things like 
>> per-pthread queues, since coroutine context should be cheaper to access than 
>> pthread_self. 
> 
>> [...]
> 
> 
> YES!
> 
> We need that. You're very focused on performance and affinity and whatnot 
> here, but knowing where the completion will run upfront is critical for 
> priority inheritance purposes.
> 
> This is exactly the spirit of the mail I just wrote in reply to Chris a bit 
> earlier tonight. Execution context matters to the OS, a lot.
> 
> The OS needs to know two things:
> - where is the precursor of this coroutine (which work is preventing the 
> coroutine to execute)
> - where will the coroutine go (which for GCD is critical because the OS 
> lazily attributes threads, so any typical OS primitive to raise an existing 
> thread priority doesn't work)
> 
> In other words, a coroutine needs:
> - various tags (QoS, logging context, ...)
> - precursors / reverse dependencies
> - where it will execute (whether it's a dispatch queue or a runloop is 
> completely irrelevant though).
> 
> 
> And then if you do it that way when the precursor fires and allows for your 
> coroutine to be scheduled, then it can actually schedule it right away on the 
> right execution context and minimize context switches (which are way worse 
> than shared mutable state for your performance).
> 
> 
>> # `onResume` hooks
>> 
>> Relying on coroutine context alone still leaves responsibility wholly on 
>> suspending APIs to pay attention to the coroutine context and schedule the 
>> continuation correctly. You'd still have the expression problem when 
>> coroutine-spawning APIs from one framework interact with suspending APIs 
>> from another framework that doesn't understand the spawning framework's 
>> desired scheduling policy. We could provide some defense against this by 
>> letting the coroutine control its own resumption with an "onResume" hook, 
>> which would run when a suspended continuation is invoked instead of 
>> immediately resuming the coroutine. That would let the coroutine-aware 
>> dispatch_async example from above do something like this, to ensure the 
>> continuation always ends up back on the correct queue:
>> 
>> extension DispatchQueue {
>> func `async`(_ body: () async -> ()) {
>>   dispatch_async(self, {
>> beginAsync(
>>   context: self,
>>   body: { await body() },
>>   onResume: { continuation in
>> // Defensively hop to the right queue
>> dispatch_async(self, continuation)
>>   }
>> )
>>   })
>> }
>> }
>> 
>> This would let spawning APIs provide a stronger guarantee that the spawned 
>> coroutine is always executing as if scheduled by a specific 
>

Re: [swift-evolution] Beyond Typewriter-Styled Code in Swift, Adoption of Symbols

2017-09-01 Thread Howard Lovatt via swift-evolution
I use Mathematica, which under the covers is very Lisp like, though with names 
outside the brackets, comma separators, and square brackets. EG `a + b` is 
really:

Add[a, b]

The editor however supports all sorts of input formats including the above two 
and renders in full mathematical glory, e.g.:

Integrate[a Sin[:theta:], {:theta:, 0, :pi:}]

The above displays, could be entered with, and can be edited with full integral 
sign with limits, Greek, etc. Note how space (between a and Sin) is a shortcut 
for * in Mathematica. Also you don’t enter spaces (other than multiply) or 
layout text, the editor does those (though you can override) in a word 
processor style dynamic layout. Different fonts are extensively used and 
comments contain rich text and images and diagrams (like playgrounds). 

Food for thought about what might be possible for a Swift editor. 

-- Howard.

> On 1 Sep 2017, at 11:27 am, John McCall via swift-evolution 
>  wrote:
> 
>>> On Aug 31, 2017, at 8:51 PM, André “Zephyz” Videla via swift-evolution 
>>>  wrote:
>>> these versions of the math operators don't quite work the same way as the 
>>> standard ones (e.g. `+` can throw), but they still carry math semantics 
>> 
>> 
>> That is exactly what I argue should be avoided. When you see `+` you don’t 
>> expect it to throw. What’s more they don’t carry “math” semantics at all 
>> because for example
>> 
>> Func * (Double, Measurement) -> Measurement is not even associative.
> 
> It's not a group operation, but it is consistent with the concept of scalar 
> multiplication in a vector space.  People sometimes forget that mathematical 
> notations are in fact human languages, which is it say that they're heavily 
> ambiguous and contextual; there are plenty of texts where you see things like 
> S_ij and it's simply understood that i and j are in fact independent indices 
> into the family S.  You could undoubtedly design a parser that understood 
> that sort of rule, but would it ultimately parse a reasonable programming 
> language?  I don't think so.
> 
> I would argue that there is a much broader philosophical truth here.  
> Programming is not, and never can be, a pure exercise in mathematics, and the 
> concepts necessary for understanding programming are related to but 
> ultimately different from the concepts necessary for understanding 
> mathematics.  That is, Dave Sweeris's mathematicians and physicists are 
> almost certainly misunderstanding their confusion: saying that the syntax is 
> wrong implies that there could be a syntax that could be right, i.e. a syntax 
> that would allow them to simply program in pure mathematics.  That is a 
> misapprehension just as deep as the belief that there could be a programming 
> language that would allow one to simply program in conversational English or 
> Korean.  Even the ability to extract code from a proof assistant like Coq or 
> Agda — and writing a proof in Coq or Agda is pretty far from the daily grind 
> of most mathematicians — doesn't belie this, because ultimately the exact 
> code extracted matters to a programmer in a way that the exact form of a 
> known-valid proof does not matter to a mathematician.
> 
> John.
> 
>> I agree that operators for this kind of functions should exist and are the 
>> right syntactic tool. But I disagree with the current implementation. My 
>> proposition for the example of `*` is as follow:
>> 
>> This signature happens quite often `(Number, T) -> T`. It would seem quite 
>> intuitive to have a dedicated operator for all “Scalar multiplication” which 
>> would be visually distinct from `*` (for example **, or Unicode ⊗) and 
>> consistent across codebases. 
>> 
>> For a + operator that throws, I would imagine a “TryAddable” protocol with a 
>> `+!` operator which can throw. I agree that it is visual noise, but I argue 
>> that it has tremendous value: consistant operator semantics.
>> 
>>> (Also, I really doubt changing concatenation to `++` is going to fly. Swift 
>>> is not Haskell.)
>> I doubt those remarks are very constructive. The point still stands: I find 
>> value in having different operators for different semantics.
>> 
>>> On 1 Sep 2017, at 01:54, Brent Royal-Gordon  wrote:
>>> 
 On Aug 31, 2017, at 3:40 PM, André Videla via swift-evolution 
  wrote:
 
 Something I could imagine is deprecate operator overloading and constrain 
 them to a single Type. For example, the operator `+` could be constrained 
 to the protocol `Addable` and has the signature `infix func + (Self, Self) 
 -> Self` and is commutative. Similarly, we could have a protocol 
 `Concatenable` which has its own operator (e.g.: ++ ) and is not 
 commutative.
>>> 
>>> 
>>> These are basically "bag of syntax protocols" which aren't really usable 
>>> generically, so we don't want this design. And if you tied this to the 
>>> numeric protocols, then you couldn't use `+` for things that are 
>>> numeric-ish but don't quite fit t

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-30 Thread Howard Lovatt via swift-evolution
t;>>>> are different enough that I’m not convinced we could have a single 
>>>>>> compiler
>>>>>> feature that meets the needs of both cleanly.
>>>>>>
>>>>>> On Aug 27, 2017, at 7:35 PM, Florent Vilmart 
>>>>>> wrote:
>>>>>>
>>>>>> Adam, you’re completely right, languages as c# and JS have been
>>>>>> through the path before, (callback, Promises , async/await) I believe
>>>>>> Chris’s goal it to avoid building a promise implementation and go 
>>>>>> straight
>>>>>> to a coroutines model, which is more deeply integrated with the 
>>>>>> compiler. I
>>>>>> don’t see a particular trade off, pursuing that route, and the main 
>>>>>> benefit
>>>>>> is that coroutines can power any asynchronous metaphor (Signals, Streams,
>>>>>> Futures, Promises etc...) which is not true of Futures so i would tend to
>>>>>> think that for the long run, and to maximize usability, async/await/yield
>>>>>> would probably be the way to go.
>>>>>>
>>>>>> On Aug 27, 2017, 22:22 -0400, Adam Kemp , wrote:
>>>>>>
>>>>>> As has been explained, futures can be built on top of async/await (or
>>>>>> the other way around). You can have the best of both worlds. We are not
>>>>>> losing anything by having this feature. It would be a huge improvement to
>>>>>> have this as an option.
>>>>>>
>>>>>> However, using futures correctly requires more nested closures than
>>>>>> you have shown in your examples to avoid blocking any threads. That's why
>>>>>> you're not seeing the advantage to async/await. You're comparing examples
>>>>>> that have very different behaviors.
>>>>>>
>>>>>> That said, I have also expressed my opinion that it is better to
>>>>>> build async/await on top of futures rather than the other way around. I
>>>>>> believe it is more powerful and cleaner to make async/await work with any
>>>>>> arbitrary future type (via a protocol). The alternative (building futures
>>>>>> on top of async/await) requires more code when the two are mixed. I very
>>>>>> much prefer how it's done in C#, where you can freely mix the two models
>>>>>> without having to resort to ad-hoc wrappers, and you can use async/await
>>>>>> with any futures implementation you might already be using.
>>>>>>
>>>>>> I really think we should be having more discussion about the
>>>>>> tradeoffs between those two approaches, and I'm concerned that some of 
>>>>>> the
>>>>>> opinions about how C# does it are not based on a clear and accurate
>>>>>> understanding of how it actually works in that language.
>>>>>>
>>>>>> --
>>>>>> Adam Kemp
>>>>>>
>>>>>> On Aug 27, 2017, at 6:02 PM, Howard Lovatt 
>>>>>> wrote:
>>>>>>
>>>>>> The async/await is very similar to the proposed Future (as I posed
>>>>>> earlier) with regard to completion-handler code, they both re-write the
>>>>>> imported completion-handler function using a closure, the relevant 
>>>>>> sentence
>>>>>> from the Async Proposal is:
>>>>>>
>>>>>> "Under the hood, the compiler rewrites this code using nested
>>>>>> closures ..."
>>>>>>
>>>>>>
>>>>>> Unlike the proposed future code the async code is not naturally
>>>>>> parallel, in the running example the following lines from the async code
>>>>>> are run in series, i.e. await blocks:
>>>>>>
>>>>>>   let dataResource  = await loadWebResource("dataprofile.txt")
>>>>>>   let imageResource = await loadWebResource("imagedata.dat")
>>>>>>
>>>>>> The equivalent lines using the proposed Future:
>>>>>>
>>>>>>   let dataResource  = loadWebResource("dataprofile.txt")
>>>>>>   let imageResource = loadWebResource("imagedata.dat")
>>>>>>
>>>>>> Run in parallel and the

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-29 Thread Howard Lovatt via swift-evolution
Oops I missed some awaits out in the async/await version I just posted.
Correct async/await version for parallel execution is:

func updateImage() async {

let image: Image

async do { // Runs in parallel (async)

image = try async preprocessImage(await downloadImage()) // Need to wait
for download

} catch {

image = defaultImage

}

let text: String

async do { // Runs in parallel (async)

text = try async translate(await downloadText()) // Need to wait for
download

} catch {

text = defaultText

}
// This line is complicated! We want render not to block (async), but have
to await for image and text.
// Render does not throw because it always has valid input.
// If async were allowed to prevent blocking then await could not

async render(image: await image, text: await text)

}


PS I think it was Wallacy not Vladimir who suggested the parallel version
using async - another mistake in the previous post - sorry.

  -- Howard.

On 30 August 2017 at 02:02, Wallacy  wrote:

> In this example i think we lose clarity, just looking for the code we cant
> know if this two line will run on parallel or not!
> Also, image.get blocks the thread, in this case we need the await anyway!
> And `async` can throws too... So the error handler can be pretty similar.
>
> let image = async preprocessImage(downloadImage()) // These first two lines 
> run in parallel and I can "see" the async keyword.let text = async 
> translate(downloadText())await render(image: image ?? defaultImage, text: 
> text ?? defaultText) // No blocking!
>
>
> Like i said before! Today's, the proposal only lack two things over the
> `Future`
> Parallel computing: Can be implemented by a third party library or a
> personal one, but i don't think this is a good approach to the first
> version.
> Coordination: This we can wait! And why? Because coordination, can be made
> in different ways, maybe is more suitable to a standard library
> class/function, not a language level resource.
>
> Also, coordination cant be applied to all variants of the runtimes in the
> same way! async/await as language level  works just as well with GCD as
> with pthreads or another API. And coordination is a compromise that we can
> make after that one.
>
> Em ter, 29 de ago de 2017 às 05:23, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> escreveu:
>
>> @David,
>>
>> Using the `Future` library based on GCD that I have previously posted
>> your example would be:
>>
>> let image = preprocessImage(downloadImage()) // These first two lines run in 
>> parallellet text = translate(downloadText())render(image: image.get ?? 
>> defaultImage, text: text.get ?? defaultText)
>>
>>
>> The main difference, and I would argue an improvement, is that the
>> `Future` version handles errors.
>>
>> So what advantage does async/await have over a `Future` library we can
>> write today?
>>
>>
>>   -- Howard.
>>
>> On 29 August 2017 at 15:28, David Hart via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> On 29 Aug 2017, at 02:22, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Mon, Aug 28, 2017 at 16:10 Adam Kemp via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>> I know what the proposal said. I’m making a case that there is value in
>>>> doing it differently.
>>>>
>>>> The composability of futures is valuable. Mixing and matching
>>>> async/await with futures is also valuable. The queue-returning behavior
>>>> that you can get from futures is also valuable, and building async/await on
>>>> top of futures means async/await can get that for free.
>>>>
>>>
>>> Why couldn't you mix and match async/await and futures and get the
>>> queue-return behavior of futures if futures are built on top of async/await
>>> instead off the other way around?
>>>
>>>
>>> We could, but the syntax is much worse. Contrast:
>>>
>>> *async/await built on top of Futures*
>>>
>>> let image = preprocessImage(downloadImage())let text = 
>>> translate(downloadText())
>>> await render(image: image, text: text)
>>>
>>>
>>> *Futures built on top of async/await*
>>>
>>> let image = Future(downloadImage).then({ preprocessImage($0) })let text = 
>>> Future(downloadText).then({ translate($0) })
>>> await render(image: image.get(), text: text.get())
>>>
>>>
>>> Maybe you don’t value those things, which is fine. But I d

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-29 Thread Howard Lovatt via swift-evolution
lieve
>>>>> it is more powerful and cleaner to make async/await work with any 
>>>>> arbitrary
>>>>> future type (via a protocol). The alternative (building futures on top of
>>>>> async/await) requires more code when the two are mixed. I very much prefer
>>>>> how it's done in C#, where you can freely mix the two models without 
>>>>> having
>>>>> to resort to ad-hoc wrappers, and you can use async/await with any futures
>>>>> implementation you might already be using.
>>>>>
>>>>> I really think we should be having more discussion about the tradeoffs
>>>>> between those two approaches, and I'm concerned that some of the opinions
>>>>> about how C# does it are not based on a clear and accurate understanding 
>>>>> of
>>>>> how it actually works in that language.
>>>>>
>>>>> --
>>>>> Adam Kemp
>>>>>
>>>>> On Aug 27, 2017, at 6:02 PM, Howard Lovatt 
>>>>> wrote:
>>>>>
>>>>> The async/await is very similar to the proposed Future (as I posed
>>>>> earlier) with regard to completion-handler code, they both re-write the
>>>>> imported completion-handler function using a closure, the relevant 
>>>>> sentence
>>>>> from the Async Proposal is:
>>>>>
>>>>> "Under the hood, the compiler rewrites this code using nested closures
>>>>> ..."
>>>>>
>>>>>
>>>>> Unlike the proposed future code the async code is not naturally
>>>>> parallel, in the running example the following lines from the async code
>>>>> are run in series, i.e. await blocks:
>>>>>
>>>>>   let dataResource  = await loadWebResource("dataprofile.txt")
>>>>>   let imageResource = await loadWebResource("imagedata.dat")
>>>>>
>>>>> The equivalent lines using the proposed Future:
>>>>>
>>>>>   let dataResource  = loadWebResource("dataprofile.txt")
>>>>>   let imageResource = loadWebResource("imagedata.dat")
>>>>>
>>>>> Run in parallel and therefore are potentially faster assuming that
>>>>> resources, like cores and IO, are available.
>>>>>
>>>>> Therefore you would be better using a Future than an async, so why
>>>>> provide an async unless you can make a convincing argument that it allows
>>>>> you to write a better future?
>>>>>
>>>>>   -- Howard.
>>>>>
>>>>> On 28 August 2017 at 09:59, Adam Kemp  wrote:
>>>>>
>>>>>> This example still has nested closures (to create a Future), and
>>>>>> still relies on a synchronous get method that will block a thread.
>>>>>> Async/await does not require blocking any threads.
>>>>>>
>>>>>> I’m definitely a fan of futures, but this example isn’t even a good
>>>>>> example of using futures. If you’re using a synchronous get method then
>>>>>> you’re not using futures properly. They’re supposed to make it easy to
>>>>>> avoid writing blocking code. This example just does the blocking call on
>>>>>> some other thread.
>>>>>>
>>>>>> Doing it properly would show the benefits of async/await because it
>>>>>> would require more nesting and more complex error handling. By 
>>>>>> simplifying
>>>>>> the code you’ve made a comparison between proper asynchronous code (with
>>>>>> async/await) and improper asynchronous code (your example).
>>>>>>
>>>>>> That tendency to want to just block a thread to make it easier is
>>>>>> exactly why async/await is so valuable. You get simple code while still
>>>>>> doing it correctly.
>>>>>>
>>>>>> --
>>>>>> Adam Kemp
>>>>>>
>>>>>> On Aug 27, 2017, at 4:00 PM, Howard Lovatt via swift-evolution <
>>>>>> swift-evolution@swift.org> wrote:
>>>>>>
>>>>>> The running example used in the white paper coded using a Future is:
>>>>>>
>>>>>> func processImageData1() -> Future {
>>>>>> return AsynchronousFuture { _ 

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-29 Thread Howard Lovatt via swift-evolution
library or a
>> personal one, but i don't think this is a good approach to the first
>> version.
>> Coordination: This we can wait! And why? Because coordination, can be
>> made in different ways, maybe is more suitable to a standard library
>> class/function, not a language level resource.
>>
>> Also, coordination cant be applied to all variants of the runtimes in the
>> same way! async/await as language level  works just as well with GCD as
>> with pthreads or another API. And coordination is a compromise that we can
>> make after that one.
>>
>> Em ter, 29 de ago de 2017 às 05:23, Howard Lovatt via swift-evolution <
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>> escreveu:
>>
>> @David,
>>
>> Using the `Future` library based on GCD that I have previously posted
>> your
>> example would be:
>>
>> let  image=  preprocessImage(downloadImage()) // These first two
>> lines run in parallel
>> let  text=  translate(downloadText())
>> render(image: image.get ?? defaultImage,text: text.get ?? defaultText)
>>
>>
>> The main difference, and I would argue an improvement, is that the
>> `Future`
>> version handles errors.
>>
>> So what advantage does async/await have over a `Future` library we
>> can write today?
>>
>>
>>-- Howard.
>>
>> On 29 August 2017 at 15:28, David Hart via swift-evolution
>> mailto:swift-evolution@swift.org>> wrote:
>>
>>
>> On 29 Aug 2017, at 02:22, Xiaodi Wu via swift-evolution
>>> mailto:swift-evolution@swift.org>>
>>> wrote:
>>>
>>> On Mon, Aug 28, 2017 at 16:10 Adam Kemp via swift-evolution
>>> mailto:swift-evolution@swift.org>>
>>> wrote:
>>>
>>> I know what the proposal said. I’m making a case that there
>>> is value in
>>> doing it differently.
>>>
>>> The composability of futures is valuable. Mixing and matching
>>> async/await with futures is also valuable. The
>>> queue-returning behavior
>>> that you can get from futures is also valuable, and building
>>> async/await on top of futures means async/await can get that
>>> for free.
>>>
>>>
>>> Why couldn't you mix and match async/await and futures and get
>>> the
>>> queue-return behavior of futures if futures are built on top of
>>> async/await
>>> instead off the other way around?
>>>
>>
>> We could, but the syntax is much worse. Contrast:
>>
>> *async/await built on top of Futures*
>> *
>> *
>>
>> let  image=  preprocessImage(downloadImage())
>> let  text=  translate(downloadText())
>> awaitrender(image: image,text: text)
>>
>>
>> *Futures built on top of async/await*
>> *
>> *
>>
>> let  image=  Future(downloadImage).then({preprocessImage($0) })
>> let  text=  Future(downloadText).then({translate($0) })
>> awaitrender(image: image.get(),text: text.get())
>>
>>
>> Maybe you don’t value those things, which is fine. But I do,
>>> and maybe
>>> other people do too. That’s why we’re having a discussion
>>> about it.
>>>
>>> It can also be valuable having a minimal implementation, but
>>> we have to
>>> acknowledge that it comes with a downside as well. The
>>> problem with
>>> doing a minimal implementation is that you can be stuck with
>>> the
>>> consequences for a long time. I want to make sure that we’re
>>> not stuck
>>> with the consequences of a minimal implementation that
>>> doesn’t
>>> adequately address the problems that async/await should be
>>> addressing.
>>> I’d hate for Swift to get an async/await that is so weak
>>> that it has to
>>> be augmented by tedious boilerplate code before it’s useful.
>>>
>>>
>>> On Aug 28, 2017, at 1:54 PM, Wallacy >>> <mailto:walla...@gmail.com>> wrote:
>>>>
>>>> We don't need to this now!
>>>>
>>>> Again: (Using proposal words)
>

Re: [swift-evolution] [Concurrency] Reactive streams as building blocks for actors etc.

2017-08-29 Thread Howard Lovatt via swift-evolution
I think this is what you mean by parallel forEach, I have just expanded the
wording below to be clearer (for myself primarily).

The Java equivalent of a `LazySequenceProtocol` has a parallel method that
returns a parallel lazy sequence, so that operations like map, reduce,
filter, and forEach all run in parallel. I have used this a lot to speed up
code and it would be another great addition.

  -- Howard.

On 29 August 2017 at 16:14, Chris Lattner  wrote:

>
> On Aug 28, 2017, at 6:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Many of the currently popular server side frameworks are switching to
> Reactive Streams:
>
> http://en.wikipedia.org/wiki/Reactive_Streams#Adoption
>
> for their underlying communication, including Akka. Reactive Streams are
> also to become builtin to Java, as the Flow class, in version 9.
>
> Would it be wise if Swift 5 also builtin Reactive Stream protocols and
> built its Actor implementation etc. on top of this protocol?
>
>
> In MHO, yes, it would be great to build a reactive stream abstraction as
> well.   I agree with you that this is an effectively “obvious” part of the
> eventual model, and that we will almost certainly end up building it.  It
> would also make sense to have foreach over an async sequence be itself
> implicitly async.  I haven’t sketched that out, but it seems like a few
> straight-forward steps beyond what is in the manifesto doc.
>
> I’ve added a mention of these to the doc, thanks!
> https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f7
> 82#further-extensions
>
> -Chris
>
>
>
>   -- Howard.
>
> More info on Reactive streams:
>
> https://github.com/reactive-streams/reactive-streams-jvm/
> blob/v1.0.1/README.md#specification
>
> http://bryangilbert.com/post/code/scala/akka-reactive-streams/
>
>
> ___
> 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] [Concurrency] Fixing race conditions in async/await example

2017-08-29 Thread Howard Lovatt via swift-evolution
for this to be useful we would need some kind of existing
>>>> future implementation, but at least we wouldn’t be tied to any particular
>>>> one. That would mean library maintainers who have already been using their
>>>> own futures implementations could quickly adopt async/await in their code
>>>> without having to rewrite their futures library or throw wrappers around
>>>> every usage of async/await. They could just adopt a protocol (using an
>>>> extension, even) and get async/await support for free.
>>>>
>>>> The downside is that this feature would be specific to the async/await
>>>> use case rather than a generic coroutine implementation (i.e., there would
>>>> have to be a separate compiler transform for yield return). It’s not clear
>>>> to me why it should be a goal to have just one generic coroutine feature.
>>>> The real-world usages of async/await and yield return are different enough
>>>> that I’m not convinced we could have a single compiler feature that meets
>>>> the needs of both cleanly.
>>>>
>>>> On Aug 27, 2017, at 7:35 PM, Florent Vilmart 
>>>> wrote:
>>>>
>>>> Adam, you’re completely right, languages as c# and JS have been through
>>>> the path before, (callback, Promises , async/await) I believe Chris’s goal
>>>> it to avoid building a promise implementation and go straight to a
>>>> coroutines model, which is more deeply integrated with the compiler. I
>>>> don’t see a particular trade off, pursuing that route, and the main benefit
>>>> is that coroutines can power any asynchronous metaphor (Signals, Streams,
>>>> Futures, Promises etc...) which is not true of Futures so i would tend to
>>>> think that for the long run, and to maximize usability, async/await/yield
>>>> would probably be the way to go.
>>>>
>>>> On Aug 27, 2017, 22:22 -0400, Adam Kemp , wrote:
>>>>
>>>> As has been explained, futures can be built on top of async/await (or
>>>> the other way around). You can have the best of both worlds. We are not
>>>> losing anything by having this feature. It would be a huge improvement to
>>>> have this as an option.
>>>>
>>>> However, using futures correctly requires more nested closures than you
>>>> have shown in your examples to avoid blocking any threads. That's why
>>>> you're not seeing the advantage to async/await. You're comparing examples
>>>> that have very different behaviors.
>>>>
>>>> That said, I have also expressed my opinion that it is better to build
>>>> async/await on top of futures rather than the other way around. I believe
>>>> it is more powerful and cleaner to make async/await work with any arbitrary
>>>> future type (via a protocol). The alternative (building futures on top of
>>>> async/await) requires more code when the two are mixed. I very much prefer
>>>> how it's done in C#, where you can freely mix the two models without having
>>>> to resort to ad-hoc wrappers, and you can use async/await with any futures
>>>> implementation you might already be using.
>>>>
>>>> I really think we should be having more discussion about the tradeoffs
>>>> between those two approaches, and I'm concerned that some of the opinions
>>>> about how C# does it are not based on a clear and accurate understanding of
>>>> how it actually works in that language.
>>>>
>>>> --
>>>> Adam Kemp
>>>>
>>>> On Aug 27, 2017, at 6:02 PM, Howard Lovatt 
>>>> wrote:
>>>>
>>>> The async/await is very similar to the proposed Future (as I posed
>>>> earlier) with regard to completion-handler code, they both re-write the
>>>> imported completion-handler function using a closure, the relevant sentence
>>>> from the Async Proposal is:
>>>>
>>>> "Under the hood, the compiler rewrites this code using nested closures
>>>> ..."
>>>>
>>>>
>>>> Unlike the proposed future code the async code is not naturally
>>>> parallel, in the running example the following lines from the async code
>>>> are run in series, i.e. await blocks:
>>>>
>>>>   let dataResource  = await loadWebResource("dataprofile.txt")
>>>>   let imageResource = await loadWebResource("imagedata.d

[swift-evolution] [Concurrency] Reactive streams as building blocks for actors etc.

2017-08-28 Thread Howard Lovatt via swift-evolution
Many of the currently popular server side frameworks are switching to
Reactive Streams:

http://en.wikipedia.org/wiki/Reactive_Streams#Adoption

for their underlying communication, including Akka. Reactive Streams are
also to become builtin to Java, as the Flow class, in version 9.

Would it be wise if Swift 5 also builtin Reactive Stream protocols and
built its Actor implementation etc. on top of this protocol?

  -- Howard.

More info on Reactive streams:


https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.1/README.md#specification

http://bryangilbert.com/post/code/scala/akka-reactive-streams/
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] modifying beginAsync, suspendAsync to support cancellation

2017-08-28 Thread Howard Lovatt via swift-evolution
I think this makes the proposed async/await coroutines more viable.
Building on this, if the proposed Cancelable became:

protocol ExecutionControl {
/// Causes the executing coroutine to throw
`TerminateCoroutine.cancelled` and also terminates all the sub-coroutines.
var isCancelled: Bool { set }

/// If an await exceeds timeout then executing task throws
`TerminateCoroutine.timeout` and also terminates all the sub-coroutines.
var timeout: DispatchTimeInterval { get set }
}

Then async/await coroutine would have feature parity with a typical
`Future` - which would be good.

PS Effectively the execution service is returning the `Future`!

  -- Howard.

On 29 August 2017 at 09:42, Marc Schlichte via swift-evolution <
swift-evolution@swift.org> wrote:

>
> Am 19.08.2017 um 20:33 schrieb Marc Schlichte via swift-evolution <
> swift-evolution@swift.org>:
>
> Hi,
>
> to support cancellation, I propose the following changes to `beginAsync()`
> and `suspendAsync()`:
>
> `beginAsync()` returns an object adhering to a `Cancelable` protocol:
>
> ```
> func beginAsync(_ body: () async throws-> Void) rethrows -> Cancelable
>
> protocol Cancelable { func cancel() }
> ```
>
> `suspendAsync()` takes a new thunk parameter:
>
> ```
> func suspendAsync(onCancel: () -> Void, body: (cont: (T) -> Void, err:
> (Error) -> Void) async -> T
> ```
>
> Now, when `cancel()` is invoked, the `onCancel` thunk in the current
> suspension (if any) will be called.
>
>
>
> Example:
>
> ```
> var task: Cancelable?
>
> @IBAction func buttonDidClick(sender: AnyObject) {
>  task = beginAsync {
>do {
>  let image = try await processImage()
>  imageView.image = image
>} catch AsyncError.canceled {
>  imageView.image = nil // or some fallback image...
>} catch {
>  // other handling
>}
>  }
> )
>
> @IBAction func cancelDidClick(sender: AnyObject) {
>  task?.cancel()
> }
>
>
> Just adding here that instead of directly using the low-level
> `beginAsync`, a Future/Promise could be used instead:
>
> ```
> var task: Future?
>
> @IBAction func buttonDidClick(sender: AnyObject) {
>   task = Future {
> try await processImage()
>   }
>   do {
> imageView.image = try await task!.get()
>   } catch AsyncError.canceled {
> imageView.image = nil // or some fallback image...
>   } catch {
> // other handling
>   }
> }
>
> @iBAction func cancelDidClick(sender: AnyObject) {
>   task?.cancel()
> }
> ```
>
> Of course, the init of Future would have to be changed
>
>   convenience init(_ body: () throws async -> T) {
> self.init()
> task = beginAsync {
>   do {
> self.fulfill(try await body())
>   } catch {
> self.fail(error)
>   }
> }
>   }
>
> (BTW also added missing throws and try in code above)
>
> and `cancel()` would have to be added to `Future`:
>
> ```
> public func cancel() {
>   task?.cancel()
> }
>
> ```
>
>
> func processImage() async throws -> UIImage {
>  // This processing should be on a background queue (or better an Actor
> :-) - but ignored for this example
>  var cancelled = false
>  suspendAsync(onCancel: {
>
>cancelled = true
>  }, body: { cont, err in
> while !done && !cancelled {
>   // do the processing on image until done or canceled
> }
> guard !cancelled else { err(AsyncError.canceled) } // BTW, maybe
> change signature of `suspendAsync` to allow to throw here instead
> cont(image)
>  }
> }
> ```
>
>
> ^ BTW, this should be `return  await suspendAsync(…`
>
>
> Cheers
> Marc
>
> ___
> 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] [Concurrency] Fixing race conditions in async/await example

2017-08-28 Thread Howard Lovatt via swift-evolution
I don't really get your point ListenableFuture is a Future, so anything
using ListenableFuture is using Future. As I said in the original message
"... there are a lot of libraries built on top of basic futures ...".

I am pointing out that people actually use Future in Java as the building
block, e.g. ListenableFuture. Therefore Swift would benefit from something
comparable and if async/await doesn't lead to a better future than you can
code using GCD then there is no point.

  -- Howard.

On 29 August 2017 at 07:14, Jean-Daniel  wrote:

>
> Le 28 août 2017 à 06:14, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
> One of the biggest incumbents in this space on the server side is Java and
> its concurrency is based on futures and works very well (though there are a
> lot of libraries built on top of basic futures).
>
>
> Most server side libraries don’t use Java Future as they force blocking at
> some point to get the future result. They instead have there own
> implementation that provide async completion handler (ListenableFuture, …),
> which result in the pattern we are trying to avoid with coroutine and
> async/await.  This is not a very good example.
>
> On 28 August 2017 at 12:35, Florent Vilmart 
> wrote:
>
>> Adam, you’re completely right, languages as c# and JS have been through
>> the path before, (callback, Promises , async/await) I believe Chris’s goal
>> it to avoid building a promise implementation and go straight to a
>> coroutines model, which is more deeply integrated with the compiler. I
>> don’t see a particular trade off, pursuing that route, and the main benefit
>> is that coroutines can power any asynchronous metaphor (Signals, Streams,
>> Futures, Promises etc...) which is not true of Futures so i would tend to
>> think that for the long run, and to maximize usability, async/await/yield
>> would probably be the way to go.
>>
>> On Aug 27, 2017, 22:22 -0400, Adam Kemp , wrote:
>>
>> As has been explained, futures can be built on top of async/await (or the
>> other way around). You can have the best of both worlds. We are not losing
>> anything by having this feature. It would be a huge improvement to have
>> this as an option.
>>
>> However, using futures correctly requires more nested closures than you
>> have shown in your examples to avoid blocking any threads. That's why
>> you're not seeing the advantage to async/await. You're comparing examples
>> that have very different behaviors.
>>
>> That said, I have also expressed my opinion that it is better to build
>> async/await on top of futures rather than the other way around. I believe
>> it is more powerful and cleaner to make async/await work with any arbitrary
>> future type (via a protocol). The alternative (building futures on top of
>> async/await) requires more code when the two are mixed. I very much prefer
>> how it's done in C#, where you can freely mix the two models without having
>> to resort to ad-hoc wrappers, and you can use async/await with any futures
>> implementation you might already be using.
>>
>> I really think we should be having more discussion about the tradeoffs
>> between those two approaches, and I'm concerned that some of the opinions
>> about how C# does it are not based on a clear and accurate understanding of
>> how it actually works in that language.
>>
>> --
>> Adam Kemp
>>
>> On Aug 27, 2017, at 6:02 PM, Howard Lovatt 
>> wrote:
>>
>> The async/await is very similar to the proposed Future (as I posed
>> earlier) with regard to completion-handler code, they both re-write the
>> imported completion-handler function using a closure, the relevant sentence
>> from the Async Proposal is:
>>
>> "Under the hood, the compiler rewrites this code using nested closures
>> ..."
>>
>>
>> Unlike the proposed future code the async code is not naturally parallel,
>> in the running example the following lines from the async code are run in
>> series, i.e. await blocks:
>>
>>   let dataResource  = await loadWebResource("dataprofile.txt")
>>   let imageResource = await loadWebResource("imagedata.dat")
>>
>> The equivalent lines using the proposed Future:
>>
>>   let dataResource  = loadWebResource("dataprofile.txt")
>>   let imageResource = loadWebResource("imagedata.dat")
>>
>> Run in parallel and therefore are potentially faster assuming that
>> resources, like cores and IO, are available.
>>
>> Therefore you would be better using a Fu

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-27 Thread Howard Lovatt via swift-evolution
he proposed future code the async code is not naturally parallel,
> in the running example the following lines from the async code are run in
> series, i.e. await blocks:
>
>   let dataResource  = await loadWebResource("dataprofile.txt")
>   let imageResource = await loadWebResource("imagedata.dat")
>
> The equivalent lines using the proposed Future:
>
>   let dataResource  = loadWebResource("dataprofile.txt")
>   let imageResource = loadWebResource("imagedata.dat")
>
> Run in parallel and therefore are potentially faster assuming that
> resources, like cores and IO, are available.
>
> Therefore you would be better using a Future than an async, so why provide
> an async unless you can make a convincing argument that it allows you to
> write a better future?
>
>   -- Howard.
>
> On 28 August 2017 at 09:59, Adam Kemp  wrote:
>
>> This example still has nested closures (to create a Future), and still
>> relies on a synchronous get method that will block a thread. Async/await
>> does not require blocking any threads.
>>
>> I’m definitely a fan of futures, but this example isn’t even a good
>> example of using futures. If you’re using a synchronous get method then
>> you’re not using futures properly. They’re supposed to make it easy to
>> avoid writing blocking code. This example just does the blocking call on
>> some other thread.
>>
>> Doing it properly would show the benefits of async/await because it would
>> require more nesting and more complex error handling. By simplifying the
>> code you’ve made a comparison between proper asynchronous code (with
>> async/await) and improper asynchronous code (your example).
>>
>> That tendency to want to just block a thread to make it easier is exactly
>> why async/await is so valuable. You get simple code while still doing it
>> correctly.
>>
>> --
>> Adam Kemp
>>
>> On Aug 27, 2017, at 4:00 PM, Howard Lovatt via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> The running example used in the white paper coded using a Future is:
>>
>> func processImageData1() -> Future {
>> return AsynchronousFuture { _ -> Image in
>> let dataResource  = loadWebResource("dataprofile.txt") //
>> dataResource and imageResource run in parallel.
>> let imageResource = loadWebResource("imagedata.dat")
>> let imageTmp  = decodeImage(dataResource.get ??
>> Resource(path: "Default data resource or prompt user"), imageResource.get
>> ?? Resource(path: "Default image resource or prompt user"))
>> let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
>> Image(dataPath: "Default image or prompt user", imagePath: "Default image
>> or prompt user"))
>> return imageResult.get ?? Image(dataPath: "Default image or
>> prompt user", imagePath: "Default image or prompt user")
>> }
>> }
>>
>> This also avoids the pyramid of doom; the pyramid is avoided by
>> converting continuation-handlers into either a sync or future, i.e. it is
>> the importer that eliminates the nesting by translating the code
>> automatically.
>>
>> This example using Future also demonstrates three advantages of Future:
>> they are naturally parallel (dataResource and imageResource lines run in
>> parallel), they timeout automatically (get returns nil if the Future has
>> taken too long), and if there is a failure (for any reason including
>> timeout) it provides a method of either detecting the failure or providing
>> a default (get returns nil on failure).
>>
>> There are a three of other advantages a Future has that this example
>> doesn’t show: control over which thread the Future runs on, Futures can be
>> cancelled, and debugging information is available.
>>
>> You could imagine `async` as a syntax sugar for Future, e.g. the above
>> Future example could be:
>>
>> func processImageData1() async -> Image {
>> let dataResource  = loadWebResource("dataprofile.txt") //
>> dataResource and imageResource run in parallel.
>> let imageResource = loadWebResource("imagedata.dat")
>> let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
>> "Default data resource or prompt user"), imageResource.get ??
>> Resource(path: "Default image resource or prompt user"))
>> let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
>> Image(dataPath: "Default image or prompt user", 

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-27 Thread Howard Lovatt via swift-evolution
One of the biggest incumbents in this space on the server side is Java and
its concurrency is based on futures and works very well (though there are a
lot of libraries built on top of basic futures). Same goes for the Akka
library mentioned in the whitepaper, that is built on top of Scala's
futures. Maybe the bad experiance in C# and JS with futures is more to do
with the implementation of futures in these languages rather than with
futures themselves?

  -- Howard.

On 28 August 2017 at 12:35, Florent Vilmart  wrote:

> Adam, you’re completely right, languages as c# and JS have been through
> the path before, (callback, Promises , async/await) I believe Chris’s goal
> it to avoid building a promise implementation and go straight to a
> coroutines model, which is more deeply integrated with the compiler. I
> don’t see a particular trade off, pursuing that route, and the main benefit
> is that coroutines can power any asynchronous metaphor (Signals, Streams,
> Futures, Promises etc...) which is not true of Futures so i would tend to
> think that for the long run, and to maximize usability, async/await/yield
> would probably be the way to go.
>
> On Aug 27, 2017, 22:22 -0400, Adam Kemp , wrote:
>
> As has been explained, futures can be built on top of async/await (or the
> other way around). You can have the best of both worlds. We are not losing
> anything by having this feature. It would be a huge improvement to have
> this as an option.
>
> However, using futures correctly requires more nested closures than you
> have shown in your examples to avoid blocking any threads. That's why
> you're not seeing the advantage to async/await. You're comparing examples
> that have very different behaviors.
>
> That said, I have also expressed my opinion that it is better to build
> async/await on top of futures rather than the other way around. I believe
> it is more powerful and cleaner to make async/await work with any arbitrary
> future type (via a protocol). The alternative (building futures on top of
> async/await) requires more code when the two are mixed. I very much prefer
> how it's done in C#, where you can freely mix the two models without having
> to resort to ad-hoc wrappers, and you can use async/await with any futures
> implementation you might already be using.
>
> I really think we should be having more discussion about the tradeoffs
> between those two approaches, and I'm concerned that some of the opinions
> about how C# does it are not based on a clear and accurate understanding of
> how it actually works in that language.
>
> --
> Adam Kemp
>
> On Aug 27, 2017, at 6:02 PM, Howard Lovatt 
> wrote:
>
> The async/await is very similar to the proposed Future (as I posed
> earlier) with regard to completion-handler code, they both re-write the
> imported completion-handler function using a closure, the relevant sentence
> from the Async Proposal is:
>
> "Under the hood, the compiler rewrites this code using nested closures ..."
>
>
> Unlike the proposed future code the async code is not naturally parallel,
> in the running example the following lines from the async code are run in
> series, i.e. await blocks:
>
>   let dataResource  = await loadWebResource("dataprofile.txt")
>   let imageResource = await loadWebResource("imagedata.dat")
>
> The equivalent lines using the proposed Future:
>
>   let dataResource  = loadWebResource("dataprofile.txt")
>   let imageResource = loadWebResource("imagedata.dat")
>
> Run in parallel and therefore are potentially faster assuming that
> resources, like cores and IO, are available.
>
> Therefore you would be better using a Future than an async, so why provide
> an async unless you can make a convincing argument that it allows you to
> write a better future?
>
>   -- Howard.
>
> On 28 August 2017 at 09:59, Adam Kemp  wrote:
>
>> This example still has nested closures (to create a Future), and still
>> relies on a synchronous get method that will block a thread. Async/await
>> does not require blocking any threads.
>>
>> I’m definitely a fan of futures, but this example isn’t even a good
>> example of using futures. If you’re using a synchronous get method then
>> you’re not using futures properly. They’re supposed to make it easy to
>> avoid writing blocking code. This example just does the blocking call on
>> some other thread.
>>
>> Doing it properly would show the benefits of async/await because it would
>> require more nesting and more complex error handling. By simplifying the
>> code you’ve made a comparison between proper asynchronous code (with
>> async/await) and improper asynch

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-27 Thread Howard Lovatt via swift-evolution
The async/await is very similar to the proposed Future (as I posed earlier)
with regard to completion-handler code, they both re-write the imported
completion-handler function using a closure, the relevant sentence from the
Async Proposal is:

"Under the hood, the compiler rewrites this code using nested closures ..."


Unlike the proposed future code the async code is not naturally parallel,
in the running example the following lines from the async code are run in
series, i.e. await blocks:

  let dataResource  = await loadWebResource("dataprofile.txt")
  let imageResource = await loadWebResource("imagedata.dat")

The equivalent lines using the proposed Future:

  let dataResource  = loadWebResource("dataprofile.txt")
  let imageResource = loadWebResource("imagedata.dat")

Run in parallel and therefore are potentially faster assuming that
resources, like cores and IO, are available.

Therefore you would be better using a Future than an async, so why provide
an async unless you can make a convincing argument that it allows you to
write a better future?

  -- Howard.

On 28 August 2017 at 09:59, Adam Kemp  wrote:

> This example still has nested closures (to create a Future), and still
> relies on a synchronous get method that will block a thread. Async/await
> does not require blocking any threads.
>
> I’m definitely a fan of futures, but this example isn’t even a good
> example of using futures. If you’re using a synchronous get method then
> you’re not using futures properly. They’re supposed to make it easy to
> avoid writing blocking code. This example just does the blocking call on
> some other thread.
>
> Doing it properly would show the benefits of async/await because it would
> require more nesting and more complex error handling. By simplifying the
> code you’ve made a comparison between proper asynchronous code (with
> async/await) and improper asynchronous code (your example).
>
> That tendency to want to just block a thread to make it easier is exactly
> why async/await is so valuable. You get simple code while still doing it
> correctly.
>
> --
> Adam Kemp
>
> On Aug 27, 2017, at 4:00 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> The running example used in the white paper coded using a Future is:
>
> func processImageData1() -> Future {
> return AsynchronousFuture { _ -> Image in
> let dataResource  = loadWebResource("dataprofile.txt") //
> dataResource and imageResource run in parallel.
> let imageResource = loadWebResource("imagedata.dat")
> let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
> "Default data resource or prompt user"), imageResource.get ??
> Resource(path: "Default image resource or prompt user"))
> let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
> Image(dataPath: "Default image or prompt user", imagePath: "Default image
> or prompt user"))
> return imageResult.get ?? Image(dataPath: "Default image or prompt
> user", imagePath: "Default image or prompt user")
> }
> }
>
> This also avoids the pyramid of doom; the pyramid is avoided by converting
> continuation-handlers into either a sync or future, i.e. it is the importer
> that eliminates the nesting by translating the code automatically.
>
> This example using Future also demonstrates three advantages of Future:
> they are naturally parallel (dataResource and imageResource lines run in
> parallel), they timeout automatically (get returns nil if the Future has
> taken too long), and if there is a failure (for any reason including
> timeout) it provides a method of either detecting the failure or providing
> a default (get returns nil on failure).
>
> There are a three of other advantages a Future has that this example
> doesn’t show: control over which thread the Future runs on, Futures can be
> cancelled, and debugging information is available.
>
> You could imagine `async` as a syntax sugar for Future, e.g. the above
> Future example could be:
>
> func processImageData1() async -> Image {
> let dataResource  = loadWebResource("dataprofile.txt") //
> dataResource and imageResource run in parallel.
> let imageResource = loadWebResource("imagedata.dat")
> let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
> "Default data resource or prompt user"), imageResource.get ??
> Resource(path: "Default image resource or prompt user"))
> let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
> Image(dataPath: "Default image or prompt user", imagePath: "Default image
> or prompt user&quo

Re: [swift-evolution] New async keyword usage

2017-08-27 Thread Howard Lovatt via swift-evolution
My experience with fire and forget without any control or error detection
is that it looks great in small examples but is inadequate in ‘real’
applications, it is highly deadlock prone! I think the minimum you need is
timeout to break deadlocks, control over the thread running the code,
cancel to eliminate hierarchies of background tasks when the top level is
cancelled (e.g. by user), and status to help debugging.


On Sat, 26 Aug 2017 at 7:14 am, Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> I actually *really* like the idea of using ‘async' to start a computation
> in a non-blocking way.  It is extremely common in real-world code to want
> to start a few computations/downloads at once in the background and then
> use the results together...
>
> I think full-fledged futures could be a framework thing added on top, but
> what I would really love to see at the language level is that using ‘async’
> just allows you to defer calling ‘await’.  That is, you could get a value
> back from something called with async, but you would be forced to await
> that value before it could be used:
>
> var image = async downloadImage()  //Image is type UIImage
> //Do something else here
> let size = await image.size //The compiler forces me to call await before
> I can actually use the value
>
> This looks somewhat similar to a future, but you can’t interact with it as
> a separate type of object.  The value above is just a UIImage, but with a
> compiler flag/annotation that forces me to call await on it before it can
> be accessed/used.  The compiler has a lot more freedom to
> optimize/reorganize things behind the scenes, because it doesn’t
> necessarily need to make an intermediate object.
>
> I don’t think this is just sugar.  It adds expressivity and control for a
> set of very common use-cases which aren’t fully supported by await alone.
>
> Thanks,
> Jon
>
>
> On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hello Swift community,
>
> I was really interested by the recent* Task-based concurrency manifesto*
>  and *Concrete proposal for async semantics in Swift.*
>
> Looking at beginAsync() and Futures, I had an idea for a new syntax based
> on the `async` keyword, I'd love to hear your feedback about this idea:
>
> https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md
>
> Would such a syntax make any sense?
>
> Thank you ! :)
>
>
> Trevör
> ___
> 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
>
-- 
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-27 Thread Howard Lovatt via swift-evolution
To avoid or at least detect deadlocks you need: timeout (which will at
least generate an error), cancel (which will prevent zombie processes), and
status information (for debugging). It doesn’t make any difference if the
reference is strong or weak. There is an advantage in strong references
since you can fire and forget if you want a deamon process that is totally
self managing.

On Sun, 27 Aug 2017 at 12:53 am, Marc Schlichte via swift-evolution <
swift-evolution@swift.org> wrote:

> Am 26.08.2017 um 02:03 schrieb Adam Kemp via swift-evolution <
> swift-evolution@swift.org>:
>
> I’m not sure I understand. What is the connection between references and
> deadlocks?
>
>
>
> This is what I had in mind:
>
> To have a deadlock from async actor methods, you would need some mutual
> invocations of them - i.e a cycle in the call graph.
>
> If your code is (strong) retain cycle free and you make invocations only
> on actors of which you have strong references, you will also have no cyclic
> call graph, hence no deadlocks.
>
>
> Now, unfortunately - and contrary to my claim - deadlocks still can happen:
>
> if you `await` in your async actor method on some state which can only be
> set via another actor method in your actor, a deadlock occurs:
>
> Example:
> ```
> actor class A {
>   var continuation: (() -> Void)?
>   actor func m1() async {
> await suspendAsync { cont in
>   continuation = cont
> }
>   }
>   actor func m2() {
> continuation?()
>   }
> }
> ```
>
> If someone calls `a.m1()`, and someone else `a.m2()`, `a.m1()` still does
> not complete as `a.m2()` is not allowed to run while `a.m1()` is not
> finished.
>
> Marking `m2` as an `interleaved actor func` would remedy that situation as
> it could then run when the next work item is picked from the serial gdc
> queue - which can happen while we `await` on the `suspendAsync` in the
> example above.
>
>
> Cheers
> Marc
>
>
> On Aug 25, 2017, at 1:07 PM, Marc Schlichte 
> wrote:
>
>
> Am 25.08.2017 um 19:08 schrieb Adam Kemp via swift-evolution <
> swift-evolution@swift.org>:
>
> I understand what you’re saying, but I just think trying to make
> synchronous, blocking actor methods goes against the fundamental ideal of
> the actor model, and it’s a recipe for disaster. When actors communicate
> with each other that communication needs to be asynchronous or you will get
> deadlocks. It’s not just going to be a corner case. It’s going to be a very
> frequent occurrence.
>
> One of the general rules of multithreaded programming is “don’t call
> unknown code while holding a lock”. Blocking a queue is effectively the
> same as holding a lock, and calling another actor is calling unknown code.
> So if the model works that way then the language itself will be encouraging
> people to call unknown code while holding locks. That is not going to go
> well.
>
>
> I would claim - without having a prove though - that as long as you don’t
> invoke async actor methods on weak or unowned actor references and the code
> is retain cycle free, no deadlocks will happen.
>
> Cheers
> Marc
>
>
> ___
> 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
>
-- 
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-27 Thread Howard Lovatt via swift-evolution
The running example used in the white paper coded using a Future is:

func processImageData1() -> Future {
return AsynchronousFuture { _ -> Image in
let dataResource  = loadWebResource("dataprofile.txt") //
dataResource and imageResource run in parallel.
let imageResource = loadWebResource("imagedata.dat")
let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
"Default data resource or prompt user"), imageResource.get ??
Resource(path: "Default image resource or prompt user"))
let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
Image(dataPath: "Default image or prompt user", imagePath: "Default image
or prompt user"))
return imageResult.get ?? Image(dataPath: "Default image or prompt
user", imagePath: "Default image or prompt user")
}
}

This also avoids the pyramid of doom; the pyramid is avoided by converting
continuation-handlers into either a sync or future, i.e. it is the importer
that eliminates the nesting by translating the code automatically.

This example using Future also demonstrates three advantages of Future:
they are naturally parallel (dataResource and imageResource lines run in
parallel), they timeout automatically (get returns nil if the Future has
taken too long), and if there is a failure (for any reason including
timeout) it provides a method of either detecting the failure or providing
a default (get returns nil on failure).

There are a three of other advantages a Future has that this example
doesn’t show: control over which thread the Future runs on, Futures can be
cancelled, and debugging information is available.

You could imagine `async` as a syntax sugar for Future, e.g. the above
Future example could be:

func processImageData1() async -> Image {
let dataResource  = loadWebResource("dataprofile.txt") // dataResource
and imageResource run in parallel.
let imageResource = loadWebResource("imagedata.dat")
let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
"Default data resource or prompt user"), imageResource.get ??
Resource(path: "Default image resource or prompt user"))
let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
Image(dataPath: "Default image or prompt user", imagePath: "Default image
or prompt user"))
return imageResult.get ?? Image(dataPath: "Default image or prompt
user", imagePath: "Default image or prompt user")
}

Since an async is sugar for Future the async runs as soon as it is created
(as soon as the underlying Future is created) and get returns an optional
(also cancel and status would be still be present). Then if you want
control over threads and timeout they could be arguments to async:

func processImageData1() async(queue: DispatchQueue.main, timeout:
.seconds(5)) -> Image { ... }

On Sat, 26 Aug 2017 at 11:00 pm, Florent Vilmart 
wrote:

> Howard, with async / await, the code is flat and you don’t have to
> unowned/weak self to prevent hideous cycles in the callbacks.
> Futures can’t do that
>
> On Aug 26, 2017, 04:37 -0400, Goffredo Marocchi via swift-evolution <
> swift-evolution@swift.org>, wrote:
>
> With both he now built in promises in Node8 as well as libraries like
> Bluebird there was ample time to evaluate them and convert/auto convert at
> times libraries that loved callback pyramids of doom when the flow grows
> complex into promise based chains. Converting to Promises seems magical for
> the simple case, but can quickly descend in hard to follow flows and hard
> to debug errors when you move to non trivial multi path scenarios. JS is
> now solving it with their implementation of async/await, but the point is
> that without the full picture any single solution would break horribly in
> real life scenarios.
>
> Sent from my iPhone
>
> On 26 Aug 2017, at 06:27, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> My argument goes like this:
>
>   1. You don't need async/await to write a powerful future type; you can
> use the underlying threads just as well, i.e. future with async/await is no
> better than future without.
>
>   2. Since future is more powerful, thread control, cancel, and timeout,
> people should be encouraged to use this; instead because async/await are
> language features they will be presumed, incorrectly, to be the best way,
> consequently people will get into trouble with deadlocks because they don't
> have control.
>
>   3. async/await will require some engineering work and will at best make
> a mild syntax improvement and at worst lead to deadlocks, therefore they
> just don't carry their weight in terms of useful additions to Swift.
>
> Therefore, save some engineering effo

Re: [swift-evolution] [Concurrency] Fixing race conditions in async/await example

2017-08-25 Thread Howard Lovatt via swift-evolution
My argument goes like this:

  1. You don't need async/await to write a powerful future type; you can
use the underlying threads just as well, i.e. future with async/await is no
better than future without.

  2. Since future is more powerful, thread control, cancel, and timeout,
people should be encouraged to use this; instead because async/await are
language features they will be presumed, incorrectly, to be the best way,
consequently people will get into trouble with deadlocks because they don't
have control.

  3. async/await will require some engineering work and will at best make a
mild syntax improvement and at worst lead to deadlocks, therefore they just
don't carry their weight in terms of useful additions to Swift.

Therefore, save some engineering effort and just provide a future library.

To turn the question round another way, in two forms:

  1. What can async/wait do that a future can't?

  2. How will future be improved if async/await is added?


  -- Howard.

On 26 August 2017 at 02:23, Joe Groff  wrote:

>
> On Aug 25, 2017, at 12:34 AM, Howard Lovatt 
> wrote:
>
>  In particular a future that is cancellable is more powerful that the
> proposed async/await.
>
>
> It's not more powerful; the features are to some degree disjoint. You can
> build a Future abstraction and then use async/await to sugar code that
> threads computation through futures. Getting back to Jakob's example,
> someone (maybe the Clang importer, maybe Apple's framework developers in an
> overlay) will still need to build infrastructure on top of IBActions and
> other currently ad-hoc signalling mechanisms to integrate them into a more
> expressive coordination framework.
>
> -Joe
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-25 Thread Howard Lovatt via swift-evolution
I think we would be better off with a future type rather than async/await
since they can offer timeout, cancel, and control over which thread
execution occurs on.

  -- Howard.

On 26 August 2017 at 00:06, Cavelle Benjamin via swift-evolution <
swift-evolution@swift.org> wrote:

> Disclaimer: not an expert
>
> Question
> I didn’t see any where the async is required to time out after a certain
> time frame. I would think that we would want to specify both on the
> function declaration side as a default and on the function call side as a
> customization. That being said, the return time then becomes an optional
> given the timeout and the calling code would need to unwrap.
>
> func loadWebResource(_ path: String) async -> Resourcefunc decodeImage(_ r1: 
> Resource, _ r2: Resource) async -> Imagefunc dewarpAndCleanupImage(_ i : 
> Image) async -> Image
> func processImageData1() async -> Image {
> let dataResource  = await loadWebResource("dataprofile.txt")
> let imageResource = await loadWebResource("imagedata.dat")
> let imageTmp  = await decodeImage(dataResource, imageResource)
> let imageResult   = await dewarpAndCleanupImage(imageTmp)
> return imageResult
> }
>
>
>
> So the prior code becomes…
>
> func loadWebResource(_ path: String) async(timeout: 1000) -> Resource?func 
> decodeImage(_ r1: Resource, _ r2: Resource) async -> Image?func 
> dewarpAndCleanupImage(_ i : Image) async -> Image?
> func processImageData1() async -> Image? {
> let dataResource  = guard let await loadWebResource("dataprofile.txt”) 
> else { // handle timeout }
> let imageResource = guard let await(timeout: 100) 
> loadWebResource("imagedata.dat”) else { // handle timeout }
> let imageTmp  = await decodeImage(dataResource, imageResource)
> let imageResult   = await dewarpAndCleanupImage(imageTmp)
> return imageResult
> }
>
>
>
> Given this structure, the return type of all async’s would be optionals
> with now 3 return types??
>
> .continuation // suspends and picks back up
> .value // these are the values we are looking for
> .none // took too long, so you get nothing.
>
>
>
> On 2017-Aug -17 (34), at 18:24, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hi all,
>
> As Ted mentioned in his email, it is great to finally kick off discussions
> for what concurrency should look like in Swift.  This will surely be an
> epic multi-year journey, but it is more important to find the right design
> than to get there fast.
>
> I’ve been advocating for a specific model involving async/await and actors
> for many years now.  Handwaving only goes so far, so some folks asked me to
> write them down to make the discussion more helpful and concrete.  While I
> hope these ideas help push the discussion on concurrency forward, this
> isn’t in any way meant to cut off other directions: in fact I hope it helps
> give proponents of other designs a model to follow: a discussion giving
> extensive rationale, combined with the long term story arc to show that the
> features fit together.
>
> Anyway, here is the document, I hope it is useful, and I’d love to hear
> comments and suggestions for improvement:
> https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782
>
> -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
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] New async keyword usage

2017-08-25 Thread Howard Lovatt via swift-evolution
I just don't see that async/await adds enough to warrant a language change.
You can write Future on top of GCD and a future type can do more, like
having a cancel, having a timeout, and giving control over what thread is
used.

  -- Howard.

On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution <
swift-evolution@swift.org> wrote:

> Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK in
> JS, any function that returns a promise can be ‘await’ upon, and
> underneath, to be able to await, a function has to return a promise.
> Marking a function async in JS, tells the consumer that some await are
> going on inside, and it’s impossible to use await outside of an async
> marked function. I believe swift is going that direction too. Futures /
> Promises are the foundation on which async / await can truly express as it
> formalizes the boxing of the result types.
> What would be interesting is async being based on a protocol FutureType
> for example, so you can bring your own library and yet, leverage async /
> await
>
> On Aug 25, 2017, 20:50 -0400, Jonathan Hull , wrote:
>
>
> On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <
> trevor.anneden...@icloud.com> wrote:
>
> =
>
> Jonathan Hull jhull at gbis.com
>
> This looks somewhat similar to a future, but you can’t interact with it as
> a separate type of object.  The value above is just a UIImage, but with a
> compiler flag/annotation that forces me to call await on it before it can
> be accessed/used.  The compiler has a lot more freedom to
> optimize/reorganize things behind the scenes, because it doesn’t
> necessarily need to make an intermediate object.
>
>
> As for the message of Wallacy I'd be interested the pros and cons of
> hiding the implementation details ! :)
>
>
> To prove (or potentially disprove) my assertion that this is not just
> sugar, how would you accomplish the following under the current proposal?
>
> let a = async longCalculationA()
> let b = async longCalculationB() //b doesn’t wait for a to complete before
> starting
> let c = async longCalculationC() //c doesn’t wait for a or b
> let result = await combineCalculations(a: a, b: b, c: c) //waits until a,
> b, and c are all available
>
>
> Would this be implemented differently than with Futures? I don't have much
> experience with concurrency, but I don't see how this would be handled
> differently than by using Futures, internally ? (at least for this case)
>
>
> It looks/behaves very similar to futures, but would potentially be
> implemented differently.  The main difference is that the resulting type is
> actually the desired type (instead of Future) with a compiler flag
> saying that it needs to call await to be used.  Behind the scenes, this
> could be implemented as some sort of future, but the compiler has a lot
> more freedom to rearrange things to be much more efficient because there is
> no affordance for the user to introspect or cancel. So for example, it
> might actually change:
>
> let image = async downloadImage()
> let size = await image.size
>
> to:
>
> let size = await downloadImage().size
>
> This would depend on the other code around it, but the compiler has much
> more freedom to avoid creating intermediate values, or even to create
> different types of intermediate values which are more efficient for the
> situation at hand.
>
> Given that as a base, it would be trivial to create a framework offering
> true Futures (which allow cancelling, etc…)
>
> Thanks,
> Jon
>
>
> ___
> 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] [Concurrency] Fixing race conditions in async/await example

2017-08-25 Thread Howard Lovatt via swift-evolution
Using a Future library, see below, you can do what you want. In particular
a future that is cancellable is more powerful that the proposed
async/await. Here is an extended example of a typical UI task including
users cancelling tasks that is written using a future library (see below):

@IBOutlet weak var timeButtonWasPressed: NSTextField!

static func progress(_ window: NSWindow, _ progress:
NSProgressIndicator) -> Future {
return AsynchronousFuture(timeout: .seconds(3)) { isCancelled ->
String in // Timeout set to 3 seconds to ensure normal progress closes the
window before timeout does.
defer { // Make sure the window always closes.
Thread.executeOnMain {
window.close()
}
}
var isFinished = false
var isClosed = false
while !(isFinished || isClosed || isCancelled()) {
Thread.sleep(forTimeInterval: 0.1) // Would do real work
here!
Thread.executeOnMain {
guard window.isVisible else { // Check if user has
closed the window.
isClosed = true
return
}
progress.increment(by: 1)
if progress.doubleValue >= progress.maxValue { // Check
if work done.
isFinished = true
}
}
}
if isClosed || isCancelled() { // Cancelled by user closing
window, by call to `cancel`, or by timeout
throw CancelFuture.cancelled
}
return "\(DispatchTime.now().uptimeNanoseconds)"
}
}

var windowOrigin = NSPoint(x: 0, y: NSScreen.main?.visibleFrame.height
?? 0) // First window in top left of screen.

@IBAction func buttonPushed(_ _: NSButton) {
let progressFrame = NSRect(x: 10, y: 10, width: 200, height: 100)
// On main thread; pop up a progress window.
let progress = NSProgressIndicator(frame: progressFrame)
progress.minValue = 0
progress.maxValue = 20
progress.isIndeterminate = false
let windowFrame = NSRect(x: 0, y: 0, width: progressFrame.width +
20, height: progressFrame.height + 20)
let window = NSWindow(contentRect: windowFrame, styleMask:
[.titled, .closable], backing: .buffered, defer: false)
window.contentView?.addSubview(progress)
windowOrigin = window.cascadeTopLeft(from: windowOrigin) //
Position window.
window.isReleasedWhenClosed = false // Needed to keep ARC happy!
window.orderFront(self) // Display the window but don't give it the
focus.
let _ = AsynchronousFuture { _ -> Void in // Runs on global default
queue.
let creationTime = ViewController.progress(window,
progress).get ?? "Cancelled" // Progress bar with close to allow user
cancellation and finishes automatically after 2 seconds to allow
cancellation or many button presses to pop up other progress windows.
Thread.executeOnMain {
self.timeButtonWasPressed.stringValue = creationTime
}
}
}

The above pops up a window with a progress bar in it every time the user
hits a button (buttonPushed), once the progress bar has completed or is
cancelled the main UI is updated, including noting cancellation by the
user. It can popup multiple windows and cancel them in any order.

This is easier to do with a future library than the proposed async/await
because the library has concepts of: cancellation, timeout, and control
over which queue routines run on.

Future library below:

//
//  main.swift
//  Future
//  Version 0.1
//
//  Created by Howard Lovatt on 22/8/17.
//  Copyright © 2017 Howard Lovatt.
//  This work is licensed under a Creative Commons Attribution 4.0
International License, http://creativecommons.org/licenses/by/4.0/.
//

import Foundation

/// - note:
///   - Written in GCD but execution service would be abstracted for a
'real' version of this proposed `Future`.
///   - It might be necessary to write an atomic class/struct and use it
for _status and isCancelled in CalculatingFuture; see comments after
property declarations.
///   - If _status and isCancelled in CalculatingFuture where atomic then
future would be thread safe.

extension Thread {
/// Run the given closure on the main thread (thread hops to main) and
*wait* for it to complete before returning its value; useful for updating
and reading UI components.
/// Checks to see if already executing on the main thread and if so
does not change to main thread before executing closure, since changing to
main when already on main would cause a deadlock.
/// - note: Not unique to `Future`, hence an extension on `Thread`.
static func executeOnMain(closure: @escaping () -> T) -> T {
var result: T?
if Thread.isMainThread {
result = closure()
} else {
DispatchQueue.main.sync {

Re: [swift-evolution] [Concurrency] Async/Await

2017-08-24 Thread Howard Lovatt via swift-evolution
You are correct, my mistake. Example should read:

func processImageData1() -> Future {
return AsynchronousFuture { _ -> Image in
let dataResource  = loadWebResource("dataprofile.txt") //
dataResource and imageResource run in parallel.
let imageResource = loadWebResource("imagedata.dat")
let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
"Default data resource or prompt user"), imageResource.get ??
Resource(path: "Default image resource or prompt user"))
let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
Image(dataPath: "Default image or prompt user", imagePath: "Default image
or prompt user"))
return imageResult.get ?? Image(dataPath: "Default image or prompt
user", imagePath: "Default image or prompt user")
}
}


  -- Howard.

On 25 August 2017 at 00:25, BJ Homer  wrote:

> Your processImageData1() function is not asynchronous, and does not need
> to return a future, because the “.get” calls are blocking; as you have
> implemented them, they will wait until they have a response or timeout. As
> a result, by the time you reach the return imageResult line, you have
> already waited for that data (or timed out), with the current thread
> blocked. There is no work left to do in the Future.
>
> The point of async/await is that we can wait for the completion of those
> items *asynchronously*, not blocking the current thread. The control
> would return to the calling function before all the data was fetched.
>
> -BJ
>
> On Aug 23, 2017, at 7:35 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hi All,
>
> Really glad that concurrency is on the table for Swift 5.
>
> I am not sure if async/await are worth adding, as is, to Swift because it
> is just as easy to do with a library function - in the spirit of Swift 5,
> see `Future` library code below that you can play with and run.
>
> If a `Future` class was added and the compiler translated
> 'completion-handler' code to 'future' code then the running example given
> in the whitepaper would become (also see the example in the code below):
>
> func loadWebResource(_ path: String) -> Future { ... }
> func decodeImage(_ dataResource: Resource, _ imageResource: Resource) ->
> Future { ... }
> func dewarpAndCleanupImage(_ image: Image) -> Future { ... }
>
> func processImageData1() -> Future {
> let dataResource  = loadWebResource("dataprofile.txt") //
> dataResource and imageResource run in parallel.
> let imageResource = loadWebResource("imagedata.dat")
> let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
> "Default data resource or prompt user"), imageResource.get ??
> Resource(path: "Default image resource or prompt user"))
> let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
> Image(dataPath: "Default image or prompt user", imagePath: "Default image
> or prompt user"))
> return imageResult
> }
>
>
> Which I would argue is actually better than the proposed async/await code
> because:
>
>1. The code is naturally parallel, in example dataResource and
>imageResource are calculated in parallel.
>2. The code handles errors and deadlocks by providing a default value
>using `??`.
>3. The code can be deadlock free or can help find deadlocks, see code
>below, due to having a timeout and a means of cancelling.
>4. The programmer who writes the creator of the `Future` controls
>which queue the future executes on, I would contend that this is the best
>choice since the programmer knows what limitations are in the code and can
>change queue if the code changes in later versions. This is the same
>argument as encapsulation, which gives more control to the writer of a
>struct/class and less control to the user of the struct/class.
>
> In summary, I don't think async/await carries its weight (pun intended),
> as it stands, compared to a library.
>
> But definitely for more Swift concurrency,
>
>  -- Howard.
>
> PS A memory model and atomic that also guaranteed volatile would really
> help with parallel programming!
>
> …(snip)...
>
> ___
> 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] [Concurrency] Async/Await

2017-08-23 Thread Howard Lovatt via swift-evolution
Hi All,

Really glad that concurrency is on the table for Swift 5.

I am not sure if async/await are worth adding, as is, to Swift because it
is just as easy to do with a library function - in the spirit of Swift 5,
see `Future` library code below that you can play with and run.

If a `Future` class was added and the compiler translated
'completion-handler' code to 'future' code then the running example given
in the whitepaper would become (also see the example in the code below):

func loadWebResource(_ path: String) -> Future { ... }
func decodeImage(_ dataResource: Resource, _ imageResource: Resource) ->
Future { ... }
func dewarpAndCleanupImage(_ image: Image) -> Future { ... }

func processImageData1() -> Future {
let dataResource  = loadWebResource("dataprofile.txt") // dataResource
and imageResource run in parallel.
let imageResource = loadWebResource("imagedata.dat")
let imageTmp  = decodeImage(dataResource.get ?? Resource(path:
"Default data resource or prompt user"), imageResource.get ??
Resource(path: "Default image resource or prompt user"))
let imageResult   =  dewarpAndCleanupImage(imageTmp.get ??
Image(dataPath: "Default image or prompt user", imagePath: "Default image
or prompt user"))
return imageResult
}


Which I would argue is actually better than the proposed async/await code
because:

   1. The code is naturally parallel, in example dataResource and
   imageResource are calculated in parallel.
   2. The code handles errors and deadlocks by providing a default value
   using `??`.
   3. The code can be deadlock free or can help find deadlocks, see code
   below, due to having a timeout and a means of cancelling.
   4. The programmer who writes the creator of the `Future` controls which
   queue the future executes on, I would contend that this is the best choice
   since the programmer knows what limitations are in the code and can change
   queue if the code changes in later versions. This is the same argument as
   encapsulation, which gives more control to the writer of a struct/class and
   less control to the user of the struct/class.

In summary, I don't think async/await carries its weight (pun intended), as
it stands, compared to a library.

But definitely for more Swift concurrency,

 -- Howard.

PS A memory model and atomic that also guaranteed volatile would really
help with parallel programming!

===

import Foundation

/// - note:
///   - Written in GCD but execution service would be abstracted for a
'real' version of this proposed `Future`.
///   - It might be necessary to write an atomic class/struct and use it
for _status and isCancelled in CalculatingFuture; see comments after
property declarations.
///   - If _status and isCancelled in CalculatingFuture where atomic then
future would be thread safe.

/// All possible states for a `Future`; a future is in exactly one of these.
enum FutureStatus {
/// Currently running or waiting to run; has not completed, was not
cancelled, has not timed out, and has not thrown.
case running

/// Ran to completion; was not cancelled, did not timeout, and did not
throw, no longer running.
case completed(result: T)

/// Was cancelled, timed out, or calculation threw an exception; no
longer running.
case threw(error: Error)
}

/// An error that signals the future was cancelled.
enum CancelFuture: Error {
/// Should be thrown by a future's calculation when requested to do so
via its `isCancelled` argument (which arises if the future is cancelled or
if the future times out).
case cancelled
}

/// Base class for futures; acts like a future that was cancelled, i.e. no
result and threw `CancelFuture.cancelled`.
/// - note:
///   - You would normally program to `Future`, not one of its derived
classes, i.e. arguments, return types, properties, etc. typed as `Future`.
///   - Futures are **not** thread safe; i.e. they cannot be shared between
threads though their results can and they themselves can be inside any
single thread.
///   - This class is useful in its own right; not just a base class, but
as a future that is known to be cancelled.
class Future {
/// The current state of execution of the future.
/// - note:
///   - The status is updated when the future's calculation finishes;
therefore there will be a lag between a cancellation or a timeout and
status reflecting this.
///   - This status lag is due to the underlying thread system provided
by the operating system that typically does not allow a running thread to
be terminated.
///   - Because status can lag cancel and timeout; prefer get over
status, for obtaining the result of a future and if detailed reasons for a
failure are not required.
///   - Status however offers detailed information if a thread
terminates by throwing (including cancellation and time out) and is
therefore very useful for debugging.
/// - note: In the case of this base class,

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0185 - Synthesizing Equatable and Hashable conformance

2017-08-09 Thread Howard Lovatt via swift-evolution
>
> The review of SE-0185 - "Synthesizing Equatable and Hashable conformance".
> The proposal is available here:
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0185-synthesize-equatable-hashable.md
>
> • What is your evaluation of the proposal?
>

Overall a worthwhile addition. Specific comments:

   1. Opt in a good choice, see 2 below.
   2. Opt in should be for trivial enums as well, even though this is a
   breaking change it is clearer.
   3. The hash function should be more tightly specified, without
   specifying what it does it is hard to know if it is appropriate to use in a
   given application. I am not particularly advocating one hash function over
   another, but rather an explanation of what the user can expect. For example
   is hash consistent across invocations on the same machine and is it
   dependent upon the order of stored property declaration. It should also
   state that the hash function is not consistent across machines, since 32
   and 64 bit machines will have a different hash (as an implementation detail
   the hash function should be required to be different on different machines
   of the same architecture so that people do not mistakenly assume that for
   example all 64 bit machines produce the same hash). There has been a number
   of problems with the Java, Python, etc hash functions because these items
   were not specified.
   4. Specifying the exact hash function to be used could be considered, if
   the hash function is known then dictionary and dictionary like structures
   can be optimized.
   5. Synthesis by extensions in the same file should be considered, now
   that private extends to the file. (As an aside: also Codeable.)
   6. It is quite possible to have class types automatically synthesize
   hash and equality by calling super.hashValue and super.equals(Self). The
   omission seems at odds with treating classes equally to values.
   7. Same for tuples (should be included).
   8. Transient is a useful marker in Java and therefore should be
   considered (would also work well with Codeable).

Hope the above doesn't read negatively, the proposal as is would be a great
addition - the above are suggested improvements rather than show stopping
musts.


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

Yes, I even have a library function that mimics this because I got fed up
of writing  boiler plate.

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

Yes, part of rounding off the language.


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

Yes, see comments above based on experience with other languages


> • How much effort did you put into your review? A glance, a quick
> reading, or an in-depth study?
>

Something I have wanted for a while because I have used this feature in
other languages.

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


Re: [swift-evolution] [swift-evolution-announce] Swift 5: start your engines

2017-08-09 Thread Howard Lovatt via swift-evolution
I am not against these changes, of requiring an implementation, but I am a
little nervous. Let me expand.

I was involved in the Java Coin initiative for community driven changes to
Java 7. In that process the implementation barrier was set very high and it
effectively meant that only changes from Sun got through, a number of
people put considerable effort in only for the proposals to be rejected. I
felt the process was in the end a little disingenuous and I think that view
was held by many, perhaps tellingly the process has never run again for
subsequent Java versions.

So my cautionary note is that this requirement of implementation requires
careful stewardship and in particular there needs to be some means of
getting 'in principle' approval before the implementation stage. If done
correctly it could work very well.

  -- Howard.

On 9 August 2017 at 02:23, Ted Kremenek  wrote:

> Hi everyone,
>
> The proposal phase for Swift 4 is now officially over, and the release is
> now in endgame engineering convergence for an expected release later this
> year.  Swift 4 has turned out to be one of the highest quality,
> well-rounded releases of Swift, and I am grateful to everyone in the
> community who made this release come together!
>
> Now it is time to turn our attention to Swift 5.  I have just posted
> updates to the README.md file on the swift-evolution repository, which
> outlines the core themes and focus areas for Swift 5:
>
>   https://github.com/apple/swift-evolution
>
> and a more persistent URL (invariant to future README.md changes):
>
>   https://github.com/apple/swift-evolution/blob/
> 9cc90f33b6659adeaf92355c359e34e6fed73254/README.md
>
> I am not going to repeat all of that information here, but I wanted to
> highlight a few important things.
>
> ## ABI Stability
>
> First, ABI stability is the center focus of Swift 5 — and we will pivot
> much of our prioritization of efforts for Swift 5 around it.  With Swift 4,
> ABI stability was a strong goal.  In Swift 5, it is a *requirement* of the
> release.  Whatever ABI we have at the end of Swift 5 is the ABI that we
> will have.  ABI stability is an important inflection point for the maturity
> of the language, and it cannot be delayed any longer.
>
> Please note that there is a difference between ABI stability and module
> stability.   If you are not aware of the difference — which is rather
> important — please read the first few paragraphs of the ABI stability
> manifesto:
>
>   https://github.com/apple/swift/blob/master/docs/ABIStabilityManifesto.md
>
> Module stability is a stretch goal for Swift 5, but even without module
> stability we can still achieve the primary value of ABI stability.
>
> ##  Other focus areas (including laying the groundwork for concurrency)
>
> There are several other areas mentioned for Swift 5 which I won’t repeat
> here, but there is a general theme of refining and broadening out the core
> ergonomics of the language and standard library.
>
> One of those that I wanted to highlight is laying the groundwork for
> concurrency.  It is a non-goal of Swift 5 to roll out a full new
> concurrency model.  That is simply too large an effort to do alongside ABI
> stability.  However, it is important that we start making progress on
> discussing the directions for concurrency and laying some of the
> groundwork.  This may take the form of specific enhancements to the
> language that get implemented, depending on where the discussions for
> concurrency lead and how they align with the priorities for delivering ABI
> stability in Swift 5.
>
> ## Changes to the language evolution process
>
> Last, I want to highlight important changes to the evolution process:
>
>   https://github.com/apple/swift-evolution#evolution-process-for-swift-5
> 
>
> With Swift 4, the release period was divided up into “stage 1” and “stage
> 2” for setting guidelines for the kind of evolution proposals that were in
> scope for the release.  This was needed to establish focus — especially
> after the churn we saw during Swift 3 — on some core themes that were
> aligned with converging the language towards source & ABI stability.  One
> downside is that “stage 2” opened up discussion for potentially disruptive
> changes fairly late in the release.  Further, some proposals — such as
> SE-0155 — came in so late that there was little runway to actually
> implement them for Swift 4, let alone evaluate their impact in practice on
> real projects.  Related, there has been some desire  for a while to be able
> to better evaluate the impact of proposals on real code before they are
> locked into the release, and the best way to do that is to actually have an
> implementation that vets out the design in a proposal.
>
> With Swift 5, the focus on ABI stability will predominate priorities for
> both design and implementation work, but the Core Team did not want that
> focus to stifl

Re: [swift-evolution] [swift-evolution-announce] Revision review: SE-104: Protocol-oriented integers

2017-07-20 Thread Howard Lovatt via swift-evolution
>
> The revised version of the proposal can be found here:
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0104-improved-integers.md
>
> • What is your evaluation of the proposal?
>

Overall +1. Two reservations:

  1. Functions like `signum()` that return a property would read better as
a property!
  2. I have found `BitwiseOperations` useful as an extension to both Bool
and Set and for a custom set type. Therefore would prefer its retention and
even more preferably that Bool and Set implement it.

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

Yes, generic representation of integers is useful.


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

Yes, particularly the re-arrangment of the protocol hierarchy is in keeping
with the rest of the restructuring of the standard library.


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

Yes, many languages I use allow generic numeric functions to be written and
I write my own numeric functions and will therefore use these protocols.


> • How much effort did you put into your review? A glance, a quick reading,
> or an in-depth study?
>

Quick read, but have pulled my hair out trying to write generic stuff in
Swift as it stands now.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] SE-0183 - Substring performance affordances

2017-07-19 Thread Howard Lovatt via swift-evolution
>
> The review of "Substring performance affordances" begins now and runs
> through July 21, 2017. The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0183-substring-affordances.md
>
> • What is your evaluation of the proposal?


Generally good. The reservation I have is there are an increasing number of
‘small’ proposals that paper over the limitations of protocols. If
protocols could be used as a type then the methods in `StringProtocol`
would return `StringProtocol` and methods would accept `StringProtocol`.
Whether `String` or `StringSlice` is actually returned by a method would be
irrelevant. Is it better to spend the engineering effort on improving
protocols and `Self` rather than continuously ‘papering over the cracks’.

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


Yes

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


It depends upon the long term view, if protocols are to be improved then
no. If protocols are to remain as is then yes.

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


Other languages that have more powerful equivalent to protocols program to
the protocol and use them for argument and return types. This works better
than the proposal because it is much more generally applicable and doesn’t
hard code implementation details.

>
> • How much effort did you put into your review? A glance, a quick
> reading, or an in-depth study?


Read the proposal only, but have had problems with protocols in general and
have tried various ad-hoc solutions including solutions similar to those
proposed for `String`.

>
>
> More information about the Swift evolution process is available at:
> https://github.com/apple/swift-evolution/blob/master/process.md
>
>
> Thank you,
>
> Chris Lattner
> Review Manager
>
>
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>
-- 
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0182 - String Newline Escaping

2017-07-12 Thread Howard Lovatt via swift-evolution
> The review of "String Newline Escaping" begins now and runs through July
> 17, 2017. The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md
>
> • What is your evaluation of the proposal?


+1. Useful addition to multi-strings and correct decision for single line.

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


Yes is an issue for multi line strings

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


Yes, very handy

>
> • How much effort did you put into your review? A glance, a quick
> reading, or an in-depth studyOn Thu, 13 Jul 2017 at 8:52 am, Chris Lattner <
> clatt...@nondot.org> wrote:

Hello Swift community,


Quick read of proposal

>
>
> Context: As part of winding down work on Swift 4, we are considering
> SE-0182 as a refinement to SE-0168.  We are specifically not opening the
> floodgates for new proposals just yet, and it is not considered in scope to
> resyntax all of multi-line string literals.  We’re just discussing this one
> potential small-scope refinement to an existing Swift 4 feature.

?
>
> More information about the Swift evolution process is available at:
> https://github.com/apple/swift-evolution/blob/master/process.md
>
>
> Thank you,
>
> Chris Lattner
> Review Manager
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>
-- 
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0179: Swift `run` Command

2017-05-16 Thread Howard Lovatt via swift-evolution
+1, useful addition. My guess is that it will be used more than build.

  -- Howard.

On 16 May 2017 at 10:09, Daniel Dunbar  wrote:

> Hello Swift community,
>
> The review of *SE-0179: Swift `run` Command* begins now and runs through *May
> 25th, 2017*.
>
> The proposal is available here:
>
>   https://github.com/apple/swift-evolution/blob/master/
> proposals/0179-swift-run-command.md
>
> Reviews are an important part of the Swift evolution process. All reviews
> should be sent to the swift-build-dev and swift-evolution mailing lists at
>
>   https://lists.swift.org/mailman/listinfo/swift-build-dev
>   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/0179-swift-run-command.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,
> Daniel Dunbar (Review Manager)
>
>
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0178: Add unicodeScalars property to Character

2017-05-12 Thread Howard Lovatt via swift-evolution
It would be nice if character was made to be like a string of exactly
length 1 (cannot be empty) and implemented the new string protocol like the
new string slice does. This way string, string slice, and character could
be used interchangeably when programming to the protocol.

  -- Howard.

On 13 May 2017 at 11:52, Nicholas Maccharoli  wrote:

> +1
>
> - Nick
> 2017年5月13日(土) 10:06 Howard Lovatt via swift-evolution <
> swift-evolution@swift.org>:
>
>> +1
>>
>> -- Howard.
>>
>> On 13 May 2017, at 6:41 am, Ted Kremenek  wrote:
>>
>> Hello Swift community,
>>
>> The review of *SE-0178: Add unicodeScalars property to Character* begins
>> now and runs through *May 17, 2017*.
>>
>> The proposal is available here:
>>
>> https://github.com/apple/swift-evolution/blob/master/
>> proposals/0178-character-unicode-view.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/0178-character-unicode-view.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,
>> Ted (Review Manager)
>>
>> ___
>> swift-evolution-announce mailing list
>> swift-evolution-annou...@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>>
>> ___
>> 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-0176: Enforce Exclusive Access to Memory

2017-05-12 Thread Howard Lovatt via swift-evolution
+1, the benefits outweigh the extra restrictions. Particularly since it is
easy to add an escaping annotation if you think the compiler is wrong.
However this will require careful documentation and good error messages so
that people know why it fails to type check and how to overcome that.

  -- Howard.

On 13 May 2017 at 12:29, Ben Cohen  wrote:

> Hello Swift community,
>
> The review of revisions to *SE-0176: **Enforce Exclusive Access to Memory* 
> begins
> now and runs through *May 17, 2017*.
> Most of this proposal was previously *accepted*.  An implementation issue
> has been discovered with the use of dynamic enforcement on inout
> parameters.  The proposal implementors suggest adopting a stronger rule
> governing the use of non-escaping closures which will also allow Swift to
> make firm guarantees about the use of static enforcement when a variable
> does not escape.  The core team tentatively supports this new rule but
> believes it is a substantial enough revision that it requires a separate
> review period.
>
> The proposal is available here: https://github.com/
> apple/swift-evolution/blob/master/proposals/0176-enforce-
> exclusive-access-to-memory.md
> Since this is a review of revisions only, you may find these two relevant
> commits easier:
> https://github.com/apple/swift-evolution/commit/
> d61c07df2f02bee6c00528e73fbe33738288179a
> https://github.com/apple/swift-evolution/commit/
> 5205a61f9cdca918d896269521bf89cb11e4aa12
>
> 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/0176-enforce-exclusive-access-to-memory.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,
>
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0178: Add unicodeScalars property to Character

2017-05-12 Thread Howard Lovatt via swift-evolution
+1

-- Howard. 

> On 13 May 2017, at 6:41 am, Ted Kremenek  wrote:
> 
> Hello Swift community,
> 
> The review of SE-0178: Add unicodeScalars property to Character begins now 
> and runs through May 17, 2017.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0178-character-unicode-view.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/0178-character-unicode-view.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,
> Ted (Review Manager)
> 
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Overriding specific methods when adopting protocols with extension

2017-05-10 Thread Howard Lovatt via swift-evolution
Here is a proposal I put forwards last month on the same topic.


=

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

| Version | Date   | Comment   |
|-|--|--|
| Draft 1   | 11 April 2017 | Initial version |
| Draft 2  | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
| Draft 3 | 17 April 2017 | Added justification section |
| Draft 4 | 2 May 2017   | Allow final extensions to be public and allow
ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

public protocol P {
func mP() -> String
 }
extension P {
func mP() -> String { return "P.mP" }
func mE() -> String { return "P.mE" }
}
struct S: P {
func mP() -> String { return "S.mP" }
func mE() -> String { return "S.mE" }
}
let s = S()
s.mP() // S.mP as expected
s.mE() // S.mE as expected
let p: P = s // Note: s now typed as P
p.mP() // S.mP as expected
p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

class C: P { /*gets the protocol extensions*/ }
let pC: P = C()
pC.mP() // P.mP as expected!
pC.mE() // P.mE as expected!
class D: C {
/*override not allowed!*/ func mP() -> String { return "D.mP" }
/*override not allowed!*/ func mE() -> String { return "D.mE" }
}
let pD: P = D()
pD.mP() // P.mP unexpected!
pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols retrospectively. The proposal still retains retroactively
adding protocol conformance and ad-hoc code reuse, however these are made
easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its
implemented methods are dispatched using a Vtable for protocols and classes
and statically for structs and enums. EG:

File P.swift

protocol P {
// func m() not declared in type since it is added by the extension,
under this proposal it is an error to include a declaration in a type
**and** in an extension
}
extension P {
func m() { print("P.m") } // m is added to the protocol declaration
}

Same or another file

struct S: P {
override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
}
let p: P = S() // Note typed as P
p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be
final, and can have where clauses and provide inheritable implementations.
Ad-hoc code reuse is supported, in particular if a class/enum/strict
already had a method, m say, and a protocol, P say, required an m then an
extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented
in an extension without the use of the override keyword. This situation
only applies to protocols, for structs/enumerated/classes you cannot
declare in type and implement in an extension at all. This proposal unifies
the behaviour of protocol/struct/enum/class with extensions and also
prevents the error of a minor typo between the protocol and extension adding
two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions and
is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that a
value instance typed as a protocol is copied onto the heap, a pointer to
its Vtable added, and its address passed/copied (i.e. it becomes a class
instance). No change is needed for a class instance typed as a protocol,
which unlike at present can now be passed/copied as a protocol directly.
Think of a protocol as like an abstract class; cannot be instantiated like
an abstract class and which possibly has abstract methods, but in different
in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
ei

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0174: Change `filter` to return an associated type

2017-05-03 Thread Howard Lovatt via swift-evolution
gt;>
>> As an aside: Currently one of the big issues with generalised
>> existentials in Swift is with Self (which you can think of as a form of
>> generic argument). Currently:
>>
>> protocol Equatable {
>> static func ==(lhs: Self, rhs: Self) -> Bool
>> ...
>> }
>> struct Int: Equatable { ... }
>> let e1: Equatable = 1
>> let e2: Equatable = 2
>> if e1 == e2 { ... } // error: e1 and e2 don't necessarily have the
>> same dynamic type
>>
>> I would replace this with:
>>
>> protocol Equatable { // Use T instead of Self
>> static func ==(lhs: T, rhs: T) -> Bool
>> ...
>> }
>> struct Int: Equatable { ... }
>> let e1: Equatable = 1
>> let e2: Equatable = 2
>> if e1 == e2 { ... } // No longer an error since they are both
>> Equatable
>>
>> As an aside on the aside, even better:
>>
>> protocol Equatable { // T defaults to Self
>> static func ==(lhs: T, rhs: T) -> Bool
>> ...
>> }
>> struct Int: Equatable { ... } // T is Int, the default is Self
>> let e1: Equatable = 1  // T is Int, the default is Self
>> let e2: Equatable = 2 // T is Int, the default is Self
>> if e1 == e2 { ... } // No longer an error since they are both
>> Equatable
>>
>> Everything I am suggesting is done in other languages and from my
>> personal experience works out better.
>>
>>
>>   -- Howard.
>>
>> On 2 May 2017 at 09:53, Xiaodi Wu  wrote:
>>
>>> Howard, take a look at the generics manifesto section on generic
>>> protocols:
>>>
>>> https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md
>>>
>>> It explains very nicely how what you're really asking for is not generic
>>> protocols but generalized existentials. This would be nice to have, but
>>> it's clearly not happening within the next month and it wouldn't change the
>>> solution for filter, for which this proposal is the obvious fix.
>>>
>>> On Mon, May 1, 2017 at 18:09 Howard Lovatt via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>> review of SE-0174 "Change `filter` to return an associated type"
>>>>
>>>>
>>>>- What is your evaluation of the proposal?
>>>>
>>>> I think a change in this 'area' is valuable because currently always
>>>> returning an array from collection operations is limiting. However I think
>>>> this proposal feels like 'papering' over problems rather than fixing the
>>>> root cause. I think it would be better to reject this and do two more
>>>> adventurous proposals instead:
>>>>
>>>>   1. Allow protocols to be generic, instead of associated types, so
>>>> that you can write Sequence
>>>>   2. Allow Self to accept a generic argument, so that you can write
>>>> Self
>>>>
>>>> With these to, admittedly much more major changes, you can then write:
>>>>
>>>> protocol Sequence {
>>>> func filter(_ isIncluded: (T) throws -> Bool) rethrows ->
>>>> Sequence
>>>> func map(_ mapper: (T) throws -> M) rethrows -> Sequence
>>>> }
>>>> extension RangeReplaceableCollection {
>>>> func filter(_ isIncluded: (T) throws -> Bool) rethrows ->
>>>> Self {
>>>> var result = Self()
>>>> for element in self {
>>>> if try isIncluded(element) {
>>>>  result.append(element)
>>>> }
>>>> }
>>>>return result
>>>> }
>>>> func map(_ mapper: (T) throws -> M) rethrows -> Self {
>>>> var result = Self()
>>>> for element in self {
>>>> try result.append(mapper(element))
>>>> }
>>>>return result
>>>> }
>>>> }
>>>>
>>>> Which I think both reads better and is more powerful since it allows
>>>> map to be written also.
>>>>
>>>>
>>>>- Is the problem being addressed significant enough to warrant a
>>>>change to Swift?
>>>>
>>>> Yes, return an array is a real pain

Re: [swift-evolution] Proposal: Split extensions into implementing methods and adding static functions Was: [swift-evolution-announce] [Review] SE-0164: Remove final support in protocol extensions

2017-05-03 Thread Howard Lovatt via swift-evolution
@Brent,

What aspects of the current proposal do you have reservations about?

  -- Howard.

On 3 May 2017 at 18:09, Brent Royal-Gordon  wrote:

> On May 3, 2017, at 12:25 AM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I definitely agree that it's a feature that _can_ be used unwisely, but
> the fact remains that it _is_ used pervasively in the standard library, and
> deliberately
>
>
> I'm not so sure that's true. Which standard library protocols
> intentionally depend upon certain parts to not be overridable? Are they so
> pervasive that we wouldn't prefer to just mark those members that need it
> with a `final` keyword? If John McCall woke up tomorrow with some genius
> idea of how to make extension methods overridable with zero overhead, would
> we choose to keep the current design?
>
> That's not to say the proposal at hand is a good idea, but I think you're
> overselling the current design.
>
> --
> Brent Royal-Gordon
> Architechies
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0174: Change `filter` to return an associated type

2017-05-02 Thread Howard Lovatt via swift-evolution
My experience with languages that have generalised existential is that they are 
superior in many circumstances; not just for collections, e.g. I gave the 
example of the comparison protocol. 

I don't think methods called on a returned generalised existential have to be 
called via a Vtable. If the return type is Self then the compiler can 
eliminate the Vtable for selfs that are value types. For selfs that are classes 
it would still have to use a Vtable though, because classes always use Vtables! 
In most cases the return type will be Self and in most cases the Self will 
be a value type, so I would argue that in most cases a Vtable won't be used. 

-- Howard.

> On 2 May 2017, at 8:57 pm, Anders Ha  wrote:
> 
> I would like to add that generalized existential is not really a better 
> solution than letting the collection optionally and statically supply one. It 
> consequentially forces all calls to the filtered collections virtual/dynamic.
> 
> Higher kinded type would ideally help, but we all know it is not coming 
> anytime soon, or perhaps ever. 
> 
> Regards
> Anders
> 
>> On 2 May 2017, at 08:41, Xiaodi Wu via swift-evolution 
>>  wrote:
>> 
>> Howard, this is also mentioned in the generics manifesto under "Opening 
>> existentials," and it's received plentiful discussion and will surely 
>> receive more as these issues become addressed in future proposals. Let's not 
>> divert the conversation here about map and filter.
>>> On Mon, May 1, 2017 at 19:36 Howard Lovatt  wrote:
>>> Yes, I know the change I suggested involves making generalised 
>>> existentials. I am suggesting not making *any* changes until such effort is 
>>> available. I understand that this would be after Swift 4. I think the wait 
>>> would be worthwhile.
>>> 
>>> As an aside: Currently one of the big issues with generalised existentials 
>>> in Swift is with Self (which you can think of as a form of generic 
>>> argument). Currently:
>>> 
>>> protocol Equatable {
>>> static func ==(lhs: Self, rhs: Self) -> Bool
>>> ...
>>> }
>>> struct Int: Equatable { ... }
>>> let e1: Equatable = 1
>>> let e2: Equatable = 2
>>> if e1 == e2 { ... } // error: e1 and e2 don't necessarily have the same 
>>> dynamic type
>>> 
>>> I would replace this with:
>>> 
>>> protocol Equatable { // Use T instead of Self
>>> static func ==(lhs: T, rhs: T) -> Bool
>>> ...
>>> }
>>> struct Int: Equatable { ... }
>>> let e1: Equatable = 1
>>> let e2: Equatable = 2
>>> if e1 == e2 { ... } // No longer an error since they are both 
>>> Equatable
>>> 
>>> As an aside on the aside, even better:
>>> 
>>> protocol Equatable { // T defaults to Self
>>> static func ==(lhs: T, rhs: T) -> Bool
>>> ...
>>> }
>>> struct Int: Equatable { ... } // T is Int, the default is Self
>>> let e1: Equatable = 1  // T is Int, the default is Self
>>> let e2: Equatable = 2 // T is Int, the default is Self
>>> if e1 == e2 { ... } // No longer an error since they are both 
>>> Equatable
>>> 
>>> Everything I am suggesting is done in other languages and from my personal 
>>> experience works out better.
>>> 
>>> 
>>>   -- Howard.
>>> 
>>>> On 2 May 2017 at 09:53, Xiaodi Wu  wrote:
>>>> Howard, take a look at the generics manifesto section on generic protocols:
>>>> 
>>>> https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md
>>>> 
>>>> It explains very nicely how what you're really asking for is not generic 
>>>> protocols but generalized existentials. This would be nice to have, but 
>>>> it's clearly not happening within the next month and it wouldn't change 
>>>> the solution for filter, for which this proposal is the obvious fix.
>>>> 
>>>> On Mon, May 1, 2017 at 18:09 Howard Lovatt via swift-evolution 
>>>>  wrote:
>>>>>> review of SE-0174 "Change `filter` to return an associated type" 
>>>>>> 
>>>>> 
>>>>>> What is your evaluation of the proposal?
>>>>> I think a change in this 'area' is valuable because currently always 
>>>>> returning an array from collection operations is limiting. However I 
>>>>

Re: [swift-evolution] Proposal: Split extensions into implementing methods and adding static functions Was: [swift-evolution-announce] [Review] SE-0164: Remove final support in protocol extensions

2017-05-02 Thread Howard Lovatt via swift-evolution
gt; 
>>>>>>>   3. "Put extension methods into their own namespace." This 
>>>>>>> recommendation is formalised in the proposal by limiting final 
>>>>>>> extensions to be fileprivate or internal.
>>>>>>> 
>>>>>>>   4. "Think twice before extending types you don’t own." 
>>>>>>> 
>>>>>>>   5. "Prefer interface extensions over class extensions." Translation 
>>>>>>> to Swift terminology provide default implementations for protocol 
>>>>>>> methods. The proposal encourages this by eliminating a major gotcha 
>>>>>>> with the current implementation, namely the proposal always dispatches 
>>>>>>> via a Vtable to give consistent behaviour.
>>>>>>> 
>>>>>>>   6. "Be as specific with the types you extend as possible." 
>>>>>>> Translation to Swift terminology provide default implementations for 
>>>>>>> protocol methods that extend other  protocols if there is a more 
>>>>>>> specific behaviour that is relevent. The proposal encourages this by 
>>>>>>> eliminating a major gotcha with the current implementation, namely the 
>>>>>>> proposal always dispatches via a Vtable to give consistent behaviour.
>>>>>>> 
>>>>>>> The proposal formalises these best practices from .NET whilst 
>>>>>>> increasing consistence and without loosing the ability to use 
>>>>>>> extensions heavily in your own one-off code to allow for rapid 
>>>>>>> development. Most of the best practices are for better libraries, 
>>>>>>> particularly third party, which is an important area for future Swift 
>>>>>>> growth onto the server side. This proposal actively encourages this 
>>>>>>> transition to large formal server side code without loosing the free 
>>>>>>> wheeling nature of app code.
>>>>>>> 
>>>>>>> ## Possible future work (not part of this proposal)
>>>>>>> 
>>>>>>> This proposal will naturally allow bodies to be added to protocols 
>>>>>>> directly rather than via an extension, since under the proposal the 
>>>>>>> extension adds the declaration to the type so it is a small step to 
>>>>>>> allow the protocol methods to have an implementation. 
>>>>>>> 
>>>>>>> In an opposite sense to the above adding bodies to protocols, 
>>>>>>> extensions could be allowed to add method declarations without bodies 
>>>>>>> to protocols. 
>>>>>>> 
>>>>>>> The two above future work proposals, if both added, would add symmetry 
>>>>>>> to where declarations and bodies may appear for protocols. 
>>>>>>> 
>>>>>>> ## In summary.
>>>>>>> 
>>>>>>> The proposal formalises the split use of extensions into their two 
>>>>>>> uses: implementing methods and post-hoc adding protocols and methods. 
>>>>>>> Syntax is added that clarifies the two use cases, the former are termed 
>>>>>>> extensions and must be in the same file as the type is declared, and 
>>>>>>> the latter are termed final extensions and can be in any file, however 
>>>>>>> if they are not in the type's file the they can only have fileprivate 
&

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0176: Enforce Exclusive Access to Memory

2017-05-02 Thread Howard Lovatt via swift-evolution
> review of SE-0176: "Enforce Exclusive Access to Memory"
> 
> What is your evaluation of the proposal?

+1, not only will the code be better optimised but also the code will be easier 
to understand. It is also nice that there is formal clarity about what the 
compiler should do. Proposal should probably be expanded to require an 
annotation to mark when part of a value is aliased, e.g. a method that returns 
a slice of an array should be annotated to mark that an access to the returned 
slice will add exclusivity to the original array as well as the slice itself. 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes, Swift is meant to be an easy to use and safe language with good 
performance. These changes improve all these aspects. 
> Does this proposal fit well with the feel and direction of Swift?

Yes, brings clarity and sets Swift up well for the future. 
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?

Not exactly and not as strong as these guarantees at the compiler level. Other 
languages with a runtime VM do offer such guarantees dynamically, e.g. Java. 
The java compiler codes conservative code and then the JVM will optimise that 
code once running and it can be proved to be safe. Obviously in Swift with 
optimisation happening at compile time this isn't possible.
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?

Have had problems with accessing sub-sections of arrays, which whilst safe was 
very slow, presumable because of conservative coding by the compiler. 

-- Howard.

> On 3 May 2017, at 6:07 am, Ben Cohen  wrote:
> 
> Hello Swift community,
> 
> The review of SE-0176: "Enforce Exclusive Access to Memory" begins now and 
> runs through May 8, 2017.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.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/0176-enforce-exclusive-access-to-memory.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
> 
> 
> Thanks,
> Ben Cohen
> Review Manager
> 
> ___
> swift-evolution-announce mailing list
> swift-evolution-annou...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution-announce
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Split extensions into implementing methods and adding static functions Was: [swift-evolution-announce] [Review] SE-0164: Remove final support in protocol extensions

2017-05-02 Thread Howard Lovatt via swift-evolution
e methods and is dispatched using a
>>> Vtable. EG:
>>>
>>> File P.swift
>>> protocol/struct/class P {
>>> // func m() not declared in type since it is added by the
>>> extension, under this proposal it is an error to include a declaration in a
>>> type *and* in an extension
>>> }
>>> extension P {
>>> func m() { print("P.m") } // m is added to the
>>> protocol/struct/class declaration
>>> }
>>>
>>> Same or other file
>>> struct S: P {
>>> override func m() { print("S.m") } // Note override required
>>> because m already has an implementation from the extension
>>> }
>>> let p: P = S() // Note typed as P
>>> p.m() // Now prints S.m as expected
>>>
>>> Extensions in the same file as the declaration can have any access, can
>>> be final, and can have where clauses and provide inheritable
>>> implementations.
>>>
>>> In a protocol at present there is a difference in behaviour between a
>>> protocol that declares a method that is then implemented in an extension
>>> and a protocol that just has the method implemented in an extension and no
>>> declaration. This situation only applies to protocols, for structs and
>>> classes you cannot declare in type and implement in extensions. The
>>> proposal unifies the behaviour of protocol/struct/class with extensions and
>>> prevents the error of a minor typo between the protocol and extension
>>> adding two methods instead of generating an error.
>>>
>>> The implementation needed to achieve this is that a value instance typed
>>> as a protocol is copied onto the heap, a pointer to its Vtable added, and
>>> it is passed as a pointer. IE it becomes a class instance. No change needed
>>> for a class instance typed as a protocol.
>>>
>>> ## Post-hoc adding protocols and methods
>>>
>>> A new type of extension is proposed, a "final extension", which can be
>>> either in or outside the file in which the protocol/struct/class
>>> declaration is in. EG:
>>>
>>> protocol P2 {
>>> func m2P()
>>> }
>>> final extension S: P2 { // Note extension marked final
>>> func m2P() { print("SP2.m2P") } // Implicitly final, completely
>>> implements P2
>>> func m2E() { print("SP2.m2E") } // Implicitly final, not an
>>> existing method
>>> }
>>>
>>> Which are called as any other method would be called:
>>>
>>> let s = S()
>>> s.m2P() // Prints SP2.m2P
>>> s.m2E() // Prints SP2.m2E
>>>
>>> A method added by a final extension is is implicitly final, as the name
>>> would suggest, and cannot be overridden.
>>>
>>> If the final extension:
>>>
>>>   1. Adds a method, e.g. m2E, that method cannot already exist. IE a
>>> final extension cannot override an existing method or implement a protocol
>>> declared method that lacks an implementation unless it also post-hoc adds
>>> the protocol.
>>>
>>>   2. Adds a protocol then it must implement all the methods in that
>>> protocol that are not currently implemented.
>>>
>>>   3. Is outside of the file in which the protocol/struct/class
>>> declaration is in then the extension and the methods can only have
>>> fileprivate or internal access. This prevents post-hoc extensions from
>>> numerous modules clashing, since they are not exported outside of the
>>> module.
>>>
>>> ## Possible future work (not part of this proposal)
>>>
>>> This proposal will naturally allow bodies to be added to protocols
>>> directly rather than via an extension, since under the proposal the
>>> extension adds the declaration to the type so it is a small step to allow
>>> the protocol methods to have an implementation.
>>>
>>> In an opposite sense to the above adding bodies to protocols, extensions
>>> could be allowed to add method declarations without bodies to protocols.
>>>
>>> The two above future work proposals, if both added, would add symmetry
>>> to where declarations and bodies may appear for protocols.
>>>
>>> ## In summary.
>>>
>>> The proposal formalises the split use of extensions into their two uses:
>>> implementing methods and post-hoc adding protocols and methods. Syntax is
>>> added that clarifies the two use cases, the former are termed extensions
>>> and must be in the same file as the type is declared, and the latter are
>>> termed final extensions and can be in any file, however if they are not in
>>> the type's file the they can only have fileprivate or internal access.
>>>
>>> Note the distinction between an extension in the same file and in a
>>> separate file is consistent with the philosophy that there is special
>>> status to the same file as proposed for private in
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>>> .
>>>
>>>
>>> 
>>>
>>> On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon 
>>> wrote:
>>>
>>> On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> I don't see that retroactive conformance needs to be exportable. If it
>>> is exported then you cannot prevent clashes from two modules, this is a
>>> known problem in C#. Because of this and other problems with C# extensions,
>>> this style of extension were rejected by other language communities
>>> (notably Java and Scala).
>>>
>>>
>>> A better alternative for export is a new class that encapsulates the
>>> standard type but with added methods for the protocol to be added. This way
>>> there is no clash between modules. EG:
>>>
>>>
>>>public protocol P {
>>>
>>>func m() -> String
>>>
>>>}
>>>
>>>public class PInt: P {
>>>
>>>var value = 0
>>>
>>>func m() -> String { return "PI.m" }
>>>
>>>}
>>>
>>>
>>> Howard, this would be very source-breaking and would fail to achieve
>>> fundamental goals of Swift's protocol design. Removing retroactive
>>> conformance is no more realistic than removing Objective-C bridging—another
>>> feature which introduces various ugly edge cases and tricky behaviors but
>>> is also non-negotiable.
>>>
>>> --
>>> Brent Royal-Gordon
>>> Architechies
>>>
>>> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> --
-- Howard.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


  1   2   3   >