Making capturing semantics of local

class A {

    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local'
requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require self.
which will be quite annoying, especially given the fact that "local" my not
even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in
an escaping context:

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }

    func otherLocal() {
        print("i am not capturing self")
    }

    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if
it's not the case, e.g. even if i only use them in a non-escaping contexts.
worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure
passed

Mike

···

on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com> wrote:

class A {
    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local' requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require self. which will be quite annoying, especially given the fact that "local" my not even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in an escaping context:

I think this would be possible, yes. If nothing else, we could allow the function to be explicitly declared escaping or non-ecaping to get this rule.

John.

···

On Oct 26, 2017, at 2:19 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:
on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }
    
    func otherLocal() {
        print("i am not capturing self")
    }
    
    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if it's not the case, e.g. even if i only use them in a non-escaping contexts. worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure passed

Mike

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

or, to keep the syntax close to the current one:

let closure = { nonescaping () -> Void in
     print("i am non escaping")
     variable = 1 // ok without self
}

with possible optimisations allowing omitting parameters / return values:

let closure = { nonescaping in
     print("i am non escaping")
     variable = 1 // ok without self
}

···

On 26 October 2017 at 19:19, Mike Kluev <mike.kluev@gmail.com> wrote:

on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com> wrote:

class A {

    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local'
requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require
self. which will be quite annoying, especially given the fact that "local"
my not even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in
an escaping context:

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }

    func otherLocal() {
        print("i am not capturing self")
    }

    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if
it's not the case, e.g. even if i only use them in a non-escaping contexts.
worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure
passed

class A {
    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local' requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require self. which will be quite annoying, especially given the fact that "local" my not even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in an escaping context:

I think this would be possible, yes. If nothing else, we could allow the function to be explicitly declared escaping or non-ecaping to get this rule.

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of A.
* It would cause ambiguity when trying to call another member function with the same name as the local function.

···

On 26 Oct 2017, at 21:16, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 26, 2017, at 2:19 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

John.

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }
    
    func otherLocal() {
        print("i am not capturing self")
    }
    
    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if it's not the case, e.g. even if i only use them in a non-escaping contexts. worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure passed

Mike

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

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

class A {
    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local' requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require self. which will be quite annoying, especially given the fact that "local" my not even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in an escaping context:

I think this would be possible, yes. If nothing else, we could allow the function to be explicitly declared escaping or non-ecaping to get this rule.

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of A.
* It would cause ambiguity when trying to call another member function with the same name as the local function.

Oh, sorry, I should've actually read the rest of the email instead of leaping to conclusions. I meant that it would make sense to disallow implicit "self." in a local function that's used as an escaping function (and by implication, allow implicit "self." in a local function that's only used as a non-escaping function), not that we should require uses of local functions that capture self to explicitly mention that fact at the use site.

John.

···

On Oct 26, 2017, at 3:24 PM, David Hart <david@hartbit.com> wrote:

On 26 Oct 2017, at 21:16, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Oct 26, 2017, at 2:19 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

John.

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }
    
    func otherLocal() {
        print("i am not capturing self")
    }
    
    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if it's not the case, e.g. even if i only use them in a non-escaping contexts. worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure passed

Mike

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

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

in the escaping contexts, "self." is currently required before the instance
members (**).
the idea is to require it before some local functions as well, recursively
analysing what these local functions do (at the compile time).

/* local */ foo() {
    bar()
    variable = 1
}

...
self.foo()

// self is required because the compiler knows what's inside, and if it
were to put the content inline that would be:

// inlining foo pseudo code:
     self.bar()
     self.variable = 1

hence the compiler can figure out that in this case "self" is required
before foo()

on the other hand:

/* local */ poo() {
    print("doesnt not capture anything")
}

here, if compiler were to use poo in the escaping context it would not
require "self." before it.

this decision (whether to require "self." on not) can be on the use side.

(**) FTM, the normal instance methods that do not capture anything may as
well not require "self." before them in escaping contexts:

/* non local */ baz() {
    print("doesn't capture anything")
}

Mike

···

On 26 October 2017 at 20:24, David Hart <david@hartbit.com> wrote:

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of A.
* It would cause ambiguity when trying to call another member function
with the same name as the local function.

class A {
    func foo() {
        func local() {
            bar() // error: Call to method ‘bar' in function ‘local' requires explicit 'self.' to make capture semantics explicit
        }

        // ...
    }
}

it's not only about calling "bar"... any variable access will require self. which will be quite annoying, especially given the fact that "local" my not even be used in an escaping context discussed. (*)

i think it is more consistent to prepend local with self if it is used in an escaping context:

I think this would be possible, yes. If nothing else, we could allow the function to be explicitly declared escaping or non-ecaping to get this rule.

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of A.
* It would cause ambiguity when trying to call another member function with the same name as the local function.

Oh, sorry, I should've actually read the rest of the email instead of leaping to conclusions. I meant that it would make sense to disallow implicit "self." in a local function that's used as an escaping function (and by implication, allow implicit "self." in a local function that's only used as a non-escaping function), not that we should require uses of local functions that capture self to explicitly mention that fact at the use site.

Gotcha.

···

On 26 Oct 2017, at 21:40, John McCall <rjmccall@apple.com> wrote:

On Oct 26, 2017, at 3:24 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 26 Oct 2017, at 21:16, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Oct 26, 2017, at 2:19 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
on Wed, 25 Oct 2017 13:41:40 +0200 David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

John.

John.

func foo() {

    func local() {
        bar() // no self needed here ever
        variable = 1 // no self needed here, ever
    }
    
    func otherLocal() {
        print("i am not capturing self")
    }
    
    DispatchQueue.main.async {
        local() // error without self
        self.local() // ok
        otherLocal() // ok without self
    }
}

(*) interestingly, closures always treat themselves as "escaping", even if it's not the case, e.g. even if i only use them in a non-escaping contexts. worth to add an explicit attribute to denote non-escaping closures?

let closure = @nonescaping {
    print("i am not escaping")
    variable = 1 // ok without self
}

DispatchQueue.main.async(execute: closure) // error, non escaping closure passed

Mike

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

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

The issues raised about local capture by local (inner) functions are valid,
likewise the discussion about the @nonescaping annotation are also valid.

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

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

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

  -- Howard.

···

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

On 26 October 2017 at 20:24, David Hart <david@hartbit.com> wrote:

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of
A.
* It would cause ambiguity when trying to call another member function
with the same name as the local function.

in the escaping contexts, "self." is currently required before the
instance members (**).
the idea is to require it before some local functions as well, recursively
analysing what these local functions do (at the compile time).

/* local */ foo() {
    bar()
    variable = 1
}

...
self.foo()

// self is required because the compiler knows what's inside, and if it
were to put the content inline that would be:

// inlining foo pseudo code:
     self.bar()
     self.variable = 1

hence the compiler can figure out that in this case "self" is required
before foo()

on the other hand:

/* local */ poo() {
    print("doesnt not capture anything")
}

here, if compiler were to use poo in the escaping context it would not
require "self." before it.

this decision (whether to require "self." on not) can be on the use side.

(**) FTM, the normal instance methods that do not capture anything may as
well not require "self." before them in escaping contexts:

/* non local */ baz() {
    print("doesn't capture anything")
}

Mike

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

I don’t think at this point such a drastic change to the language is likely to happen.

Slava

···

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

Rather than expand local function syntax why not deprecate local functions completely

i use a lot of local @inline(__always) functions as a sort of weird macro so this change would be hugely source breaking. Also can you even annotate a function object as force-inlineable?

···

On Oct 26, 2017, at 6:45 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

The issues raised about local capture by local (inner) functions are valid, likewise the discussion about the @nonescaping annotation are also valid.

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

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

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

  -- Howard.

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

On 26 October 2017 at 20:24, David Hart <david@hartbit.com> wrote:

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of A.
* It would cause ambiguity when trying to call another member function with the same name as the local function.

in the escaping contexts, "self." is currently required before the instance members (**).
the idea is to require it before some local functions as well, recursively analysing what these local functions do (at the compile time).

/* local */ foo() {
    bar()
    variable = 1
}

...
self.foo()

// self is required because the compiler knows what's inside, and if it were to put the content inline that would be:

// inlining foo pseudo code:
     self.bar()
     self.variable = 1

hence the compiler can figure out that in this case "self" is required before foo()

on the other hand:

/* local */ poo() {
    print("doesnt not capture anything")
}

here, if compiler were to use poo in the escaping context it would not require "self." before it.

this decision (whether to require "self." on not) can be on the use side.

(**) FTM, the normal instance methods that do not capture anything may as well not require "self." before them in escaping contexts:

/* non local */ baz() {
    print("doesn't capture anything")
}

Mike

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

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

a cautious +0.5. local functions do not add that much value as one would
hope and beyond what's already discussed above, unfortunately break one
major programming guideline: "keep functions short" (*). the following two
fragments are not too different:

<<<<<<<<<<<<<<
func foo() {

let animations = {
self.view.alpha = 0.5 // self needed
}

UIView.animate(withDuration: 1, animations: animations) {
self.variable = 1 // self needed
print("completed")
}
}

···

On 27 October 2017 at 00:45, Howard Lovatt <howard.lovatt@gmail.com> wrote:

Rather than expand local function syntax why not deprecate local functions
completely

==============
func foo() {

func animations() {
view.alpha = 0.5 // can do without self...
}

func completion(_ : Bool) {
variable = 1 // can do without self...
print("completed")
}
UIView.animate(withDuration: 1, animations: animations, completion:
completion)
}

(*) - closures break the "keep functions short" guideline as well :slight_smile:

Mike

Allow function types that are both let and initialized to be annotated
with @inline.
If closures get more features then we fix the bug pointed out with local
functions and we get better closures. Good bang for the buck.

  -- Howard.

···

On 27 October 2017 at 12:22, Taylor Swift <kelvin13ma@gmail.com> wrote:

i use a lot of local @inline(__always) functions as a sort of weird macro
so this change would be hugely source breaking. Also can you even annotate
a function object as force-inlineable?

On Oct 26, 2017, at 6:45 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

The issues raised about local capture by local (inner) functions are
valid, likewise the discussion about the @nonescaping annotation are also
valid.

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

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

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

  -- Howard.

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

On 26 October 2017 at 20:24, David Hart <david@hartbit.com> wrote:

I don’t see how this makes any sense or be possible:

* It doesn’t make sense for me because local is not a member function of
A.
* It would cause ambiguity when trying to call another member function
with the same name as the local function.

in the escaping contexts, "self." is currently required before the
instance members (**).
the idea is to require it before some local functions as well,
recursively analysing what these local functions do (at the compile time).

/* local */ foo() {
    bar()
    variable = 1
}

...
self.foo()

// self is required because the compiler knows what's inside, and if it
were to put the content inline that would be:

// inlining foo pseudo code:
     self.bar()
     self.variable = 1

hence the compiler can figure out that in this case "self" is required
before foo()

on the other hand:

/* local */ poo() {
    print("doesnt not capture anything")
}

here, if compiler were to use poo in the escaping context it would not
require "self." before it.

this decision (whether to require "self." on not) can be on the use side.

(**) FTM, the normal instance methods that do not capture anything may as
well not require "self." before them in escaping contexts:

/* non local */ baz() {
    print("doesn't capture anything")
}

Mike

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

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

It would be easy to provide a fixit. How often are they actually used? I
rarely use them and all my use cases could be a closure instead.

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

  -- Howard.

···

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

Rather than expand local function syntax why not deprecate local functions
completely

I don’t think at this point such a drastic change to the language is
likely to happen.

Slava

Closures cannot replace all uses of local functions. Local functions can

be recursive, and have a generic parameter list.

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

In terms of recursion you can fiddle it:

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

  -- Howard.

···

On 27 October 2017 at 15:53, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 9:52 PM, Howard Lovatt <howard.lovatt@gmail.com> > wrote:

It would be easy to provide a fixit.

That is still a source breaking change that requires migration, though.

How often are they actually used? I rarely use them and all my use cases
could be a closure instead.

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

Closures cannot replace all uses of local functions. Local functions can
be recursive, and have a generic parameter list.

Slava

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution < >> swift-evolution@swift.org> wrote:

Rather than expand local function syntax why not deprecate local
functions completely

I don’t think at this point such a drastic change to the language is
likely to happen.

Slava

It would be easy to provide a fixit.

That is still a source breaking change that requires migration, though.

How often are they actually used? I rarely use them and all my use cases could be a closure instead.

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

Closures cannot replace all uses of local functions. Local functions can be recursive, and have a generic parameter list.

Slava

···

On Oct 26, 2017, at 9:53 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com <mailto:spestov@apple.com>> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Rather than expand local function syntax why not deprecate local functions completely

I don’t think at this point such a drastic change to the language is likely to happen.

Slava

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

> Closures cannot replace all uses of local functions. Local functions can be recursive, and have a generic parameter list.

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

Since closures are first class values, giving closures the ability to define their own generic parameters means the type system would now need to support higher-rank polymorphism. This is a complex feature...

In terms of recursion you can fiddle it:

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

Sure, this is just the Scheme letrec-to-let transform done by hand. But at this point, it’s clearly worse than defining a local function, even more so if you have multiple mutually recursive local functions.

Slava

···

On Oct 26, 2017, at 10:27 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

  -- Howard.

On 27 October 2017 at 15:53, Slava Pestov <spestov@apple.com <mailto:spestov@apple.com>> wrote:

On Oct 26, 2017, at 9:52 PM, Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:

It would be easy to provide a fixit.

That is still a source breaking change that requires migration, though.

How often are they actually used? I rarely use them and all my use cases could be a closure instead.

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

Closures cannot replace all uses of local functions. Local functions can be recursive, and have a generic parameter list.

Slava

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com <mailto:spestov@apple.com>> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Rather than expand local function syntax why not deprecate local functions completely

I don’t think at this point such a drastic change to the language is likely to happen.

Slava

I use local functions heavily in my day-to-day workflow and an very
interested in them supporting capture lists.
Here is a draft feature specification:
https://bitbucket.org/snippets/lynchrb/r487zn

Anyone see any weak spots?

Alex

···

On Fri, Oct 27, 2017 at 12:54 AM, Slava Pestov via swift-evolution < swift-evolution@swift.org> wrote:

On Oct 26, 2017, at 9:53 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

It would be easy to provide a fixit.

That is still a source breaking change that requires migration, though.

How often are they actually used? I rarely use them and all my use cases
could be a closure instead.

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

Closures cannot replace all uses of local functions. Local functions can
be recursive, and have a generic parameter list.

Slava

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution < >> swift-evolution@swift.org> wrote:

Rather than expand local function syntax why not deprecate local
functions completely

I don’t think at this point such a drastic change to the language is
likely to happen.

Slava

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

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

> Closures cannot replace all uses of local functions. Local functions can be recursive, and have a generic parameter list.

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

In terms of recursion you can fiddle it:

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

sorry, offtopic to the thread but that you can have easier with the fixed-point combinator (https://en.wikipedia.org/wiki/Fixed-point_combinator)

// the fixed-point combinator
func fix<T>(_ f: @escaping ((@escaping (T) -> T) -> (T) -> T)) -> (T) -> T {
    return { (x: T) in (f(fix(f)))(x) }
}

// demo
let fact = fix { fact_ in { n in n == 1 ? 1 : n * fact_(n-1) } }
for i in 1..<10 {
    print(fact(i))
}

-- Johannes

···

On 27 Oct 2017, at 6:27 am, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

  -- Howard.

On 27 October 2017 at 15:53, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 9:52 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

It would be easy to provide a fixit.

That is still a source breaking change that requires migration, though.

How often are they actually used? I rarely use them and all my use cases could be a closure instead.

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

Closures cannot replace all uses of local functions. Local functions can be recursive, and have a generic parameter list.

Slava

  -- Howard.

On 27 October 2017 at 12:26, Slava Pestov <spestov@apple.com> wrote:

On Oct 26, 2017, at 4:45 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

Rather than expand local function syntax why not deprecate local functions completely

I don’t think at this point such a drastic change to the language is likely to happen.

Slava

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