diff --git a/second-edition/src/ch03-01-variables-and-mutability.md b/second-edition/src/ch03-01-variables-and-mutability.md index ef1750d8a5..b6971765da 100644 --- a/second-edition/src/ch03-01-variables-and-mutability.md +++ b/second-edition/src/ch03-01-variables-and-mutability.md @@ -1,17 +1,13 @@ -## Variables and Mutability +## 변수와 가변성 -As mentioned in Chapter 2, by default variables are *immutable*. This is one of -many nudges in Rust that encourages you to write your code in a way that takes -advantage of the safety and easy concurrency that Rust offers. However, you -still have the option to make your variables mutable. Let’s explore how and why -Rust encourages you to favor immutability, and why you might want to opt out. +2 장에서 언급했듯이, 기본 변수는 *불변성* 입니다. 이것은 Rust가 제공하는 안전성과 손쉬운 동시성이라는 장점을 +취할 수 있도록 코드를 작성하게끔 강제하는 요소 중 하나 입니다. 하지만 여전히 당신은 가변 변수를 사용하고 싶을테죠. +어떻게 그리고 왜 Rust에서 불변성을 애호해주길 권장하는지 알아보면 그런 생각을 포기할 수 있을지도 모르겠습니다. -When a variable is immutable, that means once a value is bound to a name, you -can’t change that value. To illustrate, let’s generate a new project called -*variables* in your *projects* directory by using `cargo new --bin variables`. - -Then, in your new *variables* directory, open *src/main.rs* and replace its -code with the following: +변수가 불변성인 경우, 일단 값이 이름에 bound되면 해당 값을 변경할 수 없습니다. 시험 삼아 +`cargo new --bin variables`을 실행해서 * projects * 디렉토리에 * variables *라는 새 프로젝트를 +생성 해 봅시다. 그런 다음 새 * variables * 디렉토리에서 * src / main.rs *를 열고 코드를 다음과 같이 +바꿉니다. Filename: src/main.rs @@ -24,8 +20,7 @@ fn main() { } ``` -Save and run the program using `cargo run`. You should receive an error -message, as shown in this output: +저장하고 `cargo run` 명령을 통해 실행시켜 봅시다. 당신은 다음과 같이 출력되는 에러를 확인하게 될 겁니다. ```text error[E0384]: re-assignment of immutable variable `x` @@ -38,34 +33,26 @@ error[E0384]: re-assignment of immutable variable `x` | ^^^^^ re-assignment of immutable variable ``` -This example shows how the compiler helps you find errors in your programs. -Even though compiler errors can be frustrating, they only mean your program -isn’t safely doing what you want it to do yet; they do *not* mean that you’re -not a good programmer! Experienced Rustaceans still get compiler errors. The -error indicates that the cause of the error is `re-assignment of immutable -variable`, because we tried to assign a second value to the immutable `x` -variable. - -It’s important that we get compile-time errors when we attempt to change a -value that we previously designated as immutable because this very situation -can lead to bugs. If one part of our code operates on the assumption that a -value will never change and another part of our code changes that value, it’s -possible that the first part of the code won’t do what it was designed to do. -This cause of bugs can be difficult to track down after the fact, especially -when the second piece of code changes the value only *sometimes*. - -In Rust the compiler guarantees that when we state that a value won’t change, -it really won’t change. That means that when you’re reading and writing code, -you don’t have to keep track of how and where a value might change, which can -make code easier to reason about. - -But mutability can be very useful. Variables are immutable only by default; we -can make them mutable by adding `mut` in front of the variable name. In -addition to allowing this value to change, it conveys intent to future readers -of the code by indicating that other parts of the code will be changing this -variable value. - -For example, change *src/main.rs* to the following: +위의 예제는 컴파일러가 당신이 만든 프로그램에서 당신을 도와 에러를 찾아주는 방법에 대해 보여주고 있습니다. +컴파일러 에러가 힘빠지게 만들 수도 있지만, 단지 당신의 프로그램이 아직 안전하게 수행되긴 미흡하다는 뜻이지, +당신의 소양이 부족함을 의미하는건 아닙니다. 숙련된 Rustacean들도 여전히 에러를 발생시키니까요. 에러가 +나타내는 것은 `불변성 변수에 재할당`이고, 원인은 우리가 불변성 변수 `x`에 두 번째로 값을 할당했기 때문입니다. + +우리가 이전에 불변성으로 선언한 것의 값을 변경하고자 하는 시도를 하면 컴파일 타임의 에러를 얻게 되고 이로 인해 +버그가 발생할 수 있기 때문에 중요합니다. 만약 우리 코드의 일부는 값이 변경되지 않는다는 것을 가정하는데 다른 코드는 +이와 다르게 값을 변경한다면, 전자에 해당하는 코드는 우리가 의도한 대로 수행되지 않을 수 있습니다. 특히 후자에 +해당되는 코드가 항상 그렇지 않고 *가끔* 값을 변경하는 경우 나중에 버그의 원인을 추적하기가 매우 어렵습니다. + +Rust에서는 컴파일러가 변경되지 않은 값에 대한 보증을 해주고, 실제로 이는 바뀌지 않습니다. 이것이 의미하는 +바는 당신이 코드를 작성하거나 분석할 시에 변수의 값이 어떻게 변경되는지 추적할 필요가 없기 때문에 코드를 더 +합리적으로 만들어줍니다. + +하지만 가변성은 매우 유용하게 사용될 수 있습니다. 변수는 기본적으로 불변성이지만 우리는 변수명의 접두어로 +`mut`을 추가하는 것을 통해 가변성 변수를 선언할 수 있습니다. 이 변수의 값이 변경을 허용하는 것에 추가로 +향후 코드를 보는 사람에게 코드의 다른 부분에서 해당 변수의 값을 변경할 것이라는 의도를 주지시킵니다. + +예를 들어, *src/main.rs*를 다음과 같이 변경해보도록 합니다. + Filename: src/main.rs @@ -78,7 +65,7 @@ fn main() { } ``` -When we run this program, we get the following: +위의 프로그램을 수행하면 다음과 같은 결과를 얻게 됩니다: ```text $ cargo run @@ -88,68 +75,55 @@ The value of x is: 5 The value of x is: 6 ``` -Using `mut`, we’re allowed to change the value that `x` binds to from `5` to -`6`. In some cases, you’ll want to make a variable mutable because it makes the -code more convenient to write than an implementation that only uses immutable -variables. +`mut`를 사용하여, `x`에 bind된 값을 `5`에서 `6`으로 변경할 수 있습니다. 불변성 변수만을 사용하는 것보다 +가변성 변수를 사용하여 보다 쉽게 구현할 수 있을 경우 가변성 변수를 만들어 사용할 수도 있습니다. + +이런 의사 결정에 있어서 버그를 예방하는 것 외에도 고려해야 할 요소들이 있습니다. 예를 들어, 대규모 데이터 구조체를 +다루는 경우 가변한 인스턴스를 사용하는 것이 새로 인스턴스를 할당하고 반환하는 것보다 빠를 수 있습니다. 데이터 규모가 +작을수록 새 인스턴스를 생성하고 함수적 프로그래밍 스타일로 작성하는 것이 더 합리적이고, 그렇기에 약간의 성능 하락을 +통해 가독성을 확보할 수 있다면 더 가치있는 선택입니다. -There are multiple trade-offs to consider, in addition to the prevention of -bugs. For example, in cases where you’re using large data structures, mutating -an instance in place may be faster than copying and returning newly allocated -instances. With smaller data structures, creating new instances and writing in -a more functional programming style may be easier to reason about, so the lower -performance might be a worthwhile penalty for gaining that clarity. -### Differences Between Variables and Constants +### 변수와 상수 간의 차이점들 -Being unable to change the value of a variable might have reminded you of -another programming concept that most other languages have: *constants*. Like -immutable variables, constants are also values that are bound to a name and -are not allowed to change, but there are a few differences between constants -and variables. +변수의 값을 변경할 수 없다는 사항이 아마 당신에게 다른 언어가 가진 프로그래밍 개념을 떠오르게 하지 않나요: *상수* +불변성 변수와 마찬가지로 상수 또한 이름으로 bound된 후에는 값의 변경이 허용되지 않지만, 상수와 변수는 조금 +다릅니다. -First, we aren’t allowed to use `mut` with constants: constants aren't only -immutable by default, they're always immutable. +첫 째로, 상수에 대해서는 `mut`을 사용하는 것이 허용되지 않습니다: 상수는 기본 설정이 불변성인 것이 아니고 +불변성 그 자체 입니다. -We declare constants using the `const` keyword instead of the `let` keyword, -and the type of the value *must* be annotated. We're about to cover types and -type annotations in the next section, “Data Types,” so don't worry about the -details right now, just know that we must always annotate the type. +우리가 상수를 사용하고자 하면 `let`키워드 대신 `const`키워드를 사용해야 하고, 값의 유형을 선언해야 +합니다. 우리가 사용할 수 있는 유형들과 유형의 선언을 챕터 “Data Types,”에서 다루게 될 것이므로 자세한 +사항은 지금 걱정하지 말고, 우리는 반드시 값의 유형을 선언해야 한다는 것을 알고 지나갑시다. -Constants can be declared in any scope, including the global scope, which makes -them useful for values that many parts of code need to know about. +상수는 전체 영역을 포함하여 어떤 영역에서도 선언될 수 있습니다. 이는 코드의 많은 부분에서 사용될 필요가 있는 +값을 다루는데 유용합니다. -The last difference is that constants may only be set to a constant expression, -not the result of a function call or any other value that could only be -computed at runtime. +마지막 차이점은 상수는 오직 상수 표현식만 설정될 수 있지, 함수 호출의 결과값이나 그 외에 실행 시간에 결정되는 +값이 설정될 수는 없다는 점 입니다. -Here's an example of a constant declaration where the constant's name is -`MAX_POINTS` and its value is set to 100,000. (Rust constant naming convention -is to use all upper case with underscores between words): +아래의 `MAX_POINTS`라는 이름을 갖는 상수를 선언하는 예제에서는 값을 100,000으로 설정합니다. (Rust의 +상수 명명 규칙에 따라 모든 단어를 대문자로 사용합니다.) ```rust const MAX_POINTS: u32 = 100_000; ``` -Constants are valid for the entire time a program runs, within the scope they -were declared in, making them a useful choice for values in your application -domain that multiple parts of the program might need to know about, such as the -maximum number of points any player of a game is allowed to earn or the speed -of light. +상수는 자신이 선언되어 있는 영역 내에서 프로그램이 실행되는 시간 동안 항상 유효하기에, 당신의 어플리케이션 도메인 전체에 +걸쳐 프로그램의 다양한 곳에서 사용되는 값을 상수로 하면 유용합니다. 사용자가 한 게임에서 획득할 수 있는 최대 포인트, +빛의 속도 같은 값 등등... -Naming hardcoded values used throughout your program as constants is useful in -conveying the meaning of that value to future maintainers of the code. It also -helps to have only one place in your code you would need to change if the -hardcoded value needed to be updated in the future. +당신의 프로그램 전체에 걸쳐 하드코드 해야 하는 값을 이름지어 상수로 사용하면 향후 코드를 유지보수 하게 될 사람에게 +그 의미를 전달할 수 있으므로 유용합니다. 또한 향후 해당 값을 변경해야 하는 경우에 상수로 선언된 값 한 곳만 변경하면 +되므로 도움이 될 겁니다. ### Shadowing -As we saw in the guessing game tutorial in Chapter 2, we can declare a new -variable with the same name as a previous variable, and the new variable -*shadows* the previous variable. Rustaceans say that the first variable is -*shadowed* by the second, which means that the second variable’s value is what -we’ll see when we use the variable. We can shadow a variable by using the same -variable’s name and repeating the use of the `let` keyword as follows: +앞서 우리가 2장에서 추측 게임 예제를 통해 봤듯이, 이전에 선언한 변수와 같은 이름의 새 변수를 선언할 수 있고, +새 변수는 이전 변수를 *shadows*하게 됩니다. Rustaceans들은 이를 첫 변수가 두 번째에 의해 *shadowed* +됐다고 표현하게 됩니다. 해당 변수명은 두 번째 변수의 값을 갖게 된다는 뜻이죠. `let`키워드를 사용해서 다음처럼 +반복하여 같은 변수 명으로 변수를 shadow 할 수 있습니다. Filename: src/main.rs @@ -165,11 +139,9 @@ fn main() { } ``` -This program first binds `x` to a value of `5`. Then it shadows `x` by -repeating `let x =`, taking the original value and adding `1` so the value of -`x` is then `6`. The third `let` statement also shadows `x`, taking the -previous value and multiplying it by `2` to give `x` a final value of `12`. -When you run this program, it will output the following: +이 프로그램은 처음 `x`에 값 `5`를 bind 합니다. 이후 반복된 `let x =` 구문으로 `x`를 shadow하고 +원본 값에 `1`을 더해서 `x`의 값은 `6`이 됩니다. 세 번째 `let` 문으로 또 `x`를 shadow하고, 이전 +값에 `2`를 곱하여 `x`의 최종값은 `12`가 됩니다. 이 프로그램을 실행하면 다음과 같은 결과를 볼 수 있습니다. ```text $ cargo run @@ -178,36 +150,32 @@ $ cargo run The value of x is: 12 ``` -This is different than marking a variable as `mut`, because unless we use the -`let` keyword again, we’ll get a compile-time error if we accidentally try to -reassign to this variable. We can perform a few transformations on a value but -have the variable be immutable after those transformations have been completed. +이와 같은 사용은 변수를 `mut`으로 선언하는 것과는 차이가 있게 됩니다. 왜냐면 `let`키워드를 사용하지 않고 변수에 +새로 값을 대입하려고 하면 컴파일-시에 에러를 얻게 되기 때문이죠. 우리가 몇 번 값을 변경할 수는 있지만 그 이후에 +변수는 불변성을 갖게 됩니다. + +또 다른 `mut`과 shadowing의 차이는 `let`키워드를 다시 사용하여 효과적으로 새 변수를 선언하고, 값의 유형을 +변경할 수 있으면서도 동일 이름을 사용할 수 있다는 점 입니다. 예를 들어, 공백 문자들을 입력받아 얼마나 많은 공백 +문자가 있는지 보여주고자 할 때, 실제로는 저장하고자 하는 것은 공백의 갯수일테죠. -The other difference between `mut` and shadowing is that because we’re -effectively creating a new variable when we use the `let` keyword again, we can -change the type of the value, but reuse the same name. For example, say our -program asks a user to show how many spaces they want between some text by -inputting space characters, but we really want to store that input as a number: ```rust let spaces = " "; let spaces = spaces.len(); ``` -This construct is allowed because the first `spaces` variable is a string type, -and the second `spaces` variable, which is a brand-new variable that happens to -have the same name as the first one, is a number type. Shadowing thus spares us -from having to come up with different names, like `spaces_str` and -`spaces_num`; instead, we can reuse the simpler `spaces` name. However, if we -try to use `mut` for this, as shown here: +이와 같은 구조가 허용되는 이유는 첫 `spaces` 변수가 문자열 유형이고 두 번째 `spaces` 변수는 첫 번째 것과 +동일한 이름을 가진 새롭게 정의된 숫자 유형의 변수이기 때문입니다. Shadowing은 `space_str`이나 `space_num` +과 같이 대체된 이름을 사용는 대신 간단히 `spaces` 이름을 사용할 수 있게 해줍니다. 그러나 우리가 `mut`을 사용하려고 +했다면: ```rust,ignore let mut spaces = " "; spaces = spaces.len(); ``` -we’ll get a compile-time error because we’re not allowed to mutate a variable’s -type: +우리는 다음처럼 변수의 유형을 변경할 수 없다는 컴파일-시의 에러를 얻게 될 겁니다: + ```text error[E0308]: mismatched types @@ -220,5 +188,4 @@ error[E0308]: mismatched types found type `usize` ``` -Now that we’ve explored how variables work, let’s look at more data types they -can have. +변수가 어떻게 동작하는지 탐구했으니, 더 많은 데이터 유형을 사용 살펴보도록 합시다. diff --git a/second-edition/src/ch03-02-data-types.md b/second-edition/src/ch03-02-data-types.md index f10c6bb252..8d1b89a8e1 100644 --- a/second-edition/src/ch03-02-data-types.md +++ b/second-edition/src/ch03-02-data-types.md @@ -1,24 +1,20 @@ -## Data Types +## 데이터 타입들 -Every value in Rust is of a certain *type*, which tells Rust what kind of data -is being specified so it knows how to work with that data. In this section, -we’ll look at a number of types that are built into the language. We split the -types into two subsets: scalar and compound. +Rust에서 사용되는 모든 값들은 어떤 *타입*을 갖습니다. 그러니 어떤 형태의 데이터인지 명시하여 Rust에게 알려줘서 +이를 통해 데이터를 어떻게 다룰지 알 수 있도록 해야 합니다. 이번 장에서, 우리는 언어에 포함되어 있는 여러 타입들을 +살펴보고자 합니다. 타입은 크게 스칼라와 컴파운드, 둘로 나눌 수 있습니다. -Throughout this section, keep in mind that Rust is a *statically typed* -language, which means that it must know the types of all variables at compile -time. The compiler can usually infer what type we want to use based on the -value and how we use it. In cases when many types are possible, such as when we -converted a `String` to a numeric type using `parse` in Chapter 2, we must add -a type annotation, like this: +이번 장의 전체에 걸쳐 주지해야 할 점은 Rust는 *타입이 고정된* 언어라는 점 입니다. 이게 의미하는 바는 모든 변수의 +타입이 컴파일 시에 반드시 정해져 있어야 한다는 겁니다. 보통 컴파일러는 우리가 값을 사용하는 지에 따라 타입을 추측할 +수 있습니다. 2장에서 `String`을 `parse`를 사용하여 숫자로 변환했던 경우처럼 타입의 선택 폭이 넓은 경우는 +반드시 타입의 명시를 첨가해야 합니다. 다음처럼: ```rust let guess: u32 = "42".parse().expect("Not a number!"); ``` -If we don’t add the type annotation here, Rust will display the following -error, which means the compiler needs more information from us to know which -possible type we want to use: +여기에 타입 명시를 첨가하지 않은 경우, Rust는 다음과 같은 에러를 발생시킵니다. +이와 같은 에러는 컴파일러가 우리에게 사용하고 싶은 타입이 무엇인지 추가적인 정보를 요구하는 겁니다. ```text error[E0282]: unable to infer enough type information about `_` @@ -30,26 +26,23 @@ error[E0282]: unable to infer enough type information about `_` = note: type annotations or generic parameter binding required ``` -You’ll see different type annotations as we discuss the various data types. +우리가 다루고자 하는 다양한 데이터 타입들 각각의 타입 명시를 살펴보겠습니다. -### Scalar Types +### 스칼라 타입들 -A *scalar* type represents a single value. Rust has four primary scalar types: -integers, floating-point numbers, booleans, and characters. You’ll likely -recognize these from other programming languages, but let’s jump into how they -work in Rust. +*스칼라*는 하나의 값으로 표현되는 타입입니다. Rust는 정수형, 부동소수점 숫자, boolean, 그리고 문자, 네 가지 +스칼라 타입을 보유하고 있습니다. 아마 다른 프로그래밍 언어에서도 본 적이 있겠지만, Rust에서 이들이 어떻게 동작하 +는지 살펴보도록 합시다. -#### Integer Types +#### 정수형 -An *integer* is a number without a fractional component. We used one integer -type earlier in this chapter, the `i32` type. This type declaration indicates -that the value it’s associated with should be a signed integer (hence the `i`, -as opposed to a `u` for unsigned) that takes up 32 bits of space. Table 3-1 -shows the built-in integer types in Rust. Each variant in the Signed and -Unsigned columns (for example, *i32*) can be used to declare the type of an -integer value. +*정수형*은 소수점이 없는 숫자 입니다. 우리는 이번 장의 앞부분에서 `i32`타입인 정수형을 사용했었습니다. 해당 타입의 +선언은 부호를 갖는 32비트 변수임을 나타냅니다.(따라서 `i`는 부호가 없는 `u`와 반대입니다.) 표 3-1은 Rust에서 +사용되는 정수형들을 보여줍니다. 부호, 미부호로 나뉜 다른 열의 타입을 사용하여(*i32*처럼) 정수 값의 타입을 선언할 +수 있습니다. -Table 3-1: Integer Types in Rust + +Table 3-1: Rust에서의 정수 타입 | Length | Signed | Unsigned | |--------|--------|----------| @@ -59,32 +52,26 @@ integer value. | 64-bit | i64 | u64 | | arch | isize | usize | -Each variant can be either signed or unsigned and has an explicit size. -Signed and unsigned refers to whether it’s possible for the number to be -negative or positive; in other words, whether the number needs to have a sign -with it (signed) or whether it will only ever be positive and can therefore be -represented without a sign (unsigned). It’s like writing numbers on paper: when -the sign matters, a number is shown with a plus sign or a minus sign; however, -when it’s safe to assume the number is positive, it’s shown with no sign. -Signed numbers are stored using two’s complement representation (if you’re -unsure what this is, you can search for it online; an explanation is outside -the scope of this book). - -Each signed variant can store numbers from -(2n - 1) to 2n - -1 - 1 inclusive, where `n` is the number of bits that variant uses. So an -`i8` can store numbers from -(27) to 27 - 1, which equals --128 to 127. Unsigned variants can store numbers from 0 to 2n - 1, -so a `u8` can store numbers from 0 to 28 - 1, which equals 0 to 255. - -Additionally, the `isize` and `usize` types depend on the kind of computer your -program is running on: 64-bits if you’re on a 64-bit architecture and 32-bits -if you’re on a 32-bit architecture. - -You can write integer literals in any of the forms shown in Table 3-2. Note -that all number literals except the byte literal allow a type suffix, such as -`57u8`, and `_` as a visual separator, such as `1_000`. - -Table 3-2: Integer Literals in Rust +각각의 타입은 부호 혹은 미부호이며 명시된 크기를 갖습니다. 부호 혹은 미부호의 의미는, 숫자가 양수 혹은 음수를 다룰 수 +있는지 혹은 없는지를 나타냅니다. 다르게 말하면, 숫자가 부호를 가져야 하는 경우(부호) 혹은 오직 양수만을 가질 것이기에 +부호가 없이도 표현할 수 있는가(미부호)를 나타냅니다. 종이에 숫자 기재하는 것과 같죠: 부호와 함께 다뤄야 하는 경우에 +숫자는 더하기 혹은 빼기 기호와 함께 표시하죠. 숫자가 양수라고 가정되도 문제 없는 상황에는 부호가 없이 표시하게 됩니다. +부호된 숫자는 2의 보수 형태를 사용하여 저장됩니다. (2의 보수가 모른다면 검색해보세요. 이 책에서 다루는 내용이 아닙니다.) + + +각 부호 변수는 -(2n - 1) 부터 2n - 1 - 1 까지의 값을 포괄합니다. 여기서 +`n`은 사용되는 타입의 비트 수 입니다. 즉, `i8`은 -(27) 에서 27 - 1 +까지의 값, 즉 -128 에서 127 사이의 값을 저장할 수 있습니다. 미부호 타입은 0 에서 2n - 1 +까지의 값을 저장할 수 있습니다. 즉, `u8` 타입은 0 에서 28 - 1 다시 말해, 0 에서 255 +까지의 값을 저장할 수 있습니다. + +추가로, `isize`와 `usize`타입은 당신의 프로그램이 동작하는 컴퓨터 환경이 64-bits인지 아닌지에 따라 결정됩니다. +64-bit 아키텍처이면 64bit를, 32-bit 아키텍처이면 32bit를 갖게 됩니다. + +당신은 테이블 3-2에서 보여주는 형태들처럼 정수형 리터럴을 사용할 수 있습니다. byte 리터럴을 제외하고 모든 정수형 +리터럴은 `57u8`과 같은 타입 접미사와 `1_000`과 같이 시각적인 구분을 위한 `_`의 사용을 허용합니다. + +Table 3-2: Rust의 정수형 리터럴들 | Number literals | Example | |------------------|---------------| @@ -94,24 +81,21 @@ that all number literals except the byte literal allow a type suffix, such as | Binary | `0b1111_0000` | | Byte (`u8` only) | `b'A'` | -So how do you know which type of integer to use? If you’re unsure, Rust’s -defaults are generally good choices, and integer types default to `i32`: it’s -generally the fastest, even on 64-bit systems. The primary situation in which -you’d use `isize` or `usize` is when indexing some sort of collection. -#### Floating-Point Types +그렇다면 어떤 타입의 정수를 사용해야 할까요? 확실하게 정해진 경우가 아니면 Rust의 기본 값인 `i32`가 일반적으로 +는 좋은 선택입니다. 이는 일반적으로 가장 빠르기 때문이죠. 심지어 64-bit 시스템에서도요. `isize`나 `usize`는 +주로 콜렉션의 정렬을 색인할 때 사용됩니다. -Rust also has two primitive types for *floating-point numbers*, which are -numbers with decimal points. Rust’s floating-point types are `f32` and `f64`, -which are 32 bits and 64 bits in size, respectively. The default type is `f64` -because it’s roughly the same speed as `f32` but is capable of more precision. -It’s possible to use an `f64` type on 32-bit systems, but it will be slower -than using an `f32` type on those systems. Most of the time, trading potential -worse performance for better precision is a reasonable initial choice, and you -should benchmark your code if you suspect floating-point size is a problem in -your situation. +#### 부동 소수점 타입 -Here’s an example that shows floating-point numbers in action: +Rust에는 소수점을 갖는 숫자인 *부동소수점 숫자*를 위한 두 가지 기본 타입도 있습니다. Rust의 부동소수점 타입은 +`f32`와 `f64`로, 예상하신 대로 각기 32bit와 64bit의 크기를 갖습니다. 기본 타입이 `f64`인 이유는 대략 +`f32`와 비슷한 속도이면서 더 정밀한 표현이 가능하기 때문입니다. `f64`타입을 32bit 환경에서 사용하는 것도 +가능하지만 해당 시스템에서 `f32`를 사용하는 것 보다는 느려질 겁니다. 대부분의 경우 보다 높은 정밀성을 위한 +성능 하락이 합리적인 초기 선택안이기에 만약 당신이 당면한 상황에 부동소수점의 크기로 인한 문제가 의심된다면 벤치마킹을 +해보셔야 합니다. + +다음은 부동소수점 숫자가 활용되는 예제입니다: Filename: src/main.rs @@ -123,14 +107,13 @@ fn main() { } ``` -Floating-point numbers are represented according to the IEEE-754 standard. The -`f32` type is a single-precision float, and `f64` has double precision. +부동소수점 숫자는 IEEE-754 표준에 따라 표현됩니다. `f32` 타입은 1배수의 정밀도인 부동소수점이고, +`f64`는 2배수의 정밀도인 부동소수점 입니다. -#### Numeric Operations +#### 수학적 연산들. -Rust supports the usual basic mathematical operations you’d expect for all of the -number types: addition, subtraction, multiplication, division, and remainder. -The following code shows how you’d use each one in a `let` statement: +Rust가 지원하는 일반적인 기본 수학적 연산은 기대하신 것처럼 모든 숫자 타입에 적용됩니다: 더하기, 빼기, 곱하기, +나누기 등등. 다음의 코드로 보여주려는 것은 각 경우를 `let`문 내에서 사용할 수 있는 방법입니다. Filename: src/main.rs @@ -153,15 +136,16 @@ fn main() { } ``` -Each expression in these statements uses a mathematical operator and evaluates -to a single value, which is then bound to a variable. Appendix B contains a -list of all operators that Rust provides. +위의 문장에서 각 표현식들은 수학 연산자를 사용하여 산출된 값을 변수로 bound 합니다. 부록 B에 Rust에서 +제공하는 모든 연산자 목록이 들어있습니다. + +#### Boolean 타입 + +대부분의 다른 언어들처럼, boolean 타입은 Rust에서 둘 중 하나의 값만 갖을 수 있습니다: +`true`와 `false`. boolean 타입은 러스트에서 `bool`로 명시됩니다. -#### The Boolean Type +예제: -As in most other programming languages, a boolean type in Rust has two possible -values: `true` and `false`. The boolean type in Rust is specified using `bool`. -For example: Filename: src/main.rs @@ -173,15 +157,13 @@ fn main() { } ``` -The main way to consume boolean values is through conditionals, such as an `if` -expression. We’ll cover how `if` expressions work in Rust in the “Control Flow” -section. +boolean 값을 사용하는 주된 방법은 `if`문과 같은 조건문에서 조건으로 사용하는 것입니다. 우리는 `if`문이 +Rust에서 동작하는 방식을 “제어 흐름” 장에서 다루게 될 겁니다. -#### The Character Type +#### 문자 타입 -So far we’ve only worked with numbers, but Rust supports letters too. Rust’s -`char` type is the language’s most primitive alphabetic type, and the following -code shows one way to use it: +지금까지 숫자 타입만을 살펴봤는데, Rust는 문자 또한 지원합니다. Rust의 `char`는 이 언어의 가장 근본적인 +알파벳 타입이고, 다음의 코드는 이를 사용하는 하나의 방법입니다: Filename: src/main.rs @@ -193,29 +175,25 @@ fn main() { } ``` -Rust’s `char` type represents a Unicode Scalar Value, which means it can -represent a lot more than just ASCII. Accented letters, Chinese/Japanese/Korean -ideographs, emoji, and zero width spaces are all valid `char` types in Rust. -Unicode Scalar Values range from `U+0000` to `U+D7FF` and `U+E000` to -`U+10FFFF` inclusive. However, a “character” isn’t really a concept in Unicode, -so your human intuition for what a “character” is may not match up with what a -`char` is in Rust. We’ll discuss this topic in detail in the “Strings” section -in Chapter 8. +Rust의 `char`타입은 Unicode Scalar를 표현하는 값이고 이는 ASCII 보다 많은 표현을 가능하게 합니다. +억양 표시가 있는 문자, 한국어/중국어/일본어 표의 문자, 이모티콘, 넓이가 0인 공백문자 모두가 Rust에서는 +`char`타입으로 사용할 수 있습니다. Unicode Scalar 값의 범위는 `U+0000`에서 `U+D7FF` 그리고 +`U+E000`에서 `U+10FFFF` 를 포괄합니다. 그럼에도 불구하고 “문자”는 Unicode을 위한 개념이 아니기 +때문에, 당신의 인간적 직관에 따른 “문자”와 Rust의 `char`가 동일하지 않을 수 있습니다. 우리는 8장 +“Strings” 부에서 이 주제에 대해 상세히 다루게 될 겁니다. -### Compound Types -*Compound types* can group multiple values of other types into one type. Rust -has two primitive compound types: tuples and arrays. +### 복합 타입들 -#### Grouping Values into Tuples +*복합 타입들*은 다른 타입의 다양한 값들을 하나의 타입으로 묶을 수 있습니다. Rust는 두 개의 기본 타입들을 갖고 +있습니다: 튜플과 배열. -A tuple is a general way of grouping together some number of other values with -a variety of types into one compound type. +#### 값들을 집합시켜서 튜플화하기. -We create a tuple by writing a comma-separated list of values inside -parentheses. Each position in the tuple has a type, and the types of the -different values in the tuple don’t have to be the same. We’ve added optional -type annotations in this example: +튜플은 다양한 타입의 몇 개의 숫자를 집합시켜 하나의 복합 타입으로 만드는 일반적인 방법입니다. + +우리는 괄호 안에 콤마로 구분되는 값들의 목록을 작성하여 튜플을 만듭니다. 튜플에 포함되는 각 값의 타입이 동일할 +필요없이 서로 달라도 됩니다. 다음의 예제에 우리는 선택 사항인 타입 명시를 추가했습니다. Filename: src/main.rs @@ -225,9 +203,8 @@ fn main() { } ``` -The variable `tup` binds to the entire tuple, since a tuple is considered a -single compound element. To get the individual values out of a tuple, we can -use pattern matching to destructure a tuple value, like this: +튜플은 단일 요소를 위한 복합계로 고려되었기에 변수 `tup`에는 튜플 전체가 bind 됩니다. 개별 값을 튜플의 밖으로 +빼내오기 위해서는, 패턴 매칭을 사용하여 튜플의 값을 구조해체 시키면 됩니다. 다음을 봅시다: Filename: src/main.rs @@ -241,15 +218,12 @@ fn main() { } ``` -This program first creates a tuple and binds it to the variable `tup`. It then -uses a pattern with `let` to take `tup` and turn it into three separate -variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks -the single tuple into three parts. Finally, the program prints the value of -`y`, which is `6.4`. +해당 프로그램은 처음에 튜플을 만들고 변수 `tup`에 bind 시킵니다. 이후 패턴과 `let`을 통해 `tup`을 세개의 +분리된 변수 `x`, `y`, 그리고 `z`에 이동시킵니다. 이것을 *구조해체*라고 부르는 이유는 하나의 튜플을 세 부분으로 +나누기 때문입니다. 최종적으로 프로그램은 `y`의 값을 출력할 것이고 이는 `6.4`입니다. -In addition to destructuring through pattern matching, we can also access a -tuple element directly by using a period (`.`) followed by the index of the -value we want to access. For example: +패턴 매칭을 통한 구조해체에 추가로, 우리는 마침표(`.`) 뒤에 우리가 접근하길 원하는 값의 색인을 넣는 것을 통해 +튜플의 요소에 직접적으로 접근할 수 있습니다. 예제를 봅시다: Filename: src/main.rs @@ -265,19 +239,16 @@ fn main() { } ``` -This program creates a tuple, `x`, and then makes new variables for each -element by using their index. As with most programming languages, the first -index in a tuple is 0. +위의 프로그램은 튜플 `x`를 만들고, 이의 각 요소들을 그들의 색인을 통해 접근하여 새 변수를 만듭니다. 대부분의 +언어가 그렇듯이, 튜플의 첫 번째 색인은 0 입니다. -#### Arrays +#### 배열 -Another way to have a collection of multiple values is with an *array*. Unlike -a tuple, every element of an array must have the same type. Arrays in Rust are -different than arrays in some other languages because arrays in Rust have a -fixed length: once declared, they cannot grow or shrink in size. +여러 값들의 집합체를 만드는 다른 방법은 *배열*입니다. 튜플과는 다르게, 배열의 모든 요소는 모두 같은 타입이여야 +합니다. Rust의 배열이 몇 다른 언어들의 배열과 다른 점은 Rust에서는 배열은 고정된 길이를 갖는다는 점입니다: +한번 선언되면, 이들은 크기는 커지거나 작아지지 않습니다. -In Rust, the values going into an array are written as a comma-separated list -inside square brackets: +Rust에서는 대괄호 안에 값들을 콤마로 구분하여 나열해서 배열을 만듭니다: Filename: src/main.rs @@ -287,28 +258,22 @@ fn main() { } ``` -Arrays are useful when you want your data allocated on the stack rather than -the heap (we will discuss the stack and the heap more in Chapter 4), or when -you want to ensure you always have a fixed number of elements. They aren’t as -flexible as the vector type, though. The vector type is a similar collection -type provided by the standard library that *is* allowed to grow or shrink in -size. If you’re unsure whether to use an array or a vector, you should probably -use a vector: Chapter 8 discusses vectors in more detail. +배열이 유용할 때는 당신의 데이터를 heap보다 stack에 할당하는 것을 원하거나(stack 과 heap에 대해서는 4장에서 +다루게 될 것입니다), 당신이 항상 고정된 숫자의 요소를 갖는다고 확신하고 싶을 때 입니다. 이들은 벡터 타입처럼 가변적 +이지 않습니다. 벡터 타입은 유사 집합체로 표준 라이브러리에서 제공되며 확장 혹은 축소가 가능합니다. 배열이나 벡터 중에 +뭘 선택해야 할지 확실하지 않은 상황이라면 벡터를 사용하도록 하세요. 8장에서 벡터에 대해 더 자세히 다룹니다. -An example of when you might want to use an array rather than a vector is in a -program that needs to know the names of the months of the year. It’s very -unlikely that such a program will need to add or remove months, so you can use -an array because you know it will always contain 12 items: +벡터가 아닌 배열을 선택하게 되는 경우의 예로, 프로그램이 올해의 달 이름을 알고자 할 경우 입니다. 프로그램이 달을 +추가하거나 삭제하는 경우는 거의 없을 것이므로, 고정적으로 12개의 아이템을 가질테니 배열을 사용하면 됩니다. ```rust let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; ``` -##### Accessing Array Elements +##### 배열 요소에 접근하기 -An array is a single chunk of memory allocated on the stack. We can access -elements of an array using indexing, like this: +배열은 stack에 단일 메모리 뭉치로 할당됩니다. 우리는 색인을 통해 배열의 요소에 접근할 수 있습니다. 이렇게요: Filename: src/main.rs @@ -321,14 +286,12 @@ fn main() { } ``` -In this example, the variable named `first` will get the value `1`, because -that is the value at index `[0]` in the array. The variable named `second` will -get the value `2` from index `[1]` in the array. +이번 예제에서, `first`로 명명된 변수는 값 `1`이 될텐데, 왜냐면 배열 색인 `[0]`에 들어있는 값이기 때문이죠. +`second`로 명명된 변수는 배열의 색인 `[1]`의 값인 `2`가 되겠죠. -##### Invalid Array Element Access +##### 유효하지 않은 배열 요소에 대한 접근 -What happens if we try to access an element of an array that is past the end of -the array? Say we change the example to the following: +만약 우리가 배열의 끝을 넘어선 요소에 접근하려고 하면 어떻게 될까요? 예제를 다음처럼 변경해봤습니다. Filename: src/main.rs @@ -343,7 +306,7 @@ fn main() { } ``` -Running this code using `cargo run` produces the following result: +이번 코드를 `cargo run`을 통해 동작시키면 다음의 결과를 얻게 됩니다: ```text $ cargo run @@ -354,14 +317,12 @@ thread '
' panicked at 'index out of bounds: the len is 5 but the index is note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` -The compilation didn’t produce any errors, but the program results in a -*runtime* error and didn’t exit successfully. When you attempt to access an -element using indexing, Rust will check that the index you’ve specified is less -than the array length. If the index is greater than the length, Rust will -*panic*, which is the term Rust uses when a program exits with an error. - -This is the first example of Rust’s safety principles in action. In many -low-level languages, this kind of check is not done, and when you provide an -incorrect index, invalid memory can be accessed. Rust protects you against this -kind of error by immediately exiting instead of allowing the memory access and -continuing. Chapter 9 discusses more of Rust’s error handling. +컴파일 시에는 아무런 에러도 발생시키지 않습니다만, 프로그램의 결과는 *실행간에* 에러가 발생했고 성공적으로 종료되지 +못했다고 나옵니다. + +색인을 사용하여 요소에 접근하려고 하면 Rust는 지정한 색인이 배열 길이보다 작은지 확인합니다. 색인이 길이보다 길면 +Rust는 프로그램이 오류와 함께 종료 될 때 Rust가 사용하는 용어인 *패닉(panic)*합니다. + +이것은 Rust의 안전 원칙이 동작하는 첫 번째 예입니다. 많은 저수준 언어에서 이러한 타입의 검사는 수행되지 않으며 잘못된 +색인을 제공하면 유효하지 않은 메모리에 액세스 할 수 있습니다. Rust는 메모리 접근을 허용하고 계속 진행하는 대신 즉시 +종료하여 이러한 종류의 오류로부터 사용자를 보호합니다. 9 장에서는 Rust의 오류 처리에 대해 자세히 설명합니다. diff --git a/second-edition/src/ch03-03-how-functions-work.md b/second-edition/src/ch03-03-how-functions-work.md index d4879491b8..4875563a10 100644 --- a/second-edition/src/ch03-03-how-functions-work.md +++ b/second-edition/src/ch03-03-how-functions-work.md @@ -1,13 +1,11 @@ -## How Functions Work +## 함수 동작 원리 -Functions are pervasive in Rust code. You’ve already seen one of the most -important functions in the language: the `main` function, which is the entry -point of many programs. You’ve also seen the `fn` keyword, which allows you to -declare new functions. +함수는 Rust에 녹아들어 있습니다. 여러분은 이미 언어에서 가장 중요하게 생각하는 `main`함수를 보셨습니다. +이는 다수의 프로그램에서 실행 지점입니다. 여러분은 또한 `fn` 키워드도 보셨을텐데, 이는 새로운 함수의 선언을 +가용하게 합니다. -Rust code uses *snake case* as the conventional style for function and variable -names. In snake case, all letters are lowercase and underscores separate words. -Here’s a program that contains an example function definition: +Rust 코드는 *뱀 형태*를 변수나 함수 이름의 형식 규칙으로 사용합니다. 뱀 형태에서, 모든 문자는 소문자를 사용하며 +밑줄 표시로 단어를 구분합니다. 다음은 예제로 함수를 선언하는 프로그램 입니다: Filename: src/main.rs @@ -23,20 +21,18 @@ fn another_function() { } ``` -Function definitions in Rust start with `fn` and have a set of parentheses -after the function name. The curly braces tell the compiler where the function -body begins and ends. +Rust 에서의 함수 선언은 `fn`으로 시작하며 함수 이름 뒤에 괄호의 형식으로 되어 있습니다. 중괄호는 컴파일러에게 +함수의 시작과 종료 지점을 알려주게 됩니다. -We can call any function we’ve defined by entering its name followed by a set -of parentheses. Because `another_function` is defined in the program, it can be -called from inside the `main` function. Note that we defined `another_function` -*after* the `main` function in the source code; we could have defined it before -as well. Rust doesn’t care where you define your functions, only that they’re -defined somewhere. +우리는 함수의 이름과 괄호 형식을 기입하는 것을 통해 우리가 선언했던 어떤 함수든 호출할 수 있습니다. +`another_function`이 프로그램 내에 정의되어 있으므로, `main` 함수에서 해당 함수를 호출할 수 있습니다. +주의할 점은, 소스 코드 내에서 `another_function`이 `main` 함수 *이후에* 정의했다는 점 입니다. 우리는 +이를 이전에도 정의할 수 있습니다. Rust는 당신의 함수의 위치를 신경쓰지 않습니다, 어디든 정의만 되어 있으면 됩니다. -Let’s start a new binary project named *functions* to explore functions -further. Place the `another_function` example in *src/main.rs* and run it. You -should see the following output: + +함수를 추가로 탐색하기 위해 *functions* 이라는 이름의 새로운 바이너리 프로젝트를 시작합시다. +`another_function` 예제를 * src / main.rs *에 넣고 실행해보세요. +다음과 같은 결과가 나타납니다: ```text $ cargo run @@ -46,22 +42,16 @@ Hello, world! Another function. ``` -The lines execute in the order in which they appear in the `main` function. -First, the “Hello, world!” message prints, and then `another_function` is -called and its message is printed. +`main` 함수 안의 내용이 줄의 순서대로 수행됩니다. 처음으로, "Hello, world!" 메시지가 출력되고, +`another_function`이 호출되고 그의 메시지를 출력합니다. -### Function Parameters +### 함수 매개변수 -Functions can also be defined to have *parameters*, which are special variables -that are part of a function's signature. When a function has parameters, we can -provide it with concrete values for those parameters. Technically, the concrete -values are called *arguments*, but in casual conversation people tend to use -the words “parameter” and “argument” interchangeably for either the variables -in a function's definition or the concrete values passed in when you call a -function. +함수는 함수 고유한 부분인 특별한 변수 *매개변수*를 갖는 형식으로 선언될 수 있습니다. 함수가 매개변수를 취할 때, 우리는 +상수를 그들의 전달인자로 제공할 수 있습니다. 기술적으로, 여기서 전달되는 상수를 *전달인자*라고 부릅니다만, 사람들은 보통 +“전달인자”와 “매개변수”를 혼용해서 사용하는 경향이 있습니다. -The following rewritten version of `another_function` shows what parameters -look like in Rust: +다음의 재작성 된 `another_function`은 Rust에서 매개변수가 어떤 것이지 보여줍니다: Filename: src/main.rs @@ -75,7 +65,7 @@ fn another_function(x: i32) { } ``` -Try running this program; you should get the following output: +이 프로그램을 실행해보시면 다음과 같은 결과가 출력되는 것을 보게 될 겁니다: ```text $ cargo run @@ -84,18 +74,13 @@ $ cargo run The value of x is: 5 ``` -The declaration of `another_function` has one parameter named `x`. The type of -`x` is specified as `i32`. When `5` is passed to `another_function`, the -`println!` macro puts `5` where the pair of curly braces were in the format -string. - -In function signatures, you *must* declare the type of each parameter. This is -a deliberate decision in Rust’s design: requiring type annotations in function -definitions means the compiler almost never needs you to use them elsewhere in -the code to figure out what you mean. +`another_function`의 선언은 `x`로 명명된 하나의 매개변수를 갖습니다. `x`의 타입은 `i32`로 정의됩니다. +`5`가 `another_function`으로 전달되면, `println!` 매크로는 중괄호 짝으로 된 형식 문자열에 `5`를 +전달합니다. 함수의 선언부에서, 여러분은 *반드시* 각 매개변수의 타입을 정의해야 합니다. 이 사항은 Rust를 설계하며 +내린 신중한 결정사항 입니다: 함수의 정의에 타입을 명시하여 코드내 다른 부분에서 이들을 사용하는 것을 통해 당신의 의도를 +추측하지 않아도 되게 됩니다. -When you want a function to have multiple parameters, separate the parameter -declarations with commas, like this: +여러분의 함수에 여러 개의 매개변수를 사용하고 싶으면, 매개변수들을 다음처럼 쉼표와 함께 구분해서 사용할 수 있습니다: Filename: src/main.rs @@ -110,14 +95,10 @@ fn another_function(x: i32, y: i32) { } ``` -This example creates a function with two parameters, both of which are `i32` -types. The function then prints out the values in both of its parameters. Note -that function parameters don't all need to be the same type, they just happen -to be in this example. - -Let’s try running this code. Replace the program currently in your *function* -project’s *src/main.rs* file with the preceding example, and run it using -`cargo run`: +이 예제는 각각 `i32` 타입인 두 개의 매개변수를 갖는 함수를 생성합니다. 함수는 그의 두 매개변수의 값을 출력합니다. +주의할 점은, 함수 매개변수는 이번 예제처럼 굳이 같은 타입이 아니여도 된다는 점 입니다. 한번 코드를 실행해봅시다. +여러분의 *function* 프로젝트의 *src/main.rs* 내용을 위의 예제로 변경한 뒤에, +`cargo run`을 통해 수행시키면 됩니다: ```text $ cargo run @@ -127,27 +108,21 @@ The value of x is: 5 The value of y is: 6 ``` -Because we called the function with `5` as the value for `x` and `6` is passed -as the value for `y`, the two strings are printed with these values. +우리는 값 `5`와 `6`을 `x`와 `y`로 전달했기 때문에, 이 값들이 담긴 두 문장을 출력합니다. -### Function Bodies +### 함수 본문 -Function bodies are made up of a series of statements optionally ending in an -expression. So far, we’ve only covered functions without an ending expression, -but we have seen expressions as parts of statements. Because Rust is an -expression-based language, this is an important distinction to understand. -Other languages don’t have the same distinctions, so let’s look at what -statements and expressions are and how their differences affect the bodies of -functions. +함수 본문은 필요에 따라 표현식으로 종결되는 구문의 나열로 구성됩니다. 지금까지 우리는 종결 표현식이 없는 함수만 +다뤘기에, 표현식이 구문의 일부처럼 여겨질지 모르겠습니다. Rust가 표현식에 기반한 언어기 때문에, 이것은 이해하셔야 +하는 중요한 차이점 입니다. 다른 언어들은 이와 같은 차이가 없으니, 구문과 표현식이 함수의 본문에 어떤 식으로 차이나게 +적용되는지 살펴보도록 하겠습니다. -### Statements and Expressions +### 구문과 표현식 -We’ve actually already used statements and expressions. *Statements* are -instructions that perform some action and do not return a value. *Expressions* -evaluate to a resulting value. Let’s look at some examples. +사실 우리는 이미 구문과 표현식을 사용했습니다. *구문*은 어떤 명령들의 나열로 값을 반환하지 않는 어떤 동작을 수행 +합니다. *포현식*은 결과 값을 산출해냅니다. 다음 몇 개의 예제를 살펴보도록 합시다. `let` 키워드를 통해 변수를 +만들고 값을 할당하는 구문을 만듭니다. 항목 3-3의, `let y = 6;`은 구문 입니다: -Creating a variable and assigning a value to it with the `let` keyword is a -statement. In Listing 3-3, `let y = 6;` is a statement: Filename: src/main.rs @@ -157,13 +132,10 @@ fn main() { } ``` -Listing 3-3: A `main` function declaration containing one statement. +항목 3-3: 하나의 구문을 갖는 `main` 함수를 선언하였다. -Function definitions are also statements; the entire preceding example is a -statement in itself. - -Statements do not return values. Therefore, you can’t assign a `let` statement -to another variable, as the following code tries to do: +함수 정의는 또 하나의 구문입니다; 상기 예제는 자신 그 자체가 구문 입니다. 구문은 값을 반환하지 않습니다. +그러니, 여러분은 다음처럼 `let` 구문을 사용해서는 다른 변수에 값을 대입할 수 없습니다: Filename: src/main.rs @@ -173,7 +145,7 @@ fn main() { } ``` -When you run this program, you’ll get an error like this: +여러분이 이 프로그램을 수행하면, 다음과 같은 에러를 보게 될 겁니다: ```text $ cargo run @@ -187,19 +159,15 @@ error: expected expression, found statement (`let`) = note: variable declaration using `let` is a statement ``` -The `let y = 6` statement does not return a value, so there isn’t anything for -`x` to bind to. This is different than in other languages, such as C and Ruby, -where the assignment returns the value of the assignment. In those languages, -you can write `x = y = 6` and have both `x` and `y` have the value `6`; that is -not the case in Rust. +`let y = 6` 구문은 반환 값이 없으므로, `x`에 bind 시킬 것이 없습니다. 이것이 다른 언어인 C나 +Ruby와의 차이점 입니다. 이들 언어들은 `x = y = 6`와 같은 코드가 `x`와 `y`에 모두 `6`의 값을 +대입할 수 있습니다; Rust에서는 허용되지 않습니다. 여러분이 작성하는 Rust 코드의 대부분은 표현식이며 +이는 어떤 값을 산출합니다. `5 + 6`과 같은 간단한 수학 연산을 살펴보면, 이는 `11`이란 값을 산출하는 +표현식입니다. -Expressions evaluate to something and make up most of the rest of the code that -you’ll write in Rust. Consider a simple math operation, such as `5 + 6`, which -is an expression that evaluates to the value `11`. Expressions can be part of -statements: in Listing 3-3 that had the statement `let y = 6;`, `6` is an -expression that evaluates to the value `6`. Calling a function is an -expression. Calling a macro is an expression. The block that we use to create -new scopes, `{}`, is an expression, for example: +표현식은 구문의 부분일 수 있습니다: 항목 3-3은 `let y = 6;`이란 구문을 갖는데, `6`은 `6`이란 값을 +산출하는 표현식입니다. 함수를 호출하는 것은 표현식입니다. 매크로를 호출하는 것은 표현식입니다. 예제처럼 새로운 +범위를 생성하는데 사용하는 block, `{}`, 은 표현식입니다: Filename: src/main.rs @@ -216,7 +184,7 @@ fn main() { } ``` -This expression: +표현식 부: ```rust,ignore { @@ -225,20 +193,17 @@ This expression: } ``` -is a block that, in this case, evaluates to `4`. That value gets bound to `y` -as part of the `let` statement. Note the line without a semicolon at the end, -unlike most of the lines you’ve seen so far. Expressions do not include ending -semicolons. If you add a semicolon to the end of an expression, you turn it -into a statement, which will then not return a value. Keep this in mind as you -explore function return values and expressions next. +이번 경우에 해당 block은 `4`를 산출합니다. 이 값은 `let` 구문의 일부로 `y`에 bound됩니다. +여러분이 앞서 봐온 것과 다르게 줄의 마지막이 세미콜론으로 끝나지 않은 점을 주목하세요. 표현식은 종결을 +나타내는 세미콜론을 사용하지 않습니다. 만약 세미콜론을 표현식 마지막에 추가하면, 이는 구문으로 변경되고 +반환 값이 아니게 됩니다. 이후부터 함수의 반환 값과 표현식을 살펴보실때 이 점을 유의하세요. + -### Functions with Return Values +### 반환 값을 갖는 함수 -Functions can return values to the code that calls them. We don’t name return -values, but we do declare their type after an arrow (`->`). In Rust, the return -value of the function is synonymous with the value of the final expression in -the block of the body of a function. Here’s an example of a function that -returns a value: +함수는 그들을 호출한 코드에 값을 반환할 수 있습니다. 우리는 반환되는 값을 명명해야 할 필요는 없지만, 그들의 +타입은 화살표(`->`) 뒤에 선언해야 합니다. Rust에서 반환 값은 함수 본문의 마지막 표현식의 값과 동일합니다. +여기 반환 값에 대한 예제가 있습니다: Filename: src/main.rs @@ -254,10 +219,9 @@ fn main() { } ``` -There are no function calls, macros, or even `let` statements in the `five` -function—just the number `5` by itself. That’s a perfectly valid function in -Rust. Note that the function’s return type is specified, too, as `-> i32`. Try -running this code; the output should look like this: +`five` 함수에는 함수 호출, 매크로, 심지어 `let` 구문도 없이 그저 `5`란 숫자 하나가 있습니다. +이는 Rust에서 완벽하게 함수로 허용됩니다. 함수 반환 값의 타입이 `-> i32`로 명시되어 있다는 점 +또한 주목하세요. 해당 코드를 수행하면 다음과 같은 결과를 얻게 될 겁니다: ```text $ cargo run @@ -266,20 +230,18 @@ $ cargo run The value of x is: 5 ``` -The `5` in `five` is the function’s return value, which is why the return type -is `i32`. Let’s examine this in more detail. There are two important bits: -first, the line `let x = five();` shows that we’re using the return value of a -function to initialize a variable. Because the function `five` returns a `5`, -that line is the same as the following: +`5`는 `five` 함수가 반환한 값이고, 이 때문에 반환 타입을 `i32`으로 한 것이지요. 좀더 자세히 +설명해보겠습니다. 중요한 지점이 두 곳 있습니다: 첫 째, `let x = five();` 줄은 우리가 반환 값을 +변수의 초기 값으로 사용하는 것을 보여줍니다. `five`의 반환 값이 `5`이기 때문에, 해당 줄은 다음과 +동일합니다: ```rust let x = 5; ``` -Second, the `five` function has no parameters and defines the type of the -return value, but the body of the function is a lonely `5` with no semicolon -because it’s an expression whose value we want to return. Let’s look at another -example: +둘 째, `five` 함수는 매개변수 없이 반환 값에 대한 타입만 정의되어 있지만, 본문에는 `5`만이 세미콜론 없이 +외로이 있는 이유는 이것이 우리가 값을 반환하고자 할때 사용하는 하는 표현식이기 때문입니다. 다른 예제를 통해 +살펴보겠습니다: Filename: src/main.rs @@ -295,9 +257,8 @@ fn plus_one(x: i32) -> i32 { } ``` -Running this code will print `The value of x is: 6`. What happens if we place a -semicolon at the end of the line containing `x + 1`, changing it from an -expression to a statement? +이 코드를 수행하면 `The value of x is: 6`를 출력하게 됩니다. 우리가 `x + 1` 끝에 세미콜론을 +추가하여 표현식을 구문으로 변경하면 어떤 일이 일어날까요? Filename: src/main.rs @@ -313,7 +274,7 @@ fn plus_one(x: i32) -> i32 { } ``` -Running this code produces an error, as follows: +이 코드를 실행하면 다음과 같은 에러를 얻게 됩니다: ```text error[E0308]: mismatched types @@ -334,10 +295,8 @@ help: consider removing this semicolon: | ^ ``` -The main error message, “mismatched types,” reveals the core issue with this -code. The definition of the function `plus_one` says that it will return an -`i32`, but statements don’t evaluate to a value, which is expressed by `()`, -the empty tuple. Therefore, nothing is returned, which contradicts the function -definition and results in an error. In this output, Rust provides a message to -possibly help rectify this issue: it suggests removing the semicolon, which -would fix the error. +에러 메시지의 중요 포인트는 “mismatched types,”으로 이 코드의 주요 문제를 보여줍니다. +`plus_one` 함수의 정의는 `i32` 값을 반환하겠다고 하였으나, 구문은 값을 산출하지 않기에 `()`처럼 +비어있는 튜플로 표현됩니다. 이런 이유로, 반환할 것이 없어서 함수가 정의된 내용과 상충하게 되고 이는 에러를 +발생시킵니다. 이번 결과에서는, Rust가 문제를 해결할 수 있도록 도와주는 메시지를 제공합니다: 세미콜론을 +제거하면 에러가 교정될 수도 있다고 제안하네요. diff --git a/second-edition/src/ch03-04-comments.md b/second-edition/src/ch03-04-comments.md index 664e155d76..28a73131a5 100644 --- a/second-edition/src/ch03-04-comments.md +++ b/second-edition/src/ch03-04-comments.md @@ -1,27 +1,25 @@ -## Comments +## 주석 -All programmers strive to make their code easy to understand, but sometimes -extra explanation is warranted. In these cases, programmers leave notes, or -*comments*, in their source code that the compiler will ignore but people -reading the source code may find useful. +모든 프로그래머들은 되도록 이해하기 쉽게 이해되는 코드를 작성하기 위해 노력하지만, 자주 부연 설명이 +필요합니다. 이런 경우, 프로그래머들은 메모를 남기거나 소스코드에 컴파일러는 무시하도록 되어 있는 *주석* +을 남겨 소스코드를 읽는 사람이 혜택을 받을 수 있게 합니다. -Here’s a simple comment: +여기에 간단한 주석이 있습니다: ```rust // Hello, world. ``` -In Rust, comments must start with two slashes and continue until the end of the -line. For comments that extend beyond a single line, you’ll need to include -`//` on each line, like this: +Rust에서 주석은 두개의 슬래쉬로 시작해야 하고 해당 줄의 끝까지 계속됩니다. 한 줄을 넘는 주석을 작성할 경우, +`//`를 각 줄에 포함시켜 사용하면 됩니다, 이런 식으로요: ```rust -// So we’re doing something complicated here, long enough that we need -// multiple lines of comments to do it! Whew! Hopefully, this comment will -// explain what’s going on. +// 우리는 여기에 뭔가 복잡한 것을 적어놓고자 하는데, 그를 위해 충분히 긴 여러 줄의 주석이 필요합니다. +// 휴! 다행입니다. +// 이 주석은 그에 대해 설명할테니까요. ``` -Comments can also be placed at the end of lines containing code: +주석은 코드의 뒷 부분에 위치할 수도 있습니다: Filename: src/main.rs @@ -31,8 +29,7 @@ fn main() { } ``` -But you’ll more often see them used in this format, with the comment on a -separate line above the code it's annotating: +하지만 주석을 코드와 나눠 앞 줄에 기재되는 형식을 더 자주 보게 될 겁니다. Filename: src/main.rs @@ -43,4 +40,4 @@ fn main() { } ``` -That’s all there is to comments. They’re not particularly complicated. +이게 전부입니다. 특별히 복잡하지 않죠. diff --git a/second-edition/src/ch03-05-control-flow.md b/second-edition/src/ch03-05-control-flow.md index 20093b3401..774d8ec8f7 100644 --- a/second-edition/src/ch03-05-control-flow.md +++ b/second-edition/src/ch03-05-control-flow.md @@ -1,19 +1,16 @@ -## Control Flow +## 제어문 -Deciding whether or not to run some code depending on if a condition is true or -deciding to run some code repeatedly while a condition is true are basic -building blocks in most programming languages. The most common constructs that -let you control the flow of execution of Rust code are `if` expressions and -loops. +조건의 상태가 참인지에 따라 어떤 코드의 실행 여부를 결정하거나 조건이 만족되는 동안 반복 수행을 하는 것은 +대부분의 프로그래밍 언어의 기초 문법입니다. 우리가 실행 흐름을 제어할 수 있는 가장 보편적인 작성 방식은 +`if`표현식과 반복문 입니다. -### `if` Expressions +### `if`표현식 -An `if` expression allows us to branch our code depending on conditions. We -provide a condition and then state, “If this condition is met, run this block -of code. If the condition is not met, do not run this block of code.” +`if`표현식은 우리의 코드가 조건에 따라 분기할 수 있게 합니다. 우리가 조건을 제공하는 것은 다음 서술과 같죠. +“만약 조건이 충족되면, 이 코드 블럭을 실행하세요. 만약 충족되지 않았다면 코드 블럭을 실행하지 마세요." -Create a new project called *branches* in your *projects* directory to explore -the `if` expression. In the *src/main.rs* file, input the following: +*branches*로 명명된 새 프로젝트를 우리의 *projects* 디렉토리에 생성하고 `if`식을 탐구합시다. +*src/main.rs* 파일에 다음의 내용을 기입하세요: Filename: src/main.rs @@ -31,20 +28,16 @@ fn main() { -All `if` expressions start with the keyword `if`, which is followed by a -condition. In this case, the condition checks whether or not the variable -`number` has a value less than 5. The block of code we want to execute if the -condition is true is placed immediately after the condition inside curly -braces. Blocks of code associated with the conditions in `if` expressions are -sometimes called *arms*, just like the arms in `match` expressions that we -discussed in the “Comparing the Guess to the Secret Number” section of -Chapter 2. Optionally, we can also include an `else` expression, which we chose -to do here, to give the program an alternative block of code to execute should -the condition evaluate to false. If you don’t provide an `else` expression and -the condition is false, the program will just skip the `if` block and move on -to the next bit of code. - -Try running this code; you should see the following output: +모든 `if`표현식은 `if`란 키워드로 시작하며 뒤이어 조건이 옵니다. 이번 경우에 조건은 변수 `number`가 +5보다 작은 값을 가지는지 여부가 됩니다. 조건이 참일 때 실행하는 코드 블록은 조건 바로 뒤 중괄호로 된 블록에 +배치됩니다. `if`식의 조건과 관련된 코드 블럭은 우리가 2장의 “비밀번호 추리 게임”에서 다뤘던 `match`식의 +갈래(arms)와 마찬가지로 *갈래(arms)*로 불립니다. 선택적으로, 우리는 이번 경우에서 처럼 `else`식을 +포함시킬 수 있는데, 이는 조건이 거짓으로 산출될 경우 실행시킬 코드 블럭을 프로그램에 제공합니다. 당신이 +`else`식을 제공하지 않는데 조건이 거짓이 되면, 프로그램은 `if`블록을 생략하고 다음 순서의 코드를 실행하게 +될 겁니다. + + +이 코드를 실행해보세요; 다음과 같은 결과를 얻을 수 있을 겁니다: ```text $ cargo run @@ -53,14 +46,13 @@ $ cargo run condition was true ``` -Let’s try changing the value of `number` to a value that makes the condition -`false` to see what happens: +`number`의 값을 조건을 `거짓`으로 만들 값으로 변경하면 무슨 일이 일어날지 살펴보도록 합시다: ```rust,ignore let number = 7; ``` -Run the program again, and look at the output: +프로그램을 다시 실행시키면, 다음과 같은 결과를 보게 됩니다: ```text $ cargo run @@ -69,9 +61,8 @@ $ cargo run condition was false ``` -It’s also worth noting that the condition in this code *must* be a `bool`. To -see what happens if the condition isn’t a `bool`, try running the following -code: +주의해야 할 중요한 점은 이번 코드의 조건은 *반드시* `bool`이어야 합니다. 만약 `bool`이 아닐 경우 +어떤 일이 일어나는지는 다음의 코드를 실행하면 알 수 있을 겁니다: Filename: src/main.rs @@ -85,8 +76,8 @@ fn main() { } ``` -The `if` condition evaluates to a value of `3` this time, and Rust throws an -error: +`if`의 조건이 `3`으로 산출되고, Rust는 에러를 발생시킵니다. + ```text error[E0308]: mismatched types @@ -99,12 +90,10 @@ error[E0308]: mismatched types found type `{integer}` ``` -The error indicates that Rust expected a `bool` but got an integer. Rust will -not automatically try to convert non-boolean types to a boolean, unlike -languages such as Ruby and JavaScript. You must be explicit and always provide -`if` with a `boolean` as its condition. If we want the `if` code block to run -only when a number is not equal to `0`, for example, we can change the `if` -expression to the following: +이 에러가 나타내는 것은 Rust가 `bool`을 기대하였으나 정수형이 왔다는 겁니다. Rust는 boolean 타입이 +아닌 것을 boolean 타입으로 자동 변환하지 않습니다. Ruby나 Javascript와는 다르죠. 우리는 반드시 +명시적으로 `boolean`을 `if`의 조건으로 사용해야 합니다. 만약 우리가 `if`표현식의 코드 블록을 숫자가 +`0`이 아닐 시에 실행하고 싶다면, 다음처럼, 우리는 `if`표현식을 변경할 수 있습니다. Filename: src/main.rs @@ -118,12 +107,12 @@ fn main() { } ``` -Running this code will print `number was something other than zero`. +이번 코드를 실행시키면 `number was something other than zero`가 출력 될 겁니다. -#### Multiple Conditions with `else if` +#### `else if`와 다수 조건 -We can have multiple conditions by combining `if` and `else` in an `else if` -expression. For example: +우리는 `if`와 `else` 사이에 `else if`식을 추가 결합하여 다양한 조건을 다룰 수 있습니다. +예제를 보시죠: Filename: src/main.rs @@ -143,8 +132,7 @@ fn main() { } ``` -This program has four possible paths it can take. After running it, you should -see the following output: +이번 프로그램은 분기할 수 있는 네 개의 경로를 갖습니다. 이를 수행하면, 다음과 같은 결과를 얻게 될 겁니다: ```text $ cargo run @@ -153,21 +141,17 @@ $ cargo run number is divisible by 3 ``` -When this program executes, it checks each `if` expression in turn and executes -the first body for which the condition holds true. Note that even though 6 is -divisible by 2, we don’t see the output `number is divisible by 2`, nor do we -see the `number is not divisible by 4, 3, or 2` text from the `else` block. The -reason is that Rust will only execute the block for the first true condition, -and once it finds one, it won’t even check the rest. +이 프로그램이 실행될 때, `if`식을 차례대로 검사하고 검사 조건이 참일 때의 첫 번째 본문을 실행합니다. 주목할 점은 +6을 2로 나누어 떨어짐에도 불구하고 `number is divisible by 2`이 출력되지 않는데, `else`의 +블럭에 위치한 `number is not divisible by 4, 3, or 2`도 마찬가지입니다. 이렇게 되는 이유는 +Rust가 첫 번째로 조건이 참이 되는 블록만 찾아 실행하고, 한번 찾게 되면 나머지는 검사하지 않기 때문입니다. -Using too many `else if` expressions can clutter your code, so if you have more -than one, you might want to refactor your code. Chapter 6 describes a powerful -Rust branching construct called `match` for these cases. +너무 많은 `else if`식의 사용은 당신의 코드를 이해하기 어렵게 하므로, 둘 이상일 경우 코드를 리팩토링하게 +될 수도 있습니다. 이런 경우를 위해 6장에서 `match`라 불리는 강력한 분기 생성자를 다룹니다. -#### Using `if` in a `let` statement +#### `let`구문에서 `if` 사용하기 -Because `if` is an expression, we can use it on the right side of a `let` -statement, for instance in Listing 3-4: +`if`가 표현식이기 때문에, 항목 3-4에서 처럼, 우리는 이를 `let` 구문의 우측에 사용할 수 있죠. Filename: src/main.rs @@ -187,8 +171,7 @@ fn main() { Listing 3-4: Assigning the result of an `if` expression to a variable -The `number` variable will be bound to a value based on the outcome of the `if` -expression. Run this code to see what happens: +변수 `number`에는 `if`식에서 산출된 값이 bound되게 됩니다. 어떤 일이 일어날지 코드를 실행해보죠: ```text $ cargo run @@ -197,13 +180,10 @@ $ cargo run The value of number is: 5 ``` -Remember that blocks of code evaluate to the last expression in them, and -numbers by themselves are also expressions. In this case, the value of the -whole `if` expression depends on which block of code executes. This means the -values that have the potential to be results from each arm of the `if` must be -the same type; in Listing 3-4, the results of both the `if` arm and the `else` -arm were `i32` integers. But what happens if the types are mismatched, as in -the following example? +기억하세요! 코드 블록은 그들의 마지막에 위치한 표현식을 산출하며 숫자는 그 자체로 표현식이라는 것을요. 이 경우 +전체 `if`식의 값은 실행되는 코드 블럭에 따라 다릅니다. 그렇기에 `if`식에 속한 각 갈래의 결과는 반드시 같은 +타입이여야 합니다. 항목 3-4에서 `if`갈래와 `else`갈래는 모두 `i32` 정수형을 결과 값으로 가집니다. +하지만 만약 다음 예제처럼 유형이 다르면 어떻게 될까요? Filename: src/main.rs @@ -221,9 +201,8 @@ fn main() { } ``` -When we try to run this code, we’ll get an error. The `if` and `else` arms have -value types that are incompatible, and Rust indicates exactly where to find the -problem in the program: +우리가 이번 코드를 실행시키려고 하면 에러를 얻게 됩니다. `if`와 `else` 갈래의 값 타입이 호환되지 않고, +Rust는 정확히 프로그램의 어느 지점에 문제가 있는지 보여줍니다. ```text error[E0308]: if and else have incompatible types @@ -241,31 +220,25 @@ error[E0308]: if and else have incompatible types found type `&'static str` ``` -The expression in the `if` block evaluates to an integer, and the expression in -the `else` block evaluates to a string. This won’t work because variables must -have a single type. Rust needs to know at compile time what type the `number` -variable is, definitively, so it can verify at compile time that its type is -valid everywhere we use `number`. Rust wouldn’t be able to do that if the type -of `number` was only determined at runtime; the compiler would be more complex -and would make fewer guarantees about the code if it had to keep track of -multiple hypothetical types for any variable. +`if` 블록이 정수형을 산출하는 식이고 `else` 블록은 문자열을 산출하는 식 입니다. 이런 경우가 성립하지 않는 +이유는 변수가 가질 수 있는 타입이 오직 하나이기 때문입니다. Rust는 컴파일 시에 `number` 변수의 타입이 뭔지 +확실히! 정의해야 합니다. 그래야 `number`가 사용되는 모든 곳에서 유효한지 검증할 수 있으니까요. Rust는 +`number`의 타입을 실행 시에 정의되도록 할 수 없습니다. 컴파일러가 모든 변수의 다양한 타입을 추적해서 알아내야 +한다면 컴파일러는 보다 복잡해지고 보증할 수 있는 것은 적어지게 됩니다. -### Repetition with Loops +### 반복문과 반복 -It’s often useful to execute a block of code more than once. For this task, -Rust provides several *loops*. A loop runs through the code inside the loop -body to the end and then starts immediately back at the beginning. To -experiment with loops, let’s make a new project called *loops*. +코드 블록을 한 번 이상 수행하는 것은 자주 유용합니다. 반복 작업을 위해서, Rust는 몇 가지 *반복문*을 제공합니다. +반복문은 반복문 시작부터 끝까지 수행하고 다시 처음부터 수행합니다. 반복문의 실험해보기 위해 *loops*으로 명명된 +새 프로젝트를 작성해 봅시다. -Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one. +Rust가 제공하는 세 가지 반복문: `loop`, `while`, 그리고 `for`을 모두 사용해 봅시다. -#### Repeating Code with `loop` -The `loop` keyword tells Rust to execute a block of code over and over again -forever or until you explicitly tell it to stop. +#### `loop`와 함께 코드의 반복 수행 -As an example, change the *src/main.rs* file in your *loops* directory to look -like this: +`loop` keyword는 Rust에게 그만두라고 명시하여 알려주기 전까지 코드 블럭을 반복 수행합니다. +예제로, 우리의 *loops*디렉토리에 *src/main.rs*를 다음처럼 변경하세요: Filename: src/main.rs @@ -277,9 +250,8 @@ fn main() { } ``` -When we run this program, we’ll see `again!` printed over and over continuously -until we stop the program manually. Most terminals support a keyboard shortcut, - ctrl-C, to halt a program that is stuck in a continual loop. Give it a try: +이 프로그램을 실행시키면, 우리는 프로그램을 강제 정지하기 전까지 `again!`이 반복 출력되는 것을 보게 됩니다. +대부분의 터미널은 ctrl-C를 통해 프로그램을 정지시키는 기능을 지원하니 이를 시도해 보세요: ```text $ cargo run @@ -292,28 +264,23 @@ again! ^Cagain! ``` -The symbol `^C` represents where you pressed ctrl-C. You may or may not see the -word `again!` printed after the `^C`, depending on where the code was in the -loop when it received the halt signal. -Fortunately, Rust provides another, more reliable way to break out of a loop. -You can place the `break` keyword within the loop to tell the program when to -stop executing the loop. Recall that we did this in the guessing game in the -“Quitting After a Correct Guess” section of Chapter 2 to exit the -program when the user won the game by guessing the correct number. +기호 `^C`는 우리가 ctrl-C를 눌렀을 때의 위치입니다. 코드가 정지 신호를 받은 시점에 따라 `^C` 이후에 +`again!`이 출력될 수도 아닐 수도 있습니다. + +다행스럽게도, Rust는 보다 안정적으로 루프에서 벗어날 수 있는 방법을 제공합니다. 우리는 `break` keyword +를 위치시켜 프로그램이 언제 루프를 멈춰야 하는지 알려줄 수 있습니다. 상기시켜 드리자면 2장 “추리 게임”에서 +사용자가 모든 숫자를 정확히 추리했을 경우 프로그램을 종료시키기 위해 사용했었습니다. -#### Conditional Loops with `while` +#### `while`와 함께하는 조건부 반복 -It’s often useful for a program to evaluate a condition within a loop. While -the condition is true, the loop runs. When the condition ceases to be true, you -call `break`, stopping the loop. This loop type could be implemented using a -combination of `loop`, `if`, `else`, and `break`; you could try that now in a -program, if you’d like. +반복문 내에서 조건을 산출하는 것은 자주 유용합니다. 조건이 참인 동안 반복문을 수행합니다. 조건이 참이 아니게 된 경우에 +`break`을 호출하여 반복을 정지시킵니다. 이런 패턴의 반복문을 구현하자면 `loop`, `if`, `else`, 그리고 +`break`를 혼합해야 합니다; 원한다면 이렇게 사용해도 됩니다. -However, this pattern is so common that Rust has a built-in language construct -for it, and it’s called a `while` loop. The following example uses `while`: the -program loops three times, counting down each time. Then, after the loop, it -prints another message and exits: +하지만, 이런 패턴은 매우 보편적이기 때문에 이와 동일한 구조자가 Rust에는 내장되어 있으며, 이를 `while` +반복문이라 부릅니다. 다음의 예제를 통해 `while`을 사용해 봅시다: 프로그램은 세 번 반복되고, 반복 때마다 +카운트 다운됩니다. 마침내 반복이 끝나면 다른 메시지를 출력하고 종료됩니다: Filename: src/main.rs @@ -331,14 +298,12 @@ fn main() { } ``` -This construct eliminates a lot of nesting that would be necessary if you used -`loop`, `if`, `else`, and `break`, and it’s clearer. While a condition holds -true, the code runs; otherwise, it exits the loop. +이 구조자는 loop, if, else 및 break를 사용하는 경우 필요한 많은 중첩을 제거하며, 더 깔끔합니다. +조건이 true인 동안 코드가 실행되고; 그렇지 않으면 루프에서 벗어납니다. -#### Looping Through a Collection with `for` +#### `for`와 함께하는 콜렉션 반복하기 -You could use the `while` construct to loop over the elements of a collection, -such as an array. For example: +우리는 `while` 구조자를 통해 배열과 같은, 콜렉션의 각 요소에 걸쳐 반복 수행 할 수 있습니다. 예: Filename: src/main.rs @@ -358,10 +323,8 @@ fn main() { Listing 3-5: Looping through each element of a collection using a `while` loop -Here, the code counts up through the elements in the array. It starts at index -`0`, and then loops until it reaches the final index in the array (that is, -when `index < 5` is no longer true). Running this code will print out every -element in the array: +여기서, 코드는 배열의 요소에 걸쳐 카운트를 증가시킵니다. 이 색인은 `0`에서 시작하고, 배열의 마지막 순서까지 반복됩니다 +(즉, `index < 5`가 참이 아닐 때까지). 이 코드를 수행하면 배열의 모든 요소가 출력되게 됩니다. ```text $ cargo run @@ -374,17 +337,15 @@ the value is: 40 the value is: 50 ``` -All five array values appear in the terminal, as expected. Even though `index` -will reach a value of `5` at some point, the loop stops executing before trying -to fetch a sixth value from the array. +예상했던 대로, 5개인 배열 모든 값이 터미널에 표시됩니다. `index` 값이 `5`에 오는 시점에, +그러니까 배열의 6번째 값에 접근하기 전에 반복은 중지되어야 합니다. -But this approach is error prone; we could cause the program to panic if the -index length is incorrect. It’s also slow, because the compiler adds runtime -code to perform the conditional check on every element on every iteration -through the loop. +그러나 이런 방식은 에러가 발생하기 쉽습니다; 우리가 정확한 길이의 색인을 사용하지 못하면 프로그램은 패닉을 발생합니다. +또한 느린데, 이유는 컴파일러가 실행 간에 반복문을 통해 반복될 때마다 요소에 대한 조건 검사를 수행하는 런타임 코드를 +추가하기 때문입니다. -As a more efficient alternative, you can use a `for` loop and execute some code -for each item in a collection. A `for` loop looks like this: +보다 효율적은 대안으로, 우리는 `for` 반복문을 사용하여 콜렉션의 각 요소에 대한 코드를 수행할 수 있습니다. +`for`반복문은 다음과 같습니다: Filename: src/main.rs @@ -401,26 +362,19 @@ fn main() { Listing 3-6: Looping through each element of a collection using a `for` loop -When we run this code, we’ll see the same output as in Listing 3-5. More -importantly, we’ve now increased the safety of the code and eliminated the -chance of bugs that might result from going beyond the end of the array or not -going far enough and missing some items. +우리가 이 코드를 수행하면, 항목 3-5와 같은 결과를 볼 수 있습니다. 더 중요한 것은, 우리는 이제 코드의 안전성을 높이고 +배열의 끝을 넘어가거나 충분한 길이를 지정하지 못해 일부 아이템이 누락되어 발생할 수있는 버그의 가능성을 제거했습니다. -For example, in the code in Listing 3-5, if you removed an item from the `a` -array but forgot to update the condition to `while index < 4`, the code would -panic. Using the `for` loop, you don’t need to remember to change any other -code if you changed the number of values in the array. +예를 들어, 코드 3-5의 코드에서 a 배열 에서 항목을 제거 했지만 조건을 `while index < 4`로 업데이트하지 +않으면 코드는 패닉을 발생합니다. for루프를 사용하면, 당신이 배열의 수를 변경 한 경우에도 다른 코드를 변경해야 +할 필요가 없습니다. (역주 : 당신은 살면서 변경한 배열의 수를 기억하고 있는가?) -The safety and conciseness of `for` loops make them the most commonly used loop -construct in Rust. Even in situations in which you want to run some code a -certain number of times, as in the countdown example that used a `while` loop -in Listing 3-5, most Rustaceans would use a `for` loop. The way to do that -would be to use a `Range`, which is a type provided by the standard library -that generates all numbers in sequence starting from one number and ending -before another number. +`for`반복문이 안전하고 간결하기 때문에 이들은 가장 보편적으로 사용되는 반복문 구조자입니다. 항목 3-5에서처럼 +`while`반복문을 사용하여 특정 횟수만큼 코드를 반복하려는 경우에도, 대부분의 Rust 사용자들은 `for`반복문 +을 사용하고자 할 것 입니다. 이런 사용을 위해 Rust에서 기본 라이브러리로 제공하는 `Range`를 사용하게 됩니다. +`Range`는 한 숫자에서 다른 숫자 전까지 모든 숫자를 차례로 생성합니다. -Here’s what the countdown would look like using a `for` loop and another method -we’ve not yet talked about, `rev`, to reverse the range: +여기 `for`반복문과 아직 설명하지 않은 range를 역순하는 `rev`메소드를 사용하는 카운트다운 프로그램이 있습니다: Filename: src/main.rs @@ -433,18 +387,16 @@ fn main() { } ``` -This code is a bit nicer, isn’t it? +꽤 괜찮은 코드인것 같죠? -## Summary +## 결론 -You made it! That was a sizable chapter: you learned about variables, scalar -and `if` expressions, and loops! If you want to practice with the concepts -discussed in this chapter, try building programs to do the following: +해냈어요! 무지 긴 장이었어: 우리는 변수, 스칼라, `if`식과 반복문까지 배웠어요! 혹시 이번 장에서 나온 내용을 +연습해보고 싶으면 다음을 수행하는 프로그램을 만들어 보세요. -* Convert temperatures between Fahrenheit and Celsius. -* Generate the nth Fibonacci number. -* Print the lyrics to the Christmas carol “The Twelve Days of Christmas,” -taking advantage of the repetition in the song. +* 화씨와 섭씨를 상호 변환. +* n번째 피보나치 수열 생성. +* 크리스마스 캐롤 “The Twelve Days of Christmas”의 가사를 반복문을 활용해 출력. -When you’re ready to move on, we’ll talk about a concept in Rust that *doesn’t* -commonly exist in other programming languages: ownership. +다음으로 넘어갈 준비가 되셨습니까? 우리는 이제 일반적인 다른 언어에는 존재하지 않는 개념에 대해서 다루고자 합니다 +: 소유권.