ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] Swift 문법 (4) - Function(함수)
    Front-End(Mobile)/iOS & Swift 2022. 1. 22. 01:42
    반응형

    이번 포스팅은 Swift의 함수에 대해 알아보도록 하겠다.

     

    함수 개념 자체는 모든 프로그래밍 언어에서 자주 사용되기에 생소하지 않을 것이다.

    특정 인자(매개변수)를 받아 내부에 설정된 로직을 수행하여, 결과(반환값)를 산출하기 때문에 반복적인 로직을 기능화하는데 주로 사용되는 문법이다.

     

    함수의 문법도 크게 상이하지 않고, 그 개념도 프로그래밍 언어 범주에 많이 중첩되기 때문에 어렵지 않게 이해할 수 있으리라!


    📙 Function(함수) 란?

    Swift 공식문서에서 함수는 "특정 임무를 수행하는 독립된 코드 조각" 이라고 정의한다.

    함수는 고유 이름을 가지며 매개변수(Parameter)라고 하는 특정값들을 받아, 일정한 로직으로 값을 반환하는 역할을 수행한다.

     

    Swift 역시 함수형 프로그래밍 작성을 위한 함수 문법을 지원하며, 이것에 대해 알아보도록 하자!

     

    - Function(함수) 정의 및 호출

    /*
    func [함수명]([변수1]: [변수1 타입], [변수2]: [변수2 타입]...) -> [반환타입] {
      [연산내용]
    }
    */
    
    func addNums(a: Int, b: Int) -> Int {
      return a + b
    }

    정의는 위 예시와 같다. 가장 기본적인 형태로, 먼저 func 키워드를 통해 함수를 선언할 수 있다.

    괄호 안에는 매개변수 및 이들의 타입을, 화살표(->) 다음에는 반환값의 타입과 내부에 세부적인 연산내용을 작성한다.

    함수가 반환하는 구문을 return [반환값] 형태로 적어주면 된다.

     

    혹은, 아래 예시처럼 매개변수 혹은 반환값이 없는 경우가 있다.

    //매개변수가 없는 경우
    func 함수이름() -> 반환타입 {
        /* 함수 구현부 */
        return 반환값
    }
    //반환값이 없는 경우
    func 함수이름() -> void{
        /* 함수 구현부 */
    }
    
    // or
    
    func 함수이름(string: String) {
        print("\(string)")
    }

     

    함수의 사용 및 호출은 아래 예시와 같다. Swift는 독특하게 함수 호출할 때 매개변수의 이름을 같이 써주어야 한다.

    var x = 3
    var y = 7
    let sum = addNums(a: x, b: y)
    
    print(sum)		// 10

     

    함수의 선언 / 호출 시의 매개변수 명을 각각 다르게 하거나, 호출 시 매개변수 명 입력을 생략하기도, 기본값을 지정할수도 있다.

    // 선언 및 호출시 다른 매개변수
    func hello(to name: String, at time: Int) {
      print("Hi, \(name) at \(time)")
    }
    
    hello(to: "TaeHyung", at: 3)

     

    // 매개변수 생략
    func no(_ name: String) {
      // ...
    }
    
    hello("TaeHyung")

     

    // 매개변수 기본값
    func no(name: String = "TaeHyung") {
      // ...
    }
    
    hello()

     

     

     

    📙 Closure(클로저) 란?

     

    - 함수 안의 함수

    Swift 역시 함수 안에서 함수를 작성할수도, 심지어 내부에 정의된 함수를 반환할 수도 있다.

    // 함수 안의 함수
    func hello(name: String, time: Int) {	// 외부 함수
      func msg(name: String) -> String {	// 내부 함수
        return "\(name)님, 안녕하세요."
      }
      
      for _ in 0..<time {
        print(msg(name: name))
      }
    }
    
    hello(name: "TaeHyung", time: 3)
    
    // TaeHyung님, 안녕하세요.
    // TaeHyung님, 안녕하세요.
    // TaeHyung님, 안녕하세요.

     

    // 내부에 정의된 함수(hello)를 반환
    func helloGenerator(msg: String) -> (String) -> String {
      func hello(name: String) -> String {
        return name + msg
      }
      
      return hello
    }
    
    let hello = helloGenerator(msg: "님, 안녕하세요!")
    print(hello("TaeHyung"))	// TaeHyung님, 안녕하세요!

    * 특히, 여기서 함수를 반환하는 외부함수는 아래와 같은 포멧으로 작성된 것이다.

    func [함수명]([매개변수]: [매개변수타입]) -> ([내부함수 매개변수타입]) -> [반환타입] {
      // 함수 내용...
    }

     

     

    - Closure (클로저)

    본격적으로 Closure에 대해 알아보자.

    클로저는 코드 안에서 전달되어 사용할 수 있는 로직을 가진 중괄호({})로 구분된 코드의 블럭이며, 일급 객체이다.

    * 일급 객체는 변수/상수에 저장할 수 있고, 함수의 매개변수 혹은 반환값이 될 수 있는 객체를 의미한다.

     

    함수의 중괄호문 역시 일종의 클로저이며, 함수명에 할당된 "이름이 있는 클로저" 라고 일컫는다. 클로저는 통상 아래와 같이 작성한다.

    { ([매개변수]: [매개변수 타입]) -> [반환타입] in
      return // 함수 로직...
    }

     

    클로저를 사용하는 이유는 크게 두 가지일 것이다. 1) 함수 안의 함수로직을 작성하고, 2) 이를 좀 더 간결하고 유연하게 표현하기 위함이다.

    아래는 내부함수로 작성된 클로저가 축약되는 과정을 표현한 예시이다.

    func helloGenerator(message: String) -> (String, String) -> String {
      return { (firstName: String, lastName: String) -> String in
        return lastName + firstName + message
      }
    }

     

    먼저, 클로저는 Swift 컴파일러의 타입 추론 덕분에, 외부함수에 작성된 내부함수 매개변수 타입, 반환타입을 기반으로 타입을 추론한다.

    그렇기에, 아래와 같이 클로저 내의 타입핑을 생략할 수 있다.

    func helloGenerator(message: String) -> (String, String) -> String {
      return { firstName, lastName in
        return lastName + firstName + message
      }
    }

     

    다음으로, 각각의 매개변수를 $[인덱스]로 치환할 수 있다. $0이 첫 번째 매개변수, $1가 두 번째 매개변수 순으로 되는 것이다.

    func helloGenerator(message: String) -> (String, String) -> String {
      return {
        return $1 + $0 + message
      }
    }

     

    마지막으로, 클로저 내부의 코드가 한 줄이라면 return 도 생략할 수 있다.

    func helloGenerator(message: String) -> (String, String) -> String {
      return { $1 + $0 + message }
    }

     

    - Closure 활용하기

    심플한 함수를 매개변수로 사용하는 곳에서 Closure(클로저)가 유용하게 활용된다. 대표적인 예로, 배열(Array) 메서드들이 있다.

    let arr = [1, 3, 6, 2, 7, 9]
    
    let arr1 = arr.sort { $0 < $1 }
    // [1, 2, 3, 6, 7, 9]
    
    let arr2 = arr.filter { $0 % 2 === 0 }
    // [6, 2]
    
    let arr3 = arr.map { $0 * 2 }
    // [2, 6, 12, 4, 14, 18]
    
    let arr4 = arr.reduce(0) { $0 + $1 }
    // 28, reduce() 내 값은 초기값이다!

    함수 자체의 개념은 어려운 부분이 없었으나, 클로저가 매우 간결하면서도 작성하는 방법이 꽤나 생소하다는 느낌을 많이 받았다.

    배열 메서드 등 많은 활용을 통해 클로저 문법에 좀 더 익숙해져야 할 필요성을 느꼈다!

     

    다음 포스팅 역시 프로그래밍 언어에서 자주 등장하는, 조건문과 반복문이 될 것 같다.

     

    📎 출처

    - [Swift5 강의] iOS Academy(Part 4 - Functions & Parameters) : https://www.youtube.com/watch?v=fffG55Ei1Qc&list=PL5PR3UyfTWvfacnfUsvNcxIiKIgidNRoW&index=4 

     

    - [함수] 프린스송 님의 블로그 : https://velog.io/@wook4506/iOS-Swift-Swift-%EB%AC%B8%EB%B2%95%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-5%ED%8E%B8-%ED%95%A8%EC%88%98Function  

    - [함수] yagom 님의 블로그 : https://blog.yagom.net/528/  

    - [함수] xho95 님의 블로그 : https://xho95.github.io/swift/language/grammar/function/2020/06/02/Functions.html

    - [함수와 클로저] devxoul 님의 깃북 : https://devxoul.gitbooks.io/ios-with-swift-in-40-hours/content/Chapter-3/functions-and-closures.html  

    - [클로거] jgj455 님의 블로그 : https://medium.com/@jgj455/%EC%98%A4%EB%8A%98%EC%9D%98-swift-%EC%83%81%EC%8B%9D-closure-aa401f76b7ce

    반응형
Designed by Tistory.