Operator : 특정 값을 확인 / 변경 / 조합 하기 위해 사용하는 간단한 symbol / phrase.

Terminology

Operator 가 연산하는 값들이 operands (피연산자)

Assignment Operator

=

let b = 10
var a = 5

a = b
// a is now equal to 10

let (x, y) = (1, 2) // tuple 값 할당

C, obj-c 와는 다르게 값 자체를 return 하지 않음. 이를 통해 equal to operator == 를 사용해야 하는 시점에 assignment operator = 를 실수로 사용하는 것을 방지해줌

if x = y {
	// ❗️ x = y 가 값을 return 하지 않기 때문에 유효하지 않음
}

Arithmetic Operators

Swift 는 네 개의 표준 arithmetic 연산자 지원

C, obj-c 와는 다르게 기본적으로 overflow 를 허용하지 않으나 overflow operators (&+, …) 를 사용할 수 있음.

Addition operator 는 String concatenation 에 지원됨

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

Remainder Operator

a % b : 나머지 연산.

a = (b x some multiplier) + remainder. 이 때 multiplier 는 가장 큰 숫자여야 함

9 % 4 // 1

-9 % 4 // -1
// -9 = (4 * -2) + (-1)

Unary Minus Operator

prefixed - 로 부호를 바꿀 수 있음

let three = 3 
let minusThree = -three // minusThree equals -3

Unary Plus Operator

변화 없이 해당 값을 그대로 return

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

Compound Assignment Operators

assignment = 와 다른 operator 를 조합한 연산자. 값을 리턴하지 않음

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

let b = a += 2 // ❗️ invalid

Comparison Operators

Bool 값을 리턴함

같은 타입과 개수의 값들을 가진 tuple 을 비교할 수 있음. Tuple 은 왼쪽 -> 오른쪽 순서대로 값 하나씩 비교됨. 모든 값이 다 같은 경우에만 같은 것으로 판단됨. 각 값에 operator 를 적용할 수 있는 경우에만 비교될 수 있음.

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


("blue", -1) < ("purple", -7)        // OK: Evaluates to true. 첫 번째 값으로 판단
("blue", false) < ("purple", true)  // ❗️ Error: Can't use < to compare Boolean values.

Swift 표준 라이브러리에서 tuple 비교는 7개보다 적은 tuple 에만 적용되기 때문에 필요하다면 직접 구현해야 함

Ternary Conditional Operator

question ? answer1 : answer2 형태.

if question {
	answer1
} else {
	answer2
}

간결하게 작성할 수 있으나 많이 사용될 경우 가독성을 떨어뜨릴 수 있음에 주의.

Nil-Coalescing Operator

a ?? b 는 optional a 의 값이 있으면 unwrap 하고 없다면 b 를 리턴

a != nil ? a! : b

short-circuit evaluation : a 가 nil 이 아닐 경우 b 는 연산되지 않음

Range Operators

Closed Range Operator

a...b : b 를 포함한 범위까지

for index in 1...5 {
	print(index)
}
// 1 ~ 5 까지 출력됨

Half-Open Range Operator

a..<b : b 를 포함하지 않는 범위까지. 배열 iterate 할 때 편함

let names = ["Anna", "Alex", "Brian", "Jack"] 
let count = names.count 

for i in 0..<count { 
	print("Person \(i + 1) is called \(names[i])") 
}

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

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

Logical Operators

Bool 값을 수정 / 조합함

Logical NOT Operator

Bool 값을 toggle 하는 prefix operator. not ~ 라고 읽음

let allowedEntry = false 
if !allowedEntry { print("ACCESS DENIED") }

Logical AND Operator

두 값이 모두 true 여야 true 가 됨. 첫 번째 조건이 false 인 경우 두 번째 조건은 연산되지 않음. (short-circuit evaluation)

let enteredDoorCode = true
let passedRetinaScan = false

if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED".

Logical OR Operator

두 값중에 하나라도 true 인 경우 true. 첫 번째 조건이 true 인 경우 두 번째 조건은 연산되지 않음 (short-circuit evaluation)

let hasDoorKey = false
let knowsOverridePassword = true

if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"

Combining Logical Operators

여러 개의 logical operator 를 엮어서 긴 표현을 작성할 수 있음

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"
// left-associative : 여러 logical operator 는 가장 왼쪽의 subexpression 을 먼저 연산
// ((enteredDoorCode && passedRetinaScan) || hasDoorKey) || knowsOverridePassword 과 같음

Explicit Parentheses

명시적으로 괄호를 써서 읽기 쉽게 하는 것이 유용함. 항상 가독성이 간결함보다 선호됨.

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"