[swift-evolution] Streamlining closures

Marc Knaup marc at knaup.koeln
Sun Dec 13 08:26:05 CST 2015


How would you write this with the new syntax?

someAsyncFunction() { error in
    // …
}

This doesn't make sense (like Thorsten explained earlier):

someAsyncFunction() error {
    // …
}

I agree though that "in" is confusing and I never understood what "in"
means here.
Since "do" is no longer used for loops but code blocks it would make sense
to replace "in" with "do".

someAsyncFunction() { error do
    // …
}


On Sun, Dec 13, 2015 at 9:42 AM, Thorsten Seitz via swift-evolution <
swift-evolution at swift.org> wrote:

> Hi Taras,
>
> I don't think the syntax { x in ... } is a hindrance for your proposal of
> turning all code blocks into closures, as all code blocks currently have no
> arguments and in that case both variants look the same. All code blocks
> with the exception of function bodies but I think having these looking
> different is ok.
>
> An advantage of the current syntax is that you can leave off the
> parentheses when calling a closure if it is the last argument which already
> enables the syntax you would like for "local":
>
> let x = local {
>         ...
> }
>
> This requires having the arguments inside the braces to allow for things
> like these:
>
> someCollection.forEach { x in ... }
> File.open("some/path") { file in ... } // having the file closed
> automatically
>
> Such usage patterns would look awkward with arguments outside of the
> braces and they are very common and very useful.
>
> Actually I was very surprised to see that your example with "local"
> returning a tuple did not work. The type inferencer should be able to infer
> the result type T to be a tuple without problems.
>
> -Thorsten
>
> Am 13.12.2015 um 05:14 schrieb Taras Zakharko via swift-evolution <
> swift-evolution at swift.org>:
>
> Dear all,
>
> first of all, thank you for giving the community the opportunity to
> influence the future of Swift. This is a strong move, which shows how
> passionate the Swift team is about their language and how you guys want to
> make it the best.
>
> Personally, I am a huge fan of streamlined, logically concise concepts as
> well as syntax in programming languages. This is an area where Swift both
> excels at (love what you do with types in the compiler) but also sometimes
> lacking, as there seems to be a lot of idiosyncrasy, as evident from the
> huge number of language keywords and compiler attributes.  Here, I would
> like to discuss some of the idiosyncrasy with closures. As I am trying to
> throw some random ideas out there, my post might be a bit chaotic, so
> please bear with me.  Besides, I literally started playing around with
> Swift only few hours ago (I know, I know, I’m late), so my practical
> knowledge of the language is very limited.
>
> 1. I always wondered about the specific closure syntax { A -> B in … }.
> The type annotation is within the block for some reason and the there is
> the keyword ‘in’, which is usually associated with the for loop. My
> proposal would be to change this to simply:
>
>    A -> B { … }
>
> That is, the closure declaration closely mirrors the function declaration,
> but without the 'func name’ part. This is far from being just a cosmetic
> change though. Rather, it has some far-reaching consequences to how the
> concept of closure is applied to the language, but I believe that this
> would make Swift much more streamlined and concise (and also solve some
> other issues in the process).
>
> The crucial point is that the type annotation is (and should be) optional.
> Which means that every code block { … } is a closure. I think this
> fundamentally makes a lot of sense. So, a function declaration is just a
> closure associated with a name identifier (aka. injected into the
> namespace). Similarly, code blocks used in statements such as for and do
> have local lexical scope, which makes them essentially compatible closures
> as far as I can see.
>
> Essentially, this approach radically simplifies the language both from the
> syntax standpoint — closures and funcs are using the same syntax, the
> notion of code blocks is removed from the language; but also from the
> semantics standpoint. For instance, one can give more formal definitions
> for statements, which opens the path of treating statements as expressions
> (see
> https://lists.swift.org/pipermail/swift-evolution/2015-December/000133.html).
> For instance, current if is of type (Bool, ()->())->(), but it can easily
> be redeclared as (Bool, ()->T)->T, which opens way to nice things like
>
>   let x = if(…) { .. some complex setup code..; value1} else { … other
> code..; value2}
>
> Similarly, do can be used to incapsulate auxiliary computations in the
> local scope (see below).
>
> 2. Another closure limitation is that return type inference does not work
> with longer closures (but they should). Here a particular use case.  Due to
> my work, I program a lot with R (which is sometimes a neat language in its
> own right). A particular paradigm I find very useful is to use anonymous
> code blocks in local scope to prevent namespace pollution, e.g. (in R code)
>
>  dataset <- local({
>    a <- some_computation
>    b <- some_computation
>
>    a combined with b
> })
>
> // a and b are not visible in the outer scope anymore
>
> In JavaScript, people often use anonymous functions for the same effect.
> The nice thing about this paradigm is that it allows one to properly
> isolate data dependency from each other, give the compiler a better sense
> of variable lifespan and overall make your code much nicer to read. Of
> course, in Swift  this can be done with nested functions or closures, but
> its the question of aesthetics. At any rate, the R function is very easy to
> emulate in Swift:
>
>  func local<T>(closure: () -> T) -> T {
>      return closure()
>  }
>
> which works beautifully, e.g.
>
>  let (a1,a2) = local({return(1, 2)}
>
> However, if I want to use more complex code, I need to explicitly declare
> the closure type:
>
>    let (a1, a2) = local({ () -> (Int, Int) in
>      let x2 = x*2
>
>      return (x2, x2+1)
>    })
>
>
> This is bulky, and frankly, unnecessary, as the compiler can easily infer
> the return type of the closure.
>
> BTW, combined with proposal in 1., this style of programming just becomes
> the beautiful
>
> let (a1, a2) = do {
>   .. do something ..
>  return(…, …) // or simply (…, …)
> }
>
>
> Summary TL;DR version of the proposal:
>
> replace the {A->B in …} closure syntax by A->B {…} — where type
> declaration is optional, remove the concept of code block (replace it by
> closure) and statements that take blocks/closures typed expressions.
> Improve type inference for return values. Current syntactic sugar for
> closures such as anonymous arguments and last line as return values should
> be preserved.
>
> Advantages: streamlines the language, solves a number of issues at the
> same time (idiosyncrasy, operators as expressions). In the end, makes the
> language easier to use and also to understand conceptually.
>
> Disadvantages: I honestly can’t see a single one
>
> Implementation challenge: would requires a parser change that might be
> non-trivial. I can also imagine that a lot of refactoring in the compiler
> code is necessary in regards to how statements work — but this might pay
> off as in the end, the compiler only needs to deal with closures and calls,
> which simplifies optimisation. And Swift is already great at aggressive
> inlining of closures.
>
> Impact on existing code: the syntax of closure declarations can be
> automatically ported as the rewrite rule is trivial. As far as I can see,
> changing code blocks to closures won’t have any impact on the semantics of
> the control structures, because the blocks are already using lexical scope.
>
> Eager to hear your thoughts on this!
>
> Cheers,
>
> Taras
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151213/c0d97fb6/attachment.html>


More information about the swift-evolution mailing list