본문 바로가기

Swift/기초 문법

기본 연산자 (Basic Operators)

  • 할당, 산술 그리고 비교와 같은 동작을 수행
  • 연산자: 값을 체크, 변경, 결합하기 위해 사용하는 기호를 말함
  • 이 챕터에서는 Swift의 기본 연산자에 대해 설명

 

술어 (Terminology)

  • 단항 (Unary)
    • “+a” 처럼 단일 항목에 동작
    • 단항 접두사 연산자: “!a” 처럼 항목 바로 직전에 위치
    • 단항 접미사 연산자: “c!” 처럼 항목 바로 직후에 위치
  • 이항 (Binary)
    • “2 + 3” 처럼 2개의 항목에 동작
    • 2개의 항목 사이에 위치해야 하므로 위치는 고정
  • 삼항 (Ternary)
    • 3개의 항목에 동작
    • “a ? b : c” 와 같이 사용
  • 연산자가 영향을 주는 값은 피연산자
  • “1 + 2”에서 “+”는 중위 연산자, “1”과 “2”가 바로 피연산자

 

대입 연산자 (Assignment Operator)

  • 대입연산자
    • “a = b”는 b의 값으로 초기화 또는 업데이트
let b = 10
var a = 5
a = b
// a는 10이된다.
  • 대입의 우항이 여러 개의 값이 있는 튜플이라면 튜플의 요소는 여러 개의 상수 또는 변수로 한 번에 분해 가능
let (x, y) = (1, 2)
// x = 1, y = 2
  • Swift의 대입 연산자는 값을 반환하지 않음
  • 아래 예문은 유효하지 않음
if x = y {
	// 이건 오류 
}
  • 위의 특징은 등호 연산자 (==)가 실제로 사용되어야 할 곳에 실수로 할당 연산자 (=)가 사용되는 것을 방지

 

산술 연산자 (Arithmetic Operators)

  • Swift는 모든 숫자 타입에 대해 4개의 기본 산술 연산자 제공
1 + 2       // equals 3
5 - 3       // equals 2
2 * 3       // equals 6
10.0 / 2.5  // equals 4.0
  • Swift 산술 연산자는 기본적으로 값이 오버플로우 되는 것을 허락하지 않음
  • 덧셈 연산자는 String 연결도 지원
"hello, " + "world"  // equals "hello, world"

 

나머지 연산자 (Remainder Operator)

  • 나머지 연산자 (remainder operator) (a % b)는 a 안에 들어갈 b 의 배수가 몇인지를 계산하고 남은 값 (나머지)을 반환
9 % 4    // equals 1

 

단항 뺄셈 연산자 (Unary Minus Operator)

  • 숫자 값의 부호는 - 접미사를 사용하여 변경할 수 있으며 이것을 단항 뺄셈 연산자 (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)

  • Swift는 대입 (=)과 다른 연산자를 결합한 복합 대입 연산자 (compound assignment operators) 를 제공
var a = 1
a += 2
// a is now equal to 3
  • 표현식 a += 2 는 a = a + 2 의 짧은 표현

Note 복합 대입 연산자는 값을 반환하지 않습니다. 예를 들어

let b = a += 2

로 작성할 수 없습니다.

비교 연산자 (Comparison Operators)

  • Swift는 아래의 비교 연산자 (comparison operators)를 제공
  • 같음 (a == b)
  • 다름 (a != b)
  • 보다 큼 (a > b)
  • 보다 작음 (a < b)
  • 보다 크거나 같음 (a >= b)
  • 보다 작거나 같음 (a <= b)
  • 각 비교 연산자는 구문이 true 인지 아닌지 판단하기 위해 Bool 값을 반환
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
  • 비교 연산자는 if 구문과 같은 조건 구문에서 사용되기도 합니다:
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".

삼항 조건 연산자 (Ternary Conditional Operator)

  • 삼항 조건 연산자 (ternary conditional operator) 는 question ? answer1 : answer2 형태의 3가지 부분으로 이루어진 특별한 연산자
  • question 이 참 또는 거짓인지에 따라 2개의 표현식 중 하나를 나타내는 식입니다.
  • question 이 참이라면 answer1 을 반환하고 반대면 answer2 를 반환
  • 삼항 조건 연산자는 아래의 코드를 줄여서 표현한 것
if question {
    answer1
} else {
    answer2
}
  • 테이블 열은 헤더를 가지고 있다면 콘텐츠 높이보다 50 포인트 더 커야 하고 헤더가 없다면 20 포인트 더 커야 합니다:
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90
  • 또는
let contentHeight = 40
let hasHeader = true
let rowHeight: Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}
// rowHeight is equal to 90
  • 삼항 조건 연산자는 두 표현식 중 하나를 결정하기 위한 효율적으로 간결한 표현을 제공
  • 삼항 조건 연산자 사용시에는 주의가 필요합니다. 너무 남용하면 읽기 어려운 코드가 될 수 있습니다. 삼항 조건 연산자의 여러 인스턴스를 하나의 복합 구문으로 결합하는 것을 피해야 합니다.

Nil-결합 연산자 (Nil-Coalescing Operator)

  • nil-결합 연산자 (nil-coalescing operator) (a ?? b)는 옵셔널 a 에 값이 있으면 a 를 풀거나 a 가 nil 이면 기본값 b 를 반환
  • 표현식 a 는 항상 옵셔널 타입 입니다. 표현식 b 는 a 에 저장된 타입과 같아야 합니다.
  • nil-결합 연산자는 아래 코드를 짧게 표현
a != nil ? a! : b
  • 위 코드는 삼항 조건 연산자를 사용하고 a 가 nil 이 아닐경우 a 안에 래핑된 값을 접근하기 위해 강제 언래핑 (a!) 하며 a 가 nil 일 경우 b 를 반환
  • a의 값이 nil이 아닐 경우 b는 절대 반환되지 않는데, 이를 연산 생략 (short-circuit evaluation) 이라고도 합니다.
  • 아래 예제는 기본 컬러 이름과 옵셔널 사용자가 정의한 컬러 이름 중 선택하기 위해 nil-결합 연산자를 사용합니다:
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"
  • serDefinedColorName 변수는 기본값이 nil 인 옵셔널 String 으로 정의됩니다.
  • userDefinedColorName 은 옵셔널 타입이기 때문에 값을 선택하기 위해 nil-결합 연산자를 사용할 수 있습니다.
  • 위의 예제에서 연산자는 colorNameToUse 라는 String 변수의 초기값을 결정하는데 사용됩니다.
  • userDefinedColorName 이 nil 이기 때문에 표현식userDefinedColorName ?? defaultColorName 은 defaultColorName 또는 "red" 의 값을 반환합니다.
  • userDefinedColorName 에 nil 이 아닌 값을 대입하고 nil-결합 연산자로 체크를 다시 수행하면 기본값 대신에 userDefinedColorName 에 래핑된 값을 사용합니다:
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is not nil, so colorNameToUse is set to "green"

닫힌 범위 연산자 (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)는 b 가 포함되지 않은 a 부터 b 까지의 범위 실행을 정의합니다.
  • 이것은 마지막 값은 포함되지 않지만 처음 값은 포함되므로 반-열림 (half-open) 이라 합니다.
  • 닫힌 범위 연산자와 같이 a 의 값은 b 보다 클 수 없습니다.
  • a 의 값이 b 와 같다면 결과 범위는 비어있을 것입니다.
  • 반-열림 범위는 리스트의 길이까지 순차적으로 작업하는 것이 유용한 배열과 같은 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)

  • 닫힌 범위 연산자는 한방향으로 계속되는 범위에 대한 대체 형식
  • 인덱스 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

논리 연산자 (Logical Operators)

  • 논리 연산자 (Logical operators) 는 부울 로직 값을 true 와 false 로 수정하거나 결합
    • 논리적 NOT (!a)
    • 논리적 AND (a && b)
    • 논리적 OR (a || b)

논리적 NOT 연산자 (Logical NOT Operator)

  • 논리적 NOT 연산자 (logical NOT operator) (!a)는 부울 값을 true 를 false 로 false 를 true 와 같이 반대로 만듭니다.
let allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"
  • 부울 상수와 변수 이름은 중복 부정과 논리적 상태의 혼동을 피하기 위해 읽기 쉽고 간결해야 합니다.

논리적 AND 연산자 (Logical AND Operator)

  • 논리적 AND 연산자 (logical AND operator) (a && b)는 두 값이 모두 true 여야 true 를 표현하는 논리적 표현식을 만듭니다.
  • 사실 첫번째 값이 false 이면 true 의 결과를 얻을 수 없기 때문에 두번째 값은 살펴보지 않습니다. 이러한 경우를 연산 생략 (short-circuit evaluation) 이라 합니다.
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"

논리적 OR 연산자 (Logical OR Operator)

  • 논리적 OR 연산자 (logical OR operator) (a || b)는 2개의 인접한 파이프 문자(|)로 만들어진 중위 연산자 (infix operator)입니다.
  • 두 값 중 하나라도 true 이면 표현식이 true 가 되는 논리적 표현식을 만듭니다.
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"
  • 첫번째 Bool 값 (hasDoorKey)은 false 이지만 두번째 값 (knowsOverridePassword)는 true 입니다. 하나의 값이 true 이기 때문에 표현식은 true 가 되고 접근이 허용됩니다:

논리적 연산자 결합 (Combining Logical Operators)

  • 긴 복합 표현식을 생성하기 위해 여러개의 논리적 연산자를 결합
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"
  • 이 예제는 긴 복합 표현식을 생성하기 위해 여러개의 && 와 || 연산자를 사용하였습니다. 그러나 && 와 || 연산자는 오직 2개의 값에서만 동작하므로 이것은 3개의 작은 표현식이 함께 엮어있는 형태입니다. 이 예제는 아래와 같이 읽을 수 있습니다:
  • 올바른 출입문 코드를 입력하고 망막 스캔을 통과했거나 유효한 키를 가지고 있거나 긴급 비밀번호를 알고 있을 경우에 접근이 허락됩니다.
  • enteredDoorCode, passedRetinaScan, 그리고 hasDoorKey 의 값을 기반으로 첫번째 2개의 표현식은 false 입니다. 그러나 긴급 비밀번호는 알고 있으므로 이 표현식의 결과는 true 입니다.
  • Swift 논리적 연산자 && 와 || 은 왼쪽 우선결합 (left-associative) 입니다. 그 의미는 여러개의 논리적 연산자로 이루어진 복합 표현식은 가장 왼쪽부터 판단한다는 뜻입니다.

명시적 소괄호 (Explicit Parentheses)

  • 소괄호를 포함하는 것이 영향이 없을 때 복합 표현식을 읽기 쉽게 하기위해 소괄호를 포함하는 것은 때때로 유용합니다.
  • 출입문 접근 예제에서 의도를 명확하게 하기위해 복합 표현식의 첫번째 부분을 소괄호를 추가하면 유용합니다:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"
  • 소괄호는 처음 두개의 값을 전체 논리에서 별도의 부분으로 고려되도록 해줍니다.
  • 복합 표현식의 결과는 바뀌지 않지만 전체적인 의도는 명확해 집니다.
  • 가독성은 항상 간결성보다 선호됩니다.
  • 의도를 명확하게 하는데 도움이 되는 곳에 소괄호를 사용해야 합니다.

'Swift > 기초 문법' 카테고리의 다른 글

컬렉션 타입 3편 - 딕셔너리  (0) 2024.12.11
컬렉션 타입 2편 - 집합  (0) 2024.12.11
컬렉션 타입 1편 - 배열  (0) 2024.12.10
enum 케이스 나누기  (0) 2024.12.02