• B6b364a4920a7ba8220a449635ca0c59?s=80&d=mm

    Changes from SoonBin

    SoonBin - about 4 years ago (Sep 12, 2015, 11:57 AM)
    패턴
  • Changes have been accepted Merged
      Looks like something's not quite right here.. We've been notified of the issue, and will get back to you soon.
      generics
      # 5.19. 제너릭 (Generics) - 100%

      가끔, 함수나 데이터 타입을 작성할 때 다양한 인자의 타입에 대해 동작하길 원할 때가 있습니다. Rust에서는 제너릭으로 할 수 있습니다. 제너릭 이라는 기능을 제공하는데 더 좋은 방법을 제공 힙니다. 제너릭은 타입이론에서 ‘매개변수 다형성(parametric polymorphism)’ 라고 하는데, 주어진 매개 변수(‘parametric’)에 따라 여러 형태를 갖는 (‘poly’
      는 다수의, ‘morph’ 는 형태를 의미) 타입이나 함수를 의미 합니다.

      타입 이론은 이만하면 됐고, 제너릭 코드를 봅시다. Rust 표준 라이브러리는 `Option` 라고하는 제너릭을 제공합니다:

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

      `` 라는 것을 전에 몇 번 봤을 겁니다. 이것은 제너릭 데이터 타입을 나타냅니다.
      enum 선언 안에 `T` 는 제너릭에서 사용할 타입과 바꿀 수 있습니다. 여기 `Option` 를 사용하는 예가 있는데 추가적인 타입 기호가 있습니다:

      ```rust
      let x: Option = Some(5);
      ```

      `Option` 라고 타입 선언을 했습니다. `Option` 와 얼마나 닮았는지 봅시다.
      이 `Option` 의 경우, `T` 는 `i32` 에 대한 값을 갖습니다. 우측 바인딩에서 `T` 가 `5` 인 `Some(T)` 를 만들 었습니다. `5` 는 `i32` 이기 때문에 양쪽은 일치합니다. 그렇지 않으면 오류가 발생합니다:

      ```rust,ignore
      let x: Option = Some(5);
      // error: mismatched types: expected `core::option::Option`,
      // found `core::option::Option<_>` (expected f64 but found integral variable)
      ```

      오류 메세지는 `f64` 을 갖는 `Option` 를 만들 수 없다는 것이 아니라, 양쪽이 일치해야 한다는 것을 의미 합니다:

      ```rust
      let x: Option = Some(5);
      let y: Option = Some(5.0f64);
      ```

      좋습니다, 한번 정의하고 여러번 사용 합니다.

      제너릭은 하나의 타입에 한정될 필요는 없습니다. rust 표준 라이브러리에서 제공하는 다른 타입을 보죠, `Result` 입니다:

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

      이 타입은 두 개의 타입에 대한 제너릭 입니다: `T` and `E`
      대문자는 아무 것이나 사용해도 됩니다. `Result` 와 같이 정의 할 수도 있습니다:

      ```rust
      enum Result {
      Ok(A),
      Err(Z),
      }
      ```

      관습적으로 제너릭 파라미터는 `타입`을 나타낼 때 `T` 를 사용하고, `에러`를 의미할 때 `E` 를 사용합니다. rust 에서는 신경쓰지 않아도 됩니다.

      `Result` 는 계산 결과를 돌려 주고, 제대로 동작하지 않았을 때 에러를 돌려줄 수 있도록 디자인 된 것입니다.

      ## 제너릭 함수 (Generic functions)

      비슷한 문법을 사용해서 제너릭 타입을 받는 함수를 만들 수 있습니다:

      ```rust
      fn takes_anything(x: T) {
      // do something with x
      }
      ```

      문법은 두 부분으로 나뉘는데,
      `` 는 "이 함수는 하나의 타입 `T`에 대한 제너릭 입니다" 라는 의미 입니다.
      `x: T` 는 "x 는 `T` 타입을 갖는다" 는 의미 입니다.

      여러개의 인자가 같은 제너릭 타입을 갖을 수 도 있습니다:

      ```rust
      fn takes_two_of_the_same_things(x: T, y: T) {
      // ...
      }
      ```

      여려개의 타입을 받는 버전을 작성할 수 도 있습니다:

      ```rust
      fn takes_two_things(x: T, y: U) {
      // ...
      }
      ```

      제너릭 함수는 ‘trait bounds’ 에서 가장 유용합니다, [traits 섹션](traits.html) 에서 다룰 에정 입니다.

      ## 제너릭 구조체 (Generic structs)

      제너릭 타입을 `struct` 에서도 사용할 수 있습니다:

      ```rust
      struct Point {
      x: T,
      y: T,
      }

      let int_origin = Point { x: 0, y: 0 };
      let float_origin = Point { x: 0.0, y: 0.0 };
      ```

      함수와 비슷하게, 제너릭 파라미터를 선언하는데 `` 를 사용하고, 타입 선언에서 `x: T` 를 사용합니다.
      patterns
      # 5.15. 패턴 (Patterns) - 100%

      Patterns are quite common in Rust. We use them in [variable
      bindings][bindings], [match statements][match], and other places, too. Let’s go
      on a whirlwind tour of all of the things patterns can do!

      [bindings]: variable-bindings.html
      [match]: match.html

      A quick refresher: you can match against literals directly, and `_` acts as an
      ‘any’ case:
      패턴은 러스트에서 흔하게 나타납니다. [변수 바인딩][bindings], [정합][match], 그 외에서 사용합니다. 그럼 이러한 패턴들을 한번 잽싸게 살펴봅시다!

      [bindings]: variable-bindings.html
      [match]: match.html

      간단한 복습: 문자 match로 문자 그대로 선언하며, `_`는 '어떤 경우에도'를 나타냅니다.


      ```rust
      let x = 1;

      match x {
      1 => println!("one"),
      2 => println!("two"),
      3 => println!("three"),
      _ => println!("anything"),
      }
      ```

      This prints `one``one`을 출력합니다.

      # Multiple patterns

      You can match multiple patterns with `|`다수의 패턴을 `|`로 묶을 수 있습니다:

      ```rust
      let x = 1;

      match x {
      1 | 2 => println!("one or two"),
      3 => println!("three"),
      _ => println!("anything"),
      }
      ```

      This prints `one or two`를 출력합니다.

      # Ranges

      You can match a range of values with `...`값의 범위를 `...`로 묶을 수 있습니다:

      ```rust
      let x = 1;

      match x {
      1 ... 5 => println!("one through five"),
      _ => println!("anything"),
      }
      ```

      This prints `one through five`.

      Ranges are mostly used with integers and `char`s
      를 출력하게 됩니다.

      범위는 정수형과 `char`형에 가장 널리 쓰입니다
      :

      ```rust
      let x = '💅';

      match x {
      'a' ... 'j' => println!("early letter"),
      'k' ... 'z' => println!("late letter"),
      _ => println!("something else"),
      }
      ```

      This prints `something else`를 출력하게 되겠죠.

      # Bindings

      You can bind values to names with `@``@`를 써서 변수를 이름에 바인딩할 수 있습니다:

      ```rust
      let x = 1;

      match x {
      e @ 1 ... 5 => println!("got a range element {}", e),
      _ => println!("anything"),
      }
      ```

      This prints `got a range element 1`. This is useful when you want to
      do a complicated match of part of a data structure
      를 출력합니다. 데이터 구조 일부분에 복잡한 작업을 하려고 할 때에 유용합니다:

      ```rust
      #[derive(Debug)]
      struct Person {
      name: Option,
      }

      let name = "Steve".to_string();
      let mut x: Option = Some(Person { name: Some(name) });
      match x {
      Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
      _ => {}
      }
      ```

      This prints `Some("Steve")`: We’ve bound the inner를 출력합니다: 내부의 `name` to `a`.

      If you use `@` with `|`, you need to make sure the name is bound in each part
      of the pattern:
      에 대입했습니다.

      `@`를 `|`와 함께 사용한다면, 각 부분들이 모두 이름에 대입된 것을 재확인시켜주어야만 합니다.


      ```rust
      let x = 5;

      match x {
      e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
      _ => println!("anything"),
      }
      ```

      # Ignoring variants

      If you’re matching on an enum which has variants, you can use `..` to
      ignore the value and type in the variant:
      열거형(enum)을 매칭할때는, `..`를 사용해 변수의 세세한 값이나 타입을 무시할 수 있습니다.

      ```rust
      enum OptionalInt {
      Value(i32),
      Missing,
      }

      let x = OptionalInt::Value(5);

      match x {
      OptionalInt::Value(..) => println!("Got an int!"),
      OptionalInt::Missing => println!("No such luck."),
      }
      ```

      This prints `Got an int!`를 출력합니다.

      # Guards

      You can introduce ‘match guards’ with `if``if`를 통해 매치 가드(match guards)를 사용할 수 있습니다:

      ```rust
      enum OptionalInt {
      Value(i32),
      Missing,
      }

      let x = OptionalInt::Value(5);

      match x {
      OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
      OptionalInt::Value(..) => println!("Got an int!"),
      OptionalInt::Missing => println!("No such luck."),
      }
      ```

      This prints `Got an int!`.

      If you’re using `if` with multiple patterns, the `if` applies to both sides
      를 출력합니다.

      `if`를 다수의 패턴과 사용한다면, `if`는 양쪽 모두에 적용됩니다
      :

      ```rust
      let x = 4;
      let y = false;

      match x {
      4 | 5 if y => println!("yes"),
      _ => println!("no"),
      }
      ```

      This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
      just the `5`, In other words, the the precedence of `if` behaves like this:
      `5`에만 적용되는게 아니라, `4 | 5` 모두에 `if`가 적용되기 때문에, `no`를 출력합니다. `if`가 우선순위가 되어 다음과 같이 작동하는 것입니다:
      ```text
      (4 | 5) if y => ...
      ```

      not this

      이렇게가 아니라요
      :

      ```text
      4 | (5 if y) => ...
      ```

      # ref and ref mut

      If you want to get a [reference][ref], use the `ref` keyword[참조][ref]를 얻고 싶다면, `ref` 키워드를 사용합니다:

      ```rust
      let x = 5;

      match x {
      ref r => println!("Got a reference to {}", r),
      }
      ```

      This prints `Got a reference to 5`를 출력합니다.

      [ref]: references-and-borrowing.html

      Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
      keyword _creates_ a reference, for use in the pattern. If you need a mutable
      reference, `ref mut` will work in the same way
      `match`의 `r` 안에는 `&i32` 타입을 가지고 있습니다. `ref` 키워드는 패턴 내에서 참조를 _생성한다는_ 뜻입니다. 만약 변경 가능한(mutable) 참조를 사용한다면, `ref mut`로 써줄 수 있습니다:

      ```rust
      let mut x = 5;

      match x {
      ref mut mr => println!("Got a mutable reference to {}", mr),
      }
      ```

      # Destructuring

      If you have a compound data type, like a [`struct`][struct], you can destructure it
      inside of a pattern:
      [`구조체`][struct]와 같이, 사용하는 데이터 타입이 복합적이라면 패턴 내에서 디스트럭처(destructure)할 수 있습니다.

      ```rust
      struct Point {
      x: i32,
      y: i32,
      }

      let origin = Point { x: 0, y: 0 };

      match origin {
      Point { x, y } => println!("({},{})", x, y),
      }
      ```

      [struct]: structs.html

      We can use `:` to give a value a different name`:`를 써서 값에 다른 이름을 줄 수 있습니다.

      ```rust
      struct Point {
      x: i32,
      y: i32,
      }

      let origin = Point { x: 0, y: 0 };

      match origin {
      Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
      }
      ```

      If we only care about some of the values, we don’t have to give them all names만약 값들 중 몇가지에만 관심이 있다면, 다른 나머지를 써줄 필요가 없습니다:

      ```rust
      struct Point {
      x: i32,
      y: i32,
      }

      let origin = Point { x: 0, y: 0 };

      match origin {
      Point { x, .. } => println!("x is {}", x),
      }
      ```

      This prints `x is 0`.

      You can do this kind of match on any member, not just the first
      `x is 0`을 출력합니다.

      첫번째에만 가능한 것이 아니라, 어떤 종류의 멤버도 매치 가능합니다
      :

      ```rust
      struct Point {
      x: i32,
      y: i32,
      }

      let origin = Point { x: 0, y: 0 };

      match origin {
      Point { y, .. } => println!("y is {}", y),
      }
      ```

      This prints `y is 0`.

      This ‘destructuring’ behavior works on any compound data type, like
      [tuples][tuples] or [enums][enums].

      [tuples]: primitive-types.html#tuples
      [enums]: enums.html

      # Mix and Match

      Whew! That’s a lot of different ways to match things, and they can all be
      mixed and matched, depending on what you’re doing
      `y is 0`을 출력합니다.

      '디스트럭처링(destructuring)'은 [튜플][tuples]이나 [열거형][enums] 등, 어떤 복잡한 데이터 타입에도 작용합니다.

      [tuples]: primitive-types.html#tuples
      [enums]: enums.html

      # Mix and Match

      휴! 당신이 어떻게 쓰느냐에 따라 짜 맞출수 있는(mixed and matched) 아주 많은 매치 방법들이 있습니다
      :

      ```rust,ignore
      match x {
      Foo { x: Some(ref name), y: None } => ...
      }
      ```

      Patterns are very powerful. Make good use of them패턴은 아주 강력합니다. 잘 사용해보세요.