Search

[Swift] Basic Operators

The Swift Programming Language Documents를 참고해서 정리했습니다. 여러 가지 생각들이 버무러져 있습니다.
contents
*이전 포스팅은 [Swift] The Basics 에서 보실 수 있습니다.

Basic Operators

Perform operations like assignment, arithmetic, and comparison. 할당, 산술, 비교 operation 수행
Operator는 값을 확인, 변경, 결합하는데 사용하는 특수 기호입니다.
해당 기호를 사용해서 값을 할당하거나 연산을 통해서 값을 변경하고 결합할 수 있습니다. 두 값을 비교하는 작업도 수행 가능합니다.
Operator에 대한 이해를 돕기 위해서 몇 가지 연산자를 예로 들어볼게요.
우리가 자주 사용하는 연산자 중엔 addition operator가 있습니다. addition operator는 + 기호로 나타냅니다. 우리는 해당 기호를 사용해서 두 숫자 타입의 값을 더할 수 있습니다.
또한, logical AND operator(&&)를 사용해서 두 부울 타입의 값을 결합할 수도 있죠.
아마 Operator를 다른 언어들에서 많이 접했을 겁니다.
Swift도 C같은 언어에서 이미 사용하고 있는 연산자를 지원합니다. 하지만, Swift에서는 코딩 오류를 개선하기 위해서 몇 가지 기능을 개선했습니다.
예를 들어서, Swift에선 할당 연산자(=)가 값을 반환할 수 없습니다. 이는 할당 연산자가 비교 연산자(==)와 비슷하기 때문에 발생할 수 있는 오류를 방지하기 위함입니다.
또한, Swift는 산술 연산자를 사용할 때에 overflow를 감지합니다. 저장하는 숫자 타입의 범위보다 크거나 작은 숫자가 해당 타입의 값으로 들어갔을 시에 발생할 수 있는 오류를 방지하기 위해서 overflow를 감지하고 값이 해당 상수, 변수로 할당되지 못하도록 합니다.
Swift는 C에는 없는 기능도 있습니다. 바로, Range Operator입니다.
Range Operator를 사용해서 Swift에서는 값의 범위를 나타낼 수 있습니다.
이번 포스팅에서는 Common Operators를 다룹니다. Advanced Operators도 얼른 작성해서 들고 오겠습니다.

Operators

Swift에서는 다양한 Operator를 지원해줍니다.

Assignment Operator

이런 형식의 코드를 일반적으로 많이 보셨을 겁니다.
let a = b
Swift
복사
상수 a와 b 사이에 나타나는 = 기호가 바로 Assignment Operator입니다.
Assignment Operator는 a의 값을 b의 값으로 초기화하거나 업데이트해주는 일을 합니다.
Assignment Operator는 C, Objective-C에서와는 달리 Swift에서는 값을 반환하지 않습니다. Assignment Operator(=)가 비교 연산자(==)와 비슷하기 때문에 발생할 수 있는 오류를 방지하기 위함입니다.
따라서, 아래처럼 코드를 구성하게 되면 값이 반환되지 않기 때문에 컴파일 에러가 발생합니다.
if x = y { // code }
Swift
복사

Arithmetic Operators

Swift에서는 숫자 타입에 4가지 기본 연산자를 제공해줍니다.
바로, +, -, *, / 입니다.
1 + 2 // 3 5 - 3 // 2 2 * 3 // 6 10.0 / 2.5 // 4.0
Swift
복사
+ 연산자는 String도 지원합니다.
"Arithmetic " + "Operators" // "Arithmetic Operators"
Swift
복사

Remainder Operator

Swift는 Remainder Operator를 사용해서 나머지 값을 계산합니다.
Remainder Operator는 % 기호를 사용합니다.
9 % 4 // 1
Swift
복사
나머지 계산은 아래 식을 따릅니다.
a=(bmultiplier)+remaindera = (b * multiplier) + remainder
9 % 4 의 나머지 값이 1 이 나올 수 있던 이유도 공식에 대입해보면 알 수 있습니다.
9=(42)+19 = (4 * 2) + 1
이렇게 나타낼 수 있기 때문이지요. 해당 공식은 음수일 때도 동일하게 적용됩니다. 우리가 구하는 식이 -9 % 4 라면 어떤 결과가 나올까요? -1 일겁니다.
9=(42)+(1)-9 = (4 * -2) + (-1)
이렇기 때문에, remainder 자리에 있는 -1이 나머지 값이 되는겁니다.
b 자리에 있는 숫자의 부호는 multiplier에 의해서 무시되기 때문에 결국 a % ba % -b 는 같은 나머지 값을 가집니다.

Unary Minus, Unary Plus Operator

Unary Minus, Unary Plus Operator는 -, + 기호로 나타내며, 공백없이 prefix로 사용합니다.
Minus의 경우에는 원래 가지고 있던 값에 -를 붙여서 부호를 바꿔버립니다. Plus는 + 기호를 붙여도 변경이 없습니다.
// minus let two = 2 let minusTwo = -two let plusTwo = -minusTwo // plus let three = 3 let plusThree = +3
Swift
복사
아무런 변경이 일어나지 않는데, Unary Plus Operator는 왜 필요할까요?
Plus Operator는 아무런 일도 발생시키지 않지만 음수를 나타내는 - 연산자를 사용할 때, 양수도 + 연산자를 사용해서 대칭성을 제공하는데 사용합니다.

Compound Assignment Operators

C처럼 Swift에도 Assignment Operator(=)를 다른 작업과 결합하는 복합 할당 연산자가 제공됩니다.
복합 할당 연산자는 Assignment Operator에 다른 작업 연산자가 붙는겁니다.
var a = 1 a += 2 // 3
Swift
복사
Compound Assignment Operator를 사용하면 원 연산식보다 짧게 쓸 수 있습니다. a += 2a = a + 2 를 복합 할당 연산자를 사용해서 짧게 작성한겁니다.
Compound Assignment Operator도 Assignment Operator와 동일하게 값을 반환하지 않습니다.
// a += 2가 값을 반환하지 않기 때문에 에러 발생 let b = a += 2
Swift
복사

Comparison Operators

Swift에서는 이러한 비교 연산자를 지원합니다.
Operator
Description
==
Equal to
!=
Not equal to
>
Greater than
<
Less than
>=
Greater than or equal to
<=
Less than or equal to
또한, Swift에서는 Identity Operator(===, !==)를 제공하기 때문에 두 Object가 참조하는 Object 인스턴스가 동일한지 테스트할 수 있습니다.
비교 연산자는 Boolean 타입의 값을 반환하기 때문에 Conditional statement에서 주로 사용합니다.
특히, if문에서 많이 볼 수 있어요.
let welcomeString = "Welcome" if welcomeString == "Welcome" { print("Welcome!") } else { print("There is no welcome") }
Swift
복사
비교 연산자를 사용해서 대부분의 타입들을 비교할 수 있는데, Tuple도 그 안에 포함됩니다.
Tuple가 가지고 있는 value의 수 그리고 각 value의 타입이 같다면 비교할 수 있습니다. 비교는 왼쪽에 위치한 값부터 오른쪽으로 위치한 값으로 진행되고, 각 value 비교 결과에 따라서 전체 결과가 결정됩니다.
(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"
Swift
복사
1번은 < 연산자를 사용해서 오른쪽에 있는 튜플이 큰 값이라면 true를 반환할겁니다. 해당 비교 연산자를 통해서 true 값이 나올겁니다. 왜냐하면, 첫번째 값인 1과 2의 비교에서 2가 더 크기 때문에 true가 나옵니다.
그렇다면, zebra와 apple은요?
첫 번째 조건에서 이미 만족한다면 다음 조건으로 넘어가지 않습니다. 따라서, zebra, apple의 비교는 이루어지지 않습니다. zebra가 실제로는 apple보다 큰 값인데도 말이죠.
2번도 동일한 연산자를 사용해서 비교를 진행합니다. 첫번째 숫자인 3은 같기 때문에 다음 요소를 비교해보아야 합니다. 비교해보니 apple보다 bird가 더 큰 값이라서 true를 반환합니다.
비교 연산자를 사용하기 위해서는 비교를 진행하는 타입들이 모두 비교 연산자를 사용할 수 있는 타입이어야 합니다. 만약, 하나라도 비교 연산을 진행할 수 없는 타입이 섞여 있다면 비교가 불가능해집니다.
그렇다면, 튜플에 element가 100개, 200개 있더라도 모두 비교를 진행할 수 있을까요?
아닙니다. 튜플에서 비교 연산을 진행하기 위해선 7개 미만의 element를 가져야 합니다. 그 이상의 element를 가져야 한다면 사용자가 직접 7개 이상의 연산을 할 수 있는 Operator를 만들어 주어야 합니다.

Ternary Conditional Operator

삼항 조건 연산자는 어떤 조건이 참인가, 거짓인가에 따라서 두 개의 expression 중 하나를 선택할 수 있게 해주는 연산자입니다.
let hasHeader = true let rowHeight = 500 + (hasHeader ? 100 : 50)
Swift
복사
위의 식은 hasHeader라는 조건이 참인지, 거짓인지에 따라서 참이면 100을, 거짓이면 50을 선택합니다.
해당 연산자는 if statement 를 간결하게 사용한 방식입니다. 한 줄로 나타낼 수 있기 때문에 긴 코드보다 간결하게 코드를 작성할 수 있습니다.
let hasHeader = true let rowHeight: Int if hasHeader { rowHeight = 500 + 50 } else { rowHeight = 500 + 20 }
Swift
복사
하지만, 간결함을 위해서 삼항 조건 연산자로만 코드를 작성하게 되면 과도하게 읽기 어려운 코드를 만들 수도 있습니다. 따라서, 삼항 조건 연산자를 사용할 시 여러 인스턴스를 하나의 Compound statement로 결합하지 않도록 해야 합니다.

Nil-Coalescing Operator

Nil-Coalescing Operator는 Optional Type 값 뒤에 붙는 ?? 기호를 말합니다.
var name: String? var userName = name ?? "No User"
Swift
복사
값이 있다면 ?? 기호 앞에 있는 값을 사용하고, 값이 없다면 default value인 ?? 기호 뒤에 있는 값을 사용합니다. 만약, name의 값이 non-nil인 경우에는 default value는 절대 사용되지 않습니다.
nil-coalescing은 아래의 코드를 간결하게 나타내는 방법입니다.
a != nil ? a! : b
Swift
복사

Range Operators

Swift는 값의 범위를 나타내는 연산자를 가지고 있습니다.

Closed Range Operator

Closed Range Operator(a...b)는 a에서 b까지의 범위를 정의합니다.
a와 b도 범위 안에 포함되며 a는 b보다 클 수 없습니다.
Closed Range Operator는 for-in 처럼 값을 사용할 범위를 지정할 시에 유용합니다.
for index in 0...4 { print("count! \(index)") } // count! 0 // count! 1 // count! 2 // count! 3 // count! 4
Swift
복사

Half-Open Range Operator

Closed Range Operator와 비슷하지만 한 쪽 범위의 최종값이 포함되지 않는 연산자입니다.
a..<b 라고 한다면 b는 범위에 포함되지 않습니다.
배열같은 zero-based list에서 사용하기 좋습니다. 배열은 index 0부터 element를 채우기 때문에 가지고 있는 element count의 -1한 값만큼의 index까지만 사용합니다.
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
Swift
복사

One-Sided Ranges

한 방향으로 계속되는 범위를 나타날 때는 One-Sided Range를 사용합니다.
해당 값을 나타낼 때는 양쪽에 쓰던 값 중 하나를 생략하면 됩니다.
for name in names[2...] { print(name) } // Brian // Jack
Swift
복사
해당 연산자는 loop가 도는 범위를 지정하기 위해 사용하기엔 좋지 않습니다.
만약, 끝이 나는 값만 있는 범위라면 어디서부터 루프를 시작해야 할 지 시작점이 명확하지 않습니다. 반대로, 시작하는 값만 있는 범위라면 범위가 무한히 계속되기에 명시적 종료 조건이 없다면 루프가 계속 돌 수 밖에 없습니다.
One-Sided Range를 사용해서 특정값이 해당 범위 내에 있는지에 대한 여부를 확인할 수 있습니다.
let range = ...5 range.contains(7) // false range.contains(4) // true range.contains(-1) // true
Swift
복사

Logical Operators

Boolean 타입의 값을 수정하거나 결합하기 위해서 사용합니다.
Swift는 C언어 기반의 3가지 표준 논리 연산자를 지원합니다.

Logical NOT Operator

NOT Operator(!)는 true 값은 false로, false 값은 true로 변경합니다.
prefix operator로 공백없이 붙여서 사용합니다.
아래 NOT Operator가 붙은 부분은 “if not allowed entry”라고 해석할 수 있습니다.
let allowedEntry = false if !allowedEntry { print("ACCESS DENIED") } // Prints "ACCESS DENIED"
Swift
복사
NOT Operator는 변수나 상수를 부정하기에 네이밍을 제대로 하지 않으면 이중 부정이나 혼동을 야기할 수도 있습니다. 또한, 가독성 측면에서 좋지 않을 수도 있기 때문에 네이밍을 신중하게 해야 할 필요가 있습니다.

Logical AND Operator

AND Operator(&&)는 두 Boolean 타입의 값이 모두 true여야만 true를 가집니다. 하나라도 false라면 전체 식도 false가 됩니다.
let enteredDoorCode = true let passedRetinaScan = false if enteredDoorCode && passedRetinaScan { print("Welcome!") } else { print("ACCESS DENIED") } // Prints "ACCESS DENIED"
Swift
복사
만약, passedRetinaScan 이 먼저 나왔다면, enteredDoorCode 에 대한 체크를 진행하지 않았을 겁니다. AND Operator에서 첫 번째 값이 false라면 다음 값은 보지 않고 false로 결론 내립니다.
AND Operator가 가진 특성상 첫 번째 값이 false라면 두 번째 값이 true이든 false이든 상관없이 결론은 false가 됩니다. 따라서, 두 번째 값을 확인해보지 않는겁니다. 이를 short-circuit evaluation 이라고 합니다.

Logical OR Operator

OR Operator(||)는 두 Boolean 타입의 값이 하나로도 true면 true를 가집니다.
그렇기 때문에, 첫 번째 값이 true라면, 두 번째 값이 true이든 false이든 상관없이 결론은 true가 됩니다.
let hasDoorKey = false let knowsOverridePassword = true if hasDoorKey || knowsOverridePassword { print("Welcome!") } else { print("ACCESS DENIED") } // Prints "Welcome!"
Swift
복사

Combining Logical Operators

위의 논리 연산자들은 결합하여 복합 표현식으로 만들어 사용할 수 있습니다.
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword { print("Welcome!") } else { print("ACCESS DENIED") } // Prints "Welcome!"
Swift
복사
위의 식에서는 enteredDoorCode가 있으면서 RetinaScan를 패스했거나 DoorKey를 가졌거나 Override Password를 알고 있으면 “Welcome”를 출력할 수 있습니다. 4개의 식이지만 앞에 조건은 묶을 수 있기에 결론적으로 3개의 표현식이 들어가 있다고 보시면 됩니다.
조건은 Explicit Parentheses(명시적 괄호)를 사용해서 묶을 수 있기에 위의 코드를 이렇게 변경할 수 있습니다.
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword { print("Welcome!") } else { print("ACCESS DENIED") } // Prints "Welcome!"
Swift
복사
괄호를 사용해서 표현식을 정리하게 되면 의도를 읽기 쉬워집니다. 괄호만 추가했을 뿐은데 전체적인 의도가 명확해지는 겁니다. 따라서, 의도를 명확하게 하고 싶다면 () 괄호를 사용해서 식을 묶어주는 것이 좋습니다.

Operator Declarations

Operator는 unary, binary, ternary가 있습니다.
unary
single target에서 작동합니다.
prefix operator, postfix operator가 target 바로 앞, 뒤에 나타납니다.
binary
two target에서 작동합니다.
infix operator가 두 대상 사이에서 나타납니다.
ternary
three target에서 작동합니다.
Swift 연산자 중에서 ternary는 삼항 조건 연산자(a ? b : c)만 존재합니다.
Operator에 대한 자세한 내용은 해당 Document 페이지에서 확인하실 수 있습니다.

참고 자료