티스토리 뷰

Swift 공식 가이드/Swift 4

Basic Operators

찜토끼 2018. 3. 23. 19:00

Apple 제공 Swift 프로그래밍 가이드(4.2)의 Basic Operators 부분을 공부하며 정리한 글입니다. 개인적인 생각, 이해를 돕기 위한 예제도 조금 들어가있습니다.


들어가며

Swift 는 표준 C 연산자를 대부분 지원합니다.

Swift 의 연산자에는 코딩 오류를 미리 잡아주기 위한 몇 가지 특별한 점들이 있습니다. 다음은 그 예시 몇 가지입니다:

  • 할당 연산자( )는 어떤 값도 return 하지 않는다. ( if 조건문 안에서 = 대신 == 를 사용하지 않도록 )

  • 산술 연산자( +, -, *, /, % 등 )는 오버플로우를 미리 감지하여 그런 연산을 허용하지 않는다. ( 연산결과가 저장될 변수에 오버플로우 값이 할당되지 않도록 )

또한 Swift 에는 범위 연산자(range operator)인 a..<b a...b가 새롭게 추가되었습니다. 값의 범위를 표현하기 위한 shortcut으로 활용할 수 있습니다. Range를 지정할 때 유용합니다.

이 챕터에서는 일반적인 연산자만 다룹니다. 고급 연산자, 자신만의 커스텀 연산자를 정의하는 법, 커스텀 타입을 위해 일반 연산자를 적절히 구현하는 법 등은 Advanced Operators 에서 다루고 있습니다.



Teminology

Swift의 연산자에는 unary(단항), binary(이항), ternary(삼항) 세 종류가 있습니다.

  • Unary operator: single target (ex: -a). Unary prefix operator 는 타겟의 바로 앞에 붙습니다(ex: !b). Unary postfix operator 는 타겟의 바로 뒤에 붙습니다(ex: c!).

  • Binary operator: two targets (ex: 2 + 3). 타겟 두 개의 가운데에 있기 때문에 infix 라고 부릅니다.

  • Ternary operator: three targets. 스위프트에서의 삼항 연산자는 삼항 조건 연산자 (? b : c) 가 유일합니다.

Operator(연산자)가 영향을 끼치는 값들을 operand(피연산자)라고 부릅니다. 1 + 2 라는 식에서 + 기호는 binary operator 이고 1 2 는 두 개의 operand 입니다.



Assignment Operator

Assignment operator (a = b) : b의 값으로 a의 값을 초기화 또는 업데이트.

1
2
3
4
5
6
7
8
9
10
let b = 10 // initialize b
var a = 5 // initialize a
= b // update a
 
let (x, y) = (12// x = 1, y =2
 
// 주의 : 할당 연산자는 return value가 없다. 다음과 같은 구문은 compile error
if x = y {
  // not valid
}
cs


C, Objective-C 와 다르게 Swift 의 = 연산자는 어떤 값도 리턴하지 않습니다. 그래서 Swift 에서는 == 연산자(equal to operator)를 사용해야 할 조건문에 실수로 = 연산자를 사용하는 것을 방지할 수 있습니다.



Arithmetic Operators

산술연산자의 종류는 다음과 같으며 모든 Number 타입에 사용할 수 있습니다:

  • Addition (+)

  • Subtraction (-)

  • Multiplication (*)

  • Division (/)

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


스위프트의 산술 연산자는 연산결과가 오버플로우 되는 것을 허용하지 않습니다. 그래서 필히 주의해야 할 경우가 생깁니다. 컴파일 시점에서는 알 수 없지만 런타임 때 오버플로우값이 연산결과로 할당되는 경우입니다. 컴파일 시점에서 알 수 있는 오버플로우 할당은 미리 컴파일러가 체크하여 오류로 잡아줍니다. 그러나 런타임 때만 알 수 있는 오버플로우 할당의 경우에는, 아예 어플리케이션이 죽어버리고 맙니다.

오버플로우 값 저장이 필요한 경우가 있을 수도 있는데, 이럴때는 오버플로우 연산자 (ex: a &+ b)를 사용하면 됩니다. Overflow Operators 에서 다루고 있습니다.

// 덧셈 연산자로 String 을 더할 수 있다.
"hello, " + "world"  // equals "hello, world”
 
// 주의 : Character+Character, String+Character 조합은 불가능
let a:Character = "a"
let b:Character = "b"
let ab = a + b // complie error (Character+Character)
let ab2 = "a" + b // compile error (String+Character)
let ab3 = "a" + "b" // ok. (String+String)
 
let c = "c" // String Type 으로 판단
let ac = "a" + c // ok. (String+String)
cs



Remainder Operator

Swift에서의 a % ba = (b x 배수) + 나머지 에서의 나머지입니다. 즉 a % b 의 결과는로 최대한 채운 후의 나머지입니다. 따라서 가 음수일 경우에도 의 부호는 무시됩니다. (9 % 4) 와 (9 % -4) 의 결과가 동일하다는 것입니다. 왜 이렇게 되는지 살펴봅시다.


1
2
3
4
9 % 4 // 9 = (4 x 2) + 1. 따라서 1
9 % -4 // 9 = (-4 x -2) + 1. 따라서 1
-9 % 4 // -9 = (4 x -2) + -1. 따라서 -1
-9 % -4 // -9 = (-4 x 2) + -1. 따라서 -1
cs







Unary Minus Operator & Unary Plus Operator

Unary Minus Operator (-) 와 Unary Plus Operator (+) 는 숫자 값의 부호에 관여합니다.

1
2
3
4
5
let three = 3
let minusThree = -three // minusThree = -(3) = -3
let plusThree = -minusThree // plusThree = -(-3) = 3
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix = +(-6) = -6
cs


위 예제에서도 드러나듯이, 사실 Unary Plus Operator(+)는 부호를 바꾸지 못하므로 사용하나 안하나 차이가 없습니다. 그러나 코드 상에서 Unary Minus Operator(-)를 사용할 때 함께 사용하면서 코드 상의 대칭을 맞출 수 있습니다.



Compound Assignment Operators

Assignment operator(=) 와 다른 연산자를 합친 compound assignment operator 를 알아봅시다. 하나의 예로 addition assignment operator (+=) 가 있습니다.

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


+= 2 는 a = a + 2 와 같습니다. + 와 += 의 수행 시간은 동일합니다.

<Note>

Compound assignment operator 역시 아무 값을 반환하지 않습니다. let b = a += 2 와 같은 코드는 compile error 를 유발합니다.


Swift 스탠다드 라이브러리에서 제공하는 연산자들에 대한 정보를 더 얻고 싶다면 Operator Declarations 를 참조하세요.



Comparison Operators

스위프트는 C의 모든 표준 비교 연산자를 지원합니다.

  • 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)

<Note>

Swift 는 또한 identity operators (A === BA !== B) 를 제공합니다. 이 연산자는 AB의 object reference(객체 참조)가 동일한 object instance(객체 인스턴스)를 가리키고 있는지 검사할 때 사용합니다. 자세한 것은 Classes and Structures 를 참고하세요.


자세한 설명은 생략하고 예제로 알아보겠습니다. 단, 튜플 부분은 문서 외의 추가 설명도 넣었습니다.

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".
 
 
 
// tuple 의 comparison
// (1) 같은 index에 같은 타입이 있어야 비교가 가능 (또한 비교가 가능한 타입이어야 한다)
// (2) 비교하는 순서는 left to right, 한번에 한 인덱스만, 두 개의 값이 같을 경우 다음 인덱스를 비교
 
(1"zebra"< (2"apple"// 1 < 2 를 해보고 곧바로 return true
(3"apple"< (3"bird"// 첫 번째 element 값이 같았으므로 "apple" < "bird" 를 해보고 return true
(4"dog"== (4"dog"// 모든 element가 같은 것을 확인한 뒤 return true
 
// 추가설명
 
("blue"false< ("purple"true// Bool 타입으로는 크고 작음을 판단할 수 없다. compile error
("blue"false== ("purple"true// Bool 타입으로 같음을 판단할 수는 있다. return false
 
cs




Ternary Conditional Operator

Ternary Conditional Operator (항 조건 연산자)는 question ? answer1 : answer2 의 폼을 가지며, 세 부분으로 구성되는 특별한 연산자입니다.

if question {
    answer1
else {
    answer2
}
 
// 위 코드를 단축하여 표현한 것이 question ? answer1 : answer2
cs


삼항 조건 연산자의 장점은 코드를 간결하게 보이게 하고, 임시변수를 줄일 수 있다는 것입니다. 하지만 남용하거나 복합 구문 안에 삽입하는 것은 가독성을 떨어트리니 주의해야 합니다. 개인적으로는 한 줄 안에 끝날 때만, 그리고 단독으로 쓰일 때만(컨텍스트가 거기서 끝날 때만?) 사용하는 편입니다.

let contentHeight = 40
let hasHeader = true
let rowHeight: Int
if hasHeader {
    rowHeight = contentHeight + 50
else {
    rowHeight = contentHeight + 20
}
 
// 위 코드를 아래와 같이 단축할 수 있습니다
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90
cs




Nil Coalescing Operator

a ?? b

optional 변수 에 만약 값이 들어있다면 그 값을 사용하고, nil 이라면 를 사용하겠다는 연산자입니다. 풀어쓰면 a != nil ? a! : 가 됩니다. 따라서 다음 두 개가 반드시 전제됩니다.

  • 는 optional 타입

  • 의 타입은 에 저장될 수 있는 타입

이 연산자를 사용하면 optional 변수를 사용할 때 nil 체크를 하고, 언랩핑하고, nil일때의 default 값을 반환하는 등의 일련의 과정을 코드 상에서 짧고 간결하게 나타낼 수 있습니다. 실제로 코딩 시 optional 변수를 사용할 때 종종 사용하는 연산자입니다.

let defaultColorName = "red"
var userDefinedColorName: String? // defaults to nil
 
var colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse) // "red"
 
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse) //"green"
cs


<Note>

삼항 연산자에는 short-circuit evaluation 이 적용됩니다. 즉, a ?? b 에서가 nil이 아니라면 는 계산되지 않습니다. 예를 들어 a ?? (b + c) 에서 에 이미 값이 들어 있다면 (b + c) 연산은 실행되지 않습니다.




Range Operators

Swift 에는 값의 범위를 표현하는 범위 연산자가 몇 종류 있습니다.

  • Closed Range Operator(a...b) : a 이상 b 이하. (ex: 1...3 은 1,2,3)

  • Half-Open Range Operator(a..<b) : a 이상 b 미만. (ex: 1..<3 은 1,2)

  • One-Sided Ranges([a...], [..<b] 등) : 한 쪽 방향으로 갈 수 있는 만큼 가게 됨. (ex: [..<2] 는 0,1)

범위 연산자는 for 문에서 유용하게 쓰일 수 있을 것 같은데, 첫 인덱스가 1인지 0인지에 따라 골라쓰면 될 것 같습니다. 예를들어 1부터 N까지 숫자를 출력하는 for문에서는 a...b를 쓰는 것이 유용하고, 배열을 도는 for문에서는 인덱스가 0부터 count-1 까지니까 a..<b 를 쓰는 것이 유용합니다. Swift 4 에서 추가된 One-Sided Range Operator 도 경우에 따라 유용하게 사용할 수 있을 것 같네요(total count 를 미리 계산해서 범위지정 하지 않아도 되는..등등? 개발하면서 테스트해보겠습니다!).

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 는 b-a+1 번 돌게된다
 
 
let names = ["Anna""Alex""Brian""Jack"]
let count = names.count
for i in 0..<count { // 0..<4
    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..<b 는 b-a 번 돌게된다
 
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
 
// One-sided ranges can be used in other contexts, not just in subscripts.
let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true
cs



Logical Operators

다음 세 가지의 논리 연산자를 통해 Boolean logic 값인 truefalse 를 다룰 수 있습니다:

  • Logical NOT (!a)

  • Logical AND (a && b)

  • Logical OR (a || b)

자세한 설명은 생략합니다. 참고로 Swift 에서 && 와 || 는 left-associative 입니다(여러 개가 한번에 결합되어 있을 때 왼쪽부터 차례로 연산된다는 의미입니다). 따라서 순서에 상관없이 특정 연산이 먼저 이루어져야 할 때는 괄호를 사용해야 합니다. 의도를 명확히 드러내기 위해 괄호를 쓰는 것도 좋습니다.

let allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
 
 
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
else {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
 
 
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!"
cs




'Swift 공식 가이드 > Swift 4' 카테고리의 다른 글

Collection Types  (0) 2018.09.05
Strings and Characters  (0) 2018.06.20
The basics  (0) 2018.03.02
A Swift Tour  (0) 2017.10.17
Version Compatibility  (0) 2017.10.04
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함