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

2017-11-22 Thread Mike Kluev via swift-evolution
On 21 November 2017 at 21:55, Mike Kluev  wrote:

>
> maybe this?
>
> {
> capture weak foo, loo, poo // "capture list", if present
> capture unowned bar, baz, booz   // shall be at the beginning
> capture weak delegate = self.delegate!  // before anything else
>
> foo()
> ...
> }
>
> compare to the current:
> {
> [
> weak foo, weak loo, weak poo
> unowned bar, unowned baz, unowned booz
> weak delegate = self.delegate!
> ] in
>
> foo()
> ...
> }
>
> a bit more explicit / expressive, looks like ordinary statements, and
> doesn't have that strange "in" at the end.
>
>
or even this:

{
weak capture foo, loo, poo
unowned capture bar, baz, booz
weak capture delegate = self.delegate!

// capture list if any has to be before anything else

weak var some = other
foo()
...
 }

here "capture" is a noun, playing the role of "var" / "let".

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


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

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


> On 13. Nov 2017, at 05:11, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution 
>>  wrote:
>> 
>> Hello evolution folks,
>> 
>> After the positive feedback on the idea of improving capturing semantics of 
>> local functions, Alex Lynch and I worked on a proposal. Please let us know 
>> if you have any feedback:
>> 
>> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/-improve-capture-semantics-of-local-functions.md
> 
> So, quoting the proposal:
> 
>> First of all, this proposal suggests extending the requirement of the self. 
>> prefix to local functions, but only if the local function is used as or used 
>> inside an escaping closure.
> 
> I don't love that the use of a function many lines away can cause errors in 
> that closure. There's a "spooky action-at-a-distance" quality to this 
> behavior that I don't like.
> 

I could go either way on that. Especially since if you want to find out where 
the escaping references are, you could just remove the @escaping annotation 
(below) and look for the compiler errors.

> The best idea I have is to require local functions to be annotated with 
> `@escaping` if they're to be used in an escaping closure:
> 
>func foo() {
>// `local1` is nonescaping since it isn't marked with the @escaping 
> attribute.
>func local1() {
>bar()
>}
>local1()   // OK, direct call
>{ local1() }() // OK, closure is nonescaping
>DispatchQueue.main.async(execute: local1)  // error: passing 
> non-escaping function 'local2' to function expecting an @escaping closure
>DispatchQueue.main.async { local1() }  // error: closure use 
> of non-escaping function 'local2' may allow it to escape
> 
>@escaping func local2() {
>bar()  // error: call to method 'bar' in escaping 
> local function requires explicit 'self.' to make capture semantics explicit
>}
> 
>@escaping func local3() {
>   self. bar() // OK, explicit `self`
>}
>DispatchQueue.main.async(execute: local3)  // OK, escaping function
>DispatchQueue.main.async { local3() }  // OK, escaping closure
>   }
> 
>func bar() {
>print("bar")
>}
> 
> But this would be quite source-breaking. (Maybe it could be introduced as a 
> warning first?)

+1

> 
>> Secondly, this proposal suggests allowing the same capture list syntax from 
>> closures in local functions. Capture lists would still be invalid in 
>> top-level and member functions.
> 
> 
> I think this is a good idea, but I don't like bringing the already weird use 
> of `in` to actual functions.
> 
> By analogy with the current closure syntax, the capture list ought to go 
> somewhere before the parameter list, in one of these slots:
> 
> 1.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 2.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 3.func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> 4.[foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
> 
> Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, 
> and 3 just seems weird. But it seems like the one that would be easiest to 
> misparse.
> 

We should keep capture lists where they are (in the body). Currently functions 
and closures have very similar syntax:

func doSomething(section: Int, value: Double) -> String { … }

var doSomething: (_ section: Int, _ value: Double) -> String { [captures…] s,v 
in }

So you basically need to replace “func” with “var”, copy your parameter names 
in to the body and replace them with underscores (because closure types can’t 
have argument labels — I think the core team do want to add those add some 
point IIRC… ). I don’t see a good reason to force developers to also shuffle 
their capture lists around. When you’re working with local functions, it’s hard 
enough to style your code so that you keep within your column-limit. It can be 
delicate, is what I’m saying.

- Karl

> -- 
> 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] [Pitch] Improving capturing semantics of local functions

2017-11-21 Thread Mike Kluev via swift-evolution
on Tue, 21 Nov 2017 11:06:04 +0100 Tino Heth <2...@gmx.de> wrote:

>
> > 5. func fn[foo, bar](param: T) throws -> T where T: Equatable
> captures [foo, bar] { … }
>
> I guess it can be considered good practice to start a line with the most
> important information, and move the details to the far right, so that they
> don’t distract the hasty reader.
> I’m not sure if the capture list an example for this, but for good or
> worse, it didn’t draw much attention in another position either (the first
> „[foo, bar]“ that slipped through).
>
> That variant (func fn[foo, bar](param: T)) is definitely my favorite,
> because it keeps a characteristic of closures (first the capture list, then
> the parameters), but doesn’t carry over the mingling of body and parameters
> that has to be done in closures.
>


maybe this?

{
capture weak foo, loo, poo // "capture list", if present
capture unowned bar, baz, booz   // shall be at the beginning
capture weak delegate = self.delegate!  // before anything else

foo()
...
}

compare to the current:
{
[
weak foo, weak loo, weak poo
unowned bar, unowned baz, unowned booz
weak delegate = self.delegate!
] in

foo()
...
}

a bit more explicit / expressive, looks like ordinary statements, and
doesn't have that strange "in" at the end.

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


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

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

> 5. func fn[foo, bar](param: T) throws -> T where T: Equatable captures 
> [foo, bar] { … }

I guess it can be considered good practice to start a line with the most 
important information, and move the details to the far right, so that they 
don’t distract the hasty reader.
I’m not sure if the capture list an example for this, but for good or worse, it 
didn’t draw much attention in another position either (the first „[foo, bar]“ 
that slipped through).

That variant (func fn[foo, bar](param: T)) is definitely my favorite, 
because it keeps a characteristic of closures (first the capture list, then the 
parameters), but doesn’t carry over the mingling of body and parameters that 
has to be done in closures.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-20 Thread Thorsten Seitz via swift-evolution


> Am 21.11.2017 um 04:00 schrieb Chris Lattner via swift-evolution 
> :
> 
> 
>> On Nov 12, 2017, at 8:52 PM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> 
>> func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
> 
> +1, potentially adding a context sensitive keyword like “capturing” before it.

+1 including the keyword "capturing"

-Thorsten

> 
>> I think #4 is ambiguous with array literals unfortunately.
>> 
>> Perhaps this proposal should be split in two — the ‘self.’/escaping part is 
>> source breaking, and will likely require more discussion. Adding capture 
>> lists to local functions seems like a more straightforward change.
> 
> +1.
> 
> -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] [Pitch] Improving capturing semantics of local functions

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

> On Nov 12, 2017, at 8:52 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
> func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }

+1, potentially adding a context sensitive keyword like “capturing” before it.

> I think #4 is ambiguous with array literals unfortunately.
> 
> Perhaps this proposal should be split in two — the ‘self.’/escaping part is 
> source breaking, and will likely require more discussion. Adding capture 
> lists to local functions seems like a more straightforward change.

+1.

-Chris

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


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

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

> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> 
>> Secondly, this proposal suggests allowing the same capture list syntax from 
>> closures in local functions. Capture lists would still be invalid in 
>> top-level and member functions.
> 
> 
> I think this is a good idea, but I don't like bringing the already weird use 
> of `in` to actual functions.
> 
> By analogy with the current closure syntax, the capture list ought to go 
> somewhere before the parameter list, in one of these slots:
> 
> 1.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 2.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 3.func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> 4.[foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
> 
> Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, 
> and 3 just seems weird. But it seems like the one that would be easiest to 
> misparse.

This is relatively rare, so I’d suggest introducing a context sensitive keyword 
to make it explicit, perhaps:

5. func fn[foo, bar](param: T) throws -> T where T: Equatable captures [foo, 
bar] { … }

It makes sense (IMO) to keep it near the body of the function, since it is more 
an artifact of the implementation than it is about the API.  Yes I know that 
caring about the API of a local function is weird :-)  


-Chris

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


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

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

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

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


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

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


> On Nov 16, 2017, at 4:38 PM, Howard Lovatt  wrote:
> 
> When the user writes:
> 
> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
> increment(1) // 2
> increment(1.1) // 2.1

This means that ‘increment’ is a *value* with a generic function type. 
Presumably you want to pass generic closures as function parameters and results 
too. This is called higher-rank polymorphism and it introduces considerable 
complexity in type checking and code generation.

> Compiler issues global struct as above. Then:
> 
> let _int_increment = _Function1__T1__T1__T1__E__Numeric({ $0 + 1 })
> try _int_increment.call(1) // 2
> let _double_increment = _Function1__T1__T1__T1__E__Numeric({ $0 + 
> 1 })
> try _double_increment.call(1.1) // 2.1

What if I do,

let array = [increment]

What is the type of ‘array’?

Slava

> 
> The more restrictive form that you suggest (I think this is what you mean 
> anyway) of only allowed locally, not globally, is easier to name mangle, you 
> just need a unique name, nothing about the name needs to be canonical. This 
> would be similar to local functions at present and would be useful (though I 
> am not sure how many local *generic* functions there are).
> 
> 
>   -- Howard.
> 
> On 17 November 2017 at 10:47, Slava Pestov  > wrote:
> 
> 
>> On Nov 16, 2017, at 3:07 PM, Howard Lovatt via swift-evolution 
>> > wrote:
>> 
>> Where I am proposing a change is that if a closure with generic arguments is 
>> encountered it is transformed into the equivalent struct and the struct is 
>> typed as it currently is (or if there is a better implementation something 
>> equivalent to this), therefore zero change to the type system.
> 
> Since we already have local functions that can capture values and be generic, 
> there’s no need to implement a new mechanism for name mangling or handling of 
> captures.
> 
>> 
>> The changes proposed are a transformation into a struct and name mangling, 
>> e.g.:
>> 
>> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
>> let increment = { (n: T) throws -> T where T: Numeric in n + 1 }
>> let increment: (T) throws -> T where T: Numeric = { (n: T) throws 
>> -> T where T: Numeric in n + 1 }
> 
> It sounds like what you’re proposing is essentially a new surface syntax for 
> local functions — since a generic closure would not be a first class value, 
> it could not appear anywhere except for the right hand side of a let binding, 
> right?
> 
> Slava
> 

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


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

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

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

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

When the user writes:

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

Compiler issues global struct as above. Then:

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

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


  -- Howard.

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

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


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

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


> On Nov 16, 2017, at 3:07 PM, Howard Lovatt via swift-evolution 
>  wrote:
> 
> Where I am proposing a change is that if a closure with generic arguments is 
> encountered it is transformed into the equivalent struct and the struct is 
> typed as it currently is (or if there is a better implementation something 
> equivalent to this), therefore zero change to the type system.

Since we already have local functions that can capture values and be generic, 
there’s no need to implement a new mechanism for name mangling or handling of 
captures.

> 
> The changes proposed are a transformation into a struct and name mangling, 
> e.g.:
> 
> let increment: (T) throws -> T where T: Numeric = { $0 + 1 }
> let increment = { (n: T) throws -> T where T: Numeric in n + 1 }
> let increment: (T) throws -> T where T: Numeric = { (n: T) throws 
> -> T where T: Numeric in n + 1 }

It sounds like what you’re proposing is essentially a new surface syntax for 
local functions — since a generic closure would not be a first class value, it 
could not appear anywhere except for the right hand side of a let binding, 
right?

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


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

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


> Am 17.11.2017 um 00:00 schrieb Slava Pestov :
> 
> Remember that only references can be captured weakly, not value types, even 
> if those value types contain reference members… so this might end up being 
> more confusing than necessary.
true… but isn’t that a constellation with potential for confusion in general?___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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

Therefore your example of:

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

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

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

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

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

Are all the same and would therefore all become:

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

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

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

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

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

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


  -- Howard.

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

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

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

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


> On Nov 16, 2017, at 2:56 PM, Tino Heth via swift-evolution 
>  wrote:
> 
> 
>> the stat suggests that in 90%+ real-life cases [weak self] is used so the 
>> "weak func" syntax sugar is worth to consider as an addition to this 
>> proposal.
> Slightly OT:
> Just thought about making all captures weak by default… I know it’s probably 
> to late for such a change, but I wonder if this was considered when closures 
> were designed

Remember that only references can be captured weakly, not value types, even if 
those value types contain reference members… so this might end up being more 
confusing than necessary.

Slava

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

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


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

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

> the stat suggests that in 90%+ real-life cases [weak self] is used so the 
> "weak func" syntax sugar is worth to consider as an addition to this proposal.
Slightly OT:
Just thought about making all captures weak by default… I know it’s probably to 
late for such a change, but I wonder if this was considered when closures were 
designed___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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

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

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

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

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

  -- Howard.

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

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


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

2017-11-15 Thread Robert Widmann via swift-evolution


~Robert Widmann 

2017/11/14 22:02、Matthew Johnson via swift-evolution 
のメール:

> 
> 
> Sent from my iPhone
> 
>> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution 
>>  wrote:
>> 
>> Having read all the arguments for what to add to local functions it still 
>> strikes me as a poor use of engineering resources to fix them (though I do 
>> agree they have problems). A better use of resources would be:
>> 
>>   1. Deprecate local functions.
>>   2. Allow closures when assigned to a function type to be:
>>   2a. Recursive.
>>   2b. Annotatable with:
>> 2bi.  @inline
>> 2bii. @escaping
>>   2c. Generic.
>> 
>> That would be a similar engineering effort and give a better short term 
>> result of better closures which would be much more widely applicable as well 
>> as addressing the issues with local functions.
> 
> I believe generic closures would require adding higher rank types to Swift.  
> That would be pretty cool but I suspect the engineering effort is at least an 
> order of magnitude greater than the changes discussed in this thread.

100% correct. Slava raises good points about implementation, I’ll raise one 
about semantics:

Without sufficient restrictions on this kind of polymorphism, type checking 
will become significantly more difficult for little corresponding benefit.  
Enabling the formation of polymorphic types just because you’re near an arrow 
means all sorts of fun things now get to happen

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

This program is illegal without a type signature, but still typeable in that 
Swift will try to look for bindings to the tn’s in this signature

f :  (T0) -> (T1) -> T1

This is good - this is the most general unifier for this expression promised to 
us by the “Hindley-Milner-like” label we have in the type checker docs.

Given even rank-2 types, the most general unifier is (ideally) now 

f :  (T0) -> ( (T1) -> T1)

Which is significant because despite an obvious isomorphism, the former is not 
a specialization of the latter.  It is a completely separate polytype that 
would require additional structural rules to recover the correct behavior.  
This can also block inference or generate counterintuitive unifiers if we’re 
forced to e.g. unify nested polytypes against each other.

~Robert Widmann

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

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

2017-11-14 Thread Robert Widmann via swift-evolution
A quick thing I noticed on a first read (sort of tangential to the rest of the 
discussion) is that it would be a good idea to land warnings for potential 
reference cycles sooner rather than later.

I have an (un-rebased) branch that lays out what parts of Sema needs to be 
touched to make this happen and have SR-1807 
(https://bugs.swift.org/browse/SR-1807) open for this in general if anybody 
would like to pick this up and carry it over the goal line.  Note that it’s not 
quite a starter bug.

Otherwise I’ll allocate time to it later on this winter.

~Robert Widmann 

2017/11/15 2:01、David Hart via swift-evolution のメール:

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


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

2017-11-14 Thread David Hart via swift-evolution


> On 15 Nov 2017, at 03:56, Howard Lovatt via swift-evolution 
>  wrote:
> 
> Having read all the arguments for what to add to local functions it still 
> strikes me as a poor use of engineering resources to fix them (though I do 
> agree they have problems). A better use of resources would be:
> 
>   1. Deprecate local functions.

Even if I agreed, which I don’t, I’m fairly sure it’s much too late in Swift’s 
timeline to deprecate something as huge as local functions.

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

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


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

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


> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution 
>  wrote:
> 
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.

Local functions can also be mutually recursive:

func f() {
  func foo() { bar() }
  func bar() { foo() }
}

This would not work with let bindings, which are not visible before the 
location where they are defined.

>   2b. Annotatable with:
> 2bi.  @inline

Neither closures nor local functions benefit from being annotated with 
@_inlineable, because they can only be referenced from inside their defining 
function, and not across module boundaries. So the optimizer can already inline 
the function or closure if needed.

> 2bii. @escaping
>   2c. Generic.

See my other response to this thread.

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


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

2017-11-14 Thread Mike Kluev via swift-evolution
On 14 November 2017 at 21:36, Mike Kluev  wrote:

>
> it might cover well over 90% of use cases (by my "pessimistic"
> estimate)... if someone has a quick way to scan and analyse, say, github
> swift sources we may even know that current percentage number of real life
> usage.
>

i did a quick & dirty search on github (queries below). here are some stats:

1) "weak var" - 946K hits

2) "weak self" - 168K hits

3) "weak" - 1127K hits

the summ of "weak var" + "weak self" = 1114K hits

number of "weak" - 1114K = 13K

let's assume this 13K is for weak "something" which is not "self"

number of "weak something" + "weak self" = 181K

"weak self" = 168K / 181K = 93%

"weak something" = 13K / 181K = 7%

the search queries for those interested:

https://github.com/search?utf8=✓=%22weak+var%22+filename%3A.swift=Code

https://github.com/search?utf8=✓=%22weak+self%22+filename%3A.swift=Code

https://github.com/search?utf8=✓=%22weak%22+filename%3A.swift=Code


note that you have to rerun the search multiple times until it settles
around some number.
also note, you can't easily use [ ] or other punctuation in github builtin
search.

the stat suggests that in 90%+ real-life cases [weak self] is used so the
"weak func" syntax sugar is worth to consider as an addition to this
proposal.

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


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

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

The compiler can emit the following for example:

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


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


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

  -- Howard.

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

>
>
> Sent from my iPhone
>
> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Having read all the arguments for what to add to local functions it still
> strikes me as a poor use of engineering resources to fix them (though I do
> agree they have problems). A better use of resources would be:
>
>   1. Deprecate local functions.
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.
>   2b. Annotatable with:
> 2bi.  @inline
> 2bii. @escaping
>   2c. Generic.
>
> That would be a similar engineering effort and give a better short term
> result of better closures which would be much more widely applicable as
> well as addressing the issues with local functions.
>
>
> I believe generic closures would require adding higher rank types to
> Swift.  That would be pretty cool but I suspect the engineering effort is
> at least an order of magnitude greater than the changes discussed in this
> thread.
>
>
> It also gives a better long term result of not having to maintain local
> functions.
>
>
>   -- Howard.
>
> On 15 November 2017 at 09:08, Alex Lynch via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> The inference algebra just suggested was enjoyable to read, but is still
>> a new syntax. Which is interesting and deserving of its own proposal. The
>> purpose of this proposal is simply to introduce the existing capture syntax
>> to local functions. Thanks to everyone's feedback pointing out that the
>> `self` reference analysis is a deeper question than initially realized.
>>
>> Alex
>>
>> On Tue, Nov 14, 2017 at 4:36 PM, Mike Kluev via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> On 14 November 2017 at 21:02, David Hart  wrote:
>>>


 I’d be very hesitant to introduce this syntax:


- it’s new syntax, so it comes with a complexity tax (it isn’t
naturally obvious what it means for a func to be weak)
- it’s only sugar for the capture of self

 it might cover well over 90% of use cases (by my "pessimistic"
>>> estimate)... if someone has a quick way to scan and analyse, say, github
>>> swift sources we may even know that current percentage number of real life
>>> usage.
>>>

- it doesn’t transpose well to local closures


>>> the last one - maybe not. follow me:
>>>
>>> let closure = { [weak self, bar] in ... }
>>>
>>> which today can be written as:
>>>
>>> let closure = { [weak self, bar] () -> Int in ... } // full form
>>>
>>> or as:
>>>
>>> let closure: () -> Int = { [weak self, bar] in ... } // full form
>>>
>>> which allows this change:
>>>
>>> let closure:  [weak self, bar] () -> Int = { ... } // full alt form
>>>
>>> or in alternative form:
>>>
>>> let closure:  weak () -> Int = { [bar] in ... } // short hand form
>>>
>>> same can be with functions:
>>>
>>> func fn() -> Int { [weak self, bar] in ... } // full form
>>>
>>> weak func fn() -> Int { [bar] in ... } // short hand form
>>>
>>> the two capture attributes will in practice be "close" to each other:
>>>
>>> weak func fn() {
>>> [bar] in
>>> 
>>> }
>>>
>>> and in majority of cases there will be only weak self:
>>>
>>> weak func fn() {
>>> 
>>> }
>>>
>>> Mike
>>>
>>>
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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


Sent from my iPhone

> On Nov 14, 2017, at 6:56 PM, Howard Lovatt via swift-evolution 
>  wrote:
> 
> Having read all the arguments for what to add to local functions it still 
> strikes me as a poor use of engineering resources to fix them (though I do 
> agree they have problems). A better use of resources would be:
> 
>   1. Deprecate local functions.
>   2. Allow closures when assigned to a function type to be:
>   2a. Recursive.
>   2b. Annotatable with:
> 2bi.  @inline
> 2bii. @escaping
>   2c. Generic.
> 
> That would be a similar engineering effort and give a better short term 
> result of better closures which would be much more widely applicable as well 
> as addressing the issues with local functions.

I believe generic closures would require adding higher rank types to Swift.  
That would be pretty cool but I suspect the engineering effort is at least an 
order of magnitude greater than the changes discussed in this thread.

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


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

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

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

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

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


  -- Howard.

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

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


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

2017-11-14 Thread Alex Lynch via swift-evolution
The inference algebra just suggested was enjoyable to read, but is still a
new syntax. Which is interesting and deserving of its own proposal. The
purpose of this proposal is simply to introduce the existing capture syntax
to local functions. Thanks to everyone's feedback pointing out that the
`self` reference analysis is a deeper question than initially realized.

Alex

On Tue, Nov 14, 2017 at 4:36 PM, Mike Kluev via swift-evolution <
swift-evolution@swift.org> wrote:

> On 14 November 2017 at 21:02, David Hart  wrote:
>
>>
>>
>> I’d be very hesitant to introduce this syntax:
>>
>>
>>- it’s new syntax, so it comes with a complexity tax (it isn’t
>>naturally obvious what it means for a func to be weak)
>>- it’s only sugar for the capture of self
>>
>> it might cover well over 90% of use cases (by my "pessimistic"
> estimate)... if someone has a quick way to scan and analyse, say, github
> swift sources we may even know that current percentage number of real life
> usage.
>
>>
>>- it doesn’t transpose well to local closures
>>
>>
> the last one - maybe not. follow me:
>
> let closure = { [weak self, bar] in ... }
>
> which today can be written as:
>
> let closure = { [weak self, bar] () -> Int in ... } // full form
>
> or as:
>
> let closure: () -> Int = { [weak self, bar] in ... } // full form
>
> which allows this change:
>
> let closure:  [weak self, bar] () -> Int = { ... } // full alt form
>
> or in alternative form:
>
> let closure:  weak () -> Int = { [bar] in ... } // short hand form
>
> same can be with functions:
>
> func fn() -> Int { [weak self, bar] in ... } // full form
>
> weak func fn() -> Int { [bar] in ... } // short hand form
>
> the two capture attributes will in practice be "close" to each other:
>
> weak func fn() {
> [bar] in
> 
> }
>
> and in majority of cases there will be only weak self:
>
> weak func fn() {
> 
> }
>
> Mike
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-14 Thread Mike Kluev via swift-evolution
On 14 November 2017 at 21:02, David Hart  wrote:

>
>
> I’d be very hesitant to introduce this syntax:
>
>
>- it’s new syntax, so it comes with a complexity tax (it isn’t
>naturally obvious what it means for a func to be weak)
>- it’s only sugar for the capture of self
>
> it might cover well over 90% of use cases (by my "pessimistic"
estimate)... if someone has a quick way to scan and analyse, say, github
swift sources we may even know that current percentage number of real life
usage.

>
>- it doesn’t transpose well to local closures
>
>
the last one - maybe not. follow me:

let closure = { [weak self, bar] in ... }

which today can be written as:

let closure = { [weak self, bar] () -> Int in ... } // full form

or as:

let closure: () -> Int = { [weak self, bar] in ... } // full form

which allows this change:

let closure:  [weak self, bar] () -> Int = { ... } // full alt form

or in alternative form:

let closure:  weak () -> Int = { [bar] in ... } // short hand form

same can be with functions:

func fn() -> Int { [weak self, bar] in ... } // full form

weak func fn() -> Int { [bar] in ... } // short hand form

the two capture attributes will in practice be "close" to each other:

weak func fn() {
[bar] in

}

and in majority of cases there will be only weak self:

weak func fn() {

}

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


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

2017-11-14 Thread David Hart via swift-evolution


> On 14 Nov 2017, at 20:41, Wallacy  wrote:
> 
> 
> 
> Em ter, 14 de nov de 2017 às 17:02, Mike Kluev via swift-evolution 
> > escreveu:
> On Mon, 13 Nov 2017 22:30:25 +0100 David Hart  > wrote:
> > On 13 Nov 2017, at 05:52, Slava Pestov  > > wrote:
> >
> >> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution 
> >> > wrote:
> >>
> >> By analogy with the current closure syntax, the capture list ought to go 
> >> somewhere before the parameter list, in one of these slots:
> >>
> >> 1.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> >> 2.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> >> 3.   func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> >> 4.   [foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
> >>
> >> Of these options, I actually think #4 reads best; 1 and 2 are very 
> >> cluttered, and 3 just seems weird. But it seems like the one that would be 
> >> easiest to misparse.
> >
> > Another option that reads nicely IMHO is
> >
> > func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
> >
> > I think #4 is ambiguous with array literals unfortunately.
> 
> adding to the list of options:
> 
> 6. func fn(param: T) throws -> T where T: Equatable [foo, bar] { … }
> 
> otherwise +1 to #1 and to the one in proposal. also see about #4 below.
> 
> plus, if 90%+ of use cases in practice would be [weak self] -- (the only 
> examples shown in the proposals FTM) -- i would strongly consider this syntax 
> sugar in addition to a generic notation:
> 
> weak func fn(param: T) throws -> T where T: Equatable { … }
> 
> works with "unowned" as a bonus.
> 
> 
> weak func  to imply [weak self] is a good idea. 

I’d be very hesitant to introduce this syntax:

it’s new syntax, so it comes with a complexity tax (it isn’t naturally obvious 
what it means for a func to be weak)
it’s only sugar for the capture of self
it doesn’t transpose well to local closures

On the other hand, the proposal attempts to resolve the problems mentioned in 
the Motivation section by introducing as little syntax as possible. And the 
little it does (capture lists) is no similar to closures that increased 
complexity tax is fairly low.

> weak func foo() {
>   self?.bar();
> }
> 
> unowned func foo() {
>   self.bar();
> }
> 
> Maybe this to:
> 
> onChange = weak { self?.bar() }
> 
> But we still have the problem using capture list.
> 
> And to avoid inconsistencies, I would leave the same way as the proposal.
> 
>  func local() { [weak self] in
> self?.bar()
> }
> 
> There's no perfect solution. And in this works fine today.
> 
>  
> if implement this sugar than some variation of #4 looks appealing to have 
> these capture things close.
> 
> Mike
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-14 Thread Wallacy via swift-evolution
Em ter, 14 de nov de 2017 às 17:02, Mike Kluev via swift-evolution <
swift-evolution@swift.org> escreveu:

> On Mon, 13 Nov 2017 22:30:25 +0100 David Hart  wrote:
>
>> > On 13 Nov 2017, at 05:52, Slava Pestov  wrote:
>> >
>> >> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >> By analogy with the current closure syntax, the capture list ought to
>> go somewhere before the parameter list, in one of these slots:
>> >>
>> >> 1.   func fn[foo, bar](param: T) throws -> T where T: Equatable { …
>> }
>> >> 2.   func fn[foo, bar](param: T) throws -> T where T: Equatable { …
>> }
>> >> 3.   func [foo, bar] fn(param: T) throws -> T where T: Equatable {
>> … }
>> >> 4.   [foo, bar] func fn(param: T) throws -> T where T: Equatable {
>> … }
>> >>
>> >> Of these options, I actually think #4 reads best; 1 and 2 are very
>> cluttered, and 3 just seems weird. But it seems like the one that would be
>> easiest to misparse.
>> >
>> > Another option that reads nicely IMHO is
>> >
>> > func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
>> >
>> > I think #4 is ambiguous with array literals unfortunately.
>>
>
> adding to the list of options:
>
> 6. func fn(param: T) throws -> T where T: Equatable [foo, bar] { … }
>
> otherwise +1 to #1 and to the one in proposal. also see about #4 below.
>
> plus, if 90%+ of use cases in practice would be [weak self] -- (the only
> examples shown in the proposals FTM) -- i would strongly consider this
> syntax sugar in addition to a generic notation:
>
> weak func fn(param: T) throws -> T where T: Equatable { … }
>
> works with "unowned" as a bonus.
>
>
weak func  to imply [weak self] is a good idea.

weak func foo() {
  self?.bar();
}

unowned func foo() {
  self.bar();
}

Maybe this to:

onChange = weak { self?.bar() }

But we still have the problem using capture list.

And to avoid inconsistencies, I would leave the same way as the proposal.

 func local() { [weak self] in
self?.bar()
}


There's no perfect solution. And in this works fine today.



> if implement this sugar than some variation of #4 looks appealing to have
> these capture things close.
>
> Mike
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-14 Thread Mike Kluev via swift-evolution
On 14 November 2017 at 19:02, Mike Kluev  wrote:

> On Mon, 13 Nov 2017 22:30:25 +0100 David Hart  wrote:
>
> > On 13 Nov 2017, at 05:52, Slava Pestov  wrote:
>> >
>> >> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >> By analogy with the current closure syntax, the capture list ought to
>> go somewhere before the parameter list, in one of these slots:
>> >>
>> >> 1.   func fn[foo, bar](param: T) throws -> T where T: Equatable { …
>> }
>> >> 2.   func fn[foo, bar](param: T) throws -> T where T: Equatable { …
>> }
>> >> 3.   func [foo, bar] fn(param: T) throws -> T where T: Equatable {
>> … }
>> >> 4.   [foo, bar] func fn(param: T) throws -> T where T: Equatable {
>> … }
>> >>
>> >> Of these options, I actually think #4 reads best; 1 and 2 are very
>> cluttered, and 3 just seems weird. But it seems like the one that would be
>> easiest to misparse.
>> >
>> > Another option that reads nicely IMHO is
>> >
>> > func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
>> >
>> > I think #4 is ambiguous with array literals unfortunately.
>>
>
> adding to the list of options:
>
> 6. func fn(param: T) throws -> T where T: Equatable [foo, bar] { … }
>
> otherwise +1 to #1 and to the one in proposal. also see about #4 below.
>
> plus, if 90%+ of use cases in practice would be [weak self] -- (the only
> examples shown in the proposals FTM) -- i would strongly consider this
> syntax sugar in addition to a generic notation:
>
> weak func fn(param: T) throws -> T where T: Equatable { … }
>
> works with "unowned" as a bonus.
>
> if implement this sugar than some variation of #4 looks appealing to have
> these capture things close.
>
>

the closer we have it to this English sentence the better IMHO:

weak throwing function "fn", capturing "foo" and "bar" weakly, using
generic type "T" which is "Equatable", having parameter "param" of type
"T", returning type "T", with the following body { ... }

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


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

2017-11-14 Thread Mike Kluev via swift-evolution
On Mon, 13 Nov 2017 22:30:25 +0100 David Hart  wrote:

> On 13 Nov 2017, at 05:52, Slava Pestov  wrote:
> >
> >> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> By analogy with the current closure syntax, the capture list ought to
> go somewhere before the parameter list, in one of these slots:
> >>
> >> 1.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> >> 2.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> >> 3.   func [foo, bar] fn(param: T) throws -> T where T: Equatable { …
> }
> >> 4.   [foo, bar] func fn(param: T) throws -> T where T: Equatable { …
> }
> >>
> >> Of these options, I actually think #4 reads best; 1 and 2 are very
> cluttered, and 3 just seems weird. But it seems like the one that would be
> easiest to misparse.
> >
> > Another option that reads nicely IMHO is
> >
> > func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
> >
> > I think #4 is ambiguous with array literals unfortunately.
>

adding to the list of options:

6. func fn(param: T) throws -> T where T: Equatable [foo, bar] { … }

otherwise +1 to #1 and to the one in proposal. also see about #4 below.

plus, if 90%+ of use cases in practice would be [weak self] -- (the only
examples shown in the proposals FTM) -- i would strongly consider this
syntax sugar in addition to a generic notation:

weak func fn(param: T) throws -> T where T: Equatable { … }

works with "unowned" as a bonus.

if implement this sugar than some variation of #4 looks appealing to have
these capture things close.

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


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

2017-11-13 Thread Tino Heth via swift-evolution
I think it would be unfortunate to have the capture list before the template 
parameters:
Template parameters might be used in the capture list, and although Swift 
doesn’t rely on strict „linearity“ or forward declarations, I don’t want to be 
forced to use things that aren’t declared yet.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-13 Thread David Hart via swift-evolution


> On 13 Nov 2017, at 05:52, Slava Pestov  wrote:
> 
> 
> 
>> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution 
>>  wrote:
>> 
>>> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution 
>>>  wrote:
>>> 
>>> Hello evolution folks,
>>> 
>>> After the positive feedback on the idea of improving capturing semantics of 
>>> local functions, Alex Lynch and I worked on a proposal. Please let us know 
>>> if you have any feedback:
>>> 
>>> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/-improve-capture-semantics-of-local-functions.md
>> 
>> So, quoting the proposal:
>> 
>>> First of all, this proposal suggests extending the requirement of the self. 
>>> prefix to local functions, but only if the local function is used as or 
>>> used inside an escaping closure.
>> 
>> I don't love that the use of a function many lines away can cause errors in 
>> that closure. There's a "spooky action-at-a-distance" quality to this 
>> behavior that I don't like.
> 
> Agreed.

Thanks Brent, Slava and John for your feedback. I think you are right: I picked 
up the idea from the original thread because it would reduce source breakage, 
but I’m starting to thing its just not worth it.

Concerning the alternative solution of annotating local functions with 
@escaping, it’s definitely an interesting idea. It might be slightly more 
source-breaking but, as mentioned in the proposal, the breakage will attract 
attention to code where its easy to unknowingly create memory leaks.

>> I think this is a good idea, but I don't like bringing the already weird use 
>> of `in` to actual functions.
>> 
>> By analogy with the current closure syntax, the capture list ought to go 
>> somewhere before the parameter list, in one of these slots:
>> 
>> 1.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
>> 2.   func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
>> 3.   func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
>> 4.   [foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
>> 
>> Of these options, I actually think #4 reads best; 1 and 2 are very 
>> cluttered, and 3 just seems weird. But it seems like the one that would be 
>> easiest to misparse.
> 
> Another option that reads nicely IMHO is
> 
> func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
> 
> I think #4 is ambiguous with array literals unfortunately.

This is pure aesthetics, but I’m a bit bothered by all 5 options. Local 
functions and closures are syntactically different enough that we can either 
choose to keep capture lists in the same position relative to the curly braces 
(like I proposed), or relative to the parameters (like Brent proposes). Don’t 
you think that the suggestion in the pitch is the least confusing for users? On 
a side note, Slava’s 5th option seems like its breaking relative position with 
the curly braces and the parameters.

> Perhaps this proposal should be split in two — the ‘self.’/escaping part is 
> source breaking, and will likely require more discussion. Adding capture 
> lists to local functions seems like a more straightforward change.

Seems like a good idea. Once we all come close to an agreement, Alex and I can 
spit them into two proposals.

David.

> Slava
> 
>> 
>> -- 
>> 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] [Pitch] Improving capturing semantics of local functions

2017-11-13 Thread John McCall via swift-evolution

> On Nov 12, 2017, at 11:11 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution 
>>  wrote:
>> 
>> Hello evolution folks,
>> 
>> After the positive feedback on the idea of improving capturing semantics of 
>> local functions, Alex Lynch and I worked on a proposal. Please let us know 
>> if you have any feedback:
>> 
>> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/-improve-capture-semantics-of-local-functions.md
> 
> So, quoting the proposal:
> 
>> First of all, this proposal suggests extending the requirement of the self. 
>> prefix to local functions, but only if the local function is used as or used 
>> inside an escaping closure.
> 
> I don't love that the use of a function many lines away can cause errors in 
> that closure. There's a "spooky action-at-a-distance" quality to this 
> behavior that I don't like.
> 
> The best idea I have is to require local functions to be annotated with 
> `@escaping` if they're to be used in an escaping closure:
> 
>func foo() {
>// `local1` is nonescaping since it isn't marked with the @escaping 
> attribute.
>func local1() {
>bar()
>}
>local1()   // OK, direct call
>{ local1() }() // OK, closure is nonescaping
>DispatchQueue.main.async(execute: local1)  // error: passing 
> non-escaping function 'local2' to function expecting an @escaping closure
>DispatchQueue.main.async { local1() }  // error: closure use 
> of non-escaping function 'local2' may allow it to escape
> 
>@escaping func local2() {
>bar()  // error: call to method 'bar' in escaping 
> local function requires explicit 'self.' to make capture semantics explicit
>}
> 
>@escaping func local3() {
>   self. bar() // OK, explicit `self`
>}
>DispatchQueue.main.async(execute: local3)  // OK, escaping function
>DispatchQueue.main.async { local3() }  // OK, escaping closure
>   }
> 
>func bar() {
>print("bar")
>}
> 
> But this would be quite source-breaking. (Maybe it could be introduced as a 
> warning first?)

I like the idea of requiring @escaping to be explicit on local funcs, but I'm 
worried that it might be too onerous; after all, we infer @escapingness on 
closures quite successfully.  At the same time, I agree that applying semantic 
rules based on how the func is used, potentially much later in the function, is 
really spooky.  I don't have a great alternative right now.

Random note: we currently infer non-escapingness for local funcs that capture 
``inout``s, since those cannot be allowed to escape.  In fact, this is the only 
way to make a local function non-escaping at all.

John.

> 
>> Secondly, this proposal suggests allowing the same capture list syntax from 
>> closures in local functions. Capture lists would still be invalid in 
>> top-level and member functions.
> 
> 
> I think this is a good idea, but I don't like bringing the already weird use 
> of `in` to actual functions.
> 
> By analogy with the current closure syntax, the capture list ought to go 
> somewhere before the parameter list, in one of these slots:
> 
> 1.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 2.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 3.func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> 4.[foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
> 
> Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, 
> and 3 just seems weird. But it seems like the one that would be easiest to 
> misparse.
> 
> -- 
> 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] [Pitch] Improving capturing semantics of local functions

2017-11-12 Thread C. Keith Ray via swift-evolution

> Another option that reads nicely IMHO is
> 
> func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }
> 

I changed my mind. Putting the capture list just before { } is where I'd rather 
see it.


> I think #4 is ambiguous with array literals unfortunately.
> 
> Perhaps this proposal should be split in two — the ‘self.’/escaping part is 
> source breaking, and will likely require more discussion. Adding capture 
> lists to local functions seems like a more straightforward change.
> 
> Slava
> 
>> 
>> -- 
>> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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


> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution 
>>  wrote:
>> 
>> Hello evolution folks,
>> 
>> After the positive feedback on the idea of improving capturing semantics of 
>> local functions, Alex Lynch and I worked on a proposal. Please let us know 
>> if you have any feedback:
>> 
>> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/-improve-capture-semantics-of-local-functions.md
> 
> So, quoting the proposal:
> 
>> First of all, this proposal suggests extending the requirement of the self. 
>> prefix to local functions, but only if the local function is used as or used 
>> inside an escaping closure.
> 
> I don't love that the use of a function many lines away can cause errors in 
> that closure. There's a "spooky action-at-a-distance" quality to this 
> behavior that I don't like.

Agreed.

> I think this is a good idea, but I don't like bringing the already weird use 
> of `in` to actual functions.
> 
> By analogy with the current closure syntax, the capture list ought to go 
> somewhere before the parameter list, in one of these slots:
> 
> 1.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 2.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 3.func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> 4.[foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
> 
> Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, 
> and 3 just seems weird. But it seems like the one that would be easiest to 
> misparse.

Another option that reads nicely IMHO is

func fn(param: T) throws -> T where T : Equatable [foo, bar] { … }

I think #4 is ambiguous with array literals unfortunately.

Perhaps this proposal should be split in two — the ‘self.’/escaping part is 
source breaking, and will likely require more discussion. Adding capture lists 
to local functions seems like a more straightforward change.

Slava

> 
> -- 
> 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] [Pitch] Improving capturing semantics of local functions

2017-11-12 Thread C. Keith Ray via swift-evolution
I'd vote for # 1 

Starting with "func" helps signal that the context is a function. (Though I 
know some things can precede "func".)
 
Having the function name second is important to me: you don't have to scan 
further for its name.

Template arguments seem more important than capture lists, so I'd put it before 
the other.

--
C. Keith Ray

* https://leanpub.com/wepntk <- buy my book?
* http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf
* http://agilesolutionspace.blogspot.com/

> On Nov 12, 2017, at 8:11 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> 
> 1.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 2.func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
> 3.func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
> 4.[foo, bar] func fn(param: T) throws -> T where T: Equatable { … }
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-12 Thread Brent Royal-Gordon via swift-evolution
> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution 
>  wrote:
> 
> Hello evolution folks,
> 
> After the positive feedback on the idea of improving capturing semantics of 
> local functions, Alex Lynch and I worked on a proposal. Please let us know if 
> you have any feedback:
> 
> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/-improve-capture-semantics-of-local-functions.md

So, quoting the proposal:

> First of all, this proposal suggests extending the requirement of the self. 
> prefix to local functions, but only if the local function is used as or used 
> inside an escaping closure.

I don't love that the use of a function many lines away can cause errors in 
that closure. There's a "spooky action-at-a-distance" quality to this behavior 
that I don't like.

The best idea I have is to require local functions to be annotated with 
`@escaping` if they're to be used in an escaping closure:

func foo() {
// `local1` is nonescaping since it isn't marked with the @escaping 
attribute.
func local1() {
bar()
}
local1()// OK, direct call
{ local1() }()  // OK, closure is nonescaping
DispatchQueue.main.async(execute: local1)   // error: passing 
non-escaping function 'local2' to function expecting an @escaping closure
DispatchQueue.main.async { local1() }   // error: closure use 
of non-escaping function 'local2' may allow it to escape

@escaping func local2() {
bar()   // error: call to method 'bar' in escaping 
local function requires explicit 'self.' to make capture semantics explicit
}

@escaping func local3() {
   self. bar()  // OK, explicit `self`
}
DispatchQueue.main.async(execute: local3)   // OK, escaping function
DispatchQueue.main.async { local3() }   // OK, escaping closure
   }

func bar() {
print("bar")
}

But this would be quite source-breaking. (Maybe it could be introduced as a 
warning first?)

> Secondly, this proposal suggests allowing the same capture list syntax from 
> closures in local functions. Capture lists would still be invalid in 
> top-level and member functions.


I think this is a good idea, but I don't like bringing the already weird use of 
`in` to actual functions.

By analogy with the current closure syntax, the capture list ought to go 
somewhere before the parameter list, in one of these slots:

1.  func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
2.  func fn[foo, bar](param: T) throws -> T where T: Equatable { … }
3.  func [foo, bar] fn(param: T) throws -> T where T: Equatable { … }
4.  [foo, bar] func fn(param: T) throws -> T where T: Equatable { … }

Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, 
and 3 just seems weird. But it seems like the one that would be easiest to 
misparse.

-- 
Brent Royal-Gordon
Architechies

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


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

2017-11-12 Thread Tino Heth via swift-evolution
Imho it’s good to copy the concept of capture lists — but it could be done 
differently, without polluting the body:
func foo[capture list](parameters) {}
I’m not sure if there are corner cases with subscript-syntax, but in general, I 
think this approach is nicer.

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