공식 문서로 공부하는 Swift (1) - 기본 연산자

ci·2020년 5월 25일
1

Basic Operations

Swift에서는 통상적으로 이용하는 +, -, /, % 같은 산술연산자와 &&, || 같은 논리 연산자, 그리고 C에서 지원하지 않는 a..a…b같이 값의 범위를 지정할 수 있는 범위 연산자를 지원한다.


용어 (Terminology)

연산자에는 단항(unary), 이항(binary) 그리고 삼항(ternary) 연산자가 있다.

  • 단항 연산자-a, !b, c!와 같이 하나의 대상에 앞뒤에 바로 붙여 사용하는 연산자다.
  • 이항 연산자2 + 3 같이 두 대상 사이에 위치하는 연산자다.
  • 삼항 연산자a ? b : c 형태로, C처럼 Swift에 삼항 연산자는 이 연산자 단 하나만 존재합니다.


할당 연산자 (Assignment Operator)

할당 연산자(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.
}

이는 동등 비교 연산자(==)를 의도한 곳에 할당 연산자가 사용되는 것을 막는다.



사칙 연산자 (Arithmetic Operators)

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)

단항 음수 연산자(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)

C와 같이, Swift도 할당 연산자(=)와 다른 연산자를 합성해 +=와 같은 형태로 축약해 사용할 수 있다.

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

합성 할당 연산자는 값을 반환하지 않는다. let b = a += 2와 같은 코드는 사용할 수 없다.



비교 연산자(Comparison Operators)

Swift는 C의 모든 표준 비교 연산자를 지원한다.

  • 같다 (a == b)
  • 같지 않다 (a != b)
  • 크다 (a > b)
  • 작다 (a < b)
  • 크거나 같다 (a >= b)
  • 작거나 같다 (a <= b)

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)

삼항 조건 연산자(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 병합 연산자 (Nil-Coalescing Operator)

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"


범위 연산자 (Range Operators)

닫힌 범위 연산자 (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보다 클 수 없다. 만약 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

단 방향 범위 (One-Sided Ranges)

[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


논리 연산자 (Logical Operators)

Swift는 다음 세 가지 논리 연산자를 지원한다.

  • 논리 부정 NOT (!a)
  • 논리 곱 AND (a && b)
  • 논리 합 OR (a || b)

논리 부정 연산자 (Logical NOT Operator)

논리 부정 연산자(!a)truefalse로, falsetrue로 변환한다.

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

논리 곱 연산자 (Logical AND Operator)

논리 곱 연산자(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"

논리 합 연산자 (Logical OR Operator)

논리 합 연산자(a || b)는 둘 중 하나만 참이어도 true를 반환한다. 논리 곱 연산자와 마찬가지로 논리 곱 연산자도 short-circuit evaluation을 사용한다. 첫 번째 값이 참이라면 두 번째 값을 판단하지 않고 즉시 true를 반환한다.

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

논리 연산자의 조합 (Combining Logical Operators)

여러 개의 논리 연산자를 조합하여 사용할 수 있다.

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

논리 연산자 &&와 ||는 왼쪽에서 오른쪽 순서로 읽는다.


명시적 괄호 (Explicit Parentheses)

논리 연산자의 적용 우선 순위를 연산자에 맡기지 않고 명시적으로 괄호를 사용해 계산 순서를 지정할 수 있다.

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

이러한 방법은 가독성을 높이는 데도 도움을 준다.

0개의 댓글