Swift-Language Guide 5.7 / Basic Operators (야매 번역 + 정리)

Newon·2022년 6월 22일
0

Swift-Language Guide 5.7

목록 보기
1/7
post-thumbnail

초록

연산자는 다음과 같이 값을 확인하거나 변화, 합치기 위해 사용되는 특별한 상징이나 구문을 의미합니다.

let i = 1 + 2
if enteredDoorCode && passedRetinaScan

Swift 의 연산자들은 비정상적인 결과값을 갖지 않도록 연산의 결과가 오버플로우 하는지를 감지하는데, 오버플로우 행동과 관련된 연산자를 활용하고 싶다면 Overflow Operators 를 확인해주세요.

Swift 는 C 언어에서는 제공되지 않았던 a..<ba...b 와 같은 줄임표현도 제공합니다. 더 많은 연산자들을 확인하고 싶다면 Advanced Operators 를 확인해주세요.



Terminology (용어)

연산자는 크게 단항 (unary), 이항 (binary), 삼항 (ternary) 으로 구분할 수 있습니다.

  • 단항 연산자는 -a 와 같이 1개의 목표 대상을 지닌 연산자를 의미하며, 접두연산자 prefix, 앞에 붙는 연산자, !a 와 접미연산자 postfix, 뒤에 붙는 연산자, a! 로 구분할 수 있습니다.
  • 이항 연산자는 2 + 3 과 같이 2개의 목표 대상을 지닌 연산자를 의미하며 중위 연산자 (infix) 라고도 불립니다.
  • 삼항 연산자는 3개의 목표 대상을 지닌 연산자로, Swift 에서는 딱 1개 , 조건부 연산자 (conditional operator) 만 있습니다.
    a ? b : c

목표 대상은 피연산자 (operand) 로 지칭합니다.
1 + 2 에서 + 는 이항 연산자, 중위 연산자 (infix) 이며 12 는 피연산자 (operand) 입니다.



Assignment Operator (할당 연산자)

할당 연산자 (a = b) 는 값을 초기화하거나 새롭게 할당할 때 사용합니다.

let b = 10
var a = 5
a = b
// a 의 값은 이제 10 입니다.

만약 오른쪽의 값이 튜플과 같이 여러개의 값을 갖고 있다면 한번에 나누어서 값을 할당할 수 있습니다.

let (x,y) = (1,2)
// x 는 1 이며, y 는 이제 2 입니다.

C 언어와 다르게 Swift 의 할당연산자 = 는 스스로 값을 리턴하지 않습니다. 따라서 다음과 같은 구문은 사용할 수 없습니다.

if x = y {
   code ....
   code ....
} 


Arithmetic Operators (산술연산자)

  • 더하기 + , ex) 1 + 2
    더하기는 String 타입에서도 사용할 수 있습니다.
    ex) "Hello", + "World!"

  • 빼기 - , ex) 5 - 3

  • 곱하기 * , ex) 2 * 3

  • 나누기 / , 10.0 / 2.5


나머지 연산자 (remainder)

나머지 연산자 a % b 는 b 가 a에 근접하도록 최대한의 곱셈을 해준 후, 남은 값을 반환하는 연산자입니다.

다른 언어에서는 나머지 연산자를 "modulo" 연산자로 알려져있습니다, 만 
Swift 의 나머지 연산자는 음의 나머지 값을 반환하므로, 
엄밀히 말해서, "remainder" 연산자라고 부르는 것이 맞습니다.

번역 : 
a = -9, b = 4 일 때, 

% 를 modulo 연산을 하게 되면
4 * 3 을 한 후 남은 3이 나머지 값이 되지만

% 를 remainder 로 계산하게 되면
4 * 2 를 한 후 남은 -1 이 나머지 값이 됩니다.

Swift 는 % 계산을 하면 -1 이 남으므로 
용어는 remainder 가 맞다라고 "엄밀히" 말하고 있습니다.

단항 빼기 연산자 (Unary Minus Operator)

정수는 접두연산 - 를 사용해서 양의 값을 음으로 바꿀 수 있습니다.

let three = 3
let minusThree = -three        // minusThree == -3
let plusThree = -minusThree    // plusThree == 3

이처럼 빼기 - 를 값의 바로 앞에 붙임으로써 해당 값이 연산되기 이전에 값을 바꾸도록 사용할 수 있습니다.

단항 더하기 연산자 (Unary Plus Operator)

더하기도 똑같이 할 수 있습니다. 만 아무런 영향도 미치지 않습니다.



Compound Assignment Operators(복합연산자)

C 언어처럼 Swift 는 = 과 다른 연산자를 합친 복합 연산자를 지원합니다.

var a = 1
a += 2

Note : 단 복합연산자는 값을 리턴하지 않습니다. 따라서 다음과 같은 구문은 사용할 수 없습니다.

let b = a += 2

Swift standard library 가 제공하는 연산자에 대한 정보를 확인하고 싶으시다면 Operator Declarations 를 확인해주세요.



Comparison Operators(비교 연산자)

Swift 는 다음과 같은 비교 연산을 지원합니다.

  • 동일하다 : a == b
  • 동일하지 않다 : a != b
  • 크다 : a > b
  • 작다 : a < b
  • 크거나 같다 : a >= b
  • 작거나 같다 : a <= b

비교 연산자는 if 구문에서 자주 사용됩니다. if 구문에 대해 더 알고 싶다면 Control Flow 를 확인해주세요.

비교 연산자는 같은 자료형과 같은 갯수를 가진 튜플(tuple) 에도 사용할 수 있습니다. 튜플을 비교할 때는 왼쪽에서 오른쪽으로, 한번에 한번씩만 비교하며 두 값이 다를 때 까지만 진행됩니다.

(1, "zebra") < (2, "apple")
// true, 1이 2보다 작기 때문입니다. zebra 와 apple 은 비교되지 않습니다.

(3, "apple") < (3, "bird")
// ture, 3과 3이 같고 apple 이 bird 보다 작기 때문입니다.
// 번역 : String 은 길이가 아닌 서로의 앞 글자부터 아스키코드 값을 비교합니다.

(4, "dog") == (4, "dog")
// true, 4과 4가 같고 "dog" 가 "dog" 로 같기 때문입니다. 

위의 예시와 같이 비교 연은 왼쪽에서 오른쪽으로 진행되는 것을 확인할 수 있습니다. 첫번째 예시를 보면 "zebra" 와 "apple" 이 비교되지 않는 것을 확인할 수 있는데, 비교 연산이 이미 첫번째로 비교한 1 2 비교에서 끝났기 때문입니다. 만약 서로의 첫번째 원소가 같다면 두번째 원소로 이동하여 서로를 비교하게 됩니다.

튜플끼리의 비교는 각 튜플 원소들의 값을 비교할 수 있을 때만 적용할 수 있습니다. 예를 들어 아래의 예시와 같이 (String, Int) 튜플은 비교할 수 있지만 (String, Bool) 은 비교할 수 없습니다. Bool 은 <, >, ==로 비교할 수 없기 때문입니다.

("blue", -1) < ("purple", 1)  // 비교 가능하며 true 입니다.
("blue", false) < ("purple", true) // 비교 자체가 불가능합니다.

Note: Swift standard library 에서 튜플은 7개 미만의 원소만 비교할 수 있습니다. 7개 이상의 원소를 포함한 튜플을 비교하고 싶다면 직접 비교 연산을 적용시켜야 합니다.



Ternary Conditional Operator (삼항 연산자)

삼항 연산자는 question ? answer1 : answer2 , 3 부분으로 이루어진 특별한 연산을 수행합니다. questiontrue 라면 answer1 을, false 라면 answer2 를 리턴합니다.

삼항 연산자는 다음의 줄임 표현입니다.

question? answer1 : answer2

if question {
	answer1
} else {
	answer2
}

침대의 가로길이를 맞추려고 할 때, 침대가 머리맡 선반이 있다면 50을, 없다면 20을 주고 싶은 상황이라면 다음과 같이 코드를 작성할 수 있습니다.

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

-----------------------------------------------------

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

삼항연산자는 효율적으로 표현을 줄일 수 있습니다. 하지만 남용하면 지나친 간결성이 코드의 가독성을 저해하므로 여러개의 상황을 결합하여 삼항 연산자를 사용하지 않도록 합니다.



Nil-Coalescing Operator(닐-병합 연산자)

닐 병합연산자 a ?? b (이하 병합연산자) 는 옵셔널(optional) 을 꺼내 풀어서 값을 갖고 있다면 (a 가 nil 이 아니라면) 그 값을, 값이 nil 이라면 기본 값인 b 를 리턴하는 연산을 의미합니다. 이때 a 는 항상 옵셔널(optional) 자료형이어야 하며, b 는 항상 a 의 자료형과 일치해야 합니다.

병합연산자는 다음의 줄임 표현이라고 할 수 있습니다.

a != nil ? a! b

이 코드는 삼항 연산자를 통해 a! 를 수행하고, 만약 a 의 값이 nil 이라면 b 를 리턴하고 있습니다.

Note: 만약 a 가 옵셔널 자료형이 아니라면 b 는 수행되지 않습니다. short-circuited 에 준하는 내용입니다.

병합 연산자의 예시로, 기본색과 유저가 정한 색을 고르는 상황입니다.

let defaultColorName = "red"
var userDefinedColorName: String? // nil 이 기본값입니다.

var colorNameToUse = uerDefinedColorName ?? defaultColorName
// userDefinedColorName 이 nil 이라면 
// colorNameToUse 에는 defaultColorName 이 할당됩니다.

userDefinedColorName 변수는 옵셔널 String 으로 정의되어 있기에, 병합연산자를 통해서 값을 정해줄 수 있습니다.

만약 userDefinedColorName 이 nil 이 아니라면 defaultColorName 대신 userDefinedColorName 이 사용됩니다.

userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName 이 nil 이 아니기때문에, colorNameToUse 는 "green" 으로 할당됩니다.

Range Operators(범위 연산자)

Swift 는 범위를 짧게 표현할 수 있는 여러 범위 연산자가 있습니다.



Closed Range Operator(닫힌 범위 연산자)

닫힌 범위 연산자는 (a...b) 로 a 부터 b 까지 범위에 a 와 b 를 모두 함하는 연산을 의미합니다. 이때 a 는 반드시 b 보다 작아야합니다.

닫힌 범위 연산자는 for ... - in ... 반복문처럼 모든 값을 확인하고 싶을 때 유용합니다.

for index in 1...5 {
	print("\(index) 곱하기 5 는 \(index * 5)")
}
// 1 곱하기 5 는 5
// 2 곱하기 5 는 10
// 3 곱하기 5 는 15
// 4 곱하기 5 는 20
// 5 곱하기 5 는 25

더 자세한 for-in 반복문은 Control Flow 를 확인해주세요.


Half-Open Range Operator(반열림 범위 연산자)

반열림 범위 연산자 (a..<b) 는 a 부터 b 까지의 범위 중 b 를 포함하지 않는 연산을 의미합니다. 반열림의 의미는 처음의 값은 포함하지만 마지막을 포함하지 않기 때문입니다. 닫힘 범위 연산자가 그러했듯 ab 보다 작아야합니다. 만약 ab 가 같다면 해당 범위 연산자는 빈 값을 리턴합니다.

반열림 범위 연산자는 특히 0을 기준으로한 배열과 함께 사용할 때 유용합니다.

let names = ["안나", "알렉스", "브라이언", "뉴원"]
let count = names.count
for i in 0..<count {
	print("사람\(i+1)\(naems[i])라고 불립니다.")
}
// 사람1 안나라고 불립니다.
// 사람2 알렉스라고 불립니다.
// 사람3 브라이언라고 불립니다.
// 사람4 뉴원라고 불립니다.

위에서 반열림 범위 연산자는 배열이 4개의 원소를 갖고 있지만, 0..<count 가 3, 배열의 마지막 인덱스, 까지만 호출하고 있습니다. 배열에 대해 더 자세히 알고 싶다면 Arrays를 참고해주세요.


One-Sided Ranges(한방향 범위 연산자)

닫힌 범위 연산자는 한 방향으로 계속해서 반복하는 형태의 연산자를 가질 수 있습니다. 이를테면 범위는 2부터 배열의 끝까지 가도록 할 수 있습니다. 이때 특정 값을 범위 연산자로부터 꺼내 사용할 수 있게됩니다. 이런 종류의 연산자를 한방향 범위 연산자(One-Sided Ranges) 라고 합니다. 연산자가 한쪽 방향에만 있기 때문에 이러한 이름이 붙게 되었습니다.

for name in names[2...] {
	print(name)
}
// 브라이언
// 뉴원

for name in names[...2] {
	print(name)
}
// 안나
// 알렉스
// 브라이언

반열림 범위 연산자 역시 위와 동일한 맥락에서 사용할 수 있습니다.

for name in names[..<2] {
	print(name)
}
// 안나
// 알렉스

한방향 범위 연산자는 for-in 구문에서만 사용할 수 있는 것이 아닌, 다른 상황에서도 사용할 수 있습니다. 하지만 이때 한방향 범위 연산자는 범위가 정해져있지 않는 연산자에게서 값을 지정할 수 없게됩니다. 범위가 정해져있지 않기에 그 값이 명확하지 않기 때문입니다.

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

Logical Operators(논리 연산자)

논리 연산자는 Boolean 자료형의 논리 값을 true 나 false 로 수정하거나 병합하는 연산자를 의미합니다. Swift 는 C 언어 바탕의 3개의 논리 연산자를 제공합니다.

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


NOT 연산자

NOT 연산자, 부정 연산자 !a 는 Boolean 자료형의 값을 뒤집는 것으로 truefalse 로, falsetrue 로 전환되는 것을 의미합니다.

부정 연산자는 접미 연산자로, 해당 값이 연산되기 이전에 나타나며 "a 가 아니다 (not a)" 로 읽을 수 있습니다.

let allowedEntry = false
if !allowedEntry {
	print("ACCESS DENIED")
}
// "ACCESS DENIED" 가 출력됩니다.

부정 연산자를 활용함으로써 코드의 가독성과 간결성을 유지할 수 있으며, 부정형을 두번 사용하거나 혼란스러운 논리 기재를 피할 수 있습니다.


AND 연산자

AND 연산자, 논리곱 연산자 a && b 는 두 값이 모두 true 임을 통해 전체 표현또한 true 임을 나타내는 연산자입니다.

만약 두 값이 false 라면 전체 표현 역시 false 가 됩니다. 이때, 사실 첫번째 값이 false 라면 두번째 값은 계산조차 되지 않는데 왜냐하면 이미 전체 표현식은 true 가 될 수 없기 때문입니다.

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
	print("Welcome!")
} else {
	print()"ACCESS DENIED
}
// "ACCESS DENIED" 가 출력됩니다.

OR 연산자

OR 연산자, 논리합 연산자 a || b 는 중위 연산자로 파이프 모양의 Character 가 2개 있는 것으로 만들 수 있습니다. OR 연산자는 둘 중 하나의 값이라도 true 라면 전체 표현 역시 true 임을 나타내는 연산자입니다.

OR 연산자도 AND 연산자와 마찬가지로, 첫번째 값이 true 라면 두번째 값부터는 계산조차 되지 않는데 왜냐하면 이미 전체 표현식은 false 가 될 수 없기 때문입니다.

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
	print("Welcome!")
} else {
	 print("ACCESS DENIED")
}
// "Welcome" 이 출력됩니다.

논리 연산자 조합하기

논리 연산자들을 여러개 사용하여 더욱 길고, 조합된 표현식을 사용할 수도 있습니다.

if enteredDoorCode && passRetinaScan || hasDoorKey || knowsOverridePassword {
	print("Welcome!")
} else {
	print("ACCESS DENIED")
}
// "Welcome" 이 출력됩니다.

위의 코드는 길어보이지만 3개의 논리 연산을 진행하고 있습니다.
enteredDoorCode 와 passRetinaScan 가 true 인지,
hasDoorKey 가 true 인지
knowsOverridePassword 가 true 인지

입니다.

Note: Swift 의 논리연산자는 왼쪽이 우선순위에 있습니다. 즉, 다수의 논리 연산자를 사용하더라도, 내부에서 나뉘더라도 왼쪽부터 논리 연산을 진행합니다.


괄호를 통해 명백하게 하기 (Explicit Parentheses)

위의 코드에서 괄호를 통해 코드를 명백하게 할 수 있습니다.

if (enteredDoorCode && passRetinaScan) || hasDoorKey || knowsOverridePassword {
	print("Welcome!")
} else {
	print("ACCESS DENIED")
}
// "Welcome" 이 출력됩니다.

괄호가 연산에 영향을 미치지는 않습니만, 코드의 가독성을 위해 활용할 수 있습니다.

profile
나만 고양이 없어

0개의 댓글