스위프트 함수의 재주꾼, 개쿨한 inout 파라미터 이해하기

콜 바이 밸류, 콜 바이 레퍼런스…
값으로 호출하기, 참조로 호출하기…
관심있다면 어디서 한번쯤 들어봤을것 같은 이야기다.
살짝 머리아파올 수도 있고 깊이 파면 메모리와 스택등 진짜 복잡해져서 싫어지는거지만 잘쓰면 유용한 그런 녀석이다.

함수에 전달되는 변수들은 가지고 있는 값을 전달한다. 즉 사본을 전달한다고 이해하면 쉽다.
하지만 어떨 땐 직접 그 값을 변경해야 할때가 있어서 원본을 주고 변경을 해야할 경우도 있다.

메타포적인 예를 들면 이렇다. 내일 영어 시험인데 교과서에 중요한것에 표시를 하고 싶다. 그래서 공부 잘하는 친구에게 복사한 책을 만들어 주고(호출) 친구(함수의 메타포)는 시험에 나올 중요한것에 밑줄을 쳐서 전달 받은 복사한 책을 돌려준다(리턴).
그러면 돌려받은 책을 보고 다시 내가 내 책에 밑줄을 표시한다.

번거롭고 복잡하다. 하지만 내가 내 책을 (원본)을 주고 친구가(함수) 밑줄을 그어주면 그대로 작업이 완료된다.
즉 콜 바이 레퍼런스로 하면 매우 쉽게 일이 처리될 수 있다.

기본적으로 모든 처리가 콜 바이 밸류(값으로 호출) 즉, 사본을 전달하는 방식이기때문에 시간과 번거로움이 생긴다.
왜 그럼 항상 콜 바이 레퍼런스하지 않을까? 당연히 값을 직접 수정하게 하면 친구가 실수도 책을 잊어버리거나 분실하거나(은유적인 표현)할 수 있어서 위험하다. 프로그래밍 세계에서는 이러한 위험이 버그라는 형태로 생기며 어떨땐 어디에서 문제가 생기는지 찾기 어려워 질때도 있어 위험하다. 버그 있으면 열받지 열받으면 술먹지 술먹으면 아프지 아프면 죽지….스위프트 넌 사람을 죽였다 임마!!

너무 서론이 길었다 바로 들어가면…다음의 코드를 보자. 참조에 의한 호출, 소위 콜 바이 레퍼펀스에 항상 나오는 두개 값을 서로 바꾸는 예제이다.

func swapTwoInts(inout a: Int, inout b: Int) {
let temporaryA = a
a = b
b = temporaryA
}

override func viewDidLoad() {
super.viewDidLoad()

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, b: &anotherInt)
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")

}

코드를 프로젝트에 입력하고 실행하면 두개의 값이 서로 바뀌어 있다.

스크린샷 2015-01-27 오후 12.29.01

함수를 정의할 때 파라미터에 inout을 명시해 준다.
이름에서 알수 있듯이 들어간 변수에 값이 바로 아웃된다. 그리고 함수를 호출할때 변수앞에 &를 붙여준다.(너무 당연할 것 같은 느낌이지만 참조값을 얻기 위해서…)

참조에의한 호출은 이처럼 막강한 장점과 함께 위험한(버그) 요소도 있음으로 잘 사용해야 하며 잘 활용하면 함수의 스코프 밖의 변수 값을 변경할 수도 있어 유용하게 사용할 수도 있다.

댓글 남기기