공식문서로 Swift 공부하기 - Basic Operator

Basic Operator

operator(연산자)는 값을 확인, 변경 또는 결합하는데 사용하는 특별한 기호 또는 구절 이라고한다.

ex) addition operator (+), logical AND operator (&&)

Swift는 C언어에서 이미 알고 있는 operator들을 지원한다 그리고 몇몇 능력을 향상시켜 일반적인 코딩 오류를 제거했다.
(=) 연산자는 (==) 연산자와 동일한 경우에 잘못 사용되는 것을 방지하기 위해 값을 리턴하지 않는다. 산술 연산자 (+, -, *, /, %)는 값을 저장하는 타입의 허용된 값의 범위보다 크거나 작은 숫자를 사용했을 때 예기치 않은 결과를 피하기 위해 값의 오버플로우를 감지하고 허용하지 않는다. Swift는 a..<b, a...b와 같은 범위 연산자도 지원해준다.

Terminology

연산자는 unary(단항), binary(이항), ternary(삼항)이다.

  • Unary operators는 하나의 대상에 대해 연산한다. (예 : -a) Unary prefix 연산자는 대상의 바로 뒤에 나타나고 (예 : !b), unary postfix 연산자는 대상의 뒤에 나타난다.(예 : c!)

  • Binary operators는 두 개의 대상에 대해 연산한다. (예 : 2 + 3) 그리고 두개의 대상 사이에 타나난다.

  • Ternary operators는 C언어와 같이 세 개의 대상에 대해 연산한다. (a ? b : c -> a가 참이면 b, 거짓이면 c)

연산자가 여향을 미치는 값은 operands(피연산자) 이다. (1 + 2 에서 +는 연산자, 값 1, 2는 operands(피연산자))

Assignment Operator

Assignment operator (a = b)는 a의 값을 b의 값으로 업데이트 하거나 초기화 한다.

let b = 10
var a = 5
a = b
// a와 b는 같아졌다.

만약 오른쪽의 assignment가 여러값인 튜플 이라면 한번에 여러개의 상수 또는 변수로 분해할 수 있다.

let (x, y) = (1, 2)
print(x)
print(y)
// x = 1, y = 2 가 된다.

Swift에서 assignment operator (=)는 자신의 값을 리턴하지 않음 따라서 아래 코드는 에러가 난다.

if x = y {
    print("yes")
    // 에러 발생
}

(==) 연산자를 사용해야 하는데 (=)가 실수로 사용되는 것을 방지하기위함

Arithmetic Operators

Swfit는 모든 숫자 타입에 4가지 기본 arithmetic operators를 제공한다.

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
print(1 + 2) // = 3
print(5 - 3) // = 2
print(2 * 3) // = 6
print(10.0 / 2.5) // = 4.0

Swift의 arithmetic operators는 기본적으로 값이 오버플로우 하는것을 허용하지 않음

Addition operator는 문자열을 연결하는것 또한 지원해줌!

print("안녕" + "하세요")
// = "안녕하세요"

Remainder Operator

Remainder operator (a % b) b의 배수가 a에 얼마나 들어갈지를 계산하고 남은 값을 반환한다. (나눗셈 연산 후 나머지를 반환한다고 생각하면 됨)

그림처럼 9를 4로 나누고 나머지는 1 이다.

print(9 % 4) // = 1

a = (b x some multiplier) + remainder
some multiplier은 a 이하의 값중 b의 가장 큰 배수이다.

위 식을 이용하여 아래의 코드를 동작시키면

print(-9 % 4) // = -1

-9 = (4 x -2) -1
나머지 -1을 출력한다.

a % b에서 b의 부호는 무시되기 때문에 a % b 와 a % -b는 항상 같은 출력값을 가진다.

Unary Minus Operator

숫자 값의 부호는 -(unary minus operator)를 붙여서 전환할 수 있다.

let three = 3
let minusThree = -three // = -3
let plusThree = -minusThree // = 3
print(minusThree)
print(plusThree)

-(unary minus operator)는 값의 바로 뒤에 공백없이 사용해야한다.

Unary Plus Operator

+(unary plus operator)는 변화없이 값을 리턴한다.

let minusSix = -6
let alsoMinusSix = +minusSix // = -6
print(alsoMinusSix)

+연산자는 아무런 동작을 하지 않지만, -연산자를 사용할 때 대칭하는 코드를 보여줄 때 사용된다.

Compound Assignment Operators

Swift에서도 C언어에서 제공하는 compound assignment operators( =와 다른 연산자를 결합하는 형태)를 제공한다.

var a = 1
a += 2 // a = 3, a = a + 2를 축약한 코드
print(a)

위 코드에서 a += 2는 a = a + 2를 축약한 형태로 동일하게 동작한다.

NOTE
Compound assignment operators는 값을 리턴 하지 않으므로 let b = a += 2와 같은 코드는 사용할 수 없다.

Comparison Operators

Swift가 지원하는 comparison operators

  • 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는 두개의 object reference가 같은 object instance를 참조하는지를 나타내는두개의 identity operators (===, !==)또한 제공한다.  (https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html#ID90)

Comparison operators는 Bool값을 리턴함

print(1 == 1) // true
print(2 != 1) // true
print(2 > 1) // true
print(1 < 2) // true
print(1 >= 1) // true
print(2 <= 1) // false

Comparison operators는 조건문에서 자주 사용된다.

let name = "World"

if name == "World" {
    print("hello, world")
} else {
    print("I'm sorry \(name), but I don't recognize you")
}
// name은 "World"이기 때문에 "hello, world"가 출력된다.

두개의 튜플이 같은 타입이고 같은 숫자의 값이면 두개의 튜플을 비교할 수 있다. 튜플은 동일하지 않은 두값이 발견될 때까지 왼쪽에서 오른쪽으로 한번에 하나씩 값이 비교된다.

print((1, "zebra") < (2, "apple")) // true
print((3, "apple") < (3, "bird")) // true
print((4, "dog") == (4, "dog")) // true

위 코드에서 1번 줄 같은경우 1이 2보다 작기 때문에 “zebra”가 “apple”보다 작은 것은 중요하지 않고 true를 출력한다. 비교는 이미 튜플의 첫번 째 요소에서 결정되기 때문이다. 만약 첫 번째 요소가 동일한 경우 두 번째 요소가 비교된다. (2, 3번째 줄 참고)

튜플은 튜플안의 값들의 타입이 연산자를 적용할 수 있을 때만 비교할 수 있음 예를 들어 두개의 튜플 (String, Bool)의 경우 Bool 타입에 <연산자를 적용할 수 없으므로 비교가 되지 않는다.

print(("blue", false) < ("purple", true)) // Error
NOTE
Swift 표준 라이브러리에는 요소가 7개 미만인 튜플에 대한 비교연산자가 포함되어 있다. 그 이상의 요소인 튜플을 비교하려면 직접 구현해야한다.

Ternary Conditional Operator

Ternary conditional operator는 3개의 파트로 구성된 특별한 연산자이다.
question ? answer1 : answer2 형태로 되어있고 qusetion이 true이면 answer1을 false이면 answer2를 리턴하는 연산자이다.

let contentHeight = 40
let hasHeader = true
let rowHeight: Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}

Ternary conditional operator를 사용하면 위의 코드를 아래와 같이 요약할 수 있다.

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20) // = 90

더 간결하게 코드를 작성할 수 있다!!
너무 남발하면 코드를 읽기 어려워질수 있기 때문에 주의 해야한다.

Nil-Coalescing Operator

Nil-coalescing operator(a ?? b)는 옵셔널 a를 언랩한다. a가 값을 가지고 있다면 a를 리턴하고 nil이라면 b를 리턴한다. a는 옵셔널 타입이어야 하고 b는 a와 같은 타입이어야한다.

Nil-coalescing operator는 아래 코드의 축약형이다.

a != nil ? a! : b

위의 코드는 삼항 연산자와 forced unwrapping을 사용하여 a가 nil이 아닐때 a!를 반환하고 그렇지 않을 경우는 b를 반환하는데 Nil-coalescing operator(??)를 사용하면 간결하고 읽기 쉬운 형식으로 unwrapping을 할 수 있는 우아한(?) 방법을 제공한다.

NOTE
만약 a의 값이 nil이 아닐 경우 b값은 evaluated(평가)되지 않음 (이를 short-circuit evaluation(단락 평가?)라고 한다)
let defaultColorName = "red"
var userDefinedColorName: String?

var colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse)
// userDefinedColorName이 nil이기 때문에 defaultColorName을 리턴한다.

userDefinedColorName에 non-nil값을 할당하면 userDefinedColorName이 리턴된다.

let defaultColorName = "red"
var userDefinedColorName: String? = "green"

var colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse)
// userDefinedColorName이 non-nil이기 때문에 userDefinedColorName을 리턴한다.

Range Operators

Swift는 값의 범위를 축약하여 표현하는 range operators를 제공한다.

Closed Range Operator

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

Half-open range operator (a..<b)는 a에서 b까지 실행되는 범위를 정의하지만 b를 포함하지 않는다. a의 값은 b보다 크면 안되고 만약 a와 b의 값이 같다면 범위는 비어있다.

Half-open range operator는 zero-based list(index가 0부터 시작하는 배열을 의미하는것 같음)에서 작업할 때 편리하다.

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

One-sided ranges([...2], [2...])는 입력된 인덱스 에서 배열 끝에 이르는 배열의 모든 요소를 포함하는 범위이다. 이 경우 범위 연산자의 한쪽에서 값을 생략할 수 있다. 연산자가 한쪽에만 값을 가지기 때문에 이러한 범위를 one-sided range라고 한다.

for name in names[2...] {
    print(name)
}
//Brian
//Jack

for name in names[...2] {
    print(name)
}
//Anna
//Alex
//Brian

Closed range operator의 대체 형식이라고 한다.

Half-open range operator 또한 최종 값만 사용하여 쓴 one-sided form을 가진다. 양쪽에 값을 포함할 때와 마찬가지로 최종 값은 범위의 일보가 아니다.

for name in names[..<2] {
    print(name)
}
// Anna
// Alex

One-sided ranges는 다른 contexts에서도 사용이 가능하다.(subscripts에서는 사용 불가)

let range = ...5
print(range.contains(7))
print(range.contains(5))
print(type(of: range))
//false
//true
//PartialRangeThrough<Int>

첫 번째 값이 생략되면 반복할 수 없고 최종값이 생략되면 반복할 수 있지만 무한 루프이므로 종료 조건을 추가해 줘야 한다. 단측 범위에 특정 값이 포함되어 있는지도 확인할 수 있다.

Logical Operators

Swift는 3가지 logical operators를 지원한다. (C언어 기반)

  1. Logical NOT (!a)
  2. Logical AND (a && b)
  3. Logical OR (a || b)

Logical NOT Operator

Logical NOT Operator(!a)는 Bool값을 true이면 false로 false이면 true로 변환해준다.

Logical NOT Operator(!a)는 prefix(접두사) operator이고 값의 바로 뒤에 공백없이 사용한다. not a라고 읽을 수 있다.

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

위 코드는 "if not allowed entry"로 읽을 수 있고 allowedEntry가 false일때만 if 문이 동작한다.

위 예시와 같이 Bool 상수 와 변수 이름을 신중하게 선택하면 이중 부정 또는 복잡한 논리문을 피하고 코드를 읽기 쉽고 간결하게 유지할 수 있다.

Logical AND Operator

The logical AND operator(a && b)는 두 값이 반드시 true일때만 표현식 전체가 참이된다. 어느 하나의 값이 false일 경우 식 전체도 false가 된다. 실제로 첫 번째 값이 false일 경우 두 번째 값은 평가되지 않는다. (이 값은 전체 식을 true로 만들 수 없기 때문임 -> short-circuit evaluation)

let enterDoorCode = true
let passedRetinaScan = false

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

두 상수가 true 일때만 "Welcome!"를 출력한다.

Logical OR Operator

Logical or operator(a || b)는 두 값 중 하나만 참이면 전체 식이 참인 논리식을 생성할 수 있다.

AND 연산자 처럼 OR 연산자 또한 short-circuit evaluation를 하는데 만약 논리식의 왼쪽값이 true이면 오른쪽 값은 평가되지 않는다.

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

hasDoorKey가 false이지만 knowsOverridePassword가 true이므로 논리식은 true가 된다.

Combining Logical Operators

여러개의 logical operators를 결합하여 표현식을 만들 수 있다.

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

위 코드에서 &&, || 연산자를 사용하여 긴 복합 표현식을 만들었지만 && 와 ||는 여전히 두개의 값에 대해서 연산을 한다. 따라서 이 표현식은 세개의 작은 표현식이 결합된 형태이다.

왼쪽에서 부터 먼저 평가를 시작한다. 첫 번째 표현식은 false이지만 뒤 쪽 표현식에 의해 전체 표현식은 true 가된다.

Explicit Parentheses (명시적 괄호)

복잡한 표현의 의도를 읽기 쉽게 하기 위해 괄호를 넣는 것이 유용할 수 있다. 위의 door access 예제에서 첫 번째 파트에 괄호를 추가하여 의도를 명확히 할 수 있다.

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

복합 논리식의 출력은 변하지 않지만 의도를 독자에게 더 명확히 할 수 있다. (간결함 보다는 가독성을 항상 선호!!)
앞의 두 값이 한 묶음이라는 것을 명확하게 보여줄 수 있다는 의미 같음

출처 : the swift programming language
swift 5.6

좋은 웹페이지 즐겨찾기