Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution

> On Aug 18, 2017, at 10:19 AM, Matthew Johnson  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
> 
>>> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>>>  wrote:
>>> Splitting this off into its own thread:
>>> 
 On Aug 17, 2017, at 7:39 PM, Matthew Johnson  
 wrote:
 One related topic that isn’t discussed is type errors.  Many third party 
 libraries use a Result type with typed errors.  Moving to an async / await 
 model without also introducing typed errors into Swift would require 
 giving up something that is highly valued by many Swift developers.  Maybe 
 Swift 5 is the right time to tackle typed errors as well.  I would be 
 happy to help with design and drafting a proposal but would need 
 collaborators on the implementation side.
>>> 
>>> Typed throws is something we need to settle one way or the other, and I 
>>> agree it would be nice to do that in the Swift 5 cycle.
>>> 
>>> For the purposes of this sub-discussion, I think there are three kinds of 
>>> code to think about: 
>>> 1) large scale API like Cocoa which evolve (adding significant 
>>> functionality) over the course of many years and can’t break clients. 
>>> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
>>> fall - being obsoleted and replaced by better packages if they encounter a 
>>> design problem.  
>>> 3) internal APIs and applications, which are easy to change because the 
>>> implementations and clients of the APIs are owned by the same people.
>>> 
>>> These each have different sorts of concerns, and we hope that something can 
>>> start out as #3 but work its way up the stack gracefully.
>>> 
>>> Here is where I think things stand on it:
>>> - There is consensus that untyped throws is the right thing for a large 
>>> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>>> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
>>> reason.
>>> - There is consensus that untyped throws is the right default for people to 
>>> reach for for public package (#2).
>>> - There is consensus that Java and other systems that encourage lists of 
>>> throws error types lead to problematic APIs for a variety of reasons.
>>> - There is disagreement about whether internal APIs (#3) should use it.  It 
>>> seems perfect to be able to write exhaustive catches in this situation, 
>>> since everything in knowable. OTOH, this could encourage abuse of error 
>>> handling in cases where you really should return an enum instead of using 
>>> throws.
>>> - Some people are concerned that introducing typed throws would cause 
>>> people to reach for it instead of using untyped throws for public package 
>>> APIs.
>> 
>> Even for non-public code.  The only practical merit of typed throws I have 
>> ever seen someone demonstrate is that it would let them use contextual 
>> lookup in a throw or catch.  People always say "I'll be able to exhaustively 
>> switch over my errors", and then I ask them to show me where they want to do 
>> that, and they show me something that just logs the error, which of course 
>> does not require typed throws.  Every.  Single.  Time.
> 
> I agree that exhaustive switching over errors is something that people are 
> extremely likely to actually want to do.  I also think it's a bit of a red 
> herring.  The value of typed errors is *not* in exhaustive switching.  It is 
> in categorization and verified documentation.
> 
> Here is a concrete example that applies to almost every app.  When you make a 
> network request there are many things that could go wrong to which you may 
> want to respond differently:
> * There might be no network available.  You might recover by updating the UI 
> to indicate that and start monitoring for a reachability change.
> * There might have been a server error that should eventually be resolved 
> (500).  You might update the UI and provide the user the ability to retry.
> * There might have been an unrecoverable server error (404).  You will update 
> the UI.
> * There might have been a low level parsing error (bad JSON, etc).  Recovery 
> is perhaps similar in nature to #2, but the problem is less likely to be 
> resolved quickly so you may not provide a retry option.  You might also want 
> to do something to notify your dev team that the server is returning JSON 
> that can't be parsed.
> * There might have been a higher-level parsing error (converting JSON to 
> model types).  This might be treated the same as bad JSON.  On the other 
> hand, depending on the specifics of the app, you might take an alternate path 
> that only parses the most essential model data in hopes that the problem was 
> somewhere else and this parse will succeed.
> 
> All of this can obviously be accomplished with untyped errors.  That said, 
> using types 

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

2017-08-18 Thread Chris Lattner via swift-evolution
On Aug 18, 2017, at 6:50 AM, Elviro Rocca  
wrote:
> Here's my thoughts:
> 
> - You might have been too soft on the callback-based syntax of many Cocoa 
> APIs: those are really bad, and in general a pain to use. Of course a import 
> strategy for future Swift will be needed, but I wouldn't consider design 
> constraints exclusively derived from some Cocoa APIs shortcomings, like 
> URLSession.dataTask(withURL:completionHandler:) that I think can be safely 
> ignored.

I don’t think the design is being constrained by Cocoa, I look at it as the 
right answer which conveniently dovetails almost perfectly with Cocoa - similar 
to when Swift 2’s error handling mechanic absorbed the NSError patterns.  In 
the case of error handling, the most common uses were absorbed directly, but 
the odd cases were not.  I expect the same to happen here if async/await is 
adopted.

> - I agree on the focus on async/await as compiler-level tools for defining 
> and using coroutines, with Future and stuff like that to be considered as 
> library functions built on top of the syntax: this way async/await doesn't 
> become mere syntactic sugar.
> 
> - I really STRONGLY disagree on conflating async and throws: they are 
> different things, and exist for different purposes, the same way as Future 
> and Result are different things and should be usable separately. The right 
> way to handle a "failable" future is to simply use a Future, and 
> eventually define convenience functions for the "success" and "failure" 
> cases, or event methods on Future (in this case a ResultType protocol would 
> be needed). It's a lot better to define simpler concepts that compose in 
> interesting ways, rather than conflating unrelated things for minor 
> conveniences.

I understand your concern, but other communities (e.g. Rust and C#) have chosen 
to conflate them out of practicality.  Joe Groff has a lot to say about this, 
hopefully he chimes in.

> - async/await is good, but the Actor model part is simply glorious :D
> 
> - I'm so happy that adding a native idiomatic Actor model has been considered 
> for Swift, and I like the interplay with await for making actor functions 
> return, as well as the progressive disclosure that can be achieved with more 
> and more restrictive keywords: it even seems to me a real step-up from 
> existing implementations of the model.
> 
> - in general I think that one of the best (if not the best) features of Swift 
> is the idea of progressive disclosure, and that should be preserved... and 
> I'm a fan of "actor class" :D
> 
> - I like the "ValueSemantical" protocol idea, but eventually I would like 
> Swift to have features to actually enforce safe patterns though the language 
> itself, like a "pure" or "safe" keyword: I almost use no classes (excluding 
> the UIKit ones that I'm forced to use) and mostly write pure functions, but 
> as the language forces me to do extra work when I'm dealing with an Optional 
> or a throwing function, and that's a good thing in my opinion and facilitates 
> my work as a software engineer, I would love a language that warned me that 
> I'm accessing a potentially mutable instance with reference semantics in a 
> context that I'm mistakenly considering as pure, or that the function I'm 
> writing is not actually pure because a non-pure function was called inside it.

Understood.  There are other interesting and potentially related opportunities 
that could dovetail here.  Several people have discussed adding a first class 
COW concept to the language to easy the implementation of COW types (here’s one 
proposal: 
https://github.com/eeckstein/swift/blob/cow-proposal/docs/proposals/CopyOnWrite.rst
 
).
  Something like that could help.

> - I love the way the "actor" keyword for a method transforms it in an 
> "inbox": I think the implementation you're proposing is super "Swifty" and 
> could appear so convenient that many people could be drawn to the language 
> just thanks to the great native concurrency model; I think that a powerful 
> but simple and usable concurrency model is a heavy motivation for adopting a 
> certain language in many contexts.

Awesome!

-Chris

___
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-18 Thread Joe Groff via swift-evolution

> On Aug 18, 2017, at 12:40 PM, Thomas  wrote:
> 
> 
>> On 18 Aug 2017, at 21:11, Joe Groff  wrote:
>> 
>> 
>>> On Aug 18, 2017, at 11:57 AM, Chris Lattner via swift-evolution 
>>>  wrote:
>>> 
>>> I think that awaiting on the result of an actor method ends up being pretty 
>>> similar (in terms of implementation and design tradeoffs) as dispatch_sync. 
>>>  That said, my understanding is that thread explosion in GCD happens 
>>> whenever something blocks a GCD thread, not when it politely yields control 
>>> back to GCD.  Am I misunderstanding what you mean.
>> 
>> dispatch_sync isn't quite the ideal way of thinking about it, since it will 
>> block the calling context, and as you note this would potentially deadlock 
>> the current thread if an actor invokes one of its own methods. This isn't a 
>> desirable or fundamentally necessary pitfall, since really, the caller actor 
>> is suspending in wait simultaneously with the callee actor taking control. 
>> This is more like a "tail-dispatch_async" kind of operation, where you don't 
>> really want the calling context to block, but you still want to be able to 
>> reuse the current thread since it'll be immediately freed up by blocking on 
>> the async operation. That's something we could conceivably build into 
>> runtime support for this model.
> 
> You seem to imply we are able to jump on the callee actor queue immediately, 
> but the queue may not be available (the actor could be processing another 
> message). So I'm not sure how it goes in term of reusing the same thread, 
> maybe there's some clever trick to do this if it can be determined that the 
> queue is immediately available. But using dispatch_sync() wouldn't work for 
> me as it would potentially block the caller GCD thread and that could end up 
> with thread explosion.

Yeah, "tail-async" would be something the runtime needs to be able to attempt 
conditionally. If either the sending context doesn't immediately return to the 
scheduler, or the receiving context is blocked (possibly with some grace 
period), then you might transparently degrade to a regular async.

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

> On Aug 18, 2017, at 7:19 AM, Michel Fortin  wrote:
> 
> Great writeup. Here's a few comments about the manifesto, actors and value 
> semantics specifically.
> 
> 
> # About actors and data isolation
> 
> Can I call global functions like sin(x) in an actor? Surely you need to be 
> able to do that. But how can the compiler know which functions are safe to 
> use and which are out of bound for an actor?

The design I outline allows you to call it, and punts on the problem of safety:
https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#global-mutable-state
 


> Actors shouldn't access the global mutable state and thus should only call 
> functions that do not access the global mutable state. We probably need a 
> concept of a functions being pure (as in not accessing the global mutable 
> state) for that.

I’m not aware of a practical model to achieve that, but if there were, more 
safety would provide more goodness :-)


> # About the part "Does a type provide proper value semantics?"
> 
> I would argue that this is the wrong question. Most types are a hybrid form 
> of value and reference semantics. All you need is to limit what you do to 
> what is proper value semantics and forbid the parts that use reference 
> semantics. Otherwise you are pessimising the capabilities of the types.
> 
> For instance, has Array value semantics?

By the commonly accepted definition, Array does not provide value 
semantics.

> You might be tempted to say that it does not because it contains class 
> references, but in reality that depends on what you do with those UIViews.

An aspect of the type (“does it have value semantics or not”) should not depend 
on the clients.  By your definition, every type has value semantics if none of 
the mutating operations are called :-)

> If you treat the class references as opaque pointers (never dereferencing 
> them), you preserve value semantics. You can count the elements, shuffle 
> them, all without dereferencing the UIViews it contains. Value semantics only 
> end when you dereference the class references. And even then, there are some 
> exceptions.

I agree with you that the model could permit all values to be sent in actor 
messages, but doing so would give up the principle advantages of mutable state 
separation.  You’d have to do synchronization, you’d have the same bugs that 
have always existed, etc.

-Chris


___
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-18 Thread Adam Kemp via swift-evolution
I am very interested in the async/await proposal. I will say up front that I 
have experience using C#’s async/await (with Cocoa via Xamarin) so I am biased 
towards what I am familiar with. That said, I think there are some advantages 
to the way C# does it that the current proposal is missing out on. One of the 
differences was touched on in Brent’s question here:

> On Aug 17, 2017, at 11:34 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> ## Dispatching back to the original queue
> 
> You correctly identify one of the problems with completion blocks as being 
> that you can't tell which queue the completion will run on, but I don't think 
> you actually discuss a solution to that in the async/await section. Do you 
> think async/await can solve that? How? Does GCD even have the primitives 
> needed? (`dispatch_get_current_queue()` was deprecated long ago and has never 
> been available in Swift.)
> 
> Or do you see this as the province of actors? If so, how does that work? Does 
> every piece of code inherently run inside one actor or another? Or does the 
> concurrency system only get you on the right queue if you explicitly use 
> actors? Can arbitrary classes "belong to" an actor, so that e.g. callbacks 
> into a view controller inherently go to the main queue/actor?
> 
> (If you *do* need actors to get sensible queue behavior, I'm not the biggest 
> fan of that; we could really use that kind of thing in many, many places that 
> aren't actors.)

I see this as one of the key advantages to the C# async/await model. One of the 
goals is to reduce the cognitive load of people writing async code such that 
you can more easily write correct code while writing in a straightforward way. 
Being on the right synchronization context without having to think too hard 
about it is a key part of that.

For instance, say you’re handling a button click, and you need to do a network 
request and then update the UI. In C# (using Xamarin.iOS as an example) you 
might write some code like this:

private async void HandleButtonClick(object sender, EventArgs e) {
var results = await GetStuffFromNetwork();
UpdateUI(results);
}

This event handler is called on the UI thread, and the UpdateUI call must be 
done on the UI thread. The way async/await works in C# (by default) is that 
when your continuation is called it will be on the same synchronization context 
you started with. That means if you started on the UI thread you will resume on 
the UI thread. If you started on some thread pool then you will resume on that 
same thread pool.

If you didn’t have that guarantee then every time you write “await" you would 
have to think about where that continuation code should run, and you would have 
to explicitly make that happen. That might mean something like this:

private async void HandleButtonClick(object sender, EventArgs e) {
var results = await GetStuffFromNetworkAsync();
BeginInvokeOnMainThread(() => {
UpdateUI(results);
});
}

That code doesn’t look much different from the non async/await code:

private void HandleButtonClick(object sender, EventArgs e) {
GetStuffFromNetwork(results => {
BeginInvokeOnMainThread(() => {
UpdateUI(results);
});
});
}

Error handling would only complicate it further.

I feel like this is a very important aspect of how async/await simplifies 
asynchronous programming, and it is especially valuable in application 
development, which is a very important use case for Swift. Obviously GCD is a 
bit different than C#’s Task Parallel Library model, but I feel like there must 
be some way to reconcile these models.



Another difference between the C# implementation and this proposal is the lack 
of futures. While I think it’s fair to be cautious about tying this proposal to 
any specific futures implementation or design, I feel like the value of tying 
it to some concept of futures was somewhat overlooked. For instance, in C# you 
could write a method with this signature:

public Task GetIntAsync();

Consumers could then call that using await:

int i = await GetIntAsync();

Or they could just get the Task and pass it off to someone else:

Task t = GetIntAsync();
return t;

Or they could get the Task and await it, but do something in between:

Task t = GetIntAsync();
// Do something
await t;

That’s more useful when shown like this:

List calculations = inputs.Select(input => 
GetIntAsync(input)).ToList();
int[] results = await Task.WhenAll(calculations);

The benefit of connecting the async/await feature to the concept of futures is 
that you can mix and match this code freely. The current proposal doesn’t seem 
to allow this. If you wanted to implement that last example in Swift you would 
need to write GetIntAsync differently than if you were implementing the simple 
case (just awaiting the one call). With the C# implementation you don’t have to 
care about whether your caller is 

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

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 2:15 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Aug 18, 2017, at 7:19 AM, Michel Fortin > > wrote:
>> 
>> Great writeup. Here's a few comments about the manifesto, actors and value 
>> semantics specifically.
>> 
>> 
>> # About actors and data isolation
>> 
>> Can I call global functions like sin(x) in an actor? Surely you need to be 
>> able to do that. But how can the compiler know which functions are safe to 
>> use and which are out of bound for an actor?
> 
> The design I outline allows you to call it, and punts on the problem of 
> safety:
> https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#global-mutable-state
>  
> 
> 
>> Actors shouldn't access the global mutable state and thus should only call 
>> functions that do not access the global mutable state. We probably need a 
>> concept of a functions being pure (as in not accessing the global mutable 
>> state) for that.
> 
> I’m not aware of a practical model to achieve that, but if there were, more 
> safety would provide more goodness :-)
> 
> 
>> # About the part "Does a type provide proper value semantics?"
>> 
>> I would argue that this is the wrong question. Most types are a hybrid form 
>> of value and reference semantics. All you need is to limit what you do to 
>> what is proper value semantics and forbid the parts that use reference 
>> semantics. Otherwise you are pessimising the capabilities of the types.
>> 
>> For instance, has Array value semantics?
> 
> By the commonly accepted definition, Array does not provide value 
> semantics.

Dave Abrahams and I had an extremely long exchange at one point where he was 
taking the opposite position (if I understood it correctly).  It would be nice 
to have the Swift community adopt a standard definition of value semantics and 
document it on swift.org .  :)

> 
>> You might be tempted to say that it does not because it contains class 
>> references, but in reality that depends on what you do with those UIViews.
> 
> An aspect of the type (“does it have value semantics or not”) should not 
> depend on the clients.  By your definition, every type has value semantics if 
> none of the mutating operations are called :-)
> 
>> If you treat the class references as opaque pointers (never dereferencing 
>> them), you preserve value semantics. You can count the elements, shuffle 
>> them, all without dereferencing the UIViews it contains. Value semantics 
>> only end when you dereference the class references. And even then, there are 
>> some exceptions.
> 
> I agree with you that the model could permit all values to be sent in actor 
> messages, but doing so would give up the principle advantages of mutable 
> state separation.  You’d have to do synchronization, you’d have the same bugs 
> that have always existed, etc.
> 
> -Chris
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2017-08-18 Thread Chris Lattner via swift-evolution
On Aug 18, 2017, at 12:34 PM, Adam Kemp  wrote:
> For instance, say you’re handling a button click, and you need to do a 
> network request and then update the UI. In C# (using Xamarin.iOS as an 
> example) you might write some code like this:
> 
> private async void HandleButtonClick(object sender, EventArgs e) {
> var results = await GetStuffFromNetwork();
> UpdateUI(results);
> }
> 
> This event handler is called on the UI thread, and the UpdateUI call must be 
> done on the UI thread. The way async/await works in C# (by default) is that 
> when your continuation is called it will be on the same synchronization 
> context you started with. That means if you started on the UI thread you will 
> resume on the UI thread. If you started on some thread pool then you will 
> resume on that same thread pool.

I completely agree, I would love to see this because it is the most easy to 
reason about, and is implied by the syntax.  I consider this to be a follow-on 
to the basic async/await proposal - part of the Objective-C importer work, as 
described here:
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#fix-queue-hopping-objective-c-completion-handlers

> Another difference between the C# implementation and this proposal is the 
> lack of futures. While I think it’s fair to be cautious about tying this 
> proposal to any specific futures implementation or design, I feel like the 
> value of tying it to some concept of futures was somewhat overlooked. For 
> instance, in C# you could write a method with this signature:
...
> 
> The benefit of connecting the async/await feature to the concept of futures 
> is that you can mix and match this code freely. The current proposal doesn’t 
> seem to allow this.

The current proposal provides an underlying mechanism that you can build 
futures on, and gives an example.  As shown, the experience using that futures 
API would work quite naturally and fit into Swift IMO.

-Chris

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Joe Groff via swift-evolution

> On Aug 17, 2017, at 11:27 PM, John McCall via swift-evolution 
>  wrote:
> 
> Essentially, you give Error a tagged-pointer representation to allow 
> payload-less errors on non-generic error types to be allocated globally, and 
> then you can (1) tell people to not throw errors that require allocation if 
> it's vital to avoid allocation (just like we would tell them today not to 
> construct classes or indirect enum cases) and (2) allow a special global 
> payload-less error to be substituted if error allocation fails.
> 
> Of course, we could also say that systems code is required to use a 
> typed-throws feature that we add down the line for their purposes.  Or just 
> tell them to not use payloads.  Or force them to constrain their error types 
> to fit within some given size.  (Note that obsessive error taxonomies tend to 
> end up with a bunch of indirect enum cases anyway, because they get 
> recursive, so the allocation problem is very real whatever we do.)

Alternatively, with some LLVM work, we could have the thrower leave the error 
value on the stack when propagating an error, and make it the catcher's 
responsibility to consume the error value and pop the stack. We could make not 
only errors but existential returns in general more efficient and "systems 
code"-worthy with a technique like that.

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Joe Groff via swift-evolution

> On Aug 17, 2017, at 9:58 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson > > wrote:
>> One related topic that isn’t discussed is type errors.  Many third party 
>> libraries use a Result type with typed errors.  Moving to an async / await 
>> model without also introducing typed errors into Swift would require giving 
>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>> is the right time to tackle typed errors as well.  I would be happy to help 
>> with design and drafting a proposal but would need collaborators on the 
>> implementation side.
> 
> Typed throws is something we need to settle one way or the other, and I agree 
> it would be nice to do that in the Swift 5 cycle.

My view of this is the opposite of Matthew's—the canonical examples of things 
for which untyped errors are the "right thing" due to unbounded failure modes, 
such as file IO, IPC, network communication, etc. are almost all things you 
also want to be 'async', so I don't think async makes typed 'throws' any more 
urgent to consider. As we've discussed in person, I feel like there's a strong 
argument to be made that 'async' should always imply untyped 'throws'.

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


Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>  wrote:
> The typed throws discussion brought me back to an old thought.
> 
> I would really like to see a new structural type, similar to tuples, which 
> act as an anonymous enum.  These would actually be a distinct type from enums 
> (not sure what to call them), in the same way that structs and tuples are 
> different.  They would have a very similar syntax to enums though, so they 
> would be easy to learn.

This is the commonly-rejected "Disjunctions in type constraints" feature.

John.

> 
> There would be two major difference from enums:
> 
> 1) Because they are structural, they can’t have associated functions or 
> extensions
> 
> 2) They can concatenate with one another freely 
> 
> For example:
> 
>   func foo( speed: .slow | .med | .fast ){
>   bar(speed: speed)
>   }
> 
>   func bar(speed: .slow | .med | .fast | .ludicrous) {
>   //but we couldn't call foo here because it doesn’t take 
> .ludicrous
>   }
> 
> Each case is it’s own mini-type in a way.  One ‘.slow’ is equivalent to any 
> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
> group of cases, and type checking just means seeing if the list/value being 
> passed is a subset of the list of possible cases.
> 
> I’d also like to see sugar for quick conversion from normal Swift enums:
> 
>   enum Speed {
>   case slow
>   case med
>   case fast
>   }
> 
>   func foo(speed: Speed | .ludicrous) {
>   //we can’t call any functions/extensions of Speed, just like we 
> can’t call a func from int on (Int, Int) 
>   }
> 
> In the above case, Speed gets converted via sugar to “.speed(Speed)” and then 
> gets concatenated with .ludicrous. Ideally, it would have the added ability 
> to truly convert to ".slow | .med | .fast | .ludicrous” when passed to 
> something that doesn’t know about Speed:
> 
>   func foo(speed: Speed | .ludicrous) {
>   switch speed {
>   case .speed(let s): //Do something with the Speed value
>   case .ludicrous: //Do something ludicrous
>   } 
>   bar(speed: speed) //This can convert to pass by unwrapping 
> Speed to a bag of cases
>   }
> 
>   func bar(speed: .slow | .med | .fast | .ludicrous) {
>   switch speed {
>   case .slow: //
>   case .med: //
>   case .fast: //
>   case .ludicrous: //
>   }
>   //We can’t reference Speed above because we just passed a bag 
> of potential cases
>   }
>   
> 
> The end result here is that in addition to building one-off enums quickly, it 
> lets us concatenate and extend enums for use in a limited scope.  I don’t 
> know about you, but I run into the situation of “I want exactly this enum, 
> but with one extra case” all the time.
> 
> I don’t know if we want typed throws, but this type of quick concatability 
> would be very useful for adding/merging potential errors.  With the same 
> sugar used on Speed above, it would also allow something similar to Union 
> types, but without the most of the implementation headache that would cause.  
> You can take in multiple types, and you get back something you can switch on 
> to recover the type which was passed:
> 
>   func myFakeUnion(_ intOrStr: Int | String){
>   switch intOrStr {
>   case .int(let i): //Do something with int
>   case .string(let s): //Do something with string
>   }
>   } 
> 
>   myFakeUnion(12) //Sugar!
>   myFakeUnion(.string(“Hey”)) //This works too
> 
> 
> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift.  
> I am not sure what the best syntax would be, but it would essentially work a 
> bit like like a dictionary:
> 
>   let mph = speed ? [.slow:10, .med:35, .fast:75]
> 
> 
> 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] async/await + actors

2017-08-18 Thread Chris Lattner via swift-evolution

> On Aug 18, 2017, at 6:17 AM, Thomas via swift-evolution 
>  wrote:
> 
> I have been writing a lot of fully async code over the recent years (in objc) 
> and this all seems to fit well with what we're doing and looks like it would 
> alleviate a lot of the pain we have writing asyc code.

Great,

> 
> # Extending the model through await
> 
> I'm a bit worried about the mention of dispatch_sync() here (although it may 
> just be there to illustrate the deadlock possibility). I know the actor 
> runtime implementation is not yet defined, but just wanted to mention that 
> dispatch_sync() will lead to problems such as this annoying thing called 
> thread explosion. This is why we currently cannot use properties in our code 
> (getters would require us to call dispatch_sync() and we want to avoid that), 
> instead we are writing custom async getters/setters with callback blocks. 
> Having async property getters would be pretty awesome.

I think that awaiting on the result of an actor method ends up being pretty 
similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
That said, my understanding is that thread explosion in GCD happens whenever 
something blocks a GCD thread, not when it politely yields control back to GCD. 
 Am I misunderstanding what you mean.

> Another thing: it is not clearly mentionned here that we're getting back on 
> the caller actor's queue after awaiting on another actor's async method.

I omitted it simply because that is related to the runtime model, which I’m 
trying to leave unspecified.  I agree with you that that is the most likely 
answer.

> # Scalable Runtime
> 
> About the problem of creating too many queues. This is something that has 
> annoyed me at this year's wwdc. It used to be back when the libdispatch was 
> introduced in 10.6 that we were told that queues are very cheap, we could 
> create thousands of them and not worry about threads, because the libdispatch 
> would do the right thing internally and adjust to the available hardware (the 
> number of threads would more or less match the number of cores in your 
> machine). Somehow this has changed, now we're being told we need to worry 
> about the threads behind the queues and not have too many of them. I'm not 
> sure if this is something inevitable due to the underlying reality of the 
> system but the way things were presented back then (think in term of queues, 
> don't worry about threads) was very compelling.

I don’t know why the messaging changed, but I agree with you: the ideal is to 
have a simple and predictable model.

> # Entering and leaving async code
> 
> Certainly seems like the beginAsync(), suspendAsync() primitives would be 
> useful outside of the stdlib. The Future example makes use of 
> suspendAsync() to store the continuation block and call it later, other codes 
> would do just as well.
> 
> Shouldn't this:
> 
>> let imageTmp= await decodeImage(dataResource.get(), imageResource.get())
> 
> rather be:
> 
>> let imageTmp= await decodeImage(await dataResource.get(), await 
>> imageResource.get())

As designed (and as implemented in the PR), “await” distributes across all of 
the calls in a subexpression, so you only need it at the top level.  This is 
one of the differences from the C# design.

-Chris
 
___
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-18 Thread David Beck via swift-evolution
https://gist.github.com/davbeck/e3b156d89b2e9d97bb5a61c59f8a07f7

# Async Await

I love this proposal so much. Much of it is exactly how I’ve thought
Swift’s concurrency model should look over the last year.

Making async a return attribute just like `throws` seems like the right
solution to me. Building on top of callbacks (rather than introducing
futures/promises) is also the right approach for swift. I think this
proposal nails the problem right on the head: callbacks don't work well
with the rest of Swift's error handling, is awkward, error prone, and yes,
looks ugly.

One point that I've gone back and forth on is how strictly to enforce
excecution order. For instance, in this example. it would make sense to
allow the first 2 lines to excecute in parallel and excecute the third line
once they both complete:

```swift
let a = await foo()
let b = await bar()
return [a, b]
```

But not in this case:

```swift
await client.connect()
let rooms = await client.getRooms()
```

In the first case the compiler could automatically optimize to run in
parallel, the second, it could not. I like the idea of wrapping parallel
code in a future, making the operation explicit and clear.

### Excecution context

I’m not familiar with C# or other implementations of async/await, only with
Javascript’s (very new) implementation. I’m curious how C# handles
execution contexts (threads, queue etc) since JS doesn’t have to deal with
that.

The `syncCoroutine` and `asyncCoroutine` example seems weird to me. It's
also unclear in that example what the context would be after a call to
async. Would excecution return to the queue, or be on whatever queue the
async function called back on? It makes a lot more sense to me to represent
this with code blocks, something like:

```swift
doSomeStuff()
await startAsync(mainQueue) {
doSomeStuffOnMainThread()
}
await startAsync(backgroundQueue) {
doSomeStuffInBackground()
}
```

Where every line in the code block is run on the context. This doesn't
handle synchronous excecution though. For instance, if we wanted to block a
queue until the entire async function had returned. An alternative might be
to have queues and other contexts define their own method that took async
functions:

```swift
doSomeStuff()
mainQueue.sync {
await loadSomethingStartingOnMain()
doSomeStuffOnMainThread()
// don't let anything else exceute on the main queue until this line
}
await mainQueue.async {
doSomeStuffInBackground()
}
```

Using `queue.async` taking an async function might be a good alternative to
a language "startAsync". Having the excecution context undefined based on
whatever queue the underlying code calls back on seems dangerous to me.
Forcing the user to define the context would fix that, but at the cost of
introducing extra dispatch calls where they may not be needed. A general
purpose context, that simply continued excecution in place would fix that,
and be more explicit when it was needed.

## Conversion of imported Objective-C APIs

One issue I see with the importer is that the conventions for callbacks
aren’t as strict as NSError ** methods were. For instance, URLSession
completion blocks include response, data and error, all of which are
optionals. The response is almost always present, even if there was an
error. But there is no way to know that from the ObjC type system, and no
way to represent a throwing function that also returns metadata on error in
Swift.

There are also cases where you wouldn’t want ObjC callbacks to be imported
as async functions. For instance, it wouldn’t make sense for
NotificationCenter callbacks to be awaited. In general, any callback that
can be called more than once is dangerous to use as an async function.

Personally, I would be in favor of taking a reserved but default on
approach to importing ObjC functions as async, and adding annotations to
ObjC to control their Swift importing. For instance, by default callbacks
with either 0 or 1 arguments would be imported as async non-throwing and
callbacks with 0 or 1 arguments plus an error would be imported as throwing
async. Callbacks with more than 1 argument would need to be manually
annotated. Methods that should not be async (like NotificationCenter) can
be annotated to not be imported as async.

Another issue we’ll need to contend with is intermediate tasks. Both
URLSession and the Photos framework come to mind. In the existing model,
they return something that allows you to cancel the request while it is in
progress. Consider the following example:

```swift
class ImageView {
private var currentTask: URLSessionTask?
var source: URL? {
didSet {
currentTask?.cancel()
image = nil
guard let source = self.source else { return }
load(source: source) { image, error in
guard self.source == source else { return }
if let image = image {
self.image = image
} else {
self.image = errorImage
}
}
}
}
var image: Image?
func load(source: URL, completion: @escaping (Image?, Error?) -> Void) {
let task = 

Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread Robert Bennett via swift-evolution
The better solution would be to allow the creation of new enums from the union 
of existing enums, which was proposed recently.

On Aug 18, 2017, at 2:36 PM, John McCall via swift-evolution 
 wrote:

>> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>>  wrote:
>> The typed throws discussion brought me back to an old thought.
>> 
>> I would really like to see a new structural type, similar to tuples, which 
>> act as an anonymous enum.  These would actually be a distinct type from 
>> enums (not sure what to call them), in the same way that structs and tuples 
>> are different.  They would have a very similar syntax to enums though, so 
>> they would be easy to learn.
> 
> This is the commonly-rejected "Disjunctions in type constraints" feature.
> 
> John.
> 
>> 
>> There would be two major difference from enums:
>> 
>> 1) Because they are structural, they can’t have associated functions or 
>> extensions
>> 
>> 2) They can concatenate with one another freely 
>> 
>> For example:
>> 
>>func foo( speed: .slow | .med | .fast ){
>>bar(speed: speed)
>>}
>> 
>>func bar(speed: .slow | .med | .fast | .ludicrous) {
>>//but we couldn't call foo here because it doesn’t take .ludicrous
>>}
>> 
>> Each case is it’s own mini-type in a way.  One ‘.slow’ is equivalent to any 
>> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
>> group of cases, and type checking just means seeing if the list/value being 
>> passed is a subset of the list of possible cases.
>> 
>> I’d also like to see sugar for quick conversion from normal Swift enums:
>> 
>>enum Speed {
>>case slow
>>case med
>>case fast
>>}
>> 
>>func foo(speed: Speed | .ludicrous) {
>>//we can’t call any functions/extensions of Speed, just like we can’t 
>> call a func from int on (Int, Int) 
>>}
>> 
>> In the above case, Speed gets converted via sugar to “.speed(Speed)” and 
>> then gets concatenated with .ludicrous. Ideally, it would have the added 
>> ability to truly convert to ".slow | .med | .fast | .ludicrous” when passed 
>> to something that doesn’t know about Speed:
>> 
>>func foo(speed: Speed | .ludicrous) {
>>switch speed {
>>case .speed(let s): //Do something with the Speed value
>>case .ludicrous: //Do something ludicrous
>>} 
>>bar(speed: speed) //This can convert to pass by unwrapping Speed to a 
>> bag of cases
>>}
>> 
>>func bar(speed: .slow | .med | .fast | .ludicrous) {
>>switch speed {
>>case .slow: //
>>case .med: //
>>case .fast: //
>>case .ludicrous: //
>>}
>>//We can’t reference Speed above because we just passed a bag of 
>> potential cases
>>}
>>
>> 
>> The end result here is that in addition to building one-off enums quickly, 
>> it lets us concatenate and extend enums for use in a limited scope.  I don’t 
>> know about you, but I run into the situation of “I want exactly this enum, 
>> but with one extra case” all the time.
>> 
>> I don’t know if we want typed throws, but this type of quick concatability 
>> would be very useful for adding/merging potential errors.  With the same 
>> sugar used on Speed above, it would also allow something similar to Union 
>> types, but without the most of the implementation headache that would cause. 
>>  You can take in multiple types, and you get back something you can switch 
>> on to recover the type which was passed:
>> 
>>func myFakeUnion(_ intOrStr: Int | String){
>>switch intOrStr {
>>case .int(let i): //Do something with int
>>case .string(let s): //Do something with string
>>}
>>} 
>> 
>>myFakeUnion(12) //Sugar!
>>myFakeUnion(.string(“Hey”)) //This works too
>> 
>> 
>> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift.  
>> I am not sure what the best syntax would be, but it would essentially work a 
>> bit like like a dictionary:
>> 
>>let mph = speed ? [.slow:10, .med:35, .fast:75]
>> 
>> 
>> 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] [Concurrency] async/await + actors

2017-08-18 Thread Thomas via swift-evolution

> On 18 Aug 2017, at 20:57, Chris Lattner  wrote:
> 
>> I'm a bit worried about the mention of dispatch_sync() here (although it may 
>> just be there to illustrate the deadlock possibility). I know the actor 
>> runtime implementation is not yet defined, but just wanted to mention that 
>> dispatch_sync() will lead to problems such as this annoying thing called 
>> thread explosion. This is why we currently cannot use properties in our code 
>> (getters would require us to call dispatch_sync() and we want to avoid 
>> that), instead we are writing custom async getters/setters with callback 
>> blocks. Having async property getters would be pretty awesome.
> 
> I think that awaiting on the result of an actor method ends up being pretty 
> similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
> That said, my understanding is that thread explosion in GCD happens whenever 
> something blocks a GCD thread, not when it politely yields control back to 
> GCD.  Am I misunderstanding what you mean.

disptach_sync() calls will cause the GCD thread to block (waiting for the queue 
to be available). I'm pretty sure this causes libdispatch to spawn more threads 
if needed (for example if dispatch_async() calls are made in other parts of the 
program), up to thread explosion.

Thomas

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


Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Daniel Dunbar via swift-evolution


> On Aug 17, 2017, at 3:47 PM, Taylor Swift  wrote:
> 
> 
> 
> On Thu, Aug 17, 2017 at 3:50 PM, Daniel Dunbar  > wrote:
> 
> > On Aug 17, 2017, at 9:26 AM, Taylor Swift via swift-evolution 
> > > wrote:
> >
> > I know this has come up before without any action, but having the standard 
> > C library be packaged under `Darwin` on OSX and `Glibc` under Linux is 
> > something that’s really becoming an issue as the Swift package ecosystem 
> > matures. Right now a lot of packages are a lot less portable than they 
> > could be because somewhere along the dependency line, there is a package 
> > that only imports the C library for one platform. Unifying it under one 
> > import would allow people to write packages that are portable by default.
> 
> What we (SwiftPM) have done for now is use a `libc` target to start by 
> normalizing the name:
>   https://github.com/apple/swift-package-manager/tree/master/Sources/libc 
> 
> (and in the past, when we find missing things in Glibc getting them added to 
> the compiler). Also, this name is technically a misnomer, but we couldn’t 
> think of a better one (“os” might have been a good one).
> 
> Unfortunately, I think this change alone is really only the tip of the 
> iceberg. It would be nice to not have it the difference, but we found we very 
> quickly needed several other layers on top to get to having a relatively 
> stable cross-platform base:
>   https://github.com/apple/swift-package-manager/tree/master/Sources/POSIX 
> 
>   https://github.com/apple/swift-package-manager/tree/master/Sources/Basic 
> 
> 
> My hope is that one minimal improvement we can get soon is multi-package repo 
> support in SwiftPM, which will at least allow us to share those targets & 
> functionality with other packages.
> 
> > Since I think this got hung up in the past over “what constitutes” a 
> > universal libc, I propose a unified package should just consist of the 
> > functionality that is common between Darwin and Glibc right now, since 
> > those are the only two supported platforms anyway.
> 
> What would the concrete proposal be? It isn’t trivial to determine that 
> subset and make it well-defined what the exact API is. Is the proposal to 
> just to pick a standard name, and reexport Darwin and Glibc from it?
> 
> I don’t know if it’s actually this simple, but could it just be the symbols 
> that are defined in both modules?

I think this would be hard to implement in practice. There are also symbols 
which are defined the same, but behave differently (or accept slightly 
different types). Reconciling all of that would be a large project.

> > Alternatively, Swift could make it a priority to get basic functionality 
> > like file IO and math functions shipped with the compiler, which would 
> > probably cover 98% of cases where people currently import Darwin/Glibc. A 
> > large portion of the standard C libraries are redundant to the Swift 
> > standard library anyway.
> 
> I’m not sure I agree with these statements about the percentages. For some 
> clients (I’m biased, the areas I work in tend to be in this boat), what we 
> largely need is good platform-agnostic access to the POSIX APIs. This is a 
> hard problem to make a good cross-platform API for (esp. if Windows support 
> is in your head), and which many projects struggle with (Netscape :: NSPR, 
> LLVM :: libSupport, many many more).
> 
> The sticking point I see is this: if the proposal is just to unify the name & 
> that doesn’t actually buy us all that much (still need standard layers on 
> top), then have we really solved enough of a problem to be worth 
> standardizing on?
> 
> +1 in general agreement with the meta-issue being an important one to discuss.
> 
> There probably is an XY issue at play here; what we really need is a way to 
> access the file system built into the standard library. (Math functions are a 
> separate, beleaguered topic for a different thread.) Having support for 
> outputting to `stderr` is also something I’d really like. Going through 
> Glibc/Darwin is just one way to solve this.

Right, this is exactly the kind of thing SwiftPM’s Basic has.

 - Daniel

___
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-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 3:11 PM, Joe Groff via swift-evolution 
>  wrote:
> 
>> On Aug 18, 2017, at 11:57 AM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> I think that awaiting on the result of an actor method ends up being pretty 
>> similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
>> That said, my understanding is that thread explosion in GCD happens whenever 
>> something blocks a GCD thread, not when it politely yields control back to 
>> GCD.  Am I misunderstanding what you mean.
> 
> dispatch_sync isn't quite the ideal way of thinking about it, since it will 
> block the calling context, and as you note this would potentially deadlock 
> the current thread if an actor invokes one of its own methods.

As well as more perniciously creating deadlock opportunities if there are 
cycles in actors dispatching to each other.  It really has to be a "re-queue 
when there's a response" model.

John.

> This isn't a desirable or fundamentally necessary pitfall, since really, the 
> caller actor is suspending in wait simultaneously with the callee actor 
> taking control. This is more like a "tail-dispatch_async" kind of operation, 
> where you don't really want the calling context to block, but you still want 
> to be able to reuse the current thread since it'll be immediately freed up by 
> blocking on the async operation. That's something we could conceivably build 
> into runtime support for this model.
> 
> -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


Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread Adrian Zubarev via swift-evolution
Wasn’t Joe Groff and Daniel Duan proposing anonymous enum cases in some of the 
early draft of the ‘Normalize Enum Case Representation’ proposal?

Maybe it’s time to revive that topic.

Matthew Johnson has also some interesting ideas in hist gist: 
https://gist.github.com/anandabits/5b7f8e3836387e893e3a1197a4bf144d#structural-unions




Am 18. August 2017 um 21:08:22, Robert Bennett via swift-evolution 
(swift-evolution@swift.org) schrieb:

The better solution would be to allow the creation of new enums from the union 
of existing enums, which was proposed recently.

On Aug 18, 2017, at 2:36 PM, John McCall via swift-evolution 
 wrote:

>> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>>  wrote:
>> The typed throws discussion brought me back to an old thought.
>>  
>> I would really like to see a new structural type, similar to tuples, which 
>> act as an anonymous enum. These would actually be a distinct type from enums 
>> (not sure what to call them), in the same way that structs and tuples are 
>> different. They would have a very similar syntax to enums though, so they 
>> would be easy to learn.
>  
> This is the commonly-rejected "Disjunctions in type constraints" feature.
>  
> John.
>  
>>  
>> There would be two major difference from enums:
>>  
>> 1) Because they are structural, they can’t have associated functions or 
>> extensions
>>  
>> 2) They can concatenate with one another freely  
>>  
>> For example:
>>  
>> func foo( speed: .slow | .med | .fast ){
>> bar(speed: speed)
>> }
>>  
>> func bar(speed: .slow | .med | .fast | .ludicrous) {
>> //but we couldn't call foo here because it doesn’t take .ludicrous
>> }
>>  
>> Each case is it’s own mini-type in a way. One ‘.slow’ is equivalent to any 
>> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
>> group of cases, and type checking just means seeing if the list/value being 
>> passed is a subset of the list of possible cases.
>>  
>> I’d also like to see sugar for quick conversion from normal Swift enums:
>>  
>> enum Speed {
>> case slow
>> case med
>> case fast
>> }
>>  
>> func foo(speed: Speed | .ludicrous) {
>> //we can’t call any functions/extensions of Speed, just like we can’t call a 
>> func from int on (Int, Int)  
>> }
>>  
>> In the above case, Speed gets converted via sugar to “.speed(Speed)” and 
>> then gets concatenated with .ludicrous. Ideally, it would have the added 
>> ability to truly convert to ".slow | .med | .fast | .ludicrous” when passed 
>> to something that doesn’t know about Speed:
>>  
>> func foo(speed: Speed | .ludicrous) {
>> switch speed {
>> case .speed(let s): //Do something with the Speed value
>> case .ludicrous: //Do something ludicrous
>> }  
>> bar(speed: speed) //This can convert to pass by unwrapping Speed to a bag of 
>> cases
>> }
>>  
>> func bar(speed: .slow | .med | .fast | .ludicrous) {
>> switch speed {
>> case .slow: //
>> case .med: //
>> case .fast: //
>> case .ludicrous: //
>> }
>> //We can’t reference Speed above because we just passed a bag of potential 
>> cases
>> }
>>  
>>  
>> The end result here is that in addition to building one-off enums quickly, 
>> it lets us concatenate and extend enums for use in a limited scope. I don’t 
>> know about you, but I run into the situation of “I want exactly this enum, 
>> but with one extra case” all the time.
>>  
>> I don’t know if we want typed throws, but this type of quick concatability 
>> would be very useful for adding/merging potential errors. With the same 
>> sugar used on Speed above, it would also allow something similar to Union 
>> types, but without the most of the implementation headache that would cause. 
>> You can take in multiple types, and you get back something you can switch on 
>> to recover the type which was passed:
>>  
>> func myFakeUnion(_ intOrStr: Int | String){
>> switch intOrStr {
>> case .int(let i): //Do something with int
>> case .string(let s): //Do something with string
>> }
>> }  
>>  
>> myFakeUnion(12) //Sugar!
>> myFakeUnion(.string(“Hey”)) //This works too
>>  
>>  
>> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift. 
>> I am not sure what the best syntax would be, but it would essentially work a 
>> bit like like a dictionary:
>>  
>> let mph = speed ? [.slow:10, .med:35, .fast:75]
>>  
>>  
>> 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] [Pitch] Improve `init(repeating:count)`

2017-08-18 Thread Erica Sadun via swift-evolution

> On Aug 17, 2017, at 9:29 PM, Taylor Swift  wrote:
> On Thu, Aug 17, 2017 at 9:06 PM, Erica Sadun via swift-evolution 
> > wrote:
> 
>> On Aug 17, 2017, at 6:56 PM, Xiaodi Wu > > wrote:
>> 
>> On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun > > wrote:
>> What people are doing is taking a real set of values (1, 2, 3, 4, 5, for 
>> example), then discarding them via `_ in`, which is different from `Void -> 
>> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", ,  
>> UIColor.red, { x: Int in x^x }). There are too many semantic shifts away 
>> from "I would like to collect the execution of this closure n times" for it 
>> to sit comfortably.
>> 
>> What arguments might help to alleviate this discomfort? Clearly, functions 
>> exist that can map this delightfully heterogeneous domain to some sort of 
>> range that the user wants. Would you feel better if we wrote instead the 
>> following?
>> 
>> ```
>> repeatElement((), count: 5).map { UIView() }
>> ```
> 
> My favorite solution is the array initializer. Something along the lines of 
> `Array(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches 
> standard library but I think it is a solid way to say "produce a collection 
> with a generator run n times". It's a common  task. I was asking around about 
> this, and found that a lot of us who work with both macOS and iOS and want to 
> stress test interfaces do this very often. Other use cases include "give me n 
> random numbers", "give me n records from this database", etc. along similar 
> lines.
> 
> The difference between this and the current `Array(repeating:count:)` 
> initializer is switching the arguments and using a trailing closure  (or an 
> autoclosure) rather than a set value. That API was designed without the 
> possibility that you might want to repeat a generator, so there's a bit of 
> linguistic turbulence.
> 
> -- E
> 
> 
> To me at least, this is a very i-Centric complaint, since I can barely 
> remember the last time I needed something like this for anything that didn’t 
> involve UIKit. What you’re asking for is API sugar for generating reference 
> types with less typing. 

No, that's what the original thread poster wanted.

I want to avoid breaking math. For any x passed to a function, I expect f(x) to 
produce the same result. To map is to create a relation so that for every x in 
a domain, there is a single y that it produces. You can hand-wave and say the 
map is "producing" the closure, but it's not. It's executing it and recovering 
a value.

How we get past the `(n ... m).map({ _ in ... })` pattern may be through 
language guidance or through language evolution. Either way, it doesn't make 
this pattern not problematic and worthy of discussion.

Finally, I don't think Swift Evolution _can_ be considered entirely outside the 
auspices of the Apple halo. Look at SE-0005, SE-0006, and SE-0023 for example. 
i-Centricity is inescapable given the core team and the hosting domain for this 
project.

-- E

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Christopher Kornher via swift-evolution

> On Aug 18, 2017, at 7:38 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> I would like to reiterate the point I made in the question that spawned this 
> thread: there are *many* Swift libraries for writing async code of various 
> sorts which are *already* using typed errors via `Result Error>`.  We don't have to speculate about how this feature might be used and 
> what kind of benefits might be realized.  We can have a discussion about what 
> people are already doing and determine whether this model should be supported 
> in the async / await world or not.  What do you think of putting a call out 
> to the broader Swift community to bring us concrete examples of how they are 
> benefiting from using typed errors in async code.

I have found this “feature" has been painful to use. I have been forced to wrap 
hetrogenous errors in a custom error type just to satisfy these ill-conceived 
APIs. i have never found any benefit to ```ErrorType: Error``` generic 
parameter. … Any. Ever.

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


Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 2:19 PM, Adrian Zubarev  
> wrote:
> 
> Wasn’t Joe Groff and Daniel Duan proposing anonymous enum cases in some of 
> the early draft of the ‘Normalize Enum Case Representation’ proposal? 
> 
> Maybe it’s time to revive that topic.
> 
> Matthew Johnson has also some interesting ideas in hist gist: 
> https://gist.github.com/anandabits/5b7f8e3836387e893e3a1197a4bf144d#structural-unions
>  
> As
>  far as I know that turns out to be equivalent to the commonly rejected 
> feature.  :)
> 
> 
> 
> 
> Am 18. August 2017 um 21:08:22, Robert Bennett via swift-evolution 
> (swift-evolution@swift.org ) schrieb:
> 
>> The better solution would be to allow the creation of new enums from the 
>> union of existing enums, which was proposed recently.
>> 
>> On Aug 18, 2017, at 2:36 PM, John McCall via swift-evolution 
>> > wrote:
>> 
>> >> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>> >> > wrote:
>> >> The typed throws discussion brought me back to an old thought.
>> >> 
>> >> I would really like to see a new structural type, similar to tuples, 
>> >> which act as an anonymous enum. These would actually be a distinct type 
>> >> from enums (not sure what to call them), in the same way that structs and 
>> >> tuples are different. They would have a very similar syntax to enums 
>> >> though, so they would be easy to learn.
>> > 
>> > This is the commonly-rejected "Disjunctions in type constraints" feature.
>> > 
>> > John.
>> > 
>> >> 
>> >> There would be two major difference from enums:
>> >> 
>> >> 1) Because they are structural, they can’t have associated functions or 
>> >> extensions
>> >> 
>> >> 2) They can concatenate with one another freely 
>> >> 
>> >> For example:
>> >> 
>> >> func foo( speed: .slow | .med | .fast ){
>> >> bar(speed: speed)
>> >> }
>> >> 
>> >> func bar(speed: .slow | .med | .fast | .ludicrous) {
>> >> //but we couldn't call foo here because it doesn’t take .ludicrous
>> >> }
>> >> 
>> >> Each case is it’s own mini-type in a way. One ‘.slow’ is equivalent to 
>> >> any ‘.slow’ (even one from a regular enum). Essentially, it is a loosely 
>> >> bound group of cases, and type checking just means seeing if the 
>> >> list/value being passed is a subset of the list of possible cases.
>> >> 
>> >> I’d also like to see sugar for quick conversion from normal Swift enums:
>> >> 
>> >> enum Speed {
>> >> case slow
>> >> case med
>> >> case fast
>> >> }
>> >> 
>> >> func foo(speed: Speed | .ludicrous) {
>> >> //we can’t call any functions/extensions of Speed, just like we can’t 
>> >> call a func from int on (Int, Int) 
>> >> }
>> >> 
>> >> In the above case, Speed gets converted via sugar to “.speed(Speed)” and 
>> >> then gets concatenated with .ludicrous. Ideally, it would have the added 
>> >> ability to truly convert to ".slow | .med | .fast | .ludicrous” when 
>> >> passed to something that doesn’t know about Speed:
>> >> 
>> >> func foo(speed: Speed | .ludicrous) {
>> >> switch speed {
>> >> case .speed(let s): //Do something with the Speed value
>> >> case .ludicrous: //Do something ludicrous
>> >> } 
>> >> bar(speed: speed) //This can convert to pass by unwrapping Speed to a bag 
>> >> of cases
>> >> }
>> >> 
>> >> func bar(speed: .slow | .med | .fast | .ludicrous) {
>> >> switch speed {
>> >> case .slow: //
>> >> case .med: //
>> >> case .fast: //
>> >> case .ludicrous: //
>> >> }
>> >> //We can’t reference Speed above because we just passed a bag of 
>> >> potential cases
>> >> }
>> >>  
>> >> 
>> >> The end result here is that in addition to building one-off enums 
>> >> quickly, it lets us concatenate and extend enums for use in a limited 
>> >> scope. I don’t know about you, but I run into the situation of “I want 
>> >> exactly this enum, but with one extra case” all the time.
>> >> 
>> >> I don’t know if we want typed throws, but this type of quick 
>> >> concatability would be very useful for adding/merging potential errors. 
>> >> With the same sugar used on Speed above, it would also allow something 
>> >> similar to Union types, but without the most of the implementation 
>> >> headache that would cause. You can take in multiple types, and you get 
>> >> back something you can switch on to recover the type which was passed:
>> >> 
>> >> func myFakeUnion(_ intOrStr: Int | String){
>> >> switch intOrStr {
>> >> case .int(let i): //Do something with int
>> >> case .string(let s): //Do something with string
>> >> }
>> >> } 
>> >> 
>> >> myFakeUnion(12) //Sugar!
>> >> myFakeUnion(.string(“Hey”)) //This works too
>> >> 
>> >> 
>> >> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in 
>> >> Swift. I am not sure what the best syntax would be, but it would 
>> 

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

2017-08-18 Thread Thomas via swift-evolution

> On 18 Aug 2017, at 21:11, Joe Groff  wrote:
> 
> 
>> On Aug 18, 2017, at 11:57 AM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> I think that awaiting on the result of an actor method ends up being pretty 
>> similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
>> That said, my understanding is that thread explosion in GCD happens whenever 
>> something blocks a GCD thread, not when it politely yields control back to 
>> GCD.  Am I misunderstanding what you mean.
> 
> dispatch_sync isn't quite the ideal way of thinking about it, since it will 
> block the calling context, and as you note this would potentially deadlock 
> the current thread if an actor invokes one of its own methods. This isn't a 
> desirable or fundamentally necessary pitfall, since really, the caller actor 
> is suspending in wait simultaneously with the callee actor taking control. 
> This is more like a "tail-dispatch_async" kind of operation, where you don't 
> really want the calling context to block, but you still want to be able to 
> reuse the current thread since it'll be immediately freed up by blocking on 
> the async operation. That's something we could conceivably build into runtime 
> support for this model.

You seem to imply we are able to jump on the callee actor queue immediately, 
but the queue may not be available (the actor could be processing another 
message). So I'm not sure how it goes in term of reusing the same thread, maybe 
there's some clever trick to do this if it can be determined that the queue is 
immediately available. But using dispatch_sync() wouldn't work for me as it 
would potentially block the caller GCD thread and that could end up with thread 
explosion.

Thomas

___
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-18 Thread Chris Lattner via swift-evolution

> On Aug 17, 2017, at 11:33 PM, Brent Royal-Gordon  
> wrote:
> 
>> On Aug 17, 2017, at 3:24 PM, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> 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
> 
> 
> I think you're selecting the right approaches and nailing many of the 
> details, but I have a lot of questions and thoughts. A few notes before I 
> start:

Thanks!

> ## Dispatching back to the original queue
> 
> You correctly identify one of the problems with completion blocks as being 
> that you can't tell which queue the completion will run on, but I don't think 
> you actually discuss a solution to that in the async/await section. Do you 
> think async/await can solve that? How?  Does GCD even have the primitives 
> needed? (`dispatch_get_current_queue()` was deprecated long ago and has never 
> been available in Swift.)
> 

Async/await does not itself solve this - again think of async/await as sugar 
for completion handlers.  However, a follow-on to this proposal would be 
another proposal that describes how existing ObjC completion handlers are 
imported.  It would be surely controversial and is possibly unwise, but we 
could build magic into the thunks for those. This is described here:
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#fix-queue-hopping-objective-c-completion-handlers

Iff it were a good idea to do this, we can work with the GCD folks to figure 
out the best implementation approach, including potentially new API.

> ## Error handling
> 
> Do you imagine that `throws` and `async` would be orthogonal to one another? 
> If so, I suspect that we could benefit from adding typed `throws` and making 
> `Never` a subtype of `Error`, which would allow us to handle this through the 
> generics system.

Great question, I explore some of it here:
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#alternate-syntax-options
 


> (Also, I notice that a fire-and-forget message can be thought of as an 
> `async` method returning `Never`, even though the computation *does* 
> terminate eventually. I'm not sure how to handle that, though)

Yeah, I think that actor methods deserve a bit of magic:

- Their bodies should be implicitly async, so they can call async methods 
without blocking their current queue or have to use beginAsync.
- However, if they are void “fire and forget” messages, I think the caller side 
should *not* have to use await on them, since enqueuing the message will not 
block.

If the actor method throws an error or returns a value, then yes, you'd have to 
await.

> ## Interop, again
> 
> There are a few actor-like types in the frameworks—the WatchKit UI classes 
> are the clearest examples—but I'm not quite worried about them. What I'm more 
> concerned with is how this might interoperate with Cocoa delegates. Certain 
> APIs, like `URLSession`, either take a delegate and queue or take a delegate 
> and call it on arbitrary queues; these seem like excellent candidates for 
> actor-ization, especially when the calls are all one-way. But that means we 
> need to be able to create "actor protocols" or something. It's also hard to 
> square with the common Cocoa (anti?)pattern of implementing delegate 
> protocols on a controller—you would want that controller to also be an actor.
> 
> I don't have any specific answers here—I just wanted to point this out as 
> something we should consider in our actor design.

As part of the manifesto, I’m not proposing that existing APIs be “actorized”, 
though that is a logical thing to look into once the basic model is nailed down.

> ## Value-type annotation
> 
> The big problem I see with your `ValueSemantical` protocol is that developers 
> are very likely to abuse it. If there's a magic "let this get passed into 
> actors" switch, programmers will flip it for types that don't really qualify; 
> we don't want that switch to have too many other effects.

I agree.  That is one reason that I think it is important for it to have a 
(non-defaulted) protocol requirement.  Requiring someone to implement some code 
is a good way to get them to think about the operation… at least a little bit.  
That said, the design does not try to *guarantee* memory safety, so there will 
always be an opportunity for error.

>  I also worry that the type behavior of a protocol is a bad fit for 
> `ValueSemantical`. Retroactive conformance to `ValueSemantical` is almost 
> certain to be an unprincipled hack; subclasses can very easily lose the 
> value-semantic behavior of their superclasses, but almost certainly can't 
> have value semantics unless their superclasses do. And yet having 
> `ValueSemantical` conformance somehow be uninherited would destroy 

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

2017-08-18 Thread Chris Lattner via swift-evolution

> On Aug 18, 2017, at 8:13 AM, Johannes Weiß  wrote:
> 
> Hi Chris & swift-evo,
> 
> (Given the already lengthy thread I tried to separate my points and keep them 
> reasonably short to allow people to skip points they don't care about. I'm 
> very happy to expand on the points.)
> 
> Thanks very much for writing up your thoughts/proposal, I've been waiting to 
> see the official kick-off for the concurrency discussions :).
> 
> I) Let's start with the async/await proposal. Personally I think this is the 
> right direction for Swift given the reality that we need to interface with 
> incredibly large existing code-bases and APIs. Further thoughts:

I think these points have been covered upthread, I’ll focus on the remaining 
topics:

> II) the actor model part
> 
> -  Erlang runtime and the actor model go hand in hand 
> I really like the Erlang actor model but I don't think it can be separated 
> from Erlang's runtime. The runtime offers green threads (which allow an actor 
> to block without blocking an OS thread) and prevents you from sharing memory 
> (which makes it possible to kill any actor at any point and still have a 
> reliable system). I don't see these two things happening in Swift. To a 
> lesser extend these issues are also present in Scala/Akka, the mitigate some 
> of the problems by having Akka Streams. Akka Streams are important to 
> establish back-pressure if you have faster producers than consumers. Note 
> that we often can't control the producer, they might be on the other side of 
> a network connection. So it's often very important to not read the available 
> bytes to communicate to the kernel that we can't consumes bytes that fast. If 
> we're networking with TCP the kernel can then use the TCP flow-control to 
> signal to the other side that they better slow down (or else packets will be 
> dropped and then need to be resent later).

Makes sense.   The design I outline does talk about how to get to effective 
elimination of shared mutable state, so the reliability piece should work.  As 
per greenthreads, I’m intentionally not getting into the runtime design, 
because there are lots of options and I’m not the best person to drive that 
discussion.

> -  regarding fatal failure in actors
> in the server world we need to be able to accept hundreds of thousands 
> (millions) of connections at the same time. There are quite a few cases where 
> these connections are long-lived and paused for most of the the time. So I 
> don't really see the value in introducing a 'reliable' actor model where the 
> system stops accepting new connections if one actor fatalError'd and then 
> 'just' finishes up serving the existing connections.

This was one example of how to handle errors, not meant to be the only 
possibility.

> So I believe there are only two possible routes: 1) treat it like C/C++ and 
> make sure your code doesn't fatalError or the whole process blows up (what we 
> have right now) 2) treat it like Erlang and let things die. IMHO Erlang 
> wouldn't be successful if actors couldn't just die or couldn't be linked. 
> Linking propagates failures to all linked processes. A common thing to do is 
> to 1) spawn a new actor 2) link yourself to the newly spawned actor 3) send a 
> message to that actor and at some point eventually await a reply message sent 
> by the actor spawned earlier. As you mentioned in the writeup it is a problem 
> if the actor doesn't actually reply which is why in Erlang you'd link them. 
> The effect is that if the actor we spawned dies, any linked actor will die 
> too which will the propagate the error to an appropriate place. That allows 
> the programmer to control where an error should propagate too. I realise I'm 
> doing a poor job in explaining what is best explained by documentation around 
> Erlang: supervision [1] and the relationship between what Erlang calls a 
> process (read 'actor') and errors [2].

Agreed.  I’m a fan of the “just let them die” approach, along with providing 
notification out when it happens (so something out of band can handle it).  
That said, there is the problem of cleanup of the actor.  If failure is 
frequent, then you will want to be able to restart the process at some point in 
time.

> - ♨️ OS threads and actors
> as you mention, the actor model only really works if you can spawn lots of 
> them, so it's very important to be able to run hundreds of thousands of them 
> on a number of OS threads pretty much equal to your number of cores. That's 
> only straightforward if there are no (OS thread) blocking operations or at 
> least it's really obvious what blocks and what doesn't. And that's not the 
> case in Swift today and with GCD you really feel that pain. GCD does spawn 
> threads for you and has a rather arbitrary limit of 64 OS threads (by default 
> on macOS). That is too many for a very scalable server application but too 
> few to just tolerate blocking APIs.

Agreed.

-Chris


Re: [swift-evolution] [Pitch] Improve `init(repeating:count)`

2017-08-18 Thread Taylor Swift via swift-evolution
On Fri, Aug 18, 2017 at 1:23 PM, Erica Sadun  wrote:

> I want to avoid breaking math.
>

it’s not that deep,,, the `for _ in 0 ..< n` loop is exactly the same thing
except more verbose. In fact, that’s how your proposed `
Array.init(count:generator:)` would be implemented. But I don’t see anyone
saying we should get rid of the underscore pattern or `@discardableResult`,,
so…
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-08-18 Thread Joe Groff via swift-evolution

> On Aug 17, 2017, at 11:53 PM, Jan Tuitman via swift-evolution 
>  wrote:
> 
> Hi,
> 
> 
> After reading Chris Lattners proposal for async/await I wonder if the 
> proposal has any way to cancel outstanding tasks.
> 
> I saw these two:
> 
> @IBAction func buttonDidClick(sender:AnyObject) {
>  // 1
>  beginAsync {
>// 2
>let image = await processImage()
>imageView.image = image
>  }
>  // 3
> } 
> 
> 
> And:
> 
> /// Shut down the current coroutine and give its memory back to the
> /// shareholders.
> func abandon() async -> Never {
>  await suspendAsync { _ = $0 }
> }
> 
> 
> Now, if I understand this correctly, the second thing is abandoning the task 
> from the context of the task by basically preventing the implicit callback of 
> abandon() to ever be called.
> 
> But I don't see any way how the beginAsync {} block can be canceled after a 
> certain amount of time by the synchronous thread/context that is running at 
> location //3

This is not something the proposal aims to support, and as you noted, abrupt 
cancellation from outside a thread is not something you should generally do, 
and which is not really possible to do robustly with cooperatively-scheduled 
fibers like the coroutine proposal aims to provide. The section above is making 
the factual observation that, in our model, a coroutine once suspended can end 
up being dropped entirely by releasing all references to its continuation, and 
discusses the impact that possibility has on the model. This shouldn't be 
mistaken for proper cancellation support; as David noted, that's something you 
should still code explicit support for if you need it.

-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-18 Thread Chris Lattner via swift-evolution
On Aug 18, 2017, at 11:56 AM, David Beck  wrote:
> ## Conversion of imported Objective-C APIs
> 
> One issue I see with the importer is that the conventions for callbacks 
> aren’t as strict as NSError ** methods were. For instance, URLSession 
> completion blocks include response, data and error, all of which are 
> optionals. The response is almost always present, even if there was an error. 
> But there is no way to know that from the ObjC type system, and no way to 
> represent a throwing function that also returns metadata on error in Swift.

Sure, the default would be to import these as just a bunch of optionals.  
Something better could be done on a case by case basis (in overlays) though.

> 
> How should we represent dataTask(with:completion:)?

Someone else brought this up.  The most conservative thing is to leave it as a 
completion handler, and only transform void-returning ObjC methods.

> ## Actors
> 
> I fail to see the benefit of adding an entirely new construct for the actor 
> model. It seems like access control, value semantics, and dispatch queues 
> largely fill this need already, and the implimentation of an actor wouldn't 
> be so complicated currently that it needs a compiler feature to ensure a 
> correct implimentation.

It really comes down to whether you think elimination of shared mutable state 
is worth it, and if you think that having a higher level answer for concurrency 
is worth it.  Reasonable people can differ on this, and I expect opinions to 
vary, because GCD and other existing things are pretty good.  I think we can 
aim higher though.

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 12:05 PM, Joe Groff  wrote:
> 
> 
>> On Aug 17, 2017, at 9:58 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson >> > wrote:
>>> One related topic that isn’t discussed is type errors.  Many third party 
>>> libraries use a Result type with typed errors.  Moving to an async / await 
>>> model without also introducing typed errors into Swift would require giving 
>>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>>> is the right time to tackle typed errors as well.  I would be happy to help 
>>> with design and drafting a proposal but would need collaborators on the 
>>> implementation side.
>> 
>> Typed throws is something we need to settle one way or the other, and I 
>> agree it would be nice to do that in the Swift 5 cycle.
> 
> My view of this is the opposite of Matthew's—the canonical examples of things 
> for which untyped errors are the "right thing" due to unbounded failure 
> modes, such as file IO, IPC, network communication, etc. are almost all 
> things you also want to be 'async', so I don't think async makes typed 
> 'throws' any more urgent to consider. As we've discussed in person, I feel 
> like there's a strong argument to be made that 'async' should always imply 
> untyped 'throws’.

That’s interesting. Have you looked at how people are using `Result` in current third party libraries that do async stuff?

Even when failure modes are unbounded it can still be very useful to categorize 
the kinds of errors that might happen and encourage thoughtfulness about 
recovery in a way that an untyped `Error` does not.  Maybe types are not the 
best way to solve that problem but I haven’t seen any alternative that looks 
promising.

> 
> -Joe

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Michael Ilseman via swift-evolution
Wouldn’t switching from `async` to `async throws` be both a source and ABI 
break for libraries? If so, there is a library evolution argument to `async` 
also encompassing throws as a reasonable default. It's likely that the 
non-throwing-ness of many `async` operations is an artifact of the initial 
implementation rather than deliberate design. Using the more verbose 
`async(non-throwing)` (or even some other keyword `generator|yielding|…`) makes 
it a deliberate API decision rather than an accidental omission.



> On Aug 18, 2017, at 10:05 AM, Joe Groff via swift-evolution 
>  wrote:
> 
> 
>> On Aug 17, 2017, at 9:58 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson >> > wrote:
>>> One related topic that isn’t discussed is type errors.  Many third party 
>>> libraries use a Result type with typed errors.  Moving to an async / await 
>>> model without also introducing typed errors into Swift would require giving 
>>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>>> is the right time to tackle typed errors as well.  I would be happy to help 
>>> with design and drafting a proposal but would need collaborators on the 
>>> implementation side.
>> 
>> Typed throws is something we need to settle one way or the other, and I 
>> agree it would be nice to do that in the Swift 5 cycle.
> 
> My view of this is the opposite of Matthew's—the canonical examples of things 
> for which untyped errors are the "right thing" due to unbounded failure 
> modes, such as file IO, IPC, network communication, etc. are almost all 
> things you also want to be 'async', so I don't think async makes typed 
> 'throws' any more urgent to consider. As we've discussed in person, I feel 
> like there's a strong argument to be made that 'async' should always imply 
> untyped 'throws'.
> 
> -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


Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 4:40 AM, Gwendal Roué  wrote:
> Hello all,
> 
> I'm also on the "side" of untyped errors, but I can imagine how other 
> developers may like a stricter error hierarchy. It surely fits some 
> situations.
> 
> Enter Result and Result:
> 
> Since Swift "native" errors don't fit well with asynchronous APIs, various 
> ways to encapsulate them have emerged, most of them eventually relying on 
> some kind of variant of those `Result` type:
> 
>   // Untyped errors
>   enum Result {
>   case success(T)
>   case failure(Error)
>   }
>   
>   // Typed errors
>   enum Result {
>   case success(T)
>   case failure(E)
>   }
> 
> The first Result fits well people who like untyped errors. And Result E> fits people who prefer typed errors. Result is objectively closer to 
> the "spirit" of Swift 2-4. Yet Result has the right to live as well.
> 
> When Swift 5 brings sugar syntax around async/await/etc, most needs for 
> Result will naturally vanish.
> 
> However, the need for Result will remain. The debate about "typed 
> throws", for me, sums up to this question: will the typed folks be able to 
> take profit from the syntax sugar brought by async/await/etc of Swift 5? Or 
> will they have to keep on carrying Result with them?

If I understand correctly, the people really attached to Result often use 
it as a normal result type rather than using the built-in error machinery at 
all.  That is, of course, their right.  If they're doing that, then they can 
have an async function that does that just as well as they can have a non-async 
function.  However, "async" implying "throws" would undermine them to a 
significant extent.

John.

> 
> Gwendal Roué
> 
> 
> 
>> Le 18 août 2017 à 10:23, John McCall via swift-evolution 
>> > a écrit :
>> 
>>> On Aug 18, 2017, at 3:28 AM, Charlie Monroe >> > wrote:
 On Aug 18, 2017, at 8:27 AM, John McCall via swift-evolution 
 > wrote:
> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
> > wrote:
> Splitting this off into its own thread:
> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson > > wrote:
>> One related topic that isn’t discussed is type errors.  Many third party 
>> libraries use a Result type with typed errors.  Moving to an async / 
>> await model without also introducing typed errors into Swift would 
>> require giving up something that is highly valued by many Swift 
>> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
>> well.  I would be happy to help with design and drafting a proposal but 
>> would need collaborators on the implementation side.
> 
> Typed throws is something we need to settle one way or the other, and I 
> agree it would be nice to do that in the Swift 5 cycle.
> 
> For the purposes of this sub-discussion, I think there are three kinds of 
> code to think about: 
> 1) large scale API like Cocoa which evolve (adding significant 
> functionality) over the course of many years and can’t break clients. 
> 2) the public API of shared swiftpm packages, whose lifecycle may rise 
> and fall - being obsoleted and replaced by better packages if they 
> encounter a design problem.  
> 3) internal APIs and applications, which are easy to change because the 
> implementations and clients of the APIs are owned by the same people.
> 
> These each have different sorts of concerns, and we hope that something 
> can start out as #3 but work its way up the stack gracefully.
> 
> Here is where I think things stand on it:
> - There is consensus that untyped throws is the right thing for a large 
> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
> throws is introduced, Apple is unlikely to adopt it in their APIs for 
> this reason.
> - There is consensus that untyped throws is the right default for people 
> to reach for for public package (#2).
> - There is consensus that Java and other systems that encourage lists of 
> throws error types lead to problematic APIs for a variety of reasons.
> - There is disagreement about whether internal APIs (#3) should use it.  
> It seems perfect to be able to write exhaustive catches in this 
> situation, since everything in knowable. OTOH, this could encourage abuse 
> of error handling in cases where you really should return an enum instead 
> of using throws.
> - Some people are concerned that introducing typed throws 

Re: [swift-evolution] typed throws

2017-08-18 Thread Joe Groff via swift-evolution

> On Aug 18, 2017, at 11:09 AM, John McCall via swift-evolution 
>  wrote:
> 
>> I think you're right that wrapping errors is tightly related to an effective 
>> use of typed errors.  You can do a reasonable job without language support 
>> (as has been discussed on the list in the past).  On the other hand, if 
>> we're going to introduce typed errors we should do it in a way that 
>> *encourages* effective use of them. My opinion is that encouraging effect 
>> use means categorizing (wrapping) errors without requiring any additional 
>> syntax beyond the simple `try` used by untyped errors.  In practice, this 
>> means we should not need to catch and rethrow an error if all we want to do 
>> is categorize it.  Rust provides good prior art in this area.
> 
> Yes, the ability to translate errors between domains is definitely something 
> we could work on, whether we have typed errors or not.

The Rust approach of automatically wrapping errors when you "cross domains", so 
to speak, has the disadvantage you've observed before that the layers of 
wrapping can obscure the structure of the underlying error when you're trying 
to ferret out and handle a particular form of failure mode. An alternative 
approach that embraces the open nature of errors could be to represent domains 
as independent protocols, and extend the error types that are relevant to that 
domain to conform to the protocol. That way, you don't obscure the structure of 
the underlying error value with wrappers. If you expect to exhaustively handle 
all errors in a domain, well, you'd almost certainly going to need to have a 
fallback case in your wrapper type for miscellaneous errors, but you could 
represent that instead without wrapping via a catch-all, and as?-casting to 
your domain protocol with a ??-default for errors that don't conform to the 
protocol. For example, instead of attempting something like thi
 s:

enum DatabaseError {
  case queryError(QueryError)
  case ioError(IOError)
  case other(Error)

  var errorKind: String {
switch self {
  case .queryError(let q): return "query error: \(q.query)"
  case .ioError(let i): return "io error: \(i.filename)"
  case .other(let e): return "\(e)"
}
  }
}

func queryDatabase(_ query: String) throws /*DatabaseError*/ -> Table

do {
  queryDatabase("delete * from users")
} catch let d as DatabaseError {
  os_log(d.errorKind)
} catch {
  fatalError("unexpected non-database error")
}

You could do this:

protocol DatabaseError {
  var errorKind: String { get }
}

extension QueryError: DatabaseError {
  var errorKind: String { return "query error: \(q.query)" }
}
extension IOError: DatabaseError {
  var errorKind: String ( return "io error: \(i.filename)" }
}

extension Error {
  var databaseErrorKind: String {
return (error as? DatabaseError)?.errorKind ?? "unexpected non-database 
error"
  }
}

func queryDatabase(_ query: String) throws -> Table

do {
  queryDatabase("delete * from users")
} catch {
  os_log(error.databaseErrorKind)
}

-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-18 Thread Joe Groff via swift-evolution

> On Aug 18, 2017, at 11:57 AM, Chris Lattner via swift-evolution 
>  wrote:
> 
> I think that awaiting on the result of an actor method ends up being pretty 
> similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
> That said, my understanding is that thread explosion in GCD happens whenever 
> something blocks a GCD thread, not when it politely yields control back to 
> GCD.  Am I misunderstanding what you mean.

dispatch_sync isn't quite the ideal way of thinking about it, since it will 
block the calling context, and as you note this would potentially deadlock the 
current thread if an actor invokes one of its own methods. This isn't a 
desirable or fundamentally necessary pitfall, since really, the caller actor is 
suspending in wait simultaneously with the callee actor taking control. This is 
more like a "tail-dispatch_async" kind of operation, where you don't really 
want the calling context to block, but you still want to be able to reuse the 
current thread since it'll be immediately freed up by blocking on the async 
operation. That's something we could conceivably build into runtime support for 
this model.

-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-18 Thread David Beck via swift-evolution
An argument could be made that throws should precede the function
definition, but since that ship has sailed, async should probably join it
at the end, since it modifies the way the function returns. In other words,
async doesn't change how the method gets run, but how and when it returns.

On Thu, Aug 17, 2017 at 11:34 PM, Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:

> > On Aug 17, 2017, at 3:24 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > 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
>
>
> I think you're selecting the right approaches and nailing many of the
> details, but I have a lot of questions and thoughts. A few notes before I
> start:
>
> * I only did one pass through this, so I probably missed or misunderstood
> some things. Sorry.
> * I think the document may have evolved since I started reading, so some
> of this may be out of date.
> * I haven't yet read the rest of the thread—this email is already long
> enough.
> * I have a lot of experience with Cocoa-style callback-based concurrency,
> a little bit (unfortunately) with Javascript Promises, and basically none
> with async/await. I've never worked with a language that formally supported
> actors, although I've used similar patterns in Swift and Objective-C.
>
> # async/await
>
> I like the choice of async/await, and I agree that it's pretty much where
> mainstream languages have ended up. But there are a few things you seem to
> gloss over. You may simply have decided those details were too specific for
> such a sweeping manifesto, but I wanted to point them out in case you
> missed them.
>
> ## Dispatching back to the original queue
>
> You correctly identify one of the problems with completion blocks as being
> that you can't tell which queue the completion will run on, but I don't
> think you actually discuss a solution to that in the async/await section.
> Do you think async/await can solve that? How? Does GCD even have the
> primitives needed? (`dispatch_get_current_queue()` was deprecated long
> ago and has never been available in Swift.)
>
> Or do you see this as the province of actors? If so, how does that work?
> Does every piece of code inherently run inside one actor or another? Or
> does the concurrency system only get you on the right queue if you
> explicitly use actors? Can arbitrary classes "belong to" an actor, so that
> e.g. callbacks into a view controller inherently go to the main queue/actor?
>
> (If you *do* need actors to get sensible queue behavior, I'm not the
> biggest fan of that; we could really use that kind of thing in many, many
> places that aren't actors.)
>
> ## Delayed `await`
>
> Most languages I've seen with async/await seem to allow you to delay the
> `await` call to do parallel work, but I don't see anything similar in your
> examples. Do you envision that happening? What's the type of the
> intermediate value, and what can you do with it? Can you return it to a
> caller?
>
> ## Error handling
>
> Do you imagine that `throws` and `async` would be orthogonal to one
> another? If so, I suspect that we could benefit from adding typed `throws`
> and making `Never` a subtype of `Error`, which would allow us to handle
> this through the generics system.
>
> (Also, I notice that a fire-and-forget message can be thought of as an
> `async` method returning `Never`, even though the computation *does*
> terminate eventually. I'm not sure how to handle that, though)
>
> ## Legacy interop
>
> Another big topic I don't see discussed much is interop with existing
> APIs. I think it's really important that we expose existing
> completion-based Cocoa APIs with async/await. This ideally means automatic
> translation, much like we did with errors. Moreover, I think we probably
> need to apply this translation to Swift 4 libraries when you're using them
> from Swift 5+ (assuming this makes Swift 5).
>
> ## Implementation
>
> The legacy interop requirement tends to lean towards a particular model
> where `await` calls are literally translated into completion blocks passed
> to the original function. But there are other options, like generating a
> wrapper that translates calls with completions into calls returning
> promises, and `await` is translated into a promise call. Or we could do
> proper continuations, but as I understand it, that has impacts further up
> the call stack, so I'm not sure how you'd make that work when some of the
> calls on the stack are from other languages.
>
> # Actors
>
> I haven't used actors before, but they look like a really promising model,
> much better than Go's channels. I do have a couple of concerns, though.
>
> ## Interop, again
>
> There are a few actor-like types in the frameworks—the WatchKit UI classes
> are the clearest examples—but I'm not quite worried about them. What I'm

Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 1:09 PM, John McCall  wrote:
> 
>> 
>> On Aug 18, 2017, at 10:19 AM, Matthew Johnson  wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
>> 
 On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
  wrote:
 Splitting this off into its own thread:
 
> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  
> wrote:
> One related topic that isn’t discussed is type errors.  Many third party 
> libraries use a Result type with typed errors.  Moving to an async / 
> await model without also introducing typed errors into Swift would 
> require giving up something that is highly valued by many Swift 
> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
> well.  I would be happy to help with design and drafting a proposal but 
> would need collaborators on the implementation side.
 
 Typed throws is something we need to settle one way or the other, and I 
 agree it would be nice to do that in the Swift 5 cycle.
 
 For the purposes of this sub-discussion, I think there are three kinds of 
 code to think about: 
 1) large scale API like Cocoa which evolve (adding significant 
 functionality) over the course of many years and can’t break clients. 
 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
 fall - being obsoleted and replaced by better packages if they encounter a 
 design problem.  
 3) internal APIs and applications, which are easy to change because the 
 implementations and clients of the APIs are owned by the same people.
 
 These each have different sorts of concerns, and we hope that something 
 can start out as #3 but work its way up the stack gracefully.
 
 Here is where I think things stand on it:
 - There is consensus that untyped throws is the right thing for a large 
 scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
 throws is introduced, Apple is unlikely to adopt it in their APIs for this 
 reason.
 - There is consensus that untyped throws is the right default for people 
 to reach for for public package (#2).
 - There is consensus that Java and other systems that encourage lists of 
 throws error types lead to problematic APIs for a variety of reasons.
 - There is disagreement about whether internal APIs (#3) should use it.  
 It seems perfect to be able to write exhaustive catches in this situation, 
 since everything in knowable. OTOH, this could encourage abuse of error 
 handling in cases where you really should return an enum instead of using 
 throws.
 - Some people are concerned that introducing typed throws would cause 
 people to reach for it instead of using untyped throws for public package 
 APIs.
>>> 
>>> Even for non-public code.  The only practical merit of typed throws I have 
>>> ever seen someone demonstrate is that it would let them use contextual 
>>> lookup in a throw or catch.  People always say "I'll be able to 
>>> exhaustively switch over my errors", and then I ask them to show me where 
>>> they want to do that, and they show me something that just logs the error, 
>>> which of course does not require typed throws.  Every.  Single.  Time.
>> 
>> I agree that exhaustive switching over errors is something that people are 
>> extremely likely to actually want to do.  I also think it's a bit of a red 
>> herring.  The value of typed errors is *not* in exhaustive switching.  It is 
>> in categorization and verified documentation.
>> 
>> Here is a concrete example that applies to almost every app.  When you make 
>> a network request there are many things that could go wrong to which you may 
>> want to respond differently:
>> * There might be no network available.  You might recover by updating the UI 
>> to indicate that and start monitoring for a reachability change.
>> * There might have been a server error that should eventually be resolved 
>> (500).  You might update the UI and provide the user the ability to retry.
>> * There might have been an unrecoverable server error (404).  You will 
>> update the UI.
>> * There might have been a low level parsing error (bad JSON, etc).  Recovery 
>> is perhaps similar in nature to #2, but the problem is less likely to be 
>> resolved quickly so you may not provide a retry option.  You might also want 
>> to do something to notify your dev team that the server is returning JSON 
>> that can't be parsed.
>> * There might have been a higher-level parsing error (converting JSON to 
>> model types).  This might be treated the same as bad JSON.  On the other 
>> hand, depending on the specifics of the app, you might take an alternate 
>> path that only parses the most essential model data in 

Re: [swift-evolution] pure functions

2017-08-18 Thread Chris Lattner via swift-evolution
Splitting this out from the concurrency thread:

> 
> On Aug 18, 2017, at 6:12 AM, Matthew Johnson  wrote:
>> On Aug 17, 2017, at 11:53 PM, Chris Lattner  wrote:
>> 
>>> In the manifesto you talk about restrictions on passing functions across an 
>>> actor message.  You didn’t discuss pure functions, presumably because Swift 
>>> doesn’t have them yet.  I imagine that if (hopefully when) Swift has 
>>> compiler support for verifying pure functions these would also be safe to 
>>> pass across an actor message.  Is that correct?
>> 
>> Correct.  The proposal is specifically/intentionally designed to be light on 
>> type system additions, but there are many that could make it better in 
>> various ways.  The logic for this approach is that I expect *a lot* of 
>> people will be writing mostly straight-forward concurrent code, and that 
>> goal is harmed by presenting significant type system hurdles for them to 
>> jump over, because that implies a higher learning curve.
>> 
>> This is why the proposal doesn’t focus on a provably memory safe system: If 
>> someone slaps “ValueSemantical” on a type that doesn’t obey, they will break 
>> the invariants of the system.  There are lots of ways to solve that problem 
>> (e.g. the capabilities system in Pony) but it introduces a steep learning 
>> curve.
>> 
>> I haven’t thought a lot about practically getting pure functions into Swift, 
>> because it wasn’t clear what problems it would solve (which couldn’t be 
>> solved another way).  You’re right though that this could be an interesting 
>> motivator. 
> 
> I can provide a concrete example of why this is definitely and important 
> motivator.  
> 
> My current project uses pure functions, value semantics and declarative 
> effects at the application level and moves as much of the imperative code as 
> possible (including effect handling) into library level code.  This is 
> working out really well and I plan to continue with this approach.  The 
> library level code needs the ability to schedule user code in the appropriate 
> context.  There will likely be some declarative ability for application level 
> code to influence the context, priority, etc, but it is the library that will 
> be moving the functions to the final context.  They are obviously not closure 
> literals from the perspective of the library.
> 
> Pure functions are obviously important to the semantics of this approach.  We 
> can get by without compiler verification, using documentation just as we do 
> for protocol requirements that can't be verified.  That said, it would be 
> pretty disappointing to have to avoid using actors in the implementation 
> simply because we can't move pure functions from one actor to another as 
> necessary.
> 
> To be clear, I am talking in the context of "the fullness of time".  It would 
> be perfectly acceptable to ship actors before pure functions.  That said, I 
> do think it's crucial that we eventually have the ability to verify pure 
> functions and move them around at will.

Right.  Pure functions are also nice when you care about thread safety, and 
there is a lot of work on this.  C has __attribute__((const)) and ((pure)) for 
example, c++ has constexpr, and many research languages have built full blown 
effects systems.

My principle concern is that things like this quickly become infectious: LOTS 
of things are pure functions, and requiring them all to be marked as such 
becomes a lot of boilerplate and conceptual overhead.  This is happening in the 
C++ community with constexpr for example.

The secondary concern is that you need to build out the model enough that you 
don’t prevent abstractions.  A pure function should be able to create an 
instance of a struct, mutate it (i.e. calling non-pure functions) etc.  This 
requires a non-trivial design, and as the design complexity creeps, you run the 
risk of it getting out of control.

-Chris

___
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-18 Thread Chris Lattner via swift-evolution

> On Aug 18, 2017, at 12:23 PM, Thomas  wrote:
> 
> 
>> On 18 Aug 2017, at 20:57, Chris Lattner  wrote:
>> 
>>> I'm a bit worried about the mention of dispatch_sync() here (although it 
>>> may just be there to illustrate the deadlock possibility). I know the actor 
>>> runtime implementation is not yet defined, but just wanted to mention that 
>>> dispatch_sync() will lead to problems such as this annoying thing called 
>>> thread explosion. This is why we currently cannot use properties in our 
>>> code (getters would require us to call dispatch_sync() and we want to avoid 
>>> that), instead we are writing custom async getters/setters with callback 
>>> blocks. Having async property getters would be pretty awesome.
>> 
>> I think that awaiting on the result of an actor method ends up being pretty 
>> similar (in terms of implementation and design tradeoffs) as dispatch_sync.  
>> That said, my understanding is that thread explosion in GCD happens whenever 
>> something blocks a GCD thread, not when it politely yields control back to 
>> GCD.  Am I misunderstanding what you mean.
> 
> disptach_sync() calls will cause the GCD thread to block (waiting for the 
> queue to be available). I'm pretty sure this causes libdispatch to spawn more 
> threads if needed (for example if dispatch_async() calls are made in other 
> parts of the program), up to thread explosion.

Ok, my misunderstanding.  That does make it a bad analogy, I’ll update the 
proposal.

-Chris

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


Re: [swift-evolution] pure functions

2017-08-18 Thread David Sweeris via swift-evolution

> On Aug 18, 2017, at 12:11, Chris Lattner via swift-evolution 
>  wrote:
> 
> Splitting this out from the concurrency thread:
> 
>> 
>>> On Aug 18, 2017, at 6:12 AM, Matthew Johnson  wrote:
 On Aug 17, 2017, at 11:53 PM, Chris Lattner  wrote:
 
 In the manifesto you talk about restrictions on passing functions across 
 an actor message.  You didn’t discuss pure functions, presumably because 
 Swift doesn’t have them yet.  I imagine that if (hopefully when) Swift has 
 compiler support for verifying pure functions these would also be safe to 
 pass across an actor message.  Is that correct?
>>> 
>>> Correct.  The proposal is specifically/intentionally designed to be light 
>>> on type system additions, but there are many that could make it better in 
>>> various ways.  The logic for this approach is that I expect *a lot* of 
>>> people will be writing mostly straight-forward concurrent code, and that 
>>> goal is harmed by presenting significant type system hurdles for them to 
>>> jump over, because that implies a higher learning curve.
>>> 
>>> This is why the proposal doesn’t focus on a provably memory safe system: If 
>>> someone slaps “ValueSemantical” on a type that doesn’t obey, they will 
>>> break the invariants of the system.  There are lots of ways to solve that 
>>> problem (e.g. the capabilities system in Pony) but it introduces a steep 
>>> learning curve.
>>> 
>>> I haven’t thought a lot about practically getting pure functions into 
>>> Swift, because it wasn’t clear what problems it would solve (which couldn’t 
>>> be solved another way).  You’re right though that this could be an 
>>> interesting motivator. 
>> 
>> I can provide a concrete example of why this is definitely and important 
>> motivator.  
>> 
>> My current project uses pure functions, value semantics and declarative 
>> effects at the application level and moves as much of the imperative code as 
>> possible (including effect handling) into library level code.  This is 
>> working out really well and I plan to continue with this approach.  The 
>> library level code needs the ability to schedule user code in the 
>> appropriate context.  There will likely be some declarative ability for 
>> application level code to influence the context, priority, etc, but it is 
>> the library that will be moving the functions to the final context.  They 
>> are obviously not closure literals from the perspective of the library.
>> 
>> Pure functions are obviously important to the semantics of this approach.  
>> We can get by without compiler verification, using documentation just as we 
>> do for protocol requirements that can't be verified.  That said, it would be 
>> pretty disappointing to have to avoid using actors in the implementation 
>> simply because we can't move pure functions from one actor to another as 
>> necessary.
>> 
>> To be clear, I am talking in the context of "the fullness of time".  It 
>> would be perfectly acceptable to ship actors before pure functions.  That 
>> said, I do think it's crucial that we eventually have the ability to verify 
>> pure functions and move them around at will.
> 
> Right.  Pure functions are also nice when you care about thread safety, and 
> there is a lot of work on this.  C has __attribute__((const)) and ((pure)) 
> for example, c++ has constexpr, and many research languages have built full 
> blown effects systems.
> 
> My principle concern is that things like this quickly become infectious: LOTS 
> of things are pure functions, and requiring them all to be marked as such 
> becomes a lot of boilerplate and conceptual overhead.  This is happening in 
> the C++ community with constexpr for example.

At a rough guess, how many of the stdlib's functions could realistically have 
their purity inferred?

If we define our semantics carefully enough, could we realistically make it so 
that "@pure" or "@impure" (or whatever) would simply be a note to the compiler, 
letting it skip that bit of analysis for the function in question?



> The secondary concern is that you need to build out the model enough that you 
> don’t prevent abstractions.  A pure function should be able to create an 
> instance of a struct, mutate it (i.e. calling non-pure functions) etc.  This 
> requires a non-trivial design, and as the design complexity creeps, you run 
> the risk of it getting out of control.

Did we ever get around to figuring which definition(s) of "pure" that we wanted 
to support, or did the discussion always get out of scope before we got that 
far? I know the issue's been brought up, but I don't recall if it was discussed 
enough to reach any conclusions.

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


Re: [swift-evolution] pure functions

2017-08-18 Thread Andrew Trick via swift-evolution

> On Aug 18, 2017, at 2:45 PM, David Sweeris via swift-evolution 
>  wrote:
> 
> If we define our semantics carefully enough, could we realistically make it 
> so that "@pure" or "@impure" (or whatever) would simply be a note to the 
> compiler, letting it skip that bit of analysis for the function in question?
> 
> 
> 
>> The secondary concern is that you need to build out the model enough that 
>> you don’t prevent abstractions.  A pure function should be able to create an 
>> instance of a struct, mutate it (i.e. calling non-pure functions) etc.  This 
>> requires a non-trivial design, and as the design complexity creeps, you run 
>> the risk of it getting out of control.
> 
> Did we ever get around to figuring which definition(s) of "pure" that we 
> wanted to support, or did the discussion always get out of scope before we 
> got that far? I know the issue's been brought up, but I don't recall if it 
> was discussed enough to reach any conclusions.

It became clear that we weren’t going to change Swift’s default semantics in 
the version 2/3 timeframe, and we made the effort to do sufficient whole-module 
analysis to make up for it. I see this primarily being a resilience issue in 
the future. Eventually I think we’ll want public APIs to be able to declare 
some level of statically enforced purity. We might even get some level of 
default guarantee as a way of “deprecating global var”. But that whole 
discussion has rightly been punted.

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Xiaodi Wu via swift-evolution
Joe Groff wrote:

An alternative approach that embraces the open nature of errors could be to
represent domains as independent protocols, and extend the error types that
are relevant to that domain to conform to the protocol. That way, you don't
obscure the structure of the underlying error value with wrappers. If you
expect to exhaustively handle all errors in a domain, well, you'd almost
certainly going to need to have a fallback case in your wrapper type for
miscellaneous errors, but you could represent that instead without wrapping
via a catch-all, and as?-casting to your domain protocol with a ??-default
for errors that don't conform to the protocol. For example, instead of
attempting something like this:

enum DatabaseError {
  case queryError(QueryError)
  case ioError(IOError)
  case other(Error)

  var errorKind: String {
switch self {
  case .queryError(let q): return "query error: \(q.query)"
  case .ioError(let i): return "io error: \(i.filename)"
  case .other(let e): return "\(e)"
}
  }
}

func queryDatabase(_ query: String) throws /*DatabaseError*/ -> Table

do {
  queryDatabase("delete * from users")
} catch let d as DatabaseError {
  os_log(d.errorKind)
} catch {
  fatalError("unexpected non-database error")
}

You could do this:

protocol DatabaseError {
  var errorKind: String { get }
}

extension QueryError: DatabaseError {
  var errorKind: String { return "query error: \(q.query)" }
}
extension IOError: DatabaseError {
  var errorKind: String ( return "io error: \(i.filename)" }
}

extension Error {
  var databaseErrorKind: String {
return (error as? DatabaseError)?.errorKind ?? "unexpected non-database
error"
  }
}

func queryDatabase(_ query: String) throws -> Table

do {
  queryDatabase("delete * from users")
} catch {
  os_log(error.databaseErrorKind)
}


On Fri, Aug 18, 2017 at 6:46 PM, Matthew Johnson 
wrote:

>
> On Aug 18, 2017, at 6:29 PM, Xiaodi Wu  wrote:
>
> On Fri, Aug 18, 2017 at 6:19 PM, Matthew Johnson 
> wrote:
>
>>
>> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>>
>>> Sent from my iPad
>>>
>>> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
>>>
>>> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>> >> Splitting this off into its own thread:
>>> >>
>>> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson 
>>> wrote:
>>> >>> One related topic that isn’t discussed is type errors.  Many third
>>> party libraries use a Result type with typed errors.  Moving to an async /
>>> await model without also introducing typed errors into Swift would require
>>> giving up something that is highly valued by many Swift developers.  Maybe
>>> Swift 5 is the right time to tackle typed errors as well.  I would be happy
>>> to help with design and drafting a proposal but would need collaborators on
>>> the implementation side.
>>> >>
>>> >> Typed throws is something we need to settle one way or the other, and
>>> I agree it would be nice to do that in the Swift 5 cycle.
>>> >>
>>> >> For the purposes of this sub-discussion, I think there are three
>>> kinds of code to think about:
>>> >> 1) large scale API like Cocoa which evolve (adding significant
>>> functionality) over the course of many years and can’t break clients.
>>> >> 2) the public API of shared swiftpm packages, whose lifecycle may
>>> rise and fall - being obsoleted and replaced by better packages if they
>>> encounter a design problem.
>>> >> 3) internal APIs and applications, which are easy to change because
>>> the implementations and clients of the APIs are owned by the same people.
>>> >>
>>> >> These each have different sorts of concerns, and we hope that
>>> something can start out as #3 but work its way up the stack gracefully.
>>> >>
>>> >> Here is where I think things stand on it:
>>> >> - There is consensus that untyped throws is the right thing for a
>>> large scale API like Cocoa.  NSError is effectively proven here.  Even if
>>> typed throws is introduced, Apple is unlikely to adopt it in their APIs for
>>> this reason.
>>> >> - There is consensus that untyped throws is the right default for
>>> people to reach for for public package (#2).
>>> >> - There is consensus that Java and other systems that encourage lists
>>> of throws error types lead to problematic APIs for a variety of reasons.
>>> >> - There is disagreement about whether internal APIs (#3) should use
>>> it.  It seems perfect to be able to write exhaustive catches in this
>>> situation, since everything in knowable. OTOH, this could encourage abuse
>>> of error handling in cases where you really should return an enum instead
>>> of using throws.
>>> >> - Some people are concerned that introducing typed throws would 

Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Greg Parker via swift-evolution

> On Aug 17, 2017, at 5:16 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Thu, Aug 17, 2017 at 6:46 PM, Taylor Swift  > wrote:
> I don’t think the “is this library functionality or standard library 
> functionality” argument is worth having, but if stdout and stdin are 
> first-class citizens in the Swift world, so should stderr.
> 
> As for bringing Foundation into the discussion, you can’t really talk about 
> Foundation without also talking about the mountains of problems that come 
> with the monolith pattern. But that’s a completely different conversation to 
> be had.
> 
> I'm not sure what you're getting at here, but I don't believe you've 
> addressed my question, which is: it's been firmly decided that I/O belongs in 
> Foundation, and Foundation does in fact offer such facilities--what is 
> missing from those facilities, and how can we fill it out?

Lots of I/O functionality is missing from Foundation. Foundation's design from 
time immemorial is that generally only relatively simple and high-level 
operations are available in Foundation itself, and if you want to do 
complicated or non-portable things then you are expected to drop down to POSIX 
or other C interfaces. That design works less well in Swift than it did in 
Objective-C because Swift's interface with C, especially low-level C, is often 
ugly.

Simple example: there is no way to access file information directly via 
NSFileHandle. You need to call NSFileHandle.fileDescriptor and pass that to  
fstat() or fcntl(). The NSFileHandle API in general is sparse and wholly 
inadequate for sophisticated I/O.


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


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


Re: [swift-evolution] SE-184 Improved Pointers

2017-08-18 Thread Andrew Trick via swift-evolution

> On Aug 15, 2017, at 9:47 PM, Taylor Swift via swift-evolution 
>  wrote:
> 
> Implementation is here: https://github.com/apple/swift/pull/11464 
> 
> 
> On Sat, Aug 12, 2017 at 8:23 PM, Taylor Swift  > wrote:
> I’ve revised the proposal based on what I learned from trying to implement 
> these changes. I think it’s worth tacking the existing methods that take 
> Sequences at the same time as this actually makes the design a bit simpler.
>  >
> 
> The previous version 
>  of this 
> document ignored the generic initialization methods on 
> UnsafeMutableBufferPointer and UnsafeMutableRawBufferPointer, leaving them to 
> be overhauled at a later date, in a separate proposal. Instead, this version 
> of the proposal leverages those existing methods to inform a more compact API 
> design which has less surface area, and is more future-proof since it 
> obviates the need to design and add another (redundant) set of 
> protocol-oriented pointer APIs later.
> 
> On Tue, Aug 8, 2017 at 12:52 PM, Taylor Swift  > wrote:
> Since Swift 5 just got opened up for proposals, SE-184 Improved Pointers is 
> ready for community review, and I encourage everyone to look it over and 
> provide feedback. Thank you!
>   
> >
> 


Would you mind adding a deallocate method to (nonmutable) 
UnsafePointer/UnsafeBufferPointer to take care of
[SR-3309](https://bugs.swift.org/browse/SR-3309 
)?

There’s simply nothing in the memory model that requires mutable memory for 
deallocation.

It fits right in with this proposal and hardly seems worth a separate one.

-Andy

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


Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Saagar Jha via swift-evolution
Just thought I’d link the previous thread on this topic: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023927.html
 
.
 I had promised to write a proposal for it back then, but never got around to 
doing it. Now that we’re out of the hectic Swift 3 timeframe, I can write a 
proposal and implementation for this, since it’s more likely to be accepted.

More broadly, however, I think a “Swiftication” of POSIX or libc is extremely 
necessary for anyone who’s not working with Foundation–and not everyone is! 
There are still parts of POSIX that are either 1. not a part of Foundation or 
2. part of Foundation/CoreFoundation but not in the open source Swift 
Foundation or CFLite (and hence not available on Linux). A big part of 
attracting newer Swift developers a moving away from the “Swift is for apps 
only” and the in my experience the need to drop down to UnsafePointer or errno 
just to use this API has been a big turn-off for programmers.

Saagar Jha

> On Aug 18, 2017, at 04:17, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Not “fundamentally” incompatible:
> 
> var stderr = FileHandle.standardError
> /* Conform FileHandle to TextOutputStream */
> print("foo", to: )
> 
> 
> On Fri, Aug 18, 2017 at 01:39 Brent Royal-Gordon  > wrote:
>> On Aug 17, 2017, at 8:20 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> * stderr should go wherever stdin and stdout go. Since it’d be silly for a 
>> function like `print(_:separator:terminator:)` or 
>> `readLine(strippingNewline:)` to live anywhere but the standard library, 
>> then it stands to reason that the stderr version should also live in the 
>> standard library.
>> 
>> FWIW, FileHandle.standardInput, FileHandle.standardError, 
>> FileHandle.standardOutput, and FileHandle.nullDevice all live in Foundation.
> 
> And, since they're read-only, are fundamentally incompatible with 
> `print(…to:)`, which requires its `output` parameter to be passed `inout`.
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2017-08-18 Thread Mike Sanderson via swift-evolution
I can’t speak to the more low-level implications, but to the extent this is
essentially “syntactic sugar for completion handlers,” I can base my
opinion on making iOS apps in different contexts for about 5 years. (Long
enough to remember when Objective-C Blocks as completion handlers were the
great new thing that was going to perfectly solve all our problems). I
especially appreciated the clear goals section of the proposal, which I
thought was on-target.



I have some uncertainty about how async/await will work in
practice—literally, how to use it. Some of this is just needing to see many
more examples and examples in common scenarios at the site of use and in
the creation of async functions.



Most of the questions I had I answered myself in the course of writing this
up, but I include them for confirmation and to call attention to aspects
that may not be clear. (I also tend to use block and closure
interchangeably when it reads better, especially where I learned them as
objective-C completion blocks, please do correct if necessary.) I hope the
write up will provide some clarity for others (assuming it's basically
correct or correctly labeled where it may not be) and provide feedback on
where it could be more clear.



*Starting at beginAsync*


@IBAction func buttonDidClick(sender:AnyObject) {

// 1

beginAsync {

// 2

let image = await processImage()

imageView.image = image

}

// 3

}

After entering a beginAsync block, code will continue to execute inside the
block (like do blocks now) until it encounters an await-marked function. In
this sense it’s more beginAsyncContext not begin-being-asynchronous, which
is how it could be read. Although the end of this block will be where
synchronicity will resume once execution goes async (suspends?) inside it.



At the point of an await function, two things can happen: 1) If the
function needs time to execute -- if "it suspends" is how to describe it?
-- code execution will jump to outside the beginAsync block. 2) If the
function has its result already, code execution will continue inside the
block, or jump to catch error if it exists? (This would not be different
from now in that a receiver of a completion block can invoke it
immediately, before returning).



This is important to clarify because after the async block (or any
functions with completion blocks now) code afterwards can’t assume what
might have happened. But this proposal doesn’t solve the problem seen in
the @IBAction example, of order 1, 3, 2, which is actually worse because if
you can have immediate completion you aren’t sure if it is 1, 3, 2, or 1,
2, 3. This is actually an easy enough situation to handle if you’re aware
of it.



*Use of suspendAsync*


suspendAsync is the point at which the waiting is actually triggered? For a
while this threw me at first (no pun intended). Since it looks like the
more common transitive verb form of “suspend”, I read this as
“suspending-the-async”, therefore, resuming. The primitives looked like
beginAsync started doing something asynchronous and suspendAsync resumed
synchronous execution? Maybe the better order would be asyncSuspend (paired
with asyncBegin--or even better for that, asyncContext) would be less
likely to be confused this way? (More on the primitives just below)



However, even inside the block passed to suspendAsync the code is not
asynchronous yet. The code in the block passed to suspendAsync is still
executed at the time the block is passed in. That code is responsible for
taking the continuation block and error block, escaping with them and
storing them somewhere, and invoking either when the value or error is
ready. Is it correct that those blocks will be called on thread that
suspendAsync was called on?



It was also somewhat unclear what happens then the block passed to
suspendAsync reaches the end. Since suspendAsync is itself an async function
called with await, it looks like control now passes back to the end of the
original beginAsync block, wherever that is. That the getStuff() async wrapper
example returns the result of the call to suspendAsync in one line obscured
what was going on. That was


func getStuff() async -> Stuff {

return await suspendAsync { continuation in

getStuff(completion: continuation)

}

}


What's going on would be more clear over two lines. For example if we
wanted to do further processing after getting our async result before
returning:



func getStuff() async -> Stuff {

let rawStuff = await suspendAsync { continuation in

getStuff(completion: continuation)

}

return processed(rawStuff)

}



Where exactly execution is paused and will resume is more clear.


In fact, the show the full async/await life cycle, it’s possible to
demonstrate in the same scope before introducing the semantics of async
functions:



beginAsync {

do {

let stuff = try await suspendAsync { continuation, error in


Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Xiaodi Wu via swift-evolution
On Fri, Aug 18, 2017 at 7:39 PM, Taylor Swift  wrote:

>
>
> On Fri, Aug 18, 2017 at 8:09 PM, Xiaodi Wu  wrote:
>
>> On Fri, Aug 18, 2017 at 6:55 PM, Greg Parker  wrote:
>>
>>>
>>> On Aug 17, 2017, at 5:16 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Thu, Aug 17, 2017 at 6:46 PM, Taylor Swift 
>>> wrote:
>>>
 I don’t think the “is this library functionality or standard library
 functionality” argument is worth having, but if stdout and stdin are
 first-class citizens in the Swift world, so should stderr.

 As for bringing Foundation into the discussion, you can’t really talk
 about Foundation without also talking about the mountains of problems that
 come with the monolith pattern. But that’s a completely different
 conversation to be had.

>>>
>>> I'm not sure what you're getting at here, but I don't believe you've
>>> addressed my question, which is: it's been firmly decided that I/O belongs
>>> in Foundation, and Foundation does in fact offer such facilities--what is
>>> missing from those facilities, and how can we fill it out?
>>>
>>>
>>> Lots of I/O functionality is missing from Foundation. Foundation's
>>> design from time immemorial is that generally only relatively simple and
>>> high-level operations are available in Foundation itself, and if you want
>>> to do complicated or non-portable things then you are expected to drop down
>>> to POSIX or other C interfaces. That design works less well in Swift than
>>> it did in Objective-C because Swift's interface with C, especially
>>> low-level C, is often ugly.
>>>
>>> Simple example: there is no way to access file information directly via
>>> NSFileHandle. You need to call NSFileHandle.fileDescriptor and pass that to
>>>  fstat() or fcntl(). The NSFileHandle API in general is sparse and wholly
>>> inadequate for sophisticated I/O.
>>>
>>
>> So that's a good starting point for the discussion.
>>
>> What, in your opinion, should be the way forward in addressing this
>> situation? Is there a realistic chance of writing a single comprehensive,
>> cross-platform API that makes possible currently "complicated or
>> non-portable things" on both macOS/iOS/tvOS/watchOS and Linux, and
>> potentially Windows? If so, does that fit within the general category of
>> filling out the currently sparse Foundation APIs or would that be a matter
>> for a separate library? In the alternative, is it the right solution to
>> make dropping down to POSIX marginally easier by re-exporting C APIs under
>> a unified name, without attempting a single cross-platform API?
>>
>>
>>
> For what it’s worth, CoreFoundation appears to support windows
> environments, at least for things like path manipulation. However atm it’s
> not very relevant as Swift doesn’t run on Windows rn.
>

If I recall, the CoreFoundation code for Windows is from a long-abandoned
port that no longer works, to the point that it is thought unsuitable as a
basis for a modern port.
___
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-18 Thread Yuta Koshizawa via swift-evolution
Hi, I have a question about the proposed `async/await`.

Are `throws async` and `await try` allowed? I think we have three options.

1. allows only `async throws`-`try await`
2. allows both `async throws`-`try await` and `throws async`-`await try`
and does not distinguish them
3. allows both and distinguishes them like `Promise` and
`Result`

Although 3 is the most expressive, I think it is too complicated. In most
cases we need only something similar to `Promise`. To select 1
also makes it possible to support 3 in the future. So 1 seems a good choice
to me.

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


Re: [swift-evolution] pure functions

2017-08-18 Thread Chris Lattner via swift-evolution
As Andy says, the major problem is that public API (which you can't see the 
implementation of in general) would all need to be marked up properly.

-Chris

> On Aug 18, 2017, at 2:45 PM, David Sweeris  wrote:
> 
> 
>> On Aug 18, 2017, at 12:11, Chris Lattner via swift-evolution 
>>  wrote:
>> 
>> Splitting this out from the concurrency thread:
>> 
>>> 
> On Aug 18, 2017, at 6:12 AM, Matthew Johnson  
> wrote:
> On Aug 17, 2017, at 11:53 PM, Chris Lattner  wrote:
> 
> In the manifesto you talk about restrictions on passing functions across 
> an actor message.  You didn’t discuss pure functions, presumably because 
> Swift doesn’t have them yet.  I imagine that if (hopefully when) Swift 
> has compiler support for verifying pure functions these would also be 
> safe to pass across an actor message.  Is that correct?
 
 Correct.  The proposal is specifically/intentionally designed to be light 
 on type system additions, but there are many that could make it better in 
 various ways.  The logic for this approach is that I expect *a lot* of 
 people will be writing mostly straight-forward concurrent code, and that 
 goal is harmed by presenting significant type system hurdles for them to 
 jump over, because that implies a higher learning curve.
 
 This is why the proposal doesn’t focus on a provably memory safe system: 
 If someone slaps “ValueSemantical” on a type that doesn’t obey, they will 
 break the invariants of the system.  There are lots of ways to solve that 
 problem (e.g. the capabilities system in Pony) but it introduces a steep 
 learning curve.
 
 I haven’t thought a lot about practically getting pure functions into 
 Swift, because it wasn’t clear what problems it would solve (which 
 couldn’t be solved another way).  You’re right though that this could be 
 an interesting motivator. 
>>> 
>>> I can provide a concrete example of why this is definitely and important 
>>> motivator.  
>>> 
>>> My current project uses pure functions, value semantics and declarative 
>>> effects at the application level and moves as much of the imperative code 
>>> as possible (including effect handling) into library level code.  This is 
>>> working out really well and I plan to continue with this approach.  The 
>>> library level code needs the ability to schedule user code in the 
>>> appropriate context.  There will likely be some declarative ability for 
>>> application level code to influence the context, priority, etc, but it is 
>>> the library that will be moving the functions to the final context.  They 
>>> are obviously not closure literals from the perspective of the library.
>>> 
>>> Pure functions are obviously important to the semantics of this approach.  
>>> We can get by without compiler verification, using documentation just as we 
>>> do for protocol requirements that can't be verified.  That said, it would 
>>> be pretty disappointing to have to avoid using actors in the implementation 
>>> simply because we can't move pure functions from one actor to another as 
>>> necessary.
>>> 
>>> To be clear, I am talking in the context of "the fullness of time".  It 
>>> would be perfectly acceptable to ship actors before pure functions.  That 
>>> said, I do think it's crucial that we eventually have the ability to verify 
>>> pure functions and move them around at will.
>> 
>> Right.  Pure functions are also nice when you care about thread safety, and 
>> there is a lot of work on this.  C has __attribute__((const)) and ((pure)) 
>> for example, c++ has constexpr, and many research languages have built full 
>> blown effects systems.
>> 
>> My principle concern is that things like this quickly become infectious: 
>> LOTS of things are pure functions, and requiring them all to be marked as 
>> such becomes a lot of boilerplate and conceptual overhead.  This is 
>> happening in the C++ community with constexpr for example.
> 
> At a rough guess, how many of the stdlib's functions could realistically have 
> their purity inferred?
> 
> If we define our semantics carefully enough, could we realistically make it 
> so that "@pure" or "@impure" (or whatever) would simply be a note to the 
> compiler, letting it skip that bit of analysis for the function in question?
> 
> 
> 
>> The secondary concern is that you need to build out the model enough that 
>> you don’t prevent abstractions.  A pure function should be able to create an 
>> instance of a struct, mutate it (i.e. calling non-pure functions) etc.  This 
>> requires a non-trivial design, and as the design complexity creeps, you run 
>> the risk of it getting out of control.
> 
> Did we ever get around to figuring which definition(s) of "pure" that we 
> wanted to support, or did the discussion always get out of scope before we 
> got that far? I know 

Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu  wrote:
> 
> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution 
> > wrote:
> 
> 
> Sent from my iPad
> 
> On Aug 18, 2017, at 1:27 AM, John McCall  > wrote:
> 
> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
> >> > wrote:
> >> Splitting this off into its own thread:
> >>
> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  >>> > wrote:
> >>> One related topic that isn’t discussed is type errors.  Many third party 
> >>> libraries use a Result type with typed errors.  Moving to an async / 
> >>> await model without also introducing typed errors into Swift would 
> >>> require giving up something that is highly valued by many Swift 
> >>> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
> >>> well.  I would be happy to help with design and drafting a proposal but 
> >>> would need collaborators on the implementation side.
> >>
> >> Typed throws is something we need to settle one way or the other, and I 
> >> agree it would be nice to do that in the Swift 5 cycle.
> >>
> >> For the purposes of this sub-discussion, I think there are three kinds of 
> >> code to think about:
> >> 1) large scale API like Cocoa which evolve (adding significant 
> >> functionality) over the course of many years and can’t break clients.
> >> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
> >> fall - being obsoleted and replaced by better packages if they encounter a 
> >> design problem.
> >> 3) internal APIs and applications, which are easy to change because the 
> >> implementations and clients of the APIs are owned by the same people.
> >>
> >> These each have different sorts of concerns, and we hope that something 
> >> can start out as #3 but work its way up the stack gracefully.
> >>
> >> Here is where I think things stand on it:
> >> - There is consensus that untyped throws is the right thing for a large 
> >> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
> >> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
> >> reason.
> >> - There is consensus that untyped throws is the right default for people 
> >> to reach for for public package (#2).
> >> - There is consensus that Java and other systems that encourage lists of 
> >> throws error types lead to problematic APIs for a variety of reasons.
> >> - There is disagreement about whether internal APIs (#3) should use it.  
> >> It seems perfect to be able to write exhaustive catches in this situation, 
> >> since everything in knowable. OTOH, this could encourage abuse of error 
> >> handling in cases where you really should return an enum instead of using 
> >> throws.
> >> - Some people are concerned that introducing typed throws would cause 
> >> people to reach for it instead of using untyped throws for public package 
> >> APIs.
> >
> > Even for non-public code.  The only practical merit of typed throws I have 
> > ever seen someone demonstrate is that it would let them use contextual 
> > lookup in a throw or catch.  People always say "I'll be able to 
> > exhaustively switch over my errors", and then I ask them to show me where 
> > they want to do that, and they show me something that just logs the error, 
> > which of course does not require typed throws.  Every.  Single.  Time.
> 
> I agree that exhaustive switching over errors is something that people are 
> extremely likely to actually want to do.  I also think it's a bit of a red 
> herring.  The value of typed errors is *not* in exhaustive switching.  It is 
> in categorization and verified documentation.
> 
> Here is a concrete example that applies to almost every app.  When you make a 
> network request there are many things that could go wrong to which you may 
> want to respond differently:
> * There might be no network available.  You might recover by updating the UI 
> to indicate that and start monitoring for a reachability change.
> * There might have been a server error that should eventually be resolved 
> (500).  You might update the UI and provide the user the ability to retry.
> * There might have been an unrecoverable server error (404).  You will update 
> the UI.
> * There might have been a low level parsing error (bad JSON, etc).  Recovery 
> is perhaps similar in nature to #2, but the problem is less likely to be 
> resolved quickly so you may not provide a retry option.  You might also want 
> to do something to notify your dev team that the server is returning JSON 
> that can't be parsed.
> * There might have been a higher-level parsing error (converting JSON to 
> model types).  This might be treated the same as bad JSON.  On the other 
> hand, depending on the 

Re: [swift-evolution] SE-184 Improved Pointers

2017-08-18 Thread Taylor Swift via swift-evolution
Should the immutable buffer pointer types also get deallocate()?

On Fri, Aug 18, 2017 at 7:55 PM, Andrew Trick  wrote:

>
> On Aug 15, 2017, at 9:47 PM, Taylor Swift via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Implementation is here: https://github.com/apple/swift/pull/11464
>
> On Sat, Aug 12, 2017 at 8:23 PM, Taylor Swift 
> wrote:
>
>> I’ve revised the proposal based on what I learned from trying to
>> implement these changes. I think it’s worth tacking the existing methods
>> that take Sequences at the same time as this actually makes the design a
>> bit simpler.
>> 
>>
>> *The previous version
>>  of this
>> document ignored the generic initialization methods on
>> UnsafeMutableBufferPointer and UnsafeMutableRawBufferPointer, leaving them
>> to be overhauled at a later date, in a separate proposal. Instead, this
>> version of the proposal leverages those existing methods to inform a more
>> compact API design which has less surface area, and is more future-proof
>> since it obviates the need to design and add another (redundant) set of
>> protocol-oriented pointer APIs later.*
>>
>> On Tue, Aug 8, 2017 at 12:52 PM, Taylor Swift 
>> wrote:
>>
>>> Since Swift 5 just got opened up for proposals, SE-184 Improved Pointers
>>> is ready for community review, and I encourage everyone to look it over and
>>> provide feedback. Thank you!
>>> >> als/0184-improved-pointers.md>
>>>
>>>
>
> Would you mind adding a deallocate method to (nonmutable) 
> UnsafePointer/UnsafeBufferPointer
> to take care of
> [SR-3309](https://bugs.swift.org/browse/SR-3309)?
>
> There’s simply nothing in the memory model that requires mutable memory
> for deallocation.
>
> It fits right in with this proposal and hardly seems worth a separate one.
>
> -Andy
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Aug 18, 2017, at 6:56 PM, Xiaodi Wu  wrote:
> 
> Joe Groff wrote:
> 
> An alternative approach that embraces the open nature of errors could be to 
> represent domains as independent protocols, and extend the error types that 
> are relevant to that domain to conform to the protocol. That way, you don't 
> obscure the structure of the underlying error value with wrappers. If you 
> expect to exhaustively handle all errors in a domain, well, you'd almost 
> certainly going to need to have a fallback case in your wrapper type for 
> miscellaneous errors, but you could represent that instead without wrapping 
> via a catch-all, and as?-casting to your domain protocol with a ??-default 
> for errors that don't conform to the protocol. For example, instead of 
> attempting something like this:
> 
> enum DatabaseError {
>   case queryError(QueryError)
>   case ioError(IOError)
>   case other(Error)
> 
>   var errorKind: String {
> switch self {
>   case .queryError(let q): return "query error: \(q.query)"
>   case .ioError(let i): return "io error: \(i.filename)"
>   case .other(let e): return "\(e)"
> }
>   }
> }
> 
> func queryDatabase(_ query: String) throws /*DatabaseError*/ -> Table
> 
> do {
>   queryDatabase("delete * from users")
> } catch let d as DatabaseError {
>   os_log(d.errorKind)
> } catch {
>   fatalError("unexpected non-database error")
> }
> 
> You could do this:
> 
> protocol DatabaseError {
>   var errorKind: String { get }
> }
> 
> extension QueryError: DatabaseError {
>   var errorKind: String { return "query error: \(q.query)" }
> }
> extension IOError: DatabaseError {
>   var errorKind: String ( return "io error: \(i.filename)" }
> }
> 
> extension Error {
>   var databaseErrorKind: String {
> return (error as? DatabaseError)?.errorKind ?? "unexpected non-database 
> error"
>   }
> }
> 
> func queryDatabase(_ query: String) throws -> Table
> 
> do {
>   queryDatabase("delete * from users")
> } catch {
>   os_log(error.databaseErrorKind)
> }

This approach isn't sufficient for several reasons.  Notably, it requires the 
underlying errors to already have a distinct type for every category we wish to 
place them in.  If all network errors have the same type and I want to 
categorize them based on network availability, authentication, dropped 
connection, etc I am not able to do that.  

The kind of categorization I want to be able to do requires a custom algorithm. 
 The specific algorithm is used to categorize errors depends on the dynamic 
context (i.e. the function that is propagating it).  The way I usually think 
about this categorization is as a conversion initializer as I showed in the 
example, but it certainly wouldn't need to be accomplished that way.  The most 
important thing IMO is the ability to categorize during error propagation and 
make information about that categorization easy for callers to discover.

The output of the algorithm could use various mechanisms for categorization - 
an enum is one mechanism, distinct types conforming to appropriate 
categorization protocols is another.  Attaching some kind of category value to 
the original error or propagating the category along with it might also work 
(although might be rather clunky).

It is trivial to make the original error immediately available via an 
`underlyingError` property so I really don't understand the resistance to 
wrapping errors.  The categorization can easily be ignored at the catch site if 
desired.  That said, if we figure out some other mechanism for categorizing 
errors, including placing different error values of the same type into 
different categories, and matching them based on this categorization I think I 
would be ok with that.  Using wrapper types is not essential to solving the 
problem.

Setting all of this aside, surely you had you had your own reasons for 
supporting typed errors in the past.  What were those and why do you no longer 
consider them important?

> 
> 
>> On Fri, Aug 18, 2017 at 6:46 PM, Matthew Johnson  
>> wrote:
>> 
>>> On Aug 18, 2017, at 6:29 PM, Xiaodi Wu  wrote:
>>> 
 On Fri, Aug 18, 2017 at 6:19 PM, Matthew Johnson  
 wrote:
 
> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu  wrote:
> 
>> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
>> 
>> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>> >>  wrote:
>> >> Splitting this off into its own thread:
>> >>
>> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson 
>> >>>  wrote:
>> >>> One related topic that isn’t discussed is type errors.  Many third 
>> >>> 

Re: [swift-evolution] typed throws

2017-08-18 Thread Xiaodi Wu via swift-evolution
On Fri, Aug 18, 2017 at 8:11 PM, Matthew Johnson 
wrote:

>
>
> Sent from my iPad
>
> On Aug 18, 2017, at 6:56 PM, Xiaodi Wu  wrote:
>
> Joe Groff wrote:
>
> An alternative approach that embraces the open nature of errors could be
> to represent domains as independent protocols, and extend the error types
> that are relevant to that domain to conform to the protocol. That way, you
> don't obscure the structure of the underlying error value with wrappers. If
> you expect to exhaustively handle all errors in a domain, well, you'd
> almost certainly going to need to have a fallback case in your wrapper type
> for miscellaneous errors, but you could represent that instead without
> wrapping via a catch-all, and as?-casting to your domain protocol with a
> ??-default for errors that don't conform to the protocol. For example,
> instead of attempting something like this:
>
> enum DatabaseError {
>   case queryError(QueryError)
>   case ioError(IOError)
>   case other(Error)
>
>   var errorKind: String {
> switch self {
>   case .queryError(let q): return "query error: \(q.query)"
>   case .ioError(let i): return "io error: \(i.filename)"
>   case .other(let e): return "\(e)"
> }
>   }
> }
>
> func queryDatabase(_ query: String) throws /*DatabaseError*/ -> Table
>
> do {
>   queryDatabase("delete * from users")
> } catch let d as DatabaseError {
>   os_log(d.errorKind)
> } catch {
>   fatalError("unexpected non-database error")
> }
>
> You could do this:
>
> protocol DatabaseError {
>   var errorKind: String { get }
> }
>
> extension QueryError: DatabaseError {
>   var errorKind: String { return "query error: \(q.query)" }
> }
> extension IOError: DatabaseError {
>   var errorKind: String ( return "io error: \(i.filename)" }
> }
>
> extension Error {
>   var databaseErrorKind: String {
> return (error as? DatabaseError)?.errorKind ?? "unexpected
> non-database error"
>   }
> }
>
> func queryDatabase(_ query: String) throws -> Table
>
> do {
>   queryDatabase("delete * from users")
> } catch {
>   os_log(error.databaseErrorKind)
> }
>
>
> This approach isn't sufficient for several reasons.  Notably, it requires
> the underlying errors to already have a distinct type for every category we
> wish to place them in.  If all network errors have the same type and I want
> to categorize them based on network availability, authentication, dropped
> connection, etc I am not able to do that.
>

Sorry, how does the presence or absence of typed throws play into this?


> The kind of categorization I want to be able to do requires a custom
> algorithm.  The specific algorithm is used to categorize errors depends on
> the dynamic context (i.e. the function that is propagating it).  The way I
> usually think about this categorization is as a conversion initializer as I
> showed in the example, but it certainly wouldn't need to be accomplished
> that way.  The most important thing IMO is the ability to categorize during
> error propagation and make information about that categorization easy for
> callers to discover.
>
> The output of the algorithm could use various mechanisms for
> categorization - an enum is one mechanism, distinct types conforming to
> appropriate categorization protocols is another.  Attaching some kind of
> category value to the original error or propagating the category along with
> it might also work (although might be rather clunky).
>
> It is trivial to make the original error immediately available via an
> `underlyingError` property so I really don't understand the resistance to
> wrapping errors.  The categorization can easily be ignored at the catch
> site if desired.  That said, if we figure out some other mechanism for
> categorizing errors, including placing different error values of the same
> type into different categories, and matching them based on this
> categorization I think I would be ok with that.  Using wrapper types is not
> essential to solving the problem.
>
> Setting all of this aside, surely you had you had your own reasons for
> supporting typed errors in the past.  What were those and why do you no
> longer consider them important?
>

My memory is certainly spotty, but as far as I can recall, I had no
distinct reasons; it just seemed like a reasonable and "natural" next step
that other people wanted for which I had no use case of my own in mind.
Having seen the argumentation that there aren't very many use cases in
general, I'm warming to the view that it's probably not such a great next
step.


On Fri, Aug 18, 2017 at 6:46 PM, Matthew Johnson 
> wrote:
>
>>
>> On Aug 18, 2017, at 6:29 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Aug 18, 2017 at 6:19 PM, Matthew Johnson 
>>  wrote:
>>
>>>
>>> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu  wrote:
>>>
>>> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution <
>>> 

Re: [swift-evolution] typed throws

2017-08-18 Thread Xiaodi Wu via swift-evolution
On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> Sent from my iPad
>
> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
>
> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
> >> Splitting this off into its own thread:
> >>
> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson 
> wrote:
> >>> One related topic that isn’t discussed is type errors.  Many third
> party libraries use a Result type with typed errors.  Moving to an async /
> await model without also introducing typed errors into Swift would require
> giving up something that is highly valued by many Swift developers.  Maybe
> Swift 5 is the right time to tackle typed errors as well.  I would be happy
> to help with design and drafting a proposal but would need collaborators on
> the implementation side.
> >>
> >> Typed throws is something we need to settle one way or the other, and I
> agree it would be nice to do that in the Swift 5 cycle.
> >>
> >> For the purposes of this sub-discussion, I think there are three kinds
> of code to think about:
> >> 1) large scale API like Cocoa which evolve (adding significant
> functionality) over the course of many years and can’t break clients.
> >> 2) the public API of shared swiftpm packages, whose lifecycle may rise
> and fall - being obsoleted and replaced by better packages if they
> encounter a design problem.
> >> 3) internal APIs and applications, which are easy to change because the
> implementations and clients of the APIs are owned by the same people.
> >>
> >> These each have different sorts of concerns, and we hope that something
> can start out as #3 but work its way up the stack gracefully.
> >>
> >> Here is where I think things stand on it:
> >> - There is consensus that untyped throws is the right thing for a large
> scale API like Cocoa.  NSError is effectively proven here.  Even if typed
> throws is introduced, Apple is unlikely to adopt it in their APIs for this
> reason.
> >> - There is consensus that untyped throws is the right default for
> people to reach for for public package (#2).
> >> - There is consensus that Java and other systems that encourage lists
> of throws error types lead to problematic APIs for a variety of reasons.
> >> - There is disagreement about whether internal APIs (#3) should use
> it.  It seems perfect to be able to write exhaustive catches in this
> situation, since everything in knowable. OTOH, this could encourage abuse
> of error handling in cases where you really should return an enum instead
> of using throws.
> >> - Some people are concerned that introducing typed throws would cause
> people to reach for it instead of using untyped throws for public package
> APIs.
> >
> > Even for non-public code.  The only practical merit of typed throws I
> have ever seen someone demonstrate is that it would let them use contextual
> lookup in a throw or catch.  People always say "I'll be able to
> exhaustively switch over my errors", and then I ask them to show me where
> they want to do that, and they show me something that just logs the error,
> which of course does not require typed throws.  Every.  Single.  Time.
>
> I agree that exhaustive switching over errors is something that people are
> extremely likely to actually want to do.  I also think it's a bit of a red
> herring.  The value of typed errors is *not* in exhaustive switching.  It
> is in categorization and verified documentation.
>
> Here is a concrete example that applies to almost every app.  When you
> make a network request there are many things that could go wrong to which
> you may want to respond differently:
> * There might be no network available.  You might recover by updating the
> UI to indicate that and start monitoring for a reachability change.
> * There might have been a server error that should eventually be resolved
> (500).  You might update the UI and provide the user the ability to retry.
> * There might have been an unrecoverable server error (404).  You will
> update the UI.
> * There might have been a low level parsing error (bad JSON, etc).
> Recovery is perhaps similar in nature to #2, but the problem is less likely
> to be resolved quickly so you may not provide a retry option.  You might
> also want to do something to notify your dev team that the server is
> returning JSON that can't be parsed.
> * There might have been a higher-level parsing error (converting JSON to
> model types).  This might be treated the same as bad JSON.  On the other
> hand, depending on the specifics of the app, you might take an alternate
> path that only parses the most essential model data in hopes that the
> problem was somewhere else and this parse will succeed.
>
> All of this can obviously be accomplished with untyped errors.  That said,
> using types to categorize errors would significantly improve the clarity of
> such code.  More 

Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Taylor Swift via swift-evolution
On Fri, Aug 18, 2017 at 8:09 PM, Xiaodi Wu  wrote:

> On Fri, Aug 18, 2017 at 6:55 PM, Greg Parker  wrote:
>
>>
>> On Aug 17, 2017, at 5:16 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Thu, Aug 17, 2017 at 6:46 PM, Taylor Swift 
>> wrote:
>>
>>> I don’t think the “is this library functionality or standard library
>>> functionality” argument is worth having, but if stdout and stdin are
>>> first-class citizens in the Swift world, so should stderr.
>>>
>>> As for bringing Foundation into the discussion, you can’t really talk
>>> about Foundation without also talking about the mountains of problems that
>>> come with the monolith pattern. But that’s a completely different
>>> conversation to be had.
>>>
>>
>> I'm not sure what you're getting at here, but I don't believe you've
>> addressed my question, which is: it's been firmly decided that I/O belongs
>> in Foundation, and Foundation does in fact offer such facilities--what is
>> missing from those facilities, and how can we fill it out?
>>
>>
>> Lots of I/O functionality is missing from Foundation. Foundation's design
>> from time immemorial is that generally only relatively simple and
>> high-level operations are available in Foundation itself, and if you want
>> to do complicated or non-portable things then you are expected to drop down
>> to POSIX or other C interfaces. That design works less well in Swift than
>> it did in Objective-C because Swift's interface with C, especially
>> low-level C, is often ugly.
>>
>> Simple example: there is no way to access file information directly via
>> NSFileHandle. You need to call NSFileHandle.fileDescriptor and pass that to
>>  fstat() or fcntl(). The NSFileHandle API in general is sparse and wholly
>> inadequate for sophisticated I/O.
>>
>
> So that's a good starting point for the discussion.
>
> What, in your opinion, should be the way forward in addressing this
> situation? Is there a realistic chance of writing a single comprehensive,
> cross-platform API that makes possible currently "complicated or
> non-portable things" on both macOS/iOS/tvOS/watchOS and Linux, and
> potentially Windows? If so, does that fit within the general category of
> filling out the currently sparse Foundation APIs or would that be a matter
> for a separate library? In the alternative, is it the right solution to
> make dropping down to POSIX marginally easier by re-exporting C APIs under
> a unified name, without attempting a single cross-platform API?
>
>
>
For what it’s worth, CoreFoundation appears to support windows
environments, at least for things like path manipulation. However atm it’s
not very relevant as Swift doesn’t run on Windows rn.
___
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-18 Thread Adam Kemp via swift-evolution
Thanks for the quick response!

> On Aug 18, 2017, at 1:15 PM, Chris Lattner  wrote:
> 
> On Aug 18, 2017, at 12:34 PM, Adam Kemp  > wrote:
>> For instance, say you’re handling a button click, and you need to do a 
>> network request and then update the UI. In C# (using Xamarin.iOS as an 
>> example) you might write some code like this:
>> 
>> private async void HandleButtonClick(object sender, EventArgs e) {
>> var results = await GetStuffFromNetwork();
>> UpdateUI(results);
>> }
>> 
>> This event handler is called on the UI thread, and the UpdateUI call must be 
>> done on the UI thread. The way async/await works in C# (by default) is that 
>> when your continuation is called it will be on the same synchronization 
>> context you started with. That means if you started on the UI thread you 
>> will resume on the UI thread. If you started on some thread pool then you 
>> will resume on that same thread pool.
> 
> I completely agree, I would love to see this because it is the most easy to 
> reason about, and is implied by the syntax.  I consider this to be a 
> follow-on to the basic async/await proposal - part of the Objective-C 
> importer work, as described here:
> https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#fix-queue-hopping-objective-c-completion-handlers
>  
> 
Maybe I’m still missing something, but how does this help when you are 
interacting only with Swift code? If I were to write an asynchronous method in 
Swift then how could I do the same thing that you propose that the Objective-C 
importer do? That is, how do I write my function such that it calls back on the 
same queue?

In my mind, if that requires any extra effort then it is already more error 
prone than what C# does.

> 
>> Another difference between the C# implementation and this proposal is the 
>> lack of futures. While I think it’s fair to be cautious about tying this 
>> proposal to any specific futures implementation or design, I feel like the 
>> value of tying it to some concept of futures was somewhat overlooked. For 
>> instance, in C# you could write a method with this signature:
> ...
>> 
>> The benefit of connecting the async/await feature to the concept of futures 
>> is that you can mix and match this code freely. The current proposal doesn’t 
>> seem to allow this.
> 
> The current proposal provides an underlying mechanism that you can build 
> futures on, and gives an example.  As shown, the experience using that 
> futures API would work quite naturally and fit into Swift IMO.

I feel like this is trading conceptual complexity in order to gain compiler 
simplicity. What I mean by that is that the feature feels harder to understand, 
and the benefit seems to be that this feature can be used more generally for 
other things. I’m not sure that’s a good tradeoff.

The other approach, which is to build a specific async/await feature using 
compiler transformations, may be less generic (yield return would have to work 
differently), but it seems (to me) easier to understand how to use.

For instance, this code (modified from the proposal):

@IBAction func buttonDidClick(sender:AnyObject) {  
doSomethingOnMainThread();
beginAsync {
let image = await processImage()
imageView.image = image
}
doSomethingElseOnMainThread();
}

Is less straightforward than this:

@IBAction async func buttonDidClick(sender:AnyObject) {
doSomethingOnMainThread();
let imageTask = processImage()
doSomethingElseOnMainThread();
imageView.image = await imageTask
}

It’s clearer from reading of the second function what order things will run in. 
The code from the proposal has a block of code (the callback from beginAsync) 
that will run in part before the code that follows, but some of it will run 
after buttonDidClick returns. That’s confusing in the same way that callbacks 
in general are confusing. The way that async/await makes code clearer is by 
making it more WYSIWYG: the order you see the code written in is the order in 
which that code is run. The awaits just mark breaks.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread Jonathan Hull via swift-evolution
It is different though.

Sure, with a little bit of sugar, it can be used to make something that looks a 
bit like union types, but it should avoid the complexity in the type checker 
which caused that to be on the rejected list.  In this case 'Int | String' is 
just sugar for '.int(Int) | .string(String)’, which creates an anonymous enum 
similar to the actual enum shown below. 

Without the sugar, it really just is a quick way to build enums.  Without the 
sugar, it can be used to make something that looks a bit like union types as 
well, but you just have to type .int(Int) | .string(String).  I can do that 
with enums right now though:

enum myType {
case int(Int)
case string(String)
}

This is just a shorthand way of quickly doing the above without giving it a 
name.




> On Aug 18, 2017, at 11:35 AM, John McCall  wrote:
> 
>> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>>  wrote:
>> The typed throws discussion brought me back to an old thought.
>> 
>> I would really like to see a new structural type, similar to tuples, which 
>> act as an anonymous enum.  These would actually be a distinct type from 
>> enums (not sure what to call them), in the same way that structs and tuples 
>> are different.  They would have a very similar syntax to enums though, so 
>> they would be easy to learn.
> 
> This is the commonly-rejected "Disjunctions in type constraints" feature.
> 
> John.
> 
>> 
>> There would be two major difference from enums:
>> 
>> 1) Because they are structural, they can’t have associated functions or 
>> extensions
>> 
>> 2) They can concatenate with one another freely 
>> 
>> For example:
>> 
>>  func foo( speed: .slow | .med | .fast ){
>>  bar(speed: speed)
>>  }
>> 
>>  func bar(speed: .slow | .med | .fast | .ludicrous) {
>>  //but we couldn't call foo here because it doesn’t take 
>> .ludicrous
>>  }
>> 
>> Each case is it’s own mini-type in a way.  One ‘.slow’ is equivalent to any 
>> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
>> group of cases, and type checking just means seeing if the list/value being 
>> passed is a subset of the list of possible cases.
>> 
>> I’d also like to see sugar for quick conversion from normal Swift enums:
>> 
>>  enum Speed {
>>  case slow
>>  case med
>>  case fast
>>  }
>> 
>>  func foo(speed: Speed | .ludicrous) {
>>  //we can’t call any functions/extensions of Speed, just like we 
>> can’t call a func from int on (Int, Int) 
>>  }
>> 
>> In the above case, Speed gets converted via sugar to “.speed(Speed)” and 
>> then gets concatenated with .ludicrous. Ideally, it would have the added 
>> ability to truly convert to ".slow | .med | .fast | .ludicrous” when passed 
>> to something that doesn’t know about Speed:
>> 
>>  func foo(speed: Speed | .ludicrous) {
>>  switch speed {
>>  case .speed(let s): //Do something with the Speed value
>>  case .ludicrous: //Do something ludicrous
>>  } 
>>  bar(speed: speed) //This can convert to pass by unwrapping 
>> Speed to a bag of cases
>>  }
>> 
>>  func bar(speed: .slow | .med | .fast | .ludicrous) {
>>  switch speed {
>>  case .slow: //
>>  case .med: //
>>  case .fast: //
>>  case .ludicrous: //
>>  }
>>  //We can’t reference Speed above because we just passed a bag 
>> of potential cases
>>  }
>>  
>> 
>> The end result here is that in addition to building one-off enums quickly, 
>> it lets us concatenate and extend enums for use in a limited scope.  I don’t 
>> know about you, but I run into the situation of “I want exactly this enum, 
>> but with one extra case” all the time.
>> 
>> I don’t know if we want typed throws, but this type of quick concatability 
>> would be very useful for adding/merging potential errors.  With the same 
>> sugar used on Speed above, it would also allow something similar to Union 
>> types, but without the most of the implementation headache that would cause. 
>>  You can take in multiple types, and you get back something you can switch 
>> on to recover the type which was passed:
>> 
>>  func myFakeUnion(_ intOrStr: Int | String){
>>  switch intOrStr {
>>  case .int(let i): //Do something with int
>>  case .string(let s): //Do something with string
>>  }
>>  } 
>> 
>>  myFakeUnion(12) //Sugar!
>>  myFakeUnion(.string(“Hey”)) //This works too
>> 
>> 
>> Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift.  
>> I am not sure what the best syntax would be, but it would essentially work a 
>> bit like like a dictionary:
>> 
>>  let mph = speed ? [.slow:10, .med:35, .fast:75]
>> 
>> 

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

2017-08-18 Thread Andre via swift-evolution
2017/08/19 3:51、Chris Lattner のメール:

>> On Aug 17, 2017, at 10:50 PM, Andre  wrote:
>> Part 1: Async/await
>> 
>> let dataResource  = await loadWebResource("dataprofile.txt")
>> 
>> 
>> Was there any thought about introducing the concept of a timeout when 
>> awaiting?
>> 
>> Something like an `await for:` optional parameter?
>> Then, if used with try, it could go like…
>> 
>> let dataResource  = try await for:10/*seconds*/ 
>> loadWebResource("dataprofile.txt”) catch _ as Timeout { //abort,retry cancel 
>> } 
>> 
>> Timeouts should probably be handled at a higher level, but its just 
>> something that jumped out to me a little, since its something I notice 
>> sometimes people neglect to take care of… :/
> 
> Something like this could definitely be built and added later: the sketch for 
> async/await is intentionally kept as minimal as possible.  That said, this 
> seems like it is wandering into territory that would make sense to be API, 
> rather than first class language feature.
I see, yea, the only reason I brought it up is because it jumped out as an 
important concept in my mind that a lot of times seems to get neglected when 
people write async operations (e.g “how long am I willing to wait for this to 
finish” there are a lot of times I have to force quit apps that’s freeze or 
become non-responsive, and it’s almost alway waiting to acquire some resource) 
so i just felt it would be good to have upfront support in some manner for 
timeouts...

>> Part 2: Actors
>> One other thing that also jumped at me was, if we are going to have actors, 
>> and having them encapsulate/isolate state, would it also make sense to make 
>> sure that we can’t invoke state changing messages when its invalid?
>> 
>> As an example, if we had a ”downloader” actor that downloads multiple files, 
>> we wouldn't want to be able to send invalid messages such as `begin` when 
>> downloading has already ”begun”…. Would it then make more sense to have 
>> callable messages be determined by the publicly visible state of the actor 
>> instead?
> 
> Yes, I completely agree and know what you’re talking about here.  You’re 
> unintentionally poking one of my other axes the grind.  :)
Wow great! ^^

> This desire (to have conceptual “states” that a type moves through) is 
> something that is super common.  Files can be in “initialized” and “open” 
> states, and that changes the valid actions that can be performed on them.  A 
> mutex can be locked or unlocked etc.  Being able to express these invariants 
> is highly related to pre and post conditions.
> 
> One abstraction that has been developed in the industry is the notion of 
> typestate (https://en.wikipedia.org/wiki/Typestate_analysis), which underlies 
> common abstractions in static analyzer tools like the Clang Static Analyzer.  
> I would love to see these ideas developed and built out at some point in 
> time, and perhaps the next time I get a long block of time I’ll write another 
> manifesto on those ideas ;-)
I would very very much look forwards to that manifesto and would love to help 
out in any way in supporting such a concept!

> Coming back to your point, these ideas apply just as much to structs and 
> classes as they do actors, so I think it should be a feature orthogonal to 
> actors.
Definitely true, that. 

―

If this was to be a feature at some point, when do you foresee a possible 
inclusion for it?
Swift 5,or 6 timeframe?

Meanwhile I will go and start playing with the languages (plaid etc) in the 
typestate theory wiki link you just shared! I’m glad there is a formal theory 
behind this, very cool.

Andre

iPadから送信

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Xiaodi Wu via swift-evolution
On Fri, Aug 18, 2017 at 6:19 PM, Matthew Johnson 
wrote:

>
> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu  wrote:
>
> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>>
>> Sent from my iPad
>>
>> On Aug 18, 2017, at 1:27 AM, John McCall  wrote:
>>
>> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >> Splitting this off into its own thread:
>> >>
>> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson 
>> wrote:
>> >>> One related topic that isn’t discussed is type errors.  Many third
>> party libraries use a Result type with typed errors.  Moving to an async /
>> await model without also introducing typed errors into Swift would require
>> giving up something that is highly valued by many Swift developers.  Maybe
>> Swift 5 is the right time to tackle typed errors as well.  I would be happy
>> to help with design and drafting a proposal but would need collaborators on
>> the implementation side.
>> >>
>> >> Typed throws is something we need to settle one way or the other, and
>> I agree it would be nice to do that in the Swift 5 cycle.
>> >>
>> >> For the purposes of this sub-discussion, I think there are three kinds
>> of code to think about:
>> >> 1) large scale API like Cocoa which evolve (adding significant
>> functionality) over the course of many years and can’t break clients.
>> >> 2) the public API of shared swiftpm packages, whose lifecycle may rise
>> and fall - being obsoleted and replaced by better packages if they
>> encounter a design problem.
>> >> 3) internal APIs and applications, which are easy to change because
>> the implementations and clients of the APIs are owned by the same people.
>> >>
>> >> These each have different sorts of concerns, and we hope that
>> something can start out as #3 but work its way up the stack gracefully.
>> >>
>> >> Here is where I think things stand on it:
>> >> - There is consensus that untyped throws is the right thing for a
>> large scale API like Cocoa.  NSError is effectively proven here.  Even if
>> typed throws is introduced, Apple is unlikely to adopt it in their APIs for
>> this reason.
>> >> - There is consensus that untyped throws is the right default for
>> people to reach for for public package (#2).
>> >> - There is consensus that Java and other systems that encourage lists
>> of throws error types lead to problematic APIs for a variety of reasons.
>> >> - There is disagreement about whether internal APIs (#3) should use
>> it.  It seems perfect to be able to write exhaustive catches in this
>> situation, since everything in knowable. OTOH, this could encourage abuse
>> of error handling in cases where you really should return an enum instead
>> of using throws.
>> >> - Some people are concerned that introducing typed throws would cause
>> people to reach for it instead of using untyped throws for public package
>> APIs.
>> >
>> > Even for non-public code.  The only practical merit of typed throws I
>> have ever seen someone demonstrate is that it would let them use contextual
>> lookup in a throw or catch.  People always say "I'll be able to
>> exhaustively switch over my errors", and then I ask them to show me where
>> they want to do that, and they show me something that just logs the error,
>> which of course does not require typed throws.  Every.  Single.  Time.
>>
>> I agree that exhaustive switching over errors is something that people
>> are extremely likely to actually want to do.  I also think it's a bit of a
>> red herring.  The value of typed errors is *not* in exhaustive switching.
>> It is in categorization and verified documentation.
>>
>> Here is a concrete example that applies to almost every app.  When you
>> make a network request there are many things that could go wrong to which
>> you may want to respond differently:
>> * There might be no network available.  You might recover by updating the
>> UI to indicate that and start monitoring for a reachability change.
>> * There might have been a server error that should eventually be resolved
>> (500).  You might update the UI and provide the user the ability to retry.
>> * There might have been an unrecoverable server error (404).  You will
>> update the UI.
>> * There might have been a low level parsing error (bad JSON, etc).
>> Recovery is perhaps similar in nature to #2, but the problem is less likely
>> to be resolved quickly so you may not provide a retry option.  You might
>> also want to do something to notify your dev team that the server is
>> returning JSON that can't be parsed.
>> * There might have been a higher-level parsing error (converting JSON to
>> model types).  This might be treated the same as bad JSON.  On the other
>> hand, depending on the specifics of the app, you might take an alternate
>> path that only parses the most essential model data in hopes 

Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 6:29 PM, Xiaodi Wu  wrote:
> 
> On Fri, Aug 18, 2017 at 6:19 PM, Matthew Johnson  > wrote:
> 
>> On Aug 18, 2017, at 6:15 PM, Xiaodi Wu > > wrote:
>> 
>> On Fri, Aug 18, 2017 at 09:20 Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> On Aug 18, 2017, at 1:27 AM, John McCall > > wrote:
>> 
>> >> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>> >> > wrote:
>> >> Splitting this off into its own thread:
>> >>
>> >>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson > >>> > wrote:
>> >>> One related topic that isn’t discussed is type errors.  Many third party 
>> >>> libraries use a Result type with typed errors.  Moving to an async / 
>> >>> await model without also introducing typed errors into Swift would 
>> >>> require giving up something that is highly valued by many Swift 
>> >>> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
>> >>> well.  I would be happy to help with design and drafting a proposal but 
>> >>> would need collaborators on the implementation side.
>> >>
>> >> Typed throws is something we need to settle one way or the other, and I 
>> >> agree it would be nice to do that in the Swift 5 cycle.
>> >>
>> >> For the purposes of this sub-discussion, I think there are three kinds of 
>> >> code to think about:
>> >> 1) large scale API like Cocoa which evolve (adding significant 
>> >> functionality) over the course of many years and can’t break clients.
>> >> 2) the public API of shared swiftpm packages, whose lifecycle may rise 
>> >> and fall - being obsoleted and replaced by better packages if they 
>> >> encounter a design problem.
>> >> 3) internal APIs and applications, which are easy to change because the 
>> >> implementations and clients of the APIs are owned by the same people.
>> >>
>> >> These each have different sorts of concerns, and we hope that something 
>> >> can start out as #3 but work its way up the stack gracefully.
>> >>
>> >> Here is where I think things stand on it:
>> >> - There is consensus that untyped throws is the right thing for a large 
>> >> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>> >> throws is introduced, Apple is unlikely to adopt it in their APIs for 
>> >> this reason.
>> >> - There is consensus that untyped throws is the right default for people 
>> >> to reach for for public package (#2).
>> >> - There is consensus that Java and other systems that encourage lists of 
>> >> throws error types lead to problematic APIs for a variety of reasons.
>> >> - There is disagreement about whether internal APIs (#3) should use it.  
>> >> It seems perfect to be able to write exhaustive catches in this 
>> >> situation, since everything in knowable. OTOH, this could encourage abuse 
>> >> of error handling in cases where you really should return an enum instead 
>> >> of using throws.
>> >> - Some people are concerned that introducing typed throws would cause 
>> >> people to reach for it instead of using untyped throws for public package 
>> >> APIs.
>> >
>> > Even for non-public code.  The only practical merit of typed throws I have 
>> > ever seen someone demonstrate is that it would let them use contextual 
>> > lookup in a throw or catch.  People always say "I'll be able to 
>> > exhaustively switch over my errors", and then I ask them to show me where 
>> > they want to do that, and they show me something that just logs the error, 
>> > which of course does not require typed throws.  Every.  Single.  Time.
>> 
>> I agree that exhaustive switching over errors is something that people are 
>> extremely likely to actually want to do.  I also think it's a bit of a red 
>> herring.  The value of typed errors is *not* in exhaustive switching.  It is 
>> in categorization and verified documentation.
>> 
>> Here is a concrete example that applies to almost every app.  When you make 
>> a network request there are many things that could go wrong to which you may 
>> want to respond differently:
>> * There might be no network available.  You might recover by updating the UI 
>> to indicate that and start monitoring for a reachability change.
>> * There might have been a server error that should eventually be resolved 
>> (500).  You might update the UI and provide the user the ability to retry.
>> * There might have been an unrecoverable server error (404).  You will 
>> update the UI.
>> * There might have been a low level parsing error (bad JSON, etc).  Recovery 
>> is perhaps similar in nature to #2, but the problem is less likely to be 
>> resolved quickly so you may not provide a retry 

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

2017-08-18 Thread Chris Lattner via swift-evolution

> On Aug 18, 2017, at 6:04 PM, Yuta Koshizawa  wrote:
> 
> Hi, I have a question about the proposed `async/await`.
> 
> Are `throws async` and `await try` allowed? I think we have three options.
> 
> 1. allows only `async throws`-`try await`
> 2. allows both `async throws`-`try await` and `throws async`-`await try` and 
> does not distinguish them
> 3. allows both and distinguishes them like `Promise` and 
> `Result`
> 
> Although 3 is the most expressive, I think it is too complicated. In most 
> cases we need only something similar to `Promise`. To select 1 
> also makes it possible to support 3 in the future. So 1 seems a good choice 
> to me.

I agree.  If we are going to keep “async” and “throws” as unrelated axes on a 
matrix, then there cannot be a relationship implied by the ordering.  “throws 
async” and “async throws” need to mean the same thing.

-Chris

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Chris Lattner via swift-evolution
On Aug 17, 2017, at 11:27 PM, John McCall  wrote:
> Even for non-public code.  The only practical merit of typed throws I have 
> ever seen someone demonstrate is that it would let them use contextual lookup 
> in a throw or catch.  People always say "I'll be able to exhaustively switch 
> over my errors", and then I ask them to show me where they want to do that, 
> and they show me something that just logs the error, which of course does not 
> require typed throws.  Every.  Single.  Time.

I won’t make any claims about what people say to you, but there are other 
benefits of course.  Even if you don’t *exhaustively* catch your errors, it is 
still useful to get code completion for the error cases that you do intend to 
handle (covering the rest with a "catch {“).

Throwing a resilient enum is actually a rather defensible way to handle this, 
since clients will be expected to have a default, and the implementation is 
allowed to add new cases.

> Programmers often have an instinct to obsess over error taxonomies that is 
> very rarely directed at solving any real problem; it is just self-imposed 
> busy-work.

Indeed, no denying that.

>> One thing that I’m personally very concerned about is in the systems 
>> programming domain.  Systems code is sort of the classic example of code 
>> that is low-level enough and finely specified enough that there are lots of 
>> knowable things, including the failure modes.
> 
> Here we are using "systems" to mean "embedded systems and kernels".  And 
> frankly even a kernel is a large enough system that they don't want to 
> exhaustively switch over failures; they just want the static guarantees that 
> go along with a constrained error type.

I think you’re over focusing on exhaustively handling cases.  If you use errno 
as one poor proxy for what kernels care about, it is totally reasonable to 
handle a few of the errors produced by a call (EAGAIN, EINTR are two common 
examples), but not all of them.  It is useful to get code completion on enum 
members, and it is also useful to get an indication from a compiler that 
something can/will never be thrown.  You give up both with full type erasure.

>> 
>> JohnMC has some ideas on how to change code generation for ‘throws’ to avoid 
>> this problem, but I don’t understand his ideas enough to know if they are 
>> practical and likely to happen or not.
> 
> Essentially, you give Error a tagged-pointer representation to allow 
> payload-less errors on non-generic error types to be allocated globally, and 
> then you can (1) tell people to not throw errors that require allocation if 
> it's vital to avoid allocation (just like we would tell them today not to 
> construct classes or indirect enum cases) and (2) allow a special global 
> payload-less error to be substituted if error allocation fails.
> 
> Of course, we could also say that systems code is required to use a 
> typed-throws feature that we add down the line for their purposes.  Or just 
> tell them to not use payloads.  Or force them to constrain their error types 
> to fit within some given size.  (Note that obsessive error taxonomies tend to 
> end up with a bunch of indirect enum cases anyway, because they get 
> recursive, so the allocation problem is very real whatever we do.)

The issue isn’t allocation that can fail, it is the fact that allocation runs 
in nondeterministic time even when it succeeds.  This is highly problematic for 
realtime systems.

Your answer basically says to me that you’re ok with offering a vastly limited 
programming model to people who care about realtime guarantees, and that gives 
up performance needlessly even in use-cases that probably care about low level 
perf.  I agree that it would not be the end of the world (that would be for 
systems programmers to have to keep using C :-), but it certainly falls short 
of the best possible system that we could build.

-Chris

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


Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution

> On Aug 18, 2017, at 11:43 PM, Mark Lilback  wrote:
> 
>> 
>> On Aug 18, 2017, at 2:27 AM, John McCall via swift-evolution 
>>  wrote:
>> 
>> Even for non-public code.  The only practical merit of typed throws I have 
>> ever seen someone demonstrate is that it would let them use contextual 
>> lookup in a throw or catch.  People always say "I'll be able to exhaustively 
>> switch over my errors", and then I ask them to show me where they want to do 
>> that, and they show me something that just logs the error, which of course 
>> does not require typed throws.  Every.  Single.  Time.
> 
> We're doing it in the project I'm working on. Sure, there are some places 
> where we just log the error. But the vast majority of the time, we're 
> handling them. Maybe that's because we're using reactive programming and 
> errors bubble to the top, so there's no need to write that many error 
> handlers. And if I am just logging, either the error doesn't really matter or 
> there is a TODO label reminding me to fix it at some point.

I'm not saying people only log errors instead of handling them in some more 
reasonable way.  I'm saying that logging functions are the only place I've ever 
seen someone switch over an entire error type.

I keep bringing exhaustive switches up because, as soon as you have a default 
case, it seems to me that you haven't really lost anything vs. starting from an 
opaque type like Error.

>> On Aug 18, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> The primary goal for me personally is to factor out and centralize code that 
>> categorizes an error, allowing catch sites to focus on implementing recovery 
>> instead of figuring out what went wrong.  Here’s some concrete sample code 
>> building on the example scenario above:
> 
> I'm using a similar approach. Here is some stripped down code:
> 
> //error object used throughout project
> public struct Rc2Error: LocalizedError, CustomStringConvertible, 
> CustomDebugStringConvertible {
>   /// basic categories of errors
>   public enum Rc2ErrorType: String, Error {
>   /// a requested object was not found
>   case noSuchElement
>   /// a requested operation is already in progress
>   case alreadyInProgress
>   /// problem parsing json, Freddy error is nested
>   case invalidJson
>   /// nestedError will be the NSError 
>   case cocoa 
>   /// nested error is related to the file system 
>   case file 
>   /// a wrapped error from a websocket 
>   case websocket 
>   /// a generic network error 
>   case network 
>   /// an invalid argument was passed (or parsed from json)
>   /// wraps an unknown error
>   case unknown
>   }
> 
>   /// the generic type of the error
>   public let type: Rc2ErrorType
>   /// the underlying error that caused the problem
>   public let nestedError: Error?
>   /// location in source code of where error happened
>   public let location: String
> }

Okay.  I mean, this seems essentially like Swift's Error design.  The comment 
says you use this type ubiquitously in your project.  The type completely 
erases any differences between functions in terms of what errors they can 
throw.  Predictably, it includes an unknown case.  Code that processes values 
of this type must look essentially exactly like switching over an Error, except 
that the unknown case involves explicitly matching '.unknown' instead of using 
'default'.

> //a domain-specific error type that will be nested
> public enum NetworkingError {
>   case unauthorized
>   case unsupportedFileType
>   case timeout
>   case connectionError(Error)
>   case canceled
>   case uploadFailed(Error)
>   case invalidHttpStatusCode(HTTPURLResponse)
>   case restError(code: Int, message: String)
> }

Okay.  So you're doing semantic tagging of errors — you're communicating out 
that an error arose during a specific operation.  And having some static 
enforcement here makes it easier to ensure that you've tagged all the errors.

> The most common errors don't need a nested error. The call site can figure 
> out how to recover based on this. Using Result I can specifically limit 
> what kind of errors are possible from a function without using the wrapper 
> error. E can always be specified as Error to ignore the typed system.

I see.  So you do have some functions that use a more specific type.

> It would be great if the native swift error system let you optionally put 
> compiler-enforced constraints on what kind of error can be thrown. Then I can 
> setup handlers for my specific type of error, but the compiler will give an 
> error/warning if I'm not handling a possible Error. A generic catch-all 

Re: [swift-evolution] typed throws

2017-08-18 Thread David Waite via swift-evolution
> Typed throws is something we need to settle one way or the other, and I agree 
> it would be nice to do that in the Swift 5 cycle.
> 
> For the purposes of this sub-discussion, I think there are three kinds of 
> code to think about: 
> 1) large scale API like Cocoa which evolve (adding significant functionality) 
> over the course of many years and can’t break clients. 
> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
> fall - being obsoleted and replaced by better packages if they encounter a 
> design problem.  
> 3) internal APIs and applications, which are easy to change because the 
> implementations and clients of the APIs are owned by the same people.
> 
> These each have different sorts of concerns, and we hope that something can 
> start out as #3 but work its way up the stack gracefully.
> 
> Here is where I think things stand on it:
> - There is consensus that untyped throws is the right thing for a large scale 
> API like Cocoa.  NSError is effectively proven here.  Even if typed throws is 
> introduced, Apple is unlikely to adopt it in their APIs for this reason.
> - There is consensus that untyped throws is the right default for people to 
> reach for for public package (#2).
> - There is consensus that Java and other systems that encourage lists of 
> throws error types lead to problematic APIs for a variety of reasons.
> - There is disagreement about whether internal APIs (#3) should use it.  It 
> seems perfect to be able to write exhaustive catches in this situation, since 
> everything in knowable. OTOH, this could encourage abuse of error handling in 
> cases where you really should return an enum instead of using throws.
> - Some people are concerned that introducing typed throws would cause people 
> to reach for it instead of using untyped throws for public package APIs.
> - Some people think that while it might be useful in some narrow cases, the 
> utility isn’t high enough to justify making the language more complex 
> (complexity that would intrude on the APIs of result types, futures, etc)

I actually can’t think of anything other than details to add to this synopsis. 

I personally think even for internal usage, errors remain very hard to neatly 
categorize into an ontology, and it is very difficult to have a single ontology 
for all usage. For internal usage, you at least have the ability to evolve your 
usage when you discover the problems, but the weight of typed throws as part of 
function/method types doesn’t seem worth a compiler-enforced exhaustive catch 
to me.

Attempting to categorize errors using a concrete error type can’t help but push 
the complexity of errors down via nested errors (e.g. “The JSON failed to parse 
- but was it due to data corruption, or transient network failure?”). Java’s 
multi-page nested exception traces are a side effect of attempting to corral 
exceptional cases using the type system - I think Swift has benefit of 
retroactive protocol conformance which would keep it from getting Java-level 
bad (see jgroff’s example), but I still don’t think people who want clear 
documentation or exhaustive catches want to have to dive through a hierarchy of 
nested errors to try to determine the root cause.

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


Re: [swift-evolution] [Concurrency] choice of actor model

2017-08-18 Thread Shams Imam via swift-evolution
Do you have example communication patterns for the actor model/asynchronous
messaging context? It would be interesting to see if selectors could be
used to simplify programming such patterns.

Regards,
Shams.

On Sat, Aug 19, 2017 at 10:47 AM, Jonathan Hull  wrote:

> The issue of a lack of ordering is one that actually comes up a lot in
> Swift, and we don’t have a good answer for it in general.  That might be
> something we want to take a deeper look at in the Swift 5 timeframe (at
> least to talk about options).  It would help more than just concurrency…
>
> Thanks,
> Jon
>
>
> On Aug 18, 2017, at 8:51 PM, Shams Imam via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> Disclaimer: this was work done during my graduate study. It was presented
> in front of an audience that included Gul Agha who appreciated the work.
>
> The Actor model is great concurrency model to build on top of thanks to
> its data isolation and asynchronous message processing properties. However,
> lack of guarantees to control the order in which messages are processed by
> an actor makes implementing synchronization and coordination patterns
> difficult in the Actor model. Solutions to support such order in processing
> constraints may require the actor to buffer messages and resend the
> messages to itself until the message is processed. The resulting code is a
> petri-dish of code that intertwines both algorithmic logic and
> synchronization constraints.
>
> I would encourage you to look into the Selector model which is an
> extension of the Actor model that allows an actor to have multiple
> mailboxes. These mailboxes can be enabled/disabled to control which message
> is processed next by the selector (in many ways this is similar to a select
> operation among multiple channels in Communicating Sequential Processes
> style programs). Enabling/disabling does not affect which messages are
> accepted at a mailbox.
>
> In essence, an actor is a selector with a single mailbox which is always
> enabled. Selectors simplify writing of synchronization and coordination
> patterns using actors such as:
>
> a) 'synchronous' request-reply,
> b) join patterns in streaming applications,
> c) supporting priorities in message processing,
> d) variants of reader-writer concurrency, and
> e) producer-consumer with bounded buffer.
>
> Relevant links:
> http://dl.acm.org/citation.cfm?id=2687360
> Detailed description: https://shamsimam.github.io/papers/2014-agere-
> selector.pdf
> Slides: https://shamsimam.github.io/papers/2014-agere-selector-slides.pdf
>
> ___
> 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] typed throws

2017-08-18 Thread Mark Lilback via swift-evolution
> 
> On Aug 18, 2017, at 2:27 AM, John McCall via swift-evolution 
>  wrote:
> 
> Even for non-public code.  The only practical merit of typed throws I have 
> ever seen someone demonstrate is that it would let them use contextual lookup 
> in a throw or catch.  People always say "I'll be able to exhaustively switch 
> over my errors", and then I ask them to show me where they want to do that, 
> and they show me something that just logs the error, which of course does not 
> require typed throws.  Every.  Single.  Time.

We're doing it in the project I'm working on. Sure, there are some places where 
we just log the error. But the vast majority of the time, we're handling them. 
Maybe that's because we're using reactive programming and errors bubble to the 
top, so there's no need to write that many error handlers. And if I am just 
logging, either the error doesn't really matter or there is a TODO label 
reminding me to fix it at some point.

> On Aug 18, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> The primary goal for me personally is to factor out and centralize code that 
> categorizes an error, allowing catch sites to focus on implementing recovery 
> instead of figuring out what went wrong.  Here’s some concrete sample code 
> building on the example scenario above:

I'm using a similar approach. Here is some stripped down code:

//error object used throughout project
public struct Rc2Error: LocalizedError, CustomStringConvertible, 
CustomDebugStringConvertible {
/// basic categories of errors
public enum Rc2ErrorType: String, Error {
/// a requested object was not found
case noSuchElement
/// a requested operation is already in progress
case alreadyInProgress
/// problem parsing json, Freddy error is nested
case invalidJson
/// nestedError will be the NSError 
case cocoa 
/// nested error is related to the file system 
case file 
/// a wrapped error from a websocket 
case websocket 
/// a generic network error 
case network 
/// an invalid argument was passed (or parsed from json)
/// wraps an unknown error
case unknown
}

/// the generic type of the error
public let type: Rc2ErrorType
/// the underlying error that caused the problem
public let nestedError: Error?
/// location in source code of where error happened
public let location: String
}

//a domain-specific error type that will be nested
public enum NetworkingError {
case unauthorized
case unsupportedFileType
case timeout
case connectionError(Error)
case canceled
case uploadFailed(Error)
case invalidHttpStatusCode(HTTPURLResponse)
case restError(code: Int, message: String)
}

The most common errors don't need a nested error. The call site can figure out 
how to recover based on this. Using Result I can specifically limit what 
kind of errors are possible from a function without using the wrapper error. E 
can always be specified as Error to ignore the typed system.

It would be great if the native swift error system let you optionally put 
compiler-enforced constraints on what kind of error can be thrown. Then I can 
setup handlers for my specific type of error, but the compiler will give an 
error/warning if I'm not handling a possible Error. A generic catch-all is not 
proper error handling. And if I'm calling something that doesn't throw 
type-constrained errors, I can use a generic handler and wrap it up in my own 
error. But the call site is getting details necessary to recover (if possible) 
without having to use the runtime to figure out what kind of error it is.

I've got a very efficient system set up right now with great error handling. I 
don't see why the same capability can't exist in the language, especially when 
you can choose to completely ignore it. Hopefully more people would use it and 
we'd stop seeing so many "unknown error" dialogs.

- Mark




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


Re: [swift-evolution] SE-184 Improved Pointers

2017-08-18 Thread Andrew Trick via swift-evolution

> On Aug 18, 2017, at 5:36 PM, Taylor Swift  wrote:
> 
> Should the immutable buffer pointer types also get deallocate()?

Both UnsafePointer and UnsafeBufferPointer should get deallocate. The Raw API 
already has those methods.

-Andy

> On Fri, Aug 18, 2017 at 7:55 PM, Andrew Trick  > wrote:
> 
>> On Aug 15, 2017, at 9:47 PM, Taylor Swift via swift-evolution 
>> > wrote:
>> 
>> Implementation is here: https://github.com/apple/swift/pull/11464 
>> 
>> 
>> On Sat, Aug 12, 2017 at 8:23 PM, Taylor Swift > > wrote:
>> I’ve revised the proposal based on what I learned from trying to implement 
>> these changes. I think it’s worth tacking the existing methods that take 
>> Sequences at the same time as this actually makes the design a bit simpler.
>> > >
>> 
>> The previous version 
>>  of this 
>> document ignored the generic initialization methods on 
>> UnsafeMutableBufferPointer and UnsafeMutableRawBufferPointer, leaving them 
>> to be overhauled at a later date, in a separate proposal. Instead, this 
>> version of the proposal leverages those existing methods to inform a more 
>> compact API design which has less surface area, and is more future-proof 
>> since it obviates the need to design and add another (redundant) set of 
>> protocol-oriented pointer APIs later.
>> 
>> On Tue, Aug 8, 2017 at 12:52 PM, Taylor Swift > > wrote:
>> Since Swift 5 just got opened up for proposals, SE-184 Improved Pointers is 
>> ready for community review, and I encourage everyone to look it over and 
>> provide feedback. Thank you!
>> >  
>> >
>> 
> 
> 
> Would you mind adding a deallocate method to (nonmutable) 
> UnsafePointer/UnsafeBufferPointer to take care of
> [SR-3309](https://bugs.swift.org/browse/SR-3309 
> )?
> 
> There’s simply nothing in the memory model that requires mutable memory for 
> deallocation.
> 
> It fits right in with this proposal and hardly seems worth a separate one.
> 
> -Andy
> 
> 

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


Re: [swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 8:13 PM, Jonathan Hull  wrote:
> 
> It is different though.
> 
> Sure, with a little bit of sugar, it can be used to make something that looks 
> a bit like union types, but it should avoid the complexity in the type 
> checker which caused that to be on the rejected list.  In this case 'Int | 
> String' is just sugar for '.int(Int) | .string(String)’, which creates an 
> anonymous enum similar to the actual enum shown below. 
> 
> Without the sugar, it really just is a quick way to build enums.  Without the 
> sugar, it can be used to make something that looks a bit like union types as 
> well, but you just have to type .int(Int) | .string(String).  I can do that 
> with enums right now though:
> 
>   enum myType {
>   case int(Int)
>   case string(String)
>   }
> 
> This is just a shorthand way of quickly doing the above without giving it a 
> name.

I see your point, but I think this is still very solidly in a space that we've 
expressed interest in not pursuing, especially with the long chain of "wouldn't 
it be great" additions you're suggesting.

John.


> 
> 
> 
> 
>> On Aug 18, 2017, at 11:35 AM, John McCall  wrote:
>> 
>>> On Aug 18, 2017, at 6:36 AM, Jonathan Hull via swift-evolution 
>>>  wrote:
>>> The typed throws discussion brought me back to an old thought.
>>> 
>>> I would really like to see a new structural type, similar to tuples, which 
>>> act as an anonymous enum.  These would actually be a distinct type from 
>>> enums (not sure what to call them), in the same way that structs and tuples 
>>> are different.  They would have a very similar syntax to enums though, so 
>>> they would be easy to learn.
>> 
>> This is the commonly-rejected "Disjunctions in type constraints" feature.
>> 
>> John.
>> 
>>> 
>>> There would be two major difference from enums:
>>> 
>>> 1) Because they are structural, they can’t have associated functions or 
>>> extensions
>>> 
>>> 2) They can concatenate with one another freely 
>>> 
>>> For example:
>>> 
>>> func foo( speed: .slow | .med | .fast ){
>>> bar(speed: speed)
>>> }
>>> 
>>> func bar(speed: .slow | .med | .fast | .ludicrous) {
>>> //but we couldn't call foo here because it doesn’t take 
>>> .ludicrous
>>> }
>>> 
>>> Each case is it’s own mini-type in a way.  One ‘.slow’ is equivalent to any 
>>> ‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
>>> group of cases, and type checking just means seeing if the list/value being 
>>> passed is a subset of the list of possible cases.
>>> 
>>> I’d also like to see sugar for quick conversion from normal Swift enums:
>>> 
>>> enum Speed {
>>> case slow
>>> case med
>>> case fast
>>> }
>>> 
>>> func foo(speed: Speed | .ludicrous) {
>>> //we can’t call any functions/extensions of Speed, just like we 
>>> can’t call a func from int on (Int, Int) 
>>> }
>>> 
>>> In the above case, Speed gets converted via sugar to “.speed(Speed)” and 
>>> then gets concatenated with .ludicrous. Ideally, it would have the added 
>>> ability to truly convert to ".slow | .med | .fast | .ludicrous” when passed 
>>> to something that doesn’t know about Speed:
>>> 
>>> func foo(speed: Speed | .ludicrous) {
>>> switch speed {
>>> case .speed(let s): //Do something with the Speed value
>>> case .ludicrous: //Do something ludicrous
>>> } 
>>> bar(speed: speed) //This can convert to pass by unwrapping 
>>> Speed to a bag of cases
>>> }
>>> 
>>> func bar(speed: .slow | .med | .fast | .ludicrous) {
>>> switch speed {
>>> case .slow: //
>>> case .med: //
>>> case .fast: //
>>> case .ludicrous: //
>>> }
>>> //We can’t reference Speed above because we just passed a bag 
>>> of potential cases
>>> }
>>> 
>>> 
>>> The end result here is that in addition to building one-off enums quickly, 
>>> it lets us concatenate and extend enums for use in a limited scope.  I 
>>> don’t know about you, but I run into the situation of “I want exactly this 
>>> enum, but with one extra case” all the time.
>>> 
>>> I don’t know if we want typed throws, but this type of quick concatability 
>>> would be very useful for adding/merging potential errors.  With the same 
>>> sugar used on Speed above, it would also allow something similar to Union 
>>> types, but without the most of the implementation headache that would 
>>> cause.  You can take in multiple types, and you get back something you can 
>>> switch on to recover the type which was passed:
>>> 
>>> func myFakeUnion(_ intOrStr: Int | String){
>>> switch intOrStr {
>>> case .int(let i): //Do something with int
>>> case .string(let s): //Do something with string
>>>  

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

2017-08-18 Thread Chris Lattner via swift-evolution
On Aug 18, 2017, at 8:18 PM, Andre  wrote:
> If this was to be a feature at some point, when do you foresee a possible 
> inclusion for it?
> Swift 5,or 6 timeframe?

It’s hard to predict.  IMO, ABI stability and concurrency are the most 
important things the community faces in the short term, so you’re looking at 
Swift 6 at the earliest, possibly 7 or 8…. 

-Chris


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


Re: [swift-evolution] [Concurrency] choice of actor model

2017-08-18 Thread Jonathan Hull via swift-evolution
The issue of a lack of ordering is one that actually comes up a lot in Swift, 
and we don’t have a good answer for it in general.  That might be something we 
want to take a deeper look at in the Swift 5 timeframe (at least to talk about 
options).  It would help more than just concurrency…

Thanks,
Jon


> On Aug 18, 2017, at 8:51 PM, Shams Imam via swift-evolution 
>  wrote:
> 
> 
> Disclaimer: this was work done during my graduate study. It was presented in 
> front of an audience that included Gul Agha who appreciated the work.
> 
> The Actor model is great concurrency model to build on top of thanks to its 
> data isolation and asynchronous message processing properties. However, lack 
> of guarantees to control the order in which messages are processed by an 
> actor makes implementing synchronization and coordination patterns difficult 
> in the Actor model. Solutions to support such order in processing constraints 
> may require the actor to buffer messages and resend the messages to itself 
> until the message is processed. The resulting code is a petri-dish of code 
> that intertwines both algorithmic logic and synchronization constraints.
> 
> I would encourage you to look into the Selector model which is an extension 
> of the Actor model that allows an actor to have multiple mailboxes. These 
> mailboxes can be enabled/disabled to control which message is processed next 
> by the selector (in many ways this is similar to a select operation among 
> multiple channels in Communicating Sequential Processes style programs). 
> Enabling/disabling does not affect which messages are accepted at a mailbox. 
> 
> In essence, an actor is a selector with a single mailbox which is always 
> enabled. Selectors simplify writing of synchronization and coordination 
> patterns using actors such as:
> 
> a) 'synchronous' request-reply,
> b) join patterns in streaming applications,
> c) supporting priorities in message processing,
> d) variants of reader-writer concurrency, and
> e) producer-consumer with bounded buffer.
> 
> 
> Relevant links:
> http://dl.acm.org/citation.cfm?id=2687360 
> 
> Detailed description: 
> https://shamsimam.github.io/papers/2014-agere-selector.pdf 
> 
> Slides: https://shamsimam.github.io/papers/2014-agere-selector-slides.pdf 
> 
> ___
> 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] choice of actor model

2017-08-18 Thread Shams Imam via swift-evolution
Disclaimer: this was work done during my graduate study. It was presented
in front of an audience that included Gul Agha who appreciated the work.

The Actor model is great concurrency model to build on top of thanks to its
data isolation and asynchronous message processing properties. However,
lack of guarantees to control the order in which messages are processed by
an actor makes implementing synchronization and coordination patterns
difficult in the Actor model. Solutions to support such order in processing
constraints may require the actor to buffer messages and resend the
messages to itself until the message is processed. The resulting code is a
petri-dish of code that intertwines both algorithmic logic and
synchronization constraints.

I would encourage you to look into the Selector model which is an extension
of the Actor model that allows an actor to have multiple mailboxes. These
mailboxes can be enabled/disabled to control which message is processed
next by the selector (in many ways this is similar to a select operation
among multiple channels in Communicating Sequential Processes style
programs). Enabling/disabling does not affect which messages are accepted
at a mailbox.

In essence, an actor is a selector with a single mailbox which is always
enabled. Selectors simplify writing of synchronization and coordination
patterns using actors such as:

a) 'synchronous' request-reply,
b) join patterns in streaming applications,
c) supporting priorities in message processing,
d) variants of reader-writer concurrency, and
e) producer-consumer with bounded buffer.


Relevant links:
http://dl.acm.org/citation.cfm?id=2687360
Detailed description: https://shamsimam.github.io/papers/
2014-agere-selector.pdf
Slides: https://shamsimam.github.io/papers/2014-agere-selector-slides.pdf
___
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-18 Thread Yuta Koshizawa via swift-evolution
`beginAsync(_:)` is a sort of poor man's `Future`—it guarantees that the
async function will start, but throws away the return value, and *might*
throw away the error unless it happens to get thrown early. Given that its
ability to return information from the body is so limited, I frankly don't
think it's worth making this function rethrow only some errors. I would
instead make it accept only a non-throwing `async` function, and if you
need to call something that throws, you can pass an async closure with a
`do`/`catch` block.


I agree. I think `rethorws` for `beginAsync` is problematic.

For example, what happens when the `foo` in the following code throws an
`Error` asynchronously?

func foo() async throws { ... }
beginAsync(foo)

`foo` is acceptable as `beginAsync`'s `body` by its type. However its error
might be thrown asynchronously and it is impossible to rethrow it. So the
error must be ignored or treated as an universal error by untyped
propagation. It breaks type safety about error handling.

So I think the signature of `beginAsync` should be the following one.

func beginAsync(_ body: () async -> Void) -> Void

--
Yuta
___
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-18 Thread Chris Lattner via swift-evolution
On Aug 18, 2017, at 2:09 PM, Adam Kemp  wrote:
>> On Aug 18, 2017, at 12:34 PM, Adam Kemp > > wrote:
>>> For instance, say you’re handling a button click, and you need to do a 
>>> network request and then update the UI. In C# (using Xamarin.iOS as an 
>>> example) you might write some code like this:
>>> 
>>> private async void HandleButtonClick(object sender, EventArgs e) {
>>> var results = await GetStuffFromNetwork();
>>> UpdateUI(results);
>>> }
>>> 
>>> This event handler is called on the UI thread, and the UpdateUI call must 
>>> be done on the UI thread. The way async/await works in C# (by default) is 
>>> that when your continuation is called it will be on the same 
>>> synchronization context you started with. That means if you started on the 
>>> UI thread you will resume on the UI thread. If you started on some thread 
>>> pool then you will resume on that same thread pool.
>> 
>> I completely agree, I would love to see this because it is the most easy to 
>> reason about, and is implied by the syntax.  I consider this to be a 
>> follow-on to the basic async/await proposal - part of the Objective-C 
>> importer work, as described here:
>> https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#fix-queue-hopping-objective-c-completion-handlers
>>  
>> 
> Maybe I’m still missing something, but how does this help when you are 
> interacting only with Swift code? If I were to write an asynchronous method 
> in Swift then how could I do the same thing that you propose that the 
> Objective-C importer do? That is, how do I write my function such that it 
> calls back on the same queue?

You’re right: if you’re calling something written in Swift, the ObjC importer 
isn’t going to help you.

However, if you’re writing an async function in Swift, then it is reasonable 
for us to say what the convention is and expect you to follow it.  Async/await 
doesn’t itself help you implement an async operation: it would be turtles all 
the way down… until you get to GCD, which is where you do the async thing.

As such, as part of rolling out async/await in Swift, I’d expect that GCD would 
introduce new API or design patterns to support doing the right thing here.  
That is TBD as far as the proposal goes, because it doesn’t go into runtime 
issues.

>>> Another difference between the C# implementation and this proposal is the 
>>> lack of futures. While I think it’s fair to be cautious about tying this 
>>> proposal to any specific futures implementation or design, I feel like the 
>>> value of tying it to some concept of futures was somewhat overlooked. For 
>>> instance, in C# you could write a method with this signature:
>> ...
>>> 
>>> The benefit of connecting the async/await feature to the concept of futures 
>>> is that you can mix and match this code freely. The current proposal 
>>> doesn’t seem to allow this.
>> 
>> The current proposal provides an underlying mechanism that you can build 
>> futures on, and gives an example.  As shown, the experience using that 
>> futures API would work quite naturally and fit into Swift IMO.
> 
> I feel like this is trading conceptual complexity in order to gain compiler 
> simplicity. What I mean by that is that the feature feels harder to 
> understand, and the benefit seems to be that this feature can be used more 
> generally for other things. I’m not sure that’s a good tradeoff.
> 
> The other approach, which is to build a specific async/await feature using 
> compiler transformations, may be less generic (yield return would have to 
> work differently), but it seems (to me) easier to understand how to use.
> 
> For instance, this code (modified from the proposal):
> 
> @IBAction func buttonDidClick(sender:AnyObject) {  
> doSomethingOnMainThread();
> beginAsync {
> let image = await processImage()
> imageView.image = image
> }
> doSomethingElseOnMainThread();
> }
> 
> Is less straightforward than this:
> 
> @IBAction async func buttonDidClick(sender:AnyObject) {
> doSomethingOnMainThread();
> let imageTask = processImage()
> doSomethingElseOnMainThread();
> imageView.image = await imageTask
> }

This isn’t a fair transformation though, and isn’t related to whether futures 
is part of the library or language.  The simplification you got here is by 
making IBAction’s implicitly async.  I don’t see that that is possible, since 
they have a very specific calling convention (which returns void) and are 
invoked by objc_msgSend.  OTOH, if it were possible to do this, it would be 
possible to do it with the proposal as outlined.

-Chris

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


Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution
> On Aug 19, 2017, at 12:25 AM, John McCall via swift-evolution 
>  wrote:
>> On Aug 18, 2017, at 11:43 PM, Mark Lilback > > wrote:
>> 
>>> 
>>> On Aug 18, 2017, at 2:27 AM, John McCall via swift-evolution 
>>> > wrote:
>>> 
>>> Even for non-public code.  The only practical merit of typed throws I have 
>>> ever seen someone demonstrate is that it would let them use contextual 
>>> lookup in a throw or catch.  People always say "I'll be able to 
>>> exhaustively switch over my errors", and then I ask them to show me where 
>>> they want to do that, and they show me something that just logs the error, 
>>> which of course does not require typed throws.  Every.  Single.  Time.
>> 
>> We're doing it in the project I'm working on. Sure, there are some places 
>> where we just log the error. But the vast majority of the time, we're 
>> handling them. Maybe that's because we're using reactive programming and 
>> errors bubble to the top, so there's no need to write that many error 
>> handlers. And if I am just logging, either the error doesn't really matter 
>> or there is a TODO label reminding me to fix it at some point.
> 
> I'm not saying people only log errors instead of handling them in some more 
> reasonable way.  I'm saying that logging functions are the only place I've 
> ever seen someone switch over an entire error type.
> 
> I keep bringing exhaustive switches up because, as soon as you have a default 
> case, it seems to me that you haven't really lost anything vs. starting from 
> an opaque type like Error.
> 
>>> On Aug 18, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>>>  wrote:
>>> 
>>> The primary goal for me personally is to factor out and centralize code 
>>> that categorizes an error, allowing catch sites to focus on implementing 
>>> recovery instead of figuring out what went wrong.  Here’s some concrete 
>>> sample code building on the example scenario above:
>> 
>> I'm using a similar approach. Here is some stripped down code:
>> 
>> //error object used throughout project
>> public struct Rc2Error: LocalizedError, CustomStringConvertible, 
>> CustomDebugStringConvertible {
>>  /// basic categories of errors
>>  public enum Rc2ErrorType: String, Error {
>>  /// a requested object was not found
>>  case noSuchElement
>>  /// a requested operation is already in progress
>>  case alreadyInProgress
>>  /// problem parsing json, Freddy error is nested
>>  case invalidJson
>>  /// nestedError will be the NSError 
>>  case cocoa 
>>  /// nested error is related to the file system 
>>  case file 
>>  /// a wrapped error from a websocket 
>>  case websocket 
>>  /// a generic network error 
>>  case network 
>>  /// an invalid argument was passed (or parsed from json)
>>  /// wraps an unknown error
>>  case unknown
>>  }
>> 
>>  /// the generic type of the error
>>  public let type: Rc2ErrorType
>>  /// the underlying error that caused the problem
>>  public let nestedError: Error?
>>  /// location in source code of where error happened
>>  public let location: String
>> }
> 
> Okay.  I mean, this seems essentially like Swift's Error design.  The comment 
> says you use this type ubiquitously in your project.  The type completely 
> erases any differences between functions in terms of what errors they can 
> throw.  Predictably, it includes an unknown case.  Code that processes values 
> of this type must look essentially exactly like switching over an Error, 
> except that the unknown case involves explicitly matching '.unknown' instead 
> of using 'default'.
> 
>> //a domain-specific error type that will be nested
>> public enum NetworkingError {
>>  case unauthorized
>>  case unsupportedFileType
>>  case timeout
>>  case connectionError(Error)
>>  case canceled
>>  case uploadFailed(Error)
>>  case invalidHttpStatusCode(HTTPURLResponse)
>>  case restError(code: Int, message: String)
>> }
> 
> Okay.  So you're doing semantic tagging of errors — you're communicating out 
> that an error arose during a specific operation.  And having some static 
> enforcement here makes it easier to ensure that you've tagged all the errors.
> 
>> The most common errors don't need a nested error. The call site can figure 
>> out how to recover based on this. Using Result I can specifically limit 
>> what kind of errors are possible from a function without using the wrapper 
>> error. E can always be specified as Error to ignore the typed system.
> 
> I see.  So you do have some functions that use a more specific type.
> 
>> It would be great if the native swift error system 

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

2017-08-18 Thread Brent Royal-Gordon via swift-evolution
> On Aug 18, 2017, at 12:35 PM, Chris Lattner  wrote:
> 
>> (Also, I notice that a fire-and-forget message can be thought of as an 
>> `async` method returning `Never`, even though the computation *does* 
>> terminate eventually. I'm not sure how to handle that, though)
> 
> Yeah, I think that actor methods deserve a bit of magic:
> 
> - Their bodies should be implicitly async, so they can call async methods 
> without blocking their current queue or have to use beginAsync.
> - However, if they are void “fire and forget” messages, I think the caller 
> side should *not* have to use await on them, since enqueuing the message will 
> not block.

I think we need to be a little careful here—the mere fact that a message 
returns `Void` doesn't mean the caller shouldn't wait until it's done to 
continue. For instance:

listActor.delete(at: index) // Void, so it 
doesn't wait
let count = await listActor.getCount()  // But we want the count 
*after* the deletion!

Perhaps we should depend on the caller to use a future (or a `beginAsync(_:)` 
call) when they want to fire-and-forget? And yet sometimes a message truly 
*can't* tell you when it's finished, and we don't want APIs to over-promise on 
when they tell you they're done. I don't know.

> I agree.  That is one reason that I think it is important for it to have a 
> (non-defaulted) protocol requirement.  Requiring someone to implement some 
> code is a good way to get them to think about the operation… at least a 
> little bit.

I wondered if that might have been your reasoning.

> That said, the design does not try to *guarantee* memory safety, so there 
> will always be an opportunity for error.

True, but I think we could mitigate that by giving this protocol a relatively 
narrow purpose. If we eventually build three different features on 
`ValueSemantical`, we don't want all three of those features to break when 
someone abuses the protocol to gain access to actors.

>>  I also worry that the type behavior of a protocol is a bad fit for 
>> `ValueSemantical`. Retroactive conformance to `ValueSemantical` is almost 
>> certain to be an unprincipled hack; subclasses can very easily lose the 
>> value-semantic behavior of their superclasses, but almost certainly can't 
>> have value semantics unless their superclasses do. And yet having 
>> `ValueSemantical` conformance somehow be uninherited would destroy Liskov 
>> substitutability.
> 
> Indeed.  See NSArray vs NSMutableArray.
> 
> OTOH, I tend to think that retroactive conformance is really a good thing, 
> particularly in the transition period where you’d be dealing with other 
> people’s packages who haven’t adopted the model.  You may be adopting it for 
> their structs afterall.
> 
> An alternate approach would be to just say “no, you can’t do that.  If you 
> want to work around someone else’s problem, define a wrapper struct and mark 
> it as ValueSemantical”.  That design could also work.

Yeah, I think wrapper structs are a workable alternative to retroactive 
conformance.

What I basically envision (if we want to go with a general 
`ValueSemantical`-type solution) is that, rather than being a protocol, we 
would have a `value` keyword that went before the `enum`, `struct`, `class`, or 
`protocol` keyword. (This is somewhat similar to the proposed `moveonly` 
keyword.) It would not be valid before `extension`, except perhaps on a 
conditional extension that only applied when a generic or associated type was 
`value`, so retroactive conformance wouldn't really be possible. You could also 
use `value` in a generic constraint list just as you can use `class` there.

I'm not totally sure how to reconcile this with mutable subclasses, but I have 
a very vague sense it might be possible if `value` required some kind of 
*non*-inheritable initializer, and passing to a `value`-constrained parameter 
implicitly passed the value through that initializer. That is, if you had:

// As imported--in reality this would be an NS_SWIFT_VALUE_TYPE 
annotation on the Objective-C definition
value class NSArray: NSObject {
init(_ array: NSArray) { self = array.copy() as! NSArray }
}

Then Swift would implicitly add some code to an actor method like this:

actor Foo {
actor func bar(_ array: NSArray) {
let array = NSArray(array)  // Note that this is 
always `NSArray`, not the dynamic subclass of it
}
}

Since Swift would always rely on the static (compile-time) type to decide which 
initializer to use, I *think* having `value` be non-inheritable wouldn't be a 
problem here.

> It would be a perfectly valid design approach to implement actors as a 
> framework or design pattern instead of as a first class language feature.  
> You’d end up with something very close to Akka, which has provides a lot of 
> the high level abstractions, but 

Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>  wrote:
> Splitting this off into its own thread:
> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  wrote:
>> One related topic that isn’t discussed is type errors.  Many third party 
>> libraries use a Result type with typed errors.  Moving to an async / await 
>> model without also introducing typed errors into Swift would require giving 
>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>> is the right time to tackle typed errors as well.  I would be happy to help 
>> with design and drafting a proposal but would need collaborators on the 
>> implementation side.
> 
> Typed throws is something we need to settle one way or the other, and I agree 
> it would be nice to do that in the Swift 5 cycle.
> 
> For the purposes of this sub-discussion, I think there are three kinds of 
> code to think about: 
> 1) large scale API like Cocoa which evolve (adding significant functionality) 
> over the course of many years and can’t break clients. 
> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
> fall - being obsoleted and replaced by better packages if they encounter a 
> design problem.  
> 3) internal APIs and applications, which are easy to change because the 
> implementations and clients of the APIs are owned by the same people.
> 
> These each have different sorts of concerns, and we hope that something can 
> start out as #3 but work its way up the stack gracefully.
> 
> Here is where I think things stand on it:
> - There is consensus that untyped throws is the right thing for a large scale 
> API like Cocoa.  NSError is effectively proven here.  Even if typed throws is 
> introduced, Apple is unlikely to adopt it in their APIs for this reason.
> - There is consensus that untyped throws is the right default for people to 
> reach for for public package (#2).
> - There is consensus that Java and other systems that encourage lists of 
> throws error types lead to problematic APIs for a variety of reasons.
> - There is disagreement about whether internal APIs (#3) should use it.  It 
> seems perfect to be able to write exhaustive catches in this situation, since 
> everything in knowable. OTOH, this could encourage abuse of error handling in 
> cases where you really should return an enum instead of using throws.
> - Some people are concerned that introducing typed throws would cause people 
> to reach for it instead of using untyped throws for public package APIs.

Even for non-public code.  The only practical merit of typed throws I have ever 
seen someone demonstrate is that it would let them use contextual lookup in a 
throw or catch.  People always say "I'll be able to exhaustively switch over my 
errors", and then I ask them to show me where they want to do that, and they 
show me something that just logs the error, which of course does not require 
typed throws.  Every.  Single.  Time.

Sometimes we then go on to have a conversation about wrapping errors in other 
error types, and that can be interesting, but now we're talking about adding a 
big, messy feature just to get "safety" guarantees for a fairly minor need.

Programmers often have an instinct to obsess over error taxonomies that is very 
rarely directed at solving any real problem; it is just self-imposed busy-work.

> - Some people think that while it might be useful in some narrow cases, the 
> utility isn’t high enough to justify making the language more complex 
> (complexity that would intrude on the APIs of result types, futures, etc)
> 
> I’m sure there are other points in the discussion that I’m forgetting.
> 
> One thing that I’m personally very concerned about is in the systems 
> programming domain.  Systems code is sort of the classic example of code that 
> is low-level enough and finely specified enough that there are lots of 
> knowable things, including the failure modes.

Here we are using "systems" to mean "embedded systems and kernels".  And 
frankly even a kernel is a large enough system that they don't want to 
exhaustively switch over failures; they just want the static guarantees that go 
along with a constrained error type.

> Beyond expressivity though, our current model involves boxing thrown values 
> into an Error existential, something that forces an implicit memory 
> allocation when the value is large.  Unless this is fixed, I’m very concerned 
> that we’ll end up with a situation where certain kinds of systems code (i.e., 
> that which cares about real time guarantees) will not be able to use error 
> handling at all.  
> 
> JohnMC has some ideas on how to change code generation for ‘throws’ to avoid 
> this problem, but I don’t understand his ideas enough to know if they are 
> practical and likely to happen or not.

Essentially, you give Error a tagged-pointer representation to allow 
payload-less errors on non-generic error types 

Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Xiaodi Wu via swift-evolution
On Fri, Aug 18, 2017 at 6:55 PM, Greg Parker  wrote:

>
> On Aug 17, 2017, at 5:16 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Thu, Aug 17, 2017 at 6:46 PM, Taylor Swift 
> wrote:
>
>> I don’t think the “is this library functionality or standard library
>> functionality” argument is worth having, but if stdout and stdin are
>> first-class citizens in the Swift world, so should stderr.
>>
>> As for bringing Foundation into the discussion, you can’t really talk
>> about Foundation without also talking about the mountains of problems that
>> come with the monolith pattern. But that’s a completely different
>> conversation to be had.
>>
>
> I'm not sure what you're getting at here, but I don't believe you've
> addressed my question, which is: it's been firmly decided that I/O belongs
> in Foundation, and Foundation does in fact offer such facilities--what is
> missing from those facilities, and how can we fill it out?
>
>
> Lots of I/O functionality is missing from Foundation. Foundation's design
> from time immemorial is that generally only relatively simple and
> high-level operations are available in Foundation itself, and if you want
> to do complicated or non-portable things then you are expected to drop down
> to POSIX or other C interfaces. That design works less well in Swift than
> it did in Objective-C because Swift's interface with C, especially
> low-level C, is often ugly.
>
> Simple example: there is no way to access file information directly via
> NSFileHandle. You need to call NSFileHandle.fileDescriptor and pass that to
>  fstat() or fcntl(). The NSFileHandle API in general is sparse and wholly
> inadequate for sophisticated I/O.
>

So that's a good starting point for the discussion.

What, in your opinion, should be the way forward in addressing this
situation? Is there a realistic chance of writing a single comprehensive,
cross-platform API that makes possible currently "complicated or
non-portable things" on both macOS/iOS/tvOS/watchOS and Linux, and
potentially Windows? If so, does that fit within the general category of
filling out the currently sparse Foundation APIs or would that be a matter
for a separate library? In the alternative, is it the right solution to
make dropping down to POSIX marginally easier by re-exporting C APIs under
a unified name, without attempting a single cross-platform API?
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] typed throws

2017-08-18 Thread Charlie Monroe via swift-evolution

> On Aug 18, 2017, at 10:22 AM, John McCall  wrote:
> 
>> On Aug 18, 2017, at 3:28 AM, Charlie Monroe > > wrote:
>>> On Aug 18, 2017, at 8:27 AM, John McCall via swift-evolution 
>>> > wrote:
 On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
 > wrote:
 Splitting this off into its own thread:
 
> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  > wrote:
> One related topic that isn’t discussed is type errors.  Many third party 
> libraries use a Result type with typed errors.  Moving to an async / 
> await model without also introducing typed errors into Swift would 
> require giving up something that is highly valued by many Swift 
> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
> well.  I would be happy to help with design and drafting a proposal but 
> would need collaborators on the implementation side.
 
 Typed throws is something we need to settle one way or the other, and I 
 agree it would be nice to do that in the Swift 5 cycle.
 
 For the purposes of this sub-discussion, I think there are three kinds of 
 code to think about: 
 1) large scale API like Cocoa which evolve (adding significant 
 functionality) over the course of many years and can’t break clients. 
 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
 fall - being obsoleted and replaced by better packages if they encounter a 
 design problem.  
 3) internal APIs and applications, which are easy to change because the 
 implementations and clients of the APIs are owned by the same people.
 
 These each have different sorts of concerns, and we hope that something 
 can start out as #3 but work its way up the stack gracefully.
 
 Here is where I think things stand on it:
 - There is consensus that untyped throws is the right thing for a large 
 scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
 throws is introduced, Apple is unlikely to adopt it in their APIs for this 
 reason.
 - There is consensus that untyped throws is the right default for people 
 to reach for for public package (#2).
 - There is consensus that Java and other systems that encourage lists of 
 throws error types lead to problematic APIs for a variety of reasons.
 - There is disagreement about whether internal APIs (#3) should use it.  
 It seems perfect to be able to write exhaustive catches in this situation, 
 since everything in knowable. OTOH, this could encourage abuse of error 
 handling in cases where you really should return an enum instead of using 
 throws.
 - Some people are concerned that introducing typed throws would cause 
 people to reach for it instead of using untyped throws for public package 
 APIs.
>>> 
>>> Even for non-public code.  The only practical merit of typed throws I have 
>>> ever seen someone demonstrate is that it would let them use contextual 
>>> lookup in a throw or catch.  People always say "I'll be able to 
>>> exhaustively switch over my errors", and then I ask them to show me where 
>>> they want to do that, and they show me something that just logs the error, 
>>> which of course does not require typed throws.  Every.  Single.  Time.
>> 
>> The issue I see here with non-typed errors is that relying on documentation 
>> is very error-prone. I'll give an example where I've used exhaustive error 
>> catching (but then again, I was generally the only one using exhaustive enum 
>> switches when we discussed those). I've made a simple library for reporting 
>> purchases to a server. The report needs to be signed using a certificate and 
>> there are some validations to be made.
>> 
>> This generally divides the errors into three logical areas - initialization 
>> (e.g. errors when loading the certificate, etc.), validation (when the 
>> document doesn't pass validation) and sending (network error, error response 
>> from the server, etc.).
>> 
>> Instead of using a large error enum, I've split this into three enums. At 
>> this point, especially for a newcommer to the code, he may not realize which 
>> method can throw which of these error enums.
>> 
>> I've found that the app can take advantage of knowing what's wrong. For 
>> example, if some required information is missing e.g. 
>> Validation.subjectNameMissing is thrown. In such case the application can 
>> inform the user that name is missing and it can offer to open UI to enter 
>> this information (in the case of my app, the UI for sending is in the 
>> document view, while the mentioned "subject name" information is in 
>> Preferences).
>> 
>> 

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

2017-08-18 Thread Brent Royal-Gordon via swift-evolution
> On Aug 17, 2017, at 11:59 PM, Félix Cloutier via swift-evolution 
>  wrote:
> 
> The purpose of `beginAsync` is to start an `async` function while firewalling 
> against the propagation of the `async` keyword to the caller. `beginAsync` 
> does not return a value. By the time `beginAsync` returns, whatever 
> continuation closure was generated for the `body` parameter has been passed 
> off to someone else and some scheduling mechanism has a reference to it and 
> will call it later. That's not giving me too much trouble either.
> 
> I'm somewhat bugged by `suspendAsync`. My understanding is that it allows you 
> to take a synchronous function which accepts a callback and turn it into an 
> asynchronous one, where "asynchronous" means "continuation-driven" more that 
> "asynchronously executing", because something like `let foo: Int = await 
> suspendAsync { $0(42) }` looks like it should be legal (although not 
> particularly useful).
> 
> The interaction of `suspendAsync` and `await` is that `suspendAsync`, like 
> any other `async` function, accepts a hidden closure parameter, and `await` 
> takes the rest of the function and turns it into a continuation closure to 
> pass as that hidden parameter. The explicit parameters of `suspendAsync` are 
> closures that accept the continuation (either for success or failure), so 
> `suspendAsync` is the primitive that's responsible for translating the rest 
> of an `async` function into something that you can pass as a callback.
> 
> That seems to make sense to me (although I might have it wrong), but I'm 
> having trouble with the terminology. I'm not trying to start a bike shed 
> debate here; it's simply not immediately clear to me what "suspendAsync" 
> means for a function that seems more about starting an "old world" 
> asynchronous task than suspending anything (let alone an asynchronous thing).

I, too, didn't really get these at first, although the code samples illuminated 
things some for me.

`beginAsync(_:)` is a sort of poor man's `Future`—it guarantees that the async 
function will start, but throws away the return value, and *might* throw away 
the error unless it happens to get thrown early. Given that its ability to 
return information from the body is so limited, I frankly don't think it's 
worth making this function rethrow only some errors. I would instead make it 
accept only a non-throwing `async` function, and if you need to call something 
that throws, you can pass an async closure with a `do`/`catch` block.

`suspendAsync(_:)` essentially converts the async calling into completion-based 
calling, as you said. I'm not sure if there's *literally* an implicit 
completion closure or if they're doing something else—the proposal doesn't lay 
out the transformations the compiler performs in much detail. I don't want to 
open this up to bikeshedding, but I sort of think of this function as 
`runAsyncWithCompletionHandler(_:)` or, more idiomatically, 
`withAsyncCompletion(do:)`.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2017, at 3:28 AM, Charlie Monroe  wrote:
>> On Aug 18, 2017, at 8:27 AM, John McCall via swift-evolution 
>>  wrote:
>>> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>>>  wrote:
>>> Splitting this off into its own thread:
>>> 
 On Aug 17, 2017, at 7:39 PM, Matthew Johnson  
 wrote:
 One related topic that isn’t discussed is type errors.  Many third party 
 libraries use a Result type with typed errors.  Moving to an async / await 
 model without also introducing typed errors into Swift would require 
 giving up something that is highly valued by many Swift developers.  Maybe 
 Swift 5 is the right time to tackle typed errors as well.  I would be 
 happy to help with design and drafting a proposal but would need 
 collaborators on the implementation side.
>>> 
>>> Typed throws is something we need to settle one way or the other, and I 
>>> agree it would be nice to do that in the Swift 5 cycle.
>>> 
>>> For the purposes of this sub-discussion, I think there are three kinds of 
>>> code to think about: 
>>> 1) large scale API like Cocoa which evolve (adding significant 
>>> functionality) over the course of many years and can’t break clients. 
>>> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
>>> fall - being obsoleted and replaced by better packages if they encounter a 
>>> design problem.  
>>> 3) internal APIs and applications, which are easy to change because the 
>>> implementations and clients of the APIs are owned by the same people.
>>> 
>>> These each have different sorts of concerns, and we hope that something can 
>>> start out as #3 but work its way up the stack gracefully.
>>> 
>>> Here is where I think things stand on it:
>>> - There is consensus that untyped throws is the right thing for a large 
>>> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>>> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
>>> reason.
>>> - There is consensus that untyped throws is the right default for people to 
>>> reach for for public package (#2).
>>> - There is consensus that Java and other systems that encourage lists of 
>>> throws error types lead to problematic APIs for a variety of reasons.
>>> - There is disagreement about whether internal APIs (#3) should use it.  It 
>>> seems perfect to be able to write exhaustive catches in this situation, 
>>> since everything in knowable. OTOH, this could encourage abuse of error 
>>> handling in cases where you really should return an enum instead of using 
>>> throws.
>>> - Some people are concerned that introducing typed throws would cause 
>>> people to reach for it instead of using untyped throws for public package 
>>> APIs.
>> 
>> Even for non-public code.  The only practical merit of typed throws I have 
>> ever seen someone demonstrate is that it would let them use contextual 
>> lookup in a throw or catch.  People always say "I'll be able to exhaustively 
>> switch over my errors", and then I ask them to show me where they want to do 
>> that, and they show me something that just logs the error, which of course 
>> does not require typed throws.  Every.  Single.  Time.
> 
> The issue I see here with non-typed errors is that relying on documentation 
> is very error-prone. I'll give an example where I've used exhaustive error 
> catching (but then again, I was generally the only one using exhaustive enum 
> switches when we discussed those). I've made a simple library for reporting 
> purchases to a server. The report needs to be signed using a certificate and 
> there are some validations to be made.
> 
> This generally divides the errors into three logical areas - initialization 
> (e.g. errors when loading the certificate, etc.), validation (when the 
> document doesn't pass validation) and sending (network error, error response 
> from the server, etc.).
> 
> Instead of using a large error enum, I've split this into three enums. At 
> this point, especially for a newcommer to the code, he may not realize which 
> method can throw which of these error enums.
> 
> I've found that the app can take advantage of knowing what's wrong. For 
> example, if some required information is missing e.g. 
> Validation.subjectNameMissing is thrown. In such case the application can 
> inform the user that name is missing and it can offer to open UI to enter 
> this information (in the case of my app, the UI for sending is in the 
> document view, while the mentioned "subject name" information is in 
> Preferences).
> 
> This way I exhaustively switch over the error enums, suggesting to the user 
> solution of the particular problem without dumbing down to a message "Oops, 
> something went wrong, but I have no idea what because this kind of error is 
> not handled.".

Surely you must have a message like that.  You're 

Re: [swift-evolution] typed throws

2017-08-18 Thread Gwendal Roué via swift-evolution
Hello all,

I'm also on the "side" of untyped errors, but I can imagine how other 
developers may like a stricter error hierarchy. It surely fits some situations.

Enter Result and Result:

Since Swift "native" errors don't fit well with asynchronous APIs, various ways 
to encapsulate them have emerged, most of them eventually relying on some kind 
of variant of those `Result` type:

// Untyped errors
enum Result {
case success(T)
case failure(Error)
}

// Typed errors
enum Result {
case success(T)
case failure(E)
}

The first Result fits well people who like untyped errors. And Result 
fits people who prefer typed errors. Result is objectively closer to the 
"spirit" of Swift 2-4. Yet Result has the right to live as well.

When Swift 5 brings sugar syntax around async/await/etc, most needs for 
Result will naturally vanish.

However, the need for Result will remain. The debate about "typed 
throws", for me, sums up to this question: will the typed folks be able to take 
profit from the syntax sugar brought by async/await/etc of Swift 5? Or will 
they have to keep on carrying Result with them?

Gwendal Roué



> Le 18 août 2017 à 10:23, John McCall via swift-evolution 
>  a écrit :
> 
>> On Aug 18, 2017, at 3:28 AM, Charlie Monroe > > wrote:
>>> On Aug 18, 2017, at 8:27 AM, John McCall via swift-evolution 
>>> > wrote:
 On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
 > wrote:
 Splitting this off into its own thread:
 
> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  > wrote:
> One related topic that isn’t discussed is type errors.  Many third party 
> libraries use a Result type with typed errors.  Moving to an async / 
> await model without also introducing typed errors into Swift would 
> require giving up something that is highly valued by many Swift 
> developers.  Maybe Swift 5 is the right time to tackle typed errors as 
> well.  I would be happy to help with design and drafting a proposal but 
> would need collaborators on the implementation side.
 
 Typed throws is something we need to settle one way or the other, and I 
 agree it would be nice to do that in the Swift 5 cycle.
 
 For the purposes of this sub-discussion, I think there are three kinds of 
 code to think about: 
 1) large scale API like Cocoa which evolve (adding significant 
 functionality) over the course of many years and can’t break clients. 
 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
 fall - being obsoleted and replaced by better packages if they encounter a 
 design problem.  
 3) internal APIs and applications, which are easy to change because the 
 implementations and clients of the APIs are owned by the same people.
 
 These each have different sorts of concerns, and we hope that something 
 can start out as #3 but work its way up the stack gracefully.
 
 Here is where I think things stand on it:
 - There is consensus that untyped throws is the right thing for a large 
 scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
 throws is introduced, Apple is unlikely to adopt it in their APIs for this 
 reason.
 - There is consensus that untyped throws is the right default for people 
 to reach for for public package (#2).
 - There is consensus that Java and other systems that encourage lists of 
 throws error types lead to problematic APIs for a variety of reasons.
 - There is disagreement about whether internal APIs (#3) should use it.  
 It seems perfect to be able to write exhaustive catches in this situation, 
 since everything in knowable. OTOH, this could encourage abuse of error 
 handling in cases where you really should return an enum instead of using 
 throws.
 - Some people are concerned that introducing typed throws would cause 
 people to reach for it instead of using untyped throws for public package 
 APIs.
>>> 
>>> Even for non-public code.  The only practical merit of typed throws I have 
>>> ever seen someone demonstrate is that it would let them use contextual 
>>> lookup in a throw or catch.  People always say "I'll be able to 
>>> exhaustively switch over my errors", and then I ask them to show me where 
>>> they want to do that, and they show me something that just logs the error, 
>>> which of course does not require typed throws.  Every.  Single.  Time.
>> 
>> The issue I see here with non-typed errors is that relying on 

Re: [swift-evolution] typed throws

2017-08-18 Thread Charlie Monroe via swift-evolution

> On Aug 18, 2017, at 8:27 AM, John McCall via swift-evolution 
>  wrote:
> 
>> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>>  wrote:
>> Splitting this off into its own thread:
>> 
>>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  wrote:
>>> One related topic that isn’t discussed is type errors.  Many third party 
>>> libraries use a Result type with typed errors.  Moving to an async / await 
>>> model without also introducing typed errors into Swift would require giving 
>>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>>> is the right time to tackle typed errors as well.  I would be happy to help 
>>> with design and drafting a proposal but would need collaborators on the 
>>> implementation side.
>> 
>> Typed throws is something we need to settle one way or the other, and I 
>> agree it would be nice to do that in the Swift 5 cycle.
>> 
>> For the purposes of this sub-discussion, I think there are three kinds of 
>> code to think about: 
>> 1) large scale API like Cocoa which evolve (adding significant 
>> functionality) over the course of many years and can’t break clients. 
>> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
>> fall - being obsoleted and replaced by better packages if they encounter a 
>> design problem.  
>> 3) internal APIs and applications, which are easy to change because the 
>> implementations and clients of the APIs are owned by the same people.
>> 
>> These each have different sorts of concerns, and we hope that something can 
>> start out as #3 but work its way up the stack gracefully.
>> 
>> Here is where I think things stand on it:
>> - There is consensus that untyped throws is the right thing for a large 
>> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
>> reason.
>> - There is consensus that untyped throws is the right default for people to 
>> reach for for public package (#2).
>> - There is consensus that Java and other systems that encourage lists of 
>> throws error types lead to problematic APIs for a variety of reasons.
>> - There is disagreement about whether internal APIs (#3) should use it.  It 
>> seems perfect to be able to write exhaustive catches in this situation, 
>> since everything in knowable. OTOH, this could encourage abuse of error 
>> handling in cases where you really should return an enum instead of using 
>> throws.
>> - Some people are concerned that introducing typed throws would cause people 
>> to reach for it instead of using untyped throws for public package APIs.
> 
> Even for non-public code.  The only practical merit of typed throws I have 
> ever seen someone demonstrate is that it would let them use contextual lookup 
> in a throw or catch.  People always say "I'll be able to exhaustively switch 
> over my errors", and then I ask them to show me where they want to do that, 
> and they show me something that just logs the error, which of course does not 
> require typed throws.  Every.  Single.  Time.

The issue I see here with non-typed errors is that relying on documentation is 
very error-prone. I'll give an example where I've used exhaustive error 
catching (but then again, I was generally the only one using exhaustive enum 
switches when we discussed those). I've made a simple library for reporting 
purchases to a server. The report needs to be signed using a certificate and 
there are some validations to be made.

This generally divides the errors into three logical areas - initialization 
(e.g. errors when loading the certificate, etc.), validation (when the document 
doesn't pass validation) and sending (network error, error response from the 
server, etc.).

Instead of using a large error enum, I've split this into three enums. At this 
point, especially for a newcommer to the code, he may not realize which method 
can throw which of these error enums.

I've found that the app can take advantage of knowing what's wrong. For 
example, if some required information is missing e.g. 
Validation.subjectNameMissing is thrown. In such case the application can 
inform the user that name is missing and it can offer to open UI to enter this 
information (in the case of my app, the UI for sending is in the document view, 
while the mentioned "subject name" information is in Preferences).

This way I exhaustively switch over the error enums, suggesting to the user 
solution of the particular problem without dumbing down to a message "Oops, 
something went wrong, but I have no idea what because this kind of error is not 
handled.".

Alternatives I've considered:

- wrapping all the errors into an "Error" enum which would switch over type of 
the error, which is not a great solution as in some cases you only throw one 
type of error
- I could throw some error that only contains 

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

2017-08-18 Thread Félix Cloutier via swift-evolution
I'm glad to see this moving forward. I have a few questions and comments.

First, I'd like it if someone could clarify for me what beginAsync and 
suspendAsync "actually do", and how they interact with `async` functions. I'm 
throwing a lot of good will at this but my brain is still fairly 
imperatively-wired, so let me try to rephrase this in more procedural terms and 
let's see if I got anything wrong.

My understanding is that an `async` function takes its continuation closure as 
a hidden parameter. That closure accepts as a parameter the "asynchronous 
return type" of the function. In other words:

func foo() async -> Int

Can (give or take error handling and parameter names) be rewritten as:

func foo(completion: (Int) -> Void) -> Void

This is fairly straightforward; it's just the inverse transformation of what's 
shown in the conversion section 
.

The purpose of `beginAsync` is to start an `async` function while firewalling 
against the propagation of the `async` keyword to the caller. `beginAsync` does 
not return a value. By the time `beginAsync` returns, whatever continuation 
closure was generated for the `body` parameter has been passed off to someone 
else and some scheduling mechanism has a reference to it and will call it 
later. That's not giving me too much trouble either.

I'm somewhat bugged by `suspendAsync`. My understanding is that it allows you 
to take a synchronous function which accepts a callback and turn it into an 
asynchronous one, where "asynchronous" means "continuation-driven" more that 
"asynchronously executing", because something like `let foo: Int = await 
suspendAsync { $0(42) }` looks like it should be legal (although not 
particularly useful).

The interaction of `suspendAsync` and `await` is that `suspendAsync`, like any 
other `async` function, accepts a hidden closure parameter, and `await` takes 
the rest of the function and turns it into a continuation closure to pass as 
that hidden parameter. The explicit parameters of `suspendAsync` are closures 
that accept the continuation (either for success or failure), so `suspendAsync` 
is the primitive that's responsible for translating the rest of an `async` 
function into something that you can pass as a callback.

That seems to make sense to me (although I might have it wrong), but I'm having 
trouble with the terminology. I'm not trying to start a bike shed debate here; 
it's simply not immediately clear to me what "suspendAsync" means for a 
function that seems more about starting an "old world" asynchronous task than 
suspending anything (let alone an asynchronous thing).


Flurry of small questions:

* How does this interact with reference counting? The `suspendAsync` functions 
mark that its closures are @escaping,  yet `async` functions don't seem to need 
to write `self` to access members. What are the dangers?
* Are there ObjC functions right now whose continuation resembles 
`void(^)(Image* __nullable, Image* __nullable, NSError
* error))`, but for which only one of either the first or second Image 
parameter has a value if the call succeeded?
* in the DispatchQueue example, is there a meaningful difference between 
`syncCoroutine` and `asyncCoroutine`? Seems to me that `sync` is currently 
useful when you need your result before you return, but that doesn't really 
make sense to me in the context of an async function. Barring deadlocks in the 
synchronous version, the calling async function should return at the same time 
in both cases.
* Nit: the DispatchQueue example probably means `self.async`, and probably 
means `{ continuation() }` (and if not, someone needs to explain me what's 
going on).


The question where I just can't not get ahead of myself: you wrote that the 
underlying support can be used to implement generators. This is a feature that 
is very close to my heart. I understand that the compiler work that turns part 
of a function into a closure can be reused there; what about the higher-level 
stuff, do we foresee a set of more or less analogous keywords for generators, 
or should the async/await terminology be good enough to encompass any type of 
coroutine-based execution?


Thanks!

Félix

> Le 17 août 2017 à 15:25, Chris Lattner via swift-evolution 
>  a écrit :
> 
>> 
>> On Aug 17, 2017, at 3:24 PM, Chris Lattner > > 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 

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

2017-08-18 Thread Brent Royal-Gordon via swift-evolution
> On Aug 17, 2017, at 11:34 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> * I haven't yet read the rest of the thread—this email is already long enough.

The detailed async/await proposal cleared up a few bits for me—in particular, I 
clearly misunderstood how closely coupled `await` was to the expression with 
asynchronous components—so please ignore these sections of my email:

> ## Delayed `await`
> ## Legacy interop
> ## Implementation

The "Future directions" section also answers the major question in "Dispatching 
back to the original queue"—you imagine it being done by the Objective-C 
importer—although my question about how it would be implemented remains. (I'm 
also not sure this is really just an Obj-C issue—queue confusion is a Swift 
problem, too—but that's a somewhat different point.)

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Tino Heth via swift-evolution

> The only practical merit of typed throws I have ever seen someone demonstrate 
> is that it would let them use contextual lookup in a throw or catch.  People 
> always say "I'll be able to exhaustively switch over my errors", and then I 
> ask them to show me where they want to do that, and they show me something 
> that just logs the error, which of course does not require typed throws.  
> Every.  Single.  Time.

I think the aspect of documentation shouldn't be underestimated:
People want to know what might go wrong — even if they have only a single 
reaction to all cases at their disposal.

Typed throws could also help to lessen the tight coupling to Objective-C:
Being forced to declare conformance to a protocol without requirements or even 
public methods feels very awkward to me.
In some way, throws are typed already, but there's just one type allowed, and 
it can't be changed.

Imho the big problem of the whole topic is the bad experience people had with 
typed throws in Java; I don't see a problem in adding typed throws and keeping 
Error as default type to be thrown if nothing else is specified.

If people want to build huge lists of possible errors… why not? As long as I'm 
still able to write my own throwing functions as today, I'm fine with that.

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


Re: [swift-evolution] typed throws

2017-08-18 Thread John McCall via swift-evolution

> On Aug 18, 2017, at 3:24 AM, Tino Heth <2...@gmx.de> wrote:
> 
> 
>> The only practical merit of typed throws I have ever seen someone 
>> demonstrate is that it would let them use contextual lookup in a throw or 
>> catch.  People always say "I'll be able to exhaustively switch over my 
>> errors", and then I ask them to show me where they want to do that, and they 
>> show me something that just logs the error, which of course does not require 
>> typed throws.  Every.  Single.  Time.
> 
> I think the aspect of documentation shouldn't be underestimated:
> People want to know what might go wrong — even if they have only a single 
> reaction to all cases at their disposal.

There's no reason we couldn't do some tooling work to expose emergent 
information about what kinds of errors are thrown by the current implementation 
of a function, and maybe even check that against the current documentation.  
Certainly, it should be possible to document particularly interesting errors 
that a function might throw.  I'm just challenging the idea that this should be 
reflected and enforced in the type system.

> Typed throws could also help to lessen the tight coupling to Objective-C:
> Being forced to declare conformance to a protocol without requirements or 
> even public methods feels very awkward to me.

Error is not about Objective-C interop; we could make the feature work without 
a protocol, and in fact the protocol alone isn't sufficient for what we try to 
do with it.  The protocol's value is mostly communicative, a way of making it 
obvious that a type is meant to be thrown, as well as to verify that you aren't 
accidentally throwing something nonsensical.

It also gives us a hook to add defaulted requirements in a later release.

> In some way, throws are typed already, but there's just one type allowed, and 
> it can't be changed.
> 
> Imho the big problem of the whole topic is the bad experience people had with 
> typed throws in Java; I don't see a problem in adding typed throws and 
> keeping Error as default type to be thrown if nothing else is specified.

The problems people have with typed throws in Java aren't ultimately because of 
some specific failure of Java (although there are certainly ways in which 
Java's design could be better in my opinion).  They pretty much all arise 
directly from conceptual problems with the idea of "restricted" sets of errors.

> If people want to build huge lists of possible errors… why not? As long as 
> I'm still able to write my own throwing functions as today, I'm fine with 
> that.

Language features have to meet a higher bar than "why not?".

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


[swift-evolution] Fast enums (was: typed throws)

2017-08-18 Thread Jonathan Hull via swift-evolution

The typed throws discussion brought me back to an old thought.

I would really like to see a new structural type, similar to tuples, which act 
as an anonymous enum.  These would actually be a distinct type from enums (not 
sure what to call them), in the same way that structs and tuples are different. 
 They would have a very similar syntax to enums though, so they would be easy 
to learn.

There would be two major difference from enums:

1) Because they are structural, they can’t have associated functions or 
extensions

2) They can concatenate with one another freely 

For example:

func foo( speed: .slow | .med | .fast ){
bar(speed: speed)
}

func bar(speed: .slow | .med | .fast | .ludicrous) {
//but we couldn't call foo here because it doesn’t take 
.ludicrous
}

Each case is it’s own mini-type in a way.  One ‘.slow’ is equivalent to any 
‘.slow’ (even one from a regular enum). Essentially, it is a loosely bound 
group of cases, and type checking just means seeing if the list/value being 
passed is a subset of the list of possible cases.

I’d also like to see sugar for quick conversion from normal Swift enums:

enum Speed {
case slow
case med
case fast
}

func foo(speed: Speed | .ludicrous) {
//we can’t call any functions/extensions of Speed, just like we 
can’t call a func from int on (Int, Int) 
}

In the above case, Speed gets converted via sugar to “.speed(Speed)” and then 
gets concatenated with .ludicrous. Ideally, it would have the added ability to 
truly convert to ".slow | .med | .fast | .ludicrous” when passed to something 
that doesn’t know about Speed:

func foo(speed: Speed | .ludicrous) {
switch speed {
case .speed(let s): //Do something with the Speed value
case .ludicrous: //Do something ludicrous
} 
bar(speed: speed) //This can convert to pass by unwrapping 
Speed to a bag of cases
}

func bar(speed: .slow | .med | .fast | .ludicrous) {
switch speed {
case .slow: //
case .med: //
case .fast: //
case .ludicrous: //
}
//We can’t reference Speed above because we just passed a bag 
of potential cases
}


The end result here is that in addition to building one-off enums quickly, it 
lets us concatenate and extend enums for use in a limited scope.  I don’t know 
about you, but I run into the situation of “I want exactly this enum, but with 
one extra case” all the time.

I don’t know if we want typed throws, but this type of quick concatability 
would be very useful for adding/merging potential errors.  With the same sugar 
used on Speed above, it would also allow something similar to Union types, but 
without the most of the implementation headache that would cause.  You can take 
in multiple types, and you get back something you can switch on to recover the 
type which was passed:

func myFakeUnion(_ intOrStr: Int | String){
switch intOrStr {
case .int(let i): //Do something with int
case .string(let s): //Do something with string
}
} 

myFakeUnion(12) //Sugar!
myFakeUnion(.string(“Hey”)) //This works too


Finally, I would love to see the switch equivalent of ‘a ? b : c’ in Swift.  I 
am not sure what the best syntax would be, but it would essentially work a bit 
like like a dictionary:

let mph = speed ? [.slow:10, .med:35, .fast:75]


Thanks,
Jon




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


Re: [swift-evolution] typed throws

2017-08-18 Thread Tino Heth via swift-evolution
> There's no reason we couldn't do some tooling work to expose emergent 
> information about what kinds of errors are thrown by the current 
> implementation of a function, and maybe even check that against the current 
> documentation.  Certainly, it should be possible to document particularly 
> interesting errors that a function might throw.
I'd prefer moving some complicated and controversial questions out of the 
language level, and probably, this might be such a case — but I think the 
preferred syntax would not be "throws(NetworkError, MyError) func mayFail() 
throws", but rather something that looks much more integrated ("func mayFail() 
throws(NetworkError, MyError)")

> I'm just challenging the idea that this should be reflected and enforced in 
> the type system.
Yes, I think this might be a can of worms — just imagine rethrows, where some 
errors will always be caught, so that ultimately, we would steer towards some 
kind of type algebra just for errors...

>> Typed throws could also help to lessen the tight coupling to Objective-C:
>> Being forced to declare conformance to a protocol without requirements or 
>> even public methods feels very awkward to me.
> 
> Error is not about Objective-C interop; we could make the feature work 
> without a protocol, and in fact the protocol alone isn't sufficient for what 
> we try to do with it.  The protocol's value is mostly communicative, a way of 
> making it obvious that a type is meant to be thrown
I guess nearly all uses look like "XYError: Error", so I really don't see much 
value in the protocol; but to me, it always feels a little bit dirty when 
language features are entwined with certain types, so it might be just a 
personal oddity.

>> If people want to build huge lists of possible errors… why not? As long as 
>> I'm still able to write my own throwing functions as today, I'm fine with 
>> that.
> 
> Language features have to meet a higher bar than "why not?".
That was more geared towards something I'd consider as derailed use — but it 
seems we agree that typed throws don't have to be something to bother the 
compiler with.

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


Re: [swift-evolution] pitch: Unified libc import (again)

2017-08-18 Thread Xiaodi Wu via swift-evolution
Not “fundamentally” incompatible:

var stderr = FileHandle.standardError
/* Conform FileHandle to TextOutputStream */
print("foo", to: )


On Fri, Aug 18, 2017 at 01:39 Brent Royal-Gordon 
wrote:

> On Aug 17, 2017, at 8:20 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> * stderr should go wherever stdin and stdout go. Since it’d be silly for
>> a function like `print(_:separator:terminator:)` or `
>> readLine(strippingNewline:)` to live anywhere but the standard library,
>> then it stands to reason that the stderr version should also live in the
>> standard library.
>>
>
> FWIW, FileHandle.standardInput, FileHandle.standardError,
> FileHandle.standardOutput, and FileHandle.nullDevice all live in Foundation.
>
>
> And, since they're read-only, are fundamentally incompatible with
> `print(…to:)`, which requires its `output` parameter to be passed `inout`.
>
> --
> Brent Royal-Gordon
> Architechies
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] typed throws

2017-08-18 Thread Johannes Weiß via swift-evolution
Hi John,

tl;dr I think throws should be optionally typed. Ie. `func someSyscall(...) 
throws(POSIXError) -> Int` should be just as legal as `func 
doSomeFancyCocoaOperation() throws -> Void`.

> [...]
>> Here is where I think things stand on it:
>> - There is consensus that untyped throws is the right thing for a large 
>> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
>> reason.
>> - There is consensus that untyped throws is the right default for people to 
>> reach for for public package (#2).
>> - There is consensus that Java and other systems that encourage lists of 
>> throws error types lead to problematic APIs for a variety of reasons.
>> - There is disagreement about whether internal APIs (#3) should use it.  It 
>> seems perfect to be able to write exhaustive catches in this situation, 
>> since everything in knowable. OTOH, this could encourage abuse of error 
>> handling in cases where you really should return an enum instead of using 
>> throws.
>> - Some people are concerned that introducing typed throws would cause people 
>> to reach for it instead of using untyped throws for public package APIs.
> 
> Even for non-public code.  The only practical merit of typed throws I have 
> ever seen someone demonstrate is that it would let them use contextual lookup 
> in a throw or catch.  People always say "I'll be able to exhaustively switch 
> over my errors", and then I ask them to show me where they want to do that, 
> and they show me something that just logs the error, which of course does not 
> require typed throws.  Every. Single.  Time.

I just grep'ed through some code and what I always see is this:

} catch let e {
fatalError("unexcepted error caught: \(e)")
}

most of the code is fairly low-level and the only error thrown in there is a 
POSIXError which basically holds the errno value and a string describing the 
failed syscall. I find this a very common pattern. Also the IMHO quite 
widespread use of Result types shows that there are valid uses of a typed 
error mechanism. On the other hand requiring a high-level Cocoa method to 
declare all errors doesn't seem right either. So why not optionally typing the 
throws?



> [...]

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution


Sent from my iPad

On Aug 18, 2017, at 1:27 AM, John McCall  wrote:

>> On Aug 18, 2017, at 12:58 AM, Chris Lattner via swift-evolution 
>>  wrote:
>> Splitting this off into its own thread:
>> 
>>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  wrote:
>>> One related topic that isn’t discussed is type errors.  Many third party 
>>> libraries use a Result type with typed errors.  Moving to an async / await 
>>> model without also introducing typed errors into Swift would require giving 
>>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>>> is the right time to tackle typed errors as well.  I would be happy to help 
>>> with design and drafting a proposal but would need collaborators on the 
>>> implementation side.
>> 
>> Typed throws is something we need to settle one way or the other, and I 
>> agree it would be nice to do that in the Swift 5 cycle.
>> 
>> For the purposes of this sub-discussion, I think there are three kinds of 
>> code to think about: 
>> 1) large scale API like Cocoa which evolve (adding significant 
>> functionality) over the course of many years and can’t break clients. 
>> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
>> fall - being obsoleted and replaced by better packages if they encounter a 
>> design problem.  
>> 3) internal APIs and applications, which are easy to change because the 
>> implementations and clients of the APIs are owned by the same people.
>> 
>> These each have different sorts of concerns, and we hope that something can 
>> start out as #3 but work its way up the stack gracefully.
>> 
>> Here is where I think things stand on it:
>> - There is consensus that untyped throws is the right thing for a large 
>> scale API like Cocoa.  NSError is effectively proven here.  Even if typed 
>> throws is introduced, Apple is unlikely to adopt it in their APIs for this 
>> reason.
>> - There is consensus that untyped throws is the right default for people to 
>> reach for for public package (#2).
>> - There is consensus that Java and other systems that encourage lists of 
>> throws error types lead to problematic APIs for a variety of reasons.
>> - There is disagreement about whether internal APIs (#3) should use it.  It 
>> seems perfect to be able to write exhaustive catches in this situation, 
>> since everything in knowable. OTOH, this could encourage abuse of error 
>> handling in cases where you really should return an enum instead of using 
>> throws.
>> - Some people are concerned that introducing typed throws would cause people 
>> to reach for it instead of using untyped throws for public package APIs.
> 
> Even for non-public code.  The only practical merit of typed throws I have 
> ever seen someone demonstrate is that it would let them use contextual lookup 
> in a throw or catch.  People always say "I'll be able to exhaustively switch 
> over my errors", and then I ask them to show me where they want to do that, 
> and they show me something that just logs the error, which of course does not 
> require typed throws.  Every.  Single.  Time.

I agree that exhaustive switching over errors is something that people are 
extremely likely to actually want to do.  I also think it's a bit of a red 
herring.  The value of typed errors is *not* in exhaustive switching.  It is in 
categorization and verified documentation.

Here is a concrete example that applies to almost every app.  When you make a 
network request there are many things that could go wrong to which you may want 
to respond differently:
* There might be no network available.  You might recover by updating the UI to 
indicate that and start monitoring for a reachability change.
* There might have been a server error that should eventually be resolved 
(500).  You might update the UI and provide the user the ability to retry.
* There might have been an unrecoverable server error (404).  You will update 
the UI.
* There might have been a low level parsing error (bad JSON, etc).  Recovery is 
perhaps similar in nature to #2, but the problem is less likely to be resolved 
quickly so you may not provide a retry option.  You might also want to do 
something to notify your dev team that the server is returning JSON that can't 
be parsed.
* There might have been a higher-level parsing error (converting JSON to model 
types).  This might be treated the same as bad JSON.  On the other hand, 
depending on the specifics of the app, you might take an alternate path that 
only parses the most essential model data in hopes that the problem was 
somewhere else and this parse will succeed.

All of this can obviously be accomplished with untyped errors.  That said, 
using types to categorize errors would significantly improve the clarity of 
such code.  More importantly, I believe that by categorizing errors in ways 
that are most relevant to a specific domain a library (perhaps internal 

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

2017-08-18 Thread Michel Fortin via swift-evolution
Great writeup. Here's a few comments about the manifesto, actors and value 
semantics specifically.


# About actors and data isolation

Can I call global functions like sin(x) in an actor? Surely you need to be able 
to do that. But how can the compiler know which functions are safe to use and 
which are out of bound for an actor?

Actors shouldn't access the global mutable state and thus should only call 
functions that do not access the global mutable state. We probably need a 
concept of a functions being pure (as in not accessing the global mutable 
state) for that.


# About the part "Does a type provide proper value semantics?"

I would argue that this is the wrong question. Most types are a hybrid form of 
value and reference semantics. All you need is to limit what you do to what is 
proper value semantics and forbid the parts that use reference semantics. 
Otherwise you are pessimising the capabilities of the types.

For instance, has Array value semantics? You might be tempted to say 
that it does not because it contains class references, but in reality that 
depends on what you do with those UIViews. If you treat the class references as 
opaque pointers (never dereferencing them), you preserve value semantics. You 
can count the elements, shuffle them, all without dereferencing the UIViews it 
contains. Value semantics only end when you dereference the class references. 
And even then, there are some exceptions.


I suggested a little while ago on this list some principles based on this that 
would allow for the compiler to enforce value semantics with a `pure` attribute 
and I'm currently working on a draft proposal. In essence this proposal will 
have pure functions guaranteeing value semantics and no access to the global 
state, and a correct implementation for copy-on-write types. I think this would 
be useful for actors.



> Le 17 août 2017 à 18:24, Chris Lattner via swift-evolution 
>  a écrit :
> 
> 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



-- 
Michel Fortin
https://michelf.ca

___
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-18 Thread Matthew Johnson via swift-evolution

> On Aug 18, 2017, at 9:19 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> Great writeup. Here's a few comments about the manifesto, actors and value 
> semantics specifically.
> 
> 
> # About actors and data isolation
> 
> Can I call global functions like sin(x) in an actor? Surely you need to be 
> able to do that. But how can the compiler know which functions are safe to 
> use and which are out of bound for an actor?
> 
> Actors shouldn't access the global mutable state and thus should only call 
> functions that do not access the global mutable state. We probably need a 
> concept of a functions being pure (as in not accessing the global mutable 
> state) for that.
> 
> 
> # About the part "Does a type provide proper value semantics?"
> 
> I would argue that this is the wrong question. Most types are a hybrid form 
> of value and reference semantics. All you need is to limit what you do to 
> what is proper value semantics and forbid the parts that use reference 
> semantics. Otherwise you are pessimising the capabilities of the types.
> 
> For instance, has Array value semantics? You might be tempted to say 
> that it does not because it contains class references, but in reality that 
> depends on what you do with those UIViews. If you treat the class references 
> as opaque pointers (never dereferencing them), you preserve value semantics. 
> You can count the elements, shuffle them, all without dereferencing the 
> UIViews it contains. Value semantics only end when you dereference the class 
> references. And even then, there are some exceptions.
> 
> 
> I suggested a little while ago on this list some principles based on this 
> that would allow for the compiler to enforce value semantics with a `pure` 
> attribute and I'm currently working on a draft proposal. In essence this 
> proposal will have pure functions guaranteeing value semantics and no access 
> to the global state, and a correct implementation for copy-on-write types. I 
> think this would be useful for actors.

It’s great to hear that you’re returning to the topic of pure functions Michel! 
 Please let me know if there is anything I can do to help.

> 
> 
> 
>> Le 17 août 2017 à 18:24, Chris Lattner via swift-evolution 
>> > a écrit :
>> 
>> 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
> 
> 
> 
> -- 
> 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] [Concurrency] async/await + actors

2017-08-18 Thread Elviro Rocca via swift-evolution
I'm also available to help on the topic of pure functions, if you need any :)


Elviro


> I suggested a little while ago on this list some principles based on this 
> that would allow for the compiler to enforce value semantics with a `pure` 
> attribute and I'm currently working on a draft proposal. In essence this 
> proposal will have pure functions guaranteeing value semantics and no access 
> to the global state, and a correct implementation for copy-on-write types. I 
> think this would be useful for actors.
> 
> -- 
> Michel Fortin
> https://michelf.ca 

___
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-18 Thread Elviro Rocca via swift-evolution
Thanks a lot for this piece: it was a great read, that could serve as primer to 
most discussions about async programming in general, also thanks to the various 
links and references.

Here's my thoughts:

- You might have been too soft on the callback-based syntax of many Cocoa APIs: 
those are really bad, and in general a pain to use. Of course a import strategy 
for future Swift will be needed, but I wouldn't consider design constraints 
exclusively derived from some Cocoa APIs shortcomings, like 
URLSession.dataTask(withURL:completionHandler:) that I think can be safely 
ignored.

- I agree on the focus on async/await as compiler-level tools for defining and 
using coroutines, with Future and stuff like that to be considered as 
library functions built on top of the syntax: this way async/await doesn't 
become mere syntactic sugar.

- I really STRONGLY disagree on conflating async and throws: they are different 
things, and exist for different purposes, the same way as Future and 
Result are different things and should be usable separately. The right way 
to handle a "failable" future is to simply use a Future, and 
eventually define convenience functions for the "success" and "failure" cases, 
or event methods on Future (in this case a ResultType protocol would be 
needed). It's a lot better to define simpler concepts that compose in 
interesting ways, rather than conflating unrelated things for minor 
conveniences.

- async/await is good, but the Actor model part is simply glorious :D

- I'm so happy that adding a native idiomatic Actor model has been considered 
for Swift, and I like the interplay with await for making actor functions 
return, as well as the progressive disclosure that can be achieved with more 
and more restrictive keywords: it even seems to me a real step-up from existing 
implementations of the model.

- in general I think that one of the best (if not the best) features of Swift 
is the idea of progressive disclosure, and that should be preserved... and I'm 
a fan of "actor class" :D

- I like the "ValueSemantical" protocol idea, but eventually I would like Swift 
to have features to actually enforce safe patterns though the language itself, 
like a "pure" or "safe" keyword: I almost use no classes (excluding the UIKit 
ones that I'm forced to use) and mostly write pure functions, but as the 
language forces me to do extra work when I'm dealing with an Optional or a 
throwing function, and that's a good thing in my opinion and facilitates my 
work as a software engineer, I would love a language that warned me that I'm 
accessing a potentially mutable instance with reference semantics in a context 
that I'm mistakenly considering as pure, or that the function I'm writing is 
not actually pure because a non-pure function was called inside it.

- I love the way the "actor" keyword for a method transforms it in an "inbox": 
I think the implementation you're proposing is super "Swifty" and could appear 
so convenient that many people could be drawn to the language just thanks to 
the great native concurrency model; I think that a powerful but simple and 
usable concurrency model is a heavy motivation for adopting a certain language 
in many contexts.


Thanks


Elviro

> Il giorno 18 ago 2017, alle ore 00:24, Chris Lattner via swift-evolution 
>  ha scritto:
> 
> 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


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

2017-08-18 Thread Thomas via swift-evolution
I have been writing a lot of fully async code over the recent years (in objc) 
and this all seems to fit well with what we're doing and looks like it would 
alleviate a lot of the pain we have writing asyc code.

# Extending the model through await

I'm a bit worried about the mention of dispatch_sync() here (although it may 
just be there to illustrate the deadlock possibility). I know the actor runtime 
implementation is not yet defined, but just wanted to mention that 
dispatch_sync() will lead to problems such as this annoying thing called thread 
explosion. This is why we currently cannot use properties in our code (getters 
would require us to call dispatch_sync() and we want to avoid that), instead we 
are writing custom async getters/setters with callback blocks. Having async 
property getters would be pretty awesome.

Another thing: it is not clearly mentionned here that we're getting back on the 
caller actor's queue after awaiting on another actor's async method.

# Scalable Runtime

About the problem of creating too many queues. This is something that has 
annoyed me at this year's wwdc. It used to be back when the libdispatch was 
introduced in 10.6 that we were told that queues are very cheap, we could 
create thousands of them and not worry about threads, because the libdispatch 
would do the right thing internally and adjust to the available hardware (the 
number of threads would more or less match the number of cores in your 
machine). Somehow this has changed, now we're being told we need to worry about 
the threads behind the queues and not have too many of them. I'm not sure if 
this is something inevitable due to the underlying reality of the system but 
the way things were presented back then (think in term of queues, don't worry 
about threads) was very compelling.

# Entering and leaving async code

Certainly seems like the beginAsync(), suspendAsync() primitives would be 
useful outside of the stdlib. The Future example makes use of suspendAsync() 
to store the continuation block and call it later, other codes would do just as 
well.

Shouldn't this:

> let imageTmp= await decodeImage(dataResource.get(), imageResource.get())

rather be:

> let imageTmp= await decodeImage(await dataResource.get(), await 
> imageResource.get())


Thomas

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


Re: [swift-evolution] typed throws

2017-08-18 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Aug 17, 2017, at 11:58 PM, Chris Lattner  wrote:
> 
> Splitting this off into its own thread:

Thanks.  I considered starting a thread but decided to ask about it first in 
case it was considered out of scope for Swift 5. 

> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  wrote:
>> One related topic that isn’t discussed is type errors.  Many third party 
>> libraries use a Result type with typed errors.  Moving to an async / await 
>> model without also introducing typed errors into Swift would require giving 
>> up something that is highly valued by many Swift developers.  Maybe Swift 5 
>> is the right time to tackle typed errors as well.  I would be happy to help 
>> with design and drafting a proposal but would need collaborators on the 
>> implementation side.
> 
> Typed throws is something we need to settle one way or the other, and I agree 
> it would be nice to do that in the Swift 5 cycle.
> 
> For the purposes of this sub-discussion, I think there are three kinds of 
> code to think about: 
> 1) large scale API like Cocoa which evolve (adding significant functionality) 
> over the course of many years and can’t break clients. 
> 2) the public API of shared swiftpm packages, whose lifecycle may rise and 
> fall - being obsoleted and replaced by better packages if they encounter a 
> design problem.  
> 3) internal APIs and applications, which are easy to change because the 
> implementations and clients of the APIs are owned by the same people.
> 
> These each have different sorts of concerns, and we hope that something can 
> start out as #3 but work its way up the stack gracefully.
> 
> Here is where I think things stand on it:
> - There is consensus that untyped throws is the right thing for a large scale 
> API like Cocoa.  NSError is effectively proven here.  Even if typed throws is 
> introduced, Apple is unlikely to adopt it in their APIs for this reason.
> - There is consensus that untyped throws is the right default for people to 
> reach for for public package (#2).
> - There is consensus that Java and other systems that encourage lists of 
> throws error types lead to problematic APIs for a variety of reasons.
> - There is disagreement about whether internal APIs (#3) should use it.  It 
> seems perfect to be able to write exhaustive catches in this situation, since 
> everything in knowable. OTOH, this could encourage abuse of error handling in 
> cases where you really should return an enum instead of using throws.
> - Some people are concerned that introducing typed throws would cause people 
> to reach for it instead of using untyped throws for public package APIs.
> - Some people think that while it might be useful in some narrow cases, the 
> utility isn’t high enough to justify making the language more complex 
> (complexity that would intrude on the APIs of result types, futures, etc)
> 
> I’m sure there are other points in the discussion that I’m forgetting.

To be clear, I don't think anyone is arguing that we should remove the ability 
to simply mark a function `throws` with an implicit error type of `Error`! :) 
This is obviously crucial and would continue to be used in many cases.  One 
important variation of this use case is that with typed errors it is also 
possible to refine `Error` and throw a slightly more specific existential.  
Obviously Apple will continue to use untyped errors in most or all APIs 
regardless of what we do and unannotated `throws` will continue to be the 
shortest syntax.

The topic of Java errors has already been beat to death on the list in the 
past.  I find it unfortunate that the counter-examples (notably Rust) are not 
usually mentioned.  I haven't worked in Java, but my study of this topic in the 
past has convinced me the Java design has some serious flaws that are 
completely avoidable.

I would like to reiterate the point I made in the question that spawned this 
thread: there are *many* Swift libraries for writing async code of various 
sorts which are *already* using typed errors via `Result`.  We don't have to speculate about how this feature might be used and 
what kind of benefits might be realized.  We can have a discussion about what 
people are already doing and determine whether this model should be supported 
in the async / await world or not.  What do you think of putting a call out to 
the broader Swift community to bring us concrete examples of how they are 
benefiting from using typed errors in async code.

If we decide it should be, typed errors for synchronous code naturally follows. 
 If we decide it shouldn't we have to be prepared for some noise about the 
unfortunate tradeoff developers will face between using async / await or 
continuing (pun not intended) to use explicit continuations and typed errors.  
I suspect most people would move to async / await and live with untyped errors 
(we don't see a lot of synchronous 

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

2017-08-18 Thread Alejandro Martinez via swift-evolution
This has been a long awaited topic so I'm really excited to see the
conversation start!
After reading the manifesto and the proposal there is one thing that
keeps wondering in my head, and is making async implicitly throwing.
It the common case it makes sense, but there is a part of the proposal
that talks about "yields" and how the implementation is "coroutines"
that can be used for other things not only for concurrent operations.
In that case, wouldn't make more sense to keep throwing separated?

On Fri, Aug 18, 2017 at 2:17 PM, Thomas via swift-evolution
 wrote:
> I have been writing a lot of fully async code over the recent years (in objc) 
> and this all seems to fit well with what we're doing and looks like it would 
> alleviate a lot of the pain we have writing asyc code.
>
> # Extending the model through await
>
> I'm a bit worried about the mention of dispatch_sync() here (although it may 
> just be there to illustrate the deadlock possibility). I know the actor 
> runtime implementation is not yet defined, but just wanted to mention that 
> dispatch_sync() will lead to problems such as this annoying thing called 
> thread explosion. This is why we currently cannot use properties in our code 
> (getters would require us to call dispatch_sync() and we want to avoid that), 
> instead we are writing custom async getters/setters with callback blocks. 
> Having async property getters would be pretty awesome.
>
> Another thing: it is not clearly mentionned here that we're getting back on 
> the caller actor's queue after awaiting on another actor's async method.
>
> # Scalable Runtime
>
> About the problem of creating too many queues. This is something that has 
> annoyed me at this year's wwdc. It used to be back when the libdispatch was 
> introduced in 10.6 that we were told that queues are very cheap, we could 
> create thousands of them and not worry about threads, because the libdispatch 
> would do the right thing internally and adjust to the available hardware (the 
> number of threads would more or less match the number of cores in your 
> machine). Somehow this has changed, now we're being told we need to worry 
> about the threads behind the queues and not have too many of them. I'm not 
> sure if this is something inevitable due to the underlying reality of the 
> system but the way things were presented back then (think in term of queues, 
> don't worry about threads) was very compelling.
>
> # Entering and leaving async code
>
> Certainly seems like the beginAsync(), suspendAsync() primitives would be 
> useful outside of the stdlib. The Future example makes use of 
> suspendAsync() to store the continuation block and call it later, other codes 
> would do just as well.
>
> Shouldn't this:
>
>> let imageTmp= await decodeImage(dataResource.get(), imageResource.get())
>
> rather be:
>
>> let imageTmp= await decodeImage(await dataResource.get(), await 
>> imageResource.get())
>
>
> Thomas
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



-- 
Alejandro Martinez
http://alejandromp.com
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-08-18 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Aug 17, 2017, at 11:53 PM, Chris Lattner  wrote:
> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson  wrote:
>> This is fantastic!  Thanks for taking the time to write down your thoughts.  
>> It’s exciting to get a glimpse at the (possible) road ahead.
> 
> Happy to.
> 
>> In the manifesto you talk about restrictions on passing functions across an 
>> actor message.  You didn’t discuss pure functions, presumably because Swift 
>> doesn’t have them yet.  I imagine that if (hopefully when) Swift has 
>> compiler support for verifying pure functions these would also be safe to 
>> pass across an actor message.  Is that correct?
> 
> Correct.  The proposal is specifically/intentionally designed to be light on 
> type system additions, but there are many that could make it better in 
> various ways.  The logic for this approach is that I expect *a lot* of people 
> will be writing mostly straight-forward concurrent code, and that goal is 
> harmed by presenting significant type system hurdles for them to jump over, 
> because that implies a higher learning curve.
> 
> This is why the proposal doesn’t focus on a provably memory safe system: If 
> someone slaps “ValueSemantical” on a type that doesn’t obey, they will break 
> the invariants of the system.  There are lots of ways to solve that problem 
> (e.g. the capabilities system in Pony) but it introduces a steep learning 
> curve.
> 
> I haven’t thought a lot about practically getting pure functions into Swift, 
> because it wasn’t clear what problems it would solve (which couldn’t be 
> solved another way).  You’re right though that this could be an interesting 
> motivator. 

I can provide a concrete example of why this is definitely and important 
motivator.  

My current project uses pure functions, value semantics and declarative effects 
at the application level and moves as much of the imperative code as possible 
(including effect handling) into library level code.  This is working out 
really well and I plan to continue with this approach.  The library level code 
needs the ability to schedule user code in the appropriate context.  There will 
likely be some declarative ability for application level code to influence the 
context, priority, etc, but it is the library that will be moving the functions 
to the final context.  They are obviously not closure literals from the 
perspective of the library.

Pure functions are obviously important to the semantics of this approach.  We 
can get by without compiler verification, using documentation just as we do for 
protocol requirements that can't be verified.  That said, it would be pretty 
disappointing to have to avoid using actors in the implementation simply 
because we can't move pure functions from one actor to another as necessary.

To be clear, I am talking in the context of "the fullness of time".  It would 
be perfectly acceptable to ship actors before pure functions.  That said, I do 
think it's crucial that we eventually have the ability to verify pure functions 
and move them around at will.

> 
>> The async / await proposal looks very nice.  One minor syntax question - did 
>> you consider `async func` instead of placing `async` in the same syntactic 
>> location as `throws`?  I can see arguments for both locations and am curious 
>> if you and Joe had any discussion about this.
> 
> I don’t think that Joe and I discussed that option.  We discussed several 
> other designs (including a more C# like model where async functions 
> implicitly return Future), but he convinced me that it is better to focus 
> language support on the coroutine transformation (leaving futures and other 
> APIs to the library), then you pretty quickly want async to work the same way 
> as throws (including marking etc).  Once it works the same way, it follows 
> that the syntax should be similar - particularly if async ends up implying 
> throws.
> 
> That said, if you have a strong argument for why this is perhaps the wrong 
> choice, lets talk about it!

I don't necessarily have a *strong* argument and don't want to see us get to 
sidetracked by a bikeshedding exercise at this point either.  :)

Briefly, here is my perspective.

In favor of the proposed syntax:
* From the point of view of the caller, it is the result that is async.
* As you noted, if `async` implies `throws` it is the only reasonable choice.
* It provides consistency with `throws` and perhaps establishes a standard 
syntactic location for additional effect specifiers down the road.

In favor of `async func`:
* `async` is arguably a much more significant modifier to the behavior of the 
function than `throws`, influencing the entire execution model, not just an 
alternate return path.
* Given the above, a case can be made for moving it to the front of the 
declaration to highlight this significant difference and ensure it isn't missed 
when reading code (especially when reading 

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

2017-08-18 Thread Johannes Weiß via swift-evolution
Hi Chris & swift-evo,

(Given the already lengthy thread I tried to separate my points and keep them 
reasonably short to allow people to skip points they don't care about. I'm very 
happy to expand on the points.)

Thanks very much for writing up your thoughts/proposal, I've been waiting to 
see the official kick-off for the concurrency discussions :).

I) Let's start with the async/await proposal. Personally I think this is the 
right direction for Swift given the reality that we need to interface with 
incredibly large existing code-bases and APIs. Further thoughts:

- ❓ GCD: dispatching onto calling queue, how?
GCD doesn't actually allow you to dispatch back to the original queue, so I 
find it unclear how you'd achieve that. IMHO the main reason is that 
conceptually at a given time you can be on more than one queue (nested 
q.sync{}/target queues). So which is 'the' current queue?

- ⊥ first class coroutine model => async & throws should be orthogonal
given that the proposal pitches to be the beginning of a first class coroutine 
model (which I think is great), I think `async` and `throws` do need to be two 
orthogonal concepts. I wouldn't want automatically throwing generators in the 
future ;). Also I think we shouldn't throw spanner in the works of people who 
do like to use Result types to hold the errors or values. I'd be fine 
with async(nothrow) or something though.
- what do we do with functions that invoke their closure multiple times? Like 
DispatchIO.read/write.


II) the actor model part

-  Erlang runtime and the actor model go hand in hand 
I really like the Erlang actor model but I don't think it can be separated from 
Erlang's runtime. The runtime offers green threads (which allow an actor to 
block without blocking an OS thread) and prevents you from sharing memory 
(which makes it possible to kill any actor at any point and still have a 
reliable system). I don't see these two things happening in Swift. To a lesser 
extend these issues are also present in Scala/Akka, the mitigate some of the 
problems by having Akka Streams. Akka Streams are important to establish 
back-pressure if you have faster producers than consumers. Note that we often 
can't control the producer, they might be on the other side of a network 
connection. So it's often very important to not read the available bytes to 
communicate to the kernel that we can't consumes bytes that fast. If we're 
networking with TCP the kernel can then use the TCP flow-control to signal to 
the other side that they better slow down (or else packets will be dropped and 
then need to be resent later).

-  regarding fatal failure in actors
in the server world we need to be able to accept hundreds of thousands 
(millions) of connections at the same time. There are quite a few cases where 
these connections are long-lived and paused for most of the the time. So I 
don't really see the value in introducing a 'reliable' actor model where the 
system stops accepting new connections if one actor fatalError'd and then 
'just' finishes up serving the existing connections. So I believe there are 
only two possible routes: 1) treat it like C/C++ and make sure your code 
doesn't fatalError or the whole process blows up (what we have right now) 2) 
treat it like Erlang and let things die. IMHO Erlang wouldn't be successful if 
actors couldn't just die or couldn't be linked. Linking propagates failures to 
all linked processes. A common thing to do is to 1) spawn a new actor 2) link 
yourself to the newly spawned actor 3) send a message to that actor and at some 
point eventually await a reply message sent by the actor spawned earlier. As 
you mentioned in the writeup it is a problem if the actor doesn't actually 
reply which is why in Erlang you'd link them. The effect is that if the actor 
we spawned dies, any linked actor will die too which will the propagate the 
error to an appropriate place. That allows the programmer to control where an 
error should propagate too. I realise I'm doing a poor job in explaining what 
is best explained by documentation around Erlang: supervision [1] and the 
relationship between what Erlang calls a process (read 'actor') and errors [2].

- ♨️ OS threads and actors
as you mention, the actor model only really works if you can spawn lots of 
them, so it's very important to be able to run hundreds of thousands of them on 
a number of OS threads pretty much equal to your number of cores. That's only 
straightforward if there are no (OS thread) blocking operations or at least 
it's really obvious what blocks and what doesn't. And that's not the case in 
Swift today and with GCD you really feel that pain. GCD does spawn threads for 
you and has a rather arbitrary limit of 64 OS threads (by default on macOS). 
That is too many for a very scalable server application but too few to just 
tolerate blocking APIs.


[1]: 
http://erlang.org/documentation/doc-4.9.1/doc/design_principles/sup_princ.html
[2]: 

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

2017-08-18 Thread Thomas via swift-evolution
The compiler could rewrite this:

print(await dataModel.getNumberOfEntries())

actor func getNumberOfEntries() -> Int
{
return theList.count
}

as this:

dataModel.getNumberOfEntries(_internalQueue) { count in
print(count)
}

actor func getNumberOfEntries(queue: DispatchQueue, handler: Int -> Void) -> 
Void
{
_internalQueue.async {
let count = theList.count
queue.async {
handler(count)
}
}
}

There is another problem that bothers me, if the function were to await on 
another actor (and therefore dispatch away from its _internalQueue), how would 
you guarantee that "only one message is processed by the actor at a time". You 
would need to somehow prevent the internal queue from processing other messages.

Thomas

> On 18 Aug 2017, at 17:13, Johannes Weiß via swift-evolution 
>  wrote:
> 
> GCD doesn't actually allow you to dispatch back to the original queue, so I 
> find it unclear how you'd achieve that. IMHO the main reason is that 
> conceptually at a given time you can be on more than one queue (nested 
> q.sync{}/target queues). So which is 'the' current queue?

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