[Swift 기초] 함수

2022. 3. 11. 15:28Swift 기초 정리

728x90

//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎

 

 

1. 함수 기초

  • 함수(function): 재사용을 목적으로 만드는 이름을 갖는 캡슐화된 코드 블록
    • 함수는 매개변수(prameter)를 받을 수 있고 값을 반환할 수도 있으나, 필요에 따라서는 그렇게 하지 않을 수도 있다.
    • 함수는 코드의 어디에도 선언될 수 있다.
//매개변수가 있고 리턴값이 있는 함수의 선언
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> 반환타입 {
	/*함수 구현*/
	return 반환값
}

//매개변수가 있고 리턴값이 없는 함수의 선언 - 반환타입(Void) 생략 가능
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> Void {
	/*함수 구현*/
	return //없어도 됨
}

func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) {
	/*함수 구현*/
}

//매개변수가 없고 리턴값이 있는 함수의 선언
func 함수이름() -> 반환타입 {
	/*함수 구현*/
}

//매개변수와 리턴값이 없는 함수의 선언
func 함수이름() -> Void {
	/*함수 구현*/
}

func 함수이름() {  /*함수 구현*/ }
  • 프로그램의 기본적인 구성요소 - 어떤 작업을 수행하는 문장의 그룹
  • 가독성의 증대, 유지관리가 쉽다.
  • C언어의 차이점은 C언어는 main()함수가 꼭 필요한데 swift는 그렇지 않다.
  • swift 함수는 튜플타입 리턴을 허용한다.

1-1. 함수의 호출

  • 함수 호출(function call): 함수를 사용하는 것, 그냥 호출하면 된다.
    • 함수를 호출하면 그 함수의 코드 블록에 있는 코드를 실행하며
    • 실행이 끝나면 제어가 복귀되어 프로그램의 함수 호출 다음에 있는 코드가 계속 실행
      func saySomething(){
      	print("Summer is so hot")
      }
      
      saySomething()    //함수의 코드는 그 함수가 호출되어야만 실행된다
    • func 키워드를 사용해서 함수 선언을 시작하고, 바로 다음에 함수의 이름을 지정
    • () 속이 빈 괄호, 함수에서 인자(argument)를 받는다면 괄호 안에 정의
    • {} 중괄호, 중괄호 안에 포함된 코드 블록은 함수가 호출될 때 실행

1-2. 함수의 인자

  • 함수에 정보를 전달하는 것 = 인자(argument) 또는 매개변수(parameter)를 전달하는 것
    • 인자나 매개변수는 함수에서 처리할 정보를 참조하며, 변수의 형태로 전달
  • 서로 다른 타입의 여러 인자들을 함수로 전달할 수 있기 때문에 함수를 선언할 때 미리 이름과 타입을 정의
    func saySeason(season: String){
    	print("It's \(season) time")
    }
    • 함수 내부에서 사용하기 위해 변수의 이름, 변수 타입을 정의
    • saySeason() 함수는 String 변수를 매개변수로 받으며, 함수 내부의 코드 블록에서 그것을 “season”으로 참조한다.
  • 매개변수가 2개 이상인 경우 반드시 전달인자 레이블을 붙여서 호출해야한다.
  • func greet(name: String, day: String) -> String{
        return "Hello \\(name), today is \\(day)"
    }
    
    print(greet(name: "정우", day: "미세먼지 없는 날"))
    //Hello 정우, today is 미세먼지 없는 날
    

1-3. 값을 반환하는 함수

  • 함수의 결과를 사용하고자 할 때는 반환 값(return value)를 갖는 함수를 생성해야 한다.
  • 함수의 반환 값: 함수의 코드 블록에서 처리한 결과 값
func randomInt(min: Int, max: Int) -> Int{
    return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}
  • -> 반환할 값의 데이터 타입 함수에서 값을 반환한다는 것을 의미
  • return 처리된 결과가 함수의 반환 값이라는 것을 알려줌
  • 데이터를 함수에 전달하여 함수가 그것을 처리한 후 결과를 반환하는 매커니즘은 굉장히 강력하고 중요하다.

1-4. 다중 반환값

  • 튜플을 사용하면 여러개의 값을 한꺼번에 리턴할 수 있다.
  • func getPersonInfo() -> (Int, String, Int){
        return (25, "김정우", 183)
    }
    
    print(getPersonInfo())
    //(25, "김정우", 183)
  • swap함수 - 튜플 재조합
    func swap(p1: String, p2: String) -> (String, String){
        return (p2, p1)
    }
    
    var n1 = "잘생긴"
    var n2 = "정우"
    print("before swap: n1 = \(n1), n2 = \(n2)")
    
    (n1, n2) = swap(p1: n1, p2: n2)
    print("after swap: n1 = \(n1), n2 = \(n2)")
    
    //before swap: n1 = 잘생긴, n2 = 정우
    //after swap: n1 = 정우, n2 = 잘생긴
    
    //swift에서는 별도로 swap을 정의하지 않아도 충분히 swap할 수 있다.
    (n1, n2) = (n2, n1)

1-5. 함수 중복 정의

  • 함수명이 같아도 매개변수가 다르면 중복해서 정의할 수 있다.
  • func getPersonInfo() -> (Int, String, Int){
        return (25, "김정우", 183)
    }
    
    func getPersonInfo(name: String){
        print(name)
    }
    
    getPersonInfo()  //(25, "김정우", 183)
    getPersonInfo(name: "김정우")  //김정우
  • 함수명이 같을 때 리턴값만 다르면 중복해서 정의할 수 없다.
    • Ambiguous use of '함수명’
    func getPersonInfo() -> (Int, String, Int){
        return (25, "김정우", 183)
    }
    
    func getPersonInfo() -> (Int, String){
        return (25, "김정우")
    }
    
    getPersonInfo()  //Ambiguous use of 'getPersonInfo()'
    

 

2. 함수 고급

2-1. 기본값을 갖는 매개변수

  • 기본값을 갖는 매개변수는 매개변수 목록 중에 뒤쪽에 위치하는 것이 좋다.
  • 매개변수 기본값을 가지는 매개변수는 생략할 수 있다.

2-2. 개수가 정해지지 않은 매개변수 함수: 가변 매개변수, 가변인자 함수

  • 매개변수에 ...을 사용하면 개수가 정해지지 않은 파라미터를 받을 수 있다.
  • func sum(_ numbers: Int...) -> Int{
        var sum = 0
        for number in numbers{
            sum += number
        }
        return sum
    }
    print(sum(1,2,3))  //6
    print(sum(1,2,3,4,5))  //15

2-3. 함수타입 상수, 변수

  • 함수타입(형)의 상수나 변수를 만들어 함수를 할당(assign)할 수 있다.
  • 함수타입(형) 변수에 레이블을 사용할 경우 error
    • Extraneous argument labels 'a:b:' in call
    func addTwoInts(a: Int, b: Int) -> Int{
        return a + b
    }
    
    //이 변수가 addTwoInts 함수를 참조하고 있다.
    var mathFunction: (Int, Int) -> Int 
    mathFunction = addTwoInts
    
    //mathFunction(a:2, b:3)     //Extraneous argument labels 'a:b:' in call
    print(mathFunction(2, 3))    //5
  • 함수형을 매개변수로 사용할 수 있다.
    func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int){
        print("Result: \(mathFunction(a, b))")
    }
    printMathResult(mathFunction: addTwoInts, a: 3, b: 5)
    //Result: 8

2-4. 함수의 반환

  • → (Int) → Int
  • 리턴타입이 (타입형)을 매개변수로 받아서 타입형을 리턴하는 함수
  • func stepForward(input: Int) -> Int{
        return input + 1
    }
    func stepBackward(input: Int) -> Int{
        return input - 1
    }
    func chooseStepFunction(backwards: Bool) -> (Int) -> Int{
        return backwards ? stepBackward : stepForward
    }
    print(chooseStepFunction(backwards: true)(10)) //9
    print(chooseStepFunction(backwards: false)(10)) //11

2-5. 함수안에 함수: 중첩함수

  • 중첩 함수(nested function): 다른 함수의 코드 블록 내부에 선언된 함수
    • 부모 함수에 국한되어 사용될 캡슐화된 코드를 갖는 함수
    • 부모 함수 내부에 선언
    • 내부 함수가 리턴할 수 있다.
    •  

 

3. 함수안에 함수: 중첩함수

  • 중첩 함수(nested function): 다른 함수의 코드 블록 내부에 선언된 함수
    • 외부 함수에 국한되어 사용될 캡슐화된 코드를 갖는 함수(외부 함수 내부에 선언)
    • 내부의 중첩된 함수는 외부함수에 선언된 변수를 사용할 수 있다.
    • 내부 함수가 리턴할 수 있다.
func chooseStepFunction(backwards: Bool) -> (Int) -> Int{
    func stepForward(input: Int) -> Int{
        return input + 1}
    func stepBackward(input : Int) -> Int{
        return input - 1}
    return backwards ? stepBackward: stepForward
}
print(chooseStepFunction(backwards: true)(10))  //9
print(chooseStepFunction(backwards: false)(10))  //11
  • 중첩함수의 호출은 함수 내부에서만 가능하므로 내부적으로 은닉이 가능하다는 장점이 있다.
  • 함수는 매개변수로 사용될 수 있고 리턴타입으로 사용할 수 있다.

3-1. 변수/상수의 범위와 함수

  • 변수의 범위(scope): 프로그램의 어떤 부분에서 변수르 사용할 수 있는지를 나타낸다.
  • 전역(global) 범위: 프로그램 어디서든 사용 가능하다. 모든 함수의 외부에 선언
    var height = 1000
    let width = 10.55
    
    func myFunc() -> Double{
        return Double(height) + width
    }
    
    myFunc()        //1010.55
    print(height)    //1000
    • 변수 score, 상수 width를 함수 내부와 외부 어디서든 사용할 수 있다.
  • 지역(local) 범위: 지역 범위를 갖는 변수는 선언된 함수 내부에서만 엑세스할 수 있다.
    var height = 1000
    let width = 10.55
    
    func myFunc(row: Double) -> Double{
    		var column = 10.0    //지역변수 선언
        return Double(height) + width + column + row
    }
    
    print(row)       //Cannot find 'row' in scope
    print(height)    //Cannot find 'height' in scope
    • 함수 내부에서 ‘height’ 변수를 생성했으므로 변수가 존재한다는 것을 알지만, 프로그램에서는 해당 변수를 액세스할 수 없다.
    • 함수의 인자는 지역범위를 갖는다.

3-2. 외부함수와 내부함수

  • 내부함수는 외부함수의 값을 읽어(캡쳐) 처리할 수 있다.
  • 내부함수는 외부함수가 실행되는 순간 생성되고 종료되는 순간 소멸된다.
//funcA: 외부함수, funcB: 내부함수
func funcA() -> Int{
    var a = 10
    //중첩함수 funcB()는 외부함수 funcA()의 내부 변수 a를 읽고 수정할 수 있다.
    func funcB(){  
        a = a + 10
    }
    funcB()
    return a
}

print(funcA())  //20
print(funcA())  //20

3-2. 중첩함수 리턴, 중첩함수 변수의 참조 캡쳐

  • 중첩함수를 반환하여 이 함수를 함수 외부에서 사용할 수 있다.
  • -> ((Int) -> Int)
  • //makeInc1()함수는 addOne함수를 리턴
    func makeInc1() -> ((Int) -> Int){
        func addOne(number: Int) -> Int{
            return number + 1
        }
        return addOne
    }
    //반환된 값을 참조할 수 있는 변수
    var increment = makeInc1()
    print(increment(7))  //8
    print(increment(7))  //8
  • -> () -> Int
  • func makeInc2(amount: Int) -> () -> Int{
        var runningTotal = 10
        func incrementor() -> Int{
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
    
    //호출할 때 마다 누적해서 증가: 내부함수(runningTotal)가 어딘가에 캡쳐되어 있다.
    //runningTotal 변수를 바깥 함수로부터 참조캡쳐하였기 때문
    var incFive = makeInc2(amount: 5)
    print(incFive())  //15
    print(incFive())  //20
    
    //incFive와 incTen가 참조하고 있는 runningTotal은 서로 다른 메모리공간에서 참조(캡처)되어 있다.
    var incTen = makeInc2(10)
    print(incTen())  //20
    print(incTen())   //30
  • 내부함수 Incrementor()는 외부함수 makeInc2()가 호출될 때 생성되어 외부함수의 호출이 종료되면 소멸
  • incFive, incTen이라는 외부참조변수가 incrementor()를 참조하여 생명이 유지되는 것을 확인할 수 있다.(위의 두 예제의 결과가 다른 이유)
  • 외부에서 참조하는 변수나 상수가 있을 경우 내부함수는 참조되어 생명이 유지된다.

 

 

참고하였습니다. 감사합니다.

https://yagom.net/courses/swift-basic/lessons/함수/

 

스위프트 기초 - 야곰닷넷

스위프트는 문법표현의 다양성이 매우 높은 언어입니다. 그래서 스위프트 문법의 모든 형태를 알기는 꽤 오랜 시간이 걸립니다. 그렇지만 최소한의 핵심 문법을 통해 무리없이 스위프트 문법을

yagom.net

https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1891?tab=curriculum 

 

학습 페이지

 

www.inflearn.com

https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1894?tab=note 

 

학습 페이지

 

www.inflearn.com

23.07.06 수정) Swift 쉽게, 더 쉽게

https://www.yes24.com/Product/Goods/17652267

728x90