Sent from my iPad

> On Aug 17, 2017, at 11:53 PM, Chris Lattner <clatt...@nondot.org> wrote:
> 
>> On Aug 17, 2017, at 7:39 PM, Matthew Johnson <matt...@anandabits.com> 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 quickly).
* It aligns with the vocabulary we naturally use: "an async function".  (The 
same can be said for "throwing function" of course, so this really hinges on 
the importance you place on the first point)

> 
> -Chris
> 

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

Reply via email to