3

Like most languages, Swift supports variables of limited scope within conditionals, loops etc., however it doesn't seem to support a plain block on its own, which is a shame as I find it a very useful way to limit the scope of a variable, particularly costly ones that might be needed for the full length of a function.

For example, I might do something like (using Swift as an example, since this won't currently compile):

var results = []
while let newResult = someFunction() { results.append(newResult) }

{
    var newItems = []
    while let newItem = foobar() { newItems.append(newItem) }
    // Process newItems into results so we can add them
    results += newItems
}

// Do some more stuff down here

It can also be very handy for common placeholder names, but which may have different types at different parts in the execution. While I could declare different names, it can actually end up more confusing or messier than just reusing a good variable name with a clearly marked scope.

Of course I can do things like if true {} to cheat a bit, but it seems unnecessary. So is there a way I can just declare a scope/block without having to put in a conditional?

I know it may have something to do with the way closures can be formed, but is there a way to do something like this purely to limit variable scope in Swift?

Haravikk
  • 3,109
  • 1
  • 33
  • 46

2 Answers2

0

What I do is define an anonymous function and execute it.

{
    () -> () in
    var newItems = []
    while let newItem = foobar() { newItems.append(newItem) }
    // Process newItems into results so we can add them
    results += newItems
}()

You might have to put a semicolon at the end of the previous line so Swift doesn't think think this is a "trailing closure".

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I don't think that compiles. – Bjorn Jan 27 '15 at 18:10
  • That also doesn't work. You have to assign it to something. – Bjorn Jan 27 '15 at 18:12
  • Put a variable declaration before your closure and see if it works then. – Bjorn Jan 27 '15 at 18:13
  • like this, this doesn't compile: https://gist.github.com/btipling/93a648cec290ba9796c2 – Bjorn Jan 27 '15 at 18:14
  • If the state of the previous line affects your current code, like it requires a semi-colon, I would call that broken. Assign to a _ and the problem goes away with no qualification. Like no "this works...but" needed. It just works. – Bjorn Jan 27 '15 at 18:17
  • If someone copies your solution into their code as is, it may or it may not work. This is a fact. :\ – Bjorn Jan 27 '15 at 18:20
  • @BjornTipling Leave it. I'm not changing my answer. He asked what people do and I told him what I do. I do this all the time. Downvote my answer if you don't like it. – matt Jan 27 '15 at 18:26
0

I do it this way, works in the playground:

var foo = "bar"

let _ = {() -> () in
   var foo = "nope"
   println(foo)
}()

println(foo)
Bjorn
  • 69,215
  • 39
  • 136
  • 164