일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Rx5700
- ryzen gen2
- 암드 라이젠 오버클럭
- 라이젠 젠2 오버
- 암드
- radeon vega
- ryzen zen2
- 암드 신제품
- Ryzen
- 라데온
- 베가
- 라데온 신제품
- 라이젠
- 젠2 오버클럭
- vega 7
- 젠2
- Zen2
- 나비
- vega
- 라이젠 오버클럭
- navi
- AMD
- Radeon
- 라데온 나비
- 라이젠 젠2
- 라데온 베가
- 라이젠 오버
- Rx5000
- Today
- Total
SW
클로저 값 획득 (복습) 본문
클로저는 자신이 정의된 위치의 주변 문맥을 통해 상수나 변수를 획득(Capture)할 수 있다.
값 획득을 통해 클로저는 주변에 정의한 상수나 변수가 더 이상 존재하지 않더라도 해당 상수나 변수의 값을 자신 내부에서 참조하거나 수정할 수 있다.
그러기에 클로저가 비동기 작업에 많이 쓰인다.
비동기 콜백(Call-Back)을 작성하는 경우, 현재 상태를 미리 획득해두지 않으면, 실제로 클로저의 기능을 실행하는 순간에는 주변의 상수나 변수가 이미 메모리에 존재하지 않는 경우가 발생한다.
이 부분을 해결하기 위해 중첩 함수를 사용한다.
중첩 함수로 주변의 변수나 상수를 획득해 놓을 수 있다.
즉, 자신을 포함하는 함수의 지역변수나 지역상수를 획득할 수 있다.
func makeIncrementer(forIncrement amount: Int) -> (() -> Int) {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTwo: (()-> Int) = makeIncrementer(forIncrement: 2)
let incrementByTwo2: (()-> Int) = makeIncrementer(forIncrement: 2)
let incrementByTen: (()-> Int) = makeIncrementer(forIncrement: 10)
let first : Int = incrementByTwo()
let second : Int = incrementByTwo()
let third : Int = incrementByTwo()
let first2 : Int = incrementByTwo2()
let second2 : Int = incrementByTwo2()
let third2: Int = incrementByTwo2()
let ten : Int = incrementByTen()
let twenty : Int = incrementByTen()
let thirty : Int = incrementByTen()
let sss : Int = incrementByTen() + incrementByTwo() + incrementByTwo2()
print(first)
print(second)
print(third)
print(first2)
print(second2)
print(third2)
print(ten)
print(twenty)
print(thirty)
print(sss)
incrementByTwo와 incrementByTwo2 의 정수 2를 amount에 입력하여 runningTotal 초기값 0과 2를 더하여 총합2가 된다. 이것을 반복한다.
incrementByTen은 amount에 10을 집어넣어 위와같이 프로그램이 실행된다.
각각의 incrementer 함수는 언제 호출이 되더라도 자신만의 runningTotal 변수를 갖고 카운트하게 된다. 다른 함수의 영향도 전혀 받지 않는다. 각각 자신만의 runningTotal의 참조를 미리 획득했기 때문이다.
이런 식으로 메모리에 상수, 변수가 존재하지 않는 현상을 막을 수 있다.
위 예제에 incrementByTwo와 incrementByTen은 모두 상수이다.
이 두 상수 클로저는 값 획득을 통해 runningTotal 변수를 계속해서 증가시킬 수 있다. 왜냐하면 참조 타입이기 때문이다.
함수나 클로전를 상수나 변수에 할당할 때마다 사실은 상수나 변수에 함수나 클로저의 참조를 설정하는 것이다.
즉 incrementByTwo라는 상수에 클로저를 할당한다는 것은 클로저의 내용물, 즉 값을 할당하는 것이 아니라 해당 클로저의 참조를 할당한 것이다.
결국 클로저의 참조를 다른 상수에 할당해준다면 이는 두 상수가 모두 같은 클로저를 가르킨다는 뜻이다.
func makeIncrementer(forIncrement amount: Int) -> (() -> Int) {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTwo: (()-> Int) = makeIncrementer(forIncrement: 2)
let same2: (()-> Int) = incrementByTwo
let first: Int = incrementByTwo()
let scound: Int = same2()
print(first)
print(scound)
'프로그래밍 > Swift' 카테고리의 다른 글
옵셔널 이해하기 (복습) (0) | 2018.10.21 |
---|---|
자동 클로저 (학습) (0) | 2018.10.17 |
클로저 탈출 (1) | 2018.10.17 |