프로그래밍 언어/Swift

THE SWIFT PROGRAMMING LANGUAGE SWIFT 5 번역 : WELCOME TO SWIFT - 스위프트로의 여행 (1)

날개 2019. 3. 11. 00:10

THE SWIFT PROGRAMMING LANGUAGE - SWIFT 5 번역



이 글은 THE SWIFT PROGRAMMING LANGUAGE를 번역한 글로, 의미가 쉽게 전달되도록 하기위해 많은 부분을 의역하였음을 미리 알려 드립니다.


WELCOME TO SWIFT


스위프트로의 여행 (1)


전통적으로 새로운 언어를 배울때 처음 하는 것은 "Hello, world!"를 화면에 출력하는 것입니다. 스위프트에서 아래와 같이 단 한줄의 코드로 "Hello, world!"를 출력할 수 있습니다.

1
2
print("Hello, world!")
// Prints "Hello, world!"
cs

여러분이 C 또는 Objective-C로 코드를 작성해왔던 경험이 있다면, 이러한 구문은 여러분에게 친숙할 것입니다. 이 한줄의 코드는 완전한 하나의 프로그램입니다. 여러분은 입출력이나 문자열을 제어하기 위해 따로 라이브러리를 임포트 할 필요가 없습니다. 전역 범위로 쓰여진 코드는 프로그램에서 시작점(entry point)으로 사용됩니다. 그렇기 때문에 여러분은 main() 함수를 사용 할 필요가 없습니다. 또한 각 문장의 끝에 세미콜론을 붙일 필요도 없습니다.

이 글에서는 여러분에게 다양한 프로그래밍 작업을 수행하는 방법을 보여줌으로써 스위프트로 코드를 작성하는 것을 시작하는데 충분한 정보를 제공할 것입니다. 하지만 여러분이 이 글에서 이해하기 어려운 부분이 있다라도 걱정하지 마세요. 이 글에서 소개된 모든 것들을 이 책의 나머지 부분에서 상세하게 설명할 것이니까요.

NOTE

최상의 경험을 위해, 아래 Playground를 다운로드 하여 Xcode에서 열어보세요. Playground는 여러분이 코드를 편집하고 즉시 그 결과를 볼 수 있도록 해 줄 것입니다.



단순한 값들 (Simple Values)

상수를 만드는데 let 을 사용하고, 변수를 만드는데 var 를 사용합니다. 상수의 값이 컴파일시 알려질 필요는 없지만, 여러분은 명확히 한번 상수 값을 할당해야 합니다. 그 말은 한번 정한 값의 상수 이름을 코드의 여러곳에서 사용할 수 있다는 뜻입니다.

1
2
3
var myVariable = 42
myVariable = 50
let myConstant = 42
cs

상수 또는 변수는 여러분이 할당하기를 원하는 값과 같은 타입을 가져야 합니다. 그러나 여러분은 타입을 항상 명시적으로 붙여주지는 않아도 됩니다.
여러분이 상수 또는 변수를 만들때 어떤 값을 주었다면, 컴파일러가 그 타입을 추정할 것입니다. 예를 들어 위 코드에서는, myVariable에 초기값으로 정수 값을 할당 하였으므로, 컴파일러가 myVariable을 정수형으로 추정할 것입니다.

만약에 초기값이 충분한 정보를 제공하지 않는다면 (또는 초기값이 없다면), 콜론(:) 뒤에 타입을 정의해 주어야 합니다.

1
2
3
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

cs

실험하기

4의 값을 가지는 Float 형의 상수를 만들어 보세요. (Float 형을 명시적으로 정의합니다.)

값들은 다른 타입으로 묵시적으로 변환되지 않습니다. 값을 다른 타입으로 변환하고자 한다면, 원하는 타입의 인스턴스를 명시적으로 만들어야 합니다.
 

1
2
3
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
cs


실험하기

위 코드에서 마지막 줄의 String 변환을 제거해 봅시다. 어떤 에러가 발생하나요?

문자열에 값을 포함시키는 더 간단한 방법이 있습니다. 괄호 안에 값을 적고, 괄호 앞에 역슬래시(\)를 적습니다. 아래에 그 예가 있습니다.

1
2
3
4
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
cs

실험하기

문자열에 부동 소숫점 계산을 포함시키는데  \()을 사용해 보세요. 그리고 인사말에 누군가의 이름을 포함시키기 위해서 \()을 사용해 보세요.

여러줄에 걸친 문자열을 위해 3개의 따옴표 사용하세요. 각닫는 3개의 따옴표를 만나기 전까지는 각각의 인용된 줄의 시작부분의 들여쓰기는 제거될 것입니다.
예를 한번 볼까요?

1
2
3
4
5
6
7
8
let quotation = """
Even though there's whitespace to the left,
the actual lines aren't indented.
Except for this line.
Double quotes (") can appear without being escaped.
 
I still have \(apples + oranges) pieces of fruit.
    """
cs

대괄호([])를 사용하여 배열과 딕셔너리를 만듭니다. 그리고 대괄호 안에 인덱스나 키를 적어서 각각의 요소에 접근합니다. 마지막 요소의 뒤에 쉼표를 붙일 수도 있습니다.

1
2
3
4
5
6
7
8
var shoppingList = ["catfish""water""tulips"]
shoppingList[1= "bottle of water"
 
var occupations = [
    "Malcolm""Captain",
    "Kaylee""Mechanic",
]
occupations["Jayne"= "Public Relations"



배열은 여러분이 요소를 추가하면 자동으로 크기가 증가합니다.

1
2
shoppingList.append("blue paint")
print(shoppingList)

cs


비어 있는 배열이나 딕셔너리를 만들기 위해, 초기화 문법을 사용하세요.

1
2
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
cs

타입이 추정될 수 있다면, 여러분은 빈 배열을 [] 으로, 빈 딕셔너리를 [:] 으로 작성할 수 있습니다. - 예를 들어, 새로운 값을 변수에 할당 할때 또는 함수에 인수를 전달 할 때 타입이 추정될 수 있을 것입니다.

1
2
shoppingList = []
occupations = [:]
cs




흐름 제어 (Control Flow)


조건문을 만들기 위해 if 와 switch 를 사용하고, 반복문을 만들기 위해 for-in, while, repeat-whit 을 사용합니다. 조건문과 반복문의 변수를 괄호로 감쌀 것인지를 여러분이 선택 할 수 있습니다. 그리고 본문은 반드시 중괄호로 감싸야 합니다.

1
2
3
4
5
6
7
8
9
10
11
let individualScores = [75431038712]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)
// Prints "11"
cs

if 문에서, 조건부는 부울 표현(true/false)이어야 합니다. - 이것은 if score { ... } 와 같은 표현은 오류라는 것을 의미합니다. 즉 스위프트에서는 이런 표현에서 내부에서 0으로 비교되지 않습니다. (C 나 자바등에서는 0이 false 를 의미하지만, 스위프트에서 0은 false 가 아님)

여러분은 if 와 let 을 값이 누락되지 않도록 함께 사용할 수 있습니다. 이러한 값들은 옵셔널로 표현됩니다. 옵셔널 값은 값을 가지고 있을 수도 있고 값이 없다는 것을 가리키기 위해 nil 일 수도 있습니다. 값의 타입의 뒤에 물음표(?)를 붙임으로써 옵셔날 값임을 표시합니다.

1
2
3
4
5
6
7
8
9
var optionalString: String= "Hello"
print(optionalString == nil)
// Prints "false"
 
var optionalName: String= "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}
cs


실험하기

optionalName 값을 nil 로 바꾸어 봅시다. 어떤 인사말이 나오나요? optional 이 nil 일 경우 다른 인사말을 설정하는 else 절을 추가해 봅시다.

만일 옵셔널 값이 nil 이면, 조건은 false 이고, 중괄호 안의 코드는 무시될 것입니다. 반면에, 옵셔널 값이 언래핑 되고 let 상수에 할당되면, 코드 블럭 안에서 언래핑 된 값을 사용할 수 있습니다.

옵셔널 값을 제어하는 또다른 방법은 ?? 연산자를 사용하여 기본 값을 할당하는 것입니다. 옵셔널에 값이 없다면, 기본 값이 대신 사용될 것입니다.

1
2
3
let nickName: String= nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
cs

switch 는 어떤 종류의 데이터든 지원하며, 또한 매우 다양한 비교 연산도 지원합니다. - 즉, 단순히 정수 값을 비교하는데 한정되지 않는 다는 뜻입니다.

1
2
3
4
5
6
7
8
9
10
11
12
let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber""watercress":
    print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything tastes good in soup.")
}
// Prints "Is it a spicy red pepper?"
cs


실험하기

default 케이스를 제거해 봅시다. 어떤 오류가 발생할까요?

let 이 패턴에 일치하는 값을 상수에 할당하는 패턴에 어떻게 사용되는지 주목해 봅시다.

일치하는 switch case 안의 코드들이 실행된 후에, 프로그램은 switch 문에서 빠져나옵니다. 하나의 일치하는 케이스 안의 코드들이 실행되고 나서는 계속해서 다음 case 로 넘어가지 않습니다. 그러므로 각각의 case 코드 끝에 명시적으로 break 를 사용할 필요는 없습니다.

여러분은 각각 키-값 쌍의 딕셔너리 안의 아이템들을 반복하게 위해 for-in 을 사용할 수 있습니다. 딕셔너리는 순서없는 컬렉션이기 때문에 순환하는 키와 값은 임의의 순서를 가집니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let interestingNumbers = [
    "Prime": [23571113],
    "Fibonacci": [112358],
    "Square": [1491625],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
print(largest)
// Prints "25"
cs


실험하기

어떤 숫자가 가장 큰지, 가장 큰 숫자가 어떤 종류의 숫자였는지 추적하는 변수를 추가해 봅시다.

조건이 변경될 때 까지 코드 블록을 반복하도록 while 을 사용합니다. 만일 반복 조건이 끝에 있을 경우 반복문은 최소한 한번은 실행됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
var n = 2
while n < 100 {
    n *= 2
}
print(n)
// Prints "128"
 
var m = 2
repeat {
    m *= 2
while m < 100
print(m)
// Prints "128"
cs

인덱스 범위를 만들기 위해 ..< 을 사용하여 인덱스를 유지할 수 있습니다.

1
2
3
4
5
6
var total = 0
for i in 0..<4 {
    total += i
}
print(total)
// Prints "6"

cs

인덱스 마지막 값을 포함하지 않으려면 ..< 을 사용하고, 마지막 값까지 포함하려면 ... 을 사용합니다.




함수와 클로저 (Functions and Closures)

함수를 선언하려면 func 를 사용합니다. 괄호안의 인수들과 함수의 이름으로 함수를 호출합니다. 함수의 매개변수 뒤에 -> 을 사용하여 함수의 반환형을 선언합니다.

1
2
3
4
func greet(person: String, day: String-> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
cs


실험하기

day 매개변수를 제거해 보세요. 인사말에 오늘의 런치 스페셜을 포함하도록 매개변수를 추가해 보세요.

기본적으로, 함수는 매개변수의 이름을 인수를 위한 라벨로 사용합니다. 매개변수 이름 앞에 인수 라벨을 적거나 인수 라벨을 생략하려면 매개변수 이름 앞에 _ (언더바)를 사용합니다.

1
2
3
4
func greet(_ person: String, on day: String-> String {
    return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
cs


복합적인 값을 만들기 위해 튜플을 사용합니다. - 예를 들어, 함수로부터 여러개의 값을 한번에 리턴하기 위해서 튜플을 사용할 수 있습니다. 튜플의 요소들은 이름으로 접근 할 수도 있고, 숫자로 접근 할 수도 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0
 
    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }
        sum += score
    }
 
    return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5310039])
print(statistics.sum)
// Prints "120"
print(statistics.2)
// Prints "120"
cs


함수안에 함수를 만들 수도 있습니다 (중첩 함수 - Nested function). 중첩 함수는 바깥쪽 함수에 선언된 변수들에 접근할 수 있습니다. 여러분은 중첩 함수를 길거나 복잡한 함수내의 코드들을 조직하고 정리하는데 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()
cs


함수는 first-class 형입니다. 이 말은 함수는 다른 함수를 그 함수의 값으로써 반환할 수 있다는 뜻입니다.

1
2
3
4
5
6
7
8
func makeIncrementer() -> ((Int-> Int) {
    func addOne(number: Int-> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)
cs


함수는 다른 함수를 인수로 받을 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
func hasAnyMatches(list: [Int], condition: (Int-> Bool-> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int-> Bool {
    return number < 10
}
var numbers = [2019712]
hasAnyMatches(list: numbers, condition: lessThanTen)
cs


함수는 실제로 클로저의 특별한 유형입니다 (코드블록은 나중에 불릴 수도 있습니다.). 클로저 안의 코드는 클로저가 생성된 범위 안에서 사용 할 수 있는 변수와 함수 같은 것들에 접근 할 수 있습니다. 심지어 클로저가 실행될 때 다른 범위에 있다하더라도 그렇습니다 (여러분은 중첩 함수와 함께 이미 이런 예를 보았습니다.). 그리고 중괄호({})로 둘러싸면, 이름 없는 클로저를 작성할 수도 있습니다. 클로저 본문에서 인수들과 반환형 뒤에 in 을 붙여 내용과 구분하세요.


1
2
3
4
numbers.map({ (number: Int-> Int in
    let result = 3 * number
    return result
})
cs

실험하기

모든 짝수에 대해 0을 반환하는 클로저로 다시 작성해 봅시다.

좀더 간결하게 클로저를 작성할 수 있는 여러가지 방법들이 있습니다. 딜리게이트에 대한 콜백처럼 클로저의 타입이 이미 알려져 있다면, 매개변수나 반환형을 생략할 수도 있습니다. 하나의 문장은 묵시적으로 그 문장의 값을 반환 값으로써 반환합니다. (아래의 예제는 return 키워드 없이 3 * number 의 결과를 반환)

1
2
3
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
// Prints "[60, 57, 21, 36]"
cs


여러분은 매개변수를 이름 대신 숫자로 참조 할 수 있습니다 (이러한 접근은 매우 짧은 클로저에서 특히 유용합니다.). 클로저는 괄호 뒤에 즉시 나타날 수 있는 함수에 마지막 인수로써 전달됩니다.

1
2
3
let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)
// Prints "[20, 19, 12, 7]"
cs



(다음 글에 계속)


원글 : https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html

번역 : 날개코더


원글 저작권 2019 Apple Inc. CC BY 4.0  원글출처 https://swift.org/documentation/#the-swift-programming-language

번역글 2차 저작권 (C) 2019 WingsNote.com