스위프트의 정말 끝내주는 개쿨한 클로져, Closures

이름 그대로 끝내주는 녀석이 왔다. 생긴건 코드 블록 {} 이다. 따라서 어떤 나름 의미있는 기능을 수행하는 하나의 코드 블록이다. Objective-C 에서 블록 (Block)은 이미 있었고 다른 C# 같은 언어에서는 람다 (Lambdas) 라고 알려진 녀석이다.

어찌보면 클로벌 혹은 네스티드(함수안의 함수) 함수가 클로져의 한 예가 될것이다. 일단 들이대보자.
우선, 여기 몇명의 이름이 있다. 형태상 스트링 배열로 되어 있다.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

일단 흔한 예로 이름들을 알파벳 순서대로 출력해보자.

println(sorted(names))

그렇다. sorted()라는 함수를 쓰면된다. 역시 애플은 다 만들어 놓았다. 왠만한건 찾아보면 다 있다. 내가 뭘 찾아야 하는줄만 알면 된다. 어쨌든. 결과도 원하는 결과를 얻는다.

기본 프로젝트 만들기 참조

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
println(sorted(names))
self.title = sorted(names).description

위에 코드를 입력해서 실행하면 아래와 같이 이름이 정렬되어 나온다.

스크린샷 2015-01-29 오후 12.26.53

쿨~~ 일단, 스트링 배열을 알파벳으로 정렬하는건 간단하게 된다.
그럼, 이번에는 이름을 반대의 순서로 적어보자. 헐~~

일단 sorted의 정의를 찾아보자.
찾아보면 결과적으로 (String, String) -> Bool 형태의 함수를 파라미터로 전달해야 한다.
즉, 두개의 스트링을 비교해서 큰지 작은지 같은지를 판단해서 줄 수 있는 함수를 sorted 에 전달해 주면된다.
위에서 하지 않은것은 우리가 일반적으로 순서를 정하는 방식, 즉 숫자는 작은것부터, 알파벳은 A부터 등과 같이 정해져 있는것은 생략할 수 있기 때문이었다.

결과적으로 우리가 반대로 정렬하려면 반대로 정렬해주는 함수를 타입을 파라미터로 전달해주면 된다.
위에서 이름들 즉, 스트링 배열임으로 이런 형태의 함수면 된다.

func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}

두개의 문자열을 받아서 어떤것이 큰지 알려주는 함수이다.
다시 프로그램을 수정해보면…

func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}

override func viewDidLoad() {
super.viewDidLoad()

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversed = sorted(names, backwards)
println(reversed)
self.title = reversed.description
}

backwards라는 함수를 정의하고 sorted를 호출할때 정의한 함수를 파라미터로 전달해준다.
그러면 원했던 반대 순서로 정렬되어 나타난다.

스크린샷 2015-01-29 오후 12.38.46

오호라..잘된다.
그러면 이번에 제대로 클러져를 사용해서 같은 작업을 해보자.

이 녀석 생긴건 그냥 {} 코드 블록인데 그 안에 이름 없는 함수처럼 달랑 파라미터랑 리턴타입이 있고 명령문이있다. 그렇다. 클로져는 이렇게 생겼다. 함수랑 비슷한데 약간 모양이 다른것 처럼 보인다. 그렇다. 그냥 이름없는 함수로 이해하면 쉽다.

{ (parameters) -> return type in
statements
}

그럼 이 녀석으로 위에서 사용했던 backwards 라는 함수를 대신해서 클로져를 사용해 보자.
이렇게 수정한다.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversed = sorted(names,
{ (s1: String, s2: String) -> Bool in return s1 > s2 } )
println(reversed)
self.title = reversed.description

역시 결과는 똑같다. 맞다. backwards 라는 함수는 정의하지 않아도 된다. 위에서 처럼 함수가 들어갈 자리에 클로져를 넣어주면 된다.
뭔가 살짝 복잡한 형태로 보이지만 함수의 이름을 만들려고 고민하지 않아도 되고 어쨌든 약간 편해진것 같다.

우리 끝내주는 클로져는 좀 더 간단하게 해도 알아서 처리해 준다. 클로져 부분을 이렇게 수정해보자.

{ s1, s2 in return s1 > s2 }

헉…결과는 같다. 어찌된 일인가? 클로져는 이미 다 안다. 어쩌피 전달되는것은 String이고 당근 리턴은 참거짓인지 알기때문에 생략해도 알아서 잘 처리해준다. 기특하다.

그럼 더 줄일수 있을까? 있다.

var reversed = sorted(names, > )

위의 코드에서 클로져 들어갈곳에 달랑 > 하나만 넣어줘도 잘 된다. 그냥 우연히 아니라 이게 끝내주는 클로져가 알아서 끝내주기 때문이다. 어짜피 전달된 파라미터가 두개이며 문자열이고 계산해서 넘겨줄게 앞에게 큰지 작은지만 알려주면 되 앞에게 큰지 작은지 > 하나만 있으면 다 알아서 해준다. 개쿨~~~하다.

댓글 남기기