Making capturing semantics of local

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

what a hack and a half :slight_smile:

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))
}

that would be a serious crime against humanity if swift allows this type of
code at all :slight_smile:

Mike

路路路

on Date: Fri, 27 Oct 2017 17:52:54 +0100 Johannes Wei脽 < johannesweiss@apple.com> wrote:

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

Hi Mike,

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

what a hack and a half :slight_smile:

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))
}

that would be a serious crime against humanity if swift allows this type of code at all :slight_smile:

the fixed-point combinator and Y combinator are pretty important in functional languages. And the above code works in Swift. The good thing is that you need to write `fix` only once and you can then use it for all closures that need to be recursive.

-- Johannes

路路路

On 27 Oct 2017, at 7:05 pm, Mike Kluev <mike.kluev@gmail.com> wrote:
on Date: Fri, 27 Oct 2017 17:52:54 +0100 Johannes Wei脽 <johannesweiss@apple.com> wrote:
> On 27 Oct 2017, at 6:27 am, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

Mike

Hi Mike,

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

what a hack and a half :slight_smile:

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))
}

that would be a serious crime against humanity if swift allows this type of code at all :slight_smile:

the fixed-point combinator and Y combinator are pretty important in functional languages.

They're important in the theory of functional languages. Anyone seriously promoting using the Y combinator in actual programming instead of using the language's native recursive-binding features is, frankly, someone you should not being taking advice from.

John.

路路路

On Oct 28, 2017, at 6:05 AM, Johannes Wei脽 via swift-evolution <swift-evolution@swift.org> wrote:

On 27 Oct 2017, at 7:05 pm, Mike Kluev <mike.kluev@gmail.com> wrote:
on Date: Fri, 27 Oct 2017 17:52:54 +0100 Johannes Wei脽 <johannesweiss@apple.com> wrote:

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

And the above code works in Swift. The good thing is that you need to write `fix` only once and you can then use it for all closures that need to be recursive.

-- Johannes

Mike

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

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?

this shall apply to methods as well, why not.

personally i'd put things like capture list (and even parameters/result in
case of closures) outside of the brackets.

At present, the programer has no choice but to select a closure, even if

the use case would make a local function more expressive or easier to read.

this quote raises a general question: are closures harder to read and if so
can we do anything to improve their readability.

Mike

路路路

on Date: Fri, 27 Oct 2017 15:15:15 -0400 Alex Lynch <lynch.sft@gmail.com> wrote:

Hi Mike,

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

what a hack and a half :slight_smile:

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))
}

that would be a serious crime against humanity if swift allows this type of code at all :slight_smile:

the fixed-point combinator and Y combinator are pretty important in functional languages.

They're important in the theory of functional languages. Anyone seriously promoting using the Y combinator in actual programming instead of using the language's native recursive-binding features is, frankly, someone you should not being taking advice from.

Definitely not arguing with that. But there are (valid?) cases when you want a recursive closure which doesn鈥檛 have a native recursion mechanism and then `fix` can be useful I鈥檇 argue. I think more straightforward than

recursive.c = { x in
聽聽聽聽聽聽聽(x == 0) ? 1 : x * recursive.c(x - 1)
聽聽聽}

. But fortunately have local functions, I can only recall wanting a recursive closure once.

鈥 Johannes

路路路

On 28 Oct 2017, at 10:14 pm, John McCall <rjmccall@apple.com> wrote:

On Oct 28, 2017, at 6:05 AM, Johannes Wei脽 via swift-evolution <swift-evolution@swift.org> wrote:

On 27 Oct 2017, at 7:05 pm, Mike Kluev <mike.kluev@gmail.com> wrote:
on Date: Fri, 27 Oct 2017 17:52:54 +0100 Johannes Wei脽 <johannesweiss@apple.com> wrote:

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

John.

And the above code works in Swift. The good thing is that you need to write `fix` only once and you can then use it for all closures that need to be recursive.

-- Johannes

Mike

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

following C tradition to have declarations mimicking usage, the
weak/unowned specifier shall be on the left to the name, as the "self"
itself is on the left: self.foo

maybe a too wild idea, but how about this:

weak func foo() {
聽聽聽...
}

as a special case of "weak self" specifier. instead of:

func foo() { [weak self] in
聽聽聽...
}

of course it doesn't address everything that can be achieved by general
capture list specifiers.

Mike

路路路

On 28 October 2017 at 23:45, Mike Kluev <mike.kluev@gmail.com> wrote:

on Date: Fri, 27 Oct 2017 15:15:15 -0400 Alex Lynch <lynch.sft@gmail.com> > wrote:

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?

Definitely not arguing with that. But there are (valid?) cases when you

want a recursive closure which doesn鈥檛 have a native recursion mechanism
and then `fix` can be useful I鈥檇 argue. I think more straightforward than

recursive.c = { x in
聽聽聽聽聽聽聽(x == 0) ? 1 : x * recursive.c(x - 1)
聽聽聽}

you can do without "recursive.c":

var factorial: ((Int) -> Int)!

factorial = { n in
聽聽n == 0 ? 1 : n * factorial(n - 1)
}

factorial(5) // 120

. But fortunately have local functions, I can only recall wanting a
recursive closure once.

in down to earth practical programming even if i didn't have local
functions i probably wouldn't bother abusing closures to implement
recursion, would just used what's available: methods. and if there is some
extra state to pass from the outer scopes, well, so be it, either via
parameters of via some instance variables, etc. wasn't too much of a
problem in good old C/C++. in a way, knowing exact state you want to pass
and passing it explicitly organises the code and the reasoning about it.

Mike

路路路

On 29 October 2017 at 14:02, Johannes Wei脽 <johannesweiss@apple.com> wrote:

Definitely not arguing with that. But there are (valid?) cases when you want a recursive closure which doesn鈥檛 have a native recursion mechanism and then `fix` can be useful I鈥檇 argue. I think more straightforward than

recursive.c = { x in
聽聽聽聽聽聽聽(x == 0) ? 1 : x * recursive.c(x - 1)
聽聽聽}

you can do without "recursive.c":

var factorial: ((Int) -> Int)!

factorial = { n in
聽聽聽聽聽聽聽聽n == 0 ? 1 : n * factorial(n - 1)
}

That鈥檚 nicer, thanks!

路路路

On 29 Oct 2017, at 3:01 pm, Mike Kluev <mike.kluev@gmail.com> wrote:

On 29 October 2017 at 14:02, Johannes Wei脽 <johannesweiss@apple.com> wrote:

factorial(5) // 120

. But fortunately have local functions, I can only recall wanting a recursive closure once.

in down to earth practical programming even if i didn't have local functions i probably wouldn't bother abusing closures to implement recursion, would just used what's available: methods. and if there is some extra state to pass from the outer scopes, well, so be it, either via parameters of via some instance variables, etc. wasn't too much of a problem in good old C/C++. in a way, knowing exact state you want to pass and passing it explicitly organises the code and the reasoning about it.

Mike