Weekoding

[Swift] Closure의 단축 인자($0, $1....) 본문

공부 노트(Swift)

[Swift] Closure의 단축 인자($0, $1....)

Weekoding 2022. 4. 11. 23:57

예제로 공부를 하던 중 아래와 같은 코드를 발견했다.

3개의 버튼에 각각 그림자 효과를 넣는 코드이다. 버튼 하나씩 적용하면 총 9줄인데..

신기하게 배열로 묶고 .forEach 메소드를 사용해 단 3줄만에 3개 버튼의 동적 처리를 끝냈다.

        [seriesBtn, movieBtn, categoryBtn].forEach{
            $0?.layer.shadowColor = UIColor.black.cgColor
            $0?.layer.shadowOpacity = 1.0
            $0?.layer.shadowOffset = CGSize(width: 1, height: 1)
        }

.forEach는 내장 함수일 것 같은데,,, $0는 무엇일까? 선언이 된 곳도 없었다.

찾아보니 Closure의 단축 인자라는 것을 알게 되었다.

 

 

⌘ 클로저(Closure): 일정 기능을 하는 코드를 하나의 블록으로 모아놓은 것

(함수도 클로저의 한 형태이다.)

클로저는 변수, 상수가 선언된 위치에서 참조를 획득(capture)하고 저장할 수 있다.

이를 변수나 상수의 Closing이라고 하는데, 여기서 Closure라는 이름이 착안된 것이다. 

//클로저의 기본 표현
{(매개변수들) -> 반환타입 in
	실행코드
}

전달인자 축약, 후행 클로저, 타입 유추, 암시적 반환 표현 등,, 클로저를 다양한 방법으로 표현할 수 있다.

sorted(by:)처럼 함수나 클로저를 인자로 받는 메소드를 사용할 때 

코드를 쉽고 간결하게 표현할 수 있다.  

 

예시를 통해 맛보기를 해보자.

let heroNames: [String] = ["Tony", "Steve", "Peter", "Wanda"]

func backwards(first: String, second: String) -> Bool{
  return first > second
}

let reversedArray: [String] = heroNames.sorted(by: backwards)
print(reversedArray)

// ["Wanda", "Tony", "Steve", "Peter"]

 

sorted(by:)는 클로저를 전달인자로 받을 수 있다.(함수도 사실은 클로저의 한 종류이기도 하니..)

//sorted(by:)에 클로저를 직접 전달
let reversedArray: [String] = heroNames.sorted(by:{(fisrt: String, second: String) -> Bool in
  return first > second
})

함수를 선언하여 넘기지 않고 클로저를 바로 넘김으로써, 코드가 많이 간결해졌다.

그런데 여기서도 클로저의 코드를 더 줄일 수 있는 방법이 있다.

 

 

 

1. [ 문맥을 이용한 타입 유추 ]

메소드 전달인자로 전달하는 클로저는 메소드에서 요구하는 변수 타입과 개수 / 반환타입을 준수해야 하기 때문에,

굳이 표현하지 않고 생략해도 적절한 유추를 통해 알 수 있다.

//전달인자로 사용되는 클로저는 매개변수, 반환타입 생략이 가능하다
let reveredArray: [String] = heroNames.sorted{(first, second) in
  return first > second
}

 

2. [단축 인자 이름]

Swift는 더 간결한 표현을 위해 단축 인자 이름을 제공한다.

첫 번째 전달인자부터 $0, $1, $2...로 이를 이용하여 생략할 수 있다.

이때, 키워드 'in'도 매개변수/반환타입을 실행코드와 구분하기 위해 사용하는 것이기 때문에 생략 가능하다

//단축 인자 이름 사용
let reversedArray: [String] = heroNames.sorted{
return $0 > $1
}

 

3. [암시적 반환 표현]

반환 값을 갖는 클로저이고, 클로저 내부 실행문이 한 줄이라면,

암시적으로 그 실행문을 반환 값으로 사용할 수 있다는 내용이다. 따라서 'return'이 생략 가능해진다.

//암시적 반환 표현(return 키워드 생략)
let reversedArray: [String] = heroNames.sorted{ $0 > $1 }

 

 

📌  어렵지만 한 단계씩 거쳐갈 때마다 간결해지는 코드를 보며 시원함을 느꼈다,,(?)

Closure는 Swift를 사용함에 있어 잘 이해해야 하는 개념 중 하나인데,

그 이유는 Swift가 함수형 프로그래밍 패러다임도 차용했기 때문이다.

표현 방법도 다양해서 조사할 때 이게 뭔가...싶었다.

더 많이 눈으로 익혀보고 코드로 접해보아야 할 것 같다.

Comments