Swift에서는 통상적으로 이용하는 +
, -
, /
, %
같은 산술연산자와 &&
, ||
같은 논리 연산자, 그리고 C에서 지원하지 않는 a..
나 a…b
같이 값의 범위를 지정할 수 있는 범위 연산자를 지원한다.
연산자에는 단항(unary), 이항(binary) 그리고 삼항(ternary) 연산자가 있다.
단항 연산자
는 -a
, !b
, c!
와 같이 하나의 대상에 앞뒤에 바로 붙여 사용하는 연산자다.이항 연산자
는 2 + 3
같이 두 대상 사이에 위치하는 연산자다.삼항 연산자
는 a ? b : c
형태로, C처럼 Swift에 삼항 연산자는 이 연산자 단 하나만 존재합니다.할당 연산자(a = b)
는 a
의 값을 b
로 초기화 하거나 변경한다. 상수, 변수에 모두 사용 가능하다.
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 또는 Objective-C와 달리 Swift는 할당 연산자가 값을 반환하지 않는다.
if x = y {
// This is not valid, because x = y does not return a value.
}
이는 동등 비교 연산자(==)
를 의도한 곳에 할당 연산자가 사용되는 것을 막는다.
Swift는 모든 숫자 타입에서 사용 가능한 네 가지 표준 사칙 연산자
를 지원한다.
1 + 2 // equals 3
5 - 3 // equals 2
2 * 3 // equals 6
10.0 / 2.5 // equals 4.0
C나 Objective-C와 달리 Swift는 사칙 연산의 값이 오버플로우되는 것을 허용하지 않는다. Swift의 오버플로우 연산자(a &+ b
와 같은 형태)를 사용해 이를 허용할 수 있다.
덧셈 연산자는 String 타입에 사용될 수 있다.
"hello, " + "world" // equals "hello, world"
나머지 연산자(a % b)
는 a를 채울 정도로 b를 곱한 뒤 남은 값을 반환한다.
a = (b * some mulitplier) + remainder
9 % 4 // equals 1
// 9 = (4 * 2) + 1
-9 % 4 // equals -1
// -9 = (4 * -2) + (-1)
단항 음수 연산자
로 알려진 -
에 의해 부호가 바뀐다.
let three = 3
let minusThree = -three // minusThree equals -3
let plusThree = -minusThree // plusThree equals 3, or "minus minus three"
단항 양수 연산자
로 알려진 `+는 아무런 변화도 일으키지 않는다.
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix equals -6
C와 같이, Swift도 할당 연산자(=)와 다른 연산자를 합성해 +=
와 같은 형태로 축약해 사용할 수 있다.
var a = 1
a += 2
// a is now equal to 3
합성 할당 연산자는 값을 반환하지 않는다.
let b = a += 2
와 같은 코드는 사용할 수 없다.
Swift는 C의 모든 표준 비교 연산자
를 지원한다.
Swift는 두 참조 객체가 같은 인스턴스를 참조하는지 판단하기 위해 두 개의 식별 연산자(=== 와 !==)를 제공한다.
1 == 1 // true because 1 is equal to 1
2 != 1 // true because 2 is not equal to 1
2 > 1 // true because 2 is greater than 1
1 < 2 // true because 1 is less than 2
1 >= 1 // true because 1 is greater than or equal to 1
2 <= 1 // false because 2 is not less than or equal to 1
비교 연산자는 주로 조건문에 사용된다.
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" are not 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"
튜플은 비교 연산자가 각각의 값을 비교할 수 있을 때만 비교할 수 있다.
("blue", -1) < ("purple", 1) // OK, evaluates to true
("blue", false) < ("purple", true) // Error because < can't compare Boolean values
Swift 표준 라이브러리에서는 7개 미만의 요소를 갖는 튜플만 비교할 수 있다. 그 이상을 비교하려면 직접 비교 연산자를 구현해야 한다.
삼항 조건 연산자(Ternary Conditional Operator)
는 question ? answer1 : answer2
의 형태를 갖는 특별한 연산자이다. question
이 참이면 answer1
이, 거짓이면 answer2
가 실행된다.
삼항 조건 연산자는 아래 코드의 축약이다.
if question {
answer1
} else {
answer2
}
삼항 연산자의 예시
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90
삼항 연산자는 코드를 효율적으로 축약할 수 있다. 하지만 과도하게 사용할 경우 되레 코드의 가독성을 떨어뜨리는 결과를 초래한다. 하나의 구문에 여러 삼항 연산자를 쓰는 건 피해야 한다.
nil 병합 연산자(a ?? b)
는 옵셔널 a가 nil
일 경우 b를, 이외의 경우(값을 포함하고 있는 경우)에는 a를 반환한다. a는 옵셔널 타입이어야 하며, b는 a에 포함되어 있는 값의 타입과 반드시 일치해야 한다.
nil 병합 연산자는 아래 코드의 축약이다.
a != nil ? a! : b
a가 nil
이 아닐 때 a가 감싸고 있는 값에 접근하거나, a가 nil
일 때 b를 반환하기 위해 삼항 연산자와 forced unwrapping을 사용한다.
만약 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"
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is not nil, so colorNameToUse is set to "green"
닫힌 범위 연산자(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
반 열린 범위 연산자(a..<b)
는 a부터 b 사이의 범위를 b를 제외하여 정의한다. 첫 번째 값은 포함하지만 마지막 값은 포함하지 않기 때문에 반만 열렸다고 표현한다. a는 b보다 클 수 없다. 만약 a와 b가 같다면 결과 범위는 비게 된다. 배열을 다루는 데 유용하다.
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
[a..]
[..a]
의 형태로 범위의 시작 혹은 끝만 지정해 사용하는 범위 연산자이다. 지정한 시작 값 혹은 끝 값은 범위에 포함된다. 예를 들어 한 배열의 2번 인덱스부터 끝까지 범위로 지정하고자 할 경우, 단 방향 범위 연산자
를 사용함으로써 생략할 수 있다.
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뿐만 아니라 아래와 같이 특정 값을 포함하는지 여부를 확인할 때도 사용 가능하다. 단, 첫 번째 값을 생략하여 반복을 제어할 수는 없다. iteration이 어디서 시작해야 하는지 명확하지 않기 때문이다. 마지막 값을 생략할 경우 반복이 가능하나, 범위가 불명확하게 반복되므로 명시적으로 끝을 지정해 주는 것이 권장된다.
let range = ...5
range.contains(7) // false
range.contains(4) // true
range.contains(-1) // true
Swift는 다음 세 가지 논리 연산자
를 지원한다.
논리 부정 연산자(!a)
는 true
를 false
로, false
를 true
로 변환한다.
let allowedEntry = false
if !allowedEntry {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
논리 곱 연산자(a && b)
는 두 값이 모두 참일 때 true
를 반환한다. 만약 첫 번째 값이 거짓이라면 두 번째 값을 판단하지 않고 즉시 false
를 반환한다(short-circuit evaluation).
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
논리 합 연산자(a || b)
는 둘 중 하나만 참이어도 true
를 반환한다. 논리 곱 연산자와 마찬가지로 논리 곱 연산자도 short-circuit evaluation
을 사용한다. 첫 번째 값이 참이라면 두 번째 값을 판단하지 않고 즉시 true
를 반환한다.
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
여러 개의 논리 연산자를 조합하여 사용할 수 있다.
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
논리 연산자 &&와 ||는 왼쪽에서 오른쪽 순서로 읽는다.
논리 연산자의 적용 우선 순위를 연산자에 맡기지 않고 명시적으로 괄호를 사용해 계산 순서를 지정할 수 있다.
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
// Prints "Welcome!"
이러한 방법은 가독성을 높이는 데도 도움을 준다.