Merge changes from master into seanmoon

seanmoon authored
revision b622fa97999a2d9497c0529c42cbbe80e1b158c1
About
# Apple Swift Programming Language translation for KOREAN
**“Apple Inc. Copyright © 2014 Apple Inc. All rights reserved.”**
This is a [The Swift Programming Language](https://developer.apple.com/swift/) guide documentation translation project.

_This project is **never used for commercial purposes**.
By translating "The Swift Programming Language" we want to help a lot of korean learners who may otherwise struggle to understand it._

> 이 프로젝트는 애플의 새로운 프로그래밍 언어 **swift** 번역 프로젝트입니다. 자유롭게 참여하세요 =)
**이 번역 프로젝트는 절대로 상업적인 목적으로 사용되지 않습니다.**

## Original Contents
- [Download “The Swift Programming Language” from the iBooks Store](https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11)
- [The Swift Programming Language 웹 사이트](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/)

## Let's translate it!
- 누가 어떤 챕터를 번역하고 있을까..? 저도 참여할 수 있을까요? - [번역작업 할당 현황](https://www.penflip.com/jjuakim/swift-korean/discussions/35)
- 번역을 시작하기전에 그리고 submit 하기 전에 꼭 읽어주세요! - [번역 가이드](https://www.penflip.com/jjuakim/swift-korean/discussions/36)
- 이러한 단어는 어떻게 번역해야 할까요? - [Dictionary](https://www.penflip.com/jjuakim/swift-korean/discussions/27)
chapter1
# 01 Swift에 대해서 (About Swift)
> Translator : 이름 (메일주소FlashMaestro (masterofflash@nate.com)

Swift는 C언어 호환성에 대한 제약없이 C언어 그리고 Objective-C언어 중 최고의 것들을 기반으로 iOS와 OS X 앱을 개발하기 위한 언어입니다. Swift는 안전한 프로그래밍 패턴을 채용했고 프로그래밍을 더욱 쉽고 유연하고 재미있게 만들어주는 최신 특징들을 더했습니다. 성숙하고 많은 사랑을 받고 있는 코코아, 코코아 터치 프레임워크를 기반으로한 Swift의 이런 훌륭함은 소프트웨어 개발 방법에 대한 새로운 상상의 기회입니다.

Swift는 몇년에 걸쳐 만들어져 왔습니다. 애플은 Swift를 위한 현존하는 진보한 컴파일러, 디버거, 프레임워크 기반의 토대를 만들었습니다. 우리는 자동 레퍼런스 계수( ARC)로 메모리 관리를 단순화 했습니다. Foundation(Apple Foundation Framework)과 코코아의 견고한 기초를 기반으로 만들어진 우리의 프레임워크 스텍은 최신화와 표준화의 결과물입니다. Objective-C는 블록, 문자집합, 모듈, 혼란없는 최신 언어 기술 프레임워크 적용 가능 등을 지원하도록 발전해왔습니다. 이러한 기초작업에 감사하며 애플 소프트웨어 개발의 미래를 위한 새로운 언어를 소개합니다.

Swift는 Objective-C 개발자들에게 매우 친숙한 느낌을 줍니다. Swift가 Objective-C의 명명식 파라미터의 읽기 쉬움과 다이나믹 객체 모델의 능력을 적용했기 때문입니다. 이를 통해 끊김없는 기존 코코아 프레임워크에 대한 접근과 Objective-C와의 혼합된 상호운영을 제공합니다. 이러한 공통점을 기반으로 만들어진 Swift는 많은 새로운 특징들과 언어의 절차지향과 객체지향적 부분에 대한 통합을 도입했습니다.

Swift는 초보 프로그래머 친화적입니다. Swift는 스크립트 언어만큼이나 표현하기 쉽고 즐거운데다가 산업품질에 적합한 시스템 프로그래밍 언어입니다. Swift는 프로그래머들이 빌드하고 실행하는 낭비없이 즉기 Swift의 코드를 실험하고 결과를 볼 수 있도록하는 혁신적인 요소인 playgrounds를 지원합니다.

Swift는 폭넓은 애플 엔지니어링 문화로 부터 나온 지혜와 뜻을 같이하는 최신 언어들중 최고의 것들을 겸비하고 있습니다. 성능과 개발편리성에 대한 타협이 필요없을 만큼 컴파일러는 성능에 최적화되어 있고, 언어는 개발편리성에 최적화 되어 있습니다. Swift는 "hello, world"로부터 전체 운영체제로 확장할 수 있게 디자인 되었습니다. 이 모든것이 Swift 때문에 애플과 개발자들에게 투자할 가치가 있다고 생각하게 합니다.

Swift는 iOS와 OS X 앱을 만들고 또 계속 새로운 기능을 추가하고 개선하기 위한 환상적인 방법입니다. Swift를 향한 우리의 목표는 야심찹니다. 우리는 당신이 Swift로 무언가 만드는 것을 빨리 보고싶습니다.
chapter10
# 10 열거형 (Enumerations)
> Translator : 이름 (메일주소)

Enumerations
An enumeration defines a common type for a group of related values and enables you to
work wi th those values in a type-safe way wi thin your code.
If you are fami l iar wi th C, you wi l l know that C enumerations assign related names to a
set of integer values. Enumerations in Swi ft are much more flexible, and do not have to
provide a value for each member of the enumeration. If a value (known as a “raw” value)
i s provided for each enumeration member, the value can be a string, a character, or a
value of any integer or floating-point type.
Al ternatively, enumeration members can speci fy associated values of any type to be
stored along wi th each di fferent member value, much as unions or variants do in other
languages. You can define a common set of related members as part of one enumeration,
each of whi ch has a di fferent set of values of appropriate types associated wi th i t.
Enumerations in Swi ft are fi rst-class types in thei r own right. They adopt many features
tradi tional ly supported only by classes, such as computed properties to provide addi tional
information about the enumeration’s current value, and instance methods to provide
functional i ty related to the values the enumeration represents. Enumerations can al so
define ini tial i zers to provide an ini tial member value; can be extended to expand thei r
functional i ty beyond thei r original implementation; and can conform to protocol s to
provide standard functional i ty.
For more on these capabi l i ties, see Properties, Methods, Ini tial i zation, Extensions, and
Protocol s.
Enumeration Syntax
You introduce enumerations wi th the enum keyword and place thei r enti re defini tion wi thin
a pai r of braces:
enum SomeEnumerati on {
// enumerati on defi ni ti on goes here
}
Here’s an example for the four main points of a compass:
enum CompassPoi nt {
case North
case South
case East
case West
}
The values defined in an enumeration (such as North, South, East, and West) are the member
values (or members) of that enumeration. The case keyword indi cates that a new l ine of
member values i s about to be defined.
N O T E
Unl i ke C and Objecti ve-C, Sw i ft enumerati on members are not assi gned a defaul t i nteger val ue w hen they are
created. In the CompassPoi nts exampl e above, North, South, East and West do not i mpl i ci tl y equal 0, 1, 2
and 3. Instead, the di fferent enumerati on members are ful l y- fl edged val ues i n thei r ow n ri ght, w i th an
expl i ci tl y-defi ned type of CompassPoi nt.
Mul tiple member values can appear on a single l ine, separated by commas:
enum Pl anet {
case Mercury, Venus, Earth, Mars, Jupi ter, Saturn, Uranus, Neptune
}
Each enumeration defini tion defines a brand new type. Like other types in Swi ft, thei r
names (such as CompassPoi nt and Pl anet) should start wi th a capi tal letter. Give enumeration
types singular rather than plural names, so that they read as sel f-evident:
var di recti onT oHead = CompassPoi nt.West
The type of di recti onT oHead i s inferred when i t i s ini tial i zed wi th one of the possible values of
CompassPoi nt. Once di recti onT oHead i s declared as a CompassPoi nt, you can set i t to a di fferent
CompassPoi nt value using a shorter dot syntax:
di recti onT oHead = . East
The type of di recti onT oHead i s al ready known, and so you can drop the type when setting i ts
value. Thi s makes for highly readable code when working wi th expl i ci tly-typed
enumeration values.
Matching Enumeration Values with a Switch Statement
You can match individual enumeration values wi th a sw i tch statement:
di recti onT oHead = . South
sw i tch di recti onT oHead {
case . North:
pri ntl n("Lots of pl anets have a north")
case . South:
pri ntl n("Watch out for pengui ns")
case . East:
pri ntl n("Where the sun ri ses")
case .West:
ri ntl n("Where the ski es are bl ue")
i nts "Watch out for pengui ns"
You can read thi s code as:
“Consider the value of di recti onT oHead. In the case where i t equal s . North, print "Lots of pl anets
have a north". In the case where i t equal s . South, print "Watch out for pengui ns".”
…and so on.
As described in Control Flow, a sw i tch statement must be exhaustive when considering an
enumeration’s members. If the case for .West i s omi tted, thi s code does not compi le,
because i t does not consider the complete l i st of CompassPoi nt members. Requi ring
exhaustiveness ensures that enumeration members are not accidental ly omi tted.
When i t i s not appropriate to provide a case for every enumeration member, you can
provide a defaul t case to cover any members that are not addressed expl i ci tly:
l et somePl anet = Pl anet. Earth
sw i tch somePl anet {
case . Earth:
pri ntl n("Mostl y harml ess")
defaul t:
pri ntl n("Not a safe pl ace for humans")
}
// pri nts "Mostl y harml ess"
Associated Values
The examples in the previous section show how the members of an enumeration are a
defined (and typed) value in thei r own right. You can set a constant or variable to
Pl anet. Earth, and check for thi s value later. However, i t i s sometimes useful to be able to
store associated values of other types alongside these member values. Thi s enables you
to store addi tional custom information along wi th the member value, and permi ts thi s
information to vary each time you use that member in your code.
You can define Swi ft enumerations to store associated values of any given type, and the
value types can be di fferent for each member of the enumeration i f needed.
Enumerations simi lar to these are known as di scriminated unions, tagged unions, or
variants in other programming languages.
For example, suppose an inventory tracking system needs to track products by two
di fferent types of barcode. Some products are labeled wi th 1D barcodes in UPC-A format,
whi ch uses the numbers 0 to 9. Each barcode has a “number system” digi t, fol lowed by
ten “identi fier” digi ts. These are fol lowed by a “check” digi t to veri fy that the code has
been scanned correctly:
Other products are labeled wi th 2D barcodes in QR code format, whi ch can use any ISO
8859-1 character and can encode a string up to 2,953 characters long:
It would be convenient for an inventory tracking system to be able to store UPC-A
barcodes as a tuple of three integers, and QR code barcodes as a string of any length.
In Swi ft, an enumeration to define product barcodes of ei ther type might look l ike thi s:
enum Barcode {
case UPCA(Int, Int, Int)
case QRCode(Stri ng)
}
Thi s can be read as:
“Define an enumeration type cal led Barcode, whi ch can take ei ther a value of UPCA wi th an
associated value of type (Int, Int, Int), or a value of QRCode wi th an associated value of type
Stri ng.”
Thi s defini tion does not provide any actual Int or Stri ng values—i t just defines the type of
associated values that Barcode constants and variables can store when they are equal to
Barcode. UPCA or Barcode.QRCode.
New barcodes can then be created using ei ther type:
var productBarcode = Barcode. UPCA(8, 85909_51226, 3)
Thi s example creates a new variable cal led productBarcode and assigns i t a value of
Barcode. UPCA wi th an associated tuple value of (8, 8590951226, 3). The provided “identi fier”
value has an underscore wi thin i ts integer l i teral—85909_51226—to make i t easier to read as
a barcode.
The same product can be assigned a di fferent type of barcode:
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
At thi s point, the original Barcode. UPCA and i ts integer values are replaced by the new
Barcode.QRCode and i ts string value. Constants and variables of type Barcode can store ei ther a
. UPCA or a .QRCode (together wi th thei r associated values), but they can only store one of
them at any given time.
The di fferent barcode types can be checked using a swi tch statement, as before. Thi s
time, however, the associated values can be extracted as part of the swi tch statement.
You extract each associated value as a constant (wi th the l et prefix) or a variable (wi th
the var prefix) for use wi thin the sw i tch case’s body:
sw i tch productBarcode {
case . UPCA(l et numberSystem, l et i denti fi er, l et check):
pri ntl n("UPC-A w i th val ue of \(numberSystem), \(i denti fi er), \(check). ")
case .QRCode(l et productCode):
pri ntl n("QR code w i th val ue of \(productCode). ")
}
// pri nts "QR code w i th val ue of ABCDEFGHIJKLMNOP. "
If al l of the associated values for a enumeration member are extracted as constants, or i f
al l are extracted as variables, you can place a single var or l et annotation before the
member name, for brevi ty:
sw i tch productBarcode {
case l et . UPCA(numberSystem, i denti fi er, check):
pri ntl n("UPC-A w i th val ue of \(numberSystem), \(i denti fi er), \(check). ")
case l et .QRCode(productCode):
pri ntl n("QR code w i th val ue of \(productCode). ")
}
// pri nts "QR code w i th val ue of ABCDEFGHIJKLMNOP. "
Raw Values
The barcode example in Associated Values shows how members of an enumeration can
declare that they store associated values of di fferent types. As an al ternative to
associated values, enumeration members can come prepopulated wi th defaul t values
(cal led raw values), whi ch are al l of the same type.
Here’s an example that stores raw ASCII values alongside named enumeration members:
enum ASCIIControl Character: Character {
case T ab = "\t"
case Li neFeed = "¶
"
case Carri ageReturn = "\r"
}
Here, the raw values for an enumeration cal led ASCIIControl Character are defined to be of type
Character, and are set to some of the more common ASCII control characters. Character
values are described in Strings and Characters.
Note that raw values are not the same as associated values. Raw values are set to
prepopulated values when you fi rst define the enumeration in your code, l ike the three
ASCII codes above. The raw value for a parti cular enumeration member i s always the
same. Associated values are set when you create a new constant or variable based on
one of the enumeration’s members, and can be di fferent each time you do so.
Raw values can be strings, characters, or any of the integer or floating-point number
types. Each raw value must be unique wi thin i ts enumeration declaration. When integers
are used for raw values, they auto-increment i f no value i s speci fied for some of the
enumeration members.
The enumeration below i s a refinement of the earl ier Pl anet enumeration, wi th raw integer
values to represent each planet’s order from the sun:
enum Pl anet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupi ter, Saturn, Uranus, Neptune
}
Auto-incrementation means that Pl anet. Venus has a raw value of 2, and so on.
Access the raw value of an enumeration member wi th i ts toRaw method:
l et earthsOrder = Pl anet. Earth. toRaw ()
// earthsOrder i s 3
Use an enumeration’s fromRaw method to try to find an enumeration member wi th a
parti cular raw value. Thi s example identi fies Uranus from i ts raw value of 7:
l et possi bl ePl anet = Pl anet. fromRaw (7)
// possi bl ePl anet i s of type Pl anet? and equal s Pl anet. Uranus
Not al l possible Int values wi l l find a matching planet, however. Because of thi s, the
fromRaw method returns an optional enumeration member. In the example above,
possi bl ePl anet i s of type Pl anet?, or “optional Pl anet.”
If you try to find a Planet wi th a posi tion of 9, the optional Pl anet value returned by fromRaw
wi l l be ni l :
l et posi ti onT oFi nd = 9
i f l et somePl anet = Pl anet. fromRaw (posi ti onT oFi nd) {
sw i tch somePl anet {
case . Earth:
pri ntl n("Mostl y harml ess")
defaul t:
pri ntl n("Not a safe pl ace for humans")
}
} el se {
ri ntl n("T here i sn't a pl anet at posi ti on \(posi ti onT oFi nd)")
i nts "T here i sn't a pl anet at posi ti on 9"
Thi s example uses optional binding to try to access a planet wi th a raw value of 9. The
statement i f l et somePl anet = Pl anet. fromRaw (9) retrieves an optional Pl anet, and sets somePl anet to
the contents of that optional Pl anet i f i t can be retrieved. In thi s case, i t i s not possible to
retrieve a planet wi th a posi tion of 9, and so the el se branch i s executed instead
inureyes (inureyes@gmail.com)

열거형 _(Enumeration)_ 은 관련있는 값들의 그룹에 대한 일반적인 타입을 정의하며, 이를 이용하여 코드 안에서 타입에 안전한 방법으로 작업할 수 있습니다. C에 익숙한 사용자라면, C 열거형은 관련있는 이름을 정수값의 set에 할당하는 것을 알고 있을 것입니다. Swift의 열거형은 훨씬 더 유연하며, 열거형의 각 숫자마다 반드시 값을 제공할 필요가 없습니다. 만약 ("원시(raw)" 값으로 알려진) 값이 각 열거형 번호마다 제공될 경우, 그 값들은 문자열, 글자, 어떠한 정수나 부동 소수점 타입이 될 수 있습니다.

또한, 열거형 멤버들은 각각 다른 멤버 값에 대하여 다른 언어의 union및 비슷한 기능들이 하듯 연관된 값들을 어떤 타입이든 지정할 수 있습니다. 관련있는 멤버들의 일반적인 집합을 하나의 열거형의 부분으로 정의할 수도 있으며, 각각은 그에 연관된 적당한 타입의 값들의 다양한 집합을 가질 수 있습니다.

Swift의 열거형은 열거형의 현재 값에 대한 추가적인 정보를 제공하기 위한 계산된 프로퍼티나, 열거형이 표현하는 값들과 연관된 기능들을 제공하는 인스턴스 메소드 같이 전통적으로 클래스 등에서만 지원되는 많은 기능들을 차용하였습니다. 또한 열거형은 초기 멤버 값을 제공하는 initiailizer를 제공할 수 있고, 원래 구현을 넘어서 기능을 확장할 수도 있으며, 표준 기능을 제공하기 위한 프로토콜을 따를 수 있습니다.

이러한 기능에 대한 자세한 내용은 [속성](), [메소드](), [초기화](), [확장](), 및 [프로토콜]()을 참조하십시오.


### 열거형 문법 (Enumeration Syntax)
열거형은 `enum` 키워드로 작성하며, 중괄호 안에 모든 정의를 집어넣습니다.

enum SomeEnumeration {
// enumeration definition goes here
}
Here’s an example for the four main points of a compass:

enum CompassPoint {
case North
case South
case East
case West
}

(`North`, `South`, `East` 및 `West` 같이) 열거형에 정의된 값들은 이 열거형의 멤버 값들입니다. `case` 키워드는 멤버 값들의 새 줄이 정의될 것임을 나타냅니다.

> **노트**
> C 및 Objective-C 와는 다르게, Swift의 열거형 멤버들은 생성시 기본 정수값들에 할당되지 않습니다. 위의 `CompassPoints` 예제에서 보듯, `North`, `South`, `East` 및 `West`는 명시적으로 0, 1, 2 및 3에 대응되지 않습니다. 대신에, 기본 열거형 멤버들은 `CompassPoint`의 명시적으로 정의된 타입과 함께 정의된 완벽하게 갖춰진 값입니다.

여러 멤버 값들이 콤마(,) 로 구분되어 한 줄에 나올 수도 있습니다:

enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

각 열거형 정의들은 새로운 타입을 정의합니다. Swift의 다른 타입과 마찬가지로, 이름들 ( `CompassPoint` 및 `Planet`과 같은) 은 대문자로 시작해야 합니다. 열거형 타입에게 자명하게 읽힐 수 있도록 복수형 대신 단수형 이름을 주세요.

var directionToHead = CompassPoint.West

`directionToHead` 타입은 `CompassPoint`의 가능한 값들 중 하나가 초기화 될 때 유추됩니다. `directionToHead`가 `CompassPoint`로 선언되면, 짧은 닷 구문을 사용하여 그 값을 다른 `CompassPoint` 값으로 할당할 수 있습니다:

directionToHead = .East

`directionToHead`의 타입은 이미 알려져 있으므로, 값을 할당할 때 타입을 명기하지 않을 수 있습니다. 이러한 부분은 명시적으로 타입된 열거형 값들로 작업할 때 매우 읽기 편한 코드를 만들어줍니다.


## 열거형의 값들과 스위치 구문간의 대응 (Matching Enumeration Values with a Switch Statement)

각각의 열거형 값들을 `switch` 구문과 대응할 수 있습니다.

directionToHead = .South
switch directionToHead {
case .North:
println("Lots of planets have a north")
case .South:
println("Watch out for penguins")
case .East:
println("Where the sun rises")
case .West:
println("Where the skies are blue")
}
// prints "Watch out for penguins

이 코드는 다음과 같이 읽을 수 있습니다:
"`directionToHead`의 값을 봅시다. 만약 `.North`와 값이 같다면, `"Lots of planets have a north"` 를 출력합니다. 만약 `.South`와 값이 같다면, `"Watch out for penguins"` 를 출력합니다."

...식이 됩니다.

[제어 구문]() 에서 설명했듯이, `switch` 구문은 열거형 멤버를 고려할때 완벽하게 작성되어야 합니다. 만약 `.West`가 빠진 경우, 이 코드는 `CompassPoint` 멤버의 완벽한 리스트를 고려하지 않았기 때문에 컴파일되지 않을 것입니다. 완벽성 (exhaustiveness) 의 요구는 열거형 멤버가 실수로 생략되는 것을 방지합니다.

모든 열거형 멤버에 대한 케이스를 제공하기에 적당하지 않은 경우, 명시적으로 언급되지 않은 멤버들을 위한 기본 케이스를 제공할 수 있습니다.

let somePlanet = Planet.Earth
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
// prints "Mostly harmless”

## 관련된 값들 (Associated Values)

앞 섹션의 에제는 열거형의 멤버들이 각각의 어떻게 정의되었는지 보여줍니다. 상수 및 변수를 `Planet.Earth` 에 할당할 수 있으며, 나중에 값들을 확인할 수도 있습니다. 그렇지만, 종종 멤버 값들과 함께 연관된 다른 타입의 값들을 저장하는 것이 유용한 경우들이 있습니다. 이는 추가적인 사용자 지정 정보를 멤버 값들마다 저장할수 있게 하며, 코드 안에서 멤버를 사용할 때 마다 정보가 변경되는 것을 허용합니다.

어떤 특정한 타입의 관련 값을 저장하는 Swift 열거형을 정의 할 수 있으며, 필요한 경우에 열거형의 각 멤버에 따라 값의 형식은 다를 수 있습니다. 이러한 열거형과 유사한 경우들이 다른 언어에서는 차별된 공용체 (discriminated union), 태깅된 공용체 (tagged unions) 및 변형체 (variants) 로 알려져 있습니다.

예를 들어 재고 추적 시스템이 각 제품을 두가지 타입의 바코드로 추적할 필요가 있다고 해 봅시다. 어떤 제품들은 UPC-A 포맷의 0에서 9 사이의 숫자를 사용하는 1차원 바코드로 레이블링 되어 있습니다. 각 바코드는 열 개의 "확인 번호(identifier)" 숫자가 뒤따르는 "번호 시스템" 숫자를 갖고 있습니다. 이 숫자들 뒤에는 각 코드가 제대로 스캔되었는지를 검증하기 위한 "확인(check)" 숫자가 붙습니다.

![chapter10-fig1.png](images/chapter10-fig1.png)

다른 제품들은 모든 ISO 8859-1 문자를 사용할 수 있으며 2,953글자의 길이를 갖는 QR 코드 포맷의 2차원 바코드로 레이블링되어 있습니다.

![chapter10-fig2.png](images/chapter10-fig2.png)

재고추적 시스템이 UPC-A 바코드를 3개의 숫자 튜플로 저장하고, QR 코드는 임의의 길이의 문자열로 저장할 수 있다면 매우 편할 것입니다.

Swift에서, 각 유형의 제품의 바코드를 정의하는 열거형은 다음처럼 보일 것입니다:

enum Barcode {
case UPCA(Int, Int, Int)
case QRCode(String)
}

이 코드는 다음과 같이 읽을 수 있습니다:

"`(Int, Int, Int)` 타입의 UPCA 값 또는 `String` 타입의 QRCode 값을 가질 수 있는 `Barcode`라는 열거형 타입을 정의합니다."

이 정의는 어떠한 실제 `Int` 및 `String` 값을 제공하지 않습니다. 오직 바코드 상수 및 변수들이 `Barcode.UPCA` 또는 `Barcode.QRCode` 중 하나와 같을 때, 그와 연관된 값들의 타입만을 정의합니다.

이제 새 바코드는 두가지 타입 중 하나로 생성될 수 있습니다:

var productBarcode = Barcode.UPCA(8, 85909_51226, 3)

이 예제는 `productBarcode` 라는 새 변수를 생성하고, `Barcode.UPCA` 의 값으로 (8, 8590951226, 3) 튜플 값을 배정합니다. 제공된 "식별자" 값은 바코드로 읽기 좋도록 정수 표현 안의 밑줄 -85909_51226-로 을 갖고 있습니다.

동일한 제품이 다른 형태의 바코드로 배정될 수도 있습니다.

productBarcode = .QRCode("ABCDEFGHIJKLMNOP")”

이 경우, 원래 `Barcode.UPCA` 및 정수 값은 새로운 `Barcode.QRCode` 와 문자열 값으로 대체됩니다. `Barcode` 타입의 상수 및 변수들은 `.UPCA` 또는 `.QRCode` 중 하나를 (해당되는 값들과 함께) 저장할 수 있지만, 한번에 둘 중 하나만 저장할 수 있습니다.

서로 다른 바코드 타입들은 앞에서와 같이 스위치 구문을 사용하여 체크할 수 있습니다. 그러나, 이번 경우 관련된 값들은 스위치 구분의 일부로 추출될 수 있습니다. 각각의 연관 값들을 `switch`의 case 내용으로 사용하기 위하여 (`let` 접두사와 함께) 상수 또는 (`var` 접두사와 함께) 변수로 추출할 수 있습니다.

switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case .QRCode(let productCode):
println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

만약 열거형 멤버들의 모든 연관 값들이 상수로 추출되었거나 모두 변수로 추출되었다면, 간결함을 위하여 멤버 이름 앞에 하나의 `var` 또는 `let` 을 붙일 수 있습니다:

switch productBarcode {
case let .UPCA(numberSystem, identifier, check):
println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case let .QRCode(productCode):
println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

## 원시 값 (Raw Values)
연관값들을 사용한 바코드 예제는 어떻게 열거형의 멤버들이 그들이 저장하는 여러 타입의 관련된 값들을 선언하는지에 대해 보여주었습니다. 연관 값들에 대한 다른 방법으로, 열거형 멤버들은 (원시 값들이라고 부르는) 모두 같은 타입인 기본값들로 미리 채워질 수 있습니다.

아래는 원시 ASCII 값들을 이름붙은 열거형 멤버들에 저장하는 예입니다.

enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "¶
"
case CarriageReturn = "\r"
}

여기서 `ASCIIControlCharacter` 열거형을 위한 원시 값들은 `Character` 타입이 되도록 정의되었으며, 더 일반적인 ASCII 제어 문자들로 할당되었습니다. `Character` 값들은 [문자열 및 글자]() 에 설명되어 있습니다.

원시 값들은 연관된 값들과 같지 않음을 유의하세요. 원시 값들은 위의 세가지 ASCII 코드들처럼 코드 안에서 처음 열거형을 정의할 때 미리 정의된 값들입니다. 개개의 열거형 멤버들의 원시 값은 언제나 동일합니다. 연관 값들은 새 상수 또는 변수를 열거형의 멤버 중 하나에 기초하여 생성할 때 할당되며, 무엇을 하느냐에 따라 매번 다를 수 있습니다.

원시 값은 문자열, 글자, 정수 또는 어떠한 부동 소수점 타입이 될 수 있습니다. 각각의 원시 값은 열거형 정의 안에서 반드시 유일해야 합니다. 원시 값으로 정수가 사용되었다면, 열거형 멤버의 일부에 아무 값도 설정되지 않은 경우 자동 증가(Auto-incrementation)할 것입니다.

아래의 열거형은 태양으로부터의 순서를 원시 정수값으로 표현하는 행성 열거형의 개선된 형태입니다.

enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

자동 증가는 `Planet.Venus`가 2의 원시 값을 갖는 식으로 진행되는 것을 의미합니다.


열거형 멤버의 원시 값들을 `toRaw` 메소드로 읽읍시다:

let earthsOrder = Planet.Earth.toRaw()
// earthsOrder is 3


열거형의 `fromRaw` 메소드를 사용하여 특정한 원시 값에 해당되는 열거형 멤버를 찾읍시다. 이 예제는 원시값 7에 해당되는 행성이 Uranus임을 판별합니다:

let possiblePlanet = Planet.fromRaw(7)
// possiblePlanet is of type Planet? and equals Planet.Uranus

모든 `Int` 값들이 해당되는 행성을 찾을 수 있는 것은 아닙니다. 그러므로, `fromRaw` 메소드는 추가적인 열거형 멤버를 반환합니다. 위의 예에서, `possiblePlanet` 은 `Planet?` 타입이거나 "optional `Planet`" 타입입니다.

만약 9번째 위치에 있는 행성을 찾는다면, `fromRaw`가 반환하는 추가적 `Planet` 값은 `nil` 이 될 것입니다:

let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) {
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
} else {
println("There isn't a planet at position \(positionToFind)")
}
// prints "There isn't a planet at position 9"

이 예제는 9의 원시값에 해당되는 행성을 읽기 위해 추가적인 바인딩을 사용합니다. `if let somePlanet = Planet.fromRaw(9)` 는 추가적인 `Planet`을 찾아내고, 찾을 수 있는 경우 추가적인 `Planet`의 내용을 `somePlanet`에 할당합니다. 이 경우, `9`의 위치에 있는 행성을 찾는 것은 불가능하기 때문에 `else` 브렌치가 대신 실행됩니다
.
chapter13
# 13 메서드 (Methods)
> Translator : 이름 (메일주소)

Methods
Methods are functions that are associated wi th a parti cular type. Classes, structures, and
enumerations can al l define instance methods, whi ch encapsulate speci fi c tasks and
functional i ty for working wi th an instance of a given type. Classes, structures, and
enumerations can al so define type methods, whi ch are associated wi th the type i tsel f.
Type methods are simi lar to class methods in Objective-C.
The fact that structures and enumerations can define methods in Swi ft i s a major
di fference from C and Objective-C. In Objective-C, classes are the only types that can
define methods. In Swi ft, you can choose whether to define a class, structure, or
enumeration, and sti l l have the flexibi l i ty to define methods on the type you create.
Instance Methods
Instance methods are functions that belong to instances of a parti cular class, structure, or
enumeration. They support the functional i ty of those instances, ei ther by providing ways
to access and modi fy instance properties, or by providing functional i ty related to the
instance’s purpose. Instance methods have exactly the same syntax as functions, as
described in Functions.
You wri te an instance method wi thin the opening and closing braces of the type i t
belongs to. An instance method has impl i ci t access to al l other instance methods and
properties of that type. An instance method can be cal led only on a speci fi c instance of
the type i t belongs to. It cannot be cal led in i solation wi thout an exi sting instance.
Here’s an example that defines a simple Counter class, whi ch can be used to count the
number of times an action occurs:
cl ass Counter {
var count = 0
func i ncrement() {
count++
}
func i ncrementBy(amount: Int) {
count += amount
}
func reset() {
count = 0
The Counter class defines three instance methods:
The Counter class al so declares a variable property, count, to keep track of the current
counter value.
You cal l instance methods wi th the same dot syntax as properties:
l et counter = Counter()
// the i ni ti al counter val ue i s 0
counter. i ncrement()
// the counter's val ue i s now 1
counter. i ncrementBy(5)
// the counter's val ue i s now 6
counter. reset()
// the counter's val ue i s now 0
Local and External Parameter Names for Methods
Function parameters can have both a local name (for use wi thin the function’s body) and
an external name (for use when cal l ing the function), as described in External Parameter
Names. The same i s true for method parameters, because methods are just functions
that are associated wi th a type. However, the defaul t behavior of local names and
external names i s di fferent for functions and methods.
Methods in Swi ft are very simi lar to thei r counterparts in Objective-C. As in Objective-C,
the name of a method in Swi ft typi cal ly refers to the method’s fi rst parameter using a
preposi tion such as w i th, for, or by, as seen in the i ncrementBy method from the preceding
i ncrement increments the counter by 1.
i ncrementBy(amount: Int) increments the counter by an speci fied integer amount.
reset resets the counter to zero.
Counter class example. The use of a preposi tion enables the method to be read as a
sentence when i t i s cal led. Swi ft makes thi s establ i shed method naming convention easy
to wri te by using a di fferent defaul t approach for method parameters than i t uses for
function parameters.
Speci fi cal ly, Swi ft gives the fi rst parameter name in a method a local parameter name by
defaul t, and gives the second and subsequent parameter names both local and external
parameter names by defaul t. Thi s convention matches the typi cal naming and cal l ing
convention you wi l l be fami l iar wi th from wri ting Objective-C methods, and makes for
expressive method cal l s wi thout the need to qual i fy your parameter names.
Consider thi s al ternative version of the Counter class, whi ch defines a more complex form of
the i ncrementBy method:
cl ass Counter {
var count: Int = 0
func i ncrementBy(amount: Int, numberOfT i mes: Int) {
count += amount * numberOfT i mes
}
}
Thi s i ncrementBy method has two parameters—amount and numberOfT i mes. By defaul t, Swi ft
treats amount as a local name only, but treats numberOfT i mes as both a local and an external
name. You cal l the method as fol lows:
l et counter = Counter()
counter. i ncrementBy(5, numberOfT i mes: 3)
// counter val ue i s now 15
You don’t need to define an external parameter name for the fi rst argument value,
because i ts purpose i s clear from the function name i ncrementBy. The second argument,
however, i s qual i fied by an external parameter name to make i ts purpose clear when the
method i s cal led.
Thi s defaul t behavior effectively treats the method as i f you had wri tten a hash symbol
(#) before the numberOfT i mes parameter:
func i ncrementBy(amount: Int, #numberOfT i mes: Int) {
count += amount * numberOfT i mes
}
The defaul t behavior described above mean that method defini tions in Swi ft are wri tten
wi th the same grammati cal style as Objective-C, and are cal led in a natural , expressive
way.
Modifying External Parameter Name Behavior for Methods
Sometimes i t’s useful to provide an external parameter name for a method’s fi rst
parameter, even though thi s i s not the defaul t behavior. You can ei ther add an expl i ci t
external name yoursel f, or you can prefix the fi rst parameter’s name wi th a hash symbol
to use the local name as an external name too.
Conversely, i f you do not want to provide an external name for the second or subsequent
parameter of a method, override the defaul t behavior by using an underscore character
(_) as an expl i ci t external parameter name for that parameter.
The self Property
Every instance of a type has an impl i ci t property cal led sel f, whi ch i s exactly equivalent to
the instance i tsel f. You use thi s impl i ci t sel f property to refer to the current instance wi thin
i ts own instance methods.
The i ncrement method in the example above could have been wri tten l ike thi s:
func i ncrement() {
sel f. count++
}
In practi ce, you don’t need to wri te sel f in your code very often. If you don’t expl i ci tly wri te
sel f, Swi ft assumes that you are referring to a property or method of the current instance
whenever you use a known property or method name wi thin a method. Thi s assumption
i s demonstrated by the use of count (rather than sel f. count) inside the three instance
methods for Counter.
The main exception to thi s rule occurs when a parameter name for an instance method
has the same name as a property of that instance. In thi s si tuation, the parameter name
takes precedence, and i t becomes necessary to refer to the property in a more qual i fied
way. You use the impl i ci t sel f property to di stingui sh between the parameter name and
the property name.
Here, sel f di sambiguates between a method parameter cal led x and an instance property
that i s al so cal led x:
struct Poi nt {
var x = 0. 0, y = 0. 0
func i sT oT heRi ghtOfX(x: Doubl e) -> Bool {
return sel f. x > x
}
}
l et somePoi nt = Poi nt(x: 4. 0, y: 5. 0)
i f somePoi nt. i sT oT heRi ghtOfX(1. 0) {
pri ntl n("T hi s poi nt i s to the ri ght of the l i ne w here x == 1. 0")
i nts "T hi s poi nt i s to the ri ght of the l i ne w here x == 1. 0"
Wi thout the sel f prefix, Swi ft would assume that both uses of x referred to the method
parameter cal led x.
Modifying Value Types from Within Instance Methods
Structures and enumerations are value types. By defaul t, the properties of a value type
cannot be modi fied from wi thin i ts instance methods.
However, i f you need to modi fy the properties of your structure or enumeration wi thin a
parti cular method, you can opt in to mutating behavior for that method. The method can
then mutate (that i s, change) i ts properties from wi thin the method, and any changes
that i t makes are wri tten back to the original structure when the method ends. The
method can al so assign a completely new instance to i ts impl i ci t sel f property, and thi s
new instance wi l l replace the exi sting one when the method ends.
You can opt in to thi s behavior by placing the mutati ng keyword before the func keyword for
that method:
struct Poi nt {
var x = 0. 0, y = 0. 0
mutati ng func moveByX(del taX: Doubl e, y del taY : Doubl e) {
x += del taX
y += del taY
}
}
var somePoi nt = Poi nt(x: 1. 0, y: 1. 0)
somePoi nt.moveByX(2. 0, y: 3. 0)
("T he poi nt i s now at (\(somePoi nt. x), \(somePoi nt. y))")
i nts "T he poi nt i s now at (3. 0, 4. 0)"
The Poi nt structure above defines a mutating moveByX method, whi ch moves a Poi nt instance
by a certain amount. Instead of returning a new point, thi s method actual ly modi fies the
point on whi ch i t i s cal led. The mutati ng keyword i s added to i ts defini tion to enable i t to
modi fy i ts properties.
Note that you cannot cal l a mutating method on a constant of structure type, because i ts
properties cannot be changed, even i f they are variable properties, as described in Stored
Properties of Constant Structure Instances:
l et fi xedPoi nt = Poi nt(x: 3. 0, y: 3. 0)
fi xedPoi nt.moveByX(2. 0, y: 3. 0)
// thi s w i l l report an error
Assigning to self Within a Mutating Method
Mutating methods can assign an enti rely new instance to the impl i ci t sel f property. The
Poi nt example shown above could have been wri tten in the fol lowing way instead:
struct Poi nt {
var x = 0. 0, y = 0. 0
mutati ng func moveByX(del taX: Doubl e, y del taY : Doubl e) {
sel f = Poi nt(x: x + del taX, y: y + del taY )
}
}
Thi s version of the mutating moveByX method creates a brand new structure whose x and y
values are set to the target location. The end resul t of cal l ing thi s al ternative version of
the method wi l l be exactly the same as for cal l ing the earl ier version.
Mutating methods for enumerations can set the impl i ci t sel f parameter to be a di fferent
member from the same enumeration:
enum T ri StateSw i tch {
case Off, Low , Hi gh
mutati ng func next() {
sw i tch sel f {
case Off:
sel f = Low
case Low :
sel f = Hi gh
case Hi gh:
sel f = Off
}
ovenLi ght = T ri StateSw i tch. Low
nLi ght. next()
venLi ght i s now equal to . Hi gh
nLi ght. next()
venLi ght i s now equal to .Off
Thi s example defines an enumeration for a three-state swi tch. The swi tch cycles between
three di fferent power states (Off, Low and Hi gh) every time i ts next method i s cal led.
Type Methods
Instance methods, as described above, are methods that are cal led on an instance of a
parti cular type. You can al so define methods that are cal led on the type i tsel f. These
kinds of methods are cal led type methods. You indi cate type methods for classes by
wri ting the keyword cl ass before the method’s func keyword, and type methods for
structures and enumerations by wri ting the keyword stati c before the method’s func
keyword.
N O T E
In Objecti ve-C, you can defi ne type- l evel methods onl y for Objecti ve-C cl asses. In Sw i ft, you can defi ne typel evel methods for al l cl asses, structures, and enumerati ons. Each type method i s expl i ci tl y scoped to the type
i t supports.
Type methods are cal led wi th dot syntax, l ike instance methods. However, you cal l type
methods on the type, not on an instance of that type. Here’s how you cal l a type method
on a class cal led SomeCl ass:
cl ass SomeCl ass {
cl ass func someT ypeMethod() {
// type method i mpl ementati on goes here
}
}
SomeCl ass. someT ypeMethod()
Wi thin the body of a type method, the impl i ci t sel f property refers to the type i tsel f, rather
than an instance of that type. For structures and enumerations, thi s means that you can
use sel f to di sambiguate between stati c properties and stati c method parameters, just as
you do for instance properties and instance method parameters.
More general ly, any unqual i fied method and property names that you use wi thin the body
of a type method wi l l refer to other type-level methods and properties. A type method
can cal l another type method wi th the other method’s name, wi thout needing to prefix i t
wi th the type name. Simi larly, type methods on structures and enumerations can access
stati c properties by using the stati c property’s name wi thout a type name prefix.
The example below defines a structure cal led Level T racker, whi ch tracks a player’s progress
through the di fferent level s or stages of a game. It i s a single-player game, but can store
information for mul tiple players on a single devi ce.
Al l of the game’s level s (apart from level one) are locked when the game i s fi rst played.
Every time a player fini shes a level , that level i s unlocked for al l players on the devi ce.
The Level T racker structure uses stati c properties and methods to keep track of whi ch level s
of the game have been unlocked. It al so tracks the current level for an individual player.
struct Level T racker {
stati c var hi ghestUnl ockedLevel = 1
stati c func unl ockLevel (l evel : Int) {
i f l evel > hi ghestUnl ockedLevel { hi ghestUnl ockedLevel = l evel }
}
stati c func l evel IsUnl ocked(l evel : Int) -> Bool {
return l evel <= hi ghestUnl ockedLevel
}
var currentLevel = 1
mutati ng func advanceT oLevel (l evel : Int) -> Bool {
i f Level T racker. l evel IsUnl ocked(l evel ) {
currentLevel = l evel
return true
} el se {
return fal se
}
The Level T racker structure keeps track of the highest level that any player has unlocked.
Thi s value i s stored in a stati c property cal led hi ghestUnl ockedLevel .
Level T racker al so defines two type functions to work wi th the hi ghestUnl ockedLevel property. The
fi rst i s a type function cal led unl ockLevel , whi ch updates the value of hi ghestUnl ockedLevel
whenever a new level i s unlocked. The second i s a convenience type function cal led
l evel IsUnl ocked, whi ch returns true i f a parti cular level number i s al ready unlocked. (Note that
these type methods can access the hi ghestUnl ockedLevel stati c property wi thout your needing
to wri te i t as Level T racker. hi ghestUnl ockedLevel .)
In addi tion to i ts stati c property and type methods, Level T racker tracks an individual player’s
progress through the game. It uses an instance property cal led currentLevel to track the level
that a player i s currently playing.
To help manage the currentLevel property, Level T racker defines an instance method cal led
advanceT oLevel . Before updating currentLevel , thi s method checks whether the requested new
level i s al ready unlocked. The advanceT oLevel method returns a Boolean value to indi cate
whether or not i t was actual ly able to set currentLevel .
The Level T racker structure i s used wi th the Pl ayer class, shown below, to track and update the
progress of an individual player:
cl ass Pl ayer {
var tracker = Level T racker()
l et pl ayerName: Stri ng
func compl etedLevel (l evel : Int) {
Level T racker. unl ockLevel (l evel + 1)
tracker. advanceT oLevel (l evel + 1)
}
i ni t(name: Stri ng) {
pl ayerName = name
The Pl ayer class creates a new instance of Level T racker to track that player’s progress. It al so
provides a method cal led compl etedLevel , whi ch i s cal led whenever a player completes a
parti cular level . Thi s method unlocks the next level for al l players and updates the
player’s progress to move them to the next level . (The Boolean return value of
advanceT oLevel i s ignored, because the level i s known to have been unlocked by the cal l to
Level T racker. unl ockLevel on the previous l ine.)
You can create a instance of the Pl ayer class for a new player, and see what happens when
the player completes level one:
var pl ayer = Pl ayer(name: "Argyri os")
pl ayer. compl etedLevel (1)
pri ntl n("hi ghest unl ocked l evel i s now \(Level T racker. hi ghestUnl ockedLevel )")
// pri nts "hi ghest unl ocked l evel i s now 2"
If you create a second player, whom you try to move to a level that i s not yet unlocked
by any player in the game, the attempt to set the player’s current level fai l s:
pl ayer = Pl ayer(name: "Beto")
i f pl ayer. tracker. advanceT oLevel (6) {
pri ntl n("pl ayer i s now on l evel 6")
} el se {
pri ntl n("l evel 6 has not yet been unl ocked")
}
// pri nts "l evel 6 has not yet been unl ocked"
북극산펭귄 (say8425@gmail.com)

#Methods

메서드Method는 타입type에 의존적인 함수입니다. 모든 클래스와 구조체 그리고 이너멀레이션Enumeration은, 타입이 정해진 인스턴스Instance가 수행하는 작업을 캡슐화하는 인스턴스 메소드를 정의 할 수 있습니다. 또한 타입 자체에 관여하는 타입 메소드를 정의 할 수 있습니다. 이 타입 메소드는 오브젝티브-C에서의 클래스Class Method와 유사합니다.

##Instance Methods

인스턴스 메소드Instance Method는 특정 클래스, 구조체 혹은 이너멀레이션의 인스턴스에 속하는 함수입니다. 이것은 인스턴스 속성에 접근하고 수정하는 방법이나, 인스턴스의 용도에 관련된 기능을 지원합니다. `함수섹션`에서 설명된대로 인스턴스 메소드는 특히 함수와 동일한 문법을 가집니다.

여러분은 인스턴스 메소드를 해당 타입이 속한 괄호내에서 작성합니다. 인스턴스 메소드는 다른 인스턴스 메소드와 해당 타입의 속성에 대한 암시적 권한Implict access을 가지고 있습니다. 인스턴스 메소드는 오직 해당 타입이 속한 특정한 인스턴스에 의해서만 호출 될 수 있습니다. 이것은 속해있는 인스턴스 없이 독립적으로 호출 될 수 없습니다.

여기 작업을 수행한 횟수를 세는, 카운터`Counter`클래스를 정의한 간단한 예제가 있습니다:


class Counter {
var count = 0
func increment() {
count++
}
func incrementBy(amount: Int) {
count += amount
}
func reset() {
count = 0
}
}


이 `Counter`클래스는 세가지 인스턴스 메소드를 정의합니다.



* `increment` 1만큼 counter를 증가시킵니다.
* `incrementBy(amount: Int)` 특정한 정수값만큼 counter를 증가시킵니다.
* `reset` counter를 0으로 재설정합니다.

또한 `Counter`클래스는 현재 카운터 값을 추적하기 위해 변수 프로퍼티Property count를 선언하였습니다.

당신은 프로퍼티와 같은 점 문법으로 인스턴스 메소드를 호출합니다:

let counter = Counter()
// 초기 counter값은 0입니다
counter.increment()
// counter값은 이제 1입니다
counter.incrementBy(5)
// counter값은 이제 6입니다
counter.reset()
// counter값은 이제 0입니다

chapter19
# 19 옵션 연쇄 (Optional Chaining)
> Translator : 이름 (메일주소)

Write here...
허혁 (hyukhur@gmail.com)

선택 연쇄(Optional chaining)란 nil이 될 수 있는 선택지(options)를 가진 프로퍼티(property), 메소드(method), 서브 스크립트 (subscript)에 질의하고 호출하는 프로세스를 말한다. 만약 어떤 선택지가 값을 가진다면 프로퍼티, 메소드, 서브스크립트 호출은 성공하고 선택지가 nil이면, 프로퍼티, 메소드, 서브스크립트 호출은 nil을 반환하게 된다.
여러개의 질의도 함께 엮일 수 있으며, 만약 연쇄(chaining) 중간의 어떤 링크가 nil이라면 조용하게 전체 체인은 실패한다.

Note
스위프트(Swift)의 선택 연쇄가 오브젝티브씨(Objective-C)에 있는 nil에 메시지 보내기와 유사하다. 그러나, 모든 타입(any type)에서 동작하고, 성공, 실패 여부를 확인할 수 있다는 점에서 차이가 있다.

## 강제 랩핑 해제(Forced Unwrapping) 대안으로써 선택 연쇄
호출하고자 하는 프로퍼티, 메소드, 서브스크립트의 선택지 값(optional value)이 nil 아닐 때 선택지 값 뒤에 물음표(?)를 두어 선택 연쇄를 둘 수 있다. 이것은 선택지 값 뒤에 느낌표(!)를 두어 그 값을 강제로 랩핑 해제하는 것과 유사하다. 가장 주요한 차이점은 선택 연쇄는 선택지가 nil일 때 자연스럽게 실패한다는 것이고, 강제 랩핑 해제는 선택지가 nil인 경우 런타임 에러가 발생한다.
선택 연쇄가 nil 값에도 호출할 수 있다는 사실을 반영하기 위해 선택 연쇄 호출 결과는 항상 선택지 값이다. 비록 질의한 프로퍼티, 메소드, 서브스크립트가 항상 선택지 값이 아닌 결과를 도출해도 그렇다. 이 선택지 반환 값을 사용해서 선택 연쇄 호출이 성공했는지 ( 반환된 선택지가 값을 가지는 ) 연쇄 중간의 nil 값 ( 선택지 반환값이 nil ) 때문에 실패했는지를 확인할 수 있다.
구체적으로, 선택 연쇄 호출 결과는 선택지로 감싸여져 있음에도 기대한 반환값과 동일한 타입이다. 일반적으로 Int를 반환하는 프로퍼티는 선택 연쇄에 따라 접근이 가능할때는 Int?를 반환할 것이다.
다은 몇몇 코드 조각은 선택 연쇄가 어떻게 강제 랩핑 해제와 다르고 성공 여부 확인을 가능케 하는지 보여준다.
먼저 Person과 Residence 라는 클래스를 정의하자.
>class Person {
var residence: Residence?
}
>class Residence {
var numberOfRooms = 1
}

Residence 인스턴스(Instance)는 기본값이 1인 numberOfRooms 이라는 단 하나의 Int 프로퍼티를 가진다. Person 인스턴스는 Residence? 타입으로 residence 이라는 선택적 프로퍼티를 가진다.
만약 Person 이라는 인스턴스를 새로 만들면, 선택지가 된 효과에 따라 기본적으로 nil로 설정된다. 아래 코드에서는 john는 nil로 된 residence 프로퍼티를 가질 것이다.
let jone = Person()
만약 Person의 residence의 numberOfRooms 프로퍼티를 그 값을 강제로 랩핑 해제를 하려고 느낌표를 붙여서 접근한다면 런타임 에러(Runtime Error)를 유발시킬 것이다. 왜냐하면 해제할 residence 값 자체가 없기 때문이다.
let roomCount = john.residence.numberOfRooms
위 코드는 john.residence가 nil이 아닌 값을 성공하며 방 갯수에 적절한 숫자를 담고 있는 Int 값에 roomCount를 설정할 것이다. 그러나 이 코드는 위에 보여지는 것처럼 residence가 nil이라면 항상 런타임 에러를 유발 시킨다.
선택 연쇄는 numberOfRooms 값에 접근하는데 대안법을 제공한다. 선택 연쇄를 사용하기 위해 느낌표 자리에 물음표를 사용하면 된다.

>if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."

이것은 스위프트(swift)가 선택적 residence 프로퍼티를 "엮고" 만약 residence가 있으면 numberOfRooms 값을 가져온다는 것을 말해준다.

numberOfRooms에 대한 접근이가 잠제적으로 실패할 수 있기 때문에 선택 연쇄는 Int?이나 "선택적 Int"형 값을 반환하려고 한다. 위 예제처럼 residence가 nil인 경우는 numberOfRooms에 대한 접근이 불가능하다는 사실을 반영하기 위해서 이 선택적 Int 역시 nil이 될 것이다.
numberOfRooms가 비선택적 Int 임에도 불구하고 참인 것을 명심해라. 선택 연쇄를 통해 질의한다는 것은 numberOfRooms가 Int 대신 Int?를 항상 반환할 것이라는 것을 의미한다.
john.residence에 Residence 인스턴스를 할당할 수 있는데 그러면 더이상 nil 값은 존재하지 않게 된다.
>john.residence = Residence()

john.residence는 실체 Residence 인스턴스를 이제 가지게 되었다. 만약 예전과 동일한 선택 연쇄를 사용해 접근하려고 하면, 1이라는 numberOfRooms 기본값을 가지는 Int?가 반환될 것이다.

>if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "John's residence has 1 room(s)."

선택 연쇄를 위한 모델(Model) 클래스(Class) 선언

프로퍼티, 메소드, 서브스크립트를 호출하는 것 같은 한단계 더 깊은 선택 연쇄을 사용할 수 있다. 이는 상호관계있는 타입간의 복잡한 모델에서 서브 프로퍼티(subproperty)를 파고 들 수 있게 해주고 그 서브 프로터티에 프로퍼티와 메소드, 서브스크립트에 접근할 수 있는지 아닌지를 확인할 수 있게 해준다.
다음 코드 조각은 다단계 선택 연쇄 예를 포함한 몇가지 순차적인 예제에서 사용될 4개의 모델 클래스를 정의한다. 이 클래스들은 위에 나온 Person과 Residence 모델에 Room과 Address 클래스를 추가하고 연관 프로퍼티와 메소드, 서브스크립트를 확장한다.
Person 클래스는 이전과 동일한 방법으로 정의한다.
>class Person {
var residence: Residence?
}

Residence 클래스는 이전보다 조금 복잡해졌다. 이번에는 Residence 클래스에 Room[] 타입의 빈 배열로 초기화된 rooms라는 변수 프로퍼티를 선언한다.
>‘class Residence {
var rooms = Room[]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
return rooms[i]
}
func printNumberOfRooms() {
println("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}’

이번 버전 Residence는 Room 인스턴스 배열을 저장하기 때문에, 그 numberOfRooms 프로퍼티는 저장된 프로퍼티가 아닌 계산된 프로퍼티로 구현했다. 계산된 numberOfRooms 프로퍼티는 단순히 rooms 배열에서 count 프로퍼티의 값을 반환한다.
그 rooms 배열에 접근하기 위한 바로가기로 이번 버전 Residence는 읽기만 가능한 서브 스크립트를 제공하는데 서브스크립트에게 전달받는 인덱스(index)가 적합할 것이라는 가정으로 시작해보겠다. 만약 인덱스가 적합하다면, 서브스크립트는 rooms 배열의 요청받은 인덱스의 방정보를 반환할 것이다.
또한 이번 버전 Residence는 printNumberOfRooms라는 이름의 메소드를 제공하는데 단순히 Residence에 방 갯수를 출력한다.
마지막으로 Residence에 Address?이란 타입으로 address라는 선택적 프로퍼티를 선언한다. 이를 위한 Address 클래스 타입은 밑에 정의하겠다.
rooms 배열에 사용하는 Room 클래스는 name이라는 프로퍼티 하나를 가지는 간단한 클래스인데 이는 적절한 방이름을 설정하기 위한 초기화 역할(initializer)을 한다.
>class Room {
let name: String
init(name: String) { self.name = name }
}

이 모델의 마지막 클래스는 Address이다. 이 클래스는 String? 타입의 선택적 프로퍼티를 3개 가지고 있다. 그 중 2개는 buildingName과 buildingNumber 인데 주소를 구성하는 특정 빌딩에 대한 구분을 짓기 위한 대체 수단이다. 3번째 프로퍼티인 street는 그 주소의 도로이름에 사용한다.
>class Address {
var buildingName: String?
var buildingNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if buildingName {
return buildingName
} else if buildingNumber {
return buildingNumber
} else {
return nil
}
}
}

또한 Address 클래스는 String? 반환값을 가지는 buildingIdentifer 이란 이름의 메소드를 제공한다. 이 메소드는 buildingName과 buildingNumber 프로퍼티를 확인해서 만약 buildingName이 값을 가진다면 그 값을 혹은 buildingNumber이 값을 가진다면 그 값을, 둘다 값이 없다면 nil을 반환한다.

##선택 연쇄를 통한 프로퍼티 호출
강제 랩핑 해제(Forced Unwrapping) 대안으로써 선택 연쇄에서 봤던 것처럼 선택 연쇄를 선택적 값에 대한 프로퍼티 접근에 접근할 수 있는지 만약 프로퍼티 접근이 가능한지 확인하기 위해 사용할 수 있다. 그러나 선택 연쇄를 통해 프로퍼티의 값을 설정하는 것은 할 수 없다.
위에 정의한 새로운 Person 인스턴스를 사용해 클래스를 만들어 이전처럼 numberOfRooms 프로퍼티에 접근하기를 시도해본다.
>let john = Person()
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."

john.residence가 nil이기 때문에 이 선택 연쇄를 예전과 동일한 방식으로 호출했지만 에러 없이 실패한다.

##선택연쇄를 통한 메소드 호출
선택 연쇄를 사용해서 선택적 값을 호출하고 메소드 호출이 성공했는지 여부를 확인해볼 수 있다. 설렁 메소드가 반환값을 정의하지 않더라고 할 수 있다.
Residence 클래스에 있는 printNumberOfRooms 메소드는 numberOfRooms의 현재 값을 출력한다. 그 메소드는 다음과 같을 것이다.
>func printNumberOfRooms() {
println("The number of rooms is \(numberOfRooms)")
}

이 메소드는 반환값을 명시하지 않았다. 그러나 반환형이 없는 함수와 메소드는 Functions Without Return Values에 나와 있는 것처럼 암시적으로 Void 타입을 반환하게 된다.
만약 선택 연쇄에 있는 선택지 값에 이 메소드를 호출한다면, 메소드 반환형은 Void가 아니라 Void?이 될 것이다. 선택 연쇄를 통해 호출될 때 선택적 타입은 항상 반환 값을 가지기 때문이다. 이는 메소드가 반환값이 정의되어 있지 않더라도 printNumberOfRooms 메소드를 호출이 가능한지를 if문을 써서 확인할 수 있게 한다. printNumberOfRooms에서 암시적 반환값은 만약 메소드가 선택 연쇄를 통해 성공적으로 호출되었다면 Void와 동일할 것이고 그렇지 않다면 nil과 동일할 것이다.
>if john.residence?.printNumberOfRooms() {
println("It was possible to print the number of rooms.")
} else {
println("It was not possible to print the number of rooms.")
}
// prints "It was not possible to print the number of rooms."

##선택 연쇄를 통한 서브스크립트 호출
선택적값에 대한 서브스크립트에서 값을 가져와서 서브스크립트 호출이 성공했는지 확인하기 위해 선택 연쇄를 사용할 수 있다. 그러나 선택 연쇄를 통해 서브스크립트로 값을 설정하는 것은 할 수 없다.

>노트
선택연쇄를 통해 선택적값에 대한 서브스크립트를 접근할 때 서브스크립트 괄호(brace) 앞에 물음표를 놓아야 한다. 뒤가 아니다. 선택연쇄 물음표는 항상 선택적인 표현식의 뒤에 바로 따라나와야 한다.

아래 예는 Residence 클래스에 정의되어 있는 서브스크립트를 사용하는 john.residence 프로퍼티의 rooms 배열에 있는 첫번째 방이름을 검색하려고 하는 것이다. john.residence가 현재 nil이기 때문에 서브스크립트는 실패한다.
>if let firstRoomName = john.residence?[0].name {
println("The first room name is \(firstRoomName).")
} else {
println("Unable to retrieve the first room name.")
}
// prints "Unable to retrieve the first room name."

선택연쇄 물음표

chapter2
# 02 Swift 둘러보기 (Swift Tour)
> Translator : 이름 (메일주소)

새로운 언어를 배울 때 첫번째 프로그램은 전통적으로 화면에 "Hello, world"란 구문을 출력해 보는 것입니다. Swift에서는 단 한줄로 이것이 가능합니다.

println("Hello, world")

C나 Objective-C에서 코드를 작성해본적이 있다면 Swift에서 이 한줄의 코드가 완전한 프로그램을 구성하는 이런 문법이 매우 익숙할 것입니다. 입.출력이나 문자열을 다루기 위한 함수들 같은 기능들을 위한 분리된 라이브러리를 임포트할 필요가 없습니다. 프로그램의 전체 지점에 있어서 코드는 전역 범위(Global scope)로 쓰여지고, 때문에 main 함수는 필요하지 않습니다. 또한 모든 문장끝에 세미콜론을 쓸 필요도 없습니다.

이 둘러보기는 다양한 프로그래밍 과제를 어떻게 완수해 나가는지 보여주면서 Swift로 어떻게 코드를 작성해야하는지에 대한 충분한 정보를 제공할 것입니다. 몇몇가지를 이해하지 못한다고 해서 걱정하지 마세요. 이번 장에서 소개되는 모든 것들은 책의 뒷 부분에서 자세히 설명될 것입니다.

노트
최선의 경험을 위해서 이번 장을 Xcode안에서 playground로 열어보세요. Playground는 코드의 수정과 즉시 결과를 볼 수 있도록 해줄 것입니다.

##간단한 값

let을 사용하면 상수를 만들고 var를 사용하면 변수를 만들 수 있습니다. 상수는 컴파일 타임에 알고 있을 필요가 없습니다. 그러나 오직 한번만 값을 할당해야합니다. 이것은 상수를 값을 한번만 결정하고 여러곳에 쓰일 이름으로 사용할 수 있다는 것을 의미합니다.

1| var myVariable =42
2| myVariable = 50
3| let myConstant = 42

상수나 변수 모두 당신이 할당하고 싶은 값의 타입을 가질 수 있습니다. 그러나 항상 타입을 명시해야만 하는 것은 아닙니다. 당신이 상수나 변수를 만들 때 할당한 값을 통해 컴파일러는 그 값의 타입을 추측합니다. 위의 예를 보면, myVariable이 정수형 값으로 초기화되었기 때문에 컴파일러는 정수형이라고 추측합니다.

만약 초기값이 충분한 정보를 제공하지 못한 경우(혹은 초기값이 없는 경우) 특정한 타입을 변수명 뒤에 세미콜론으로 분리하여 써주어야 합니다.

1| let inplicitInteger = 70
2| let implicitDouble = 70.0
3| let explicitDouble: Double = 70

실험
4와 명시적으로 Float 형태의 값을 갖는 상수를 만들어보자.

값은 절대 암시적으로 다른 형태의 값으로 변환할 수 없습니다. 만약 다른 형태의 값으로 변화해야 한다면 명시적으로 원하는 형태의 인스턴스로 만들어야 합니다.

1| let label = "The width is "
2| let width = 94
3| let widthLabel = label + String(width)

실험
마지막줄에 있는 String으로 변환 부분을 제거해보자. 어떤 에러가 발생하는가?

문자열 안에 값들을 포함하는 쉬운 방법도 있습니다. 괄호 안에 값을 쓰고 괄호 앞에 백슬래시를 쓰면 됩니다. 예를 들면

1| let apples = 3
2| let oranges = 5
3| let appleSummary = "I have \(apples) apples."
4| let fruitSummary = "I have \(apples + oranges) pieces of fruit."

실험
문자열안에 \()를 이용해 실수형 계산을 포함하도록 해보고, 인사말 안에 누군가의 이름을 넣어보자.

배열과 딕셔너리는 대괄호([])를 이용해 만들 수 있습니다. 그리고 대괄호 안에 인덱스나 키를 이용해 각각의 요소에 접근할 수 있습니다.

1| var shoppingList = ["catfish", "water", "tulips", "blue paint"]
2| shoppingList[1] = "bottle of water"
3|
4| var occupations = [
5| "Malcolm":"Captian",
6| "Kaylee":"Mechanic",
7| ]
8| occupations["Jayne"] = "Public Relations"

빈 배열이나 딕셔너리를 만들려면, 초기화자(initializer) 문법을 사용하면 됩니다.

1| let emptyArray = String[]()
2| let emptyDictionary = Dictionary()

타입 정보를 추론할 수 없다면 빈 배열은 []로 빈 딕셔너리는 [:]로 쓸 수 있습니다. 예를 들어 변수에 새로운 값을 할당하거나 함수에 인자로 넘겨줄 때

shoppingList = [] //쇼핑을 가서 모든 것을 샀다.

##흐름 제어
if와 switch를 사용해서 조건문을 만들 수 있고 for-in, for, while, do-while을 이용해서 반복문을 만들 수 있습니다. 조건문과 반복문을 괄호로 감싸는 것은 선택사항입니다. 중괄호로 몸통을 감싸는 것은 필수입니다.

1| let individualScores = [75, 43, 103, 87, 12]
2| var teamScore = 0
3| for score in individualScores {
4| if score > 50 {
5| teamScore += 3
6| } else {
7| teamScore += 1
8| }
9|}
10|teamScore

if문 안에 조건은 꼭 불리언(Boolean) 표현이어야 합니다. 이것은 if score {...} 이 0과의 비교를 암시하지 않기 때문에 에러가 발생합니다.

사라질 값을 가지고 if와 let을 함께 사용하는 것도 가능합니다. 이런 값들은 옵션으로 대표됩니다. 옵션값은 어떤 값을 가지거나 사라질 값을 표현하는 nil을 가지기도 합니다. 값의 타입 뒤에 물음표를 쓰면 옵션값이라는 것을 나타냅니다.

1| var optionalString: String? = "Hello"
2| optionalString == nil
3|
4| var optionalName: String? = "John Appleseed"
5| var greeting = "Hello!"
6| if let name = optionalName {
7| greeting = "Hello, \(name)"
8| }

실험
optionalName의 값을 nil로 바꿔보자. 어떤 greeting의 값을 받을 수 있는가? optionalName이 nil일 때 다른 값을 greeting에 할당하도록 else 절을 추가해보자.

만약 옵션값이 nil이라면 조건문은 false이고 중괄호 안에 있는 코드를 건너뛰게 됩니다. 반대의 경우에는 중괄호 블록 안에서 사용할 수 있도록 let 뒷부분의 상수에 값이 할당되고 옵션값으로 사용할 수 있습니다.

스위치(Switch) 구문에는 정수형 값이나 동등 비교연산 뿐만 아니라 어떤 종류의 데이터든 사용할 수 있고 다양한 비교 연산자들을 사용할 수 있습니다.

1| let vegetable = "red pepper"
2| switch vegetable {
3| case "celery":
4| let vegetableComment = "Add some raisins and make ants on a log."
5| case "cucumber", "watercress":
6| let vegetableComment = "That would make a good tea sandwich."
7| case let x where x.hasSuffix("pepper"):
8| let vegetableComment = "Is it a spicy \(x)?"
9| default:
10| let vegetableComment = "Everything tastes good in soup."
11| }

실험
스위치 구문에서 default의 경우를 제거해 보자. 어떤 에러가 발생하는가?

스위치 구문안의 일치하는 경우의 코드를 실행하고 나면 프로그램은 스위치 구문을 빠져나옵니다. 실행한 코드 이후에 나오는 내용은 실행하지 않기 때문에 각 경우의 코드 끝마다 빠져나오도록 명시적으로 써주지 않아도됩니다.(*역자 주: 보통 사용되는 break를 굳이 쓸 필요가 없다는 것입니다.)

for-in 문을 사용하면 각각 키-값 쌍으로 사용할 수 있는 이름들의 쌍을 이용해 딕셔너리에 있는 요소들을 반복처리할 수 있습니다.

1| let interestingNumbers = [
2| "Prime": [2, 3, 5, 7, 11, 13],
3| "Fibonacci": [1, 1, 2, 3, 5, 8],
4| "Square": [1, 4, 9, 16, 25],
5| ]
6| var largest = 0
7| for (kind, numbers) in interestingNumbers {
8| for number in numbers {
9| if number > largest {
10| largest = number
11| }
12| }
13| }
14| largest

실험
계속 알아 보기 위해서 기존의 제일 큰 값만큼 큰 값을 가지는 요소를 추가해보자.

조건문이 변경될 때까지 코드 블록을 반복 실행하기 위해서 while 문을 사용해 봅시다.

반복문이 적어도 한번은 실행될 수 있도록 보장하기 위해서 조건문을 반복문 끝에 쓸수도 있습니다.

1| var n = 2
2| while n < 100 {
3| n = n * 2
4| }
5| n
6|
7| var m = 2
8| do {
9| m = m * 2
10| } while m < 100
11| m

반복문안에서 ..을 사용해 인덱스의 범위를 만들어 사용하거나 명시적으로 초기화, 조건문, 증감식을 사용하는 것 또한 가능합니다. 아래쪽에 나오는 두가지 반복문은 동일한 일을 수행합니다.

1| var firstForLoop = 0
2| for i in 0..3 {
3| firstForLoop += i
4| }
5| firstForLoop
6|
7| var secondForLoop = 0
8| for var i = 0; i < 3; ++i {
9| secondForLoop += 1
10| }
11| secondForLoop

..을 사용해서 범위를 지정하면 제일 나중값은 제외가 됩니다. 대신 ...을 사용하면 양쪽 끝값 모두 포함하게 됩니다.

##함수(Functions)와 클로저(Closures)

func를 사용해 함수를 선언할 수 있습니다. 함수의 이름과 괄호안에 인자들을 넣어서 함수를 호출할 수 있습니다. 매개변수들의 이름과 분리해서 ->를 사용해 타입을 써주면 함수 반환값의 타입을 지정할 수 있습니다.

1| func greet(name: String, day: String) -> String {
2| return "Hello \(name), today is \(day)."
3| }
4| greet("Bob", "Tuesday")


실험
매개변수 day를 제거하고 오늘의 스페셜 런치 매개변수를 greeting에 추가해보자.

튜플(tuple)을 사용하면 여러개의 값을 반환할 수 있습니다.

1| func getGasPrices() -> (Double, Double, Double) {
2| return (3.59, 3.69, 3.79)
3| }
4| getGasPrices()

함수는 배열을 이용해서 여러개의 값을 인자로 받는 것도 가능합니다.

1| func sumOf(numbers: Int...) -> Int {
2| var sum = 0
3| for number in numbers {
4| sum += number
5| }
6| return sum
7| }
8| sumOf()
9| sumOf(42, 597, 12)

실험
인자들의 평균값을 계산하는 함수를 만들어보자.

함수는 다른 것에 포함될 수도 있습니다. 내장된(Nested) 함수는 감싸고 있는 함수에서 선언된 변수에 접근할 수 있습니다. 길어지고 복잡한 함수의 코드를 정리하기 위해 내장된 함수를 사용할 수 있습니다.

1| func returnFifteen() -> Int {
2| var y = 10
3| func add() {
4| y += 5
5| }
6| add()
7| return y
8| }
9| returnFifteen()

함수는 최상위 타입입니다. 이것은 어떤 함수가 다른 함수를 반환값형태로 반환할 수 있다는 것을 의미합니다.

1| func makeIncrementer() -> (Int -> Int) {
2| func addOne(number: Int) -> Int {
3| return 1 + number
4| }
5| return addOne
6| }
7| var increment = makeIncrementer()
8| increment(7)

또 함수는 다른 함수를 인자로 받을 수 있습니다.

1| func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
2| for item in list {
3| if condition(item) {
4| return true
5| }
6| }
7| return false
8| }
9| func lessThanTen(number: Int) -> Bool {
10| return number < 10
11| }
12| var numbers = [20, 19, 7, 12]
13| hasAnyMatches(numbers, lessThanTen)

함수는 실제로는 클로저의 특별한 예입니다. 중괄호로 묶기만 해서 이름없이 클로저를 사용할 수도 있습니다. in을 사용해 몸통에서 인자와 반환값 타입을 분리해 쓸 수 있습니다.

1| numbers.map({
2| (number: Int) -> Int in
3| let result = 3 * number
4| return result
5| })

실험
모든 홀수값에 대해 0을 반환하도록 클로저를 수정해보자.

클로저를 간결하게 쓰기 위한 몇가지 옵션이 있습니다. 델리게이트(delegate)를 위한 콜백같이 이미 클로저의 타입을 아는 경우라면 매개변수의 타입, 반환값 타입을 모두 생략하거나 선택적으로 생략할 수 있습니다. 한줄짜리 구문을 가진 클로저라면 구문만 가지고도 반환 타입을 추측할 수 있습니다.

numbers.map({ number in 3 * number })

매개변수의 이름 대신에 번호로 참조하는 것은 클로저를 짧게 만드는데 특히 유용합니다. 이때 클로저는 함수의 바로 뒤에 중괄호를 이용해 인자로 전달됩니다.

sort([1, 5, 3, 12, 2]) { $0 > $1 }

##객체(Objects)와 클래스(Classes)

클래스를 만들기 위해서는 클래스 이름과 함께 class 키워드를 사용하면 됩니다.클래스 컨텍스트(context) 내부를 제외하고 클래스 안에 속성을 선언하기 위해서는 상수나 변수를 선언하는 것과 똑같은 방식으로 쓰면 됩니다. 마찬가지로 메서드와 함수도 선언할 수 있습니다.

1| class Shape {
2| var numberOfSides = 0
3| func simpleDescription() -> String {
4| return "A shape with \(numberOfSides) sides."
5| }
6| }

어떤 클래스의 인스턴스를 만들려면 클래스 이름 다음에 괄호를 넣으면 됩니다. .(점) 문법을 사용하면 인스턴스의 속성이나 메서드에 접근할 수 있습니다.

1| var shape = Shape()
2| shape.numberOfSides = 7
3| var shapeDescription = shape.simpleDescription()

현재 상태의 Shape클래스는 중요한 것이 빠져있습니다. 바로 클래스가 생성될 때 클래스를 초기화하기 위한 초기화자 입니다. init 키워드를 사용해 만들어 봅시다.

1| class NamedShape {
2| var numberOfSides: Int = 0
3| var name: String
4| init(name: String) {
5| self.name = name
6| }
7| func simpleDescription() -> String {
8| return "A shape with \(numberOfSides) sides."
9| }
10| }

인자의 name과 속성의 name을 구분하기 위해서 self 키워드가 어떻게 사용되는지 주의해서 봅시다. 클래스의 인스턴스를 만들 때 초기화자에 인자를 전달하는 방식은 함수에 전달하는 방식과 동일합니다. 모든 속성은 numberOfSides 처럼 값을 선언 할 때 혹은 name처럼 클래스를 초기화 할 때 처럼 적어도 둘중에 한가지 방법을 통해 값을 할당해줘야 합니다.

오브젝트를 해제하기전 정리 작업이 필요하다면 deinit을 사용해서 디이니셜라이저(deinitializer)를 만들 수 있습니다.

하위 클래스는 클래스명 뒤에 상위 클래스의 이름을 세미콜론으로 구분해 포함합니다. 꼭 기본 루트 클래스가 필요한 것은 아니기 때문에 상위 클래스를 포함해도 되고 생략해도 됩니다.

하위 클래스에서 상위 클래스에서 구현된 메서드를 오버라이드(override) 하려면 override 키워드를 이용해 표시해줘야 합니다. override키워드를 사용하지 않고 어떤 메서드를 갑자기 오버라이드하면 컴파일러에서 에러로 인식합니다. 또 override 키워드를 사용했는데 실제로 상위 클래스에는 해당 메서드가 없다면 이것 또한 컴파일러가 잡아냅니다.

```c
class Square: NamedShape {
var sideLength: Double

init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}

func area() -> Double {
return sideLength * sideLength
}

override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
```

실험
NamedShape클래스의 또 다른 하위 클래스인 Circle을 만들어보자. 이 클래스는 이니셜 라이저를 통해 radius와 name을 인자로 받는다. Circle 클래스 안에 area, describe 함수를 구현해보자.

저장되어 있는 간단한 속성 외에도 속성은 getter와 setter를 가질 수 있습니다.

```c
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0

init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}

var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}

override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
```
perimeter의 setter안에서는 newValue라는 이름이 새로운 값을 나타내고 있습니다. 반면에 명시적으로 set 뒤에 괄호를 이용해 명시적으로 이름을 지정해 줄수도 있습니다.

EquilateralTriangle 클래스의 이니셜라이저는 세가지의 다른 단계를 가지고 있음을 살펴봅시다.

1. 하위 클래스에서 선언한 속성의 값을 지정합니다.
2. 상위 클래스의 이니셜라이저를 호출합니다.
3. 상위 클래스에 의해 정의된 속성값을 변경합니다. 어떤 메서드나 setter,getter를 사용하지 않고도 가능 하다는 것이 중요한점 입니다.

속성의 값을 계산할 필요는 없지만 새로운 값을 할당하기 전이나 후에 수행해야할 코드가 있다면 willSet, didSet을 사용할 수 있습니다. 예를 들면 아래쪽에 나오는 클래스에서는 삼각형의 빗면의 길이가 사각형의 옆면의 길이와 항상 동일하다는 것을 보장합니다.

```c
class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size: Double, name: String) {
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength
```

클래스에 있는 메서드들은 함수와는 다른 중요한 특징이 한가지 있습니다.함수에서 사용되는 매개변수의 이름들은 함수 내부에서만 사용합니다. 그러나 메서드에 사용되는 매개변수의 이름은 메서드를 호출할 때도 사용됩니다(첫번째 매개변수의 이름은 제외하고). 기본적으로 메서드는 호출할 때 혹은 메서드에서 사용되는 이름과 동일한 매개변수 이름을 갖습니다. 하지만 메서드 내부에서 사용될 두번째 이름을 특별히 정해줄 수도 있습니다.

```c
class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes times: Int) {
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
```
옵션 값을 사용할 때는 메서드나 속성, 서브스크립트 앞에 ?를 쓸 수 있습니다. 만약 ? 앞에 값이 nil 이라면 ? 이후에 나오는 모든 것은 무시되고 표현의 값들은 nil을 갖습니다. 반면에 값이 있는 경우라면 ? 이후의 모든 그 값을 기준으로 동작합니다. 양쪽 경우 모두 옵션 값으로 사용됩니다.

##열거형(Enumerations)과 구조체(Structures)
enum 키워드를 사용하면 열거형을 만들 수 있습니다. 클래스나 모든 알려진 타입들의 경우 열거형에 메서드를 포함할 수 있습니다.

```c
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
```

>실험
두개의 Rank 값의 원본 값을 비교하는 함수를 만들어보자.

위의 예를 보면 열거형의 원본 값의 타입은 int 입니다. 그래서 특별히 첫번째 원본값만 가지고 있는 것입니다. 나머지 원본 값들은 순서에 따라 자동으로 할당됩니다. 또 문자열이나 실수형태의 값들도 원본값으로 가진 열거형을 만들 수 있습니다.

toRaw와 fromRaw 함수를 사용해서 원본값과 열거형 값을 상호 변환할 수 있습니다.

```c
if let convertedRank = Rank.fromRaw(3) {
let threeDescription = convertedRank.simpleDescription()
}
```

열거형의 구성값들은 실제 값을 쓰는 다른 방법일 뿐 아니라. 모두 실제 값입니다. 사실 실제값이 의미있는 경우가 아니라면 굳이 첫번째 값을 제공할 필요가 없습니다.

```c
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
```

>실험
Suit에 color 메서드를 추가해 보자. color 메서드는 스페이드와 클로버는 'black'을 반환하고 하트와 다이아몬드는 'red'를 반환하도록 하면 됩니다.

열거형의 구성중 하나인 Heart가 상단값을 어떻게 참조하는지 두가지 방법을 살펴봅시다. 상수 hearts에 값을 할당 할 때, 상수는 명시적으로 타입을 가지고 있지 않기 때문에 Suit.Hearts 처럼 전체 이름을 살펴봅니다. 스위치문 안에서는 열거형은 .Hearts로 축약형을 써서 참조하는데, 이것은 self가 이미 suit라는 것을 알고 있기 때문입니다. 값의 형을 이미 알고 있다면 언제든지 축약형을 사용해도 됩니다.

구조체를 만들기 위해서는 struct 키워드를 사용합니다. 구조체는 메서드나 이니셜라이저 같은 클래스와 비슷한 기능들을 지원합니다. 클래스와 구조체의 가장 중요한 차이점중 하나는 구조체의 경우 코드 내에서 전달될 때 값복사 형태로 전달되지만 클래스의 경우에는 참조복사 형태로 전달된 다는 것입니다.

```c
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
```
>실험
각 카드를 rank와 suit를 조합해서 만들어 전체 카드를 만들어 주는 메서드를 Card에 추가해보자.


































FlashMaestro (masterofflash@nate.com)

새로운 언어를 배울 때 첫번째 프로그램은 전통적으로 화면에 "Hello, world"란 구문을 출력해 보는 것입니다. Swift에서는 단 한줄로 이것이 가능합니다.

println("Hello, world")

C나 Objective-C에서 코드를 작성해본적이 있다면 Swift에서 이 한줄의 코드가 완전한 프로그램을 구성하는 이런 문법이 매우 익숙할 것입니다. 입.출력이나 문자열을 다루기 위한 함수들 같은 기능들을 위한 분리된 라이브러리를 임포트할 필요가 없습니다. 전역 범위(Global scope)로 쓰여진 코드는 프로그램의 진입점(entry point)로 사용되기 때문에, main 함수는 필요하지 않습니다. 또한 모든 문장끝에 세미콜론을 쓸 필요도 없습니다.

이 둘러보기는 다양한 프로그래밍 과제를 어떻게 완수해 나가는지 보여주면서 Swift로 어떻게 코드를 작성해야하는지에 대한 충분한 정보를 제공할 것입니다. 몇몇가지를 이해하지 못한다고 해서 걱정하지 마세요. 이번 장에서 소개되는 모든 것들은 책의 뒷 부분에서 자세히 설명될 것입니다.

>노트
최선의 경험을 위해서 이번 장을 Xcode안에서 playground로 열어보세요. Playground는 코드의 수정과 즉시 결과를 볼 수 있도록 해줄 것입니다.

##간단한 값

let을 사용하면 상수를 만들고 var를 사용하면 변수를 만들 수 있습니다. 상수는 컴파일 타임에 알고 있을 필요가 없습니다. 그러나 오직 한번만 값을 할당해야합니다. 이것은 상수를 값을 한번만 결정하고 여러곳에 쓰일 이름으로 사용할 수 있다는 것을 의미합니다.

```c
var myVariable =42
myVariable = 50
let myConstant = 42
```

상수나 변수 모두 당신이 할당하고 싶은 값의 타입을 가질 수 있습니다. 그러나 항상 타입을 명시해야만 하는 것은 아닙니다. 당신이 상수나 변수를 만들 때 할당한 값을 통해 컴파일러는 그 값의 타입을 추측합니다. 위의 예를 보면, myVariable이 정수형 값으로 초기화되었기 때문에 컴파일러는 정수형이라고 추측합니다.

만약 초기값이 충분한 정보를 제공하지 못한 경우(혹은 초기값이 없는 경우) 특정한 타입을 변수명 뒤에 세미콜론으로 분리하여 써주어야 합니다.

```c
let inplicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
```

>실험
4와 명시적으로 Float 형태의 값을 갖는 상수를 만들어보자.

값은 절대 암시적으로 다른 형태의 값으로 변환할 수 없습니다. 만약 다른 형태의 값으로 변화해야 한다면 명시적으로 원하는 형태의 인스턴스로 만들어야 합니다.

```c
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
```

>실험
마지막줄에 있는 String으로 변환 부분을 제거해보자. 어떤 에러가 발생하는가?

문자열 안에 값들을 포함하는 쉬운 방법도 있습니다. 괄호 안에 값을 쓰고 괄호 앞에 백슬래시를 쓰면 됩니다. 예를 들면

```c
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
```

>실험
문자열안에 \()를 이용해 실수형 계산을 포함하도록 해보고, 인사말 안에 누군가의 이름을 넣어보자.

배열과 딕셔너리는 대괄호([])를 이용해 만들 수 있습니다. 그리고 대괄호 안에 인덱스나 키를 이용해 각각의 요소에 접근할 수 있습니다.

```c
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"

var occupations = [
"Malcolm":"Captian",
"Kaylee":"Mechanic",
]
occupations["Jayne"] = "Public Relations"
```

빈 배열이나 딕셔너리를 만들려면, 초기화자(initializer) 문법을 사용하면 됩니다.

```c
let emptyArray = String[]()
let emptyDictionary = Dictionary()
```

타입 정보를 추론할 수 없다면 빈 배열은 []로 빈 딕셔너리는 [:]로 쓸 수 있습니다. 예를 들어 변수에 새로운 값을 할당하거나 함수에 인자로 넘겨줄 때

```c
shoppingList = [] //쇼핑을 가서 모든 것을 샀다.
```

##흐름 제어
if와 switch를 사용해서 조건문을 만들 수 있고 for-in, for, while, do-while을 이용해서 반복문을 만들 수 있습니다. 조건문과 반복문을 괄호로 감싸는 것은 선택사항입니다. 중괄호로 몸통을 감싸는 것은 필수입니다.

```c
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
teamScore
```

if문 안에 조건은 꼭 불리언(Boolean) 표현이어야 합니다. 이것은 if score {...} 이 0과의 비교를 암시하지 않기 때문에 에러가 발생합니다.

사라질 값을 가지고 if와 let을 함께 사용하는 것도 가능합니다. 이런 값들은 옵션으로 대표됩니다. 옵션값은 어떤 값을 가지거나 사라질 값을 표현하는 nil을 가지기도 합니다. 값의 타입 뒤에 물음표를 쓰면 옵션값이라는 것을 나타냅니다.

```c
var optionalString: String? = "Hello"
optionalString == nil

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
```

>실험
optionalName의 값을 nil로 바꿔보자. 어떤 greeting의 값을 받을 수 있는가? optionalName이 nil일 때 다른 값을 greeting에 할당하도록 else 절을 추가해보자.

만약 옵션값이 nil이라면 조건문은 false이고 중괄호 안에 있는 코드를 건너뛰게 됩니다. 반대의 경우에는 중괄호 블록 안에서 사용할 수 있도록 let 뒷부분의 상수에 값이 할당되고 옵션값으로 사용할 수 있습니다.

스위치(Switch) 구문에는 정수형 값이나 동등 비교연산 뿐만 아니라 어떤 종류의 데이터든 사용할 수 있고 다양한 비교 연산자들을 사용할 수 있습니다.

```c
let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)?"
default:
let vegetableComment = "Everything tastes good in soup."
}
```

>실험
스위치 구문에서 default의 경우를 제거해 보자. 어떤 에러가 발생하는가?

스위치 구문안의 일치하는 경우의 코드를 실행하고 나면 프로그램은 스위치 구문을 빠져나옵니다. 실행한 코드 이후에 나오는 내용은 실행하지 않기 때문에 각 경우의 코드 끝마다 빠져나오도록 명시적으로 써주지 않아도됩니다.(*역자 주: 보통 사용되는 break를 굳이 쓸 필요가 없다는 것입니다.)

for-in 문을 사용하면 각각 키-값 쌍으로 사용할 수 있는 이름들의 쌍을 이용해 딕셔너리에 있는 요소들을 반복처리할 수 있습니다.

```c
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
largest
```

>실험
계속 알아 보기 위해서 기존의 제일 큰 값만큼 큰 값을 가지는 요소를 추가해보자.

조건문이 변경될 때까지 코드 블록을 반복 실행하기 위해서 while 문을 사용해 봅시다.

반복문이 적어도 한번은 실행될 수 있도록 보장하기 위해서 조건문을 반복문 끝에 쓸수도 있습니다.

```c
var n = 2
while n < 100 {
n = n * 2
}
n

var m = 2
do {
m = m * 2
} while m < 100
m
```

반복문안에서 ..을 사용해 인덱스의 범위를 만들어 사용하거나 명시적으로 초기화, 조건문, 증감식을 사용하는 것 또한 가능합니다. 아래쪽에 나오는 두가지 반복문은 동일한 일을 수행합니다.

```c
var firstForLoop = 0
for i in 0..3 {
firstForLoop += i
}
firstForLoop

var secondForLoop = 0
for var i = 0; i < 3; ++i {
secondForLoop += 1
}
secondForLoop
```

..을 사용해서 범위를 지정하면 제일 나중값은 제외가 됩니다. 대신 ...을 사용하면 양쪽 끝값 모두 포함하게 됩니다.

##함수(Functions)와 클로저(Closures)

func를 사용해 함수를 선언할 수 있습니다. 함수의 이름과 괄호안에 인자들을 넣어서 함수를 호출할 수 있습니다. 매개변수들의 이름과 분리해서 ->를 사용해 타입을 써주면 함수 반환값의 타입을 지정할 수 있습니다.

```c
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
```

>실험
매개변수 day를 제거하고 오늘의 스페셜 런치 매개변수를 greeting에 추가해보자.

튜플(tuple)을 사용하면 여러개의 값을 반환할 수 있습니다.

```c
func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
getGasPrices()
```

함수는 배열을 이용해서 여러개의 값을 인자로 받는 것도 가능합니다.

```c
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(42, 597, 12)
```

>실험
인자들의 평균값을 계산하는 함수를 만들어보자.

함수는 다른 것에 포함될 수도 있습니다. 내장된(Nested) 함수는 감싸고 있는 함수에서 선언된 변수에 접근할 수 있습니다. 길어지고 복잡한 함수의 코드를 정리하기 위해 내장된 함수를 사용할 수 있습니다.

```c
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
```

함수는 최상위 타입입니다. 이것은 어떤 함수가 다른 함수를 반환값형태로 반환할 수 있다는 것을 의미합니다.

```c
func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
```

또 함수는 다른 함수를 인자로 받을 수 있습니다.

```c
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
```

함수는 실제로는 클로저의 특별한 예입니다. 중괄호로 묶기만 해서 이름없이 클로저를 사용할 수도 있습니다. in을 사용해 몸통에서 인자와 반환값 타입을 분리해 쓸 수 있습니다.

```c
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
```

>실험
모든 홀수값에 대해 0을 반환하도록 클로저를 수정해보자.

클로저를 간결하게 쓰기 위한 몇가지 옵션이 있습니다. 델리게이트(delegate)를 위한 콜백같이 이미 클로저의 타입을 아는 경우라면 매개변수의 타입, 반환값 타입을 모두 생략하거나 선택적으로 생략할 수 있습니다. 한줄짜리 구문을 가진 클로저라면 구문만 가지고도 반환 타입을 추측할 수 있습니다.

numbers.map({ number in 3 * number })

매개변수의 이름 대신에 번호로 참조하는 것은 클로저를 짧게 만드는데 특히 유용합니다. 이때 클로저는 함수의 바로 뒤에 중괄호를 이용해 인자로 전달됩니다.

sort([1, 5, 3, 12, 2]) { $0 > $1 }

##객체(Objects)와 클래스(Classes)

클래스를 만들기 위해서는 클래스 이름과 함께 class 키워드를 사용하면 됩니다.클래스 컨텍스트(context) 내부를 제외하고 클래스 안에 속성을 선언하기 위해서는 상수나 변수를 선언하는 것과 똑같은 방식으로 쓰면 됩니다. 마찬가지로 메서드와 함수도 선언할 수 있습니다.

```c
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
```

어떤 클래스의 인스턴스를 만들려면 클래스 이름 다음에 괄호를 넣으면 됩니다. .(점) 문법을 사용하면 인스턴스의 속성이나 메서드에 접근할 수 있습니다.

```c
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
```

현재 상태의 Shape클래스는 중요한 것이 빠져있습니다. 바로 클래스가 생성될 때 클래스를 초기화하기 위한 초기화자 입니다. init 키워드를 사용해 만들어 봅시다.

```c
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
```

인자의 name과 속성의 name을 구분하기 위해서 self 키워드가 어떻게 사용되는지 주의해서 봅시다. 클래스의 인스턴스를 만들 때 초기화자에 인자를 전달하는 방식은 함수에 전달하는 방식과 동일합니다. 모든 속성은 numberOfSides 처럼 값을 선언 할 때 혹은 name처럼 클래스를 초기화 할 때 처럼 적어도 둘중에 한가지 방법을 통해 값을 할당해줘야 합니다.

오브젝트를 해제하기전 정리 작업이 필요하다면 deinit을 사용해서 디이니셜라이저(deinitializer)를 만들 수 있습니다.

하위 클래스는 클래스명 뒤에 상위 클래스의 이름을 세미콜론으로 구분해 포함합니다. 꼭 기본 루트 클래스가 필요한 것은 아니기 때문에 상위 클래스를 포함해도 되고 생략해도 됩니다.

하위 클래스에서 상위 클래스에서 구현된 메서드를 오버라이드(override) 하려면 override 키워드를 이용해 표시해줘야 합니다. override키워드를 사용하지 않고 어떤 메서드를 갑자기 오버라이드하면 컴파일러에서 에러로 인식합니다. 또 override 키워드를 사용했는데 실제로 상위 클래스에는 해당 메서드가 없다면 이것 또한 컴파일러가 잡아냅니다.

```c
class Square: NamedShape {
var sideLength: Double

init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}

func area() -> Double {
return sideLength * sideLength
}

override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
```

>실험
NamedShape클래스의 또 다른 하위 클래스인 Circle을 만들어보자. 이 클래스는 이니셜 라이저를 통해 radius와 name을 인자로 받는다. Circle 클래스 안에 area, describe 함수를 구현해보자.

저장되어 있는 간단한 속성 외에도 속성은 getter와 setter를 가질 수 있습니다.

```c
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0

init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}

var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}

override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
```
perimeter의 setter안에서는 newValue라는 이름이 새로운 값을 나타내고 있습니다. 반면에 명시적으로 set 뒤에 괄호를 이용해 명시적으로 이름을 지정해 줄수도 있습니다.

EquilateralTriangle 클래스의 이니셜라이저는 세가지의 다른 단계를 가지고 있음을 살펴봅시다.

1. 하위 클래스에서 선언한 속성의 값을 지정합니다.
2. 상위 클래스의 이니셜라이저를 호출합니다.
3. 상위 클래스에 의해 정의된 속성값을 변경합니다. 어떤 메서드나 setter,getter를 사용하지 않고도 가능 하다는 것이 중요한점 입니다.

속성의 값을 계산할 필요는 없지만 새로운 값을 할당하기 전이나 후에 수행해야할 코드가 있다면 willSet, didSet을 사용할 수 있습니다. 예를 들면 아래쪽에 나오는 클래스에서는 삼각형의 빗면의 길이가 사각형의 옆면의 길이와 항상 동일하다는 것을 보장합니다.

```c
class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size: Double, name: String) {
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength
```

클래스에 있는 메서드들은 함수와는 다른 중요한 특징이 한가지 있습니다.함수에서 사용되는 매개변수의 이름들은 함수 내부에서만 사용합니다. 그러나 메서드에 사용되는 매개변수의 이름은 메서드를 호출할 때도 사용됩니다(첫번째 매개변수의 이름은 제외하고). 기본적으로 메서드는 호출할 때 혹은 메서드에서 사용되는 이름과 동일한 매개변수 이름을 갖습니다. 하지만 메서드 내부에서 사용될 두번째 이름을 특별히 정해줄 수도 있습니다.

```c
class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes times: Int) {
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
```
옵션 값을 사용할 때는 메서드나 속성, 서브스크립트 앞에 ?를 쓸 수 있습니다. 만약 ? 앞에 값이 nil 이라면 ? 이후에 나오는 모든 것은 무시되고 표현의 값들은 nil을 갖습니다. 반면에 값이 있는 경우라면 ? 이후의 모든 그 값을 기준으로 동작합니다. 양쪽 경우 모두 옵션 값으로 사용됩니다.

##열거형(Enumerations)과 구조체(Structures)
enum 키워드를 사용하면 열거형을 만들 수 있습니다. 클래스나 모든 알려진 타입들의 경우 열거형에 메서드를 포함할 수 있습니다.

```c
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
```

>실험
두개의 Rank 값의 원본 값을 비교하는 함수를 만들어보자.

위의 예를 보면 열거형의 원본 값의 타입은 int 입니다. 그래서 특별히 첫번째 원본값만 가지고 있는 것입니다. 나머지 원본 값들은 순서에 따라 자동으로 할당됩니다. 또 문자열이나 실수형태의 값들도 원본값으로 가진 열거형을 만들 수 있습니다.

toRaw와 fromRaw 함수를 사용해서 원본값과 열거형 값을 상호 변환할 수 있습니다.

```c
if let convertedRank = Rank.fromRaw(3) {
let threeDescription = convertedRank.simpleDescription()
}
```

열거형의 구성값들은 실제 값을 쓰는 다른 방법일 뿐 아니라. 모두 실제 값입니다. 사실 실제값이 의미있는 경우가 아니라면 굳이 첫번째 값을 제공할 필요가 없습니다.

```c
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
```

>실험
Suit에 color 메서드를 추가해 보자. color 메서드는 스페이드와 클로버는 'black'을 반환하고 하트와 다이아몬드는 'red'를 반환하도록 하면 됩니다.

열거형의 구성중 하나인 Heart가 상단값을 어떻게 참조하는지 두가지 방법을 살펴봅시다. 상수 hearts에 값을 할당 할 때, 상수는 명시적으로 타입을 가지고 있지 않기 때문에 Suit.Hearts 처럼 전체 이름을 살펴봅니다. 스위치문 안에서는 열거형은 .Hearts로 축약형을 써서 참조하는데, 이것은 self가 이미 suit라는 것을 알고 있기 때문입니다. 값의 형을 이미 알고 있다면 언제든지 축약형을 사용해도 됩니다.

구조체를 만들기 위해서는 struct 키워드를 사용합니다. 구조체는 메서드나 이니셜라이저 같은 클래스와 비슷한 기능들을 지원합니다. 클래스와 구조체의 가장 중요한 차이점중 하나는 구조체의 경우 코드 내에서 전달될 때 값복사 형태로 전달되지만 클래스의 경우에는 참조복사 형태로 전달된 다는 것입니다.

```c
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
```
>실험
각 카드를 rank와 suit를 조합해서 만들어 전체 카드를 만들어 주는 메서드를 Card에 추가해보자.

열거형 구성자의 인스턴스는 인스턴스와 함께 관련값들을 사용할 수 있습니다. 같은 열거형의 구성자의 인스턴스들은 각 인스턴스와 함께 다른 관련값을 가질 수 있습니다. 인스턴스를 만들 때 관련값을 공급할 수 있습니다. 관련값과 원본값은 다릅니다. 열거형 구성자의 원본값은 모든 인스턴스에서 같은 값(열거형을 정의할 때 지정한 값)을 갖습니다.

예를 들면, 일출, 일몰 시간을 서버에 요청한다고 가정해보자. 서버는 두 시간 모두를 응답하거나 에러 정보를 응답할 수도 있다.

```c
enum ServerResponse {
case Result(String, String)
case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
let serverResponse = "Failure... \(error)"
}
```

>실험
ServerResponse에 세번째 경우를 추가하고 스위치문에도 추가해보자.

스위치문의 경우의 수와 비교를 수행하기 위해 ServerResponse로 부터 일출, 일몰 시간 값을 어떻게 추출해 내는지 눈여겨 보자.

##프로토콜(Protocols)와 확장(Extensions)##

프로토콜을 선언하기 위해 protocol 키워드를 사용하자

```c
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
```

클래스, 열거형, 구조체 모두에 프로토콜을 사용할 수 있다.

```c
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
```

>실험
프로토콜을 사용하는 열거형을 만들어보자.

구조체를 수정하기 위해 사용되는 메서드를 표시하기 위해 SimpleStructure 선언부에 사용되는 mutating 키워드를 살펴봅시다. SimpleClass에는 mutating으로 표시된 메서드가 필요하지 않습니다. 왜냐하면 클래스 안에 있는 모든 메서드들은 항상 클래스를 수정할 수 있기 때문입니다.

extension 키워드를 사용해서 기존의 타입들에 새로운 메서드나 속성들을 비교하기 위한 기능들을 추가할 수 있습니다. 타입이 선언된 곳 어디서든 혹은 라이브러리나 프레임워크에서 불러온 타입들에 extension 키워드를 사용해 프로토콜을 적용할 수 있습니다.

```c
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
7.simpleDescription
```

>실험
extension을 사용해 Double 타입에 absoluteValue 속성을 추가해보자.

프로토콜 이름은 다른 알려진 변수들 처럼 지정할 수 있습니다. 예를 들면 객체들의 모음을 만들 때, 모든 객체는 다른 타입을 가지지만 하나의 프로토콜을 따릅니다. 프로토콜 타입인 값들을 가지고 작업할 때 프로토콜 외부에서 메서드를 정의하는 것은 불가능 합니다.

```c
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty // Uncomment to see the error
```

protocalValue 변수가 실행시 SimpleClass 타입이더라도 컴파일러는 주어진ExampleProtocal 타입으로 취급합니다. 이것은 프로토콜 관습 외에도 클래스에서 구현된 메서드나 속성에 실수로 접근할 수는 없다는 것을 의미합니다.

##제네릭(Generics)

제네릭 함수나 타입을 만들려면 꺾쇠안에 이름을 쓰면 됩니다.

```c
func repeat(item: ItemType, times: Int) -> ItemType[] {
var result = ItemType[]()
for i in 0..times {
result += item
}
return result
}
repeat("knock", 4)
```

클래스, 열거형, 구조체와 마찬가지로 함수나 메서드를 제네릭 형태로 만들 수 있습니다.

```c
// Reimplement the Swift standard library's optional type
enum OptionalValue {
case None
case Some(T)
}
var possibleInteger: OptionalValue = .None
possibleInteger = .Some(100)
```

특정 요구 조건들의 타입 뒤에 `where`키워드를 사용해 봅시다. 예를 들어 프로토콜 구현의 위한 타입을 요구하거나 똑같은 타입을 요구하는 경우 혹은 특정 상위 클래스를 요구하는 경우 말입니다.

```c
func anyCommonElements (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
```

>실험
anyCommonElements 함수를 공통적으로 두개의 연속값을 갖는 배열을 반환하도록 수정해 봅시다.

간단한 경우에는 where을 생략하고 프로토콜과 클래스 이름을 콜론뒤에 바로 쓸 수 있습니다. ``과 ``은 동일합니다.

chapter24

No preview for this file type

chapter25
# 25 고급 연산자 (Advanced Operators)
> Translator : 심상진 (dyanos@gmail.com)

기본 연산자 항목에서 설명했던 연산자들에 더하여, Swift는 훨씬 다양한 방법으로 값을 다루는 몇개의 고급 연산자들을 제공합니다. 이들은 당신이 C와 Objective-C에서 부터 친근하게 여겼던 비트를 다루는 연산자들 모두를 포함합니다.

C에서의 산술 연산자들과는 다르게, Swift에서의 산술 연산자들은 기본적으로 넘침(Overflow)이 일어나지 않습니다. 넘치는 동작(Overflow behavior)은 오류로써 잡히고 보고됩니다. 넘치는 동작을 허용하기 위해서, 넘침을 기본으로 하는 산술 연산들 중에 Swift의 두번째 집합을 사용해야 합니다. 예를 들어, 넘침 덧셈(overflow addition, &+)이 그러한 집합에 속합니다. 모든 넘침 연산자들은 엠퍼샌드(ampersand, &)를 가지고 시작합니다.

당신이 당신 소유의 구조체들과 클래스, 그리고 열거자들을 선언할때, 이들 커스텀 타입들에 대해서 표준 Swift 연산자들의 독자적인 구현들(own implementations)을 제공하는데 유용할 수 있습니다. Swift는 이들 연산자들의 맞춤형(tailored) 구현들을 제공하고 그들의 행동이 당신이 만든 각각의 타입에 대해서 무엇을 해야할지를 정확하게 결정하기 쉽게 만듭니다. (역자 주, operator overload)

당신은 연산자들을 재정의하는데 아무런 제한이 없습니다. Swift는 당신에게 당신 자신의 맞춤형 중간(infix), 전위(prefix), 후위(postfix) 그리고 할당 연산자들을 정의하는데 자유를 줍니다. 그리고 그것들의 우선순위와 결합순위 역시 자유롭게 정의가 가능합니다. 이들 연산자들은 마치 이미 선언된 연산자들 처럼 당신의 코드 안에 사용되고 적용될 수 있고, 당신은 당신이 정의한 맞춤형 연산자들을 지원하도록 이미 존재하는 타입들조차 확장할 수 있습니다.

**비트 연산자들**

비트 연산자들은 당신에게 하나의 데이터 구조체 안에 있는 개개의 가공되지 않은 데이터 비트들(raw data bits)을 다루는 것을 허용합니다. 그들은 종종 그래픽 프로그래밍과 디바이스 드라이버 프로그래밍(device driver creation)과 같은 저수준 프로그래밍에 사용됩니다. 또한 비트 연산자들은 당신이 외부의 입력들(external source)로부터 오는 가공되지 않은 데이터(raw data)를 가지고 작업할때 유용합니다. 예를 들어, 커스텀 프로토콜을 이용한 통신에서 데이터의 부호화(encoding)와 복호화(decoding)과 같은 것들이 그것입니다.

Swift는 C에서 발견되는 모든 비트 연산자들을 지원합니다. 이는 아래에서 좀더 자세히 설명드리겠습니다.

**비트 NOT 연산자**

비트 NOT 연산자(~)는 다음과 같이 숫자의 모든 비트들을 뒤집습니다.(invert)



비트 NOT 연산자는 전위연산자입니다. 그리고 공백없이, 연산하는 값 바로 앞에 나타납니다.

1: let initialBits: UInt8 = 0b00001111
2: let invertedBits = ~initialBits // equals 11110000

UInt8 정수들은 8개의 비트를 가지며, 0에서부터 255까지의 임의의 값을 저장할 수 있습니다. 이 예는 UInt8 정수 변수를, 최초의 4개 비트는 0으로, 나머지 4개비트는 1로 설정한, 이진 값 00001111을 가지도록 초기화합니다. 이것은 십진수 15와 동일한 것입니다.

다음 줄에서, 비트 NOT 연산자는 invertedBits라 불리우는 새로운 상수를 생성하는데 사용합니다. 이것은 initialBits와 동일하지만 모든 비트들이 뒤집어져 있습니다. 다시말해, 이때 initialBit의 비트들중에 0은 1이되고, 1은 0이 됩니다. "그러므로" invertedBits의 값은 11110000이 됩니다. 이것은 부호없는 십진수 240과 동일합니다.

**비트 AND 연산자**

비트 AND 연산자(&)는 두 숫자의 비트들을 결합합니다. 비트들이 다음과 같이 양쪽 입력 숫자들에서 1과 같아야만 비트들이 1로 설정되는 새로운 숫자을 돌려받습니다.(""""좀더 명확하게 이해되도록 수정해야할 필요가 있음"""")



아래의 예에서, firstSixBits변수와 lastSixBits양쪽의 값들은 4개의 중간 비트가 1로 되어있습니다. 비트 AND 연산자는 그들을 부호없는 십진수 60과 동일한 숫자인 00111100로 만들도록 조합합니다.

1: let firstSixBits: UInt8 = 0b11111100
2: let lastSixBits: UInt8 = 0b00111111
3: let middleFourBits = firstSixBits & lastSixBits // equals 00111100

**비트 OR 연산자**

비트 OR 연산자(|)는 두 수의 비트들을 비교합니다. 연산자는 만일 다음처럼 입력 수들 중에 어떤 하나가 비트 1이면, 비트가 1로 설정된 새로운 수를 돌려줍니다.



아래의 예제에서, someBits와 moreBits의 값은 1로 설정된 다른 비트들을 가집니다. 비트 OR 연산자는 그들을 부호없는 십진수 256와 동일한 숫자인 11111110으로 만들어지도록 조합합니다.

1:let someBits: UInt8 = 0b10110010
2:let moreBits: UInt8 = 0b01011110
3:let combinedbits = someBits | moreBits // equals 11111110”

**비트 XOR 연산자**

비트 XOR 연산자 또는 배타적(exclusive) OR 연산자 (^)는 두 수의 비트들을 비교합니다. 연산자는 다음과 같이 입력 비트들이 다르면 1로 같으면 0으로 설정되어진 새로운 수를 돌려받습니다.



아래 예에서, firstBits와 otherBits 각각의 값들은 하나의 위치에서 1로 설정된 하지만 다른 변수에서는 그렇지 않은 비트를 가집니다. 비트 XOR 연산자는 그것들의 출력 값에서 이들 비트들의 양쪽을 1로 설정합니다. firstBits와 otherBits에서 모든 다른 비트들은 같으며, 이것은 다음과 같이 출력 값에서 0으로 나타납니다.

1:let firstBits: UInt8 = 0b00010100
2:let otherBits: UInt8 = 0b00000101
3:let outputBits = firstBits ^ otherBits // equals 00010001

**비트 왼쪽 및 오른쪽 이동(shift) 연산자들**

비트 왼쪽 이동 연산자(<<)와 비트 오른쪽 이동 연산자(>>)는 수에서 아래 정의된 규칙에 따라서, 특정 수의 위치(a certain number of places)로 모든 비트들을 왼쪽 또는 오른쪽으로 이동시킵니다.

비트 왼쪽 그리고 오른쪽 이동은 2의 인수로 정수에 곱한 것과 나눈 것의 효과를 가집니다. 왼쪽으로 한 자리만큼 정수의 비트들을 이동하는 것은 값을 두배로 하는 것과 같은 효과를 나타냅니다. 마찬가지로 오른쪽으로 이동하는 것은 2로 나누는 것과 동일한 효과를 가집니다.

**부호없는 정수들에 대한 이동 방법**

부호없는 정수의 비트 이동은 다음처럼 합니다.

1. 존재하는 비트들은 요청된 수의 위치로(the requested number of places) 왼쪽 또는 오른쪽으로 이동되어 집니다.
2. 정수 공간의 크기를 넘어 이동된 비트들은 버려집니다.
3. 원래의 비트들이 이동되고 남은 자리에 0이 삽입됩니다.

이 접근은 논리적 이동(또는 옮김)으로써 알려져 있습니다.

아래의 그림은 11111111<<1의 결과를 보여줍니다.(여기서는 왼쪽으로 1만큼 이동하는 것을 말합니다.) 그리고 11111111>>1(이것은 오른쪽으로 1만큼 이동하는 것을 말합니다.) 여기서 파란색 비트들은 이동된 비트들을 말하며, 회색 비트들은 버려진 것을 말합니다. 그리고 오랜지색의 0은 삽입된 것을 말합니다.

<>

여기서는 Swift 코드 안에서 어떻게 비트 이동을 하는지를 다음의 실제 코드로 보여줍니다.

1:let shiftBits: UInt8 = 4 // 00000100 in binary
2:shiftBits << 1 // 00001000
3:shiftBits << 2 // 00010000
4:shiftBits << 5 // 10000000
5:shiftBits << 6 // 00000000
6:shiftBits >> 2 // 00000001

당신은 다음과 같이 다른 데이터 타입들안에 있는 값들을 부호화하기 위해서 그리고 복호화하기 위해서 비트 이동을 사용할 수 있습니다.

1:let pink: UInt32 = 0xCC6699
2:let redComponent = (pink & 0xFF0000) >> 16 // redComponent is 0xCC, or 204
3:let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent is 0x66, or 102
4:let blueComponent = pink & 0x0000FF // blueComponent is 0x99, or 153

이 예제는 핑크색에 대한 Cascading Style Sheets 색 값을 저장하기 위해 pink로 불리우는 UInt32 타입의 상수를 사용합니다. CSS 컬러 값 #CC6699는 Swift의 16진수 표현으로 0xCC6699가 됩니다. 이 색깔은 비트 AND 연산자(&)와 비트 오른쪽 이동 연산자(>>)를 사용하여 빨간색 (CC), 녹색(66), 파란색 (99) 요소들로 나누어서 나타낼 수 있습니다.

빨간색 요소는 숫자 0xCC6699와 0xFF0000사이에 비트 AND 연산을 수행하므로써 얻어집니다. 0xFF0000에서, 6699를 무시되게 하기 위해서 그리고 결과에서 0xCC0000를 남기기 위해서, 0은 효과적으로 0xCC6699의 두번째와 세번째 바이트를 가려줍니다.(mask)

그때 이 수는 오른쪽으로 16칸 이동(>>16)합니다. 16진수에서의 두자리는 2진수의 8비트와 같습니다, 그래서 오른쪽으로 16칸짜리 이동은 0xCC0000를 0x0000CC로 변환할 것 입니다. 이것은 10진수 204인 0xCC와 같습니다.

비슷하게, 녹색 요소는 출력으로써 0x006600을 주는 0xCC6699와 0x00FF00사이에 비트 AND 연산을 수행하므로써 얻어집니다. 이 출력은 오른쪽으로 8칸 이동되어 지고, 10진수로 102에 해당하는 0x66의 값을 줍니다.

마지막으로, 파란색 요소는 출력으로 0x000099를 주는 0xCC6699와 0x0000FF사이의 비트 AND 연산을 수행하므로써 얻어집니다. 여기서는 오른쪽으로의 이동이 필요없습니다. 이미 0x000099는 10진수로 153에 해당하는 0x99와 동일하기 때문입니다.

부호있는 정수의 이동 모습(behavior)

이동은 부호있는 정수를 할때 부호없는 정수때보다 더 복잡합니다. 이는 부호있는 정수를 이진수로 표현하는 방식때문입니다. (아래 예들은 간단함을 위해 8비트 부호있는 정수들을 기본으로 하여 진행됩니다. 그러나 어떠한 크기의 부호있는 정수에도 앞으로 나올 원칙을 적용할 수 있습니다.)

부호있는 정수들은 (부호 비트로 알려진) 그들의 첫번째 비트를 그 정수가 양의 정수인지 음의 정수인지를 타나내는데 사용합니다. 부호비트가 0이면 양수를, 부호비트가 1이면 음수를 의미합니다.

값 비트로 알려진 남아 있는 비트들은 실제 값을 저장합니다. 양의 정수는 정확하게 부호없는 정수에 대해서 하는 것과 같이 정확하게 같은 방법인 0부터 위쪽으로 계산하는 방법(counting upwards from 0)으로 저장합니다. 여기서는 어떻게 Int8안에서 숫자 4를 표현하는지 보여줍니다.



부호 비트가 0(즉, 양수)이고, 7개의 값 비트들은 단지 이진 표현으로 쓰여진 숫자 4를 의미합니다.

그렇지만 음수는 다르게 저장됩니다. 2의 n승에서 그들의 절대값을 빼므로써 저장됩니다. 이때 n은 값 비트의 수를 의미합니다. 8비트 수는 7개의 값 비트를 가집니다. 그래서 이것은 2의 7승 또는 128을 의미합니다.

여기서는 어떻게 Int8에서 -4를 표현하는지 보여줍니다.



이번에는, 부호 비트가 1(즉, 음수)이고, 7개의 비트는 이진값으로 (128 - 4인) 124를 가집니다.



음수에 대한 부호화 방법은 2의 보수 표현현으로써 알려져 있습니다. 이것은 이상한 방법처럼 보이지만, 이러한 방법은 몇가지 이득을 가집니다.

첫번째 당신은 다음과 같이 (부호 비트를 포함하는) 모든 8개의 비트들에 대해서 표준 이진 덧셈을 하고, 8비트에 적합하지 않은 어떤것도 버릴필요없이 간단하게 -1을 -4에 더할 수 있습니다.



두번째, 2의 보수 표현은 당신에게 양수에서와 같이 음수의 비트들을 왼쪽 또는 오른쪽으로 이동시키고, 여전히 왼쪽 이동에 대해서 그들을 배가하거나 오른쪽 이동으로 반분되어지도록 합니다. 이것을 이루기 위해서, 부호있는 정수를 오른쪽으로 이동시킬때 다음의 추가적인 규칙들이 적용됩니다.

당신이 오른쪽으로 부호있는 정수를 이동시킬때, 부호없는 정수에서와 같은 규칙들을 적용하면 됩니다만 부호와 함께 왼쪽에 있는 임의의 빈 비트들을 0과는 다른 것으로 채워야 합니다.



이러한 행동은 부호있는 정수들이 오른쪽으로 이동후에도 같은 부호를 가지는 것을 확실히 하기 위해서 입니다. 그리고 이러한 행동은 산술 이동이라고 알려져 있습니다.

양수와 음수가 저장되는 특별한 방식 때문에, 그들 중에 하나를 오른쪽으로 이동하는 것은 그들을 0으로 이동합니다. 이러한 이동동안 부호 비트를 같게 유지하는 것은 음수를 그들의 값을 0으로 옮기는 동안에도 음수로 남아있게 한다는 것을 의미합니다.

넘침 연산자들

만일 당신이 값을 유지할 수 없는 정수 상수 또는 변수에 하나의 숫자를 넣기를 시도한다면, 기본적으로 Swift는 유효하지 않은 값이 생성되기를 허락하기 보다는 오류를 보고 합니다. 이 행동은 당신이 너무 큰거나 너무 작은 숫자들을 가지고 작업할때 추가적인 안전함(extra safety)을 당신에게 제공합니다.

예를 들어, Int16 정수 타입은 -32768부터 32767까지의 임의의 부호있는 정수를 가지고 있을 수 있습니다. UInt16 상수 또는 변수에 이 범위를 벗어나는 숫를 설정하려고 노력하는 것은 오류를 일으킵니다.

1:“var potentialOverflow = Int16.max
2:// potentialOverflow equals 32767, which is the largest value an Int16 can hold
3:potentialOverflow += 1
4:// this causes an error”

값이 너무 크거나 너무 작을때 다루는 오류를 제공하는 것은 경계값 조건에 대해서 코딩할때 훨씬 더 많은 유연성을 당신에게 줍니다.

그렇지만, 당신이 가능한 비트들의 수를 일부를 줄이기 위해서 넘침 조건을 특별히 원할때, 당신은 오류를 일으키는 것보다 다음의 행동으로 이를 수행할 수 있습니다. Swift는 정수 계산에 대해서 넘침 동작을 수행할 수 있는 다섯가지의 넘침 연산자들을 제공합니다. 이들 연산자들 모두는 앰퍼센트(&)를 가지고 시작합니다.

Overflow addition (&+)
Overflow subtraction (&-)
Overflow multiplication (&*)
Overflow division (&/)
Overflow remainder (&%)”

값 넘침

여기서는 넘침 덧셈 연산자(&+)를 사용하여, 부호없는 값이 넘침이 허용될때 무슨일이 일어나는지에 대한 예를 보여줍니다.

1:“var willOverflow = UInt8.max
2:// willOverflow equals 255, which is the largest value a UInt8 can hold
3:willOverflow = willOverflow &+ 1
4:// willOverflow is now equal to 0

변수 willOverflow는 UInt8이 가질 수 있는 최대 값(즉, 255 또는 이진수로 11111111)으로 초기화되어 있습니다. 그때 넘침 덧셈 연산자(&+)를 사용하여 1을 증가시킵니다. 이것은 그것들의 이진 표현을 UInt8의 크기를 넘도록 밀어내는데, 이것은 아래 그림에서 보여지듯이 범위를 넘어서서 넘침을 발생시킵니다. 넘침 덧셈 이후로 UInt8의 범위안에 남아있는 값은 00000000 또는 0입니다.



값 언더플로

숫자들은 또한 그들 타입의 최대 범위안에서 맞기에는 너무 작게 될 수 도 있습니다. 여기에 예제가 있습니다.

UInt8가 유지할 수 있는 가장 작은 수는 0(즉, 8비트 이진 형태에서는 00000000이 됩니다.)입니다. 만일 당신이 넘침 뺄셈 연산자를 사용하여 00000000으로부터 1을 뺀다면, 그 수는 이진수 11111111 또는 십진수 255으로 꺼꾸로 넘칠 것 입니다.



다음은 Swift코드 에서 어떻게 보이는 지를 나타냅니다.

1:var willUnderflow = UInt8.min
2:// willUnderflow는 UInt8이 유지할 수 있는 가장 작은 값인 0이 됩니다.
3:willUnderflow = willUnderflow &- 1
4:// 현재 willUnderflow는 255와 동일합니다.

유사한 언터플로는 부호있는 정수에서 발생됩니다. 부호있는 정수들에 대한 모든 뺄셈은 직접적인 이진 뺄셈으로써 수행됩니다. 이는 밸셈을 하고있는 숫자의 부분으로써 포함되어 있는 부호비트도 함께이며, 비트 왼쪽 그리고 오른쪽 연산자들에서 설명한 것과 같습니다. Int8인 가질 수 있는 가장 작은 값은 -128입니다. -128은 이진수로 10000000로 나타납니다. 넘침 연산자를 가지고 이 이진 수로부터 1을 빼는 것은 01111111의 이진 수를 줍니다. 이것은 부호비트를 뒤집고 양수 127을 줍니다. 이는 Int8이 가질 수 있는 가장 큰 양의 수입니다.



다음은 Swift코드에서의 표현입니다.

1:var signedUnderflow = Int8.min
2:// signedUnderflow는 -128과 같습니다. 이는 Int8이 가질 수 있는 가장 작은 값입니다.
3:signedUnderflow = signedUnderflow &- 1
4:// signedUnderflow는 지금 127과 같습니다.

위에 설명된 넘침과 언터플로의 행동의 마지막 결과는 부호있는 그리고 부호없는 정수 양쪽에 대해서, 항상 넘침이 가장 크게 유효한 정수 값으로 부터 가장 작은 것으로 반복되며, 언더플로는 가장 작은 값으로부터 가장 큰 값으로 반복됩니다.

0으로 나누기

0으로 숫자를 나는 것(i/0) 또는 0으로 나머지를 계산하기(i%0)를 시도하는 것은 오류를 발생시킵니다.

1:let x = 1
2:let y = x / 0

그렇지만 이들 연산자들(&/와 &%)의 오버플로 버젼들은 당신이 만일 0으로 나누면 0의 값을 돌려줍니다.

1:let x = 1
2:let y = x &/ 0
3:// y는 0입니다.

우선순위와 결합순위

연산자 우선순위는 다른 것보다 더 높은 우선 순위를 몇몇 연산자에게 줍니다: 이들 연산자들은 첫번째로 계산되어 집니다.

연산자 결합순위는 같은 우선순위의 연산자들이 어떻게 함께 그룹화되는지 또는 왼쪽으로부터 그룹화되는지, 아니면 오른쪽으로부터 그룹화되는지를 정의합니다. "그들이 그들의 오른쪽으로 그 표현(expression)과 관련있다는 의미 또는 "그들은 그들의 오른쪽으로 그 표현과 관련있다는 의미로써 그것을 생각해보세요.(해석이 애매함...)

복합 표현이 계산될 곳에서 계산 순서로 계산할때 각각의 연산자의 우선순위와 결합순위를 고려하는 것은 중요합니다. 다음은 예입니다. 왜 다음에 표현이 4일까요?

1:2 + 3 * 4 % 5
2:// 이것은 4와 동일합니다.

엄격하게 왼쪽에서부터 오른쪽으로 얻어질때, 당신은 이것을 다음처럼 읽기를 기대할지도 모릅니다.

1.2 더하기 3은 5입니다.
2.5 곱하기 4는 20입니다.
3.20을 5로 나누었을때의 나머지는 0입니다.

그렇지만, 실제 답은 0이 아니라 4입니다. 더 높은 우선순위의 연산자들은 낮은 우선순위를 가진 연산자보다 먼저 계산되어 집니다. Swift에서는, C에서와 같이, 곱셈 연산자(*)와 나머지 연산자(%)는 덧셈 연산자(+)보다 더 높은 우선순위를 가집니다. 결과적으로, 그들은 덧셈이 고려되기 전에 양쪽다 계산되어집니다.

그렇지만, 곱셈과 나머지 연산자는 서로에 대해서 같은 우선순위를 가집니다. 사용하기 위한 정확한 계산 순위를 이끌어내기 위해서, 당신은 또 그들의 결합을 고려할 필요가 있습니다. 곱셈과 나눗셈 양쪽은 표현을 그들의 왼쪽과 결합시킵니다. 그들의 오른쪽에서 시작하는 표현의 이들 부분들 주변에 내포된 괄호를 더함으로써 이것을 생각해보세요.

2 + ((3 * 4) % 5)

(3 * 4)는 12입니다. 그래서 이것은 다음으로 표현됩니다.

2 + (12 % 5)

(12 % 5)는 2입니다. 역시 이것은 다음으로 표현됩니다.

2 + 2

이것의 계산은 4를 답으로써 이야기합니다.

Swift에서 연산자 우선순위오 결합순위의 완벽한 목록에 대해서는 "Expressions" 항목을 보세요.

참고

Swift의 연산자 우선순위와 결합순위 규칙은 C와 Objective-C에서 발견되는 것보다 더 간단하고 더 쉽게 예측될 수 있습니다. 하지만, 이것은 그것들이 C를 기본으로하는 언어들에서와 완전히 같지 않다는 것을 의미합니다. 여전히 연산자들 간의 상호작용이 이미 존재하는 코드를 Swift코드로 포팅할때 당신이 의도하는 방식으로 동작하는지에 대해서 확신을 가지고 주의깊게 적용해야 합니다.

연산자 함수들

클래스와 구조체는 이미 존재하는 연산자들에 대해서 그들 자신의 구현을 제공할 수 있습니다. 이것은 이미 존재하는 연산자들을 오버로딩하는 것으로 알려져 있습니다.

아래의 예는 사용자 정의 구조에 대해서 산술 덧셈 연산자(+)를 어떻게 구현할 수 있는지를 보여줍니다. 산술 덧셈 연산자는 두개의 대상에서 동작하기 때문에 2항 연산자이며, 그것이 이들 두개의 대상 사이에서 나타나기 때문에 중간연산자라고 불리울 수 있습니다.

예는 2차원 위치 벡터 (x, y)에 대한 Vector2D 구조체를 정의합니다. 여기서 Vector2D 구조체의 인스턴스들을 함께 더하기 위한 연산자 함수의 정의가 뒤따릅니다.

1:struct Vector2D {
2: var x = 0.0, y = 0.0
3:}
4:@infix func + (left: Vector2D, right: Vector2D) -> Vector2D {
5: return Vector2D(x: left.x + right.x, y: left.y + right.y)
6:}

연산자 함수는 '+'이라고 불리우는 전역 함수로써 선언됩니다. 이 함수는 두개의 입력 파라메터로 Vector2D 타입을 가지며, 하나의 단일 출력 값을 돌려줍니다. 이때 출력 값의 타입은 Vector2D입니다. 당신은 @infix라는 속성을 연산자 함수 선언할때 'func' 키워드 앞에 쓰므로써 중간 연산자를 구현하는 것이 됩니다.

이 구현에서, 입력 파라메터들은 '+' 연산자의 왼쪽과 오른쪽에 있는 타겟들을 Vector2D 인스턴스로 표현하는 left와 right라는 변수로 이름지어져 있습니다. 이 함수는 새로운 Vector2D 인스턴스를 돌려줍니다. 새로운 인스턴스의 x와 y는 더해지는 두개의 Vector2D 인스턴스들로부터 x속성들의 합과 y속성들의 합으로써 초기화 되어집니다.

함수는 Vector2D 구조체상의 하나의 함수로써가 아닌, 전역적으로 정의되어 집니다. 그것은 존재하는 Vector2D 인스턴스들 사이의 중간 연산자로써 사용되기 위해서 입니다.

1:let vector = Vector2D(x: 3.0, y: 1.0)
2:let anotherVector = Vector2D(x: 2.0, y: 4.0)
3:let combinedVector = vector + anotherVector
4:// combinedVector는 (5.0, 5.0)의 값을 가진 Vector2D 구조체의 인스턴스입니다.

이 예는 아래의 그림처럼 두 벡터 (3.0, 1.0)과 (2.0, 4.0)을 벡터 (5.0, 5.0)으로 만들기 위해서 더 합니다.



전위 연산자와 후위 연산자들

위에서 보여준 예는 2항 중간 연산자의 사용자 정의 구현을 설명한 것 입니다. 클래스와 구조체들은 표준 단항 연산자들의 구현을 제공해줄 수 있습니다. 단항연산자들은 단일 타겟에 대해서 동작합니다. 만일 그것들이 그들의 타겟보다 앞서서 나타난다면(예를 들어 -a와 같은) 전위 연산자이고, 반대로 그들의 타겟 뒤에서 나타난다면(i++과 같은) 후위 연산자라고 말합니다.

당신은 연산자 함수를 선언할때 'func' 키워드 앞에 '@prefix' 또는 '@postfix' 속성을 사용하므로써 전위 또는 후위 단항 연산자를 구현합니다.

1:@prefix func - (vector: Vector2D) -> Vector2D {
2: return Vector2D(x: -vector.x, y: -vector.y)
3:}

위의 예는 Vector2D 인스턴스에 대해서 단항 뺄셈 연산자(-a)를 구현합니다. 단항 뺄셈 연산자는 전위 연산자이고, 그래서 이 함수는 '@prefix'속성으로 전위연산자임을 알려주어야 합니다.

간단한 수치 값들에 대해서, 단항 뺄셈 연산자는 양수를, 부호를 뒤집을때 같아지는 음수로 변환합니다. Vector2D에 대한 동일한 구현은 x와 y속성들 양쪽에 이 동작을 수행합니다.

1:let positive = Vector2D(x: 3.0, y: 4.0)
2:let negative = -positive
3:// 음수는 (-3.0, -4.0)의 값을 가지는 Vector2D 인스턴스가 됩니다.
4:let alsoPositive = -negative
5:// alsoPositive는 (3.0, 4.0)의 값을 가지는 Vector2D 인스턴스가 됩니다.

복합 할당 연산자

복합 할당 연산자들은 다른 동작에 할당(=) 연산자를 결합한 것 입니다. 예를들어, 덧셈 할당 연산자(+=)는 하나의 동작안에 덧셈과 할당 연산을 합친 것 입니다. 복합 할당 연산자를 구현하는 연산자 함수는 '@assignment' 속성을 기술하므로써 결합 할당 연산자임을 알려주어야 합니다. 당신은 또한 복합 할당 연산자들의 왼쪽 입력 파라메터들을 'inout'으로써 표시해야만 합니다. 이것은 파라메터의 값이 연산자 함수안에서 직접적으로 수정될 것이기 때문입니다.

아래 예는 Vector2D 인스턴스들에 대해서 덧셈 할당 연산자 함수를 구현한 것 입니다.

1:@assignment func += (inout left: Vector2D, right: Vector2D) {
2: left = left + right
3:}

덧셈 연산자는 더 먼저 정의되었기 때문에, 당신은 덧셈 절체를 여기서 다시 구현할 필요가 없습니다. 대신에 덧셈 할당 연산자 함수는 존재하는 덧셈 연산자 함수의 이점을 가져오고, 그것은 왼쪽값을 오른쪽값과 더하여 왼쪽값에 설정하기위해서 그것을 사용합니다.

1:var original = Vector2D(x: 1.0, y: 2.0)
2:let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
3:original += vectorToAdd
4:// original은 현재 (4.0, 6.0)의 값을 가집니다.

당신은 '@prefix'또는 '@postfix' 속성 둘중에 하나를 '@assignment'속성과 함께 결합할 수 있습니다. 이는 Vector2D 인스턴스에 대해서 전위 증가 연산자 (예로 ++a)의 구현에서 사용할 수 있습니다.

1:@prefix @assignment func ++ (inout vector: Vector2D) -> Vector2D {
2: vector += Vector2D(x: 1.0, y: 1.0)
3: return vector
4:}

위의 전위 증가 연산자 함수는 초기에 정의된 덧셈 할당 연산자의 이득을 취합니다. 그것은 그것이 불리워진 곳 상에서 x값과 y값으로 1.0을 가지는 Vector2D를 더합니다. 그리고 결과를 돌려줍니다.

1:var toIncrement = Vector2D(x: 3.0, y: 4.0)
2:let afterIncrement = ++toIncrement
3:// toIncrement는 지금 (4.0, 5.0)의 값을 가집니다.
4:// afterIncrement는 또한 (4.0, 5.0)의 값을 가집니다.

주목

기본 할당 연산자(=)를 오버로드하는 것은 불가능합니다. 단지 복합 할당 연산자들만이 오버로드됩니다. 비슷하게 3항 조건 연산자(a ? b : c)는 오버로드될 수 없습니다.

동등 연산자들

사용자 정의 클래스와 구조체들은 동등 연산자들, 즉 "같음(equal to)" 연산자 (==)와 "다름" 연산자(!=)로써 알려져 있는 연산자들의 기본 구현들을 받지 못 합니다. Swift에서는 당신 자신의 사용자 정의 타입에 대해서 "같음"으로 인정될 수 있는 것에 대한 추측하는 것이 불가능합니다. 이것은 "같음"의 정의가 당신의 코드에서 이들 타입들이 수행하는 역할에 의존하기 때문입니다.

사용자가 만든 타입의 동등성 검사를 위한 동등성 연산자를 사용하기 위해서는 다른 중위 연산자들에 대해서와 같이 연산자들의 구현을 제공해야 합니다.

1:@infix func == (left: Vector2D, right: Vector2D) -> Bool {
2: return (left.x == right.x) && (left.y == right.y)
3:}
4:@infix func != (left: Vector2D, right: Vector2D) -> Bool {
5: return !(left == right)
6:}

위의 예는 두개의 Vector2D 인스턴스가 동등함 값을 가지는지에 대해서 검사하기 위해서 "같음" 연산자(==)를 구현하는 것입니다. Vector2D의 컨텍스트에서 그것은 "같음"을 "양쪽 인스턴스가 같은 x값과 y값들을 가진다"는 의미로써 고려되는 것이 이치에 맞습니다. 그래서 이것은 연산자 구현에 의해서 사용된 논리입니다. 예는 또한 "같지 않음" 연산자(!=)를 구현합니다. 이것은 간단하게 "같음" 연산자의 결과에 역을 돌려줍니다.

당신은 지금 두개의 Vector2D 인스턴스들이 같은지 아닌지를 검사하는데 이들 연산자들을 사용할 수 있습니다.

1:let twoThree = Vector2D(x: 2.0, y: 3.0)
2:let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
3:if twoThree == anotherTwoThree {
4: println("These two vectors are equivalent.")
5:}
6:// prints "These two vectors are equivalent."

사용자 정의 연산자들

당신은 Swift에 의해서 제공되는 표준 연산자들 뿐만이 아니라 당신 소유의 사용자 정의 연산자들을 선언하고 구현할 수 있습니다. 사용자 정의 연산자들은 문자들 / = - + * % < > ! & | ^ . ~.를 가지고 단지 정의될 수 있습니다.

새로운 연산자들은 연산자 키워드를 사용하여 전역 수준에서 정의되어 지고, 전위, 중위 또는 후위로써 정의되어 질 수 있습니다.

operator prefix +++ {}

위의 예는 '+++'라고 불리우는 새로운 전위 연산자를 정의합니다. 이 연산자는 Swift에서 미리 정의된 의미를 가지고 있지 않습니다. 그래서 Vector2D 인스턴스들과 함께 동작하는 특정 컨텐스트 안에서 아래와 같이 의미를 부여는 자신 소유의 사용자 정의 연산자를 선언할 수 있습니다. 이 예제의 목적을 위해서, '+++'를 새로운 "전위 두배 증가" 연산자로써 다룹니다. 그것은 이전에 정의했던 덧셈 할당 연산자를 통해 그 자신을 그 벡터에 더하므로써, Vector2D 인스턴스의 x와 y값을 두배가 증가 시킵니다.

1:@prefix @assignment func +++ (inout vector: Vector2D) -> Vector2D {
2: vector += vector
3: return vector
4:}

'+++'의 이 구현은 Vector2D에 대해서 '++'의 구현과 매우 비슷합니다. 단지 이 연산자 함수가 Vector2D(1.0, 1.0)을 더하는 것 보다, 벡터를 그자신에 더한다는 것을 제외하고는 같습니다.

1:var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
2:let afterDoubling = +++toBeDoubled
3:// toBeDoubled는 지금 (2.0, 8.0)의 값들을 가집니다.
4:// afterDoubling은 또한 (2.0, 8.0)의 값들을 가집니다.

사용자 정의 중간 연산자들에 대한 우선순위와 결합순위

사용자 정의 중위 연산자들 또한 우선순위와 결합순위를 나열할 수 있습니다. 이들 두개의 문자를 가진 연산자들이 다른 중위 연산자들과 중위 연산자들의 상호작용에 어떻게 영향을 미치는지에 대한 설명을 위해서 'Precedence and Associativity'장을 보세요.

결합순위에 대해서 가능한 조건들은 왼쪽, 오른쪽, 그리고 아무것도 아닌쪽이 있습니다. 왼쪽 결합 연산자들은 만일 같은 우선순위를 가진 다른 왼쪽 결합 연산자들 옆에 쓰여져 있다면 왼쪽으로 결합합니다. 유사하게, 오른쪽 결합 연산자들은 같은 우선순위의 다른 오른쪽 결합 연산자들이 옆에 쓰여져 있을 경우 오른쪽으로 결합니다. 아무쪽도 아닌 결합 연산자들은 같은 우선 순위를 가진 다른 연산자들 옆에 쓰여질 수 없습니다.

결합 방법에 대한 조건은 특별히 이야기되지 않는다면 아무쪽도 아닌게 기본입니다. 우선순위의 경우 특별히 이야기되지 않는다면 100이 기본입니다.

다음의 예제는 '+-'라고 불리우는 새로운 사용자 정의 중위 연산자을 정의합니다. 이때 이 연산자는 왼쪽 결합이며 140의 우선순위를 가집니다.

1:operator infix +- { associativity left precedence 140 }
2:func +- (left: Vector2D, right: Vector2D) -> Vector2D {
3: return Vector2D(x: left.x + right.x, y: left.y - right.y)
4:}
5:let firstVector = Vector2D(x: 1.0, y: 2.0)
6:let secondVector = Vector2D(x: 3.0, y: 4.0)
7:let plusMinusVector = firstVector +- secondVector
8:// plusMinusVector는 (4.0, -2.0)의 값들을 가지는 Vector2D 인스턴스입니다.

이 연산자는 두개의 벡터의 x값들을 더하고 첫번째 것으로부터 두번째 벡터의 y값을 뺍니다. 그것은 본질적으로 덧셈 연산자이기 때문에, '+'나 '-'와 같은 기본 덧셈 중위 연산자들로써 같은 결합순위와 우선순위(왼쪽, 그리고 140)가 주어집니다. 기본적인 Swift 연산자 우선순위 및 결합순위 설정에 대한 완벽한 목록에 대해서는 "Expressions"장을 참조하세요.




















chapter29
Deleted file
chapter3
# 03 기초 다지기 (The Basics)
> Translator : 이름 (메일주소)

Write here...
FlashMaestro (masterofflash@nate.com)

Swift는 iOS와 OS X 앱을 개발하기 위한 새로운 프로그래밍 언어 입니다. 그러나 많은 부분이 C나 Objective-C로 개발하면서 얻었던 경험들과 유사할 것입니다.

Swift는 정수형을 위한 `Int`, 부동소숫점 값을 위한 `Double`과 `Float`, 불리언값을 위한 `Bool`, 문자열 데이터를 위한 `String`을 포함해 C와 Objective-C의 기본적인 데이터 타입에서 약간 변형된 형태로 제공합니다. 또한 `컬랙션 타입`으로 통칭되는 `Array`와 `Dictionary` 이 두가지 주요한 컬랙션 타입 또한 강력한 형태로 제공합니다.

Swift도 C처럼 식별 가능한 이름을 가지고 값을 참조하거나 저장하기 위한 변수를 사용합니다. 또한 변경 불가능한 값들 또한 폭넓게 사용되도록 했습니다. 보통 상수라고 알려져 있는데, 이것은 C에서의 상수보다 훨씬 강력합니다. 상수는 변경될 필요가 없는 값을 가지고 작업하려고 할 때 코드를 조금 더 안전하고 깔끔하게 만들 수 있도록 Swift 전반에 걸쳐 쓰이게 됩니다.

Swift는 잘 알려진 타입들 뿐 아니라 Objective-C에는 없었던 고급 타입들도 선보이고 있습니다. 값들의 묶음을 만들고 전달할 수 있도록 하는 튜플도 이 고급 타입들 중에 하나입니다. 튜플은 함수의 반환값으로 여러개의 값을 하나로 결합해 돌려줄 수 있도록 합니다.

Swift는 어떤 값의 부재를 다룰 수 있는 선택형 타입도 제공 합니다. 이 선택형은 "값이 존재하고, 그 값은 x입니다." 혹은 "값이 존재 하지 않습니다."라고 할 수 있습니다. 선택형은 Objective-C의 포인터에서 `nil`을 사용하는 것과 비슷합니다. 하지만 클래스 뿐만 아니라 어떤 타입에도 사용할 수 있습니다. 선택형은 Objective-C의 `nil` 포인터보다 훨씬 안전하고 쓰임새 있습니다. 또 Swift의 강력한 기능들중 핵심적인 기능입니다.

선택형은 Swift가 `type safe`하다는 예시 입니다. Swift는 당신이 코드를 통해 다루는 값들의 타입을 확실히 하는 것을 돕습니다. 당신이 만든 코드중에 일부가 `String` 타입을 사용해야 할 때 타입 세이프는 `Int`같은 값을 전달하는 실수를 막아줍니다. 이를 통해 개발하는 동안 가능한한 빨리 에러는 인지하고 고치는 것이 가능합니다.

##상수(Constants)와 변수(Variables)
상수와 변수는 어떤 이름(`maximumNumberOfLoginAttempts`나 `welcomeMessage`)과 특정한 형태의 값(숫자 `10`이나 문자열 `Hello`)의 결합으로 구성됩니다. 상수의 값은 한번 지정되고 난 후에는 변경될 수 없고 변수는 값이 지정되고 난 이후에도 변경될 수 있습니다.


###상수와 변수의 선언
상수와 변수는 사용되기 전에 선언되어야 합니다. 상수는 let키워드, 변수는 var 키워드를 가지고 정의할 수 있습니다. 여기 사용자가 로그인을 시도한 횟수를 추적하는데 사용되는 변수와 상수를 만드는 예제가 있습니다.

```c
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
```

이 코드는 다음과 같이 해석할 수 있습니다.

"maxiumNumberOfLoginAttempts라는 새로운 상수를 선언하고 값은 10으로 할당한다. 그리고 currentLoginAttempt라는 변수를 선언하고 0이라는 초기값을 할당한다."

예제에서 보면 최대값은 변하지 않기 때문에 로그인을 시도할 수 있는 최대 횟수가 상수에 정의되어 있습니다. 그리고 매번 로그인을 실패할 때마다 숫자가 증가해야 하기 때문에 현재 로그인 시도 횟수는 변수로 정의되어 있습니다.

콤마로 구분해서 한줄에 여러개의 상수나 변수를 선언하는 것도 가능합니다.

var x = 0.0, y = 0.0, z = 0.0

>노트
코드를 작성할 때 변경할 필요가 없는 값을 저장하는 경우 항상 `let` 키워드를 사용해 상수로 선언하라. 그리고 변경할 필요가 있을 경우에만 변수로 선언하라.

###타입 명시(Type Annotations)
상수나 변수를 만들 때 어떤 형태의 값이 저장될 지 명확하게 하기 위해 타입을 명시할 수 있습니다. 상수나 변수의 이름뒤에 콜론을 쓰고 한칸을 띄우고 사용하고 싶은 타입의 이름을 써서 타입을 명시할 수 있습니다.

다음 예시는 `welcomeMessage`라는 변수에 `String`값이 저장될 수 잇다는 것을 표시하기 위해 타입 명시를 하는 것입니다.

var welcomeMessage: String

콜론은 "~타입 의"라는 의미를 가집니다. 따라서 위의 코드는 다음과 같이 해석할 수 있습니다.

"`String`타입의 변수 welcomeMessage를 선언한다."

"`String`타입의" 라는 말은 "어떤 `String`값이든 저장할 수 있다."라는 의미 입니다. "어떤타입의"(혹은 "어떤 종류의") 라는 것은 그것이 저장될 수 있다 라는 의미로 생각하면 됩니다.

이제 `welcomeMessage`변수에는 오류없이 어떤 문자열 값이든 저장할 수 있습니다.

welcomeMessage = "Hello"

>노트
연습중에 타입 명시를 해야하는 경우는 드물다. 만약 상수나 변수를 정의하는 지점에 초기값을 지정한다면, Swift는 그 상수나 변수를 위해 사용할 타입을 추측한다. 이것이 바로 `타입 세이프`와 `타입 추정`이다. 위의 예제에서 `welcomeMessage`에 초기값을 지정하지 않았다. 그래서 초기값으로 부터 타입을 추정하기 힘들기 때문에 타입을 명시해준 것이다.

###상수와 변수 이름 짓기
상수와 변수의 이름을 지정하기 위해서 유니코드를 포함한 어떤 문자든지 사용할 수 있습니다.

```c
let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"
```

상수와 변수의 이름에는 수학기호, 화살표, 개인용(혹은 유효하지 않은) 유니코드, -선, 상자 그리기용 문자 등을 사용할 수 없다. 또 숫자로 시작해서도 안되고 이름 중간에 숫자가 들어가서도 안됩니다.

특정 타입의 상수나 변수를 한번 선언 했다면, 같은 이름으로 다시 선언하는 것이나 다른 형태의 값을을 저장하도록 하는 것은 불가능 합니다. 또 변수에 상수를 저장하거나 상수에 변수를 저장하는 것 또한 불가능 합니다.

>노트
만약 Swift 예약어로 상수나 변수명을 만들고 싶다면 변수명을 ```표시로 묶어서 쓸 수 있다. 그러나 정말 다른 대안이 없는 경우가 아니면 사용하지 않는 것이 좋다.

기존 변수의 값을 호환 가능한 다른 값으로 변경할 수 있습니다.. 예를 들면 `friendlyWelcome`의 값은 `"Hello!"`에서 `"Bonjour!"`로 변경됩니다.

```c
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome is now "Bonjour!
```

변수와는 다르게 상수는 한번 값이 정해지면 변경할 수 없습니다.. 컴파일할 때 에러가 발생하도록 시도해 봅시다.

```c
let languageName = "Swift"
languageName = "Swift++"
// this is a compile-time error - languageName cannot be changed
```


### 상수와 변수의 출력
`println` 함수를 사용하면 상수와 변수의 현재 값을 출력할 수 있습니다.

```c
println(friendlyWelcome)
// prints "Bonjour!
```

`println`은 출력하기 적절하게 줄단위로 끊어서 값을 출력해주는 전역 함수 입니다. Xcode에서 작업을 하고 있다면 `println`을 사용하면 Xcode의 "console"창에 결과가 나옵니다. (다음으로 `print` 함수는 `println`함수와 동일한 기능을 수행하지만 값을 출력하기 위해 한줄의 끝을 표시해줄 필요가 없습니다.)

`println`함수는 전달된 어떤 `String`값이든 출력해줍니다.

```c
println("This is a string")
// prints "This is a string
```

`println`함수는 코코아의 `NSLog`함수와 비슷한 방식으로 복잡한 로그 메시지를 출력하는 것도 가능합니다. 메시지에는 상수와 변수의 현재값을 포함할 수 있습니다.

Swift는 긴 문자열에서 상수나 변수명을 대체문자로 사용해 Swift가 상수나 변수의 현재 값으로 즉시 대체할 수 있도록 문자열 해석 방식을 사용합니다. 다음과 같이 이름을 괄호로 감싸고 이스케이프 시키기 위해 여는 괄호 앞에 백슬래시를 써주면 됩니다.

```c
println("The current value of friendlyWelcome is \(friendlyWelcome)")
// prints "The current value of friendlyWelcome is Bonjour!
```

>노트
문자열 해석에 관한 모든 옵션은 `문자열 해석` 부분에 설명되어 있습니다.

###주석(Comments)

스스로 상기하기 위해서 혹은 메모하기 위해 코드내에 실행되지 않는 글을 쓰려고 할 때 주석을 사용할 수 있습니다. 작성한 코드를 컴파일 할 때 Swift의 컴파일러는 주석을 무시합니다.

Swift의 주석은 C의 주석과 흡사합니다. 한줄 주석은 /(슬래시)를 두번 연속해서 쓰면 시작됩니다.

// this is a comment

또 여러줄 주석도 쓸 수 있습니다. 여러줄 주석은 슬래시와 별표를 쓰고(/*) 끝에는 별표와 슬래시(*/)를 순서대로 써주면 됩니다.

```c
/* this is also a comment,
but written over multiple lines */
```

C의 여러줄 주석과는 다르게 Swift에서는 여러줄 주석 안에 다른 여러줄 주석을 쓸 수 있습니다. 내부 여러줄 주석을 쓰려면 첫번째 여러줄 주석 부분을 시작하고 두번째 여러줄 주석을 첫번째 주석 안에서 시작합니다. 그리고 두번째 주석을 닫아준 후 첫번째 주석을 닫아주면 됩니다.

```c
/* this is the start of the first multiline comment
/* this is the second, nested multiline comment */
this is the end of the first multiline comment */
```

내부 여러줄 주석은 이미 코드에 여러줄 주석을 포함하고 있더라도 넓은 범위의 코드를 빠르고 쉽게 주석처리 할 수 있게해줍니다.

###세미콜론(Semicolons)
많은 다른 언어들과는 다르게 Swift는 코드의 각 문장 끝마다 세미콜론이 꼭 필요하지는 않습니다. 하지만 쓰고 싶다면 써도 됩니다. 하지만 한줄에 여러 문장을 처리하려고 한다면 세미콜론이 꼭 필요 합니다.

```c
let cat = "🐱"; println(cat)
// prints "🐱"
```

###정수(Integers)
정수는 `42`나 `-23`같이 소수점 단위가 없는 숫자들 전체 입니다. 정수는 부호가 있는 것(양수,0, 음수)와 부호가 없는 것(양수, 0) 모두를 포함합니다.

Swift는 8, 16, 32, 64 비트 형태로 부호있는 정수와 부호없는 정수를 지원합니다. 정수형은 부호 없는 8비트 정수형 `UInt8`, 부호있는 32비트 정수형 `Int32` 처럼 C와 비슷한 관습을 따른 이름을 갖고 있습니다. Swift의 다른 모든 타입과 마찬가지고 정수형 타입명 역시 대문자로 시작합니다.

####정수범위
각 정수형 타입에 최대값과 최소값은 `min`과 `max` 속성을 가지고 접근할 수 있습니다.

```c
let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
```

이런 속성값들은 예제에서 볼 수 있는 `Uint8`과 같은 타입들의 적정 범위를 나타내는 값이기 때문에 다른 타입들에도 동일 표현으로 사용할 수 있습니다.

####Int
대부분의 경우 코드 내에서 사용하기 위해 특정 크기를 지정할 필요가 없습니다. Swift가 현재의 플랫폼에 해당하는 워드(word) 크기를 갖는 `Int`라는 추가 타입을 지원하기 때문입니다.

- 32비트 플랫폼에서 `Int`는 `Int32`와 동일한 크기를 갖습니다.
- 64비트 플랫폼에서 `Int`는 `Int64`와 동일한 크기를 갖습니다.

정수형의 특정 크기가 필요한 것이 아니라면 코드 내에서 항상 `Int`를 사용하면 됩니다. 이것은 코드가 일관성을 갖고 상호처리가 가능하도록 합니다. 32비트 플랫폼에서 조차 `Int`는 넓은 범위의 정수를 포함하기에 충분할 만한 `-2,147,483,648` ~ `2,147,483,647`의 범위를 갖습니다.

####UInt
Swift는 `UInt`라는 부호없는 정수 타입도 지원합니다. 이것 또한 현재 플랫폼에 해당하는 워드 크기를 갖습니다.

- 32비트 플랫폼에서 `UInt`는 `UInt32`와 동일한 크기를 갖습니다.
- 64비트 플랫폼에서 `UInt`는 `UInt64`와 동일한 크기를 갖습니다.

>노트
특별히 현재 플랫폼 해당 워드 크기의 부호없는 정수형이 필요할 때만 `UInt`를 사용하라. 그런 경우가 아니라면 양수만 저장하는 경우일지라도 `Int`가 더 적절하다. 정수형을 위한 `Int`의 일관성이 코드가 `타입 세이프`와 `타입 추정`으로 묘사되는 다른 숫자 형태로의 변환또는 정수의 추정 타입일치가 필요한 경우를 피해 상호처리가 가능하도록 합니다.

###부동 소수점 수
부동 소수점 수란 `3.14159`, `0.1`, `-273.15` 처럼 소수 부분을 갖는 숫자를 말합니다.

부동 소수점 타입은 `Int` 타입에 저장될 수 있는 것보다 훨씬 크거나 작은 숫자를 저장하거나 더 넓은 범위의 숫자를 표현할 수 있습니다. Swift는 두가지의 부동 소수점 타입을 제공합니다.

- `Double`은 64비트 부동 소수점 수를 표현합니다. 매우 크거나 특별히 정밀한 부동 소수점 값을 원할 경우 사용합니다.
- `Float`은 32비트 부동 소수점 수를 표현합니다. 64비트의 정밀함이 필요하지 않은 경우 사용합시다.

>노트
`Float`이 6자리의 소수를 표현할 수 있는 것에 비해 `Double`은 최소 15자리의 소수를 표현할 수 있는 정도의 정밀도를 갖습니다. 코드에서 다루는데 필요한 속성이나 값의 범위에 따라 적절히 부동 소수점 타입을 골라서 사용합니다.

### 타입 세이프와 타입 추정(Type Safty and Type Inference)
Swift는 타입 세이프 언어입니다. 타입 세이프 언어들은 코드 내에서 다루는 값들의 타입이 명확하도록 만듭니다. 코드의 어떤 부분에서 `String`타입이 기대된다면 실수로 `Int`타입을 전달하는 것은 불가능합니다.

Swift가 타입 세이프이기 때문에 컴파일을 할 때 타입 검사를 수행하고 일치하지 않는 타입들에 대해서 에러로 표시합니다. 이를 통해 개발을 진행하면서 가능한 일찍 오류를 인지하고 고칠 수 있도록 합니다.

타입 검사는 다른 형태의 값들을 가지고 일을할 때 에러를 피할 수 있도록 해줍니다. 그러나 이것이 항상 상수나 변수를 선언할 때 타입을 명시해줘야 한다는 것을 의미하지는 않습니다. 필요로 하는 값의 타입을 명시해야 하지 않는 경우 Swift는 적절한 타입을 찾기 위해 타입 추정을 수행합니다. 타입 추정은 코드를 컴파일할 때 프로그래머가 공급한 값을 가지고 컴파일러가 자동적으로 특정 표현식의 타입을 알아내도록 합니다.

Swift는 타입 추정 때문에 C나 Objective-C에 비해 타입을 지정해줘야 하는 경우가 적습니다. 상수나 변수는 여전히 명시적으로 타입이 지정되지만 그 타입을 특정하는 많은 일들이 대신 수행됩니다.(*역자주: 상수나 변수는 타입 추정을 통해 타입을 확실하게 가지게 되기 때문에 타입을 지정해주기 위해 프로그래머가 해야할 일들이 줄었다는 것입니다.)

타입 추정은 상수나 변수를 초기값과 함께 선언할 때 특히 유용합니다. 종종 타입 추정은 상수나 변수가 선언되는 지점에서 문자 그대로의 값을 할당하는 것을 통해 이뤄집니다.(문자 그대로의 값이란 아래쪽 예시에서 볼 수 있는 `42`나 `3.14159`와 같은 소스코드에 직접적으로 쓰여져 있는 값을 말합니다.)

예를 들면, 타입을 명시하지 않고 새로운 상수를 선언할 때 `42`라는 문자그대로의 값을 할당하면 Swift는 정수형처럼 보이는 숫자를 가지고 초기화를 했기 때문에 상수가 `Int`값을 갖기를 원한다고 추정합니다.

```c
let meaningOfLife = 42
// meaningOfLife is inferred to be of type Int
```

이와 비슷하게 부동 소수점 수를 위한 타입을 특정하지 않으면 Swift는 `Double`형 타입을 생성하길 원하다고 추정합니다.

```c
let pi = 3.14159
// pi is inferred to be of type Double
```

Swift는 부동 소수점 수를 위한 타입을 추정할 때 `Float`보다는 항상 `Double`을 선택합니다.

만약 한 표현식 안에 정수와 부동 소수점 수를 결합해서 사용하면 문맥으로부터 `Double` 타입이라고 추정될 것입니다.

```c
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double
```

문자 그대로의 `3`은 스스로 어떤 타입인지 명시되어 있지 않습니다. 또 덧셈 부분에 부동 소수점 수가 존재하기 때문에 `Double`이 출력 지정 타입으로 추정됩니다.



chapter4
# 04 기본 연산자 (Basic Operators)
> Translator : 해탈 (kimqqyun@gmail.com)

연산자는 값을 확인 변경 합치기 위해 사용하는 특수 기호나 문구입니다. 예를 들어 더하기 연산자(`+`)는 두 숫자를 더합니다. (`let i = 1 + 2` 과 같이)
더 복잡한 예는 논리 AND 연산자 (`&&`) 포함입니다. (`enteredDoorCode && passedRetinaScan`)그리고 증가 연산자인 `++i`는 `i`의 값 `1`을 증가시키는 축약 연산자입니다.

Swift 는 대부분의 표준 C 연산자를 지원하며 일반적인 코딩 오류를 제거하는 몇가지 기능을 항샹향상 시켰습니다. 할당연산자 (`=`)나 항등 연산자(`==`)를 사용할때 실수를 방지하기 위해 값을 반환하지 않습니다.
산술연산자(`+` ,` -` ,`*`,`/` ,`%` 등)가 오버플로우를 감지하고 그들을 저장하는 유형의 허용된 값의 범위보다 크거나 작아 숫자로 작업할때 예기치 않은 결과를 방지 할 수 있습니다.
당신은 오버 플로우 연산자에 설명된대로 Swift의 오버플로우 연산자를 사용하여 오버플로 값을 선택할수 있습니다. 이것은 Overflow Operaters 에 설명되어 있습니다. // 링크

C 와 달리, Swift는 부동 소수점 숫자에 나머지 (`%`) 계산을 수행 할 수 있습니다. Swift는 또한 2개의 범위 연산자를 제공합니다. (`A..B`) 그리고 (`A...B`) 이며 값의 범위를 표현하기 위한 연산자이고 이것은 C 에서 찾을 수 없습니다.

이 장에서는 Swift의 일반적인 연산자를 설명합니다. 고급 연산자는 고급 연산자(Advanced Operator) 장에 있습니다, 그리고 사용자 정의 연산자를 정의하고 사용자 정의 형식에 대한 표준 연산자를 구현하는 방법에 대해 설명합니다.

## 용어 (Teminology)
연산자는 단항, 이진, 그리고 삼항이 있습니다.

- 단항 연산자는 단일 대상에서 작동합니다. (예 `-a`) 단항 전위 연산자를 바로 앞에 나타내고, (예 `!b`) 단항 후위 연산자는 타겟이후에 즉시 나타납니다. (예 `i++`)
- 이항 연산자는 두개의 대상에 작동하며 그들의 두 대상 사이에 나타납니다. 왜냐하면 중위연산자입니다. (예 `2 + 3`)
- 삼항 연산자는 세 가지 대상에 작동합니다. C 처럼 , Swift는 하나의 삼항연산자, 삼항 조건 연산자가 (`a ? b : c`)

연산자에 영향을 주는 값은 피연산자 입니다. 식 `1 + 2` 는 이항 연산자와 두 피연산자의 값은 `1`과 `2`입니다.

## 할당 연산자
할당 연산자는 `(a = b)` 초기화 하거나 `b` 의 값을 `a` 에 할당하는것이다.
```
let b = 100
var a = 5
a = b
// a 는 이제 10 과 같다.
```

만약 오른쪽이 같은 여러 값을 가진 튜플의 경우, 그 요소는 한번에 여러개의 상수 또는 변수로 분해 될수 있다.
```
let (x, y) = (1, 2)
// x 는 1 과 같다 그리고 y 는 2 와 같다.
```

C 와 Objective-C의 대입 연산자와는 달리, Swift의 대입 연산자 자체가 값을 반환하지 않습니다. 다음 구문은 유효하지 않습니다.
```
if x = y {
// x = y가 값을 반환하지 않기 때문에 이것은 유효하지 않다,
}
```

이 기능은 실수로 (`==`) 연산자를 사용하여 막는것은 (`=`)를 대신 사용하는것을 방지하기 떄문입니다. `if x = y` 가 유효하지 않게 함으로써 Swift 코드에서 이러한 종류의 오류를 방지하는데 도움이 됩니다.

## 산술 연산자
Swift 는 4가지의 산술연산자가 모든 숫자 타입을 지원합니다.

- 덧셈 (`+`)
- 뺼셈 (`-`)
- 곱셈 (`*`)
- 나눗셈 (`/`)

```
1 + 2 // 3 과 같다
5 - 3 // 2 와 같다
2 * 3 // 6 과 같다
10.0 / 2.5 // 4.0 과 같다
```
C 및 Objective-C의 산술 연산자와는 달리 Swift 산술 연산자는 값이 기본적으로 오버플로우하는것을 허용하지 않는다. Swift 오버플로우 연산자를 사용하여 값 오버플로 동작을 선택할 수있습니다. Overflow Operators를 참조하십시오. // 링크

또한 덧셈 연산자는 String 문자열을 지원한다.
```
"hello, " + "world" // "hello, world" 와 같다
```

두 개의 `Character` 값이거나 하나는 `Character` 값 그리고 하나는 `String` 값일때 두 개를 함께 더해서 새로운 `String` 값을 만들 수 있습니다.

```
‘let dog: Character = "🐶🐶
let cow: Character = "🐮"
let dogCow = dog + cow
// dogCow is equal to "🐶🐮"
```
이것에 대해선 Strings and Characters 또한 참조 바란다. // 링크

## 나머지 연산자
나머지 연산자는 (`a % b`) `b` 의 많은 배수가 `a`에 맞게 곱해지며 그리고 남아 있는 값을 반환합니다. (이는 나머지 라고 불립니다.)

> NOTE

> 나머지 연산자는 (%) 또한 모듈로 연산으로 다른 언어에 알려져있다. 그러나 Swift에서의 동작은 음수를 의미한다. 엄격히 말하면, 모듈로 연산보다는 나머지 연산이다.

여기에 나머지 연산의 동작이 어떻게 되는지 있다. ` 9 % 4 ` 을 계산해보면, 당신은 첫번째로 `4`들을 `9`에 맞게 맞출것이다.
![remainderinteger_2x.png](images/remainderinteger_2x.png)


당신은 `4`들을 9에 맞추었고 그리고 나머지는 `1`이다. (오렌지 색깔을 보라)

Swift에서는 이렇게 쓰여진다

9 % 4 // 1과 같다

a % b 의 답을 측정해보면, % 계산 연산자는 나머지 출력과 = 연산자를 반한단다.

`a = (b x 배수) + 나머지`

`배수`가 `a` 내부의 맞는 가장 큰 수일 경우다.

9 와 4를 대입 할경우

` 9 = (4 × 2) + 1 `

a 의 값이 음수 일때도 같은 메소드가 지원되며 나머지 값이 음수가 나온다.

`-9 % 4 // -1과 같다`

-9 와 4 를 넣으면 다음 과 같은 식이 나온다.

`-9 = (4 × -2) + -1`

나머지 값이 `-1`이 주어진다.

`b`의 부호는 `b`의 음의 값이 무시됩니다. 이것은 `a % b` 와 `a % -b`는 항상 같은 대답을 주고 있다는 것을 의미한다.

## 부동 소수점 나머지 연산
C 와 Objective-C의 나머지 연산과는 달리, Swift의 나머지 연산은 부동 소수점 연산 또한 지원합니다.

`8 % 2.5 // 2.5와 같음`
예를 들어 8을 2.5로 나누었을때 3과 같다 나머지는 0.5와 같다. 그리고 나머지 연산이 반환하는 값은 Double 타입의 0.5이다.
![remainderfloat_2x.png](images/remainderfloat_2x.png)


## 증가연산자와 감소 연산자
C와 같이, Swift는 증가 연산자(`++`)와 감소 연산자(`--`)를 제공한다. 이것은 숫자 변수 `1`를 증가시키거나 감소시키는 축약형이다. 정수형과 부동소수점형을 연산자와 같이 사용 가능하다.
```
var i = 0
++i // i 는 이제 1과 같다
```

만약 `++i` 호출마다 `i`의 값은 `1` 씩 증가된다. 기본적으로 `++i` 는 `i = i + 1` 의 약어이다. 마찬가지로 `--i`를 `i = i - 1` 의 약어로 사용할 수 있습니다.

`++` 와 `--` 기호는 전위연산자 또는 후위연산자로 사용이 가능합니다. `++i` 와 `++i`는 둘다` i`의 값을` 1` 증가시키는 방법입니다. 비슷하게, `--i` 와 `i--`는 `i`의 값을 `1` 감소시키는 방법입니다.

이러한 수정연산자는 i 와 그리고 반환값 까지 변화시킵니다. 만약 i 에 저장된 값을 증가 또는 감소 할 경우, 반환값을 무시 할 수있습니다. 그러나 반환된 값을 사용할 경우, 당신은 다음과 같은 규칙에 따라 접두사 또는 연산자의 후위버전을 사용하는지 여부에 따라 달라집니다.

- 만약 변수 앞에 쓰여질 경우, 값이 증가한 후에 반환된다.
- 반약 변수 뒤에 쓰여질 경우, 값이 반환된 뒤에 증가된다.

예제 코드 (For example:)
```
var a = 0
let b = ++a
// a 그리고 b는 지금 a 둘다 1과 같다.
let c = a++
// a 는 지금 2, 그러나 c는 이전의 값인 1이 이미 설정되어있다.
```

위의 예제코드에서 `let b = ++a` 는 `a`를 반환하기 전에 `a`를 증가시킨다. 이 방법은 a 와 b 하나의 새로운 값이 동등한 이유이다.

그러나, `let c = a++` 는 `a`를 반환한 후에 `a`를 증가시킨다. 이 뜻은 `c`가 없은 값은 예전의 값인 `1`이며 `a`에게는 업데이트 된 `2`와 같다.

당신은 i++의 특정동작을 필요로 하지 않는한, 이것은 당신이 ++i 나 --i를 사용하는것이 좋습니다. 왜냐하면 그것은 모든 경우에 `i`를 수정하고 결과를 반환하는 예상된 동작을 가지기 때문입니다.

##단항 마이너스 연산자
숫자 값의 부호는 접두어 -를 사용하여 전환할수 있다. 이것은 단항 마이너스 연산자로 알려진것이다.

```
let three = 3
let minusThree = -three // minusThree equal -3
let plusThree = -minusThree // plus equal 3, or "minus minus three"
```
단항 마이너스 연산자는 공백없이 작동하는 값 바로 앞에 추가 됩니다.

##단항 플러스 연산자
단항 플러스 연산자(+)는 간단하게 변경하지 않고, 값을 반환합니다.

```
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix equals -6
```

플러스 연산자가 있음에도 불구하고 실제로 아무것도 하지 않지만, 당신은 또한 단항 마이너스 연산자를 사용하는 경우 양수에 대한 코드대칭에 사용할 수 있습니다.

## 복합 할당 연산자
C와 같이 Swift는 다른 작업에 할당(=)을 결합하는 복합 할당 연산자를 제공합니다. 한 예를 들어 덧셈 할당 연산자입니다 (+=):
```
var a = 1
a += 2
// a 는 3과 같다
```

표현식 `a += 2` 는 `a = a + 2` 의 축약형이다. 효과적으로 한 연산자가 가산 및 할당이 동시에 작업과 결합이 된다.

>NOTE
>
> 복합 할당 연산자는 값을 반환하지 않는다. 당신은 `let b = a += 2` 이러한 코드를 작성할수 없다. 예를 들어 이러한 코드는 위의 증가 및 감소 연산자와는 다릅니다.

복합 할당 연산자의 전체 목록은 Expressions 에서 찾을 수 있습니다. // 링크

## 비교 연산자
Swift는 C의 정식 비교연산자를 지원합니다.

- 같음 연산자 (`a == b`)
- 같지 않음 연산자 (`a != b`)
- 보다 큰 (`a > b`)
- 보다 작은(`a < b`)
- 보다 크거나 같은 (`a >= b`)
- 보다 작거나 같은 (`a <= b`)

>NOTE
>
>Swift는 또한 두 개체 참조가 동일한 인스턴스 객체를 참조하고 있는지 여부를 테스트 하는 연산자를 지원합니다. (`===` 와 `!==`) 자세한 내용은 Classes and Structures를 참조하십시오 // 링크

비교 연산자의 각 문장이 참인지 여부를 나타내는 `Bool` 값을 반환합니다 :

```
1 == 1 // 참
2 != 1 // 참
2 > 1 // 참
1 < 2 // 참
1 >= 1 // 참
2 <= 1 // 거짓

```

비교 연산자는 종종 if문 같은 조건문에 사용된다 :

```
let name == "world"
if name == "world" {
println("hello, world")
} else {
println("I'm sorry \(name), but I don't recognize you")
}
```
`if`에 대한 더 많은 정보는 Control Flow를 참조하기 바란다. // 링크

## 삼항 조건 연산자
삼항 조건 연산자는 특별한 연산자와 세개의 파트로 이루어져있습니다.
양식은 이러합니다. (`question ? answer1 : answer2`)
이 `question`이 참인지 거짓인지에 따라 두 식중 하나를 평가하기 위한 축약어입니다. 만약 `question` 이 참이면 `answer1`을 계산하고 값을 반환합니다; 그렇지 않으면 `answer2`를 계산하고 값을 반환합니다.

삼항 조건 연산자는 아래의 코드에 대한 속기입니다.

```
if question {
answer1
} else {
answer2
}
```
이것은 테이블 행의 픽셀 높이를 계산하는 예제입니다. 행의 헤더가 있다면 컨텐츠의 높이가 50 픽셀이상이고 행의 헤더가 없다면 20픽셀 보다 큰것입니다.:

```
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 는 90과 같다
```

위의 예제코드는 아래 코드의 속기입니다.
```
let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
rowHeight = rowHeight + 50
} else {
rowHeight = rowHeight + 20
}

```

첫번째 예제의 삼항 조건 연산자의 사용은 `rowheight`에 단 한줄의 코드에 올바른 값으로 설정될 수 있음을 의미합니다. 이것은 두 번째 예제코드보다 간결하고 그 값이 `if` 문 내에서 수정될 필요가 없기 떄문에 이것은 `rowheight`가 변수가 될 필요성이 없어집니다.

삼항 조건 연산자는 두 식의 어떤 결정을 고려하는것을 위해 효율적인 속기를 제공합니다. 그러나 삼항 조건 연산자는 주의해서 다뤄야 합니다. 남용하면 그 간결함은 읽기 어려운 코드로 이어질 수 있습니다. 하나의 복합 문에 삼항 조건 연산자와 다중 인스턴스를 결합하는것을 피하세요.

## 범위 연산자
Swift는 두 개의 범위연산자를 지원하며 이 축약어는 값의 범위를 표현합니다.

### 폐쇄 범위 연산자
폐쇄 범위 연산자(`a...b`)는 `a`에서 `b` 까지의 범위를 정의합니다. 그리고 `a`와 `b`의 값을 포함합니다.

폐쇄 범위 연산자는 `for-in` 루프와 같이 사용하고자 하는 값 범위에서 반복할때 폐쇄 범위 연산자는 유용합니다.

```
for index in 1...5 {
println("\(index) time 5 is \(index * 5)")
}
// 1번쨰 반복 5 is 5
// 2번쨰 반복 5 is 10
// 3번쨰 반복 5 is 15
// 4번쨰 반복 5 is 20
// 5번쨰 반복 5 is 25
```
`for-in` 루프에 대해서는 Control Flow 항목을 참조하시오 // 링크

### 반 폐쇄 범위 연산자
반 폐쇄 범위 연산자 (`a..b`)는 a 에서 b 로 실행되는 범위를 정의하지만 b가 포함되어 있지 않습니다. 그것은 최종값이 아니며 처음 값을 포함하고 있기 때문에 반폐쇄라고 합니다.

반 폐쇄 범위는 특히 0을 기반으로한 목록 또는 배열로 작업할때 유용합니다. 그것은 리스트의 길이(포함안되는)까지 계산하는데 유용합니다.
```
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = name.count
for i in 0.count {
println("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
```
배열에는 4개의 항목이 포함되어있습니다. 하지만 반 폐쇄 범위기 때문에 `0..count` 는 단지 3까지만 카운트 합니다. (배열의 마지막 항목의 인덱스)
arrays에 대해 더 참조하고 싶다면 Arrays 항목 를 참조하시오 // 링크

## 논리 연산자
논리 연산자는 `true`와 `false` 불리언 논리 값을 수정하거나 결합합니다. Swift는 C 기반 언어의 세 가지 표준 논리 연산자를 지원합니다.

- NOT (!a)
- AND (a && b)
- OR (a || b)

##논리 NOT 연산자
논리 NOT 연산자(`!a`)는 불리언 값인 `true` 값을 반전시키고 `false` 값은 `true` 가 된다.

논리 NOT 연산자는 전위 연산자입니다. 값 앞에 연산을 공백없이 즉시 표현 할 수 있습니다. 이것은 "`not` a"로 바로 읽을 수 있으며 다음의 예제에서 볼 수 있습니다.

```
let allowedEntry = false
if !allowedEnrty {
println("ACCESS DENIED")
}
// prints "ACCESS DENIED"
```
`if !allowedEntry` 는 "if not allowed entry" 로 읽을 수 있습니다.
즉 `allowedEntry`이 false인 경우 라인 이후의 `not allowed entry` 가 `true`인 경우에 해당할 경우로 실행됩니다.
이 예제에서와 같이 불리언 상수와 변수 이름의 주의 깊은 선택은 이중 부정 또는 혼란한 논리구문을 피하면서 읽기 쉽고 간결한 코드를 유지하는데 도움이 될 수 있습니다.

## 논리 AND 연산자

논리 AND 연산자(`a && b`)의 overall expression은 두 값이 모두 `true`이어야 `true`가 됩니다.

반대로 두 값이 `false` 이면 overall expression 또한 `false` 입니다. 사실 첫번째 값이 `false` 인 경우 두번째 값이 evaluated 되지 않습니다. 그것을 가능할수 없기 떄문에 overall expression이 `true`와 같게 됩니다. 이는 short-circuit evaluation 로 불린다.

이 예제에서는 두 개의 `Bool`값을 고려하여 만약 두 값이 `true` 에만 액세스 할 수 있습니다.

```
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
println("Welcome!")
} else {
println("ACCEss DENIED")
}
// prints "ACCESS DENIED"
```
## 논리 OR 연산자
논리 OR 연산자(`a || b`)는 인접한 파이프 문자로 만든 중위연산자 입니다. overall expression 이 `true`가 될 때 까지 두 개의 값 중 하나만이 참이어야 하는 논리식을 만드는데 사용합니다.

위의 논리 AND 연산자처럼 논리 OR 연산자는 식을 고려할떄 short-circuit evaluation을 사용합니다. 논리 OR식의 좌측에 `true`가 해당하는 경우는 overall expression 식의 결과를 변경 할수 있기 때문에 우측은 계산되지 않는다.

아래의 예제에서 첫 번째 `Bool` 값(`hasDoorKey`)은 `false`이지만 두 번째 값(`knowsOverridePassword`)는 `true`이다. 하나의 값 이`true`이기 떄문에 overall expression은 `true`로 평가하고 액세스가 허용됩니다.

```
let hasDoorKey = false
let knowOverridePassword = true
if hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
## 복합 논리 연산자

당신은 여러 논리 연산자를 결합하여 복합 논리 연산자를 만들 수 있습니다.
```
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
이 예제는 && 및 || 연산자를 여러개 사용하려 긴 복합 표현식을 만들었습니다. 그러나 && 와 || 연산자는 여전히 두 개의 값에 대해 작동하므로 이는 실제로 서로 세개가 연결된 작은 표현입니다.
이것은 이렇게 읽을 수 있습니다:

만약 우리가 문의 코드를 입력하고 망막 검사를 통과한경우; 우리가 유효한 도어 키가 있는 경우이거나 긴급 재정의 암호를 알고있는 경우 다음 액세스 할 수 있습니다.

`enteredDoorCode` 와 `passedRetinaScan` 그리고 `hasDoorKey` 의 값에 기초하여 처음 작은 표현식은 `false`이다. 그러나 긴급 재정의 암호가 `true`로 알려져있다 ,그래서 전체 복합 표현식은 여전히 `true`로 평가됩니다.

## 괄호 명시
괄호가 엄격히 필요하지 않은경우, 읽기 복잡한 표현의 의도록 쉽게 만들수 있는 경우에 괄호가 포함되는것이 유용한 경우가 종종 있다.

위의 door access 예제 코드에서 그것의 의도를 명시적으로 확인하기 위해 복합 표현식의 첫번째 부분을 괄호를 추가하는데에 유용합니다.

```
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```
괄호는 처음 두 값을 전체 논리에서 별도의 가능한 상태의 일부로 분명히 간주되게 만듭니다. 복합식의 출력이 변하지는 않지만 전체적인 목적이 독자에게 명확해집니다. 가독성은 항상 간결함을 선호합니다; 괄호의 사용은 당신의 의도를 확실히 파악하는데 도움이 됩니다.

chapter6
# 06 컬렉션 타입 (Collection Types)
> Translator : 이름 (메일주소)

Write here...

> Translator : 유정협 (justin.yoo@aliencube.com)

스위프트는 여러 값들을 한꺼번에 저장하기 위해 배열과 딕셔너리로 알려진 두가지 *컬렉션 타입*을 제공한다. 배열은 동일한 타입을 가진 값을 순서대로 저장한다. 딕셔너리는 동일한 타입을 가진 값을 순서와 상관 없이 저장한다. 따라서, 딕셔너리는 유일한 식별자인 키를 통해 값을 찾고 참조하게 된다.

스위프트에서 배열과 딕셔너리는 항상 자신이 저장하고자 하는 키와 값의 타입을 확인한다. 이것은 다른 타입을 가진 값을 배열이나 딕셔너리에 실수로라도 저장하지 못한다는 것을 의미한다. 이는 또한 배열과 딕셔너리에서 값을 가져올 때 어떤 타입의 값을 가져올 수 있는지 확신할 수 있다는 의미이기도 하다. 스위프트에서 이렇게 명시적인 타입 컬렉션을 사용하는 것은 당신의 코드가 명확한 밸류 타입을 가져야 하게끔 하는 것이며 개발시 타입이 맞는지 아닌지를 바로바로 잡아낼 수 있게끔 해준다는 것이다.

> **참고:**
> 스위프트의 `Array` 타입은 상수나 변수에 지정될 때, 혹은 함수나 메소드에서 사용될 때 다른 타입들과 다른 행동을 보여준다. 더 자세한 내용은 "컬렉션의 변경 가능성"\*링크필요\* 섹션과 "컬렉션 타입에서 할당과 복사 형태"\*링크필요\* 섹션을 참고하도록 하자.


## 배열 Arrays ##

배열은 같은 타입을 가진 여러개의 값을 순서대로 저장한다. 한 배열 안에서는 같은 값이 여러 다른 위치에서 나타날 수 있다.

스위프트에서 배열은 특정한 종류들의 값들을 저장할 수 있다. 이것은 Objective-C의 `NSArray`와 `NSMutableArray` 클라스와는 다르다. `NSArray`와 `NSMutableArray` 클라스는 어느 종류의 객체든 저장할 수 있고, 반환하는 객체의 속성에 대한 어떠한 정보도 제공하지 않는다. 반면에 스위프트에서는 특정 배열에 저장할 수 있는 밸류 타입은 항상 명시적인 타입 선언을 통하거나 타입 추정을 통해 확인한다. 굳이 클라스 타입이 될 필요는 없다. 예를 들어 만약 당신이 `Int` 타입 배열을 하나 생성한다고 하면, `Int` 값이 아닌 어떤 값도 이 배열에 대입할 수 없다. 스위프트는 타입 지정에 대해 안전하고, 배열 안에 무슨 타입이 들어있는지를 혹은 들어갈지를 항상 확인한다.


### 배열 타입 축약 문법 Array Type Shorthand Syntax ###

스위프트 배열 타입을 정확하게 쓰려면 `Array` 형태로 해야 한다. 여기서 `SomeType`은 배열에 저장할 타입을 의미한다. 또한 축약 형태인 `SomeType[]`으로도 배열을 사용할 수 있다. 이 두 가지 형태가 기능적으로는 동일할지라도, 축약 형태를 사용하는 것을 권장한다. 이 축약 형태의 배열이 이 가이드 문서에서도 계속 쓰일 것이다.


### 배열 표현식 Array Literals ###

배열은 배열 표현식을 통해서 초기화를 시킬 수 있다. 배열 표현식은 하나 또는 그 이상의 값들을 배열 컬렉션에 담는 축약 형태를 가리킨다. 배열 표현식은 대괄호로 둘러싸고, 콤마로 값들을 구분하는 형태로 하여 여러개의 값들을 표현한다.

```
[value1, value2, value3]
```

아래는 `String` 타입의 값들을 저장하는 `shoppingList`라는 배열을 생성하는 예제이다.

```
var shoppingList: String[] = ["Eggs", "Mink"]

// shoppingList has been initialized with two initial items
```

`shoppingList` 변수는 "`String` 타입의 값들을 갖는 배열"로 정의했기 때문에 `String[]` 타입으로 배열 타입을 지정했다. 이렇게 `Strign` 타입을 갖는 것으로 배열 타입을 지정했기 때문에 이 배열은 오직 `String` 값들만을 저장할 수 있다. 여기서 `shoppingList` 배열은 두 "`Eggs`", "`Mink`" `String` 값을 배열 표현식으로 지정하여 초기화를 시켰다.

> **참고:**
> 이 `shoppingList` 배열은 다음에 나올 예제에서 더 많은 쇼핑 목록을 추가하기 때문에 상수를 위한 `let` introducer가 아닌 `var` introducer를 통해 변수로 지정했다.

이 경우에 배열 표현식은 두 `String` 값 이외에는 다른 것을 포함하지 않는다. 이것은 `shoppingList` 변수의 타입 정의 – 오직 `String` 타입의 값들만 저장할 수 있는 배열 – 와 일치한다. 따라서, 배열 표현식을 이용하여 `shoppingList` 변수를 초기화 하는 것이 허용된다.

스위프트의 타입 추정 덕분에 당신은 배열 표현식을 이용하여 같은 타입을 갖는 변수를 초기화 시킨다면 배열 타입을 쓸 필요가 없다. 따라서, `shoppingList` 변수의 초기화는 아래와 같이 좀 더 간결한 형태로도 가능하다.

```
var shoppingList = ["Eggs", "Mink"]
```

배열 표현식의 모든 값들이 모두 같은 타입이기 때문에 스위프트는 `String[]`이 `shoppingList` 변수의 사용에 맞는 타입이라고 추정할 수 있다.


### 배열의 접근 및 수정 Accessing and Modifying an Array ###

배열은 메소드와 프로퍼티를 통해 접근과 수정이 가능하다. 혹은 subscript 문법을 사용할 수도 있다.

배열 안에 값이 몇 개나 있는지를 확인하기 위해 읽기 전용 속성인 `count` 프로퍼티를 사용한다:

```
println("The shopping list contains \(shoppingList.count) items.")

// prints "The shopping list contains 2 items."
```

불리언 값을 반환하는 `isEmpty` 프로퍼티를 이용하면 `count` 프로퍼티 값이 `0`인지 아닌지 곧바로 확인할 수 있다:

```
if shoppingList.isEmpty {
println("The shopping list is empty.")
} else {
println("The shopping list is not empty.")
}

// prints "The shopping list is not empty."
```

새로운 값을 배열의 마지막에 추가하는 것은 `append` 메소드를 이용하면 된다:

```
shoppingList.append("Flour")

// shoppingList now contains 3 items, and someone is making pancakes
```

추가 할당 연산자인 `+=`를 이용하여 배열의 마지막에 새로운 값을 추가할 수도 있다.

```
shoppingList += "Baking Powder"

// shoppingList now contains 4 items
```

같은 타입을 갖는 배열 표현식을 이용하여 한꺼번에 추가시킬 수도 있다:

```
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]

// shoppingList now contains 7 items
```

배열로부터 값을 찾는 것은 배열 변수 바로 뒤에 대괄호를 사용해서 찾고자 하는 값의 인덱스값을 이용하면 된다:

```
var firstItem = shoppingList[0]

// firstItem is equal to "Eggs"
```

배열의 첫번째 값이 갖는 인덱스는 `0`이다. `1`이 아님을 명심하자. 스위프트에서 배열의 인덱스는 항상 0부터 시작한다.

Subscript 문법을 사용하면 지정한 인덱스에 이미 존재하는 값을 바꿀 수도 있다:

```
shoppingList[0] = "Six eggs"

// the first item in the list is now equal to "Six eggs" rather than "Eggs"
```

Subscript 문법을 이용하면 범위를 줘서 한꺼번에 값을 바꿀 수도 있다. 심지어는 바꾸려고 하는 범위가 실제 값의 크기와 달라도 그게 가능하다. 아래 예제는 `shoppingList` 배열에 있는 "`Chocolate Spread`", "`Cheese`", "`Butter`" 값을 "`Bananas`", "`Apples`"으로 바꾸어 버린다:

```
shoppingList[4...6] = ["Bananas", "Apples"]

// shoppingList now contains 6 items
```

> **참고:**
> Subscript 문법을 사용해서 새 값을 배열의 마지막에 추가하는 것은 안된다. 만약에 배열의 크기보다 큰 인덱스 값을 사용해서 배열에 접근하려 한다면 런타임 에러를 확인할 수 있을 것이다. 하지만 유효한 인덱스 값은 사용 전에 배열의 `count` 프로퍼티를 이용하여 확인이 가능하다. `count` 프로퍼티 값이 `0`인 경우 – 빈 배열인 경우 – 를 제외하면 배열에서 가장 큰 인덱스 값은 항상 `count - 1`이 될 것이다. 인덱스는 항상 `0`에서 시작하기 때문이다.

특정한 인덱스에 배열 값을 넣고 싶다면 배열의 `insert(atIndex:)` 메소드를 이용한다:

```
shoppingList.insert("Maple Syrup", atIndex: 0)

// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list
```

이것은 `insert` 메소드를 이용하여 "`Mayple Syrup`"이란 새로운 값을 `shoppingList` 배열의 가장 앞 – `0` 인덱스 값을 가진 곳 – 에 넣는 것이다.

비슷한 방식으로 배열에서 값을 지울 수도 있다. `removeAtIndex` 메소드를 이용하면 되는데, 이 메소드는 배열내 주어진 인덱스에서 특정 값을 지우고 난 후 그 지워진 값을 반환한다. 이 지워진 값은 필요하지 않다면 무시해도 좋다.

```
let mapleSyrup = shoppingList.removeAtIndex(0)

// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string
```

배열에서 값을 지우고난 다음에 생기는 공백은 자동으로 지워진다. 따라서, `0` 인덱스에 해당하는 값은 이제 "`Six eggs`"이다:

```
firstItem = shoppingList[0]

// firstItem is now equal to "Six eggs"
```

만약 배열의 마지막 값을 지우고 싶다면 `removeLast` 메소드를 이용한다. 이 메소드를 이용하면 `removeAtIndex` 메소드를 `count` 프로퍼티와 함께 사용하는 불필요한 수고를 피할 수 있다. `removeAtIndex` 메소드와 마찬가지로 `removeLast` 메소드 역시 지워진 값을 반환한다:

```
let apples = shoppingList.removeLast()

// the last item in the array has just been removed
// shoppingList now contains 5 items, and no cheese
// the apples constant is now equal to the removed "Apples" string
```

### 배열에서 반복문 사용하기 Iterating Over an Array ###

`for-in` 반복문을 사용하면 배열 안의 모든 값들에 접근할 수 있다:

```
for item in shoppingList {
println(item)
}

// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
```

만약 배열 안의 개별적인 값들과 그에 해당하는 인덱스가 함께 필요하다면 전역 함수인 `enumerate`를 사용해서 배열을 돌릴 수 있다. `enumerate` 함수는 배열내 각각의 값에 대해 인덱스와 결합한 튜플 값을 반환한다. 반복문을 돌리는 도중 이 튜플을 변수나 상수로 분리하여 사용할 수 있다:

```
for (index, value) in enumerate(shoppingList) {
println("Item \(index + 1): \(value)")
}

// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
```

`for-in` 반복문에 대해서는 "For 반복문"\*링크필요\* 항목을 참고하도록 하자.


### 배열의 생성과 초기화 Creating and Initializing an Array ###

배열의 초기화 문법을 이용하면 초기값 할당 없이 특정 타입을 가진 빈 배열을 만들 수 있다:

```
var someInts = Int[]()
println("someInts is of type Int[] with \(someInts.count) items.")

// prints "someInts is of type Int[] with 0 items."
```

`someInts` 변수의 타입은 `Int[]`로 추정 가능한데, 이것은 `Int[]`로 초기화를 했기 때문이다.

또한 만약 컨텍스트 상에서 함수의 인자라든가 이미 타입 선언이 된 변수 혹은 상수라든가 하는 식으로 해서 이미 타입 정보를 갖고 있다면, 빈 배열을 곧바로 빈 배열 표현식을 이용하여 만들 수 있다. 빈 배열 표현식은 `[]`와 같이 대괄호만을 이용한다:

```
someInts.append(3)

// someInts now contains 1 value of type Int

someInts = []

// someInts is now an empty array, but is still of type Int[]
```

스위프트의 `Array` 타입도 특정 크기와 기본 값을 갖는 배열을 만들 수 있는 생성자를 제공한다. 배열에 들어갈 수 있는 값의 갯수(`count` 인자)와 기본 값(`repeatedValue` 인자)을 생성자에 제공하여 배열을 만들 수 있다:

```
var threeDoubles = Double[](count: 3, repeatedValue: 0.0)

// threeDoubles is of type Double[], and equals [0.0, 0.0, 0.0]
```

생성자를 사용할 때 기본 값에서 타입을 추정하기 때문에 배열 생성시 굳이 타입 지정을 할 필요가 없다:

```
var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)

// anotherThreeDoubles is inferred as Double[], and equals [2.5, 2.5, 2.5]
```

마지막으로 이미 존재하는 같은 타입의 두 배열을 `+` 연산자를 통해 합치는 것만으로 새로운 배열을 생성할 수도 있다. 이렇게 만들어진 새로운 배열의 타입은 합치기 전 두 배열의 타입으로부터 추정 가능하다:

```
var sixDoubles = threeDoubles + anotherThreeDoubles

// sixDoubles is inferred as Double[], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
```


## 딕셔너리 Dictionaries ##

딕셔너리는 같은 타입을 가진 여러개의 값을 저장하는 하나의 컨테이너이다. 각각의 값은 유일한 키 값에 물려 있으며, 이 키 값은 딕셔너리 안에서 해당 값을 찾기 위한 식별자의 역할을 한다. 배열의 값들과 달리 딕셔너리 안에 저장된 값은 어떤 순서가 정해져 있지 않다. 실제로 사전에서 어떤 단어의 정의를 찾는 것과 매우 같은 방식으로 딕셔너리 안에 정의된 식별자를 이용해서 값을 찾는다.

스위프트의 딕셔너리는 특정한 타입의 키와 그에 따른 값을 저장한다. 이는 Objective-C에서 제공하는 `NSDictionary`와 `NSMutableDictionary` 클라스와는 다르다. `NSDictionary`와 `NSMutableDictionary` 클라스는 어느 종류의 객체든 키와 값으로 저장이 가능한 반면 그 저장된 객체의 속성에 대한 어떠한 정보도 제공하지 않는다. 스위프트에서는 특정 딕셔너리에 저장할 수 있는 키 타입과 밸류 타입은 항상 명시적인 타입 선언을 하거나 타입 추정을 통해 확인한다.

스위프트의 딕셔너리 타입은 `Dictionary` 형태로 쓰인다. 여기서 `KeyType`은 딕셔너리의 키 값으로 쓰이는 값에 대한 타입이고, `ValueType`은 딕셔너리의 키 값에 맞추어 저장하고자 하는 밸류의 타입을 정의하는 것이다.

딕셔너리가 갖고 있는 유일한 제약사항은 반드시 `KeyType`은 해시 가능한 타입이어야 한다. 즉, 그 자체로 유일하게 표현이 가능한 방법을 제공해야 한다는 것이다. 스위프트의 모든 기본 타입들 – `String`, `Int`, `Double`, `Bool` – 은 기본적으로 해시 가능한 것들이므로 딕셔너리의 키 타입으로 사용 가능하다. 연관된 값이 없는 열거형의 멤버 값들 역시도 기본적으로 해시 가능한 타입이다. ("Enumerations"\*링크필요\* 참조)


### 딕셔너리 표현식 Dictionary Literals ###

딕셔너리는 딕셔너리 표현식을 통해서 초기화를 시킬 수 있다. 딕셔너리 표현식은 앞에서 살펴봤던 배열 표현식과 비슷한 문법을 갖는다. 딕셔너리 표현식은 하나 또는 그 이상의 키/밸류 쌍을 딕셔너리 컬렉션에 담는 축약 형태를 가리킨다.

키/밸류 쌍은 키와 밸류의 조합이다. 딕셔너리 표현식에서 각각의 키/밸류 쌍 안에서 키와 밸류는 콜론으로 나뉜다. 키/밸류 쌍은 리스트로써, 콤마로 나뉘고 대괄호로 감싼다:

```
[ key 1 : value 1 , key 2 : value 2 , key 3 : value 3 ]
```

아래 예제는 국제공항들의 이름들을 저장하는 딕셔너리를 생성한다. 이 딕셔너리에서 키 값은 국제공항 코드 (IATA 코드)를 나타내는 세글자 코드이며 밸류는 공항의 이름이다:

```
var airports: Dictionary = ["TYO": "Tokyo", "DUB": "Dublin"]
```

`airports` 딕셔너리는 `Dictionary` 타입을 갖게끔 정의했으며 이것은 "`Dictionary` 타입으로서 `String` 타입의 키, `String` 타입의 밸류를 갖는다"는 것을 의미한다.

> **참고:**
> `airports` 딕셔너리는 `let` introducer를 이용한 상수형 대신 `var` introducer를 이용하여 변수로 정의하였다. 이는 아래 예제들에서 이 딕셔너리에 계속해서 공항들을 추가할 것이기 때문이다.

`airports` 딕셔너리는 두 개의 키/밸류 쌍을 포함하는 딕셔너리 표현식을 통해 초기화를 시켰다. 첫번째 쌍은 "`TYO`" 라는 키에 "`Tokyo`" 라는 밸류를 갖는다. 두번째 쌍은 "`DUB`" 라는 키에 "`Dublin`" 이라는 밸류를 갖는다.

이 딕셔너리 표현식은 두개의 `String:String` 쌍을 포함한다. 이것은 `airports` 타입의 정의인 `String` 타입의 키와 `String` 타입의 밸류를 갖는 딕셔너리와 일치한다. 따라서 딕셔너리 표현식을 이용해서 `airpots` 딕셔너리 변수를 두개의 초기값으로 초기화 시킬 수 있다.

As with arrays, you don’t have to write the type of the dictionary if you’re initializing it
with a dictionary literal whose keys and values have consistent types. The initialization of
airports could have been be written in a shorter form instead:
배열과 같이 딕셔너리 표현식의 키/밸류 쌍이 갖는 타입이 일정하다면 딕셔너리 타입을 정의할 필요가 없다. `aiports`의 초기화는 아래와 같은 축약 형태로 표현할 수 있다:

```
var airports = ["TYO": "Tokyo", "DUB": "Dublin"]
```

딕셔너리 표현식 안의 모든 키 값의 타입이 서로 같고, 마찬가지로 모든 밸류 타입이 서로 같기 때문에, 스위프트는 `Dictionary` 타입이 `airports` 딕셔너리에 적용 가능하다고 추정할 수 있다.


### 딕셔너리의 접근 및 수정 Accessing and Modifying a Dictionary ###

You access and modify a dictionary through its methods and properties, or by using
subscript syntax. As with an array, you can find out the number of items in a Dictionary by
checking its read-only count property:

딕셔너리는 메소드와 프로퍼티를 통해 접근과 수정이 가능하다. 혹은 subscript 문법을 사용할 수도 있다. 배열과 같이 딕셔너리 안에 값이 몇 개나 있는지를 확인하기 위해 읽기 전용 속성인 `count` 프로퍼티를 사용한다:

```
println("The dictionary of airports contains \(airports.count) items.")

// prints "The dictionary of airports contains 2 items."
```

딕셔너리에 새 아이템을 추가하기 위해 subscript 문법을 사용할 수 있다. 같은 타입의 새 키를 subscript 인덱스로 사용하여 같은 타입의 새로운 밸류를 할당한다:

```
airports["LHR"] = "London"

// the airports dictionary now contains 3 items
```

You can also use subscript syntax to change the value associated with a particular key:
Subscript 문법을 사용하여 특정 키에 물려 있는 값을 변경시킬 수도 있다:

```
airports["LHR"] = "London Heathrow"

// the value for "LHR" has been changed to "London Heathrow"
```

또다른 subscripting 방법으로써, 딕셔너리의 `updateValue(forKey:)` 메소드를 사용하여 특정 키에 해당하는 값을 설정하거나 변경할 수 있다. 위의 Subscript 예제와 같이 `updateValue(forKey:)` 메소드는 만약 키가 존재하지 않을 경우에는 값을 새로 설정하거나 키가 이미 존재한다면 기존의 값을 수정한다. 하지만 subscript와는 달리 `updateValue(forKey:)` 메소드는 업데이트를 하고난 뒤 이전 값을 반환한다. 이렇게 함으로써 실제로 업데이트가 일어났는지 아닌지를 확인할 수 있게 된다.

`updateValue(forKey:)` 메소드는 딕셔너리의 밸류 타입에 해당하는 `Optional` 값을 반환한다. 예를 들어 어떤 딕셔너리가 `String` 밸류를 저장한다면 이 메소드는 `String?` 타입 또는 "Optional `String`" 타입의 밸류를 반환한다. 이 Optional 밸류는 만약 키가 이미 있었다면 수정하기 이전 밸류를, 아니라면 `nil`을 갖는다:

```
if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") {
println("The old value for DUB was \(oldValue).")
}

// prints "The old value for DUB was Dublin."
```

Subscript 문법을 이용하면 특정 키 값에 대응하는 밸류를 딕셔너리에서 찾을 수 있다. 값이 존재하지 않는 키를 요청할 수 있기 때문에 딕셔너리는 딕셔너리의 밸류 타입에 해당하는 Optional 밸류를 반환한다. 만약 딕셔너리가 요청한 키에 대응하는 밸류를 갖고 있다면, Subscript 는 그 키에 대응하는 밸류를 Optional 밸류를 반환한다. 아니라면 Subscript는 `nil`을 반환한다:

```
if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}

// prints "The name of the airport is Dublin International."
```

Subscript 문법을 이용해 `nil` 값을 특정 키에 할당하는 것으로 딕셔너리에서 키/밸류 쌍을 삭제할 수 있다:

```
airports["APL"] = "Apple International"

// "Apple International" is not the real airport for APL, so delete it

airports["APL"] = nil

// APL has now been removed from the dictionary
```

또는 키/밸류 쌍을 딕셔너리에서 삭제할 때 `removeValueForKey` 메소드를 이용할 수 있다. 이 메소드는 키/밸류 쌍을 삭제하고 삭제된 값을 반환하거나 값이 없다면 `nil`을 반환한다:

```
if let removedValue = airports.removeValueForKey("DUB") {
println("The removed airport's name is \(removedValue).")
} else {
println("The airports dictionary does not contain a value for DUB.")
}

// prints "The removed airport's name is Dublin International."
```


### 딕셔너리에서 반복문 사용하기 Iterating Over a Dictionary ###

`for-in` 반복문을 사용하면 딕셔너리 안의 모든 키/밸류 쌍에 접근할 수 있다. 딕셔너리 각각의 아이템은 `(key, value)` 튜플을 반환하고, 반복문을 돌리는 도중 이 튜플의 멤버들을 분리하여 임시 상수 혹은 변수에 할당하여 사용할 수 있다:


```
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}

// TYO: Tokyo
// LHR: London Heathrow
```

`for-in` 반복문에 대한 자세한 내용은 "For 반복문"\*링크필요\* 섹션을 참고하도록 하자.

또한 딕셔너리의 `keys`, `values` 프로퍼티를 이용하면 키 또는 밸류 컬렉션을 반복문으로 돌릴 수 있다:

```
for airportCode in airports.keys {
println("Airport code: \(airportCode)")
}

// Airport code: TYO
// Airport code: LHR

for airportName in airports.values {
println("Airport name: \(airportName)")
}

// Airport name: Tokyo
// Airport name: London Heathrow
```

만약 딕셔너리의 키 콜렉션, 밸류 콜렉션을 `Array` 인스턴스를 이용하고 싶다면, 딕셔너리의 `keys`, `values` 프로퍼티를 배열로 초기화하여 사용할 수 있다:

```
let airportCodes = Array(airports.keys)

// airportCodes is ["TYO", "LHR"]

let airportNames = Array(airports.values)

// airportNames is ["Tokyo", "London Heathrow"]
```

> **참고:**
> 스위프트의 `Dictionary` 타입은 순서를 정하지 않는 컬렉션이다. 키, 밸류, 키/밸류 쌍의 순서는 반복문을 돌릴때 정해지지 않는다.


### 빈 딕셔너리 만들기 Creating an Empty Dictionary ###

배열과 마찬가지로 초기화 문법을 이용하여 비어있는 딕셔너리 타입을 만들 수 있다:

```
var namesOfIntegers = Dictionary()

// namesOfIntegers is an empty Dictionary
```

이 예제는 `Int, String` 타입을 갖는 빈 딕셔너리를 만든다. 키는 `Int` 타입, 밸류는 `String` 타입이다.

만약 컨텍스트에서 이미 해당 타입에 대한 정보를 제공한다면 빈 딕셔너리 표현식을 이용하여 딕셔너리를 초기화하여 만들 수 있다. 빈 딕셔너리 표현식은 `[:]` 으로 나타낼 수 있다:

```
namesOfIntegers[16] = "sixteen"

// namesOfIntegers now contains 1 key-value pair

namesOfIntegers = [:]

// namesOfIntegers is once again an empty dictionary of type Int, String
```

> **참고:**
> 스위프트의 배열과 딕셔너리 타입은 제너릭 컬렉션을 구현한다. 제너릭 타입과 컬렉션에 대한 더 자세한 내용은 "제너릭"\*링크필요\* 섹션을 참고하도록 하자.


## 컬렉션의 변경 가능성 Mutability of Collections ##

배열과 딕셔너리는 하나의 컬렉션 안에 여러개의 값을 저장한다. 만약 어떤 변수를 배열이나 딕셔너리 형태로 만든다면 이 컬렉션은 변경이 가능하다. 이는 컬렉션이 초기화된 후에도 여기에 아이템을 더 추가한다거나 뺀다거나 하는 식으로 컬렉션의 크기를 변경시킬 수 있다는 것을 의미한다. 반면에 배열이나 딕셔너리를 상수에 할당한다면 이때에는 컬렉션의 값도, 크기도 바꿀 수 없다.

이러한 불변성 딕셔너리는 기존의 키에 대응하는 값을 바꿀 수 없다는 것을 의미한다. 다시 말해서 불변성 딕셔너리라면 한 번 값이 설정된 후에는 절대로 바꿀 수 없다.

그러나 배열에서 이러한 불변성은 살짝 다른 의미를 갖는다. 불변성 배열의 크기를 바꿀 가능성이 있는 어떤 것도 할 수 없지만, 기존의 배열 인덱스에 새로운 값을 설정하는 것은 가능하다. 이것은 배열의 크기가 고정될 경우, 스위프트의 `Array` 타입에 배열 연산과 관련하여 최적의 성능을 제공한다.

스위프트가 제공하는 `Array` 타입의 변경 가능성은 또한 어떻게 배열 인스턴스가 생성되고 변경되는지에 대해서도 영향을 미친다. 더 자세한 내용은 "컬렉션 타입에서 할당과 복사 형태"\*링크필요\* 섹션을 참조하도록 하자.

> **참고:**
> 컬렉션의 크기를 변경시킬 필요가 없는 경우에는 불변성 컬렉션을 만드는 것이 좋다. 이렇게 함으로써 스위프트 컴파일러가 컬렉션의 퍼포먼스에 최적화를 시킬 수 있다.

chapter7
# 07 흐름 제어 (Control Flow)
> Translator : 김나솔(nasol.kim@gmail.com)

Swift 언어에서는 C언어 같은 프로그래밍 언어에서 제공하는 것과 비슷한 제어문 관련 constructs를 제공합니다. 이러한 constructs에는 `for`나 `while`이 있으며, 이러한 키워드는 어떤 과제(task)를 여러 번 수행합니다. `if`와 `switch`문은 특정 조건이 충족되는지에 따라서 분기시켜서 코드 블럭을 실행시킵니다. 또한 `break`나 `continue` 같은 구문은 실행의 흐름을 코드 상의 다른 곳으로 이동시킵니다.

C언어에서는 `for`-조건부-증가(increment) 순환문(loop) 이런 방식을 전통적으로 사용하는데, Swfit에서는 `for-in` 순환문(loop)이라는 것이 있어서 배열이나 사전(dictionaries), ranges, 문자열(strings)등 sequence에 대해서iteration하기가 쉽습니다.

C언어의 `switch`문과 비교했을 때, Swift의 `switch`문은 훨씬 더 강력합니다. Swift에서는 `switch`문이 "fall through" 하지 않습니다(역자주: fall through란, switch문에서 한 case에 대해서 처리하고 난 후 다음 case로 넘어가는 것). C언어에서는 실수로 `break`문을 써주지 않아서 에러가 생기는 경우가 있는데 Swift에서는 fall through 하지 않기 때문에 이런 에러를 방지할 수 있습니다. `swich`내의 case에 대해서 여러 종류의 pattern-maching을 사용할 수 있습니다. 수의 범위 match, 투플 match, casts to a specific type. `switch case`에서 match된 값을 임시 상수나 변수에 binding할 수도 있습니다. 이렇게 binding해두면 case의 본문(body) 내에서 이 상수나 변수를 사용할 수 있습니다. 또한 매칭 조건(matching condition)이 복잡한 경우에는, 각 case에 대해서 where절(where clause)을 사용해서 표현할 수 있습니다.

## `For` 순환문(For Loops)

`for` 순환문(for loop) 사용하면 코드 블럭을 특정 횟수 만큼 수행할 수 있습니다. Swift에는 두 종류의 for 순환문이 있습니다:

* `for-in` : 어떤 범위나 sequence, collection, progression에 대해서, 이 안에 있는 각 항목(item)에 대해서 코드(a set of statement)를 실행합니다.

* `for-condition-increment` : 특정 조건부가 참이 될 때까지 코드를 실행합니다. 보통 루프를 한 번 도는 것이 끝날 때마다 counter를 1씩 증가시킵니다.

## `For-In`

여러 항목이 들어 있는 컬렉션(collection)이나, 어떤 범위, 배열 안에 들어 있는 항목(item)에 대해서, 또는 문자열에 들어 있는 각 문자에 대해서 iteration을 할 때 `for-in` loop를 사용합니다.

다음의 예는 구구단의 5단에서 처음 몇 개를 출력해 줍니다:
```
for index in 1...5 { println("\(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
```

위 예에서는 범위가 1부터 5까지로 정해져 있고(closed range of numbers), 이 범위에 대해서 컬렉션(collection)안에 들어 있는 각 항목(item)에 대해 이터레이션을 돌고 있습니다. 단, 1...5라고 표현했을 때, ...(closed range operator)를 보면 알 수 있듯이, 이 범위에는 1과 5가 포함됩니다. 인덱스(index)의 값은 범위 내의 첫번째 수, 즉 1이 되며, 루프 내에 있는 구문이 실행됩니다. 위 예에서 루프 안에는 구문이 하나만 있습니다. 인덱스의 현재 값에 대해서 5단의 첫번째를 출력해주는 것입니다. 이 구문이 실행된 다음에 인덱스의 값은 범위 내의 두번째 값, 즉 2가 되도록 업데이트 됩니다. 그리고 printLn 함수가 다시 호출됩니다. 이 작업은 인덱스가 범위의 끝에 이를 때까지 계속됩니다.

위 예에서 인덱스는 상수(constant)이며, 이 상수의 값은 루프를 돌 때마다, 초반에 자동으로 값이 지정됩니다. 따라서 이 상수를 사용하기 전에 선언할 필요가 없습니다. 루프를 선언할 때 포함시키기만 해도 암묵적으로 선언한 셈이 됩니다. 즉 let 선언 키워드(declaration keyword)를 써줄 필요가 없습니다.

>NOTE - 인덱스 상수는 루프의 스코프(scope)안에서만 존재합니다. 루프문이 끝난 다음에 이 인덱스의 값을 확인하고 싶거나, 이 값을 상수가 아니라 변수로 사용하고 싶으면, 루프 안에서 변수로 직접 선언해 주어야 합니다.


범위 내에 있는 값이 필요 없다면, 변수명 대신에 언더바(`_`, underscore)를 써주면 됩니다:

```
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
println("\(base) to the power of \(power) is \(answer)")
println("\(base)를 \(power)번 곱한 것은 \(answer)이다")

// prints "3 to the power of 10 is 59049"
// prints “3의 10승은 59049입니다.”
```

위 예는 어떤 수의 몇 승을 계산해 줍니다(이 예에서는 3의 10승을 계산했습니다). 시작하는 값은 1인데(이는 3의 0승입니다), 이 시작하는 값에 다시 3을 곱해줍니다. 이 때 0에서 시작해서 9에서 끝나는 half-closed loop를 사용하였습니다. 이 계산을 수행할 때, 루프를 도는 동안 counter의 값은 필요 없습니다. 정확한 횟수만큼 루프를 도는 것만이 중요합니다. 밑줄(`_`, underscore)은 위 예에서 루프 변수 자리에 쓰였는데요, 그 결과 루프를 돌 때의 counter 현재값에 접근할 수 없게 됩니다.

배열 안에 들어 있는 항목(item)에 대해서 이터레이션(iteration)을 할 때에, `for-in` 루프를 사용하세요.

```
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
println("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex !
// Hello, Brian!
// Hello, Jack!
```


딕셔너리(dictionary)에 대해서도 이터레이션(iteration)을 해서 키-값 쌍(key-value pairs)에 접근할 수 있습니다. 딕셔너리에 대해서 이터레이션을 하면, 딕셔너리의 각 항목이 (key, value) 투플의 형태로 반환됩니다. 그리고 이 키-값 쌍은 쪼개어져서 두 개의 상수의 값으로 들어갑니다. 이 값은 `for-in` 루프 내의 본문(body)내에서 사용할 수 있습니다. 아래의 예에서 딕셔너리의 **키**는 animalName이라는 상수에, 딕셔너리의 **값**은 legCount라는 상수에 값으로 들어갑니다:

```
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
println("\(animalName)s have \(legCount) legs")
}
// spiders have 8 legs
// ants have 6 legs
// cats have 4 legs
```
딕셔너리 안에 있는 항목이 이터레이션 될 때, 딕셔너리 안에 들어 있는 순서대로 되지는 않습니다. 딕셔너리 안에 들어 있는 데이터는 원래 정의상 순서가 없으며, 이터레이션을 돌 때에도, 어느 항목에 대해서 돌지 확신할 수 없습니다. 배열과 딕셔너리에 대해서 더 자세히 보시려면 컬렉션 형(Collection Types) 장을 참조하세요.


이 이터레이션 되는 순서는 고정되어 있지 않습니다. 딕셔너리 안에 들어 있는 순서대로
배열과 딕셔너리 외에도, 문자열 내의 각 문자에 대해 이터레이션을 돌 때, `for-in` 루프를 사용할 수 있습니다:

```
for character in "Hello" {
println(character)
}
// H
// e
// l
// l
// o
```

## For-조건부-증가부 (For-Condition-Increment )

Swift는 `for-in`루프 말고도 C언어에서 쓰는, 조건부와 증가부가 들어 있는 `for` 루프를 지원합니다:

```
for var index = 0; index < 3; ++index {
println("index is \(index)")
}
// index is 0 // index is 1 // index is 2
```
다음은 이번에 다루는 루프 형식을 일반화해서 나타낸 것입니다.

```
for initialization ; condition ; increment {
statements
}
```

루프의 정의부는 세 부분으로 구성되는데, C언어에서처럼 각 부분을 세미콜론`;`으로 구분하고 있습니다. C언어와는 다르게 Swift에서는 "초기화;조건부;증가부" 부분을 괄호로 감싸주지 않아도 됩니다.

다음은 루프가 실행되는 단계를 나타냅니다:

1. 처음 루프에 들어가면, 초기화 표현식(initialization expression)이 검토되고 루프를 도는 데 필요한 변수나 상수의 값을 지정합니다.
2. 조건 표현식(condition expression)을 검토합니다. 조건부가 거짓(false)이면, 루프는 종료하고, 코드 실행(code execution)은 루프를 닫는 중괄호(})다음 부분에서 계속됩니다. 조건부가 참(true)이면, 코드 실행은 루프를 여는 괄호({) 안에서 구문들을 실행합니다.
3. 모든 구문이 실행된 후에는 증가부 표현식(increment expression)이 검토됩니다. 검토 결과 카운터의 값이 증가할 수도 있고 감소할 수도 있습니다. 또는 초기화되었던 변수의 값이 실행된 구문의 결과값에 근거하여 새로운 값으로 대체될 수도 있습니다. 증가부 부분이 검토된 후, 코드 실행은 2단계로 돌아가며, 조건 표현식이 다시 검토됩니다.

위에서 설명한 루프문의 형식(format)과 코드 실행 절차를 개요로 나타내면 다음과 같습니다:
```
initialization
while condition {
statements
increment
}
```
초기화 부분에서 선언된 상수와 변수(예를 들면 var index=0)는 `for` 루프 스코프 내에서만 사용할 수 있습니다. 루프가 끝난 후에도 index의 마지막 값에 접근할 수 있으려면, 루프 스코프가 시작하는 지점 이전에 index를 선언해주어야 합니다 (즉 루프 스코프의 바깥에서 선언해 주어야 합니다):

```
var index : Int // <= 이 부분에서 선언해 주어야..
for index = 0; index < 3; ++index {
println("index is \(index)")
}
// index is 0
// index is 1
// index is 2
println("The loop statements were executed \(index) times")
// prints "The loop statements were executed 3 times"
```

위 예에서 한 가지 주의할 점이 있습니다. 루프가 끝났을 때 index의 마지막 값은 2가 아니라 3입니다. 마지막으로 증가부(increment)가 실행되었을 때, index의 값은 3이 됩니다. index가 3이 되니, index < 3 조건부 false가 되서 루프가 끝난 것입니다.

## While 루프 (While Loops)

`while` 루프는 조건부가 거짓이 될 때까지 코드 블럭을 실행시킵니다. 이런 종류의 루프는 보통, 이터레이션이 시작하기 전에 이터레이션이 몇 번이나 돌 지 알지 못할 때 자주 사용합니다. Swift는 두 종류의 `while`루프를 지원합니다. 하나는 `while`인데, 이 루프는 루프를 돌기 시작할 때 조건부를 검토합니다. 다른 하나는 `do-while`인데, 이 루프는 루프를 돌고 나서 조건부를 검토합니다.

### While

`while` 루프는 한 개의 조건부를 검토하는 것에서 시작합니다. 조건부가 참이면, 코드가 실행되며, 조건부가 거짓이 될 때까지 반복해서 실행됩니다.
다음은 `while`루프를 일반화해서 나타낸 것입니다:

```
while condition {
statements
}
```

이번에 사용할 예제는 뱀과 사다리 게임입니다.

[그림 삽입]

게임의 규칙은 다음과 같습니다:

* 게임판에는 25개의 칸이 있으며, 목표는 25번 칸에 도달하거나 이를 넘는 것입니다.
* 자기 차례가 오면, 참가자는 6면 주사위를 던지고 나온 수 만큼 점선으로 표시된 경로를 따라서 이동합니다.
* 이동했을 때, 사다리의 아랫 부분에 도달하면, 사다리를 타고 올라갑니다.
* 이동했을 때 뱀의 머리에 도달하면, 뱀을 타고 내려갑니다.

게임판은 정수값 (Int values)으로 나타냅니다. 게임판의 크기는 finalSquare 상수로 정합니다. finalSquare는 배열을 초기화할 때 사용하며, 나중에 게임에 이겼는지 여부를 판별할 때도 사용합니다. 배열 board는 26개의 정수값 0으로 초기화됩니다. 25개가 아닙니다. (0부터 25까지, 26개입니다.)

```
let finalSquare = 25
var board = Int[](count : finalSquare + 1, repeatedValue: 0)
```

몇몇 칸에는 0이 아니라 특정한 값이 지정됩니다. 이 값은 뱀과 사다리 때문에 필요한 값입니다. 사다리의 밑부분이 들어 있는 칸은 게임판에서 앞으로 이동시키는 만큼의 양수(positive number)를 포함하고, 뱀 머리가 들어 있는 칸은 게임판에서 뒤로 이동시키는 만큼의 음수(negative number)를 포함합니다:

```
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
```

3번 칸은 사다리의 밑 부분을 포함합니다. 여기에 가면 참가자는 11번 칸으로 이동합니다. 이것을 나타내기 위해서 board[03]에 +08 값을 지정합니다. 이는 정수값 8과 동일합니다(11과 3간의 차이). 단항 연산자인 plus operator(+i)는 단항 연산자 minus operator(-i)와 균형을 이룹니다. 또한 10보다 작은 수에는 10자리에 0을 넣어서(예: 8 -> 08) 줄이 맞추어져 가지런하게 보이도록 했습니다.

(이처럼 0을 넣는 등 스타일에 변화를 주는 것은 꼭 필요한 것은 아닙니다만, 이렇게 하면 코드가 더 깔끔하게 보입니다.)


게임 참가자가 시작하는 칸은 "0번 칸"이며, 이 칸은 게임판의 좌측 하단 바깥에 있습니다. 주사위를 처음 던지면, 참가자는 항상 게임판 위로 이동하게 됩니다:

```
var square = 0
var diceRoll = 0
while square < finalSquare {
// 주사위를 던진다
if ++diceRoll == 7 { diceRoll = 1 }
// 주사위를 던져 나온 수 만큼 이동한다
square += diceRoll
if square < board.count {
// 아직 게임판에 있다면, 뱀을 타고 내려가거나 사다리를 타고 올라간다
//if we're still on the board, move up or down for a snake or a ladder
square += board[square]
("Game over!")
```

이 예제에서는 주사위를 던지는 부분을 간단하게 처리했습니다. 난수를 발생시키지 않고, diceRoll의 값을 0에서 시작하게 하고, 루프를 돌 때마다, diceRoll 값이 1씩 증가하도록 했습니다. ++i (prefix increment operator)를 사용해서 말이죠. 그런 다음에 diceRoll의 값이 너무 크지 않은지 확인했습니다. ++diceRoll 값은 diceRoll이 1만큼 증가한 값과 같습니다. ++diceRoll 값이 7과 같아지면, 값이 너무 커진 것이며, 이 때 diceRoll 값을 1로 해줍니다. 이렇게 하면 diceRoll의 값은 항상 1,2,3,4,5,6,1,2, 등등의 값을 가지게 됩니다.

주사위를 던진 후에, 게임 참가자는 diceRoll 값 만큼 칸을 이동합니다. 주사위에서 나온 수만큼 이동했는데, 참가자가 25번 칸을 넘어가는 경우가 생길 수 있습니다. 이 경우에는 게임이 끝납니다. 이 시나리오를 따르기 위해서, 코드는 현재의 칸 번호(square) 값에다 board[squre]에 저장된 값을 더해서 참가자를 이동시키기 전에, 칸 번호가 board 배열의 count 값보다 작은지 확인합니다.

이렇게 확인작업을 해주지 않으면, board[squre]라고 썼을 때 board 배열의 범위를 넘어서는 값을 접근하려고 시도하게 됩니다.



chapter8
# 08 함수 (Functions)
> Translator : 이름 (메일주소Quartet( ungsik.yun@gmail.com )

함수는 특정 일을 수행하는 자기 완결성(Self-contained)을 가진 코드들의 집합입니다. 당신은 함수의 이름을 지으면서 이 함수가 무엇을 하는지 식별하게 할 수 있습니다. 그리고 그 이름으로 함수를 "호출(Call)"하여 필요할때 함수의 일을 수행하게 만들 수 있습니다.
스위프트(Swift)의 함수 문법은 파라메터가 없는 C스타일의 함수에서부터 지역 파라메터와 파라메터 이름 각각에 대한 외부 파라메터를 가지고 있는 복잡한 오브젝티브-C 스타일의 함수까지 전부 표현할 수 있습니다. 파라메터는 기본 값을 가질수 있어 단순한 함수 호출에 쓰일수 있습니다. 또한 In-out 파라메터로서 변수를 넘겨 변수가 함수의 실행후에 파라메터가 변경되게 할 수도 있습니다.
파라메터 타입과 반환(Return) 타입으로 이루어진 모든 스위프트의 함수들은 타입을 가집니다. 스위프트에 있는 다른 타입들과 마찬가지로, 함수의 타입들을 사용할 수 있습니다. 즉 함수를 다른 함수에 파라메터로서 넘겨주거나 함수를 다른 함수에서 반환받을 수 있습니다. 함수들은 유용한 기능 캡슐화를 위해 중첩된 함수안의 범위 내에서 쓰여질수도 있습니다.

## 함수 정의와 호출
함수를 정의할때 함수의 입력(파라메터)을 하나 이상의 이름이 있고 타입이 정해진 값으로 할 수 있습니다. 또한 값의 타입은 함수의 실행이 끝났을때 함수가 되돌려줄 수 있습니다 (반환 타입).
모든 함수는 함수명을 가지고 있으며, 함수명은 함수가 하는일을 설명해줍니다. 함수를 사용하기위해서 함수를 함수의 이름을 사용하여 "호출"하고 함수의 파라메터 타입들과 일치하는 입력 값들(아규먼트Arguments)을 넘겨줍니다. 함수의 입력값은 함수의 파라메터리스트와 언제나 일치해야합니다.
아래의 함수 예제 이름은 `greetingForPerson`입니다. 함수가 행하는 일이 바로 그것(사람에게 환영인사Greeting for person)이기 때문입니다. 입력으로 사람의 이름을 받아서 그 사람에 대한 환영 인사를 반환합니다. 이를 달성하기 위해 파라메터를 하나 정의하고 - `personName`이라는 `String` 값 - 반환 타입을 `String`으로 합니다. 그렇게 그 사람에 대한 인사를 포함하는 것입니다.

```
func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
```
이 모든 정보들은 func 키워드 접두어를 쓰는 함수의 정의안에 포함이 되게도비니다. 함수의 반환 타입은 화살표(하이픈과 우측 꺽괄호) `->`를 사용하여 화살표 오른쪽에 표시합니다.
함수 정의는 함수가 무엇을 하는지, 무엇을 파라메터로 받는지 완료되었을때 무엇을 반환하는지 설명합니다. 함수 정의는 함수가 코드안에서 호출될때 명확하고 애매함이 없는 방법으로 사용될수 있게합니다:

```
println(sayHello("Anna"))
// prints "Hello, Anna!"
println(sayHello("Brian"))
// prints "Hello, Brian!"
```
`sayHello` 함수를 괄호안에 `String` 타입의 인수를 넣어서 호출합니다. 예를들면 `sayHello("Anna")` 처럼 말이죠. `sayHello`가 `String`타입을 반환하기에 `sayHello`함수는 println로 싸여서 호출될 수 있습니다. 이렇게 함으로서 println함수가 sayHello함수의 반환값을 위에 보이는 것처럼 출력할 수 있습니다.
`sayHello`함수의 몸체는 `greeting`이라는 새 `String` 상수를 선언하는 것으로 시작합니다. 그리고 `greeting`을 `personName`에 대한 단순한 환영인사로 설정합니다. 이 환영 인사는 `return`키워드를 통해 함수의 밖으로 되돌려지게 됩니다. `return greeting`이 실행 되면 함수의 실행은 끝나게되고, `greeting`의 현재 값을 돌려주게됩니다.
`sayHello` 함수를 다른 입력값으로 여러번 호출할 수 있습니다. 위의 예제는 입력값이 "Anna", "Brian" 일때를 각각 보여주고 있습니다. 함수는 사람(입력값)에 맞게끔 환영인사를 각각의 경우에 맞추어 돌려줍니다.
함수 몸체를 단순화하기 위해서는, 메시지의 생성과 반환을 한줄로 합치면 됩니다:
```
func sayHelloAgain(personName: String) -> String {
return "Helloagain, " + personName + "!"
}
println(sayHelloAgain("Anna"))
// prints "Helloagain, Anna!
```
## 함수 파라메터와 반환값
스위프트에서 함수 파라메터와 반환값은 극도로 유연합니다. 이름없는 파라메터를 사용하는 단순한 기능성 함수에서부터 명시적 파라메터 이름(expressive parameter names)과 다른 파라메터 옵션을 가진 복잡한 함수에 이르기까지 무엇이든 정의할수 있습니다.

### 파라메터 복수 입력
함수는 괄호 안에서 콤마로 구분되는 복수의 입력 파라메터를 가질수 있습니다.
이 함수는 반개영역(half-open range)의 시작과 끝의 인덱스를 받아 얼마나 많은 요소(elements)들이 영역안에 있는지 계산합니다:

func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
println(halfOpenRangeLength(1, 10))
// prints "9"

## 파라메터가 없는 함수
함수에 입력 파라메터를 정의할 필요는 없습니다. 밑의 예제는 입력 파라메터가 없는 함수입니다. 이 함수는 호출될때마다 언제나 같은 메시지를 반환합니다.

func sayHelloWorld() -> String {
return "hello, world"
}
println(sayHelloWorld())
// prints "hello, world"
```
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
println(halfOpenRangeLength(1, 10))
// prints "9"
```
### 파라메터가 없는 함수
함수에 입력 파라메터를 정의할 필요는 없습니다. 밑의 예제는 입력 파라메터가 없는 함수입니다. 이 함수는 호출될때마다 언제나 같은 메시지를 반환합니다.
```
func sayHelloWorld() -> String {
return "hello, world"
}
println(sayHelloWorld())
// prints "hello, world"
```

함수 정의는 아무런 파라메터를 받지 않는다고 해도 함수 이름뒤에 여전히 괄호를 포함해야 합니다. 함수가 호출될 때도 함수 이름뒤에 빈 괄호 한쌍이 따라와야합니다.

### 반환값이 없는 함수
함수에 반환 타입을 정의할 필요는 없습니다. 밑의 예제는 `sayHello`의 `waveGoodbye`라 불리는 버전입니다. 값을 반환하지 않고 자신만의 `String`값을 출력합니다.

func sayGoodbye(personName: String) {
println("Goodbye, ` \(personName)! ")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"
```
func sayGoodbye(personName: String) {
println("Goodbye, ` \(personName)! ")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"
```

반환값을 필요로 하지 않기 때문에 함수 정의는 반환 화살표(return arrow)나 반환 타입을 포함하지 않습니다.

> N O T OTE
엄밀히 말하자면, `sayGoodbye` 함수는 반환값이 정의되어있지 않아도 여전히 반환값을 가집니다. 반환값이 정의되어있지 않은 함수는 `Void`타입의 특수값을 반환합니다. '()'로 쓰여질수 있는 단순한 빈 튜플(Tuple)이며, 사실상 요소를 갖고있지 않은 튜플입니다.

함수가 호출되었을때 함수의 반환값은 무시될수 있다.
```
func printAndCount(stringToPrint: String) -> Int {
println(stringToPrint)
return countElements(stringToPrint)
}
func printWithoutCounting(stringToPrint: String) {
printAndCount(stringToPrint)
}
printAndCount("hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting("hello, world")
// prints "hello, world" but does not return a value
```
첫번째 함수인 `printAndCount`는 문자열을 출력하고 출력한 문자열의 캐릭터 갯수를 세서 Int 타입으로 반환합니다. 두번째 함수인 `printWithoutCounting`은 첫번째 함수를 호출합니다. 하지만 반환값은 무시합니다. 두번째 함수가 호출되면 메시지는 첫번째 함수에 의해 여전히 출력되지만, 첫번째 함수의 반환값은 사용되지 않습니다.

> N O T OTE
반환값은 무시될수 있습니다. 하지만 함수는 언제나 값을 반환할것입니다. 반환 타입이 정의된 함수는 값을 반환하지 않은채로 함수가 실행 될수 없습니다. 그렇게 하려고 시도할 경우 컴파일 에러를 낼 것입니다.

### 여러개의 반환값을 가지는 함수
튜플 타입은 하나의 합성된 반환값으로서 함수의 반환에 사용될 수 있습니다.
아래의 예제는 `count`라는 함수의 정의입니다. 이 함수는 아메리칸 영어에서 사용되는 표준 모음과 자음을 기반으로 모음과 자음 그리고 다른 문자들을 문자열안에서 셉니다.
```
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {
var vowels = 0, consonants = 0, others = 0
for character in string {
switch String(character).lowercaseString {
case "a", "e", "i ", "o", "u":
++vowels
case "b", "c", "d", "f", "g", "h", "j", "k", "l ", "m",
"n", "p", "q", "r", "s", "t", "v", "w ", "x", "y", "z":
++consonants
default:
++others
}
}
return (vowels, consonants, others)
}
```
이 count 함수를 이용함으로서 임의의 문자열의 문자 갯수를 셀수 있습니다. 그리고 세 개의 이름있는 Int 값으로 구성된 튜플로 그 값을 받아옵니다.
```
let total = count("some arbitrary string! ")
println("\(total.vowels) vowels and \(total.consonants) consonants")
// prints "6 vowels and 13 consonants"
```
튜플의 멤버들은 함수 내에서 반환할때 이름을 지을 필요가 없습니다. 함수 정의시에 함수의 반환 타입에 이미 명시가 되어있기 때문입니다.

## 함수 파라메터 이름
위의 모든 함수들은 함수 자신의 파라메터로 파라메터 이름을 정의하고 있다.
```
func someFunction(parameterName: Int) {
// function body goes here, and can use parameterName
// to refer to the argument value for that parameter
}
```
하지만 그러한 파라메터 이름들은 오직 함수 자신의 몸체(Body) 안에서만 사용될 수 있습니다. 또한 함수를 호출할때는 사용할 수 없습니다. 그러한 종류의 파라메터 이름은 지역 파라메터 이름(local parameter names)이라고 합니다. 오직 함수의 내부(Body)에서만 사용할 수 있기 때문입니다.

### 외부 파라메터 이름(External Parameter Names)
때때로 각각의 파라메터의 이름을 함수를 호출할때 지어주는 것이 유용할때가 있습니다. 함수에게 어떤 인수가 어떤 목적인지 지시하기 위해서죠.
만약 당신이 만든 함수를 사용하려는 사용자에게 파라메터 이름을 제공하고 싶다면, 지역 파라메터 이름과 외부 파라메터 이름을 정의하면 됩니다. 외부 파라메터 이름은 지역 파라메터 이름 바로 앞에 공백으로 구분해서 작성합니다.
```
func someFunction(external ParameterName localParameterName: Int) {
// function body goes here, and can use local ParameterName
// to refer to the argument value for that parameter
}
```
> N O T OTE
만약 외부 파라메터 이름이 파라메터에 대해 제공된다면, 외부 파라메터 이름은 언제나 함수 호출시에 사용되어야 합니다.

예를 들어 다음과 같은 함수가 있다고 합시다. 이 함수는 두 문자열 사이에 `joiner` 문자열을 삽입해 연결하는 함수입니다.
```
func join(s1: String, s2: String, joiner: String) -> String {
return s1 + joiner + s2
}
```
이 함수를 호출할때 함수로 전달되는 세 문자열의 목적이 불분명합니다.
```
join("hello", "world", ", ")
// returns "hello, world"
```
문자열 값들의 목적을 명확하게 하기 위해, 외부 파라메터를 join함수의 각각의 파라메터에 정의합니다.

```
func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String {
return s1 + joiner + s2
}
```

이 버전의 join 함수에서는 첫번째 파라메터의 외부 이름은 `string`이며 지역 이름은 `s1`이다. 두번째 파라메터는 외부 이름으로 `toString`을 쓰고 지역 이름은 `s2`이다. 그리고 세번째 파라메터는 외부 이름으로 `withJoiner`를 쓰고 지역 이름은 `joiner`이다.
이제 외부 파라메터 이름을 사용하여 함수를 호출할때 명확하고 애매하지 않은 방법으로 호출할 수 있게 되었다.
```
join(string: "hello", toString: "world", withJoiner: ", ")
// returns "hello, world"
```
외부 파라메터 이름의 사용은 이 두번째 join함수를 명시적이며 말이 되는(sentence-like) 방법으로 사용자들이 호출할 수 있게 합니다. 함수 몸체는 여전히 가독성이 좋고 명확한 의도를 가진채 말이죠. (whi le sti l l providing a function body that is readable and clear in intent.)

>N O T OTE
누군가가 당신의 코드를 처음 보았을때 명확하지 않을 수 있다면 외부 파라메터 이름을 쓰는것을 언제나 고려하십시오. 만약 함수가 호출될때 각각의 파라메터들의 목적이 명확하고 모호하지 않다면 외부 파라메터 이름을 정할 필요는 없습니다.

### 단축 외부 파라메터 이름
만약 함수의 외부 파라메터 이름을 제공하려 할때 이미 해당 파라메터의 내부 이름(local parameter name)이 이미 적절한 이름을 가지고 있다면, 똑같은 이름을 두번 쓸 필요가 없다. 대신 파라메터 이름을 한번 쓰고, 이름의 접두어로 해시 심볼(hash symbol) (`#`)을 붙인다. 이렇게 함으로서 스위프트는 해당 이름을 외부 파라메터 이름과 지역 파라메터 이름으로 동시에 쓰게 될 것이다.
이 예제는 `containsCharacter` 함수를 정의하고 호출한다. 해당 함수는 두 입력 파라메터에 `#`을 붙여서 같은 이름으로 외부 파라메터 이름과 내부 파라메터 이름으로 쓰이게 하였다.
```
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
for character in string {
if character == characterToFind {
return true
}
}
return false
}
```
이 함수의 파라메터 이름 선정은 함수 몸체를 명확하고 가독성있게 하며 동시에 함수 호출에 모호함이 없게 하였다.
```
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee equals true, because "aardvark" contai ns a "v"
```
### 기본(default) 파라메터 값
함수 정의의 일부로서 파라메터의 기본 값을 지정해줄 수 있다. 기본값이 지정되어 있으면 함수를 호출할때 해당 파라메터를 생략할 수 있다.

>N O T OTE
기본값을 가지는 파라메터는 함수의 파라메터 리스트에서 마지막에 둔다. 이렇게 함으로써 함수 호출이 기본값을 가지지 않는 파라메터들이 언제나 같은 순서임을 보장할 수 있고, 매번 함수가 호출될 때마다 같은 함수가 호출되게 한다.

앞서 보인 `join`함수의 `joiner` 파라메터에 기본값을 부여한 버전이 있다.
```
func join(string s1: String, toString s2: String, withJoiner joiner: String = " ")
-> String {
return s1 + joiner + s2
}
```
만약 `join`함수의 `joiner` 문자열 값이 주어지면, 앞서 보았던 것처럼 해당 문자열 값이 두 문자열을 붙이는데 사용된다.
```
join(string: "hello", toString: "world", withJoiner: "-")
// returns "hello-world
```
하지만 아무런 값이 `joiner`에 주어지지 않는다면, 기본값인 공백 한칸 (`" "`)이 대신 사용된다.
```
join(string: "hello", toString: "world")
// returns "hello world"
```
### 기본값을 가지는 외부 파라메터 이름
대부분의 경우 외부 파라메터 이름에 기본값을 제공(외부 파라메터이기에 요구되기도 하는)하는 것은 유용하다. 그렇게 함으로써 함수가 호출될때 인수가 파라메터에 대해 가지는 목적이 명확해진다.
이 과정을 쉽게 하기위해, 외부 이름을 부여하지 않은 파라메터에 대해 스위프트는 자동 외부 이름을 기본값이 정의되어 있는 파라메터에 대해 제공한다. 자동 외부 이름은 지역 이름과 똑같다. 앞서 본 해시 심볼(`#`)을 사용한 것처럼.
여기에 `joiner` 문자열 값에 기본값을 부여하였지만, 파라메터 일체에 외부 파라메터 이름은 주지 않은 버전의 `join`함수가 있다.
```
func join(s1: String, s2: String, joiner: String = " ") -> String {
return s1 + joiner + s2
}
```
이 경우에 스위프트는 자동적으로 외부 파라메터 이름을 기본값이 있는 파라메터 `joiner`에 대해 부여한다. 그러므로 외부 이름은 반드시 함수가 호출 될 때에 제공되어야 하며, 파라메터의 목적을 명확하고 모호하지 않게 한다.
```
join("hello", "world", joiner: "-")
// returns "hello-world"
```
>N O T OTE
함수를 정의할때 명시적인 외부 이름을 쓰는 것 대신에 밑줄(`_`)을 씀으로써 이 동작을 수행하지 않게 할 수 있다. 하지만 기본값을 가진 파라메터에 적절한 외부 이름을 제공하는것은 언제나 바람직하다.

## Variadic Parameters
A variadi c parameter accepts zero or more values of a speci fied type. You use a variadi c
parameter to speci fy that the parameter can be passed a varying number of input values
when the function i s cal led. Wri te variadi c parameters by inserting three period
characters (. . .) after the parameter’s type name.
The values passed to a variadi c parameter are made avai lable wi thin the function’s body
as an array of the appropriate type. For example, a variadi c parameter wi th a name of
numbers and a type of Doubl e. . . i s made avai lable wi thin the function’s body as a constant
array cal led numbers of type Doubl e[].
The example below cal culates the ari thmeti c mean (al so known as the average) for a l i st
of numbers of any length:
func ari thmeti cMean(numbers: Doubl e. . . ) -> Doubl e {
var total : Doubl e = 0
for number i n numbers {
total += number
}
return total / Doubl e(numbers. count)
}
ari thmeti cMean(1, 2, 3, 4, 5)
// returns 3. 0, w hi ch i s the ari thmeti c mean of these fi ve numbers
meti cMean(3, 8, 19)
turns 10. 0, w hi ch i s the ari thmeti c mean of these three numbers
> N O T E
A functi on may have at most one vari adi c parameter, and i t must al w ays appear l ast i n the parameter l i st, to
avoi d ambi gui ty w hen cal l i ng the functi on w i th mul ti pl e parameters.
If your functi on has one or more parameters w i th a defaul t val ue, and al so has a vari adi c parameter, pl ace
the vari adi c parameter after al l the defaul ted parameters at the very end of the l i st.

## Constant and Variable Parameters
Function parameters are constants by defaul t. Trying to change the value of a function
parameter from wi thin the body of that function resul ts in a compi le-time error. Thi s
means that you can’t change the value of a parameter by mi stake.
However, sometimes i t i s useful for a function to have a variable copy of a parameter’s
value to work wi th. You can avoid defining a new variable yoursel f wi thin the function by
speci fying one or more parameters as variable parameters instead. Variable parameters
are avai lable as variables rather than as constants, and give a new modi fiable copy of the
parameter’s value for your function to work wi th.
Define variable parameters by prefixing the parameter name wi th the keyword var:
func al i gnRi ght(var stri ng: Stri ng, count: Int, pad: Character) -> Stri ng {
l et amountT oPad = count - countEl ements(stri ng)
for _ i n 1. . . amountT oPad {
stri ng = pad + stri ng
}
return stri ng
}
l et ori gi nal Stri ng = "hel l o"
l et paddedStri ng = al i gnRi ght(ori gi nal Stri ng, 10, "-")
addedStri ng i s equal to "- - - - -hel l o"
i gi nal Stri ng i s sti l l equal to "hel l o"
Thi s example defines a new function cal led al i gnRi ght, whi ch al igns an input string to the
right edge of a longer output string. Any space on the left i s fi l led wi th a speci fied
padding character. In thi s example, the string "hel l o" i s converted to the string "- - - - -hel l o".
The al i gnRi ght function defines the input parameter stri ng to be a variable parameter. Thi s
means that stri ng i s now avai lable as a local variable, ini tial i zed wi th the passed-in string
value, and can be manipulated wi thin the body of the function.
The function starts by working out how many characters need to be added to the left of
stri ng in order to right-al ign i t wi thin the overal l string. Thi s value i s stored in a local
constant cal led amountT oPad. The function then adds amountT oPad copies of the pad character
to the left of the exi sting string and returns the resul t. It uses the stri ng variable parameter
for al l i ts string manipulation.

>N O T E
T he changes you make to a vari abl e parameter do not persi st beyond the end of each cal l to the functi on,
and are not vi si bl e outsi de the functi on’s body. T he vari abl e parameter onl y exi sts for the l i feti me of that
functi on cal l .

## In-Out Parameters
Variable parameters, as described above, can only be changed wi thin the function i tsel f.
If you want a function to modi fy a parameter’s value, and you want those changes to
persi st after the function cal l has ended, define that parameter as an in-out parameter
instead.
You wri te an in-out parameter by placing the i nout keyword at the start of i ts parameter
defini tion. An in-out parameter has a value that i s passed in to the function, i s modi fied
by the function, and i s passed back out of the function to replace the original value.
You can only pass a variable as the argument for an in-out parameter. You cannot pass a
constant or a l i teral value as the argument, because constants and l i teral s cannot be
modi fied. You place an ampersand (&) di rectly before a variable’s name when you pass i t
as an argument to an inout parameter, to indi cate that i t can be modi fied by the function.
>N O T E
In-out parameters cannot have defaul t val ues, and vari adi c parameters cannot be marked as i nout. If you
mark a parameter as i nout, i t cannot al so be marked as var or l et.

Here’s an example of a function cal led sw apT w oInts, whi ch has two in-out integer
parameters cal led a and b:
func sw apT w oInts(i nout a: Int, i nout b: Int) {
l et temporaryA = a
a = b
b = temporaryA
}
The sw apT w oInts function simply swaps the value of b into a, and the value of a into b. The
function performs thi s swap by storing the value of a in a temporary constant cal led
temporaryA, assigning the value of b to a, and then assigning temporaryA to b.
You can cal l the sw apT w oInts function wi th two variables of type Int to swap thei r values.
Note that the names of someInt and anotherInt are prefixed wi th an ampersand when they
are passed to the sw apT w oInts function:
var someInt = 3
var anotherInt = 107
sw apT w oInts(&someInt, &anotherInt)
pri ntl n("someInt i s now \(someInt), and anotherInt i s now \(anotherInt)")
// pri nts "someInt i s now 107, and anotherInt i s now 3"
The example above shows that the original values of someInt and anotherInt are modi fied by
the sw apT w oInts function, even though they were original ly defined outside of the function.
>N O T E
In-out parameters are not the same as returni ng a val ue from a functi on. T he sw apT w oInts exampl e above
does not defi ne a return type or return a val ue, but i t sti l l modi fi es the val ues of someInt and anotherInt. Inout parameters are an al ternati ve w ay for a functi on to have an effect outsi de of the scope of i ts functi on
body.

## Function Types
Every function has a speci fi c function type, made up of the parameter types and the
return type of the function.
For example:
func addT w oInts(a: Int, b: Int) -> Int {
return a + b
}
func mul ti pl yT w oInts(a: Int, b: Int) -> Int {
return a * b
}
Thi s example defines two simple mathemati cal functions cal led addT w oInts and mul ti pl yT w oInts.
These functions each take two Int values, and return an Int value, whi ch i s the resul t of
performing an appropriate mathemati cal operation.
The type of both of these functions i s (Int, Int) -> Int. Thi s can be read as:
“A function type that has two parameters, both of type Int, and that returns a value of
type Int.”
Here’s another example, for a function wi th no parameters or return value:
func pri ntHel l oWorl d() {
pri ntl n("hel l o, w orl d")
}
The type of thi s function i s () -> (), or “a function that has no parameters, and returns Voi d.”
Functions that don’t speci fy a return value always return Voi d, whi ch i s equivalent to an
empty tuple in Swi ft, shown as ().
## Using Function Types
You use function types just l ike any other types in Swi ft. For example, you can define a
constant or variable to be of a function type and assign an appropriate function to that
variable:
var mathFuncti on: (Int, Int) -> Int = addT w oInts
Thi s can be read as:
“Define a variable cal led mathFuncti on, whi ch has a type of ‘a function that takes two Int
values, and returns an Int value.’ Set thi s new variable to refer to the function cal led
addT w oInts.”
The addT w oInts function has the same type as the mathFuncti on variable, and so thi s
assignment i s al lowed by Swi ft’s type-checker.
You can now cal l the assigned function wi th the name mathFuncti on:
pri ntl n("Resul t: \(mathFuncti on(2, 3))")
// pri nts "Resul t: 5"
A di fferent function wi th the same matching type can be assigned to the same variable, in
the same way as for non-function types:
mathFuncti on = mul ti pl yT w oInts
pri ntl n("Resul t: \(mathFuncti on(2, 3))")
// pri nts "Resul t: 6"
As wi th any other type, you can leave i t to Swi ft to infer the function type when you
assign a function to a constant or variable:
l et anotherMathFuncti on = addT w oInts
// anotherMathFuncti on i s i nferred to be of type (Int, Int) -> Int
## Function Types as Parameter Types
You can use a function type such as (Int, Int) -> Int as a parameter type for another
function. Thi s enables you to leave some aspects of a function’s implementation for the
function’s cal ler to provide when the function i s cal led.
Here’s an example to print the resul ts of the math functions from above:
func pri ntMathResul t(mathFuncti on: (Int, Int) -> Int, a: Int, b: Int) {
pri ntl n("Resul t: \(mathFuncti on(a, b))")
}
pri ntMathResul t(addT w oInts, 3, 5)
// pri nts "Resul t: 8"
Thi s example defines a function cal led pri ntMathResul t, whi ch has three parameters. The fi rst
parameter i s cal led mathFuncti on, and i s of type (Int, Int) -> Int. You can pass any function of
that type as the argument for thi s fi rst parameter. The second and thi rd parameters are
cal led a and b, and are both of type Int. These are used as the two input values for the
provided math function.
When pri ntMathResul t i s cal led, i t i s passed the addT w oInts function, and the integer values 3
and 5. It cal l s the provided function wi th the values 3 and 5, and prints the resul t of 8.
The role of pri ntMathResul t i s to print the resul t of a cal l to a math function of an appropriate
type. It doesn’t matter what that function’s implementation actual ly does—i t matters only
that the function i s of the correct type. Thi s enables pri ntMathResul t to hand off some of i ts
functional i ty to the cal ler of the function in a type-safe way.
## Function Types as Return Types
You can use a function type as the return type of another function. You do thi s by wri ting
a complete function type immediately after the return arrow (->) of the returning function.
The next example defines two simple functions cal led stepForw ard and stepBackw ard. The
stepForw ard function returns a value one more than i ts input value, and the stepBackw ard
function returns a value one less than i ts input value. Both functions have a type of (Int) ->
Int:
func stepForw ard(i nput: Int) -> Int {
return i nput + 1
}
func stepBackw ard(i nput: Int) -> Int {
return i nput - 1
}
Here’s a function cal led chooseStepFuncti on, whose return type i s “a function of type (Int) -> Int”.
chooseStepFuncti on returns the stepForw ard function or the stepBackw ard function based on a
Boolean parameter cal led backw ards:
func chooseStepFuncti on(backw ards: Bool ) -> (Int) -> Int {
return backw ards ? stepBackw ard : stepForw ard
}
You can now use chooseStepFuncti on to obtain a function that wi l l step in one di rection or the
other:
var currentVal ue = 3
l et moveNearerT oZero = chooseStepFuncti on(currentVal ue > 0)
// moveNearerT oZero now refers to the stepBackw ard() functi on
The preceding example works out whether a posi tive or negative step i s needed to move
a variable cal led currentVal ue progressively closer to zero. currentVal ue has an ini tial value of 3,
whi ch means that currentVal ue > 0 returns true, causing chooseStepFuncti on to return the
stepBackw ard function. A reference to the returned function i s stored in a constant cal led
moveNearerT oZero.
Now that moveNearerT oZero refers to the correct function, i t can be used to count to zero:
pri ntl n("Counti ng to zero:")
// Counti ng to zero:
w hi l e currentVal ue ! = 0 {
pri ntl n("\(currentVal ue). . . ")
currentVal ue = moveNearerT oZero(currentVal ue)
}
pri ntl n("zero! ")
// 3. . .
// 2. . .
. .
ero!
## Nested Functions
Al l of the functions you have encountered so far in thi s chapter have been examples of
global functions, whi ch are defined at a global scope. You can al so define functions inside
the bodies of other functions, known as nested functions.
Nested functions are hidden from the outside world by defaul t, but can sti l l be cal led and
used by thei r enclosing function. An enclosing function can al so return one of i ts nested
functions to al low the nested function to be used in another scope.
You can rewri te the chooseStepFuncti on example above to use and return nested functions:
func chooseStepFuncti on(backw ards: Bool ) -> (Int) -> Int {
func stepForw ard(i nput: Int) -> Int { return i nput + 1 }
func stepBackw ard(i nput: Int) -> Int { return i nput - 1 }
return backw ards ? stepBackw ard : stepForw ard
}
var currentVal ue = -4
l et moveNearerT oZero = chooseStepFuncti on(currentVal ue > 0)
// moveNearerT oZero now refers to the nested stepForw ard() functi on
w hi l e currentVal ue ! = 0 {
ri ntl n("\(currentVal ue). . . ")
urrentVal ue = moveNearerT oZero(currentVal ue)
("zero! ")
. . .
. . .
. . .
. . .
ero!
# 가변 갯수(Variadic) 파라메터
가변 갯수 파라메터는 특정 타입의 값을 0개나 그 이상 받을 수 있습니다. 가변 갯수 파라메터를 사용함으로써 함수 호출시 입력 값들이 임의의 갯수가 될수 있다고 정할 수 있습니다. 파라메터의 타입 이름의 뒤에 마침표 세개(`...`)를 삽입하는 것으로 가변 갯수 파라메터를 작성할 수 있습니다.
가변 갯수 파라메터로 함수의 내부에 전달된 값들은 적절한 타입의 배열(`array`)로 만들어진다. 예를 들어 `numbers`라는 이름의 가변 갯수 파라메터의 타입이 `Double...`이라면 함수의 내부에서는 `Double[]`타입의 `numbers` 이름을 가진 배열로 만들어지는 것이다.
밑의 예제는 평균이라 불리는 산술 평균(arithmetic mean)을 임의의 갯수를 가진 숫자의 목록에서 구하는 것이다.
```
func arithmeticMean(numbers: Double...) -> Double {
var total : Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8, 19)
// returns 10.0, which is the arithmetic mean of these three numbers
```
> NOTE
함수는 최대 한개의 가변 갯수 파라메터를 가질 수 있다. 그리고 가변 갯수 파라메터는 언제나 파라메터 목록의 마지막에 배치되어야 한다. 이렇게 함으로써 복수의 파라메터를 가진 함수를 호출할때 생기는 모호함을 피할 수 있다.
만약 함수의 파라메터중 하나 이상의 파라메터가 기본값을 가지고, 그와 동시에 가변 갯수 파라메터를 가진다면 가변 갯수 파라메터는 기본 값을 가지는 파라메터의 맨 마지막에 두어라.

### 상수(Constant)와 가변(Variable) 파라메터
함수의 파라메터들은 기본적으로 상수들입니다. 함수의 내부에서 파라메터의 값을 바꾸려 시도하는 것은 컴파일 에러를 냅니다. 이렇게 함으로써 실수로 파라메터를 바뀌지 않게 합니다.
하지만 때로는 함수가 파라메터의 값을 다양하게 복사하여 사용하는 것이 유용할때가 있습니다. 새로운 변수(variable)를 정의하지 않고 대신 가변 파라메터를 하나 이상 지정하여 함수 내부에서 사용할 수 있다. 가변 파라메터는 상수보다 병수처럼 사용 가능하며, 함수가 이용하는 파라메터의 변경 가능한 값의 새로운 사본을 제공한다.
가변 파라메터를 정의하려면 파라메터의 이름 앞에 `var` 키워드를 접두어로 사용한다
```
func alignRight(var string: String, count: Int, pad: Character) -> String {
let amountToPad = count - countElements(string)
for _ in 1...amountToPad {
string = pad + string
}
return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, 10, "-")
// paddedString is equal to "-----hello"
// originalString is still equal to "hello"
```
이 예제는 `alignRight`라는 함수를 새로 정의하고 있다. 이 함수는 입력 문자열을 오른쪽 가장자리로 정렬된 더 긴 출력 문자열을 만든다. 문자열의 왼쪽에 생긴 공간에는 정해진 채움 문자로 채워진다. 이 예제에서는 "hello"라는 문자열이 "-----hello"로 변환되었다.
`alignRight`함수는 입력 파라메터 `string`을 가변 파라메터로 정의하고 있다. 이것은 `string`이 지역 변수(variable)로서 사용될 수 있고, 전해받은 문자열 값으로 초기화 되며, 함수 내부에서 변경될 수 있음을 뜻한다.
이 함수는 우측 정렬된 전체 문자열 안에 얼마나 많은 채움 문자가 `string`의 왼쪽에 들어가야 할지 계산하는 것으로 시작한다. 이 값은 지역 상수인 `amountToPad`에 저장된다. 그리고 함수는 `amountToPad`만큼 `pad`문자를 존재하던 문자열의 왼쪽에 붙여넣고 그 값을 반환한다. 이러한 문자열 변경 과정에서 `string` 가변 파라메터가 사용된다.

>NOTE
가변 파라메터에 생긴 변화는 각각의 함수 호출이 끝난 뒤에는 남아있지 않는다. 또한 함수의 외부에서는 보이지(visible)않는다. 가변 파라메터는 함수 호출이 되는 동안만 유지된다.

###In-Out 파라메터
위에 설명된것과 같이 가변 파라메터는 오직 함수 자신의 내부에서만 변경 될 수 있다. 만약 함수가 파라메터의 값을 변경하고 그 변경이 함수 호출이 종료된 후에도 계속되길 원한다면, 파라메터를 _in-out_ 파라메터로 정의하면 된다.
_in-out_파라메터를 정의하기 위해서는 `inout` 키워드를 파라메터 정의의 시작점에 작성하면 된다. in-out 파라메터의 값은 함수의 _안으로_ 전달 되어, 함수에 의해 변경되고, 함수에서 다시 _나와서_ 원래의 값을 대체한다.
in-out 파라메터로 넘길 수 있는 값은 인수(argument)뿐이다. 상수나 문자 값은 in-out 파라메터로 넘겨질 수 없다. 상수나 문자값은 변경될 수 없기 때문이다. 인수를 in-out 파라메터로 넘길때 변수의 이름 바로 앞에 앰퍼샌드(`&`)를 붙여서 이 파라메터가 함수에 의해 변경될 수 있음을 표시한다.

>NOTE
In-out 파라메터는 기본값을 가질 수 없다. 또한 가변 갯수 파라메터도 `inout`으로 지정할 수 없으며 `var`나 `let`으로 표시될 수도 없다.

여기에 `swapTwoInts`라는 함수 예제가 있다. 이 함수는 두개의 in-out 정수(integer) 파라메터인 `a`와 `b`를 가지고 있다.
```
func swapTwoInts(inout a: Int, inout b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
```
`swapTwoInts` 함수는 단순히 두 값을 교환하여 `b`를 `a`의 값으로 하고, `a`를 `b`의 값으로 한다. 이 함수는 `a`의 값을 임시 상수인 `temporaryA`에 저장하고, `b`의 값을 `a`로 할당한다. 그리고 `temporaryA`의 값을 `b`로 할당한다.
`swapTwoInts` 함수는 두 `Int` 타입의 변수를 가지고 서로의 값을 교환하는 함수라고 할 수 있다. 주의할것은 `someInt`와 `anotherInt`는 앰퍼샌드 접두어가 쓰여서 함수에 전달되었다는 것이다.
```
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"
```
위의 예제는 `someInt`와 `anotherInt`가 함수 외부에서 정의되었음에도, 그 값이 `swapTwoInts` 함수에 의해 변경 되었음을 보여주고 있다.

>NOTE
In-out 파라메터는 함수가 값을 반환하는 것과 같지 않다. 위의 `swapTwoInts` 예제는 반환 타입이나 반환값을 정의하고 있지 않다. 하지만 `someInt`와 `anotherInt`의 값을 변경한다. In-out 파라메터는 함수가 함수 밖의 범위(scope)에 영향을 끼칠 수 있는 또다른 방법이다.

##함수 타입
모든 함수들은 특유의 함수 타입을 가지고 있다. 함수 타입은 함수의 파라메터 타입들과 반환 타입으로 구성된다.
예를 들자면 이렇다:
```
func addTwoInts(a: Int, b: Int) -> Int {
return a + b
}
func multiplyTwoInts(a: Int, b: Int) -> Int {
return a * b
}
```
이 예제는 `addTwoInts`와 `multiplyTwoInts`, 두개의 단순한 수학 함수를 정의한다. 함수들은 각각 두개의 `Int`값을 취하고 `Int`값을 계산의 적절한 결과로서 반환한다.
위 두 함수의 타입은 `(Int, Int) -> Int`다. 이것은 "함수 타입은 `Int`타입의 파라메터가 두개며 반환값의 타입은 `Int`다." 라고 말할 수 있다.
여기의 또다른 예제는 파라메터나 반환값이 없는 함수다.
```
func printHelloWorld() {
println("hello, world")
}
```
이 함수의 타입은 `()->()`이며, "함수는 파라메터가 없고 `Void`를 반환한다."고 할 수 있다. 반환값을 정해지지 않은 함수는 언제나 `Void`를 반환하며, 이는 빈 튜플인 `()`로 표시될 수 있다.

###함수 타입을 사용하기
스위프트의 다른 타입들처럼 함수 타입 역시 사용될 수 있다. 예를들어 함수 타입의 상수나 변수를 만들어서 적절한 함수를 할당할 수 있다.
```
var mathFunction: (Int, Int) -> Int = addTwoInts
```
위 코드는 "두개의 `Int` 값을 취하며 `Int`값을 반환하는 함수 타입 `mathFuntion`을 정의한다. 이 새로운 변수가 `addTwoInts` 함수를 참조(refer)하도록 한다."고 할 수 있다.
`addTwoInts` 함수는 `mathFunction`변수와 같은 타입이다. 따라서 스위프트의 타입 체커에 의해 할당이 허용된다.
이제 `mathFunction`을 이용해 할당된 함수를 호출할 수 있다.
```
println("Result: \(mathFunction(2, 3))")
// prints "Result: 5"
```
함수 타입이 아닌 변수가 그러하듯이, 일치하는 타입의 다른 함수 또한 같은 변수에 할당 될 수 있다.
```
mathFunction = multiplyTwoInts
println("Result: \(mathFunction(2, 3))")
// prints "Result: 6"
```
다른 타입과 마찬가지로, 함수를 상수나 변수에 할당할때 스위프트가 타입을 추론하게 내버려 둘 수 있다.
```
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int페
```
###파라메터 타입으로서의 함수 타입
`(Int, Int) -> Int`와 같은 함수 타입을 파라메터 타입으로 함수에 이용할 수 있다. 이로서 함수 구현의 일부를 함수가 호출 될때 함수를 호출하는 쪽에 맡기는 것이 가능하게 된다.
이 예제는 위에서 가져온 수학 함수의 결과를 출력한다.
```
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
println("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"
```
이 예제는 세개의 파라메터를 가지는 `printMathResult`함수를 정의한다. 첫번째 파라메터는 타입이 `(Int, Int) -> Int`인 `mathFunction`이다. 함수 타입이 맞는 함수라면 인수로서 첫번째 파라메터에 어느것이나 넘길 수 있다. 두번째와 세번째 파라메터는 `a`와 `b`이며 둘 다 `Int`타입이다. 이 둘은 제공된 수학 함수의 두 입력값으로 사용된다.
`printMathResult` 함수가 호출되면 `addTwoInts`함수와, 정수 값으로 `3`과 `5`를 넘긴다. 이 함수는 제공받은 함수를 호출할때 `3`과 `5`를 이용한다. 그리고 결과인 `8`을 출력한다.
`printMathResult`의 역할은 적절한 타입의 수학 함수의 실행 결과를 출력하는 것이다. 이 함수는 넘겨받는 함수의 구현이 실제로 무엇을 하는지 상관하지 않는다. 오직 함수가 정확하게 일치하는 타입인지만 본다. 이로서 `printMathResult`함수가 타입에 안전한 방식(type-safe way)으로 자신의 기능의 일부를 호출자에게 넘길 수 있게 한다.

###함수 타입과 반환 타입
함수 타입을 다른 함수의 반환 타입으로 사용할 수 있다. 이는 완전한 함수 타입을 반환할 함수 정의의 반환 화살표 (`->`)바로 뒤에 작성함으로서 할 수 있다.
다음 예제는 두개의 간단한 함수인 `stepForward`와 `stepBackward`를 정의하고 있다. `stepForward`함수는 입력값보다 1이 더 큰 값을 반환하고 `stepBackward`함수는 입력 값보다 1이 작은 값을 반환한다. 두 함수의 타입은 모두 `(Int) -> Int`다.
```
func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input - 1
}
```
여기 `chooseStepFunction` 함수가 있다. 이 함수의 반환 타입은 "`(Int) -> Int`를 반환하는 함수"다. `chooseStepFunction`은 `backwards` 불리언 파라메터에 따라 `stepForward`함수와 `stepBackward`함수중 하나를 반환한다.
```
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward : stepForward
}
```
`chooseStepFunction`를 이용하여 어느 한쪽 방향으로 나아가는(증가 또는 감소하는) 함수를 얻을 수 있다.
```
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
```
앞서 한 예제들은 `currentValue`변수에 따라 점진적으로 0이 되기 위해 필요한 증가나 감소 방향을 산출한다. `currentValue > 0`은 `true`를 반환하여, `chooseStepFunction`이 `stepBackward`함수를 반환하게 한다. 반환된 함수에 대한 참조(reference)는 `moveNearerToZero` 상수에 저장된다.
Now that moveNearerToZero refers to the correct function, it can be used to count to zero:
이제 `moveNearerToZero`가 올바른 함수를 참조하기에, 이를 0까지 세는데 이용할 수 있다.
```
println("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
println("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// 3...
// 2...
// 1...
// zero!
```
##중첩된 함수들
여기까지 이 챕터에서 마주친 모든 함수들은 모두 전역 범위(global scope)에 정의된 _전역 함수_의 예제였다. 또한 _중첩된 함수_라 불리는, 함수 내부에 다른 함수를 정의할 수 있다.
중첩 함수는 범위 밖의 세계에서 기본적으로 숨겨져 있다. 하지만 감싸고 있는 함수에 의해 여전히 이용될 수 있다. 감싸고 있는 함수는 중첩된 함수들을 반환하여 다른 범위에서 함수가 사용될 수 있게 할 수 있다.
위 예제의 `chooseStepFunction`을 다음과 같이 중첩된 함수를 이용하여 재작성 할 수 있다.
```
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
println("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
```

chapter9
# 09 클로저 (Closures)
> Translator : 이름 (메일주소)

Closures
Closures are sel f-contained blocks of functional i ty that can be passed around and used in
your code. Closures in Swi ft are simi lar to blocks in C and Objective-C and to lambdas in
other programming languages.
Closures can capture and store references to any constants and variables from the
context in whi ch they are defined. Thi s i s known as closing over those constants and
variables, hence the name “closures”. Swi ft handles al l of the memory management of
capturing for you.
N O T E
Don’t w orry i f you are not fami l i ar w i th the concept of “capturi ng”. It i s expl ai ned i n detai l bel ow i n Capturi ng
Val ues.
Global and nested functions, as introduced in Functions, are actual ly special cases of
closures. Closures take one of three forms:
Swi ft’s closure expressions have a clean, clear style, wi th optimi zations that encourage
brief, clutter-free syntax in common scenarios. These optimi zations include:
Closure Expressions
Global functions are closures that have a name and do not capture any values.
Nested functions are closures that have a name and can capture values from thei r
enclosing function.
Closure expressions are unnamed closures wri tten in a l ightweight syntax that can
capture values from thei r surrounding context.
Inferring parameter and return value types from context
Impl i ci t returns from single-expression closures
Shorthand argument names
Trai l ing closure syntax
Nested functions, as introduced in Nested Functions, are a convenient means of naming
and defining sel f-contained blocks of code as part of a larger function. However, i t i s
sometimes useful to wri te shorter versions of function-l ike constructs wi thout a ful l
declaration and name. Thi s i s parti cularly true when you work wi th functions that take
other functions as one or more of thei r arguments.
Closure expressions are a way to wri te inl ine closures in a brief, focused syntax. Closure
expressions provide several syntax optimi zations for wri ting closures in thei r simplest
form wi thout loss of clari ty or intent. The closure expression examples below i l lustrate
these optimi zations by refining a single example of the sort function over several
i terations, each of whi ch expresses the same functional i ty in a more succinct way.
The Sort Function
Swi ft’s standard l ibrary provides a function cal led sort, whi ch sorts an array of values of a
known type, based on the output of a sorting closure that you provide. Once i t completes
the sorting process, the sort function returns a new array of the same type and si ze as the
old one, wi th i ts elements in the correct sorted order.
The closure expression examples below use the sort function to sort an array of Stri ng
values in reverse alphabeti cal order. Here’s the ini tial array to be sorted:
l et names = ["Chri s", "Al ex", "Ew a", "Barry", "Dani el l a"]
The sort function takes two arguments:
Thi s example i s sorting an array of Stri ng values, and so the sorting closure needs to be a
function of type (Stri ng, Stri ng) -> Bool .
One way to provide the sorting closure i s to wri te a normal function of the correct type,
and to pass i t in as the sort function’s second parameter:
func backw ards(s1: Stri ng, s2: Stri ng) -> Bool {
return s1 > s2
}
An array of values of a known type.
A closure that takes two arguments of the same type as the array’s contents, and
returns a Bool value to say whether the fi rst value should appear before or after the
second value once the values are sorted. The sorting closure needs to return true i f
the fi rst value should appear before the second value, and fal se otherwi se.
var reversed = sort(names, backw ards)
// reversed i s equal to ["Ew a", "Dani el l a", "Chri s", "Barry", "Al ex"]
If the fi rst string (s1) i s greater than the second string (s2), the backw ards function wi l l return
true, indi cating that s1 should appear before s2 in the sorted array. For characters in
strings, “greater than” means “appears later in the alphabet than”. Thi s means that the
letter "B" i s “greater than” the letter "A", and the string "T om" i s greater than the string
"T i m". Thi s gives a reverse alphabeti cal sort, wi th "Barry" being placed before "Al ex", and so
on.
However, thi s i s a rather long-winded way to wri te what i s essential ly a single-expression
function (a > b). In thi s example, i t would be preferable to wri te the sorting closure inl ine,
using closure expression syntax.
Closure Expression Syntax
Closure expression syntax has the fol lowing general form:
{ ( parameters ) -> return type i n
statements
}
Closure expression syntax can use constant parameters, variable parameters, and i nout
parameters. Defaul t values cannot be provided. Variadi c parameters can be used i f you
name the variadi c parameter and place i t last in the parameter l i st. Tuples can al so be
used as parameter types and return types.
The example below shows a closure expression version of the backw ards function from
earl ier:
reversed = sort(names, { (s1: Stri ng, s2: Stri ng) -> Bool i n
return s1 > s2
})
Note that the declaration of parameters and return type for thi s inl ine closure i s identi cal
to the declaration from the backw ards function. In both cases, i t i s wri tten as (s1: Stri ng, s2:
Stri ng) -> Bool . However, for the inl ine closure expression, the parameters and return type
are wri tten inside the curly braces, not outside of them.
The start of the closure’s body i s introduced by the i n keyword. Thi s keyword indi cates
that the defini tion of the closure’s parameters and return type has fini shed, and the body
of the closure i s about to begin.
Because the body of the closure i s so short, i t can even be wri tten on a single l ine:
reversed = sort(names, { (s1: Stri ng, s2: Stri ng) -> Bool i n return s1 > s2 } )
Thi s i l lustrates that the overal l cal l to the sort function has remained the same. A pai r of
parentheses sti l l wrap the enti re set of arguments for the function. However, one of those
arguments i s now an inl ine closure.
Inferring Type From Context
Because the sorting closure i s passed as an argument to a function, Swi ft can infer the
types of i ts parameters and the type of the value i t returns from the type of the sort
function’s second parameter. Thi s parameter i s expecting a function of type (Stri ng, Stri ng) ->
Bool . Thi s means that the Stri ng, Stri ng, and Bool types do not need to be wri tten as part of the
closure expression’s defini tion. Because al l of the types can be inferred, the return arrow
(->) and the parentheses around the names of the parameters can al so be omi tted:
reversed = sort(names, { s1, s2 i n return s1 > s2 } )
It i s always possible to infer parameter types and return type when passing a closure to a
function as an inl ine closure expression. As a resul t, you rarely need to wri te an inl ine
closure in i ts ful lest form.
Nonetheless, you can make the types expl i ci t i f you wi sh, and doing so i s encouraged i f i t
avoids ambigui ty for readers of your code. In the case of the sort function, the purpose of
the closure i s clear from the fact that sorting i s taking place, and i t i s safe for a reader to
assume that the closure i s l ikely to be working wi th Stri ng values, because i t i s assi sting
wi th the sorting of an array of strings.
Implicit Returns from Single-Expression Closures
Single-expression closures can impl i ci tly return the resul t of thei r single expression by
omi tting the return keyword from thei r declaration, as in thi s version of the previous
example:
reversed = sort(names, { s1, s2 i n s1 > s2 } )
Here, the function type of the sort function’s second argument makes i t clear that a Bool
value must be returned by the closure. Because the closure’s body contains a single
expression (s1 > s2) that returns a Bool value, there i s no ambigui ty, and the return keyword
can be omi tted.
Shorthand Argument Names
Swi ft automati cal ly provides shorthand argument names to inl ine closures, whi ch can be
used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.
If you use these shorthand argument names wi thin your closure expression, you can omi t
the closure’s argument l i st from i ts defini tion, and the number and type of the shorthand
argument names wi l l be inferred from the expected function type. The i n keyword can al so
be omi tted, because the closure expression i s made up enti rely of i ts body:
reversed = sort(names, { $0 > $1 } )
Here, $0 and $1 refer to the closure’s fi rst and second Stri ng arguments.
Operator Functions
There’s actual ly an even shorter way to wri te the closure expression above. Swi ft’s Stri ng
type defines i ts string-speci fi c implementation of the greater-than operator (>) as a
function that has two parameters of type Stri ng, and returns a value of type Bool . Thi s
exactly matches the function type needed for the sort function’s second parameter.
Therefore, you can simply pass in the greater-than operator, and Swi ft wi l l infer that you
want to use i ts string-speci fi c implementation:
reversed = sort(names, >)
For more about operator functions, see Operator Functions.
Trailing Closures
If you need to pass a closure expression to a function as the function’s final argument and
the closure expression i s long, i t can be useful to wri te i t as a trai l ing closure instead. A
trai l ing closure i s a closure expression that i s wri tten outside of (and after) the
parentheses of the function cal l i t supports:
func someFuncti onT hatT akesACl osure(cl osure: () -> ()) {
// functi on body goes here
}
// here's how you cal l thi s functi on w i thout usi ng a trai l i ng cl osure:
someFuncti onT hatT akesACl osure({
// cl osure's body goes here
})
ere's how you cal l thi s functi on w i th a trai l i ng cl osure i nstead:
eFuncti onT hatT akesACl osure() {
/ trai l i ng cl osure's body goes here
N O T E
If a cl osure expressi on i s provi ded as the functi on’s onl y argument and you provi de that expressi on as a
trai l i ng cl osure, you do not need to w ri te a pai r of parentheses () after the functi on’s name w hen you cal l the
functi on.
The string-sorting closure from the Closure Expression Syntax section above can be
wri tten outside of the sort function’s parentheses as a trai l ing closure:
reversed = sort(names) { $0 > $1 }
Trai l ing closures are most useful when the closure i s suffi ciently long that i t i s not
possible to wri te i t inl ine on a single l ine. As an example, Swi ft’s Array type has a map
method whi ch takes a closure expression as i ts single argument. The closure i s cal led
once for each i tem in the array, and returns an al ternative mapped value (possibly of
some other type) for that i tem. The nature of the mapping and the type of the returned
value i s left up to the closure to speci fy.
After applying the provided closure to each array element, the map method returns a new
array containing al l of the new mapped values, in the same order as thei r corresponding
values in the original array.
Here’s how you can use the map method wi th a trai l ing closure to convert an array of Int
values into an array of Stri ng values. The array [16, 58, 510] i s used to create the new array
["OneSi x", "Fi veEi ght", "Fi veOneZero"]:
l et di gi tNames = [
0: "Zero", 1: "One", 2: "T w o", 3: "T hree", 4: "Four",
5: "Fi ve", 6: "Si x", 7: "Seven", 8: "Ei ght", 9: "Ni ne"
]
l et numbers = [16, 58, 510]
The code above creates a di ctionary of mappings between the integer digi ts and Engl i shlanguage versions of thei r names. It al so defines an array of integers, ready to be
converted into strings.
You can now use the numbers array to create an array of Stri ng values, by passing a closure
expression to the array’s map method as a trai l ing closure. Note that the cal l to numbers.map
does not need to include any parentheses after map, because the map method has only
one parameter, and that parameter i s provided as a trai l ing closure:
l et stri ngs = numbers.map {
(var number) -> Stri ng i n
var output = ""
w hi l e number > 0 {
output = di gi tNames[number % 10]! + output
number /= 10
}
return output
}
ri ngs i s i nferred to be of type Stri ng[]
val ue i s ["OneSi x", "Fi veEi ght", "Fi veOneZero"]
The map function cal l s the closure expression once for each i tem in the array. You do not
need to speci fy the type of the closure’s input parameter, number, because the type can be
inferred from the values in the array to be mapped.
In thi s example, the closure’s number parameter i s defined as a variable parameter, as
described in Constant and Variable Parameters, so that the parameter’s value can be
modi fied wi thin the closure body, rather than declaring a new local variable and assigning
the passed number value to i t. The closure expression al so speci fies a return type of Stri ng,
to indi cate the type that wi l l be stored in the mapped output array.
The closure expression bui lds a string cal led output each time i t i s cal led. It cal culates the
last digi t of number by using the remainder operator (number % 10), and uses thi s digi t to
look up an appropriate string in the di gi tNames di ctionary.
N O T E
T he cal l to the di gi tNames di cti onary’s subscri pt i s fol l ow ed by an excl amati on mark (! ), because di cti onary
subscri pts return an opti onal val ue to i ndi cate that the di cti onary l ookup can fai l i f the key does not exi st. In
the exampl e above, i t i s guaranteed that number % 10 w i l l al w ays be a val i d subscri pt key for the di gi tNames
di cti onary, and so an excl amati on mark i s used to force-unw rap the Stri ng val ue stored i n the subscri pt’s
opti onal return val ue.
The string retrieved from the di gi tNames di ctionary i s added to the front of output, effectively
bui lding a string version of the number in reverse. (The expression number % 10 gives a
value of 6 for 16, 8 for 58, and 0 for 510.)
The number variable i s then divided by 10. Because i t i s an integer, i t i s rounded down
during the divi sion, so 16 becomes 1, 58 becomes 5, and 510 becomes 51.
The process i s repeated unti l number /= 10 i s equal to 0, at whi ch point the output string i s
returned by the closure, and i s added to the output array by the map function.
The use of trai l ing closure syntax in the example above neatly encapsulates the closure’s
functional i ty immediately after the function that closure supports, wi thout needing to
wrap the enti re closure wi thin the map function’s outer parentheses.
Capturing Values
A closure can capture constants and variables from the surrounding context in whi ch i t i s
defined. The closure can then refer to and modi fy the values of those constants and
variables from wi thin i ts body, even i f the original scope that defined the constants and
variables no longer exi sts.
The simplest form of a closure in Swi ft i s a nested function, wri tten wi thin the body of
another function. A nested function can capture any of i ts outer function’s arguments and
can al so capture any constants and variables defined wi thin the outer function.
Here’s an example of a function cal led makeIncrementor, whi ch contains a nested function
cal led i ncrementor. The nested i ncrementor function captures two values, runni ngT otal and amount,
from i ts surrounding context. After capturing these values, i ncrementor i s returned by
makeIncrementor as a closure that increments runni ngT otal by amount each time i t i s cal led.
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runni ngT otal = 0
func i ncrementor() -> Int {
runni ngT otal += amount
return runni ngT otal
}
return i ncrementor
}
The return type of makeIncrementor i s () -> Int. Thi s means that i t returns a function, rather
than a simple value. The function i t returns has no parameters, and returns an Int value
each time i t i s cal led. To learn how functions can return other functions, see Function
Types as Return Types.
The makeIncrementor function defines an integer variable cal led runni ngT otal , to store the
current running total of the incrementor that wi l l be returned. Thi s variable i s ini tial i zed
wi th a value of 0.
The makeIncrementor function has a single Int parameter wi th an external name of forIncrement,
and a local name of amount. The argument value passed to thi s parameter speci fies how
much runni ngT otal should be incremented by each time the returned incrementor function i s
cal led.
makeIncrementor defines a nested function cal led i ncrementor, whi ch performs the actual
incrementing. Thi s function simply adds amount to runni ngT otal , and returns the resul t.
When considered in i solation, the nested i ncrementor function might seem unusual :
func i ncrementor() -> Int {
runni ngT otal += amount
return runni ngT otal
}
The i ncrementor function doesn’t have any parameters, and yet i t refers to runni ngT otal and
amount from wi thin i ts function body. It does thi s by capturing the exi sting values of
runni ngT otal and amount from i ts surrounding function and using them wi thin i ts own function
body.
Because i t does not modi fy amount, i ncrementor actual ly captures and stores a copy of the
value stored in amount. Thi s value i s stored along wi th the new i ncrementor function.
However, because i t modi fies the runni ngT otal variable each time i t i s cal led, i ncrementor
captures a reference to the current runni ngT otal variable, and not just a copy of i ts ini tial
value. Capturing a reference ensures sure that runni ngT otal does not di sappear when the cal l
to makeIncrementor ends, and ensures that runni ngT otal wi l l continue to be avai lable the next
time that the incrementor function i s cal led.
N O T E
Sw i ft determi nes w hat shoul d be captured by reference and w hat shoul d be copi ed by val ue. Y ou don’t need
to annotate amount or runni ngT otal to say that they can be used w i thi n the nested i ncrementor functi on.
Sw i ft al so handl es al l memory management i nvol ved i n di sposi ng of runni ngT otal w hen i t i s no l onger needed
by the i ncrementor functi on.
Here’s an example of makeIncrementor in action:
l et i ncrementByT en = makeIncrementor(forIncrement: 10)
Thi s example sets a constant cal led i ncrementByT en to refer to an incrementor function that
adds 10 to i ts runni ngT otal variable each time i t i s cal led. Cal l ing the function mul tiple times
shows thi s behavior in action:
i ncrementByT en()
// returns a val ue of 10
i ncrementByT en()
// returns a val ue of 20
i ncrementByT en()
// returns a val ue of 30
If you create another incrementor, i t wi l l have i ts own stored reference to a new,
separate runni ngT otal variable. In the example below, i ncrementBySeven captures a reference to
a new runni ngT otal variable, and thi s variable i s unconnected to the one captured by
i ncrementByT en:
l et i ncrementBySeven = makeIncrementor(forIncrement: 7)
i ncrementBySeven()
// returns a val ue of 7
i ncrementByT en()
// returns a val ue of 40
N O T E
If you assi gn a cl osure to a property of a cl ass i nstance, and the cl osure captures that i nstance by referri ng to
the i nstance or i ts members, you w i l l create a strong reference cycl e betw een the cl osure and the i nstance.
Sw i ft uses capture l i sts to break these strong reference cycl es. For more i nformati on, see Strong Reference
Cycl es for Cl osulosures Are Reference Types
In the example above, i ncrementBySeven and i ncrementByT en are constants, but the closures
these constants refer to are sti l l able to increment the runni ngT otal variables that they have
captured. Thi s i s because functions and closures are reference types.
Whenever you assign a function or a closure to a constant or a variable, you are actual ly
setting that constant or variable to be a reference to the function or closure. In the
example above, i t i s the choi ce of closure that i ncrementByT en refers to that i s constant, and
not the contents of the closure i tsel f.
Thi s al so means that i f you assign a closure to two di fferent constants or variables, both
of those constants or variables wi l l refer to the same closure:
l et al soIncrementByT en = i ncrementByT en
al soIncrementByT en()
// returns a val ue of 50
inureyes (inureyes@gmail.com)

## 클로저 (Closures)
클로저는 사용자의 코드 안에서 전달되거나 사용할 수 있는 기능을 포함한 독립적인 블록(block)입니다. Swift에서의 클로저는 C 및 Objective-C 의 blocks와 유사하며, 다른 언어의 람다(lambda)와도 유사합니다.
클로저는 자신이 정의된 컨텍스트 (context) 로부터 임의의 상수 및 변수의 참조(reference) 를 획득 (capture)하고 저장할 수 있습니다. _(주: 클로저의 경우 클로저 바로 밖의 scope 의 상수 및 변수에 접근할 수 있다는 이야기입니다)_ 이렇게 상수 및 변수를 제약하는 특징때문에 클로저라는 이름이 되었습니다. Swift는 획득 과정의 메모리 관리를 모두 제어해줍니다.

> **노트**
> "획득" 개념에 대해서 익숙하지 않아도 걱정하지 마세요. 아래의 [값 획득하기]() 항목에서 자세히 다룰 것입니다.

함수 에서 소개된 전역 및 중첩 함수들은 사실 클로저의 특수한 경우들입니다. 클로저는 아래의 세가지 중 하나의 형태입니다.

- 전역 함수는 이름이 있지만 아무 값도 획득하지 않는 클로저입니다.
- 중첩 함수들은 이름이 있고, 내부의 함수의 값을 획득할 수 있는 클로저입니다.
- 클로저 표현식은 자신을 둘러싼 컨텍스트에서 값을 획득할 수 있는 가벼운 문법으로 작성된 클로저입니다.

Swift의 클로저 표현식은 깨끗하고 명확한 스타일을 일반적인 경우에 대한 간략하고 명확한 구문을 최적화와 함께 제공합니다. 이러한 최적화는 아래의 항목을 포함합니다.

- 컨텍스트로부터 인자 및 반환 값을 유추
- 단일 표현식 클로저로부터 명확한 반환값
- 단축 인자 이름
- 클로저 문법 추적

## 클로저 표현식 (Closure expressions)
중첩 함수에서 소개된 중첩 함수들은 더 큰 함수의 일부로서 동작하는 자체 포함된 코드 블럭을 명명하거나 정의하는 편리한 방법입니다. 그러나, 종종 완전한 선언이나 이름이 없는 더 짧은 버전의 함수같은 구조를 만드는 것이 유용할 때가 있습니다. 이는 당신이 다른 함수들을 하나 또는 그 이상의 인자로 받는 함수를 만들때 특히 그렇습니다.

클로저 표현식들은 인라인 클로저를 간단명료하고 집중적인 문법으로 작성하는 방법입니다. 클로저 표현식은 명확성과 의도를 잃지 않는 선에서 가장 간결한 형태로 클로저를 작성하기 위한 몇가지 문법 최적화를 제공합니다. 아래의 클로저 표현식 예에서 sort 함수를 각 단계마다 동일한 기능을 표현하지만 더 간결해지도록 몇가지 단계를 거쳐 개량하는 최적화를 소개합니다.

## 정렬 함수
Swift 의 표준 라이브러리는 당신에 제공한 정렬 클로저(sorting closure)의 결과값에 기반하여 알려진 값들의 배열을 정렬하는 sort 라는 함수를 제공합니다. 정렬 과정이 끝나면, sort 함수는 원래와 동일한 타입(type) 및 크기를 갖지만 그 요소들은 올바르게 정렬된 새로운 배열을 반환합니다.

아래의 클로저 표현식 예는 string 값으로 구성된 배열을 알파벳 역순으로 정렬합니다.

이 배열이 정렬될 배열입니다:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

`sort` 함수는 두 매개변수를 받습니다.

- 알려진 타입(type)의 값들로 된 배열
- 동일한 타입의 두 인자를 받아 첫번째 값이 두번째 값보다 앞에 나와야 할 지의 여부를 알려주는 `Bool` 값을 돌려주는 클로저. 정렬 클로저는 만약 첫 값이 두번째 값보다 앞에 나와야 할 경우 `true`를, 나머지 경우에는 `false`를 반환합니다.

이 예제는 String 값들의 배열을 정렬하므로, 정렬 클로저는 타입 `(String, String) -> Bool` 타입의 함수가 되어야 합니다.

정렬 클로저를 제공하는 한가지 방법은 정확한 타입과 함께 일반적인 함수를 작성하고, 이 함수를 `sort` 함수의 두번째 인자로 사용하는 방법입니다.

func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sort(names, backwards)
// reversed i s equal to ["Ewa", "Daniell a", "Chris", "Barry", "Alex"]

첫 번째 문자열 (S1)이 두 번째 문자열 (S2)보다 큰 경우, `backwards` 함수는 정렬된 배열에서 `s1`이 `s2`보다 먼저 나와야 함을 의미하는 `true` 를 반환합니다. `string` 안의 `character`들의 경우, "더 크다"는 의미는 "알파벳에서 나중에 등장하는" 것을 의미합니다. 이는 글자 "B"가 글자 "A"보다 "더 크다"는 의미이며, 문자열 "Tom" 이 문자열 "Tim" 보다 크다는 의미입니다. 따라서 이 함수는 "Barry"가 "Alex"보다 앞에 오게 되는 알파벳 역순 정렬 결과를 주게 됩니다.

그러나, 이것은 본질적으로 하나의 표현 함수 `(a > b)` 인 기능을 작성하기엔 다소 장황한 방법입니다. 이 예제의 경우 클로저 표현식 문법을 사용하여 인라인 정렬 클로저를 작성하는 것이 더 바람직할 것입니다.

## 클로저 표현식 문법 (Closure Expression Syntax)
클로저 표현식 문법은 아래의 일반 형식을 따릅니다:

{ ( parameters ) -> return type in
statements
}

클로저 표현식 문법은 상수 인자, 변수 인자 및 `inout` 인자를 사용할 수 있습니다. 기본 값은 주어지지 않습니다. 만약 당신이 가변 인자에 이름을 주고 마지막 매개 변수에 위치할 경우 가변 인자도 사용할 수 있습니다. 튜플 또한 인자 타입 및 반환 타입으로 사용할 수 있습니다.

아래의 예는 앞에서 소개한 `backwards` 함수의 클로저 표현 판입니다.

reversed = sort(names, { (s1: String, s2: String) -
> Bool in
return s1 > s2
})

이 인라인 클로저에 대한 인자의 및 리턴 타입의 정의는 `backwards` 함수의 정의와 동일합니다. 두 경우 모두, `(s1: String, s2: String) -> Bool` 로 쓸 수 있습니다. 그러나, 인라인 클로저 표현식의 경우, 인자와 리턴 타입은 중괄호 안에 쓰여야 하며, 밖에 쓰일 수는 없습니다.

클로저의 내용은 `in` 키워드로 시작합니다. 이 키워드는 클로저의 인자 및 반환 타입 정의가 끝났으며, 클로저의 내용이 시작됨을 지시합니다.

클로저의 내용이 매우 짧기 때문에, 심지어 한 줄에도 쓸 수 있습니다.

reversed = sort(names, { (s1: String, s2: String) - > Bool in return s1 > s2 } )

이 구문은 `sort` 함수의 전체적인 호출이 똑같이 유지됨을 보여줍니다. 괄호쌍은 여전히 함수의 전체 인자를 감싸고 있습니다. 그러나 그 중 하나의 인자는 이제 인라인 클로저입니다.

## 컨텍스트로부터 타입 유추하기 (Inferring Type From Context)

정렬 클로저가 함수의 인자로 전달되기 때문에, Swift는 클로저의 인자 타입과 `sort` 함수의 두번째 인자의 타입으로부터 반환되는 값의 타입을 유추할 수 있씁니다. 이 인자는 `(String, String) -> Bool` 타입의 함수를 기대합니다. 이는 `String, String` 및 `Bool` 타입이 클로저 표현형의 정의의 일부로 쓰일 필요가 없음을 의미합니다. 모든 타입이 유추 가능하기 때문에, 반환 화살표 (->) 와 인자 이름을 감싼 괄호 또한 제외할 수 있습니다.

reversed = sort(names, { s1, s2 in return s1 > s2 } )

인라인 클로저 표현 형태로 클로저를 함수에 전달할 경우 인자와 반환 값의 타입을 유추하는 것이 언제나 가능합니다. 결과적으로, 인라인 클로저를 최대한의 형태로 명시적으로 기술할 일은 거의 없을 것입니다.

그럼에도 불구하고, 당신이 필요로 하거나, 또한 코드를 읽는 사람들에게 모호함을 주고 싶지 않을 경우 타입을 명시적으로 기술할 수 있습니다. `sort` 함수의 경우, 클로저의 목적은 정렬이 일어난다는 사실로부터 명확하게 보이며, 독자들은 문자열들의 배열을 정렬하는 것을 돕기 떄문에 이 클로저가 `String` 값과 함꼐 돌아간다고 가정하는 것이 안전합니다.

## 단일 표현식 클로저로부터의 암시적 반환 ( Implicit Returns from Single-Expression Closures)

단일 표현식 클로저는 앞의 예에서 정의할 때 `return` 키워드를 생략하여 단일 표현식의 결과를 암시적으로 반환할 수 있습니다.

reversed = sort(names, { s1, s2 in s1 > s2 } )

sort 함수의 두번째 인자의 함수 형은 클로저가 `Bool` 값을 반드시 반환해야 함을 명확하게 해 줍니다. 클로저의 내용이 `Bool` 값을 반환하는 단일 표현식 `(s1 > s2)` 이기 때문에, 이 경우 애매모호함이 발생하지 않으며, `return` 키워드는 생략이 가능합니다.

## 단축 인자 이름들 ( Shorthand Argument Names)
Swift는 자동으로 단축 인자 이름을 인라인 클로저에 제공하며, 클로저의 인자들을 $0, $1, $2 등등의 방식으로 참조할 수 있습니다.

만약 이러한 단축 인자 이름들을 클로저 표현식에서 사용할 경우, 클로저 인자 리스트를 클로저의 정의에서 생략할 수 있으며, 단축 인자들의 번호 및 타입은 기대되는 함수 타입으로부터 추정될 것입니다. 클로저 표현식이 클로저 내용에 완전히 표현될 수 있으므로 `in` 키워드 또한 생략할 수 있습니다:

reversed = sort(names, { $0 > $1 } )

여기서 $0 와 $1 은 클로저의 첫번째와 두번째 `String` 매개변수를 가리킵니다.

## 연산자 함수들 ( Operator Functions )
사실 위의 클로저 표현식은 _더 짧아질 수도_ 있습니다. Swift 의 `String` 타입은 `String`에 특화된 크기 비교 연산자 (>) 를 두 `String` 인자를 갖는 함수로 정의하고 있으며, `Bool` 타입을 반환합니다. 이 연산자는 `sort` 함수의 두번째 인자를 위해 필요한 함수형과 정확히 칠치합니다. 그러므로, 이 크기 비교 연산자를 바로 전달하면 Swift 는 사용자가 `String` 전용의 구현체를 사용하려고 한다고 유추합니다.

reversed = sort(names, > )

연산자 함수에 대해 더 많은 내용은 [연산자 함수]() 항목을 참조하시기 바랍니다.

## 후행 클로저 ( Trailing Closures )

만약 클로저 표현식을 함수에 함수의 마지막 인자로 전달할 때 클로저 표현식이 긴 경우, 대신에 후행 클로저 (Trailing closure) 를 작성하는 것이 유용할 수 있습니다. 후행 클로저는 함수 호출 괄호의 밖 (또는 뒤) 에 쓰여져서 함수를 지원하는 클로저 표현식입니다.

func someFunctionThatTakesAClosure(closure: () -> ()) {
// function body goes here
}
// here's how you call this function without using a trailing closure:

someFunctionThatTakesAClosure({
// closure's body goes here
})

// here's how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}

> **노트**
> 클로저 표현식이 함수의 하나뿐인 인자이며 이 표현식을 후행 클로저로 작성할 경우, 함수를 호출할때 함수 이름의 뒤에 괄호쌍 () 을 쓸 필요는 없습니다.

위의 [클로저 표현식 문법]()의 문자열 정렬 클로저는 `sort` 함수의 괄호 밖에 후행 클로저로 작성될 수도 있습니다.

reversed = sort(names) { $0 > $1 }

후행 클로저는 클로저가 충분히 길어서 줄 안이나 한 줄 정도로 기술할 수 없는 경우에 아주 유용합니다. 예를 들어, Swift의 `Array` 타입은 클로저 표현식을 하나의 인자로 받는 `map` 메소드를 제공합니다. 클로저는 행렬 안의 각 아이템마다 한 번씩 호출되고, 그 아이템의 (다른 타입일 수도 있는) 새롭게 매핑된 값을 반환합니다. 매핑의 동작과 반환값의 타입은 클로저에 의하여 지정됩니다.

`map` 메소드는 제공된 클로저를 각 행렬 항목마다 적용한 후, 새롭게 매핑된 값들이 원래 행렬의 해당 값들의 순서와 같도록 배치된 새 행렬을 반환합니다.

`Int` 값들로 구성된 행렬을 `String` 값들로 구성된 행렬로 변환하는 map 메소드를 후행 클로저와 함께 사용하는 예를 보겠습니다. 행렬 `[16,58,510]` 이 새로운 행렬인 `["OneSix", "FiveEight", "FiveOneZero"]` 를 생성하기 위해 사용되었습니다.

let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

위의 코드는 정수와 그 수들의 영어 표현사이의 매핑 사전을 생성합니다. 또한 문자열로 변환될 정수 행렬도 정의합니다.

이제 `numbers` 행렬을 `map` 메소드에 후행 클로저를 클로저 표현식으로 전달하는 방법으로 `String` 값의 행렬을 생성하기 위해 사용할 수 있습니다. `map` 메소드가 단 하나의 인자만을 받으므로 `numbers.map` 을 호출할 때 `map` 뒤에 어떤 괄호도 필요하지 않음을 기억하세요. 후행 클로저가 이 인자로 제공됩니다.

let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]


`map` 함수는 클로저 표현식을 각 행렬의 항목마다 호출합니다. 클로저의 입력 인자, `number`, 의 타입을 지정할 필요는 없는데, 이는 타입을 매핑될 배열의 값으로부터 추측할 수 있기 때문입니다.

이 예제에서, 클로저의 `number` 인자는 [상수 및 변수 파라미터]() 에서 설명한 변수 인자 (variable parameter) 로 정의되었으므로, 인자의 값이 새로운 지역 변수를 정의하고 `number` 값을 그 변수에 할당하는 방법 대신 클로저 본문에서 변경될 수 있습니다. 또한 클로저 표현식은 매핑된 결과 배열의 타입을 지시하기 위해 `String` 의 반환 타입을 지정합니다.

클로저 표현 식은 호출될 때 마다 `output` 이라는 문자열을 생성합니다. `number` 의 마지막 숫자를 나머지 연산자 `(number % 10)` 를 사용하여 알아낸 후, 이 숫자에 해당되는 문자열을 `digitNames` 사전에서 찾습니다.

> **노트**
> `digitNames` 사전의 첨자 (subscript) (주: 적당한 표현이 없어서 의미적으로 가까운 '첨자'로 번역)에 접근할 때 느낌표 (!) 가 붙는데, 이 이유는 사전의 첨자 반환값은 사전 안에 해당되는 키값이 없어서 열람이 실패했을 경우 반환하는 선택적인 값이 있기 때문입니다. 위의 예에서, `number % 10` 은 `digitNames` 사전을 위해 언제나 유효한 첨자 키값을 제공하는 것이 보장되어 있으므로, 느낌표는 첨자의 선택적인 반환 값에 보관된 값을 강제로 풀어 `String` 값을 알기 위해 사용합니다.

`digitNames` 사전으로부터 가져온 문자열은 `output`의 앞부분에 추가되며, 숫자의 역순으로 해당되는 문자열이 효율적으로 만들어집니다. ( `number % 10` 표현식은 16의 경우 6, 58의 경우 8, 510일 경우 0을 돌려줍니다.)

`number` 변수는 이후 10으로 나눠집니다. 이 변수가 정수이기 때문에, 나누기 과정에서 소숫점 아랫 값이 버려집니다. 따라서 16은 1이, 58은 5가, 510은 51이 됩니다.

이 과정은 `number /=10` 이 0이 될 때까지 반복되며, 이때 `output` 문자열이 클로저로부터 반환되고, `map` 함수에 의하여 출력 행렬에 더해집니다.

이 예제에서 사용한 후행 클로저 구문은 전체 클로저를 `map` 함수의 외부 괄호로 전체 클로저를 감쌀 필요 없이, 클로저의 기능을 클로저가 지원하는 함수의 바로 뒤에서 깔끔하게 캡슐화합니다.

## 값 획득하기 (Capturing Values)
클로저는 자신이 정의된 주변 컨텍스트로부터 상수 및 변수의 값을 획득할 수 있습니다. 클로저는 이러한 상수와 변수들을 원래 상수와 변수들이 정의된 범위 (scope) 가 더이상 존재하지 않는 경우에조차도 값을 참조하거나 수정할 수 있습니다.

Swift에서 클로저의 가장 간단한 형태는 다른 함수의 본문 안에 작성된 중첩 함수입니다. 중첩 함수는 바깥 함수의 모든 인자를 획득할 수 있으며, 또한 바깥 함수 내에서 정의된 모든 상수 및 변수를 획득할 수 있습니다.

아래는 `Incrementor`라는 중첩 함수를 포함한 `makeIncrementor` 예입니다. 중첩된 `incrementor` 함수는 `runningTotal` 및 amount 의 두 값을 자신을 둘러싼 컨텍스트로부터 획득합니다. 이 두 값을 획득한 후, `incrementor`는 호출될 때 마다 `runningTotal` 을 `mount` 만큼 증가시키는 클로저로써 `makeIncrementor` 로부터 반환됩니다.

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}

`makeIncrementor` 의 반환 타입은 `() -> Int` 입니다. 이는 간단한 값 대신 함수를 반환함을 의미합니다. 반환되는 함수는 인자가 하나도 없으며, 호출될 때 마다 `Int` 값을 반환합니다. 어떻게 함수가 다른 함수를 반환할 수 있는가에 대해서는 [반환 타입으로서의 함수 타입]() 을 참조하시기 바랍니다.

`makeIncrementor` 함수는 runningTotal 정수 변수를 정의하며, 이 변수는 현재 실행중인 incrementor 의 총합을 보관하고 반환될 변수입니다. 이 변수는 0으로 초기화됩니다.

`makeIncrementor` 함수는 `Int` 인자를 외부 이름인 `forIncrement` 와 지역 이름인 `amount` 로 받습니다. 이 인자로 전달된 인수는 `runningTotal` 이 `incrementor` 함수가 호출될 때 마다 얼마만큼씩 증가해야 할 지 지정합니다.

`makeIncrementor` 는 `incrementor`라는 실제 증가를 수행하는 중첩 함수를 정의합니다. 이 함수는 간단하게 amount 를 runningTotal 에 더하고, 결과값을 반환합니다.

고립된 상황을 생각해보면, 중첩함수 `incrementor`는 독특하게 보입니다.

func incrementor() -> Int {
runningTotal += amount
return runningTotal
}

`incrementor` 함수는 아무 인자도 갖고 있지 않으며, `runningTotal` 및 `amount` 를 함수 내에서 참조합니다. 이 함수는 자신을 둘러싼 함수로부터 `runningTotal` 및 `amount`를 획득하고 함수 안에서 그 값들을 사용합니다.

이 함수는 `amount` 값을 수정하지 않기 때문에, `incrementor`는 `amount` 안에 보관된 값을 획득하고 그 복사판을 보관합니다. 이 값은 새로운 `incrementor` 함수에서도 계속 이어져 보관됩니다.

그러나, 이 함수가 `runningTotal` 변수를 호출시마다 변경하기 때문에, `incrementor`는 현재 `runningTotal`의 복사본 대신 값의 참조를 획득합니다. 참조 획득은 `runningTota`l 이 `makeIncrementor` 가 끝난 이후에도 사라지지 않음을 보증하며, `incrementor` 함수가 이후 호출될 때도 연속적으로 사용될 수 있음을 보증합니다.

> **노트**
> Swift는 어떤 변수가 참조 로 획득되고 어떤 변수가 복사값으로 획득될지 판단합니다. 사용자는 `amount` 및 `runningTotal` 이 `incrementor` 중첩 함수에서 쓰일지의 여부를 명기할 필요가 없습니다. Swift는 또한 `runningTotal` 이 더이상 `incrementor` 함수로부터 필요로하지 않을 때 폐기하는 모든 메모리 관리 과정을 담당합니다.

`makeIncrementor` 의 사용 예입니다.

let incrementByTen = makeIncrementor(forIncrement: 10)

이 예제는 호출될 때 마다 `runningTotal`에 10씩을 더하는 증가 함수를 참조하는 `incrementByTen` 을 정의합니다. 이 함수를 여러번 부르면 동작을 볼 수 있습니다.

incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

만약 새로운 `incrementor` 를 생성할 경우, 그 `incrementor`는 새롭고 독립적인 `runningTotal` 변수로의 참조를 갖게 됩니다. 아래의 예제에서, `incrementBySeven`은 새로운 `runningTotal` 변수의 참조를 획득하며, 이 변수는 `incrementByTen`에서 획득한 변수와 연결되지 않습니다.

let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// returns a value of 7
incrementByTen()
// returns a value of 40

> **노트**
> 만약 클로저를 클래스 인스턴스의 프로퍼티로 지정하고, 클로저가 인스턴스 또는 인스턴스의 멤버를 참조하여 인스턴스를 획득할 경우, 클로저와 인스턴스의 강력한 참조 순환을 만들게 됩니다. Swift는 이러한 강력한 참조 순환을 깨기 위하여 capture list 를 사용합니다. 더 많은 정보는 [클로저의 강력한 참조 순환]() 을 참조하시기 바랍니다.

## 클로저는 참조 타입 (Closures Are Reference Types)
위의 예에서, `incrementBySeven` 및 `incrementByTen`은 상수입니다. 그러나 클로저로써 이러한 상수들은 여전히 그들이 획득한 `runningTotal` 변수를 증가시킬 수 있습니다. 이는 함수와 클로저가 참조 타입이기 때문입니다.

함수나 클로저를 상수에 할당하는 것은, 실제로는 그 상수에 함수나 클로저를 가리키는 참조를 할당하는 것입니다. 위의 예에서, `incrementByTen`이 참조하는 것은 클로저를 가리키는 상수이며, 클로저 그 자체의 내용은 아닙니다.

이는 또한 클로저를 두 개의 다른 상수나 변수에 할당하면, 두 상수나 변수들이 동일한 클로저를 참조하게 되는 것을 의미합니다.

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50



images/chapter10-fig1
images/chapter10-fig2