Merge changes from master into sangwoo

sangwoo authored
revision 1a5dc90edb1026b660ea296f9ffddffcbc2cdf72
error-handling
# 4.7. 오류 처리 (Error Handling) - 04%

수많은 프로그래밍 언어들이 그렇듯, 러스트는 프로그래머가 오류를 처리할 수 있는 방법을 제공합니다. 일반적으로 말하길, 오류 처리는 크게 두가지 분류로 나뉜다고 일커집니다: 첫쩨, 예외와 변수 리턴. 둘째, 변수 리턴을 위한 러스트 OPT

이 쳅터에서는, 크고 강려크한 당신의 에러들과 싸울 수 있는 방비책을 소개 할것러스트에서 오류들을 처리하는 포괄적인 처리 방법에 대해 다루고자합니다. 또한, 오류를 다루는 것을 한 번에 한 조각씩 소개하고자합니다. 그래야만 모든 조각들이 어떻게 딱 들어맞는지에 대한 튼튼한 기반 지식을 가질 수 있기 때문입니다.
In this chapter, we intend to provide a comprehensive treatment of how to deal
with errors in Rust. More than that, we will attempt to introduce error handling
one piece at a time so that you'll come away with a solid working knowledge of
how everything fits together.

순진하게 하자면, 러스트의 오류 처리 방법은 수다스럽고 짜증날 수 있습니다. 이번 챕터는 우연히 마주치는 블록들을 탐험하고 정규 라이브러리를 가지고 어떻게 오류를 간결하고 인체공학적으로 다룰 수 있을지 설명하겠습니다.
When done naïvely, error handling in Rust can be verbose and annoying. This
chapter will explore those stumbling blocks and demonstrate how to use the
standard library to make error handling concise and ergonomic.

# 목차

이번 챕터는 매우 깁니다. 대체로 우리는 sum types와 combinators들의 완전 처음부터 시작하고 있고, 러스트가 점진적으로 오류를 처리하도록 시키도록 시도하려고 하기 때문입니다. 따라서, 다른 표현적인 타입 시스템에 대한 경험이 있는 프로그래머들은 그냥 뛰어넘어버리고 싶을지도 모르겠네요.
This chapter is very long, mostly because we start at the very beginning with
sum types and combinators, and try to motivate the way Rust does error handling
incrementally. As such, programmers with experience in other expressive type
systems may want to jump around.

* [The Basics](#the-basics)
* [Unwrapping explained](#unwrapping-explained)
* [The `Option` type](#the-option-type)
* [Composing `Option` values](#composing-optiont-values)
* [The `Result` type](#the-result-type)
* [Parsing integers](#parsing-integers)
* [The `Result` type alias idiom](#the-result-type-alias-idiom)
* [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil)
* [Working with multiple error types](#working-with-multiple-error-types)
* [Composing `Option` and `Result`](#composing-option-and-result)
* [The limits of combinators](#the-limits-of-combinators)
* [Early returns](#early-returns)
* [The `try!` macro](#the-try-macro)
* [Defining your own error type](#defining-your-own-error-type)
* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling)
* [The `Error` trait](#the-error-trait)
* [The `From` trait](#the-from-trait)
* [The real `try!` macro](#the-real-try-macro)
* [Composing custom error types](#composing-custom-error-types)
* [Advice for library writers](#advice-for-library-writers)
* [Case study: A program to read population data](#case-study-a-program-to-read-population-data)
* [Initial setup](#initial-setup)
* [Argument parsing](#argument-parsing)
* [Writing the logic](#writing-the-logic)
* [Error handling with `Box`](#error-handling-with-boxerror)
* [Reading from stdin](#reading-from-stdin)
* [Error handling with a custom type](#error-handling-with-a-custom-type)
* [Adding functionality](#adding-functionality)
* [The short story](#the-short-story)

# 기본

당신은 오류 처리를 *상태 분석*을 사용해서 연산이 성공적이었는지 아니었는지 판단하는 것이라고 생각해도 좋습니다. 앞으로 보겠지만, 인체공학적 오류 처리란 프로그래머가 계속 신경써야만 하는 명시적인 상태 분석을 줄이면서도 코드를 조립가능하게 유지하는 것을 의미합니다.
You can think of error handling as using *case analysis* to determine whether
a computation was successful or not. As you will see, the key to ergonomic error
handling is reducing the amount of explicit case analysis the programmer has to
do while keeping code composable.

코드를 조립가능하게 유지하는 것은 중요합니다. 그렇지않으면 기대치않은 어떤 것을 만날 때마다 [`패닉`](../std/macro.panic!.html)을 사용할 수도 있습니다. (`패닉`은 현재 작업을 되돌리고, 그리고 대부분의 경우, 프로그램 전체를 강제중단시킵니다.) 아래에 예시가 있습니다.
Keeping code composable is important, because without that requirement, we
could [`panic`](../std/macro.panic!.html) whenever we
come across something unexpected. (`panic` causes the current task to unwind,
and in most cases, the entire program aborts.) Here's an example:

```rust,should_panic
// 1에서 10 사이의 수 하나를 예측합니다.
// 만일 그 수가 생각한 수가 맞으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
// Guess a number between 1 and 10.
// If it matches the number we had in mind, return true. Else, return false.
fn guess(n: i32) -> bool {
if n < 1 || n > 10 {
panic!("Invalid number: {}", n);
}
n == 5
}

fn main() {
guess(11);
}
```

이 코드를 실행하려고 하면, 프로그램은 강제종료되면서 다음 메시지를 출력합니다.
If you try running this code, the program will crash with a message like this:

```text
thread '
' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
```

또 한가지 덜 억지스러운 예를 들어보겠습니다. 정수를 매개변수로 받아서 두배로 출력하는 프로그램이 있습니다.
Here's another example that is slightly less contrived. A program that accepts
an integer as an argument, doubles it and prints it.

```rust,should_panic
use std::env;

fn main() {
let mut argv = env::args();
let arg: String = argv.nth(1).unwrap(); // error 1
let n: i32 = arg.parse().unwrap(); // error 2
println!("{}", 2 * n);
}
```

If you give this program zero arguments (error 1) or if the first argument
isn't an integer (error 2), the program will panic just like in the first
example.

You can think of this style of error handling as similar to a bull running
through a china shop. The bull will get to where it wants to go, but it will
trample everything in the process.

## Unwrapping explained

In the previous example, we claimed
that the program would simply panic if it reached one of the two error
conditions, yet, the program does not include an explicit call to `panic` like
the first example. This is because the
panic is embedded in the calls to `unwrap`.

To “unwrap” something in Rust is to say, “Give me the result of the
computation, and if there was an error, just panic and stop the program.”
It would be better if we just showed the code for unwrapping because it is so
simple, but to do that, we will first need to explore the `Option` and `Result`
types. Both of these types have a method called `unwrap` defined on them.

## `Option` 형식

The `Option` type is
[defined in the standard library][1]:

```rust
enum Option {
None,
Some(T),
}
```

The `Option` type is a way to use Rust's type system to express the
*possibility of absence*. Encoding the possibility of absence into the type
system is an important concept because it will cause the compiler to force the
programmer to handle that absence. Let's take a look at an example that tries
to find a character in a string:

```rust
// Searches `haystack` for the Unicode character `needle`. If one is found, the
// byte offset of the character is returned. Otherwise, `None` is returned.
fn find(haystack: &str, needle: char) -> Option {
for (offset, c) in haystack.char_indices() {
if c == needle {
return Some(offset);
}
}
None
}
```

Notice that when this function finds a matching character, it doen't just
return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
a *value constructor* for the `Option` type. You can think of it as a function
with the type `fn(value: T) -> Option`. Correspondingly, `None` is also a
value constructor, except it has no arguments. You can think of `None` as a
function with the type `fn() -> Option`.

This might seem like much ado about nothing, but this is only half of the
story. The other half is *using* the `find` function we've written. Let's try
to use it to find the extension in a file name.

```rust
# fn find(_: &str, _: char) -> Option { None }
fn main() {
let file_name = "foobar.rs";
match find(file_name, '.') {
None => println!("No file extension found."),
Some(i) => println!("File extension: {}", &file_name[i+1..]),
}
}
```

This code uses [pattern matching][1] to do *case
analysis* on the `Option` returned by the `find` function. In fact, case
analysis is the only way to get at the value stored inside an `Option`. This
means that you, as the programmer, must handle the case when an `Option` is
`None` instead of `Some(t)`.

But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)?
There was no case analysis there! Instead, the case analysis was put inside the
`unwrap` method for you. You could define it yourself if you want:

```rust
enum Option {
None,
Some(T),
}

impl Option {
fn unwrap(self) -> T {
match self {
Option::Some(val) => val,
Option::None =>
panic!("called `Option::unwrap()` on a `None` value"),
}
}
}
```

The `unwrap` method *abstracts away the case analysis*. This is precisely the thing
that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
`unwrap` is not composable: it is the bull in the china shop.

### `Option` 변수들을 사용하기

In [`option-ex-string-find`](#code-option-ex-string-find-2)
we saw how to use `find` to discover the extension in a file name. Of course,
not all file names have a `.` in them, so it's possible that the file name has
no extension. This *possibility of absence* is encoded into the types using
`Option`. In other words, the compiler will force us to address the
possibility that an extension does not exist. In our case, we just print out a
message saying as such.

Getting the extension of a file name is a pretty common operation, so it makes
sense to put it into a function:

```rust
# fn find(_: &str, _: char) -> Option { None }
// Returns the extension of the given file name, where the extension is defined
// as all characters proceding the first `.`.
// If `file_name` has no `.`, then `None` is returned.
fn extension_explicit(file_name: &str) -> Option<&str> {
match find(file_name, '.') {
None => None,
Some(i) => Some(&file_name[i+1..]),
}
}
```

(Pro-tip: don't use this code. Use the
[`extension`](../std/path/struct.Path.html#method.extension)
method in the standard library instead.)

The code stays simple, but the important thing to notice is that the type of
`find` forces us to consider the possibility of absence. This is a good thing
because it means the compiler won't let us accidentally forget about the case
where a file name doesn't have an extension. On the other hand, doing explicit
case analysis like we've done in `extension_explicit` every time can get a bit
tiresome.

In fact, the case analysis in `extension_explicit` follows a very common
pattern: *map* a function on to the value inside of an `Option`, unless the
option is `None`, in which case, just return `None`.

Rust has parametric polymorphism, so it is very easy to define a combinator
that abstracts this pattern:

```rust
fn map(option: Option, f: F) -> Option where F: FnOnce(T) -> A {
match option {
None => None,
Some(value) => Some(f(value)),
}
}
```

Indeed, `map` is [defined as a method][2] on `Option` in the standard library.

Armed with our new combinator, we can rewrite our `extension_explicit` method
to get rid of the case analysis:

```rust
# fn find(_: &str, _: char) -> Option { None }
// Returns the extension of the given file name, where the extension is defined
// as all characters proceding the first `.`.
// If `file_name` has no `.`, then `None` is returned.
fn extension(file_name: &str) -> Option<&str> {
find(file_name, '.').map(|i| &file_name[i+1..])
}
```

One other pattern that we find is very common is assigning a default value to
the case when an `Option` value is `None`. For example, maybe your program
assumes that the extension of a file is `rs` even if none is present. As you
might imagine, the case analysis for this is not specific to file
extensions - it can work with any `Option`:

```rust
fn unwrap_or(option: Option, default: T) -> T {
match option {
None => default,
Some(value) => value,
}
}
```

The trick here is that the default value must have the same type as the value
that might be inside the `Option`. Using it is dead simple in our case:

```rust
# fn find(haystack: &str, needle: char) -> Option {
# for (offset, c) in haystack.char_indices() {
# if c == needle {
# return Some(offset);
# }
# }
# None
# }
#
# fn extension(file_name: &str) -> Option<&str> {
# find(file_name, '.').map(|i| &file_name[i+1..])
# }
fn main() {
assert_eq!(extension("foobar.csv").unwrap_or("rs"), "csv");
assert_eq!(extension("foobar").unwrap_or("rs"), "rs");
}
```

(Note that `unwrap_or` is [defined as a method][3] on `Option` in the
standard library, so we use that here instead of the free-standing function we
defined above. Don't forget to check out the more general [`unwrap_or_else`][4]
method.)

There is one more combinator that we think is worth paying special attention to:
`and_then`. It makes it easy to compose distinct computations that admit the
*possibility of absence*. For example, much of the code in this section is
about finding an extension given a file name. In order to do this, you first
need the file name which is typically extracted from a file *path*. While most
file paths have a file name, not *all* of them do. For example, `.`, `..` or
`/`.

So, we are tasked with the challenge of finding an extension given a file
*path*. Let's start with explicit case analysis:

```rust
# fn extension(file_name: &str) -> Option<&str> { None }
fn file_path_ext_explicit(file_path: &str) -> Option<&str> {
match file_name(file_path) {
None => None,
Some(name) => match extension(name) {
None => None,
Some(ext) => Some(ext),
}
}
}

fn file_name(file_path: &str) -> Option<&str> {
// implementation elided
unimplemented!()
}
```

You might think that we could just use the `map` combinator to reduce the case
analysis, but its type doesn't quite fit. Namely, `map` takes a function that
does something only with the inner value. The result of that function is then
*always* [rewrapped with `Some`](#code-option-map). Instead, we need something
like `map`, but which allows the caller to return another `Option`. Its generic
implementation is even simpler than `map`:

```rust
fn and_then(option: Option, f: F) -> Option

where F: FnOnce(T) -> Option
{
match option {
None => None,
Some(value) => f(value),
}
}
```

Now we can rewrite our `file_path_ext` function without explicit case analysis:

```rust
# fn extension(file_name: &str) -> Option<&str> { None }
# fn file_name(file_path: &str) -> Option<&str> { None }
fn file_path_ext(file_path: &str) -> Option<&str> {
file_name(file_path).and_then(extension)
}
```

The `Option` type has many other combinators [defined in the standard
library][5]. It is a good idea to skim this list and familiarize
yourself with what's available—they can often reduce case analysis
for you. Familiarizing yourself with these combinators will pay
dividends because many of them are also defined (with similar
semantics) for `Result`, which we will talk about next.

Combinators make using types like `Option` ergonomic because they reduce
explicit case analysis. They are also composable because they permit the caller
to handle the possibility of absence in their own way. Methods like `unwrap`
remove choices because they will panic if `Option` is `None`.

## `Result` 형식

The `Result` type is also
[defined in the standard library][6]:

```rust
enum Result {
Ok(T),
Err(E),
}
```

The `Result` type is a richer version of `Option`. Instead of expressing the
possibility of *absence* like `Option` does, `Result` expresses the possibility
of *error*. Usually, the *error* is used to explain why the result of some
computation failed. This is a strictly more general form of `Option`. Consider
the following type alias, which is semantically equivalent to the real
`Option` in every way:

```rust
type Option = Result;
```

This fixes the second type parameter of `Result` to always be `()` (pronounced
“unit” or “empty tuple”). Exactly one value inhabits the `()` type: `()`. (Yup,
the type and value level terms have the same notation!)

The `Result` type is a way of representing one of two possible outcomes in a
computation. By convention, one outcome is meant to be expected or “`Ok`” while
the other outcome is meant to be unexpected or “`Err`”.

Just like `Option`, the `Result` type also has an
[`unwrap` method
defined][7]
in the standard library. Let's define it:

```rust
# enum Result { Ok(T), Err(E) }
impl Result {
fn unwrap(self) -> T {
match self {
Result::Ok(val) => val,
Result::Err(err) =>
panic!("called `Result::unwrap()` on an `Err` value: {:?}", err),
}
}
}
```

This is effectively the same as our [definition for
`Option::unwrap`](#code-option-def-unwrap), except it includes the
error value in the `panic!` message. This makes debugging easier, but
it also requires us to add a [`Debug`][8] constraint on the `E` type
parameter (which represents our error type). Since the vast majority
of types should satisfy the `Debug` constraint, this tends to work out
in practice. (`Debug` on a type simply means that there's a reasonable
way to print a human readable description of values with that type.)

OK, let's move on to an example.

### 변수 파싱

The Rust standard library makes converting strings to integers dead simple.
It's so easy in fact, that it is very tempting to write something like the
following:

```rust
fn double_number(number_str: &str) -> i32 {
2 * number_str.parse::().unwrap()
}

fn main() {
let n: i32 = double_number("10");
assert_eq!(n, 20);
}
```

At this point, you should be skeptical of calling `unwrap`. For example, if
the string doesn't parse as a number, you'll get a panic:

```text
thread '
' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729
```

This is rather unsightly, and if this happened inside a library you're
using, you might be understandably annoyed. Instead, we should try to
handle the error in our function and let the caller decide what to
do. This means changing the return type of `double_number`. But to
what? Well, that requires looking at the signature of the [`parse`
method][9] in the standard library:

```rust,ignore
impl str {
fn parse(&self) -> Result;
}
```

Hmm. So we at least know that we need to use a `Result`. Certainly, it's
possible that this could have returned an `Option`. After all, a string either
parses as a number or it doesn't, right? That's certainly a reasonable way to
go, but the implementation internally distinguishes *why* the string didn't
parse as an integer. (Whether it's an empty string, an invalid digit, too big
or too small.) Therefore, using a `Result` makes sense because we want to
provide more information than simply “absence.” We want to say *why* the
parsing failed. You should try to emulate this line of reasoning when faced
with a choice between `Option` and `Result`. If you can provide detailed error
information, then you probably should. (We'll see more on this later.)

OK, but how do we write our return type? The `parse` method as defined
above is generic over all the different number types defined in the
standard library. We could (and probably should) also make our
function generic, but let's favor explicitness for the moment. We only
care about `i32`, so we need to [find its implementation of
`FromStr`](../std/primitive.i32.html) (do a `CTRL-F` in your browser
for “FromStr”) and look at its [associated type][10] `Err`. We did
this so we can find the concrete error type. In this case, it's
[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html).
Finally, we can rewrite our function:

```rust
use std::num::ParseIntError;

fn double_number(number_str: &str) -> Result {
match number_str.parse::() {
Ok(n) => Ok(2 * n),
Err(err) => Err(err),
}
}

fn main() {
match double_number("10") {
Ok(n) => assert_eq!(n, 20),
Err(err) => println!("Error: {:?}", err),
}
}
```

This is a little better, but now we've written a lot more code! The case
analysis has once again bitten us.

Combinators to the rescue! Just like `Option`, `Result` has lots of combinators
defined as methods. There is a large intersection of common combinators between
`Result` and `Option`. In particular, `map` is part of that intersection:

```rust
use std::num::ParseIntError;

fn double_number(number_str: &str) -> Result {
number_str.parse::().map(|n| 2 * n)
}

fn main() {
match double_number("10") {
Ok(n) => assert_eq!(n, 20),
Err(err) => println!("Error: {:?}", err),
}
}
```

The usual suspects are all there for `Result`, including
[`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) and
[`and_then`](../std/result/enum.Result.html#method.and_then).
Additionally, since `Result` has a second type parameter, there are
combinators that affect only the error type, such as
[`map_err`](../std/result/enum.Result.html#method.map_err) (instead of
`map`) and [`or_else`](../std/result/enum.Result.html#method.or_else)
(instead of `and_then`).

### `Result` 형식의 다른 표현법

In the standard library, you may frequently see types like
`Result`. But wait, [we defined `Result`](#code-result-def-1) to
have two type parameters. How can we get away with only specifying
one? The key is to define a `Result` type alias that *fixes* one of
the type parameters to a particular type. Usually the fixed type is
the error type. For example, our previous example parsing integers
could be rewritten like this:

```rust
use std::num::ParseIntError;
use std::result;

type Result = result::Result;

fn double_number(number_str: &str) -> Result {
unimplemented!();
}
```

Why would we do this? Well, if we have a lot of functions that could return
`ParseIntError`, then it's much more convenient to define an alias that always
uses `ParseIntError` so that we don't have to write it out all the time.

The most prominent place this idiom is used in the standard library is
with [`io::Result`](../std/io/type.Result.html). Typically, one writes
`io::Result`, which makes it clear that you're using the `io`
module's type alias instead of the plain definition from
`std::result`. (This idiom is also used for
[`fmt::Result`](../std/fmt/type.Result.html).)

## A brief interlude: unwrapping isn't evil

If you've been following along, you might have noticed that I've taken a pretty
hard line against calling methods like `unwrap` that could `panic` and abort
your program. *Generally speaking*, this is good advice.

However, `unwrap` can still be used judiciously. What exactly justifies use of
`unwrap` is somewhat of a grey area and reasonable people can disagree. I'll
summarize some of my *opinions* on the matter.

* **In examples and quick 'n' dirty code.** Sometimes you're writing examples
or a quick program, and error handling simply isn't important. Beating the
convenience of `unwrap` can be hard in such scenarios, so it is very
appealing.
* **When panicking indicates a bug in the program.** When the invariants of
your code should prevent a certain case from happening (like, say, popping
from an empty stack), then panicking can be permissible. This is because it
exposes a bug in your program. This can be explicit, like from an `assert!`
failing, or it could be because your index into an array was out of bounds.

This is probably not an exhaustive list. Moreover, when using an
`Option`, it is often better to use its
[`expect`](../std/option/enum.Option.html#method.expect)
method. `expect` does exactly the same thing as `unwrap`, except it
prints a message you give to `expect`. This makes the resulting panic
a bit nicer to deal with, since it will show your message instead of
“called unwrap on a `None` value.”

My advice boils down to this: use good judgment. There's a reason why the words
“never do X” or “Y is considered harmful” don't appear in my writing. There are
trade offs to all things, and it is up to you as the programmer to determine
what is acceptable for your use cases. My goal is only to help you evaluate
trade offs as accurately as possible.

Now that we've covered the basics of error handling in Rust, and
explained unwrapping, let's start exploring more of the standard
library.

# Working with multiple error types

Thus far, we've looked at error handling where everything was either an
`Option` or a `Result`. But what happens when you have both an
`Option` and a `Result`? Or what if you have a `Result` and a
`Result`? Handling *composition of distinct error types* is the next
challenge in front of us, and it will be the major theme throughout the rest of
this chapter.

## Composing `Option` and `Result`

So far, I've talked about combinators defined for `Option` and combinators
defined for `Result`. We can use these combinators to compose results of
different computations without doing explicit case analysis.

Of course, in real code, things aren't always as clean. Sometimes you have a
mix of `Option` and `Result` types. Must we resort to explicit case analysis,
or can we continue using combinators?

For now, let's revisit one of the first examples in this chapter:

```rust,should_panic
use std::env;

fn main() {
let mut argv = env::args();
let arg: String = argv.nth(1).unwrap(); // error 1
let n: i32 = arg.parse().unwrap(); // error 2
println!("{}", 2 * n);
}
```

Given our new found knowledge of `Option`, `Result` and their various
combinators, we should try to rewrite this so that errors are handled properly
and the program doesn't panic if there's an error.

The tricky aspect here is that `argv.nth(1)` produces an `Option` while
`arg.parse()` produces a `Result`. These aren't directly composable. When faced
with both an `Option` and a `Result`, the solution is *usually* to convert the
`Option` to a `Result`. In our case, the absence of a command line parameter
(from `env::args()`) means the user didn't invoke the program correctly. We
could just use a `String` to describe the error. Let's try:

```rust
use std::env;

fn double_arg(mut argv: env::Args) -> Result {
argv.nth(1)
.ok_or("Please give at least one argument".to_owned())
.and_then(|arg| arg.parse::().map_err(|err| err.to_string()))
}

fn main() {
match double_arg(env::args()) {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}", err),
}
}
```

There are a couple new things in this example. The first is the use of the
[`Option::ok_or`](../std/option/enum.Option.html#method.ok_or)
combinator. This is one way to convert an `Option` into a `Result`. The
conversion requires you to specify what error to use if `Option` is `None`.
Like the other combinators we've seen, its definition is very simple:

```rust
fn ok_or(option: Option, err: E) -> Result {
match option {
Some(val) => Ok(val),
None => Err(err),
}
}
```

The other new combinator used here is
[`Result::map_err`](../std/result/enum.Result.html#method.map_err).
This is just like `Result::map`, except it maps a function on to the *error*
portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is
returned unmodified.

We use `map_err` here because it is necessary for the error types to remain
the same (because of our use of `and_then`). Since we chose to convert the
`Option` (from `argv.nth(1)`) to a `Result`, we must
also convert the `ParseIntError` from `arg.parse()` to a `String`.

## The limits of combinators

Doing IO and parsing input is a very common task, and it's one that I
personally have done a lot of in Rust. Therefore, we will use (and continue to
use) IO and various parsing routines to exemplify error handling.

Let's start simple. We are tasked with opening a file, reading all of its
contents and converting its contents to a number. Then we multiply it by `2`
and print the output.

Although I've tried to convince you not to use `unwrap`, it can be useful
to first write your code using `unwrap`. It allows you to focus on your problem
instead of the error handling, and it exposes the points where proper error
handling need to occur. Let's start there so we can get a handle on the code,
and then refactor it to use better error handling.

```rust,should_panic
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> i32 {
let mut file = File::open(file_path).unwrap(); // error 1
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap(); // error 2
let n: i32 = contents.trim().parse().unwrap(); // error 3
2 * n
}

fn main() {
let doubled = file_double("foobar");
println!("{}", doubled);
}
```

(N.B. The `AsRef` is used because those are the
[same bounds used on
`std::fs::File::open`](../std/fs/struct.File.html#method.open).
This makes it ergnomic to use any kind of string as a file path.)

There are three different errors that can occur here:

1. A problem opening the file.
2. A problem reading data from the file.
3. A problem parsing the data as a number.

The first two problems are described via the
[`std::io::Error`](../std/io/struct.Error.html) type. We know this
because of the return types of
[`std::fs::File::open`](../std/fs/struct.File.html#method.open) and
[`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string).
(Note that they both use the [`Result` type alias
idiom](#the-result-type-alias-idiom) described previously. If you
click on the `Result` type, you'll [see the type
alias](../std/io/type.Result.html), and consequently, the underlying
`io::Error` type.) The third problem is described by the
[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html)
type. The `io::Error` type in particular is *pervasive* throughout the
standard library. You will see it again and again.

Let's start the process of refactoring the `file_double` function. To make this
function composable with other components of the program, it should *not* panic
if any of the above error conditions are met. Effectively, this means that the
function should *return an error* if any of its operations fail. Our problem is
that the return type of `file_double` is `i32`, which does not give us any
useful way of reporting an error. Thus, we must start by changing the return
type from `i32` to something else.

The first thing we need to decide: should we use `Option` or `Result`? We
certainly could use `Option` very easily. If any of the three errors occur, we
could simply return `None`. This will work *and it is better than panicking*,
but we can do a lot better. Instead, we should pass some detail about the error
that occurred. Since we want to express the *possibility of error*, we should
use `Result`. But what should `E` be? Since two *different* types of
errors can occur, we need to convert them to a common type. One such type is
`String`. Let's see how that impacts our code:

```rust
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
File::open(file_path)
.map_err(|err| err.to_string())
.and_then(|mut file| {
let mut contents = String::new();
file.read_to_string(&mut contents)
.map_err(|err| err.to_string())
.map(|_| contents)
})
.and_then(|contents| {
contents.trim().parse::()
.map_err(|err| err.to_string())
})
.map(|n| 2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}", err),
}
}
```

This code looks a bit hairy. It can take quite a bit of practice before code
like this becomes easy to write. The way we write it is by *following the
types*. As soon as we changed the return type of `file_double` to
`Result`, we had to start looking for the right combinators. In
this case, we only used three different combinators: `and_then`, `map` and
`map_err`.

`and_then` is used to chain multiple computations where each computation could
return an error. After opening the file, there are two more computations that
could fail: reading from the file and parsing the contents as a number.
Correspondingly, there are two calls to `and_then`.

`map` is used to apply a function to the `Ok(...)` value of a `Result`. For
example, the very last call to `map` multiplies the `Ok(...)` value (which is
an `i32`) by `2`. If an error had occurred before that point, this operation
would have been skipped because of how `map` is defined.

`map_err` is the trick the makes all of this work. `map_err` is just like
`map`, except it applies a function to the `Err(...)` value of a `Result`. In
this case, we want to convert all of our errors to one type: `String`. Since
both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
`to_string()` method to convert them.

With all of that said, the code is still hairy. Mastering use of combinators is
important, but they have their limits. Let's try a different approach: early
returns.

## Early returns

I'd like to take the code from the previous section and rewrite it using *early
returns*. Early returns let you exit the function early. We can't return early
in `file_double` from inside another closure, so we'll need to revert back to
explicit case analysis.

```rust
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
let mut file = match File::open(file_path) {
Ok(file) => file,
Err(err) => return Err(err.to_string()),
};
let mut contents = String::new();
if let Err(err) = file.read_to_string(&mut contents) {
return Err(err.to_string());
}
let n: i32 = match contents.trim().parse() {
Ok(n) => n,
Err(err) => return Err(err.to_string()),
};
Ok(2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}", err),
}
}
```

Reasonable people can disagree over whether this code is better that the code
that uses combinators, but if you aren't familiar with the combinator approach,
this code looks simpler to read to me. It uses explicit case analysis with
`match` and `if let`. If an error occurs, it simply stops executing the
function and returns the error (by converting it to a string).

Isn't this a step backwards though? Previously, we said that the key to
ergonomic error handling is reducing explicit case analysis, yet we've reverted
back to explicit case analysis here. It turns out, there are *multiple* ways to
reduce explicit case analysis. Combinators aren't the only way.

## The `try!` macro

A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro
abstracts case analysis just like combinators, but unlike combinators, it also
abstracts *control flow*. Namely, it can abstract the *early return* pattern
seen above.

Here is a simplified definition of a `try!` macro:

```rust
macro_rules! try {
($e:expr) => (match $e {
Ok(val) => val,
Err(err) => return Err(err),
});
}
```

(The [real definition](../std/macro.try!.html) is a bit more
sophisticated. We will address that later.)

Using the `try!` macro makes it very easy to simplify our last example. Since
it does the case analysis and the early return for us, we get tighter code that
is easier to read:

```rust
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
let mut contents = String::new();
try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
let n = try!(contents.trim().parse::().map_err(|e| e.to_string()));
Ok(2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}", err),
}
}
```

The `map_err` calls are still necessary given
[our definition of `try!`](#code-try-def-simple).
This is because the error types still need to be converted to `String`.
The good news is that we will soon learn how to remove those `map_err` calls!
The bad news is that we will need to learn a bit more about a couple important
traits in the standard library before we can remove the `map_err` calls.

## Defining your own error type

Before we dive into some of the standard library error traits, I'd like to wrap
up this section by removing the use of `String` as our error type in the
previous examples.

Using `String` as we did in our previous examples is convenient because it's
easy to convert errors to strings, or even make up your own errors as strings
on the spot. However, using `String` for your errors has some downsides.

The first downside is that the error messages tend to clutter your
code. It's possible to define the error messages elsewhere, but unless
you're unusually disciplined, it is very tempting to embed the error
message into your code. Indeed, we did exactly this in a [previous
example](#code-error-double-string).

The second and more important downside is that `String`s are *lossy*. That is,
if all errors are converted to strings, then the errors we pass to the caller
become completely opaque. The only reasonable thing the caller can do with a
`String` error is show it to the user. Certainly, inspecting the string to
determine the type of error is not robust. (Admittedly, this downside is far
more important inside of a library as opposed to, say, an application.)

For example, the `io::Error` type embeds an
[`io::ErrorKind`](../std/io/enum.ErrorKind.html),
which is *structured data* that represents what went wrong during an IO
operation. This is important because you might want to react differently
depending on the error. (e.g., A `BrokenPipe` error might mean quitting your
program gracefully while a `NotFound` error might mean exiting with an error
code and showing an error to the user.) With `io::ErrorKind`, the caller can
examine the type of an error with case analysis, which is strictly superior
to trying to tease out the details of an error inside of a `String`.

Instead of using a `String` as an error type in our previous example of reading
an integer from a file, we can define our own error type that represents errors
with *structured data*. We endeavor to not drop information from underlying
errors in case the caller wants to inspect the details.

The ideal way to represent *one of many possibilities* is to define our own
sum type using `enum`. In our case, an error is either an `io::Error` or a
`num::ParseIntError`, so a natural definition arises:

```rust
use std::io;
use std::num;

// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
Parse(num::ParseIntError),
}
```

Tweaking our code is very easy. Instead of converting errors to strings, we
simply convert them to our `CliError` type using the corresponding value
constructor:

```rust
# #[derive(Debug)]
# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
let mut file = try!(File::open(file_path).map_err(CliError::Io));
let mut contents = String::new();
try!(file.read_to_string(&mut contents).map_err(CliError::Io));
let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
Ok(2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {:?}", err),
}
}
```

The only change here is switching `map_err(|e| e.to_string())` (which converts
errors to strings) to `map_err(CliError::Io)` or `map_err(CliError::Parse)`.
The *caller* gets to decide the level of detail to report to the user. In
effect, using a `String` as an error type removes choices from the caller while
using a custom `enum` error type like `CliError` gives the caller all of the
conveniences as before in addition to *structured data* describing the error.

A rule of thumb is to define your own error type, but a `String` error type
will do in a pinch, particularly if you're writing an application. If you're
writing a library, defining your own error type should be strongly preferred so
that you don't remove choices from the caller unnecessarily.

# Standard library traits used for error handling

The standard library defines two integral traits for error handling:
[`std::error::Error`](../std/error/trait.Error.html) and
[`std::convert::From`](../std/convert/trait.From.html). While `Error`
is designed specifically for generically describing errors, the `From`
trait serves a more general role for converting values between two
distinct types.

## The `Error` trait

The `Error` trait is [defined in the standard
library](../std/error/trait.Error.html):

```rust
use std::fmt::{Debug, Display};

trait Error: Debug + Display {
/// A short description of the error.
fn description(&self) -> &str;

/// The lower level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
}
```

This trait is super generic because it is meant to be implemented for *all*
types that represent errors. This will prove useful for writing composable code
as we'll see later. Otherwise, the trait allows you to do at least the
following things:

* Obtain a `Debug` representation of the error.
* Obtain a user-facing `Display` representation of the error.
* Obtain a short description of the error (via the `description` method).
* Inspect the causal chain of an error, if one exists (via the `cause` method).

The first two are a result of `Error` requiring impls for both `Debug` and
`Display`. The latter two are from the two methods defined on `Error`. The
power of `Error` comes from the fact that all error types impl `Error`, which
means errors can be existentially quantified as a
[trait object](../book/trait-objects.html).
This manifests as either `Box` or `&Error`. Indeed, the `cause` method
returns an `&Error`, which is itself a trait object. We'll revisit the
`Error` trait's utility as a trait object later.

For now, it suffices to show an example implementing the `Error` trait. Let's
use the error type we defined in the
[previous section](#defining-your-own-error-type):

```rust
use std::io;
use std::num;

// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
Parse(num::ParseIntError),
}
```

This particular error type represents the possibility of two types of errors
occurring: an error dealing with I/O or an error converting a string to a
number. The error could represent as many error types as you want by adding new
variants to the `enum` definition.

Implementing `Error` is pretty straight-forward. It's mostly going to be a lot
explicit case analysis.

```rust,ignore
use std::error;
use std::fmt;

impl fmt::Display for CliError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Both underlying errors already impl `Display`, so we defer to
// their implementations.
CliError::Io(ref err) => write!(f, "IO error: {}", err),
CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
}
}
}

impl error::Error for CliError {
fn description(&self) -> &str {
// Both underlying errors already impl `Error`, so we defer to their
// implementations.
match *self {
CliError::Io(ref err) => err.description(),
// Normally we can just write `err.description()`, but the error
// type has a concrete method called `description`, which conflicts
// with the trait method. For now, we must explicitly call
// `description` through the `Error` trait.
CliError::Parse(ref err) => error::Error::description(err),
}
}

fn cause(&self) -> Option<&error::Error> {
match *self {
// N.B. Both of these implicitly cast `err` from their concrete
// types (either `&io::Error` or `&num::ParseIntError`)
// to a trait object `&Error`. This works because both error types
// implement `Error`.
CliError::Io(ref err) => Some(err),
CliError::Parse(ref err) => Some(err),
}
}
}
```

We note that this is a very typical implementation of `Error`: match on your
different error types and satisfy the contracts defined for `description` and
`cause`.

## The `From` trait

The `std::convert::From` trait is
[defined in the standard
library](../std/convert/trait.From.html):

```rust
trait From {
fn from(T) -> Self;
}
```

Deliciously simple, yes? `From` is very useful because it gives us a generic
way to talk about conversion *from* a particular type `T` to some other type
(in this case, “some other type” is the subject of the impl, or `Self`).
The crux of `From` is the
[set of implementations provided by the standard
library](../std/convert/trait.From.html).

Here are a few simple examples demonstrating how `From` works:

```rust
let string: String = From::from("foo");
let bytes: Vec = From::from("foo");
let cow: ::std::borrow::Cow = From::from("foo");
```

OK, so `From` is useful for converting between strings. But what about errors?
It turns out, there is one critical impl:

```rust,ignore
impl<'a, E: Error + 'a> From for Box
```

This impl says that for *any* type that impls `Error`, we can convert it to a
trait object `Box`. This may not seem terribly surprising, but it is
useful in a generic context.

Remember the two errors we were dealing with previously? Specifically,
`io::Error` and `num::ParseIntError`. Since both impl `Error`, they work with
`From`:

```rust
use std::error::Error;
use std::fs;
use std::io;
use std::num;

// We have to jump through some hoops to actually get error values.
let io_err: io::Error = io::Error::last_os_error();
let parse_err: num::ParseIntError = "not a number".parse::().unwrap_err();

// OK, here are the conversions.
let err1: Box = From::from(io_err);
let err2: Box = From::from(parse_err);
```

There is a really important pattern to recognize here. Both `err1` and `err2`
have the *same type*. This is because they are existentially quantified types,
or trait objects. In particularly, their underlying type is *erased* from the
compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
Additionally, we constructed `err1` and `err2` using precisely the same
function call: `From::from`. This is because `From::from` is overloaded on both
its argument and its return type.

This pattern is important because it solves a problem we had earlier: it gives
us a way to reliably convert errors to the same type using the same function.

Time to revisit an old friend; the `try!` macro.

## The real `try!` macro

Previously, we presented this definition of `try!`:

```rust
macro_rules! try {
($e:expr) => (match $e {
Ok(val) => val,
Err(err) => return Err(err),
});
}
```

This is not it's real definition. It's real definition is
[in the standard library](../std/macro.try!.html):

```rust
macro_rules! try {
($e:expr) => (match $e {
Ok(val) => val,
Err(err) => return Err(::std::convert::From::from(err)),
});
}
```

There's one tiny but powerful change: the error value is passed through
`From::from`. This makes the `try!` macro a lot more powerful because it gives
you automatic type conversion for free.

Armed with our more powerful `try!` macro, let's take a look at code we wrote
previously to read a file and convert its contents to an integer:

```rust
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
let mut contents = String::new();
try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
let n = try!(contents.trim().parse::().map_err(|e| e.to_string()));
Ok(2 * n)
}
```

Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all
we have to do is pick a type that `From` works with. As we saw in the previous
section, `From` has an impl that let's it convert any error type into a
`Box`:

```rust
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result> {
let mut file = try!(File::open(file_path));
let mut contents = String::new();
try!(file.read_to_string(&mut contents));
let n = try!(contents.trim().parse::());
Ok(2 * n)
}
```

We are getting very close to ideal error handling. Our code has very little
overhead as a result from error handling because the `try!` macro encapsulates
three things simultaneously:

1. Case analysis.
2. Control flow.
3. Error type conversion.

When all three things are combined, we get code that is unencumbered by
combinators, calls to `unwrap` or case analysis.

There's one little nit left: the `Box` type is *opaque*. If we
return a `Box` to the caller, the caller can't (easily) inspect
underlying error type. The situation is certainly better than `String`
because the caller can call methods like
[`description`](../std/error/trait.Error.html#tymethod.description)
and [`cause`](../std/error/trait.Error.html#method.cause), but the
limitation remains: `Box` is opaque. (N.B. This isn't entirely
true because Rust does have runtime reflection, which is useful in
some scenarios that are [beyond the scope of this
chapter](https://crates.io/crates/error).)

It's time to revisit our custom `CliError` type and tie everything together.

## Composing custom error types

In the last section, we looked at the real `try!` macro and how it does
automatic type conversion for us by calling `From::from` on the error value.
In particular, we converted errors to `Box`, which works, but the type
is opaque to callers.

To fix this, we use the same remedy that we're already familiar with: a custom
error type. Once again, here is the code that reads the contents of a file and
converts it to an integer:

```rust
use std::fs::File;
use std::io::{self, Read};
use std::num;
use std::path::Path;

// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
Parse(num::ParseIntError),
}

fn file_double_verbose>(file_path: P) -> Result {
let mut file = try!(File::open(file_path).map_err(CliError::Io));
let mut contents = String::new();
try!(file.read_to_string(&mut contents).map_err(CliError::Io));
let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
Ok(2 * n)
}
```

Notice that we still have the calls to `map_err`. Why? Well, recall the
definitions of [`try!`](#code-try-def) and [`From`](#code-from-def). The
problem is that there is no `From` impl that allows us to convert from error
types like `io::Error` and `num::ParseIntError` to our own custom `CliError`.
Of course, it is easy to fix this! Since we defined `CliError`, we can impl
`From` with it:

```rust
# #[derive(Debug)]
# enum CliError { Io(io::Error), Parse(num::ParseIntError) }
use std::io;
use std::num;

impl From for CliError {
fn from(err: io::Error) -> CliError {
CliError::Io(err)
}
}

impl From for CliError {
fn from(err: num::ParseIntError) -> CliError {
CliError::Parse(err)
}
}
```

All these impls are doing is teaching `From` how to create a `CliError` from
other error types. In our case, construction is as simple as invoking the
corresponding value constructor. Indeed, it is *typically* this easy.

We can finally rewrite `file_double`:

```rust
# use std::io;
# use std::num;
# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
# impl From for CliError {
# fn from(err: io::Error) -> CliError { CliError::Io(err) }
# }
# impl From for CliError {
# fn from(err: num::ParseIntError) -> CliError { CliError::Parse(err) }
# }

use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
let mut file = try!(File::open(file_path));
let mut contents = String::new();
try!(file.read_to_string(&mut contents));
let n: i32 = try!(contents.trim().parse());
Ok(2 * n)
}
```

The only thing we did here was remove the calls to `map_err`. They are no
longer needed because the `try!` macro invokes `From::from` on the error value.
This works because we've provided `From` impls for all the error types that
could appear.

If we modified our `file_double` function to perform some other operation, say,
convert a string to a float, then we'd need to add a new variant to our error
type:

```rust
use std::io;
use std::num;

enum CliError {
Io(io::Error),
ParseInt(num::ParseIntError),
ParseFloat(num::ParseFloatError),
}
```

And add a new `From` impl:

```rust
# enum CliError {
# Io(::std::io::Error),
# ParseInt(num::ParseIntError),
# ParseFloat(num::ParseFloatError),
# }

use std::num;

impl From for CliError {
fn from(err: num::ParseFloatError) -> CliError {
CliError::ParseFloat(err)
}
}
```

And that's it!

## Advice for library writers

If your library needs to report custom errors, then you should
probably define your own error type. It's up to you whether or not to
expose its representation (like
[`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like
[`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless
of how you do it, it's usually good practice to at least provide some
information about the error beyond just its `String`
representation. But certainly, this will vary depending on use cases.

At a minimum, you should probably implement the
[`Error`](../std/error/trait.Error.html)
trait. This will give users of your library some minimum flexibility for
[composing errors](#the-real-try-macro). Implementing the `Error` trait also
means that users are guaranteed the ability to obtain a string representation
of an error (because it requires impls for both `fmt::Debug` and
`fmt::Display`).

Beyond that, it can also be useful to provide implementations of `From` on your
error types. This allows you (the library author) and your users to
[compose more detailed errors](#composing-custom-error-types). For example,
[`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html)
provides `From` impls for both `io::Error` and `byteorder::Error`.

Finally, depending on your tastes, you may also want to define a
[`Result` type alias](#the-result-type-alias-idiom), particularly if your
library defines a single error type. This is used in the standard library
for [`io::Result`](../std/io/type.Result.html)
and [`fmt::Result`](../std/fmt/type.Result.html).

# Case study: A program to read population data

This chapter was long, and depending on your background, it might be
rather dense. While there is plenty of example code to go along with
the prose, most of it was specifically designed to be pedagogical. So,
we're going to do something new: a case study.

For this, we're going to build up a command line program that lets you
query world population data. The objective is simple: you give it a location
and it will tell you the population. Despite the simplicity, there is a lot
that can go wrong!

The data we'll be using comes from the [Data Science
Toolkit][11]. I've prepared some data from it for this exercise. You
can either grab the [world population data][12] (41MB gzip compressed,
145MB uncompressed) or just the [US population data][13] (2.2MB gzip
compressed, 7.2MB uncompressed).

Up until now, we've kept the code limited to Rust's standard library. For a real
task like this though, we'll want to at least use something to parse CSV data,
parse the program arguments and decode that stuff into Rust types automatically. For that, we'll use the
[`csv`](https://crates.io/crates/csv),
and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.

## Initial setup

We're not going to spend a lot of time on setting up a project with
Cargo because it is already covered well in [the Cargo
chapter](../book/hello-cargo) and [Cargo's documentation][14].

To get started from scratch, run `cargo new --bin city-pop` and make sure your
`Cargo.toml` looks something like this:

```text
[package]
name = "city-pop"
version = "0.1.0"
authors = ["Andrew Gallant "]

[[bin]]
name = "city-pop"

[dependencies]
csv = "0.*"
rustc-serialize = "0.*"
getopts = "0.*"
```

You should already be able to run:

```text
cargo build --release
./target/release/city-pop
# Outputs: Hello, world!
```

## Argument parsing

Let's get argument parsing out of the way. we won't go into too much
detail on Getopts, but there is [some good documentation][15]
describing it. The short story is that Getopts generates an argument
parser and a help message from a vector of options (The fact that it
is a vector is hidden behind a struct and a set of methods). Once the
parsing is done, we can decode the program arguments into a Rust
struct. From there, we can get information about the flags, for
instance, wether they were passed in, and what arguments they
had. Here's our program with the appropriate `extern crate`
statements, and the basic argument setup for Getopts:

```rust,ignore
extern crate getopts;
extern crate rustc_serialize;

use getopts::Options;
use std::env;

fn print_usage(program: &str, opts: Options) {
println!("{}", opts.usage(&format!("Usage: {} [options] ", program)));
}

fn main() {
let args: Vec = env::args().collect();
let program = args[0].clone();

let mut opts = Options::new();
opts.optflag("h", "help", "Show this usage message.");

let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(e) => { panic!(e.to_string()) }
};
if matches.opt_present("h") {
print_usage(&program, opts);
return;
}
let data_path = args[1].clone();
let city = args[2].clone();

// Do stuff with information
}
```

First, we get a vector of the arguments passed into our program. We
then store the first one, knowing that it is our program's name. Once
that's done, we set up our argument flags, in this case a simplistic
help message flag. Once we have the argument flags set up, we use
`Options.parse` to parse the argument vector (starting from index one,
becouse index 0 is the program name). If this was successful, we
assign matches to the parsed object, if not, we panic. Once past that,
we test if the user passed in the help flag, and if so print the usage
message. The option help messages are constructed by Getopts, so all
we have to do to print the usage message is tell it what we want it to
print for the program name and template. If the user has not passed in
the help flag, we assign the proper variables to their corresponding
arguments.

## Writing the logic

We're all different in how we write code, but error handling is
usually the last thing we want to think about. This isn't very good
practice for good design, but it can be useful for rapidly
prototyping. In our case, because Rust forces us to be explicit about
error handling, it will also make it obvious what parts of our program
can cause errors. Why? Because Rust will make us call `unwrap`! This
can give us a nice bird's eye view of how we need to approach error
handling.

In this case study, the logic is really simple. All we need to do is parse the
CSV data given to us and print out a field in matching rows. Let's do it. (Make
sure to add `extern crate csv;` to the top of your file.)

```rust,ignore
// This struct represents the data in each row of the CSV file.
// Type based decoding absolves us of a lot of the nitty gritty error
// handling, like parsing strings as integers or floats.
#[derive(Debug, RustcDecodable)]
struct Row {
country: String,
city: String,
accent_city: String,
region: String,

// Not every row has data for the population, latitude or longitude!
// So we express them as `Option` types, which admits the possibility of
// absence. The CSV parser will fill in the correct value for us.
population: Option,
latitude: Option,
longitude: Option,
}

fn print_usage(program: &str, opts: Options) {
println!("{}", opts.usage(&format!("Usage: {} [options] ", program)));
}

fn main() {
let args: Vec = env::args().collect();
let program = args[0].clone();

let mut opts = Options::new();
opts.optflag("h", "help", "Show this usage message.");

let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(e) => { panic!(e.to_string()) }
};

if matches.opt_present("h") {
print_usage(&program, opts);
return;
}

let data_file = args[1].clone();
let data_path = Path::new(&data_file);
let city = args[2].clone();

let file = fs::File::open(data_path).unwrap();
let mut rdr = csv::Reader::from_reader(file);

for row in rdr.decode::() {
let row = row.unwrap();

if row.city == city {
println!("{}, {}: {:?}",
row.city, row.country,
row.population.expect("population count"));
}
}
}
```

Let's outline the errors. We can start with the obvious: the three places that
`unwrap` is called:

1. [`fs::File::open`](../std/fs/struct.File.html#method.open)
can return an
[`io::Error`](../std/io/struct.Error.html).
2. [`csv::Reader::decode`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.decode)
decodes one record at a time, and
[decoding a
record](http://burntsushi.net/rustdoc/csv/struct.DecodedRecords.html)
(look at the `Item` associated type on the `Iterator` impl)
can produce a
[`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html).
3. If `row.population` is `None`, then calling `expect` will panic.

Are there any others? What if we can't find a matching city? Tools like `grep`
will return an error code, so we probably should too. So we have logic errors
specific to our problem, IO errors and CSV parsing errors. We're going to
explore two different ways to approach handling these errors.

I'd like to start with `Box`. Later, we'll see how defining our own
error type can be useful.

## Error handling with `Box`

`Box` is nice because it *just works*. You don't need to define your own
error types and you don't need any `From` implementations. The downside is that
since `Box` is a trait object, it *erases the type*, which means the
compiler can no longer reason about its underlying type.

[Previously](#the-limits-of-combinators) we started refactoring our code by
changing the type of our function from `T` to `Result`. In
this case, `OurErrorType` is just `Box`. But what's `T`? And can we add
a return type to `main`?

The answer to the second question is no, we can't. That means we'll need to
write a new function. But what is `T`? The simplest thing we can do is to
return a list of matching `Row` values as a `Vec`. (Better code would
return an iterator, but that is left as an exercise to the reader.)

Let's refactor our code into its own function, but keep the calls to `unwrap`.
Note that we opt to handle the possibility of a missing population count by
simply ignoring that row.

```rust,ignore
struct Row {
// unchanged
}

struct PopulationCount {
city: String,
country: String,
// This is no longer an `Option` because values of this type are only
// constructed if they have a population count.
count: u64,
}

fn print_usage(program: &str, opts: Options) {
println!("{}", opts.usage(&format!("Usage: {} [options] ", program)));
}

fn search>(file_path: P, city: &str) -> Vec {
let mut found = vec![];
let file = fs::File::open(file_path).unwrap();
let mut rdr = csv::Reader::from_reader(file);
for row in rdr.decode::() {
let row = row.unwrap();
match row.population {
None => { } // skip it
Some(count) => if row.city == city {
found.push(PopulationCount {
city: row.city,
country: row.country,
count: count,
});
},
}
}
found
}

fn main() {
let args: Vec = env::args().collect();
let program = args[0].clone();

let mut opts = Options::new();
opts.optflag("h", "help", "Show this usage message.");

let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(e) => { panic!(e.to_string()) }
};
if matches.opt_present("h") {
print_usage(&program, opts);
return;
}

let data_file = args[1].clone();
let data_path = Path::new(&data_file);
let city = args[2].clone();
for pop in search(&data_path, &city) {
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
}
}

```

While we got rid of one use of `expect` (which is a nicer variant of `unwrap`),
we still should handle the absence of any search results.

To convert this to proper error handling, we need to do the following:

1. Change the return type of `search` to be `Result,
Box>`.
2. Use the [`try!` macro](#code-try-def) so that errors are returned to the
caller instead of panicking the program.
3. Handle the error in `main`.

Let's try it:

```rust,ignore
fn search>
(file_path: P, city: &str)
-> Result, Box> {
let mut found = vec![];
let file = try!(fs::File::open(file_path));
let mut rdr = csv::Reader::from_reader(file);
for row in rdr.decode::() {
let row = try!(row);
match row.population {
None => { } // skip it
Some(count) => if row.city == city {
found.push(PopulationCount {
city: row.city,
country: row.country,
count: count,
});
},
}
}
if found.is_empty() {
Err(From::from("No matching cities with a population were found."))
} else {
Ok(found)
}
}
```

Instead of `x.unwrap()`, we now have `try!(x)`. Since our function returns a
`Result`, the `try!` macro will return early from the function if an
error occurs.

There is one big gotcha in this code: we used `Box`
instead of `Box`. We did this so we could convert a plain string to an
error type. We need these extra bounds so that we can use the
[corresponding `From`
impls](../std/convert/trait.From.html):

```rust,ignore
// We are making use of this impl in the code above, since we call `From::from`
// on a `&'static str`.
impl<'a, 'b> From<&'b str> for Box

// But this is also useful when you need to allocate a new string for an
// error message, usually with `format!`.
impl From for Box
```

Now that we've seen how to do proper error handling with `Box`, let's
try a different approach with our own custom error type. But first, let's take
a quick break from error handling and add support for reading from `stdin`.

## Reading from stdin

In our program, we accept a single file for input and do one pass over the
data. This means we probably should be able to accept input on stdin. But maybe
we like the current format too—so let's have both!

Adding support for stdin is actually quite easy. There are only two things we
have to do:

1. Tweak the program arguments so that a single parameter—the
city—can be accepted while the population data is read from stdin.
2. Modify the program so that an option `-f` can take the file, if it
is not passed into stdin.
3. Modify the `search` function to take an *optional* file path. When `None`,
it should know to read from stdin.

First, here's the new usage:

```rust,ignore
fn print_usage(program: &str, opts: Options) {
println!("{}", opts.usage(&format!("Usage: {} [options] ", program)));
}
```
The next part is going to be only a little harder:

```rust,ignore
...
let mut opts = Options::new();
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
opts.optflag("h", "help", "Show this usage message.");
...
let file = matches.opt_str("f");
let data_file = file.as_ref().map(Path::new);

let city = if !matches.free.is_empty() {
matches.free[0].clone()
} else {
print_usage(&program, opts);
return;
};

for pop in search(&data_file, &city) {
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
}
...
```

In this peice of code, we take `file` (which has the type
`Option`), and convert it to a type that `search` can use, in
this case, `&Option>`. Do do this, we take a reference of
file, and map `Path::new` onto it. In this case, `as_ref()` converts
the `Option` into an `Option<&str>`, and from there, we can
execute `Path::new` to the content of the optional, and return the
optional of the new value. Once we have that, it is a simple matter of
getting the `city` argument and executing `search`.

Modifying `search` is slightly trickier. The `csv` crate can build a
parser out of
[any type that implements `io::Read`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.from_reader).
But how can we use the same code over both types? There's actually a
couple ways we could go about this. One way is to write `search` such
that it is generic on some type parameter `R` that satisfies
`io::Read`. Another way is to just use trait objects:

```rust,ignore
fn search>
(file_path: &Option

, city: &str)
-> Result, Box> {
let mut found = vec![];
let input: Box = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
let mut rdr = csv::Reader::from_reader(input);
// The rest remains unchanged!
}
```

## Error handling with a custom type

Previously, we learned how to
[compose errors using a custom error type](#composing-custom-error-types).
We did this by defining our error type as an `enum` and implementing `Error`
and `From`.

Since we have three distinct errors (IO, CSV parsing and not found), let's
define an `enum` with three variants:

```rust,ignore
#[derive(Debug)]
enum CliError {
Io(io::Error),
Csv(csv::Error),
NotFound,
}
```

And now for impls on `Display` and `Error`:

```rust,ignore
impl fmt::Display for CliError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CliError::Io(ref err) => err.fmt(f),
CliError::Csv(ref err) => err.fmt(f),
CliError::NotFound => write!(f, "No matching cities with a \
population were found."),
}
}
}

impl Error for CliError {
fn description(&self) -> &str {
match *self {
CliError::Io(ref err) => err.description(),
CliError::Csv(ref err) => err.description(),
CliError::NotFound => "not found",
}
}
}
```

Before we can use our `CliError` type in our `search` function, we need to
provide a couple `From` impls. How do we know which impls to provide? Well,
we'll need to convert from both `io::Error` and `csv::Error` to `CliError`.
Those are the only external errors, so we'll only need two `From` impls for
now:

```rust,ignore
impl From for CliError {
fn from(err: io::Error) -> CliError {
CliError::Io(err)
}
}

impl From for CliError {
fn from(err: csv::Error) -> CliError {
CliError::Csv(err)
}
}
```

The `From` impls are important because of how
[`try!` is defined](#code-try-def). In particular, if an error occurs,
`From::from` is called on the error, which in this case, will convert it to our
own error type `CliError`.

With the `From` impls done, we only need to make two small tweaks to our
`search` function: the return type and the “not found” error. Here it is in
full:

```rust,ignore
fn search>
(file_path: &Option

, city: &str)
-> Result, CliError> {
let mut found = vec![];
let input: Box = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
let mut rdr = csv::Reader::from_reader(input);
for row in rdr.decode::() {
let row = try!(row);
match row.population {
None => { } // skip it
Some(count) => if row.city == city {
found.push(PopulationCount {
city: row.city,
country: row.country,
count: count,
});
},
}
}
if found.is_empty() {
Err(CliError::NotFound)
} else {
Ok(found)
}
}
```

No other changes are necessary.

## Adding functionality

Writing generic code is great, because generalizing stuff is cool, and
it can then be useful later. But sometimes, the juice isn't worth the
squeeze. Look at what we just did in the previous step:

1. Defined a new error type.
2. Added impls for `Error`, `Display` and two for `From`.

The big downside here is that our program didn't improve a whole lot.
There is quite a bit of overhead to representing errors with `enum`s,
especially in short programs like this.

*One* useful aspect of using a custom error type like we've done here is that
the `main` function can now choose to handle errors differently. Previously,
with `Box`, it didn't have much of a choice: just print the message.
We're still doing that here, but what if we wanted to, say, add a `--quiet`
flag? The `--quiet` flag should silence any verbose output.

Right now, if the program doesn't find a match, it will output a message saying
so. This can be a little clumsy, especially if you intend for the program to
be used in shell scripts.

So let's start by adding the flags. Like before, we need to tweak the usage
string and add a flag to the Option variable. Once were done that, Getopts does the rest:

```rust,ignore
...
let mut opts = Options::new();
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
opts.optflag("h", "help", "Show this usage message.");
opts.optflag("q", "quit", "Silences errors and warnings.");
...
```

Now we just need to implement our “quiet” functionality. This requires us to
tweak the case analysis in `main`:

```rust,ignore
match search(&args.arg_data_path, &args.arg_city) {
Err(CliError::NotFound) if args.flag_quiet => process::exit(1),
Err(err) => fatal!("{}", err),
Ok(pops) => for pop in pops {
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
}
}
```

Certainly, we don't want to be quiet if there was an IO error or if the data
failed to parse. Therefore, we use case analysis to check if the error type is
`NotFound` *and* if `--quiet` has been enabled. If the search failed, we still
quit with an exit code (following `grep`'s convention).

If we had stuck with `Box`, then it would be pretty tricky to implement
the `--quiet` functionality.

This pretty much sums up our case study. From here, you should be ready to go
out into the world and write your own programs and libraries with proper error
handling.

# The Short Story

Since this chapter is long, it is useful to have a quick summary for error
handling in Rust. These are some good “rules of thumb." They are emphatically
*not* commandments. There are probably good reasons to break every one of these
heuristics!

* If you're writing short example code that would be overburdened by error
handling, it's probably just fine to use `unwrap` (whether that's
[`Result::unwrap`](../std/result/enum.Result.html#method.unwrap),
[`Option::unwrap`](../std/option/enum.Option.html#method.unwrap)
or preferably
[`Option::expect`](../std/option/enum.Option.html#method.expect)).
Consumers of your code should know to use proper error handling. (If they
don't, send them here!)
* If you're writing a quick 'n' dirty program, don't feel ashamed if you use
`unwrap`. Be warned: if it winds up in someone else's hands, don't be
surprised if they are agitated by poor error messages!
* If you're writing a quick 'n' dirty program and feel ashamed about panicking
anyway, then using either a `String` or a `Box` for your
error type (the `Box` type is because of the
[available `From` impls](../std/convert/trait.From.html)).
* Otherwise, in a program, define your own error types with appropriate
[`From`](../std/convert/trait.From.html)
and
[`Error`](../std/error/trait.Error.html)
impls to make the [`try!`](../std/macro.try!.html)
macro more ergnomic.
* If you're writing a library and your code can produce errors, define your own
error type and implement the
[`std::error::Error`](../std/error/trait.Error.html)
trait. Where appropriate, implement
[`From`](../std/convert/trait.From.html) to make both
your library code and the caller's code easier to write. (Because of Rust's
coherence rules, callers will not be able to impl `From` on your error type,
so your library should do it.)
* Learn the combinators defined on
[`Option`](../std/option/enum.Option.html)
and
[`Result`](../std/result/enum.Result.html).
Using them exclusively can be a bit tiring at times, but I've personally
found a healthy mix of `try!` and combinators to be quite appealing.
`and_then`, `map` and `unwrap_or` are my favorites.

[1]: ../book/patterns.html
[2]: ../std/option/enum.Option.html#method.map
[3]: ../std/option/enum.Option.html#method.unwrap_or
[4]: ../std/option/enum.Option.html#method.unwrap_or_else
[5]: ../std/option/enum.Option.html
[6]: ../std/result/
[7]: ../std/result/enum.Result.html#method.unwrap
[8]: ../std/fmt/trait.Debug.html
[9]: ../std/primitive.str.html#method.parse
[10]: ../book/associated-types.html
[11]: https://github.com/petewarden/dstkdata
[12]: http://burntsushi.net/stuff/worldcitiespop.csv.gz
[13]: http://burntsushi.net/stuff/uscitiespop.csv.gz
[14]: http://doc.crates.io/guide.html
[15]: http://doc.rust-lang.org/getopts/getopts/index.html

# 2. 시작하기(Getting Started) - 20%

이 책의 첫 번째 장을 통해 여러분은 Rust와 Rust에 관련된 도구들을 챙기게 될 거에요. 먼저 우리는 Rust를 설치할 것입니다. 그 다음은 전통적인 "안녕, 세상아_Hello, World_" 프로그램이죠. 마지막으로 Rust의 빌드 시스템이자 패키지 매니저인 Cargo에 대해서 이야기할 것입니다.

# Rust 설치하기

먼저 Rust를 사용하기 위해선 Rust를 설치해야 합니다. 우선 여러분이 이 장에서 소개된 명령어들을 실행하려면 인터넷에 연결되어 있어야 합니다.

이 책에서는 터미널에서 사용되는 몇 개의 명령어의 시작을 `$` 를 표시하여 강조할 것입니다.
하지만 `$` 는 해당 라인이 커맨드라는 사실을 나타낼 뿐이므로 실제로 입력하지 않아도 됩니다.
인터넷에 존재하는 많은 튜토리얼과 예제에서 `$` 는 보통 유저(일반적인 권한을 가진 유저)가 실행하는 커맨드들의 앞에 표시하고, `#`은 관리자(관리자 권한을 가진 유저)가 실행하는 명령어들 앞에 표시하는 관습이 있는데요, 이 책도 역시 그 관습을 따릅니다.


## 플랫폼 지원

'러스트' 는 수많은 플랫폼에서 컴파일되고 실행될 수 있습니다. 러스트가 지원하는 플랫폼들은 크게 세 가지로 나뉠 수 있습니다.


### 단계 1

1단계 플랫폼들은 쉽게 생각해서 '빌드가 가능하고 실행 가능한' 플랫폼입니다. 정확히는 아래의 요구사항을 만족하는 플랫폼입니다.

요구사항 -
- 테스트를 수행하기 위한 자동화가 되어 있음.
- `rustlang/rust` 저장소에 새로운 변경사항이 있을 때 테스트를 통과하는지 확인함.
- 플랫폼을 공식적으로 지원함.
- 해당 플랫폼에서 러스트를 빌드하고 사용하기위한 문서가 작성돼있음.


| 타겟 플랫폼 | std |rustc|cargo| 비고 |
|-------------------------------|-----|-----|-----|----------------------------|
| `x86_64-pc-windows-msvc` | ✓ | ✓ | ✓ | 64-bit MSVC (Windows 7+) |
| `i686-pc-windows-gnu` | ✓ | ✓ | ✓ | 32-bit MinGW (Windows 7+) |
| `x86_64-pc-windows-gnu` | ✓ | ✓ | ✓ | 64-bit MinGW (Windows 7+) |
| `i686-apple-darwin` | ✓ | ✓ | ✓ | 32-bit OSX (10.7+, Lion+) |
| `x86_64-apple-darwin` | ✓ | ✓ | ✓ | 64-bit OSX (10.7+, Lion+) |
| `i686-unknown-linux-gnu` | ✓ | ✓ | ✓ | 32-bit Linux (2.6.18+) |
| `x86_64-unknown-linux-gnu` | ✓ | ✓ | ✓ | 64-bit Linux (2.6.18+) |

### Tier 2

2단계 플랫폼들은 러스트 코드를 빌드할 수 있는 플랫폼입니다. 자동화된 테스트는 수행되지 않기 때문에 이 플랫폼에서 완벽한 작동은 보장할 순 없지만 꽤 잘 작동합니다. 이 플랫폼에 대한 패치는 언제나 환영합니다!

요구사항-
- 자동화된 테스트가 있지만 실행되지는 않을 수 있음.
- `rustlang/rust` 저장소의 master branch에 변경사항이 있을 때 **빌드**가 되는지 확인함. 어떤 플랫폼에서는 완벽히 작동하는 반면, 어떤 플랫폼에서는 빌드만 될 수 있음.
- 플랫폼을 공식적으로 지원함.


| 타겟 플랫폼 | std |rustc|cargo| 비고 |
|-------------------------------|-----|-----|-----|----------------------------|
| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) |

### 3단계

3단계 플랫폼들은 러스트를 지원하나, 최신 버전의 빌드와 검증 작업이 이루어지지 않은 플랫폼들을 말합니다. 이러한 플랫폼들을 개별 커뮤니티들에 의해 유지되는 경우가 많기 때문에 퀄리티가 보장되지 않을 수 있습니다. 포함 패키지들과 인스톨러가 공식적으로 제공되지 않지만 커뮤니티에 의해 지원 될 수도 있습니다.

| 타겟 플랫폼 | std |rustc|cargo| 비고 |
|-------------------------------|-----|-----|-----|----------------------------|
| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL |
| `arm-linux-androideabi` | ✓ | | | ARM Android |
| `i686-linux-android` | ✓ | | | 32-bit x86 Android |
| `aarch64-linux-android` | ✓ | | | ARM64 Android |
| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) |
| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) |
| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) |
| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) |
| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) |
| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) |
| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS |
| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS |
| `armv7-apple-ios` | ✓ | | | ARM iOS |
| `armv7s-apple-ios` | ✓ | | | ARM iOS |
| `aarch64-apple-ios` | ✓ | | | ARM64 iOS |
| `i686-unknown-freebsd` | ✓ | ✓ | | 32-bit FreeBSD |
| `x86_64-unknown-freebsd` | ✓ | ✓ | | 64-bit FreeBSD |
| `x86_64-unknown-openbsd` | ✓ | ✓ | | 64-bit OpenBSD |
| `x86_64-unknown-netbsd` | ✓ | ✓ | | 64-bit NetBSD |
| `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig |
| `x86_64-unknown-dragonfly` | ✓ | ✓ | | 64-bit DragonFlyBSD |
| `x86_64-rumprun-netbsd` | ✓ | | | 64-bit NetBSD Rump Kernel |
| `i686-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |
| `x86_64-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |

이 목록은 더 추가 될 수 있고, 여기 나열된 것들만 3단계 플랫폼이란 건 아닙니다!


## 리눅스와 맥에서의 러스트 설치

당신이 리눅스 또는 맥을 쓰고 있다면, 설치를 위해 할 것은 다음의 명령어를 터미널에 입력하는 것뿐입니다.

```bash
$ curl -sSf https://static.rust-lang.org/rustup.sh | sh
```

이것은 설치 스크립트를 다운로드하여 설치를 진행하게 해줄 것입니다. 그리고 이 작업이 모두 잘 진행된다면 다음의 메시지가 나타날 것입니다.

```text
Welcome to Rust.

This script will download the Rust compiler and its package manager, Cargo, and
install them to /usr/local. You may install elsewhere by running this script
with the --prefix= option.

The installer will run under ‘sudo’ and may ask you for your password. If you do
not want the script to run ‘sudo’ then pass it the --disable-sudo flag.

You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh,
or by running this script again with the --uninstall flag.

Continue? (y/N)
```

여기서 `y` (예)를 입력하고 편안히 설치를 기다리시면 됩니다.

## 윈도우에서의 러스트 설치

당신이 윈도우를 사용하고 있다면, 윈도우용 인스톨러를 받아서 사용해주세요 [installer][install-page].

[install-page]: https://www.rust-lang.org/install.html

## 러스트 제거

러스트를 제거하는 방법은 굉장히 쉽습니다. 리눅스와 맥에서 단지 언인스톨러 스크립트를 실행하기만 하면 됩니다.

```bash
$ sudo /usr/local/lib/rustlib/uninstall.sh
```

만약 당신이 윈도우의 편리한 인스톨러의 노예라면, 다시 `.msi`확장자를 가진 러스트 인스톨러를 다시 실행하여 제거 버튼을 누르면 됩니다.

## 문제 해결

러스트를 인스톨한 후 터미널을 열어 다음 명령어를 실행해 보십시오.

```bash
$ rustc --version
```

당신은 러스트의 버전과, 커밋 해쉬, 커밋 날짜를 볼 수 있어야 합니다.

그것이 성공하면 러스트는 성공적으로 인스톨 된 것입니다!

만약 당신이 윈도우를 사용하고, 위 작업이 실패했으면, 시스템 %PATH% 변수 안에 러스트 설치 경로가 들어있는지 확인하세요. 설치경로가 포함돼있지 않으면, 러스트를 설치한 폴더의 경로를 추가해주시길 바랍니다. _(어떻게 하는진 다들 아실 거라 믿습니다)_

불행하게도 윈도우 이외의 플랫폼에서 설치가 실패했다면, 도움을 받을 수 있는 곳이 있습니다. 가장 쉬운곳은 공식 [irc.mozilla.org의 #rust IRC 체널][irc] 입니다. IRC 클라이언트는 [Mibbit][mibbit] 을 사용하실 수 있습니다. 다른 곳으론, [사용자 포럼][users]과 [(우리들의 친구) Stack Overflow][stackoverflow]가 있습니다.

[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: https://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust

러스트 인스톨러는 자동적으로 공식 문서를 로컬에 저장해줍니다. 유닉스 기반 운영체제라면 `/usr/local/share/doc/rust`에, 윈도우 기반이라면 `(러스트 인스톨 경로)/share/doc`에서 찾을 수 있습니다.

# Hello, world!

이제 러스트를 설치했으니, 간단한 첫 프로그램을 만들어 봅시다. 암묵적인 세계적 프로그래머 전통을 따라서 우리는 작고 아름다운 _(모두가 아는.)_ 'Hello, world!' 프로그램을 만들어 볼 것입니다.

이러한 작은 프로그램을 만들어보는 건 컴파일러가 잘 작동하는지 확인할 수 있습니다. 그리고 화면에 문자를 출력하는 건 가장 일반적인 것들임으로 빨리해볼수록 좋죠.

> 참고: 이 문서는 기본적으로 터미널에서 작업하는 것을 전제로 쓰여있습니다. 러스트는 러스트자체의 코딩 툴이 없습니다. 하지만 러스트를 지원하는 [SolidOak][soak]라는 IDE가 존재합니다. 그리고 커뮤니티에는 사용자들이 개발한 수많은 확장기능들이 있고, 러스트 재단에서 [수많은 에디터][various editors]들을 위한 러스트 플러그인을 제공합니다. 당신이 사용하는 IDE나 에디터들의 설정은 이제부터 진행할 튜토리얼과는 조금 다른 모양과 설정을 가지고 있을 수 있습니다. 그러니 IDE나 추가 에디터를 사용할 경우 적절히 설정을 변경해서 사용해주십시오.

[soak]: https://github.com/oakes/SolidOak
[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md

## 프로젝트 파일 생성

첫째로, 러스트 코드를 만들어 봅시다. 러스트는 당신이 어디서 코드를 만들든 볶든 우리든 상관하지 않지만, 우리들은 새로운 프로젝트 폴더를 당신의 홈디렉터리에 생성할 것을 권장합니다. 다음의 명령어들은 간단히 프로젝트 폴더를 생성하는 법을 소개합니다.

```bash
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
```

> 참고: 당신이 윈도우에서 파워셀이 아닌 명령프롬포트를 사용하고 있다면, `~`문자는 작동하지 않을 것입니다.

## 러스트 프로그램을 작성하고 실행하기

다음으로, 새로운 소스 파일을 만들고 *main.rs*로 이름을 작성해주십시오. 러스트 소스 파일은 항상 *.rs*를 확장자로 가집니다. 만약 당신의 파일 이름에 한 단어 이상 사용했다면, 스페이스 대신 밑줄문자 *_* 를 사용해주십시오. 예로, *wonderful rust language.rs* 를 *wonderful_rust_language.rs* 로 작성해주십시오.

이제 *main.rs*파일을 열어서 다음의 코드를 입력해봅시다.

```rust
fn main() {
println!("Hello, world!");
}
```

파일을 빌드하기 위해서는 터미널로 일단 돌아갑니다. 당신이 리눅스와 맥을 사용하고 있다면 다음 명령어들을 실행해주세요.

```bash
$ rustc main.rs
$ ./main
Hello, world!
```

당신의 운영체제가 윈도우라면, 위 명령어 중에서 그저 `main` 을 `main.exe`로 바꾸면 됩니다. 그리고 빌드 후에는 당신의 운영체제와 상관없이 터미널에 `Hello, world!` 가 출력될 것입니다. 이것이 성공했다면, 이 텍스트는 당신이 첫 러스트로 출력한 텍스트가 된 것입니다! 러스트의 세계로 오신 당신을 정말 환영합니다!

## 간단한 러스트 문법

지금부터, 방금 작성한 "Hello, world" 프로그램에 대해 자세하게 설명하도록 하겠습니다. 그럼 첫 줄부터 보시죠.

```rust
fn main() {

}
```

이 코드 라인들은 러스트에서의 *함수*를 정의하고 있습니다. 이 `main`함수는 특별합니다: 이 함수는 모든 러스트 프로그램의 시작점입니다. 코드의 첫 줄은 "난 이름이 `main`이고 아무 매개변수도 필요로 하지 않으며 아무것도 리턴하지 않는 함수를 정의하고 있어요" 라고 말하고 있습니다. 만약 매개변수가 있다면 소괄호 기호`(` 와 `)` 사이로 들어가면 됩니다. 그리고 우리는 이 함수에서 아무것도 리턴을 하지 않을 것이니까, 우리는 리턴타입을 통째로 생략할 수 있습니다.

또한 함수 본문은 중괄호 `{` 와 `}`로 쌓여있습니다. 러스트는 모든 함수의 몸체를 중괄호로 둘러싸는 것을 요구합니다. 함수 선언과 같은 줄에 한 칸의 스페이스를 두고 중괄호를 여는 것이 좋은 코드 스타일이라 여겨집니다.

`main()` 함수 안에서:

```rust
println!("Hello, world!");
```

This line does all of the work in this little program: it prints text to the
screen. There are a number of details that are important here. The first is
that it’s indented with four spaces, not tabs.

The second important part is the `println!()` line. This is calling a Rust
*[macro]*, which is how metaprogramming is done in Rust. If it were calling a
function instead, it would look like this: `println()` (without the !). We'll
discuss Rust macros in more detail later, but for now you just need to
know that when you see a `!` that means that you’re calling a macro instead of
a normal function.

[macro]: macros.html

Next is `"Hello, world!"` which is a *string*. Strings are a surprisingly
complicated topic in a systems programming language, and this is a *[statically
allocated]* string. We pass this string as an argument to `println!`, which
prints the string to the screen. Easy enough!

[statically allocated]: the-stack-and-the-heap.html

The line ends with a semicolon (`;`). Rust is an *[expression oriented]*
language, which means that most things are expressions, rather than statements.
The `;` indicates that this expression is over, and the next one is ready to
begin. Most lines of Rust code end with a `;`.

[expression-oriented language]: glossary.html#expression-oriented-language

## 컴파일과 실행은 다른 단계로 이루어짐

In "Writing and Running a Rust Program", we showed you how to run a newly
created program. We'll break that process down and examine each step now.

Before running a Rust program, you have to compile it. You can use the Rust
compiler by entering the `rustc` command and passing it the name of your source
file, like this:

```bash
$ rustc main.rs
```

If you come from a C or C++ background, you'll notice that this is similar to
`gcc` or `clang`. After compiling successfully, Rust should output a binary
executable, which you can see on Linux or OSX by entering the `ls` command in
your shell as follows:
이 줄에서 이 작은 프로그램이 하는 모든 일이 실행됩니다: 화면에 텍스트를 띄우는 일이요. 이 한 줄에는 주목할 점이 꽤 많습니다. 그 중 첫번째는, 들여쓰기가 탭이 아니라 스페이스 네 개로 되어 있다는 점입니다.

두번째 주목해야 할 것은 `println!()` 부분입니다. 이것은 러스트의 *[매크로]*라고 부르는데 이걸로 러스트에서 메타프로그래밍을 합니다. 만약 이것 대신 함수를 호출하려 했다면`println()`(!가 없습니다)라고 썼겠죠. 러스트의 매크로에 관해서는 나중에 좀더 자세히 다루겠지만, `!`가 붙으면 그건 그냥 함수가 아니라 매크로라는 점은 알아두세요.

[매크로]: macros.html

다음은 *string*인 `"Hello, world!"` 부분입니다. string은 시스템 프로그래밍 언어에서 무척이나 복잡한 부분인데, 이것은 *[정적으로 할당된]* string입니다. 이 string을 `println!`에 인자로 전달하면 `println!()`이 받은 string을 화면에 띄워줍니다. 쉽죠?

[정적으로 할당된]: the-stack-and-the-heap.html

다음 줄은 세미콜론(`;`)으로 끝납니다. 러스트는 대부분의 것들이 문(statement)보다 식(expression)인 *[표현식 지향]*적인 언어입니다. `;`는 표현식이 끝났고 다음 표현식이 시작할 준비가 되었다는 것을 가리킵니다. 러스트 코드의 대부분의 줄은 `;`로 끝납니다.

[표현식 지향]: glossary.html#expression-oriented-language

## 컴파일과 실행은 다른 단계로 이루어짐

"러스트 프로그램을 작성하고 실행하기"에서 갓 만든 프로그램을 실행해보았습니다. 이제 각각의 단계들을 하나씩 파헤쳐봅시다.

러스트 프로그램을 실행하기 전에 먼저 컴파일을 해야 합니다. 명령어 `rustc` 뒤에 소스파일의 이름을 입력하면 러스트 컴파일러를 사용할 수 있습니다. 이렇게요.

```bash
$ rustc main.rs
```

C나 C++을 배웠다면 `gcc`나 `clang`이랑 비슷하게 느껴질 것입니다. 성공적으로 컴파일을 했으면 러스트는 바이너리 실행파일을 결과물로 내놓을 것입니다. Linux나 OSX의 셸에서 `ls` 명령으로 보면 이렇게 보입니다.


```bash
$ ls
main main.rs
```

On Windows, you'd enter:윈도우에서는 이렇게 보입니다.

```bash
$ dir
main.exe main.rs
```

This shows we have two files: the source code, with an `.rs` extension, and the
executable (`main.exe` on Windows, `main` everywhere else). All that's left to
do from here is run the `main` or `main.exe` file, like this:

```bash
$ ./main # or main.exe on Windows
```

If *main.rs* were your "Hello, world!" program, this would print `Hello,
world!` to your terminal.

If you come from a dynamic language like Ruby, Python, or JavaScript, you may
not be used to compiling and running a program being separate steps. Rust is an
*ahead-of-time compiled* language, which means that you can compile a program,
give it to someone else, and they can run it even without Rust installed. If
you give someone a `.rb` or `.py` or `.js` file, on the other hand, they need
to have a Ruby, Python, or JavaScript implementation installed (respectively),
but you only need one command to both compile and run your program. Everything
is a tradeoff in language design.

Just compiling with `rustc` is fine for simple programs, but as your project
grows, you'll want to be able to manage all of the options your project has,
and make it easy to share your code with other people and projects. Next, I'll
introduce you to a tool called Cargo, which will help you write real-world Rust
programs.

# Hello, Cargo!

Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to
manage their Rust projects. Cargo manages three things: building your code,
downloading the libraries your code depends on, and building those libraries.
We call libraries your code needs ‘dependencies’ since your code depends on
them.

The simplest Rust programs don’t have any dependencies, so right now, you'd
only use the first part of its functionality. As you write more complex Rust
programs, you’ll want to add dependencies, and if you start off using Cargo,
that will be a lot easier to do.

As the vast, vast majority of Rust projects use Cargo, we will assume that
you’re using it for the rest of the book. Cargo comes installed with Rust
itself, if you used the official installers. If you installed Rust through some
other means, you can check if you have Cargo installed by typing:

```bash
$ cargo --version
```

Into a terminal. If you see a version number, great! If you see an error like
‘`command not found`’, then you should look at the documentation for the system
in which you installed Rust, to determine if Cargo is separate.

## Cargo로 변환하기

이제 Hello World 프로그램을 Cargo로 변환 해봅시다. Cargo 프로젝트로 만들기 위해서 필요한 것들은 다음에 나열했습니다.

1. 당신의 소스를 정확한 폴더에 집어넣어 주십시오.
2. 이전에 만든 실행 파일을 지워 주십시오. _(윈도우라면 `main.exe`을, 다른 운영체제라면 `main` 을 지워 주시면 됩니다)_
3. Cargo 설정 파일을 생성합니다.

자, 시작해봅시다!

### 새로운 실행 파일과 소스 폴더를 생성하기

앞서, 터미널로 돌아가서 당신의 *hello_world* _(프로젝트 폴더)_ 폴더로 이동합니다. 그리고 다음의 명령어들을 실행합니다.

```bash
$ mkdir src
$ mv main.rs src/main.rs
$ rm main # or 'del main.exe' on Windows
```

Cargo expects your source files to live inside a *src* directory, so do that
first. This leaves the top-level project directory (in this case,
*hello_world*) for READMEs, license information, and anything else not related
to your code. In this way, using Cargo helps you keep your projects nice and
tidy. There's a place for everything, and everything is in its place.

Now, copy *main.rs* to the *src* directory, and delete the compiled file you
created with `rustc`. As usual, replace `main` with `main.exe` if you're on
Windows.

This example retains `main.rs` as the source filename because it's creating an
executable. If you wanted to make a library instead, you'd name the file
`lib.rs`. This convention is used by Cargo to successfully compile your
projects, but it can be overridden if you wish.

### 설정 파일 생성하기

Next, create a new file inside your *hello_world* directory, and call it
`Cargo.toml`.

Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do
with the configuration file.

This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is
similar to INI, but has some extra goodies, and is used as Cargo’s
configuration format.

[TOML]: https://github.com/toml-lang/toml

이 파일을 대신해서, 다음의 것들을 입력해주세요.

```toml
[package]

name = "hello_world"
version = "0.0.1"
authors = [ "Your name " ]
```

The first line, `[package]`, indicates that the following statements are
configuring a package. As we add more information to this file, we’ll add other
sections, but for now, we just have the package configuration.

The other three lines set the three bits of configuration that Cargo needs to
know to compile your program: its name, what version it is, and who wrote it.

Once you've added this information to the *Cargo.toml* file, save it to finish
creating the configuration file.

## Cargo프로젝트를 빌드하고 실행하기

With your *Cargo.toml* file in place in your project's root directory, you
should be ready to build and run your Hello World program! To do so, enter the
following commands:

```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
$ ./target/debug/hello_world
Hello, world!
```

모두 잘 작동했다면, `Hello, world!`라는 문자열이 당신의 터미널에 출력될 것입니다.

당신은 방금 `cargo build` 명령어로 프로젝트를 빌드했고,
빌드한 결과물은 `./target/debug/hello_world`에 있을 것입니다. 하지만 사실 빌드한 후 빌드한 결과물을 확인, 실행하는 것은 `cargo run` 명령어로 간단히 할 수 있습니다.

```bash
$ cargo run
Running `target/debug/hello_world`
Hello, world!
```

Notice that this example didn’t re-build the project. Cargo figured out that
the file hasn’t changed, and so it just ran the binary. If you'd modified your
source code, Cargo would have rebuilt the project before running it, and you
would have seen something like this:

```bash
$ cargo run
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
Running `target/debug/hello_world`
Hello, world!
```

Cargo는 자동으로 어느 프로젝트 파일이 수정되었는지 확인하고, 수정된 코드만 다시 빌드합니다.

With simple projects, Cargo doesn't bring a whole lot over just using `rustc`,
but it will become useful in future. With complex projects composed of multiple
crates, it’s much easier to let Cargo coordinate the build. With Cargo, you can
just run `cargo build`, and it should work the right way.

## 프로그램 릴리즈

When your project is finally ready for release, you can use `cargo build
--release` to compile your project with optimizations. These optimizations make
your Rust code run faster, but turning them on makes your program take longer
to compile. This is why there are two different profiles, one for development,
and one for building the final program you’ll give to a user.

Running this command also causes Cargo to create a new file called
*Cargo.lock*, which looks like this:

```toml
[root]
name = "hello_world"
version = "0.0.1"
```

Cargo uses the *Cargo.lock* file to keep track of dependencies in your
application. This is the Hello World project's *Cargo.lock* file. This project
doesn't have dependencies, so the file is a bit sparse. Realistically, you
won't ever need to touch this file yourself; just let Cargo handle it.

That’s it! If you've been following along, you should have successfully built
`hello_world` with Cargo.

Even though the project is simple, it now uses much of the real tooling you’ll
use for the rest of your Rust career. In fact, you can expect to start
virtually all Rust projects with some variation on the following commands:

```bash
$ git clone someurl.com/foo
$ cd foo
$ cargo build
```

## 무작정 따라하는 Cargo프로젝트 만들기

앞의 길고 긴 방법은 너무나도 번거롭습니다. _당신도 공감하리라 믿습니다._ 하지만 사실, 당신은 앞서 보여드린 번거롭디번거로운 과정을 매 새 프로젝트를 시작 할 때마다 하지 않아도 됩니다. Cargo는 쉽고 빠르게 당신이 정확하게 개발을 시작할 수 있도록 프로젝트 폴더를 구성해줍니다.

새 Cargo 프로젝트를 생성하려면, `cargo new`명령어를 실행하시면 됩니다.

```bash
$ cargo new hello_world --bin
```

This command passes `--bin` because the goal is to get straight to making an
executable application, as opposed to a library. Executables are often called
*binaries* (as in `/usr/bin`, if you’re on a Unix system).

Cargo has generated two files and one directory for us: a `Cargo.toml` and a
*src* directory with a *main.rs* file inside. These should look familliar,
they’re exactly what we created by hand, above.

This output is all you need to get started. First, open `Cargo.toml`. It should
look something like this:

```toml
[package]

name = "hello_world"
version = "0.1.0"
authors = ["Your Name "]
```

Cargo has populated *Cargo.toml* with reasonable defaults based on the arguments
you gave it and your `git` global configuration. You may notice that Cargo has
also initialized the `hello_world` directory as a `git` repository
두 파일이 있는데, 하나는 `.rs` 확장자를 갖는 소스코드이고, 다른 하나가 실행파일입니다(윈도우에서는 `main.exe`, 다른 데서는 `main`). 이제 `main`이나 `main.exe` 파일을 실행하기만 하면 됩니다. 이렇게요.

```bash
$ ./main # or main.exe on Windows
```

*main.rs*가 "Hello, world!" 프로그램이면 터미널에 `Hello, world`를 띄울 겁니다.

루비나 파이썬, 자바스크립트같은 동적 언어를 배웠다면 컴파일과 실행과정이 분리되어 있는 것에 익숙치 않을 지도 모릅니다. 러스트는 *AOT 컴파일* 언어입니다. 그렇기 때문에 프로그램을 컴파일해서 누군가에게 주면 그 사람은 러스트가 깔려있지 않아도 그 프로그램을 실행할 수 있습니다. 만약에 `.rb`, `.py`, `.js` 파일을 준다면 각각 루비, 파이썬, 자바스크립트가 깔려있어야 실행할 수 있겠죠. 대신 컴파일하고 실행을 동시에 한 명령어로 수행할 수 있습니다. 프로그래밍 언어 디자인에서 모든 것은 등가교환입니다.

간단한 프로그램일때는 `rustc`로 그냥 컴파일하는 것이 편하지만 프로젝트가 커지면 프로젝트의 옵션들을 관리하고 소스를 관리하는 것을 좀더 쉽게 하고싶어질 것입니다. 이제, 진짜 러스트 프로그램을 쓰는 것을 도와줄 Cargo를 소개합니다.

# Hello, Cargo!

카고는 러스트의 빌드 시스템이자 패키지 매니저입니다. 러스트인들은 그들의 러스트 프로젝트를 관리하는데 카고를 사용합니다. 카고는 다음 세가지를 관리해줍니다. 코드를 빌드하고, 의존성이 있는 라이브러리를 다운로드하고, 그 라이브러리를 빌드합니다. 코드가 호출하고 있는 라이브러리를 '의존성'이라고 합니다. 코드가 거기에 의존하고 있으니까요.

가장 간단한 러스트 프로그램은 의존성이 없기 때문에 바로 함수를 작성하면 됩니다. 좀더 정교한 러스트 프로그램을 짜기 시작하면 의존성을 더하게 될텐데 이때 카고를 사용하면 훨씬 쉬워집니다.

거의 대부분의 러스트 프로젝트는 카고를 사용하고, 아마 이 책의 나머지 부분에서도 쭉 사용할 것입니다. 러스트 공식 인스톨러를 사용했다면 러스트와 함께 카고도 깔렸을 것입니다. 러스트를 다른 방법으로 설치했다면 이렇게 터미널에 쳐서 카고가 깔려있는지 체크해야 합니다.

```bash
$ cargo --version
```

버전이 보이면, 좋습니다! '`command not found`' 따위의 에러가 보이면, 러스트가 설치된 시스템의 매뉴얼을 보고 카고가 빠져있는지 확인해야 합니다.

## Cargo로 변환하기

이제 Hello World 프로그램을 Cargo로 변환 해봅시다. Cargo 프로젝트로 만들기 위해서 필요한 것들은 다음에 나열했습니다.

1. 당신의 소스를 정확한 폴더에 집어넣어 주십시오.
2. 이전에 만든 실행 파일을 지워 주십시오. _(윈도우라면 `main.exe`을, 다른 운영체제라면 `main` 을 지워 주시면 됩니다)_
3. Cargo 설정 파일을 생성합니다.

자, 시작해봅시다!

### 새로운 실행 파일과 소스 폴더를 생성하기

앞서, 터미널로 돌아가서 당신의 *hello_world* _(프로젝트 폴더)_ 폴더로 이동합니다. 그리고 다음의 명령어들을 실행합니다.

```bash
$ mkdir src
$ mv main.rs src/main.rs
$ rm main # or 'del main.exe' on Windows
```

카고는 소스파일들이 *src* 디렉터리에 있을 것이라 전제하기 때문에 먼저 그것부터 해결해야 합니다. 프로젝트의 최상위 디렉터리에는(이 경우는 *hello_world*) README, 라이센스 정보, 기타 코드랑 관련없는 것들만 남겨둡니다. 이렇게 해서 카고는 프로젝트를 깔끔하게 유지하는걸 도와줍니다. 만물에는 제자리가 있는 법이니까요.

이제 *main.rs* 파일을 *src* 디렉터리로 복사하고, `rustc` 명령어로 컴파일된 파일을 삭제합니다. 물론 윈도우에서는 `main`이 아니라 `main.exe`입니다.

이 예제에서는 실행파일을 만들기 때문에 소스파일 이름을 `main.rs`로 그대로 두었습니다. 실행파일이 아니라 라이브러리를 만들때는 파일 이름을 `lib.rs`로 해야 합니다. 이 전통은 카고가 성공적으로 컴파일하는데 사용되지만 원한다면 바꿀 수도 있습니다.

### 설정 파일 생성하기

다음에는 *hello_world* 디렉터리에 새 파일을 만들고 이름을 이렇게 짓습니다.
`Cargo.toml`.

`Cargo.toml` 안의 `C`가 대문자임에 주의하세요. 안그러면 카고가 설정파일을 인식하지 못합니다.

이 파일은 *[TOML]* 형식을 따릅니다. TOML은 INI와 비슷하지만 몇가지 장점이 있어서 카고의 설정 파일 형식으로 사용됩니다.

[TOML]: https://github.com/toml-lang/toml

이 파일을 대신해서, 다음의 것들을 입력해주세요.

```toml
[package]

name = "hello_world"
version = "0.0.1"
authors = [ "Your name " ]
```

첫째줄에서 `[package]`는 다음 구문들이 패키지의 설정이라는 것을 알려줍니다. 이 파일에 뭔가 다른 정보를 더하면 다른 섹션을 사용하게 되겠지만 지금은 그냥 패키지 설정 뿐입니다.

나머지 세 줄은 카고가 프로그램을 컴파일하는데 필요한 정보를 알려줍니다. 이름, 버전정보, 그리고 쓴 사람을요.

이 정보들을 *Cargo.toml* 파일에 쓰고 나면 저장해서 설정을 마치세요.

## Cargo프로젝트를 빌드하고 실행하기

*Cargo.toml* 파일이 프로젝트 루트 디렉터리에 있으면 Hello World 프로그램을 빌드하고 실행할 준비가 된겁니다! 그렇게 하려면 다음 명령어를 치세요.

```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
$ ./target/debug/hello_world
Hello, world!
```

모두 잘 작동했다면, `Hello, world!`라는 문자열이 당신의 터미널에 출력될 것입니다.

당신은 방금 `cargo build` 명령어로 프로젝트를 빌드했고,
빌드한 결과물은 `./target/debug/hello_world`에 있을 것입니다. 하지만 사실 빌드한 후 빌드한 결과물을 확인, 실행하는 것은 `cargo run` 명령어로 간단히 할 수 있습니다.

```bash
$ cargo run
Running `target/debug/hello_world`
Hello, world!
```

이 예제가 프로젝트를 다시 빌드하지 않았다는 사실을 주목해주세요. 카고는 파일이 바뀌지 않았다는 것을 알아차리고는 그냥 바이너리를 실행했습니다. 만약 소스코드를 바꿨다면 카고는 실행하기 전에 프로젝트를 리빌드할거고 다음과 같은 메시지가 뜰 것입니다.

```bash
$ cargo run
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
Running `target/debug/hello_world`
Hello, world!
```

Cargo는 자동으로 어느 프로젝트 파일이 수정되었는지 확인하고, 수정된 코드만 다시 빌드합니다.

간단한 프로젝트에서 카고는 단순히 `rustc`를 여러 번 실행할 뿐입니다. 하지만 나중에는 유용하게 쓰일겁니다. 여러 개의 크레이트가 있는 복잡한 프로젝트는 카고가 빌드를 관리하게 냅두는게 훨씬 쉽습니다. 카고가 있으면 그냥 `cargo build`만 실행시키면 제대로 작동할 것입니다.

## 프로그램 릴리즈

프로그램이 마침내 배포될 때가 오면 프로젝트를 최적화 옵션을 켜고 컴파일하기 위해 `cargo build --release` 명령어를 칩니다. 이 최적화는 러스트 코드의 속도를 향상시키지만 이것을 켜 놓으면 컴파일이 더 오래걸립니다. 그렇기 때문에 개발을 위한 컴파일과 배포를 위한 컴파일이 따로 있는 것입니다.

이 명령어를 실행시키는 것은 또한 *Cargo.lock*이라는 새로운 파일을 만듭니다. 그 내용은 다음과 같습니다.

```toml
[root]
name = "hello_world"
version = "0.0.1"
```

카고는 *Cargo.lock* 파일을 애플리케이션의 의존성을 추적하는데 사용합니다. 이게 Hello World 프로젝트의 *Cargo.lock* 파일입니다. 이 프로젝트는 의존성이 없기 때문에 파일이 텅 비어있습니다. 현실적으로 이 파일을 직접 만질 필요는 거의 없습니다. 그냥 카고가 작성하도록 냅두세요.

이게 답니다! 잘 따라왔다면 성공적으로 `hello_world`를 카고로 빌드할 수 있을 겁니다.

이 프로젝트는 무척 간단하지만 러스트 인생에서 사용할 툴의 대부분을 사용하고 있습니다. 사실상 대부분의 러스트 프로젝트를 시작할 때는 다음 명령어를 약간씩만 바꾼다고 볼 수 있습니다.

```bash
$ git clone someurl.com/foo
$ cd foo
$ cargo build
```

## 무작정 따라하는 Cargo프로젝트 만들기

앞의 길고 긴 방법은 너무나도 번거롭습니다. _당신도 공감하리라 믿습니다._ 하지만 사실, 당신은 앞서 보여드린 번거롭디번거로운 과정을 매 새 프로젝트를 시작 할 때마다 하지 않아도 됩니다. Cargo는 쉽고 빠르게 당신이 정확하게 개발을 시작할 수 있도록 프로젝트 폴더를 구성해줍니다.

새 Cargo 프로젝트를 생성하려면, `cargo new`명령어를 실행하면 됩니다.

```bash
$ cargo new hello_world --bin
```

이 프로젝트는 라이브러리가 아니라 실행 프로그램을 만들 것이기 때문에 `--bin` 옵션을 붙였습니다. 실행파일은 *바이너리*라고도 불립니다(유닉스 시스템의 `/usr/bin` 안에 있는 것처럼).

카고는 두 개의 파일과 하나의 디렉터리를 만들었습니다. `Cargo.toml` 파일과 *src* 디렉터리, 그리고 그 안에 들어있는 *main.rs* 파일입니다. 이것들이 익숙해보인다면, 우리가 방금 전 위에서 직접 만들었으니까 당연합니다.

이 결과물이 시작할 때 필요한 전부입니다. 먼저 `Cargo.toml` 파일을 열면 이렇게 되어있을 것입니다.

```toml
[package]

name = "hello_world"
version = "0.1.0"
authors = ["Your Name "]
```

카고는 *Cargo.toml*에 주어진 조건에 맞는 디폴트들과 `git` 전역 설정을 작성했을 것입니다. 카고는 또한 `hello_world` 디렉터리를 만들 때 `git` 레포지터리를 시작합니다
.

`src/main.rs`에는 다음의 코드가 작성돼 있을 것입니다:

```rust
fn main() {
println!("Hello, world!");
}
```

Cargo는 당신을 위해서 "Hello world!"를 먼저 생성해 둘 것입니다. 이제 당신이 코딩할 차례입니다!

> 참고: Cargo에 대해 더 궁금하다면, 공식 [Cargo 문서][Cargo guide]를 참고 하시면 좋습니다.

[Cargo guide]: http://doc.crates.io/guide.html

# 마치며

이 챕터는 기본적으로 당신의 러스트와 함께하는 시간이 목적입니다. 자, 이제 당신은 충분히 러스트와 함께 쉬고 대화했으니, 이젠 러스트가 말할 차례입니다.

당신은 두 가지 선택지가 있습니다. 바로 [러스트와 함께하는 새로운 프로젝트][learnrust]를 시작하거나, 처음부터 [러스트의 문법][syntax]을 배우며 입문하는 것입니다. 많은 경험자들 _(사실 거의 모든 이 문서의 독자들)_ 러스트와 함께하는 새로운 프로젝트를 선호할 것입니다. 뭐 사정 다른 사람은 다른 선택지를 선택하게 되겠죠! 뭐, 저에게 당신이 무엇을 아는지 모르는지가 중요한가요. 당신이 원하는 대로 하시면 됩니다.

[learnrust]: learn-rust.html
[syntax]: syntax-and-semantics.html