Swift의 함수, 메서드, 클로저 개요

5 분 소요

스위프트 함수 선언

 
func <함수명> (<매개변수 이름>: <매개변수 타입>,
             <매개변수 이름>: <매개변수 타입>, ... ) -> <반환 결과 타입> {
    // 함수 코드
}

  • 함수 시그니처(function signature) - 함수명, 매개변수, 반환 결과 타입의 조합
  • func - 이것이 함수임을 컴파일러에게 알려주기 위해 사용되는 키워드
  • <함수명> - 함수에 할당되는 이름, 애플리케이션 코드 내에서 함수를 호출할 때 참조되는 이름
  • <매개변수 이름> - 함수 코드 내에서 참조할 매개변수의 이름
  • <매개변수 타입> - 해당 매개변수의 타입
  • <반환 결과 타입> - 함수가 반환하는 결과의 데이터 타입, 만일 함수가 결과를 반환하지 않는다면 반환 결과 타입을 지정하지 않음(Void)
  • 함수 코드 - 작업을 수행하는 함수의 코드
func sayHello() {
    print("Hello")
}

매개변수x 반환결과x 메시지 표시

func buildMessageFor(name: String, count: Int) -> String {
    return "\(name), you are customer number \(count)"
}

매개변수: 문자열, 정수 반환결과타입: 문자열

매개변수와 인자 혼용

매개변수(parameter): 함수가 호출될 때 받게 되는 값
인자(argument): 실제로 함수가 호출되고 값이 전돨된 시점에서는 매개변수x -> 인자

함수와 메서드

메서드: 특정 클래스나 구조체 또는 열거형과 연관된 함수
Ex) 스위프트 클래스 내에서 함수를 선언했다면 이것은 메서드로 간주


단일 표현식에서의 암묵적 반환

함수가 단일 표현식 을 가지고 있다면 return 구문을 생략가능

func buildMessageFor(name: String, count: Int) -> String {
    "\(name), you are customer number \(count)"
}

하나 이상의 표현식을 가지고 있다면 컴파일 에러 발생

func buildMessageFor(name: String, count: Int) -> String {
    let uppername = name.uppercased()
    "\(name), you are customer number \(count)" // 컴파일 에러
}

스위프트 함수 호출


<함수명> (<인자1>, <인자2> ...)

함수를 통해 전달되는 각각의 인자는 함수가 받도록 구성된 매개변수와 일치

sayHello()

매개변수x 반환결과x


반환값 처리하기

let message = buildMessageFor(name: "John", count: 100)

매개변수: 문자열, 정수 반환결과타입: 문자열

반환된 결괏값을 사용하지 않는 경우

_ = buildMessageFor(name: "John", count: 100) // 결괏값을 버림

지역 매개변수명과 외부 매개변수명

지역 매개변수명(local parameter name, 매개변수명(parameter name)): 함수 코드 내에서 참조할 수 있는 이름을 할당한 매개변수
외부 매개변수명(external parameter name, 인자명(argument label)): 함수가 호출될 때 참조되는 매개변수

기본적으로, 함수 매개변수에는 동일한 지역 매개변수명과 외부 매개변수명이 할당

let message = buildMessageFor(name: "John", count: 100)

지역 매개변수명: name, count, 외부 매개변수명: name, count

매개변수에 할당된 디폴트 외부 매개변수명은 삭제 가능(_)

func buildMessageFor(_ name: String, _ count: Int) -> String {
    return "\(name), you are customer number \(count)"
}
 
let message = buildMessageFor("John", 100)

지역 매개변수명: name, count, 외부 매개변수명: x

외부 매개변수명 추가

func buildMessageFor(userName name: String, userCount count: Int) -> String {
    return "\(name), you are customer number \(count)"
}
 
let message = buildMessageFor(userName: "John", userCount: 100)

지역 매개변수명: name, count, 외부 매개변수명: userName, userCount


함수에 디폴트 매개변수 선언하기

인자로 쓸 값이 들어오지 않은 경우, 사용할 디폴트 매개변수 값을 지정

func buildMessageFor(_ name: String = "Customer", count: Int) -> String {
    return "\(name), you are customer number \(count)"
}

let message = buildMessageFor(count: 100) //name 인자는 전달x
print(message)

출력
Customer, you are customer number 100


여러 결괏값 반환하기

튜플로 래핑하면 여러 개의 결괏값을 반환가능

func sizeConverter(_ length: Float) -> (yards: Float, centimeters: Float, meters: Float) {
    let yards = length * 0.0277778
    let centimeters = length * 2.54
    let meters = length * 0.0254
     
    return (yards, centimeters, meters)
}
let lengthTuple = sizeConverter(20) // 튜플 인스턴스 생성

print(lengthTuple.yards)
print(lengthTuple.centimeters)
print(lengthTuple.meters)

가변개수 매개변수

함수가 받게 될 매개변수가 몇 개인지 알 수 없는 경우: 가변개수 매개변수(variadic parameter) 를 사용

func displayStrings(_ strings: String...){ // 0개 이상
    for string in strings { // 배열 개체의 형태로 사용
        print(string)
    }
}

displayStrings("one", "two", "three", "fout")

변수인 매개변수

함수가 받는 모든 매개변수는 기본적으로 상수 로 취급 - 변경x
함수 내에서 매개변수의 값을 변경하기 위해서 섀도 복사본(shadow copy) 생성

func calcuateArea(length: Float, width: Float) -> Float {
     
    var length = length // shadow copy
    var width = width // shadow copy
     
    length = length * 2.54
    width = width * 2.54
    return length * width
}

print(calcuateArea(length: 10, width: 20))

입출력 매개변수로 작업하기

섀도 복사본은 변경하더라도 원본 변수에 반영되지 않는다!

var myValue = 10

func doubleValue(_ value: Int) -> Int {
    var value = value
    value += value
    return value
}

print("Before function call myValue = \(myValue)")
print("doubleValue call returns \(doubleValue(myValue))")
print("After function call myValue = \(myValue)")

출력

Before function call myValue = 10
doubleValue call returns 20
After function call myValue = 10

myValue 변수가 변경되지 않음

함수가 값을 반환한 뒤에도 매개변수에 대한 변경을 유지하기 위해선,
함수 선언부 내에서 매개변수를 입출력 매개변수(in-out parameter)로 선언

func doubleValue(_ value: inout Int) -> Int {
     //var value = value 섀도우 복사본x
     value += value
     return value
}
.
.
.
print("doubleValue call returns \(doubleValue(&myValue))") // 함수 호출 시 '&'

출력

Before function call myValue = 10
doubleValue call returns 20
After function call myValue = 20

매개변수인 함수

함수를 데이터 타입처럼 취급

  • 함수를 상수나 변수에 할당
     func inchestoFeet (_ inches: Float) -> Float {
          return inches * 0.0833333
      }
     let toFeet = inchestoFeet
    
     let result = toFeet(10) // 상수 이름을 이용하여 함수 호출
    

    toFeet의 데이터 타입은 (Float) -> Float

  • 함수를 매개변수로 사용
     func inchestoFeet(_ inches: Float) -> Float {
         return inches * 0.0833333
     }
     func inchesToYards(_ inches: Float) -> Float {
         return inches * 0.0277778
     }
     let toFeet = inchestoFeet // 상수 할당, 데이터 타입은 동일
     let toYards = inchesToYards // 상수 할당, 데이터 타입은 동일
    
     func outputConversion(_ converterFunc: (Float) -> Float, value: Float) {
         let result = converterFunc(value)
         print("Result of conversion is \(result)")
     }
    
     outputConversion(toYards, value: 10) // 야드로 변환하기
     outputConversion(toFeet, value: 10) // 피트로 변환하기
    
  • 함수를 데이터 타입으로 반환
     func decideFunction(_ feet: Bool) -> (Float) -> Float {
         if feet {
             return toFeet
         } else {
             return toYards
         }
     }
    

클로저 표현식

클로저 표현식(closure expression): 독릭적인 코드블록

let sayHello = { print("Hello") }
sayHello()

클로저 표현식을 선언 후 sayHello 상수로 할당

매개변수를 받아 결괏값을 반환


{(<매개변수 이름>: <매개변수 타입>, <매개변수 이름>: <매개변수 타입>, ...) 
   -> <반환 타입> in
    // 클로저 표현식 코드
}

let multiply = {(_ val1: Int, _ val2: Int) -> Int in
    return val1 * val2
}
let result = multiply(10, 20)

매개변수: 두 개의 정수, 반환: 하나의 정수
함수 선언과 비슷
이름을 갖지 않음
매개변수와 반환 타입은 괄호 안에 포함
코드의 시작을 가리키는 in 키워드 사용
매개변수, 반환값 타입 생략 가능 {(_ val1, _ val2) in


스위프트의 클로저

컴퓨터 공학 용어에서의 클로저(closure): 독릭접인 코드 블록과 코드 블록 주변에 있는 하나 이상의 변수가
결합된 것 = 함수, 클로저 표현식

func function() -> () -> Int {
    var counter = 0
    
    func functionB() -> Int {
        return count + 10
    }
    return functionB
}
 
let myClosure = functionA()
let result = myClosure()

functionB는 functionB의 내부 영역 밖에 선언된 counter 변수에 의존
-> functionA는 클로저를 반환
functionB는 counter 변수를 잡고있다(captured), 또는 가두고 있다(closed over)
-> 클로저로 간주