본문 바로가기

Swift Language

A Swift Tour (1)

Swift의 기능과 구문을 살펴보자!

새로운 언어의 첫번째 프로그램

전통적으로 새로운 언어의 첫번째 프로그램은 "Hello, world!"를 출력하는 것

Swift에서는 한줄로 표현이 가능

print("Hello, world!")
// Prints "Hello, world!"

이 자체만으로 완벽한 프로그램임

출력, 문자열 처리와 같은 기능을 위해 별도의 라이브러리를 가져올 필요가 없음

전역 범위에서 작성된 코드는 프로그램의 전체에서 사용되기 때문에 main() 함수가 필요 없음

Simple Value

상수는 let, 변수는 var를 사용하여 값 생성

상수는 컴파일타임에 알 필요가 없지만 반드시 한번은 할당되어야 함

할당은 한번만 되지만 여러 위치에서 호출될 수 있음

할당 시 타입에 맞게 값을 입력해야하지만, 타입을 꼭 명시하진 않아도 됨

상수, 변수를 생성할 때 값을 제공하면 컴파일러가 타입을 유추

초기값이 타입에 대한 충분한 정보를 제공하지 않거나, 초기값이 없는 경우 타입을 명시해야 함

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

값들은 다른 타입의 값으로 절대 변경되지 않음

타입을 변경하고 싶다면 원하는 타입의 인스턴스를 명시적으로 만들어야 함

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

\() : 값을 문자열 값으로 간단하게 추가할 수 있음

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

[] : 배열과 딕셔너리를 생성 및 요소 접근 시 사용

마지막 요소 뒤에 쉼표는 용인됨

var fruits = ["strawberries", "limes", "tangerines"]
fruits[1] = "grapes"

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

[] 는 배열 / [:] 는 딕셔너리

Control Flow

조건문 : if 구문, switch 구문

반복문 : for-in 구문, while 구문, repeat-while 구문

* 이때 () 소괄호는 선택사항, {} 중괄호는 필수사항

 

if 구문의 조건부는 반드시 Boolean으로 표현되어야 함

특정 값을 나타내는 표현이 들어오면 에러임

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
	// if score { -> error
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)
// Prints "11"

조건을 기준으로 값을 선택하여 값을 할당할 수 있음

= 이나 return 뒤에, if 또는 switch를 작성할 수 있음

let scoreDecoration = if teamScore > 10 {
    "🎉"
} else {
    ""
}
print("Score:", teamScore, scoreDecoration)
// Prints "Score: 11 🎉"

if와 let으로 옵셔널 바인딩을 할 수 있음

var optionalString: String? = "Hello"
print(optionalString == nil)
// Prints "false"

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

?? 연산자를 사용하여 기본값을 제공하여 옵셔널 바인딩을 할 수 있음

let nickname: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickname ?? fullName)"

switch는 정수 및 단순 비교에 제한되지 않고 모든 종류의 데이터와 다양한 비교 작업을 지원함

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?"

패턴과 일치하는 값을 상수에 할당하기 위해 패턴에서 let을 사용하는지 보자

switch case문을 실행하고 switch문을 종료함

 

for-in 구문을 사용하여 Dictionary 항목을 조회

Dictionary는 순서가 없는 Collection이기 때문에, key-value값은 임의의 순서로 조회됨

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (_, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
print(largest)
// Prints "25"

 

조건이 바뀔 때까지 코드의 블럭을 반복하려면 while구문을 사용해야 함

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"

Functions & Closure

func로 함수 선언

선언한 함수를 소괄호 안에 인수의 리스트와 함수의 이름으로 호출

반환타입에는 -> 를 붙여서 명시

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

인수 라벨을 사용하지 않으면 _ 로 작성

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

여러 개 값을 반환 시 Tuple을 사용할 수 있음

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: [5, 3, 100, 3, 9])
print(statistics.sum)
// Prints "120"
print(statistics.2)
// Prints "120"

중첩함수

중첩함수는 외부 함수에서 선언한 변수에 접근 가능함

이를 사용하여 함수의 길이가 긴 경우 보다 간결하게 코드 작성 가능

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()

함수는 1급 객체(first class type)이기 때문에 함수가 다른 함수를 값으로 반환할 수 있음

func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

함수는 1급 객체(first class type)이기 때문에 함수를 다른 함수의 인자로 가질 수 있음

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 = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)

클로저는 클로저가 생성된 범위에서 사용 가능한 변수와 함수와 같은 항목에 접근할 수 있음

({}) 로 코드를 묶어 이름없는 클로저를 작성할 수 있으며, 인수와 반환 타입을 분리하기 위해 in 을 사용

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

클로저의 타입을 알고 있다면 파라미터의 타입, 반환 타입을 생략할 수 있음

단일 클로저 구문은 암시적으로 구문의 값만 반환

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

간략한 클로저의 접근 방법으로 숫자로 파라미터를 참조할 수 있음

클로저가 함수의 유일한 인수일 때 소괄호는 생략 가능

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

 

728x90

'Swift Language' 카테고리의 다른 글

A Swift Tour(2)  (0) 2024.02.14
Version Compatibility  (0) 2024.01.24
About Swift  (0) 2024.01.22