Suyeon9911 / TIL

매일 오전에 적는 미라클 TIL 🥣
10 stars 0 forks source link

[Swift] 함수 #76

Closed Suyeon9911 closed 1 year ago

Suyeon9911 commented 1 year ago

함수 = 메서드? 기본적으로 같지만 상황이나 위치에 따라 다른용어로 부르는 것 뿐이다.

구조체, 클래스, 열거형 등 특정 타입에 연관되어 사용하는 함수를 메서드., 모듈 전체에서 전역저으로 사용할 수 있는 함수를 그냥 함수라고 부른다.

매개변수와 전달인자

Suyeon9911 commented 1 year ago

매개변수

Parameter Name과 Argument Label

스위프트에서 기본적으로 사용하는 키워드는 매개변수 이름으로 사용할수 없다.하지만 ` backquote로 이름을 감싸주면 사용가능하다

func sayHello(from myName: String, to name: String) -> String {
    return "hello \(name)! I am \(myName)"
}

print(sayHello(from: "누구", to: "수연"))

함수 내부에서는 전달인자 레이블을 사용할수없고, 함수외부에서는 매개변수 이름을 사용할 수 없다. 와일드 카드 식별자를 사용하면 전달인자 레이블을 생략할수 있다.

func sayHello(_ myName: String, _ name: String) -> String {
    return "hello \(name)! I am \(myName)"
}

print(sayHello("누구","수연"))

전달인자 레이블을 변경하면 함수의 이름자체가 변경된다.

매개변수 기본값

가변매개변수와 입출력 매개변수

func sayHelloTofriends(me: String, friends names: String...) -> String {
    var result: String = ""

    for friend in names {
        result += "Hello \(friend)!"
    }

    return result
}

입출력 매개변수의 전달 순서

  1. 함수를 호출할때 전달인자의 값을 복사
  2. 해당 전달인자의 값을 변경하며 1에서 복사한 것을 함수 내부에서 변경
  3. 함수를 반환하는 시점에 2에서 변경된 값을 원래의 매개변수에 할당
var numbers: [Int] = [1,2,3]

func nonReferenceParameter(_ arr: [Int]) {
    var copiedArr: [Int] = arr
    copiedArr[1] = 1
}

func referenceParameter(_ arr: inout [Int]) {
    arr[1] = 1
}

nonReferenceParameter(numbers)
print(numbers[1]) // 2

referenceParameter(numbers)
print(numbers[1]) // 1
Suyeon9911 commented 1 year ago

반환이 없는 함수

함수는 특정 연산을 실행한 후 결과값을 반환 그러나 값의 반환이 굳이 필요하지 않은 함수도 있다.

데이터 타입으로서의 함수

func sayHello(name: String, times: Int) -> String {

}

-> 이 함수의 타입은 (String, Int) -> String !

typealias CalculateTwoInts = (Int, Int) -> Int

func addTwoInts(_ a: Int, _b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(_a: Int, _b: Int) -> Int {
    return a * b
}

var mathFunction: CalculateTwoInts = addTwoInts
print(mathFunction(2,5)) // 7

mathFunction = multiplyTwoInts
print(mathFunction(2,5)) // 10
func printMathResult(_ mathFunction: CalculateTwoInts, _ a: Int, _ b: Int ) {
    print("Result: \(mathFunction(a,b))")
}

func chooseMathFunction(_ toAdd: Bool) -> CalculateTwoInts {
    return toAdd ? addTwoInts : multiplyTwoInts
}

전달인자 레이블과 함수 타입

Suyeon9911 commented 1 year ago

중첩함수

typealias MoveFunc = (Int) -> Int

func goRight(_ currentPosition: Int) -> Int {
    return currentPosition + 1
}

func goLeft(_ currentPosition: Int) -> Int {
    return currentPosition - 1
}

func functionForMove(_ shouldGoLeft: Bool) -> MoveFunc {
    return shouldGoLeft ? goLeft : goRight
}

var positon: Int = 3

// 현 위치가 0보다 크므로 전달되는 인자값은 true
// goLeft 함수 할당

let moveToZero: MoveFunc = functionForMove(positon > 0)
// 원점으로 도착하면 반복문 종료

while position != 0 {
    position = moveToZero(position)
}

-기존에 우리가 함수를 구현하던 방식

typealias MoveFunc = (Int) -> Int

func functionForMove(_ shouldGoLeft: Bool) -> MoveFunc {

    func goRight(_ currentPosition: Int) -> Int {
        return currentPosition + 1
    }

    func goLeft(_ currentPosition: Int) -> Int {
        return currentPosition - 1
    }

    return shouldGoLeft ? goLeft : goRight
}

이런것들을 하나씩 공부할 수록, 생각을 하면서 코드를 짜는 방향을 배워가는듯 싶다. 역시 기본기가 중요한듯! 전역함수가 많은 큰 프로젝트에서는 전역으로 사용이 불필요한 함수의 사용범위를 조금 더 명확하고 깔끔하게 표현해줄 수 있다.! !

Suyeon9911 commented 1 year ago

종료되지 않는 함수

func crashAndBurn() -> Never {
    fatalError("Something very, very bad happened")
}

crashAndBurn() // 프로세스 종료 후 오류 보고

func someFunction(isAllIsWell: Bool) {
    guard isAllIsWell else {
        print("마을에 도둑이 들었습니다 !")
        crashAndBurn()
    }
    print("All is well")
}

someFunction(isAllIsWell: true) // All is well
someFunction(isAllIsWell: false) // 마을에 도둑이 들었습니다 !
// 프로세스 종료 후 오류 보고

Never 타입이 스위프트 표준 라이브러리에서 사용되는 대표적인 예로는 fatalError 함수가 있다.

Suyeon9911 commented 1 year ago

반환값을 무시할 수 있는 함수