2024년 3월 16일 토요일
- 익명 함수 closurer와,
- 다른 함수를 인자로 받거나, 함수의 결과로 함수를 반환하는 고차함수(map, filter, reduce)를 공부해 봅니다.
#1. Closure
#2. Higher Order Function (고차함수)
#1. Closure
- 이름없는 함수 즉, 코드 블록을 말한다. ('closure'라는 단어가 참 잘 어울린다.. )
- 상수나 변수의 참조를 캡쳐(capture)해 저장할 수 있습니다
- 주변 환경에 있는 변수나 상수를 캡처하여 저장하고, 이를 나중에 사용할 수 있도록 하는데 이것은 클로저가 생성될 때 클로저가 참조하는 변수 또는 상수의 값에 대한 복사본을 유지하고 저장하는 메커니즘이다.
- 값(value) 캡처: 클로저가 변수나 상수의 값을 캡처한다. 이때, 클로저 내부에서 캡처한 값이 변경되어도 원본 값은 변경되지 않는다.
- 참조(reference) 캡처: 클로저가 변수나 상수의 참조를 캡처한다. 클로저 내에서 해당 변수나 상수를 변경하면 원본 값도 변경된다.
// 값 캡처
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var total = 0
// 클로저를 반환합니다.
let incrementer: () -> Int = {
// total 변수를 캡처하여 저장합니다.
total += amount
return total
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // total = 10, 결과: 10
print(incrementByTen()) // total = 20, 결과: 20
// 참조 캡처
class SimpleClass {
var value: Int = 10
}
func createClosure() -> (() -> Int) {
let instance = SimpleClass()
// 참조 캡처를 사용하여 SimpleClass의 인스턴스를 캡처합니다.
let closure: () -> Int = {
// 클로저가 참조하는 인스턴스의 속성을 업데이트합니다.
instance.value *= 2
return instance.value
}
return closure
}
// 클로저 생성
let myClosure = createClosure()
print(myClosure()) // 20
print(myClosure()) // 40
// 클로저 내부에서 참조된 인스턴스의 속성을 변경하였으므로 원본에도 영향을 줍니다.
- 클로저를 사용하는 이유는? 가장 일반적으로는 기능을 저장하기 위해서 사용한다.
- 클로저는 비동기 처리가 필요할 때 사용할 수 있는 코드 블록이다.
- 클로저는 클래스와 마찬가지로 참조 타입(reference type)이다.
{ (parameters) -> return type in
// 구현 코드
}
// 함수와 클로저 비교
func pay(user: String, amount: Int) {
// code
}
let payment = { (user: String, amount: Int) in
// code
}
func func1(_ param: String) -> String {
return param + "!"
}
func func2(name: String) -> String {
return name + "***"
}
// 함수를 변수에 할당가능(변수가 함수를 가르키게 됨)
var a: (String) -> String = func1
a("안녕")
a = func2
a("hello")
// 함수(클로저)를 변수에 할당해서
let closure1 = { (param: String) -> String in // 클로저 리터럴
return param + "!"
}
// 사용(실행)
closure1("스티브")
#2. Higher Order Function (고차함수) : map, filter, reduce
☑️ map 함수
- map 함수는 컬렉션 내부의 기존 데이터를 변형(transform)하여 새로운 컬렉션를 생성
- 기존의 컬렉션의 요소에 대해 정의한 익명함수로 매핑한 결과를 새로운 컬렉션으로 반환
// for 문으로 구현
let num = ["1", "2", "3", "4", "5"]
var numberArray: [Int] = []
for index in num {
if let changeToInt = Int(index) {
numberArray.append(changeToInt)
}
}
print(numberArray)
// [1, 2, 3, 4, 5]
// map으로 구현
let stringArray = ["1", "2", "3", "4", "5"]
numberArray = stringArray.map {
if let changeToInt = Int($0) {
return changeToInt
}
return 0
}
/*
$0와 $1
{ } 를 익명함수인 클로저라고 합니다.
클로저의 매개변수 이름이 필요하지 않은 경우 단축 인자 이름을 활용할 수 있습니다.($0, $1)
단축 인자이름은 순서대로 $0 , $1 , $2, $3 ...으로 표현합니다.
$0 은 첫번째 인자, $1은 두번째 인자를 뜻합니다.
*/
print(numberArray)
// [1, 2, 3, 4, 5]
☑️ filter 함수
- 기존 컨테이너의 요소 중 조건에 만족하는 값에 대해 새로운 컨테이너를 만들어 반환
// for 문으로 구현
// numbers에서 짝수만 추출하기
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var evenNumbers: [Int] = []
for number in numbers {
if number % 2 == 0 {
evenNumbers.append(number)
}
}
print(evenNumbers)
// [2, 4, 6, 8]
// filter로 구현
// numbers에서 짝수만 추출하기
let numbers1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let evenNumbers2 = numbers1.filter { $0 % 2 == 0 }
print(evenNumbers2)
// [2, 4, 6, 8]
☑️ reduce 함수
- 기존의 컨테이너의 요소에 대해 정의한 클로저로 매핑한 결과를 새로운 컨테이너로 반환
// for 문으로 구현
// 각 요소의 합 구하기
let numbers2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var sum = 0
for number in numbers2 {
sum += number
}
print(sum)
// 55
// reduce로 구현
// 표현식1
// 각 요소의 합 구하기
let numbers3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum1 = numbers3.reduce(0, +)
print(sum1)
// 55
//표현식2
// 각 요소의 합 구하기
let numbers4 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum2 = numbers4.reduce(0) { $0 + $1 }
print(sum2)
// 55
'iOS 앱 개발자 프로젝트 > Swift 문법 정복하기' 카테고리의 다른 글
[Swift] Closure, Higher Order Function (2) (0) | 2024.03.31 |
---|---|
[Swift] Struct vs. Class (2) | 2024.03.28 |
[Swift] Escaping closure (0) | 2024.03.15 |
[Swift] Thread, Asynchronous & Networking (1) | 2024.03.14 |
[Swift] Generic (0) | 2024.03.13 |