Swift 정리 - 5. 연산자


Swift의 연산자에 대해 알아보자.


연산자는 값을 확인하고, 바꾸고, 조합하는데 사용되는 특별한 심볼 혹은 문구다. Swift는 이미 잘 알려진 연산자들을 지원하고, 흔한 코딩 에러를 방지하기 위해 여러 향상된 기능을 도입했다. 예를 들어 = 연산자는 값을 리턴하지 않게 해서 == 가 의도된 곳에 실수로 쓰이지 않게 하고, 이항 연산자는 오버플로우를 감지하고 이를 허용하지 않아서 타입을 넘어서는 값들을 가지고 작업할 때 예상치 못한 결과가 나오는 상황을 피하게 해준다.

Swift는 또한 C에서 볼 수 없는 a..<b, a...b와 같은 범위 연산자를 제공한다.

Terminology

연산자는

  1. 연산되는 값의 수 : unary, binary, ternary
  2. 연산자의 위치 : 전위, 중위, 후위

에 따라 구분된다.

띄어쓰기와 연산자 Swift에서는 띄어쓰기도 중요한 문법 중 하나이기 때문에 연사자의 앞, 뒤 어디에 공백이 있느냐도 중요하다. 즉 A != BA! = B는 완전히 다르다.

연산자의 종류

Assignment Operator

= : 값을 할당할 때 사용한다.

let b = 10
var a = 5
a = b
// a is now equal to 10


let (x, y) = (1, 2)
// x is equal to 1, and y is equal to 2

C에서와는 다르게 Swift에서의 할당 연산자는 값을 리턴하지 않는다. 그래서 다음 예제는 유효하지 않다.

if x = y {
    // This isn't valid, because x = y doesn't return a value.
}

컴파일 에러가 난다.

image

이 기능은 == 자리에 =가 실수로 쓰이는 걸 방지해준다.

Arithmetic Operators

Swfit는 네 개의 표준 연산자(덧셈, 뺄셈, 곱셈, 나눗셈)을 지원한다.

1 + 2       // equals 3
5 - 3       // equals 2
2 * 3       // equals 6
10.0 / 2.5  // equals 4.0

C와는 다르게, Swift의 산술 연산자는 기본적으로 overflow를 허용하지 않는다. 참고로 덧셈 연산자는 문자열을 합치는데도 사용된다.

"hello, " + "world"  // equals "hello, world"

Remainder Operator

나눗셈 연산자(%)는 나눈 나머지를 반환하는 연산자다.

9 % 4    // equals 1

음수의 나머지 연산의 경우는 아래와 같다.

-9 % 4   // equals -1

참고로 a%b에서 b의 부호는 무시된다. 즉 a % ba % -b는 같다.

Swift의 나머지 연산과 나누기 연산자 Swift에서는 부동 소수점 타입의 나머지 연산까지 지원한다.

let number: Double = 5.0
var result: Double = number.truncatingRemainder(dividingBy:  1.5) // 0.5
result = 12.truncatingRemainder(dividingBy: 2.5) // 2.0

나누기 연산은 기존의 프로그래밍 언어처럼 나머지나 소수점을 제외한 정수만을 결괏값을 반환한다.

var result: Int = 5/3 // 1
result = 10/3 // 3

계속 강조하지만 Swift는 type-safe한 언어이고, 서로 다른 자료형끼리의 연산을 엄격히 제한한다. Int타입과 UInt 타입도 다른 타입이기 때문에 이 둘의 연산도 제한된다.

Unary Minus Operator

수의 값은 앞에 -를 붙여 음/양이 바뀔 수 있다. 공백 없이 붙여써야 한다.

let three = 3
let minusThree = -three       // minusThree equals -3
let plusThree = -minusThree   // plusThree equals 3, or "minus minus three"

Unary Plus Operator

+ 연산자는 변화 없이 단순히 값을 리턴한다.

let minusSix = -6
let alsoMinusSix = +minusSix  // alsoMinusSix equals -6

Compound Assignment Operators

복합 할당 연산자는 할당 연산자와 다른 연산자를 조합한 것이다.

var a = 1
a += 2
// a is now equal to 3

복합 할당 연산자는 값을 리턴하지 않는다. 예를 들어 let b = a += 2와 같이 쓸 수 없다.

Comparison Operators

Swift는 아래의 비교 연산자를 지원한다.

  • Equal to (a == b)
  • Not equal to (a != b)
  • Greater than (a > b)
  • Less than (a < b)
  • Greater than or equal to (a >= b)
  • Less than or equal to (a <= b)

Swift는 두 개의 identity operators(참조 연산자) ===, !==를 제공한다. 이는 비교하는 값들이 참조 타입일 때 같은 인스턴스를 가리키는지를 비교해서 불리언 값을 반환한다.

참조 비교 연산자 Swift의 유일한 참조 타입인 클래스의 인스턴스에서만 참조 비교 연산자를 사용할 수 있다. Swift의 기본 데이터 타입은 모두 구조체로 구현되어 있기 때문에 값 타입이다. 따라서 비교 연산에는 ==를 사용하고, 클래스의 인스턴스인 경우에만 ===를 사용한다.

비교 연산자는 주로 조건 문제엇 많이 사용된다.

let name = "world"
if name == "world" {
    print("hello, world")
} else {
    print("I'm sorry \(name), but I don't recognize you")
}
// Prints "hello, world", because name is indeed equal to "world".

같은 개수와 같은 타입을 가진 튜플을 비교할 수도 있다. 튜플은 왼쪽에서 오른쪽순으로 비교되고, 한 번에 한 값만 비교된다. 만약 모든 값들이 같을 경우 튜플은 같다고 여겨진다.

(1, "zebra") < (2, "apple")   // true because 1 is less than 2; "zebra" and "apple" aren't compared
(3, "apple") < (3, "bird")    // true because 3 is equal to 3, and "apple" is less than "bird"
(4, "dog") == (4, "dog")      // true because 4 is equal to 4, and "dog" is equal to "dog"

Swift 표준 라이브러리에서 튜플을 비교 연산자로 비교하는 것은 튜플의 요소가 7개보다 적을때만 가능하다. 7개 이상 원소를 가진 튜플을 비교하려면 비교 연산자를 구현해야 한다.

Ternary Conditional Operator

삼항 연산자는 question ? answer1 : answer2와 같은 형태로 작성한다. 이를 풀어서 코드를 작성하면 아래와 같다.

if question {
    answer1
} else {
    answer2
}

Nil-Coalescing Operator

Nil 병함 연산자 ??(a ?? b)에서 옵셔널 a를 unwrapping해서 만약 a에 값이 있다면 값을 리턴하고 nil일 경우 b를 리턴한다. a의 표현식은 항상 옵셔널 타입이어야 한다. b는 a 내에 저장되어 있는 값의 타입과 일치해야 한다.

코드로 풀어쓰면 아ㅐㄹ와 같다.

a != nil ? a! : b

위 예제에서 상항 연산자와 옵셔널 강제 추출 연산자 (a!)를 썼다.

a가 nil이 아닌 경우, b의 값은 평가되지 않는다. 이걸 short-circuit evaluation이라고 한다.

let defaultColorName = "red"
var userDefinedColorName: String?   // defaults to nil

var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"

Range Operators

Swift는 여러 범위 연산자를 지원한다.

Closed Range Operator

폐쇄 범위 연산자 (a...b)는 a, b를 포함해 a부터 b까지의 범위를 정의한다. a는 b보다 크면 안된다.

이 폐쇄 범위 연산자는 for-in 문에서 반복할 때 유용하다.

for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25

Half-Open Range Operator

반 폐쇄 범위 연산자 (a..<b)는 a에서 b까지를 의미하는데, b를 포함하지 않는 것을 의미한다. 만약 a와 b가 같다면 범위는 아무것도 포함하고 있지 않을 것이다.

반 폐쇄 범위 연산자는 배ㅕㅇㄹ같은 zero-based 리스트에서 유용하다.

let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
    print("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack

One-Sided Ranges

단방향 범위 연산자는 한 방향으로 쭉 갈 수 있는 범위를 나타내는 연산자다.

for name in names[2...] {
    print(name)
}
// Brian
// Jack

for name in names[...2] {
    print(name)
}
// Anna
// Alex
// Brian

for name in names[..<2] {
    print(name)
}
// Anna
// Alex

단방향 범위 연산자는 subscript 뿐만 아니라 다른 곳에서도 많이 사용된다. 처음 값이 없는 단방향 범위를 반복할 수는 없는데, 그 이유는 이 반복이 어디서부터 시작될지 명확하지 않기 떄문이다. 이런 경우에는 아래와 같이 특정 범위내에 값이 있는지를 확인한다.

let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true

Logical Operators

논리 연산자는 두 불리언 로직 값을 수정하거나 조합하는 연산자다.

  • Logical NOT (!a)
  • Logical AND (a && b)
  • Logical OR (a b)

Overflow Operators

Swift는 기본 연산자를 통해 오버플로에 대비할 수 있게 했다. 오버플로 연산자를 사용하면 오버플로를 자동으로 처리한다.

  • 오버플로 더하기 연산자 &+ : 오버플로에 대비한 덧셈 연산을 한다.
  • 오버플로 빼기 연산자 &- : 오버플로에 대비한 뺄셈 연산을 한다.
  • 오버플로 곱하기 연산자 &* : 오버플로에 대비한 곱셈 연산을 한다.

Value Overflow

숫자는 양과 음 모든 방향으로 오버플로우가 발생할 수 있다.

var potentialOverflow = Int16.max
// potentialOverflow equals 32767, which is the maximum value an Int16 can hold
potentialOverflow += 1
// this causes an error

var unsignedOverflow = UInt8.max
// unsignedOverflow equals 255, which is the maximum value a UInt8 can hold
unsignedOverflow = unsignedOverflow &+ 1
// unsignedOverflow is now equal to 0

Custom Operators

Swift.org:Custom Operators

Swift에서는 표준 연산자에, 내가 추가로 커스텀 연산자를 선언할 수 있다.

=과 삼항 연산자는 사용자 정의 역할을 부여할 수 없다.

sdfsdfsd