Variable capture by gates in Swift and inout parameters

I noticed that when a variable is captured by a closure in Swift, the closure can actually change the value. This seems crazy to me and a great way to get terrifying errors, especially when the same var is caught in multiple closures.

var capture = "Hello captured"
func g(){
    // this shouldn't be possible!
    capture = capture + "!"
}

g()
capture

On the other hand, there are inout parameters that allow a function or closure to change its parameters.

What is the need for inout, even captured variables can already be changed with impunity ?? !!

Just trying to understand the design decisions behind this ...

+4
source share
4 answers

, , , :

func captureMe() -> (String) -> () {

    //  v~~~ This will get 'captured' by the closure that is returned:
    var capturedString = "captured"

    return {

        // The closure that is returned will print the old value,
        // assign a new value to 'capturedString', and then 
        // print the new value as well:

        println("Old value: \(capturedString)")
        capturedString = $0
        println("New value: \(capturedString)")
    }
}

let test1 = captureMe()      // Output: Old value: captured
println(test1("altered"))    //         New value: altered

// But each new time that 'captureMe()' is called, a new instance
// of 'capturedString' is created with the same initial value:

let test2 = captureMe()               // Output: Old value: captured
println(test2("altered again..."))    //         New value: altered again...

// Old value will always start out as "captured" for every 
// new function that captureMe() returns. 

, , - , , . , .

+4

, , , mutablility . () , , ( )

, capture, .

var global = "Global"

func function(nonmutable:Int, var mutable:Int, inout returnable:Int) -> Void {
    // global can be modified here because it a global (not captured!)
    global = "Global 2"

    // nomutable can't be modified
//    nonmutable = 3

    // mutable can be modified, but it caller won't see the change
    mutable = 4

    // returnable can be modified, and it caller sees the change
    returnable = 5
}

var nonmutable = 1
var mutable = 2
var output = 3
function(nonmutable, mutable, &output)

println("nonmutable = \(nonmutable)")
println("mutable = \(mutable)")
println("output = \(output)")

, , inout -, , .

+7

, , , :

, . Theres a filter , , . , , , ? - , , :

func removeDupes<T: Hashable>(source: [T]) -> [T] {
    // "seen" is a dictionary used to track duplicates
    var seen: [T:Bool] = [:]
    return source.filter { // brace marks the start of a closure expression
        // the closure captures the dictionary and updates it
        seen.updateValue(true, forKey: $0) == nil
    }
}

// prints [1,2,3,4]
removeDupes([1,2,3,1,1,2,4])

, , inout, - , , . ( reduce filter, , filter, , )

GeneratorOf, . , , .

, , m 0 n. GeneratorOf:

import Darwin

func randomGeneratorOf(#n: Int, #from: Int) -> GeneratorOf<Int> {

    // state variable to capture in the closure
    var select = UInt32(n)
    var remaining = UInt32(from)
    var i = 0

    return GeneratorOf {
        while i < from {
            if arc4random_uniform(remaining) < select {
                --select
                --remaining
                return i++
            }
            else {
                --remaining
                ++i
            }
        }
        // returning nil marks the end of the sequence
        return nil
    }
}

var g = randomGeneratorOf(n: 5, from: 20)
// prints 5 random numbers in 0..<20
println(",".join(map(g,toString)))

, - , , / , , , . .

+1

, , . #, JavaScript, Perl, PHP, Ruby, Common Lisp, Scheme, Smalltalk . Objective-C, __block, Python 3, nonlocal, ++, &

+1

All Articles