본문 바로가기
YAGOM CAREER STARTER

[TIL] 20221223: Magic literal/number, Tuple, Recursive Function

by Rhode 2022. 12. 24.

본문은 야곰 아카데미 커리어 스타터 캠프를 통해 학습한 내용을 회고한 글입니다.

 


매직 리터럴/넘버 Magic literal/number

Magic literal/number는 의미를 가진 문자나 숫자를 코드에서 그대로 표현한 것을 말한다. 이러한 표현은 코드를 읽기 어렵게 만든다. 이 코드를 짠 나는 알 수 있지만, 다른 사람들은 해당 문자열, 숫자가 무엇을 의미하는지 확신할 수 없기 때문이다. 가능하면, 문자나 숫자를 변수/상수로 선언하여 주고 그것을 사용해주는 것이 좋다. 

print("안녕하세요.")
print("Rhode입니다.")
print("당신의 이름을 입력해주세요 : ", terminator: "")

위의 코드는 매직 리터럴 투성이다. 이것을 다음의 코드로 바꿀 수 있다.

let greetingMessage = """
                     안녕하세요.
                     Rhode입니다.
                     당신의 이름을 입력해주세요 :
                     """
                   
print(greetingMessage, terminator: " ")

매직 넘버도 마찬가지이다. 웬만하면 숫자가 무엇을 의미하는지 알 수 있게 상수나 변수를 통해 선언해주고 그것을 사용하자. 

 

튜플 Tuple

다음의 함수를 만들면서 반환값으로 딕셔너리를 사용했다. 아얀이 튜플을 활용해보라고 하셔서 튜플에 대해서 공부를 해봤다. 

func countBallAndStrike(from computerRandomNumbers: [Int], comparing userNumbers: [Int]) -> [String: Int] {
    var result = [String: Int]()
    result["strike"] = 0
    result["ball"] = 0

    for index in 0...2 {
        if computerRandomNumbers[index] == userNumbers[index] {
            result["strike"]? += 1
        } else if userNumbers.contains(computerRandomNumbers[index]) {
            result["ball"]? += 1
        }
    }

    return result
}

 

 

튜플은 파이썬에 있는 튜플과 유사한 타입이다. 소괄호(())안에 일정 타입들을 나열하여 튜플을 선언한다. 그리고 튜플은 인덱스를 통해 값을 출력하거나 할당할 수 있다. 

var Person : (String, Int, Double) = ("Rhode", 27, 157.3)

print("이름 : \(Person.0), 나이 : \(Person.1), 키 : \(Person.2)")  //이름 : Rhode, 나이 : 27, 키 : 157.3

Person.0 = "YJChoi"
Person.1 = 25
Person.2 = 185.3

print("이름 : \(Person.0), 나이 : \(Person.1), 키 : \(Person.2)")  //이름 : YJChoi, 나이 : 25, 키 : 185.3

 

 

튜플에는 이름을 붙여줄 수도 있다. 이름을 붙여주면 인덱스 대신 이름으로 값을 출력하거나 할당할 수도 있다.

var Person : (name: String, age: Int, height: Double) = ("Rhode", 27, 157.3)

print("이름 : \(Person.name), 나이 : \(Person.age), 키 : \(Person.height)")  //이름 : Rhode, 나이 : 27, 키 : 157.3

Person.name = "YJChoi"
Person.age = 25
Person.height = 185.3

print("이름 : \(Person.name), 나이 : \(Person.age), 키 : \(Person.height)")  //이름 : YJChoi, 나이 : 25, 키 : 185.3

 

매번 같은 모양의 튜플을 사용하고 싶다면, 타입 별칭을 이용할 수도 있다. 선언할 때마다 긴 튜플 타입을 모두 써줄 필요가 없는 것이다.

typealias PersonTuple = (name: String, age: Int, height: Double)

let Rhode: PersonTuple = ("Rhode", 27, 157.3)
let YJChoi: PersonTuple = ("YJChoi", 25, 185.3)

print("이름: \(Rhode.name), 나이: \(Rhode.age), 신장: \(Rhode.height)")  //이름: Rhode, 나이: 27, 신장: 157.3
print("이름: \(YJChoi.name), 나이: \(YJChoi.age), 신장: \(YJChoi.height)")  //이름: YJChoi, 나이: 25, 신장: 185.3

 

그래서, 튜플을 활용하여 코드를 짜면 다음과 같을 것이다. 

func countBallAndStrike(from computerRandomNumbers: [Int], comparing userNumbers: [Int]) -> (Int, Int) {
    var result: (strike: Int, ball: Int) = (0, 0)

    for index in 0...2 {
        if computerRandomNumbers[index] == userNumbers[index] {
            result.strike += 1
        } else if userNumbers.contains(computerRandomNumbers[index]) {
            result.ball += 1
        }
    }

    return result
}

임의로 숫자를 넣어서 프린트 해봤다. 튜플을 사용한다면, 이런 형태로 반환이 될 것이다. 그렇다면, 튜플을 사용하는 것의 장점은 무엇일까? 결과값을 바인딩할 필요가 없어진다. 엊그제 공부했다싶이 딕셔너리의 value는 옵셔널이다. 그래서 다른 함수에서 strike와 ball의 결과를 사용하면서 바인딩을 해주었다.

if let strikeCount = ballAndStrikeCount["strike"], let ballCount = ballAndStrikeCount["ball"] {
            print("\(strikeCount) 스트라이크, \(ballCount) 볼")
        }

그런데, 이런 과정이 필요 없게 되는것이다. 그러니 코드가 보다 간결해질 수 있다는 장점이 있겠다. 

 

 

재귀함수 Recursive Function

재귀함수는 자기자신 안에서 자기자신을 호출하는 함수이다. 변수와 코드 길이를 줄일 수 있어 가독성이 있다는 강점이 있다. 그러나, 자칫 잘못 사용한다면 무한재귀를 통해 스택오버플로우를 일으킬 수 있다는 단점이 있다. 재귀함수와 비교되는 것이 바로 반복문이다. 반복문은 재귀함수보다 속도가 빠르고 성능이 좋다. 하지만, 코드가 더 지저분하고 복잡하다는 단점이 있다. 재귀함수의 단점을 반복문을 통해 보완한 것이 바로 꼬리재귀이다. (더 공부할 것)

 

 

참조

http://www.yes24.com/Product/Goods/78907450

 

스위프트 프로그래밍 - YES24

문법을 넘어 프로그래밍 패러다임도 익히는 스위프트 5스위프트 5의 핵심 키워드는 ‘안정화’다. ABI 안정화 덕분에 버전과 환경에 크게 영향받지 않고 더 유연하게 스위프트를 사용할 수 있게

www.yes24.com