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

Howard Lovatt howard.lovatt at gmail.com
Thu Nov 16 18:38:11 CST 2017


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

    struct _Function1__T1__T1__T1__E__Numeric<T> 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>(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<Int>({ $0 + 1 })
    try _int_increment.call(1) // 2
    let _double_increment = _Function1__T1__T1__T1__E__Numeric<Double>({ $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 <spestov at apple.com> wrote:

>
>
> On Nov 16, 2017, at 3:07 PM, Howard Lovatt via swift-evolution <
> swift-evolution at 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>(T) throws -> T where T: Numeric = { $0 + 1 }
>     let increment = { <T>(n: T) throws -> T where T: Numeric in n + 1 }
>     let increment: <T>(T) throws -> T where T: Numeric = { <T>(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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171117/3463b81a/attachment.html>


More information about the swift-evolution mailing list