ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chapter 3: Basic Control Flow
    Raywenderlich/Swift Apprentice 2021. 6. 16. 15:01

    Version

    Swift 5.5, iOS 15, Xcode 13

     

    컴퓨터 프로그램(computer program)을 작성(writing)할 때, 다른 시나리오(scenarios)에서 수행할 작업을 컴퓨터에 알려야 할 필요가 있다. 예를 들어(for example), 계산기 앱(calculator app)에서 사용자(user)가 더하기(addition) 버튼(button)과 빼기(subtraction) 버튼(button)을 탭(taps)할 때 다른 작업을 수행해야 한다.

    컴퓨터 프로그래밍(computer-programming) 용어(terms)에서 이 개념(concept)은 제어 흐름(control flow)으로 알려져 있는데, 프로그램(program)의 흐름(flow)이 다양한(various) 방법(methods)으로 제어(controlled)되기 때문이다. 이 장(chapter)에서는 구문(syntax)을 사용하여 흐름(flow)을 제어(control)함으로써, 프로그램(programs)에서 의사 결정(decisions)을 내리고 작업을 반복(repeat)하는 방법을 배운다. 또한 참(true)과 거짓(false)을 나타내는(represent) 부울(Booleans)과 이를 사용하여 데이터를 비교(compare)하는 방법에 대해서도 알아 본다.

     

    Comparison operators

    지금까지 Int, Double, String과 같은 몇 가지 유형(types)을 살펴 보았다. 여기서는 비교 연산자(comparison operators)를 사용해 값(values)을 비교(compare)할 수 있는 또 다른 유형(type)에 대해 알아본다.

    둘 이상의 숫자 중 큰 것을 찾는 경우와 같이, 비교(comparison)를 수행(perform)할 때의 답은 참(true) 또는 거짓(false)이다. Swift에는 이를 위한 데이터 유형(type)이 있다. Bool이라 하는데 Boolean의 줄임말(short)로, 이는 참(true)과 거짓(false)이라는 개념(concept)을 중심으로 수학(mathematics)의 전체 분야(entire field)를 나타낸(invented) George Boole이라는 영리한(clever) 수학자의 이름에서 유래(after)했다.

    Swift에서 부울(Boolean)을 사용하는 방법은 다음과 같다:

    let yes: Bool = true
    let no: Bool = false

    그리고 Swift의 유형 추론(type inference) 덕분에 유형(type) 주석(annotation)을 생략(leave off)할 수 있다:

    let yes = true
    let no = false

    부울(Boolean)은 true 또는 false 키워드(keywords)로 표시(denoted)되는 참(true) 또는 거짓(false)만 사용할 수 있다. 위의 코드에서 키워드(keywords)를 사용하여 각 상수(constant)의 상태(state)를 설정(set)한다.

     

    Boolean operators

    부울(Booleans)은 일반적으로(commonly) 값(values)을 비교(compare)하는 데 사용된다. 예를 들어(for example), 두 개의 값(values)이 동일(true)한지 또는 그렇지 않은지(false) 알고 싶은 경우가 있다.

    Swift에서는 ==로 표시(denoted)되는 등호 연산자(equality operator)를 사용하여 이 작업을 수행한다:

    let doesOneEqualTwo = (1 == 2)

    Swift는 doOneEqualTwoBool로 추론(infers)한다. 분명하게(clearly), 1과 2는 같지 않으므로 dosOneEqualTwofalse이다.

    마찬가지로(similarly) != 연산자(operator)를 사용하여 두 값(values)이 같지 않은지 확인할 수 있다:

    let doesOneNotEqualTwo = (1 != 2)

    이번에는 1이 2와 같지 않기 때문에 비교(comparison)는 참(true)이며 dosOneNotEqualTwotrue가 된다.

    부정 연산자(not-operator)라고도 하는 접두사(prefix) ! 연산자(operator)는 true를 false로, false를 true로 전환(toggles)한다. 위 내용을 작성하는 또 다른 방법은 다음과 같다:

    let alsoTrue = !(1 == 2)

    1은 2와 같지 않기 때문에 (1 == 2)false이고 !는 그것을 true로 바꾼다(flips).

    두 개의 연산자(operators)를 더 사용하면, 해당 값(value)이 다른 값(value)보다 큰지(>) 아니면 작은지(<) 확인(determine)할 수 있다. 수학(mathematics)에서의 배운 다음과 같은 연산들을 알고 있을 것이다:

    let isOneGreaterThanTwo = (1 > 2)
    let isOneLessThanTwo = (1 < 2)

    그리고 isOneGreaterThanTwofalse이고, isOneLessThanTwotrue라는 것을 알아내는 것은 로켓 과학(rocket science)이 아니다.

    값(value)이 다른 값보다 작거나 같은지(less than or equal to) 확인(test)할 수 있는 <= 연산자(operator)도 있다. <==의 조합(combination)이므로 첫 번째 값(value)이 두 번째 값(value)보다 작거나 같으면 true를 반환(return)한다.

    마찬가지로(similarly), 값(value)이 다른 값보다 크거나 같은지(greater than or equal to) 확인(test)할 수 있는 >= 연산자(operator)도 있다.

     

    Boolean logic

    위의 각 예제(examples)는 하나의 조건(condition)만 확인(tests)한다. George Boole이 부울(Boolean)을 발명(invented)했을 때, 그는 이러한 초라한(humble) 시작(beginnings)보다 훨씬 더 많은 계획(planned)을 가지고 있었다. 그는 여러 조건(multiple conditions)을 결합(combine)하여 하나의 결과(result)를 생성(form)할 수 있는 부울(Boolean) 논리(logic)를 발명(invented)했다. 

    조건(conditions)을 결합(combine)하는 한 가지 방법은 AND를 사용하는 것이다. 두 개의 부울(Booleans)을 AND 하면 결과(result)는 또 다른 부울(Boolean)이다. 두 입력(input) 부울(Booleans)이 모두 true이면 결과(result)는 true이다. 그렇지 않으면 결과(result)는 false이다.

     

    Swift에서 부울(Boolean) AND 연산자(operator)는 &&이며 다음과 같이 사용한다:

    let and = true && true

    이 경우(case), andtrue가 된다. 오른쪽의 값(values) 중 하나가 false이면 andfalse가 된다.

    조건(conditions)을 결합(combine)하는 또 다른 방법은 OR을 사용하는 것이다. 두 개의 부울(Booleans)을 OR할 때, 입력(input) 부울(Booleans) 중 하나가 true이면 결과(result)는 true이다. 두 입력(input) 부울(Booleans) 모두가 false인 경우에만 결과(result)가 false가 된다.

    Swift에서 부울(Boolean) OR 연산자(operator)는 ||이며, 다음과 같이 사용한다:

    let or = true || false

    이 경우(case), ortrue이다. 오른쪽에 있는 두 값(values)이 모두 false이면 orfalse가 된다. 둘 다 true라면 or는 여전히 true가 된다.

    Swift는 부울(boolean) 논리(logic)를 사용하여 여러(multiple) 조건(conditions)을 평가(evaluate)한다. 두 조건(conditions)이 참(true)인지 확인(determine)하고 싶은 경우에 AND를 사용한다. 두 조건(conditions) 중 하나 이상이 참(true)인지 관심 있다면 OR을 사용한다.

    예를 들어(for example), 다음 코드를 고려(consider)해 본다:

    let andTrue = 1 < 2 && 4 > 3
    let andFalse = 1 < 2 && 3 > 4
    
    let orTrue = 1 < 2 || 3 > 4
    let orFalse = 1 == 2 || 3 == 4

    이들 각각은 AND 또는 OR과 결합(combining)하여 두 개의 개별(separate) 조건(conditions)을 확인(tests)한다.

    부울(Boolean) 논리(logic)를 사용하여 둘 이상의 비교(comparisons)를 결합(combine)하는 것도 가능(possible)하다. 예를 들어(for example), 다음과 같이 복잡한(complex) 비교(comparison)를 구성(form)할 수도 있다:

    let andOr = (1 < 2 && 3 > 4) || 1 < 4

    괄호(parentheses)는 표현(expression)을 명확(disambiguates)하게 한다. Swift는 괄호(parentheses) 안의 하위 표현식(sub-expression)을 먼저(first) 평가(evaluates)한 후, 다음 단계(steps)에 따라 전체(full) 표현식(expression)을 평가(evaluates)한다:

    1. (1 < 2 && 3 > 4) || 1 < 4
    2. (true && false) || true
    3. false || true
    4. true

     

    String equality

    때때로(sometimes) 두 문자열(strings)이 같은지(equal) 확인(determine)해야 하는 경우가 있다. 예를 들어(for example), 사진 속 동물의 이름을 맞추는 아동용 게임은 사용자(player)가 올바르게(correctly) 대답(answered)했는지 확인(determine)해야 한다.

    Swift에서 표준(standard) 항등 연산자(equality operator) ==를 사용하여 숫자(numbers)를 비교(compare)하는 것과 같은 방식으로 문자열(strings)을 비교(compare)할 수 있다. 예를 들면(for example) 다음과 같다:

    let guess = "dog"
    let dogEqualsCat = guess == "cat"

    여기에서 "dog""cat"과 같지 않기 때문에 dogEqualsCat은 부울(Boolean) 값 false이다. 간단하다(simple).

    숫자와 마찬가지로(just as with numbers) 동일(equality) 비교(compare) 뿐만 아니라, 한 값(value)이 다른 값(value)보다 크거나(greater than) 작은지(less) 확인(determine)할 수도 있다. 예를 들면(for example) 다음과 같다:

    let order = "cat" < "dog"

    이 구문(syntax)은 해당 문자열(string)이 알파벳순(alphabetically)으로 다른 문자열 보다 앞서는지 확인(checks)한다. 이 경우(case) "cat""dog"보다 앞서기(comes before) 때문에 ordertrue이다.

    Note: 문자열(string) 동일성(equality)에 대한 자세한 내용은 9장(chapter), "Strings"에서 배우게 된다. 문자열(strings)에 특수 문자(special characters)가 포함(contain)되어 있을 때 나타나는(crop up) 몇 가지 흥미로운 점들(interesting things)을 확인하게 될 것이다.

     

    Toggling a Bool

    Bool은 종종(often) "켜짐(on)" 또는 "꺼짐(off)" 상태(state)를 나타내기(represents)도 한다. 이러한 경우(cases), 상태(state) 간에 전환(toggled)될 수 있는 것이 일반적(common)이다. 예를 들어(for example), 앱(application)에서 Bool을 사용하여 조명 스위치(switch) 상태(state)를 나타내고(represent) "켜짐(on)"과 "꺼짐(off)" 으로 전환(toggle)할 수 있다.

    이러한 상황(situations)에서 Booltrue에서 false로 전환(flip)하고 다시 되돌리는(back again) 편리한(handy) 방법이 있다. 다음과 같다(like so):

    var switchState = true
    switchState.toggle() // switchState = false
    switchState.toggle() // switchState = true

    여기서 switchState라는 변수(variable)는 true로 시작(starts as)한다. 그리고 한 번 toggle하면 false가 된다. 또 한 번의 toggle 후에는 다시 true로 설정(set to)된다.

    Note: 여기에서 toggle()함수(function) 호출(call)이다. 이에 대한 자세한 내용은 5장(chapter), "Functions" 그리고 특정 유형(types)에 적용(apply to)하는 방법은 12장(chapter), "Methods"에서 확인할 수 있다.

     

    Mini-exercises

    1. myAge라는 상수(constant)를 만들고 나이(age)를 설정한다. 그런 다음 부울(Boolean) 논리(logic)를 사용하여 나이(age)가 13세에서 19세 사이의 사람인지 확인(determine)하는 isTeenager라는 상수(constant)를 만든다.
    2. theirAge라는 또 다른 상수(constant)를 만들고, 30으로 설정한다. 그런 다음 부울(Boolean) 논리(logic)를 사용하여 둘 모두가 10대인지 확인(determine)하는 bothTeenagers라는 상수(constant)를 만든다.
    3. reader라는 상수(constant)를 만들고, 당신의 이름을 문자열(string)로 설정한다. author라는 상수(constant)를 만들고, Matt Galloway로 설정한다. 그리고 문자열을 비교하여 readerauthor가 같은지(equal) 확인(determine)하는 authorIsReader 상수(constant)를 만든다.
    4. 문자열 비교(string comparison)를 사용하여 readerauthor보다 알파벳 순서상 앞서는지 판별(determine)하는 readerBeforeAuthor 상수(constant)를 만든다.

     

    The if statement

    프로그램(program)의 흐름(flow)을 제어(controlling)하는 가장 일반적(common)인 첫 번째(first) 방법은 특정 조건(certain condition)이 참(true)인 경우에만 프로그램(program)이 무언가를 수행할 수 있도록 하는 if 문(statement)을 사용하는 것이다. 예를 들어(for example), 다음을 고려(consider)해 본다:

    if 2 > 1 {
      print("Yes, 2 is greater than 1.")
    }

    이것은 간단한 if 문(statement)이다. 조건(condition)이 참(true)이면 중괄호(braces) 사이의 코드를 실행(execute)하고 조건(condition)이 거짓(false)이면 중괄호(braces) 사이의 코드를 실행(execute)하지 않는다. 이게 전부이다(it’s as simple as that).

    if 문(statement)의 핵심은 조건(condition)이다. 조건(condition)은 확인(checked) 하고자 하는 것이며, 중괄호(braces) 안의 코드는 실행되거나 실행되지 않는다. 따라서 if 문(statement)은 조건문(conditional statement)의 한 형태이다. 이 장(chapter)에서 해당 용어(term)가 다시 나타나는 것을 볼 수 있을 것이다.

    if 문을 확장(statement)하여, 조건(condition)이 거짓(false)인 경우 실행할 코드를 제공(provide)할 수 있다. 이를 else 절(clause)이라 하며, 다음은 그 예(example)이다:

    let animal = "Fox"
    
    if animal == "Cat" || animal == "Dog" {
      print("Animal is a house pet.")
    } else {
      print("Animal is not a house pet.")
    }

    여기서 animal"Cat" 또는 "Dog"와 같으면(equals), 첫 번째 코드 블록(block)을 실행(run)한다. animal"Cat" 또는 "Dog"와 같지 않으면 if 문(statement)의 else 부분 블록(block)을 실행(run)하여 디버그 영역(debug area)에 다음을 출력(printing)한다:

    Animal is not a house pet.

    그러나 if 문(statements)을 더 다양하게 사용할 수 있다(you can go even further). 때로는(sometimes) 하나의 조건(condition)을 확인(check)한 다음, 다른 조건을 확인해야 할 수 있다. 이때 이전(previous) if 문(statement)의 else 절(clause)에 다른 if 문(statement)을 중첩(nesting)하는 else-if를 사용할 수 있다.

    다음과 같이 사용할 수 있다:

    let hourOfDay = 12
    var timeOfDay = ""
    
    if hourOfDay < 6 {
      timeOfDay = "Early morning"
    } else if hourOfDay < 12 {
      timeOfDay = "Morning"
    } else if hourOfDay < 17 {
      timeOfDay = "Afternoon"
    } else if hourOfDay < 20 {
      timeOfDay = "Evening"
    } else if hourOfDay < 24 {
      timeOfDay = "Late evening"
    } else {
      timeOfDay = "INVALID HOUR!"
    }
    print(timeOfDay)

    이러한 중첩(nested) if 문(statements)은 참(true) 조건(condition)을 찾을 때까지 여러 조건(multiple conditions)을 하나씩 확인(test)한다. 다음(subsequent) else-if 조건(conditions)이 참(true)인지 여부에 관계없이(regardless of) 첫 번째 참(true) 조건(condition)과 연결된(associated with) 코드만 실행(executed)한다. 다시 말해(in other words), 조건(conditions)의 순서(order)가 중요하다.

    조건(conditions)이 참(true)이 아닌 경우(case)를 처리(handle)하기 위해 끝(end)에 else 절(clause)을 추가(add)할 수 있다. 이 else 절(clause)은 선택 사항(optional)이다. 이 예제(example)에서는 timeOfDay가 출력될 때 유효한 값(valid value)을 보장(ensure)하기 위해 필요하다.

    이 예제(example)에서 if 문(statement)은 하루 중의 시간을 나타내는(representing) 숫자(number)를 가져와, 해당 시간 범위를 나타내는(representing) 문자열(string)로 변환(converts)한다. 24시간(24-hour clock)을 사용하여 한 번에 하나씩 순서(order)대로 확인(checked)한다:

    • 첫 번째로 해당 시간이 6시 미만(less than)인지 확인(check)한다. 참이라면, 이른 아침(early morning)임을 의미한다.
    • 해당 시간이 6보다 작지(less than) 않은 경우, 첫 번째 else-if로 계속 진행(continues)하여 12보다 작은지(less than) 확인(checks)한다.
    • 그런 다음(then) 조건(conditions)이 거짓(false)으로 판명(turn)되면, 해당 시간이 17 미만(less than), 20 미만(less than), 24 미만(less than)인지 확인(checks)한다.
    • 마지막으로(finally), 범위를 벗어나면(out of range) 해당 정보(information)를 콘솔(console)에 출력(prints)한다.

    위의 코드에서 hourOfDay 상수(constant)는 12이다. 따라서 해당 코드는 다음을 출력(print)한다:

    Afternoon

    hourOfDay < 20hourOfDay < 24 조건(conditions)도 모두 참(true)이지만, 조건(condition)이 참(true)인 첫 번째 블록(first block)만 실행(executes)된다. 이 경우(case)에는 hourOfDay < 17 조건(condition) 블록(block)이다.

     

    Short-circuiting

    if 문(statements)에 대한 중요한 사실(important fact)은 AND(&&) 또는 OR(||)로 구분된(separated by) 여러(multiple) 부울(Boolean) 조건(conditions)에서 발생(happens)한다.

    다음 코드를 고려(consider)해 본다:

    if 1 > 2 && name == "Matt Galloway" {
      // ...
    }

    if 문(statement)의 첫 번째 조건(condition)인 1 > 2false이다. 그러므로(therefore) 전체 표현(whole expression)은 결코 true가 될 수 없다.

    따라서 Swift는 표현식(expression)의 두 번째 부분(second part) 즉(namely), name을 확인(check)하지 않는다. 마찬가지로(similarly), 다음 코드를 고려(consider)해 본다:

    if 1 < 2 || name == "Matt Galloway" {
      // ...
    }

    1 < 2true이므로 name의 값(value)에 관계없이 전체 표현식(whole expression)이 true이어야 한다. 따라서(therefore), 다시 한 번 name 확인(check)을 수행(executed)하지 않는다. 이것은 나중에 더 복잡한 데이터 유형(complex data types)을 다룰 때(dealing with) 유용(handy)할 것이다.

     

    Encapsulating variables

    if 문(statements)은 중괄호(braces)를 사용하여 변수(variables)를 캡슐화(encapsulate)하는 새로운 개념(concept)의 scope를 도입(introduce)한다. 고객(client)에게 청구할 요금(fee)를 계산(calculate)한다고 할때, 거래(deal) 내용은 다음과 같다:

    최대 40시간까지는 시간당 $25, 그 이후에는 시간당 $50를 받는다(You earn $25 for every hour up to 40 hours, and $50 for every hour after that).

    Swift를 사용하면 다음과 같이 요금(fee)을 계산(calculate)할 수 있다:

    var hoursWorked = 45
    
    var price = 0
    if hoursWorked > 40 {
      let hoursOver40 = hoursWorked - 40
      price += hoursOver40 * 50
      hoursWorked -= hoursOver40
    }
    price += hoursWorked * 25
    
    print(price)

    이 코드는 시간(hours)을 가져와 40을 초과(over)하는지 확인(checks)한다. 참이라면, 40을 초과하는 시간을 계산(calculates)하고 $50를 곱해(multiplies) 그 결과를 price에 추가한다. 그런 다음 hoursWorked에서 40시간을 초과하는 시간을 빼고(subtracts) $25를 곱(multiplies)하여 총(total) price에 추가(adds)한다.

    위의 예제(example)에서 결과(result)는 다음과 같다:

    1250

    여기서 흥미로운 점(interesting thing)은 if 문(statement) 내부(inside)의 코드이다. 40이 넘는 시간을 저장(store)하기 위해 새로운 상수(constant) hoursOver40을 선언(declaration)했다. 분명하게(clearly), if 문(statement) 내부(inside)에서 사용할 수 있다. 그러나 위 코드의 마지막(at the end)에서 이를 사용(use)하려고 하면 어떻게 되는지 확인해 본다:

    ...
    
    print(price)
    print(hoursOver40)

    그러면 다음과 같은 오류(error)가 발생한다:

    Use of unresolved identifier 'hoursOver40'

    이 오류(error)는 생성된(created) 범위(scope) 내에서만 hoursOver40 상수(constant)를 사용할 수 있음을 알려(informs)준다. 이 경우(case)에서는 if 문(statement)에 새로운 범위(scope)가 도입(introduced)되었으므로, 해당 범위가 끝나면(finished) 이 상수(constant)를 더 이상 사용할 수 없다.

    그러나 각 범위(scope)는 상위 범위(parent scope)의 변수(variables)와 상수(constants)를 사용할 수 있다. 위의 예(example)에서, if 문(statement)의 범위(scope)는 상위 범위(parent scope)에서 생성한 pricehoursWorked 변수(variables)를 사용한다.

     

    The ternary conditional operator

    이제 2장(chapter) "Types & Operations"에서 볼 수 없었던 새로운 연산자(operator)를 소개(introduce)한다. 삼항 조건 연산자(ternary conditional operator)라고 하며 if 문(statements)과 관련(related to)이 있다.

    두 변수(variables)의 최소값(minimum)과 최대값(maximum)을 알아낼(determine) 때, 다음과 같이 if 문(statements)을 사용할 수 있다:

    let a = 5
    let b = 10
    
    let min: Int
    if a < b {
      min = a
    } else {
      min = b
    }
    
    let max: Int
    if a > b {
      max = a
    } else {
      max = b
    }

    지금이라면 이것이 어떻게 작동하는지 알겠지만, 코드의 양이 많다. 삼항 조건 연산자(ternary conditional operator)를 사용해 이를 몇 줄(a couple of lines)로 줄일(shrink) 수 있다.

    삼항 조건 연산자(ternary conditional operator)는 조건(condition)의 참(true) 거짓(false) 여부에 따라(depending on) 두 값(values) 중 하나를 반환(returns)한다. 문법(syntax)은 다음과 같다:

    (<CONDITION>) ? <TRUE VALUE> : <FALSE VALUE>

    이 연산자(operator)를 사용하면 위의 긴 코드 블록(code block)을 다음과 같이 다시 쓸(rewrite) 수 있다:

    let a = 5
    let b = 10
    
    let min = a < b ? a : b
    let max = a > b ? a : b

    첫 번째 예(example)에서 조건(condition)은 a < b이다. 이것이 참(true)이면 min에 할당(assigned)되는 결과(result)는 a의 값(value)이 되고, 거짓(false)이면 b의 값(value)이 된다.

    훨씬 간단(simpler)하다는 데에 동의(agree)할 것이다. 자주(regularly) 사용하게 될 유용한(useful) 연산자(operator)이다.

    Note: 두 숫자 중 크거나(greater) 작은(smaller) 숫자를 찾는(finding) 것은 매우 일반적(common)인 작업(operation)이기 때문에, Swift 표준 라이브러리(standard library)는 이러한 목적(purpose)의 maxmin 두 가지 함수(functions)를 제공(provides)한다. 이 책의 앞부분(earlier)에서 주의를 기울였다면(paying attention) 이미 학습했던 내용임을 기억(recall)할 것이다.

     

    Mini-exercises

    1. myAge 상수(constant)를 생성하고 나이에 맞게 초기화(initialize)한다. if 문(statement)을 작성하여 나이가 13세에서 19세 사이라면 Teenager를 출력(print out)하고, 13세에서 19세 사이가 아니면 Not a Teenager를 출력한다.
    2. answer상수(constant)를 생성하고 삼항 조건(ternary condition)을 사용하여 위의 예제(exercise)와 동일한 경우에 대해 출력 결과를 동일하게 설정(set)한다. 그런 다음 answer을 출력(print out)한다.

     

    Loops

    반복문(loops)은 Swift가 코드를 여러 번 실행(executing)하는 방법이다. 이 섹션(section)에서는 반복문(loop)의 한 유형(type)인 while 반복문(loop)에 대해 배운다. 다른 프로그래밍 언어(programming language)를 알고 있다면 개념(concepts)과 구문(syntax)에 익숙(familiar)할 것이다.

     

    While loops

    while 반복문(loop)은 조건(condition)이 참(true)인 동안 코드 블록(block)을 반복(repeats)한다. 다음과 같은 방식으로 while 반복문(loop)을 만든다:

    while <CONDITION> {
      <LOOP CODE>
    }

    반복문(loop)은 모든 반복(iteration)에 대한 조건(condition)을 확인(checks)한다. 조건(condition)이 true이면 반복문(loop)이 실행(executes)되고, 다른 반복(iteration)으로 이동(moves)한다. 조건(condition)이 false이면 반복문(loop)이 중지된다. if 문(statements)과 마찬가지로 while 반복문(loops)에도 범위(scope)가 있다.

    가장 간단한(the simplest) while 반복문(loop)은 다음과 같은 형식(form)이다:

    while true {  }

    조건(condition)이 항상 true이기 때문에 이 while 반복문(loop)은 절대로 끝나지 않는다. 물론(of course), 프로그램(program)이 영원히 동작(spin)할 것이기 때문에 이러한 while 반복문(loop)을 작성하지는 않을 것이다. 이 상황(situation)을 무한 루프(infinite loop)라고 하며, 프로그램이 중단(crash)되지는 않지만 컴퓨터가 정지(freeze)할 수 있다.

    다음은 while 반복문(loop)의 더 유용한(useful) 예(example)이다:

    var sum = 1
    
    while sum < 1000 {
      sum = sum + (sum + 1)
    }

    이 코드는 값(value)이 1000보다 커지는(greater than) 지점까지 수학적 순서(mathematical sequence)를 계산(calculates)한다.

    반복문(loop)은 다음과 같이 실행(executes)된다:

    • Before iteration 1: sum = 1, loop condition = true
    • After iteration 1: sum = 3, loop condition = true
    • After iteration 2: sum = 7, loop condition = true
    • After iteration 3: sum = 15, loop condition = true
    • After iteration 4: sum = 31, loop condition = true
    • After iteration 5: sum = 63, loop condition = true
    • After iteration 6: sum = 127, loop condition = true
    • After iteration 7: sum = 255, loop condition = true
    • After iteration 8: sum = 511, loop condition = true
    • After iteration 9: sum = 1023, loop condition = false

    아홉 번의 반복(iteration) 후, sum 변수(variable)는 1023이 되므로 sum < 1000의 반복(loop) 조건(condition)은 거짓(false)이 된다. 이 시점에서(at this point) 반복(loop)은 중지된다.

     

    Repeat-while loops

    while 반복문(loop)의 변형(variant)을 repeat-while 반복문(loop)이라 한다. 조건(condition)이 처음(beginning)이 아니라 반복문(loop)의 끝(end)에서 평가(evaluated)된다는 점이 while 반복문(loop)과 다르다. 다음과 같이 repeat-while 반복문(loop)을 구성(construct)한다:

    repeat {
      <LOOP CODE>
    } while <CONDITION>

    다음은 지난 섹션(section)과 동일하지만 repeat-while 반복문(loop)을 사용하는 예(example)이다:

    sum = 1
    
    repeat {
      sum = sum + (sum + 1)
    } while sum < 1000

    이 예제(example)의 결과(outcome)는 이전(before)과 동일하다. 그러나(however), 항상 그런 것은 아니다. 다른 조건(different condition)에서는 다른 결과(different result)가 나올 수 있다.

    다음 while 반복(loop)을 고려(consider)해 본다:

    sum = 1
    
    while sum < 1 {
      sum = sum + (sum + 1)
    }

    동일한 조건(condition)을 사용하는 repeat-while 반복문(loop)은 다음과 같다:

    sum = 1
    
    repeat {
      sum = sum + (sum + 1)
    } while sum < 1

    일반 while 반복문(loop)의 경우 조건(condition) sum < 1은 처음부터(from the start) false이다. 즉, 반복문(loop)의 본문(body)에 도달(reached)하지 않는다. 반복문(loop)이 반복(iterations)을 실행(execute)하지 않으므로 sum의 값(value)은 1이 된다.

    repeat-while 반복문(loop)의 경우, 반복(loop)이 한 번 실행(executes)되기 때문에 sum3이 된다.

     

    Breaking out of a loop

    때로는(sometimes), 반복문(loop)에서 일찍(early) 벗어나고(break out) 싶을 때가 있다. 반복문(loop)의 실행(execution)을 즉시(immediately) 중지하고, 반복문(loop) 이후의 코드를 계속(continues) 실행하는 break 문(statement)을 사용하여 이를 수행할 수 있다.

    예를 들어(for example), 다음 코드를 고려(consider)해 본다:

    sum = 1
    
    while true {
      sum = sum + (sum + 1)
      if sum >= 1000 {
        break
      }
    }

    여기서 반복문(loop) 조건(condition)은 true이므로, 반복문(loop)은 일반적으로(normally) 영원히 반복(iterate)된다. 그러나(however), breaksum1000 이상(greater than or equal to)이면 while 반복문(loop)을 종료시킨다.

    동일한 반복문(loop)을 다양한 방법으로 작성하여, 컴퓨터 프로그래밍(computer programming)에서 여러 가지 방법으로 동일한 결과(result)를 얻을(achieve) 수 있다는 것을 알게 되었다.

    가장 읽기(read) 쉽고 최대한 의도(intent)를 잘 전달(conveys)할 수 있는 방법(method)을 선택해야 한다. 이는 충분한(enough) 시간과 연습(practice)으로 내면화(internalize)할 수 있다.

     

    Mini-exercises

    1. counter라는 변수(variable)를 만들고 0으로 설정(set)한다. counter is X(여기서 Xcounter 값(value)으로 대체(replaced with)한다)를 출력(prints out)하는 조건(condition) counter < 10으로 while 반복문(loop)을 만든 다음 counter1씩 증가(increments)시킨다.
    2. counter라는 변수(variable)를 만들고 0으로 설정(set)한다. roll이라는 다른 변수(variable)를 만들고 0으로 설정(set)한다. repeat-while 반복문(loop)를 만들고, 반복문(loop) 내부에서 roll0에서 5사이의 임의(random)의 숫자를 선택(pick)하는 Int.random(in: 0...5)로 설정(set)한다. 그런 다음 counter1씩 증가(increment) 시킨다. 마지막으로(finally) After X rolls, roll is Y(여기서 Xcounter 값(value)이고 Yroll 값(value)이다)을 출력(print)한다. 첫 번째(first) 0이 굴려 졌을(rolled)때 반복문(loop)이 완료(finishes)되도록 반복(loop) 조건(condition)을 설정(set)한다.

     

    Challenges

    다음으로 넘어가기(moving on) 전에 기본 제어 흐름(basic control flow)에 대한 지식(knowledge)을 확인(test)하는 몇 가지 챌린지(challenges)가 있다. 스스로 해결(solve)해 보려고 하는 것이 가장 좋지만, 막힌다면(get stuck) 다운로드(download)나 소스 코드 링크(source code link)에서 해답(solutions)을 참고할 수 있다.

     

    Challenge 1: Find the error

    다음 코드의 문제점을 확인해 본다.

    let firstName = "Matt"
    
    if firstName == "Matt" {
      let lastName = "Galloway"
    } else if firstName == "Ray" {
      let lastName = "Wenderlich"
    }
    let fullName = firstName + " " + lastName

     

    Challenge 2: Boolean challenge

    다음 각 구문(statements)에서 부울(Boolean) answer 상수(constant)의 값(value)을 확인해 본다.

    let answer = true && true
    let answer = false || false
    let answer = (true && 1 != 2) || (4 > 3 && 100 < 1)
    let answer = ((10 / 2) > 3) && ((10 % 2) == 0)

     

    Challenge 3: Snakes and ladders

    위치(position) 1에서 위치(position) 20으로 이동하는 뱀과 사다리(snakes & ladders) 게임(game)을 하고 있다고 상상(imagine)해 본다. 위치(position) 3과 위치(position) 7에 사다리(ladders)가 있어 각각(respectively) 15와 12로 이동한다. 그리고 위치(position) 11과 17(position)에 뱀(snakes)이 있어, 각각(respectively) 2와 9로 이동한다.

    1과 20 사이의 원하는 위치(position)로 설정할 수 있는 currentPosition 상수(constant)를 생성한다. 그리고 원하는 주사위 굴림(roll of the dice)으로 설정(set)할 수 있는 diceRoll 상수(constant)를 생성한다. 마지막으로(finally) 사다리(ladders)와 뱀(snakes)을 고려하여 최종 위치(position)를 계산(calculate)하는 nextPosition을 생성한다.

     

    Challenge 4: Number of days in a month

    월(month, 모두 소문자(lowercase) String으로 표시)과 현재 연도(year, Int로 표시)가 주어지면, 해당 월(month)의 일(days) 수를 계산(calculate)합니다. 연도(year)가 4의 배수(multiple)이지만 100의 배수(multiple)가 아닌 경우 "2월(february)"은 윤년(leap years)이 되어 29일이라는 것을 기억(remember)해야 한다. 또한 연도(year)가 400의 배수(multiple)인 경우에도 2월(february)은 29일이다.

     

    Challenge 5: Next power of two

    숫자(number)가 주어지면 그 숫자보다 크거나 같은(above or equal to) 2의 다음 거듭제곱(power of two)을 계산(determine)한다.

     

    Challenge 6: Triangular number

    숫자(number)가 주어지면 해당 깊이(depth)의 삼각수(triangular number)를 출력(print)한다. 다음 링크에서 삼각수(triangular numbers)의 정의를 확인할 수 있다:

    https://en.wikipedia.org/wiki/Triangular_number

     

    Challenge 7: Fibonacci

    n번째 피보나치 수(Fibonacci number)를 계산(calculate)한다. 피보나치 수(Fibonacci numbers)는 1과 1로 시작하고, 다음(subsequent) 숫자(numbers)는 시퀀스(sequence)에서 이전의 두 값(values)을 더한 것과 같다. 다음 링크에서 피보나치 수(Fibonacci numbers)의 정의를 확인할 수 있다:

    https://en.wikipedia.org/wiki/Fibonacci_number

     

    Challenge 8: Make a loop

    반복문(loop)을 사용하여 주어진 인수(factor)의 최대 12까지의 시간표(times table)를 출력(print out)한다.

     

    Challenge 9: Dice roll table

    2개의 6면체 주사위 굴림(six-sided dice rolls)이 주어졌을 때 2에서 12까지의 각 숫자를 만드는 조합(combinations)의 수를 보여주는 표(table)를 출력한다. 공식(formula)을 사용하지 않고, 가능한 각 주사위 굴림(dice roll)을 고려(considering)하여 조합(combinations)의 수를 남김없이(exhaustively) 계산(compute)해야 한다.

     

    Key points

    • 부울(Boolean) 데이터 유형(type) Bool을 사용하여 참(true)과 거짓(false)을 나타낸다(represent).
    • 부울(Boolean)을 반환(return)하는 비교 연산자(comparison operators)는 다음과 같다:

    • 부울(Boolean) 논리(&&, ||)를 사용하여 비교(comparison) 조건(conditions)을 결합(combine)할 수 있다.
    • 조건(condition)에 따라(based on) 간단한 결정(decisions)을 내리기 위해 if 문(statements)을 사용한다.
    • 단일 조건(single condition) 이상(beyond)으로 의사 결정(decision)을 확장(extend)하기 위해, if 문(statement) 내에서 elseelse-if를 사용한다.
    • short-circuiting은 부울(Boolean) 표현식(expression)의 최소한(minimal)의 필수 부분(required parts)만 평가(evaluated)되도록 한다.
    • 간단한 if 문(statements) 대신 삼항 연산자(ternary operator, a ? b : c)를 사용할 수 있다.
    • 변수(variables)와 상수(constants)는 특정(certain) 범위(scope)에 속하며, 그 범위를 넘어서(beyond)는 사용할 수 없다. 범위(scope)는 상위(parent)의 변수(variables)와 상수(constants)를 상속(inherits)한다.
    • while 반복문(loops)을 사용하면, 조건(condition)이 충족(met)될 때까지(until) 특정(certain) 작업(task)을 여러 번 수행(perform)할 수 있다.
    • repeat 반복문(loops)은 항상 반복(loop)을 한 번 이상 실행(execute)한다.
    • break 문(statement)을 사용하면 반복문(loop)에서 벗어날(break out) 수 있다.

    'Raywenderlich > Swift Apprentice' 카테고리의 다른 글

    Chapter 6: Optionals  (0) 2021.10.08
    Chapter 5: Functions  (0) 2021.09.02
    Chapter 4: Advanced Control Flow  (0) 2021.08.03
    Chapter 2: Types & Operations  (0) 2021.03.16
    Chapter 1: Expressions, Variables & Constants  (0) 2021.01.19
Designed by Tistory.