Swift - 연산자 1

 

기본 연산자 중 swift의 특징적인 연산자들

Swift의 특수한 연산자들


할당 연산자

  • 튜플의 할당
let (x, y) = (1, 2)
// x에는 1이 y에는 2가 할당된다.
  • Swift는 If문 안에서 함수로부터 바로 리턴받아 평가하는 식을 사용하지 못한다. 아래 코드는 유효하지 않다.
if x = y {
    // swift는 조건문 안에서 비교를 위한 == 연산자만을 허용하고 개발자가 x = y 형태의
    // 조건문을 사용하는 실수를 피하도록 하기 위해 이러한 형태를 허용하지 않는다.
}
  • Swift의 산술 연산자는 C나 Objective-C와 달리 연산 결과가 Overflow 되었을 때 자동으로 처리해주지 않는다. Overflow에 대응하기 위해서는 별도의 Overflow 연산자를 사용해야 한다.
  • Swift에는 두 객체가 같은 인스턴스를 참조하고 있는지 확인하는 ===, !== 두 연산자가 있다.
  • 두 개의 튜플이 같은 타입이고 같은 개수의 값을 가지고 있다면 튜플간의 비교도 가능하다.
  • 튜플의 비교는 왼쪽부터 오른쪽으로 서로 같지 않은 값을 찾을 때까지 각 값들을 한번에 하나씩 순차적으로 비교해 나간다.
  • 튜플의 첫 번째 값이 같지 않다면 첫 번째 값의 비교 결과를 전체 튜플의 비교 결과로 결정하며 두 번째 값은 비교하지 않는다. 하지만 첫 번째 값이 같다면 두 번째 값을 비교하여 결과를 결정한다.
  • 튜플의 모든 구성 값들이 같을 경우에 두 개의 튜플은 같다고 한다.
(1, zebra) < (2, apple)   // 이미 1과 2에서 비교가 완료되었기에 문자열은 비교하지 않는다. 결과는 2가 1보다 크기 때문에 true
(3, apple) < (3, bird)    // 첫 번째 값이 3과 3이 동일하므로 문자열까지 비교하여 판단한다. 결과는 bird가 apple 보다 크기 때문에 true
(4, dog) == (4, dog)      // 앞에 숫자와 뒤의 문자열이 모두 같기 때문에 true
  • 튜플의 구성요소가 모두 비교 가능한 경우에만 튜블간 비교가 가능하다. 예를들어 (String, Bool) 형태의 튜플은 Bool 타입이 비교 불가하기 때문에 튜플 자체를 비교할 수 없다.
("blue", -1) < ("purple", 1)        // OK, 두 구성요소가 모두 비교 가능한 타입
("blue", false) < ("purple", true)  // Error, Bool 타입은 비교 불가!
  • 스위프트에는 7개 미만의 요소를 가진 튜플 비교 연산자가 포함되어 있으며 7개 이상의 요소를 갖는 튜플의 비교 연산자는 직접 구현해야 한다(하지만 이 연산자가 어떤 것을 의미하는지 모르겠음…-.-)

Nil-Coalescing 연산자

  • Nil 병합(Nil-Coalescing) 연산자는 (a ?? b)와 같이 쓴다.
  • optional 변수(상수) a에 값이 들어있을 경우 언래핑하고 그렇지 않을 경우 기본값 b를 리턴한다.
  • 이때 a는 optional 타입어아야 하고 b의 값은 a의 값과 같은 타입이어야 한다.
  • 이 연산자는 다음 코드의 단축형이다.
a != nil ? a! : b
let defaultColorName = "red"
var userDefinedColorName: String?   // 기본값이 nil이다.

var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName이 nil이기 때문에 기본값인 "red"를 리턴한다.

// 만일 userDefinedColorName 변수에 값을 할당한다면
userDefinedColorName = "green"

var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName에 값이 있기 때문에 "green"을 리턴한다.

범위 연산자

  • 값들의 범위를 표현하기 위한 연산자이다.
  1. 닫힌 범위 연산자(Closed Range Operator) :
    • 연산자 앞 뒤의 값을 포함하며 앞의 값이 뒤의 값보다 작아야 한다. (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
  1. 반열린 범위 연산자(Half-Open Range Operator) : ..<
    • 시작 값은 포함하지만 마지막 값은 포함하지 않는다, 시작값은 마지막 값보다 작아야 한다.
    • (a..<b)인 경우 a는 범위에 포함되고 b는 범위에 포함되지 않으며 a < b여야 한다.
    • a == b인 경우 범위는 빈 값이 리턴된다.
    • 배열같은 zero 베이스의 값을 처리할 때 유용하다.
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
  1. One-Sided Range
    • 닫힌 범위 연산자(Closed Range Operator)에서 한쪽 범위를 생략한 형태이다.
    • 배열을 예로들면 특정 인덱스부터 마지막 인덱스까지 혹은 첫 인덱스부터 특정 인덱스까지의 범위를 지정하는 경우 사용한다.
for name in names[2...] {
    print(name)
}
// Brian
// Jack

for name in names[...2] {
    print(name)
}
// Anna
// Alex
// Brian
  • 반열린 범위 연산자(Half-Open Range Operator)의 경우 처음 범위만 생략 가능하다.
for name in names[..<2] {
    print(name)
}
// Anna
// Alex
  • 범위가 제한되지 않은 일반적인 컨텍스트에서는 One-Sided Range 사용을 주의해야 한다. 시작값이 생략되는 경우 어디부터가 시작인지 모호해지며 종료 값이 생략되는 경우 값이 무한대로 이어질 수 있다. 가장 좋은 방법은 범위 내에 적절한 값이 들어있는지를 확인하는 것이다.
let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true