Updated closures.md

hanbum authored
revision 8c713e728fcf57a984a834d41537a0228ab6bd90
closures
# 5.23. 클로저 (Closures) - 10%

가끔 내부 함수와 _자유 변수_(_free variable_)(내부 함수 안에서 정의되지 않은 변수)를 둘러싼 함수가 유용할 때가 있습니다. 자유 변수는 내부 함수와 인접한 영역(scope)에서 갖고 오고, 이 함수를 사용할 때 '닫힙니다(결정됩니다)'. 그렇기 때문에 이런 함수를 '클로저(closure)'라 부릅니다. 러스트는 이것을 정말 잘 지원하고 있습니다.
실제로 살펴보도록 하죠.

## 문법

다음과 같은 클로저가 있습니다:

```rust
let plus_one = |x: i32| x + 1;

assert_eq!(2, plus_one(1));
```

우리는 `plus_one`에 바인딩을 만들어, 클로저에 그것을 할당했습니다. 클로저의 인수(arguments)는 파이프(`|`) 사이에, 몸체(body)에는 표현식을 씁니다. `x + 1` 이 해당됩니다.
`{ }`가 표현식(expression)이라는 것을 기억하시나요? 이걸로 여러 줄로 된 클로저 또한 만들 수 있습니다.

```rust
let plus_two = |x| {
let mut result: i32 = x;

result += 1;
result += 1;

result
};

assert_eq!(4, plus_two(2));
```

클로저가 `fn`으로 정의되는 일반 함수와 약간 다르다는 것을 눈치채셨을 겁니다. 첫번째로 클로저가 받는 인수나 반환값의 타입을 명시해줄 필요가 없다는 것입니다.
물론 명시해 줄 수 있습니다:

```rust
let plus_one = |x: i32| -> i32 { x + 1 };

assert_eq!(2, plus_one(1));
```

그렇지만 그렇게 할 필요가 없습니다. 왜 그럴까요? 기본적으로, 사람이 보다 편하기 위해서입니다. 일반 함수가 문서나 타입 추론에 도움이 되게 하기 위해 타입들을 모두 명시하는 반면에, 클로저는 익명함수로써 error-at-a-distance 종류의 문제를 일으키지 않기 때문에 좀처럼 그렇게 하지 않습니다.

두번째는 문법이 비슷하지만, 조금은 다르다는 것입니다. 간단한 비교를 해보죠.

```rust
fn plus_one_v1 (x: i32 ) -> i32 { x + 1 }
let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: i32 | x + 1 ;
```

조금 다르긴 하지만 그래도 비슷합니다.

## 클로저와 그 환경(environment)

클로저의 환경은 그것을 둘러싼 영역의 변수는 물론 바인딩까지도 포함합니다.
다음을 보면:

```rust
let num = 5;
let plus_num = |x: i32| x + num;

assert_eq!(10, plus_num(5));
```

`plus_num` 이라는 클로저는, 본인이 속한 영역에서 `let` 을 통해 바인딩되어 있는 `num`을 참조합니다. 정확히 말하면, 그 바인딩을 빌리게 됩니다. 만약 우리가 바인딩 된 이것을 가지고 뭔가 하게 되면 충돌이 발생하고, 이런 에러가 납니다:


```rust,ignore
let mut num = 5;
let plus_num = |x: i32| x + num;

let y = &mut num;
```

이런 에러 메시지도 같이요:

```text
error: cannot borrow `num` as mutable because it is also borrowed as immutable
let y = &mut num;
^~~
note: previous borrow of `num` occurs here due to use in closure; the immutable
borrow prevents subsequent moves or mutable borrows of `num` until the borrow
ends
let plus_num = |x| x + num;
^~~~~~~~~~~
note: previous borrow ends here
fn main() {
let mut num = 5;
let plus_num = |x| x + num;

let y = &mut num;
}
^
```

장황하긴 하지만 유용한 에러 메시지에서 볼 수 있듯이, 우리는 `num`을 변화 가능한 형태로 빌릴 수 없는데, 이유는 클로저가 이미 `num`을 빌리는 중이기 때문입니다. 그렇기 때문에 클로저의 영역 바깥에서나 `num`을 빌릴 수 있습니다:

```rust
let mut num = 5;
{
let plus_num = |x: i32| x + num;

} // plus_num goes out of scope, borrow of num ends

let y = &mut num;
```

그러나 클로저가 소유권을 달라고 하면 Rust는 소유권을 가져가고 대신 환경을 옮겨(move)버립니다. 다음 코드는 동작하지 않습니다:

```rust,ignore
let nums = vec![1, 2, 3];

let takes_nums = || nums;

println!("{:?}", nums);
```

에러메시지는 이렇습니다:

```text
note: `nums` moved into closure environment here because it has type
`[closure(()) -> collections::vec::Vec]`, which is non-copyable
let takes_nums = || nums;
^~~~~~~
```

`Vec`는 자신 내부 요소들에 대해 소유권을 갖기 때문에, 클로저에서 이를 참조하려면 `nums`의 소유권을 얻을 필요가 있습니다. 말하자면 `nums`를 함수에서 사용하려면 `nums`의 소유권도 같이 전달하는 것과 같죠.


## `move` 클로저

`move` 키워드로 클로저가 자신의 환경의 소유권을 가져가도록 할 수 있습니다:

```rust
let num = 5;

let owns_num = move |x: i32| x + num;
```

이 경우는 `move` 키워드가 있는데도 변수는 그냥 일반적인 이동을 따릅니다. 이 경우 `5`가 `Copy`되고, `owns_num`는 복사된 `num`의 소유권을 가져갑니다. 차이점이 뭘까요?

```rust
let mut num = 5;

{
let mut add_num = |x: i32| num += x;

add_num(5);
}

assert_eq!(10, num);
```

이번에는 클로저가 변경가능한 `num`의 리퍼런스를 가져가기 때문에 `add_num`를 호출하면, `num` 값이 변경될 겁니다. 환경이 변하기 때문에 `add_num` 을 `mut`로 선언해야 합니다.

`move` 클로저로 바꾸면 이렇게 달라집니다:

```rust
let mut num = 5;

{
let mut add_num = move |x: i32| num += x;

add_num(5);
}

assert_eq!(5, num);
```

이렇게 하면 그냥 `5`가 나옵니다. 변경가능한 `num`을 빌려오는 대신에 그냥 `num`을 복사한 값의 소유권을 갖고 온 거죠.

이렇게도 생각해 볼까요. `move` 클로저는 클로저에게 자기만의 스택 공간을 줍니다. `move` 가 없으면 클로저는 생성될 때의 스택에 묶이겠죠. 말하자면 `move` 클로저는 컨테이너라고 할 수 있습니다. 즉 예를 들어서, 일반적으로 함수 내에서 `move` 클로저가 아닌 클로저를 반환하는 것은 불가능합니다.

클로저를 취하고 반환하는 법을 더 자세히 다루기 전에, 클로저를 구현하는 방식에 대해서 더 다뤄 봅시다. 시스템 언어인 러스트는 코드로 통제할 수 있는 부분이 엄청나게 많고, 이는 클로저도 마찬가지입니다.

## Closure implementation 클로저 구현

러스트에서 클로저를 구현하는 방식은 다른 언어와는 약간 다르다. 그들은 traits를 위한 효과적 문법 설탕이다. 이에 대해 더 알고 싶다면 traits chapter를 살펴보거나 그 전에 trait-object 챕터를 읽어보도록 해라.
Rust’s implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. You’ll want to make sure to have read
the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects].

[traits]: traits.html
[trait-objects]: trait-objects.html

다 읽었나? 좋아.
Got all that? Good.

클로저를 이해하는 방식의 키는 조금 낯설 수도 있다. `foo()`와 같은 방식으로 `()`를 사용하여 함수를 호출하게 되는데, 이는 오버로드 가능한 연산자이다. 이런 방식은 다른 모든 것에도 동일하게 적용된다.( 역주: `()`라는 오퍼레이션이 오버로드 되어 함수 호출자가 되는 것과 동일 방식) 러스트에서는 trait 시스템을 연산자 오버로드에 사용한다. 함수를 호출하는 것도 다른지 않다. 우리는 이를 위해 세 개의 traits를 사용한다.
The key to understanding how closures work under the hood is something a bit
strange: Using `()` to call a function, like `foo()`, is an overloadable
operator. From this, everything else clicks into place. In Rust, we use the
trait system to overload operators. Calling functions is no different. We have
three separate traits to overload with:

```rust
# mod foo {
pub trait Fn : FnMut {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

pub trait FnMut : FnOnce {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

pub trait FnOnce {
type Output;

extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
# }
```

몇 가지 차이점들이 눈에 띄지만, 가장 중요한 것은 `self`:`Fn`이 `&self`를 취하고, `FnMut`이 `&mut self`를 취하며 `FnOnce`는 `self`를 취한다는 점이다. 이 세 가지 형태의 `self`는 모두 함수 호출 문법으로 사용된다. 하지만 우리는 이것을 하나보다는 세개의 traits으로 나누어 구현했다. 이것이 우리가 사용할 수 있는 클로저에 많은 권한을 부여한다.
You’ll notice a few differences between these traits, but a big one is `self`:
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
covers all three kinds of `self` via the usual method call syntax. But we’ve
split them up into three traits, rather than having a single one. This gives us
a large amount of control over what kind of closures we can take.

클로저 문법인 `|| {}`이 이 세개의 traits를 위한 요소이다. 러스트는 환경을 위한 구조체를 만들고, 적절한 trait을 `impl` 하여, 사용하게 된다.
The `|| {}` syntax for closures is sugar for these three traits. Rust will
generate a struct for the environment, `impl` the appropriate trait, and then
use it.


## Taking closures as arguments
클로저의 인자 값 취하기

이제 우리는 클로저가 traits임을 알게 됐으니, 이를 통해 클로저로 인자 값을 받거나 리턴하는 방법도 알게 됐다. 그냥 다른 trait처럼 사용하면 된다!

Now that we know that closures are traits, we already know how to accept and
return closures: just like any other trait!

이것은 또한 우리가 static 혹은 dynamic 한 방식을 취할 수 있음을 뜻한다. 첫 째로, 호출할 수 있는 함수를 만들어 호출하고 리턴하는 함수를 만들어보자. 이렇게 :
This also means that we can choose static vs dynamic dispatch as well. First,
let’s write a function which takes something callable, calls it, and returns
the result:

```rust
fn call_with_one(some_closure: F) -> i32
where F : Fn(i32) -> i32 {

some_closure(1)
}

let answer = call_with_one(|x| x + 2);

assert_eq!(3, answer);
```
우리는 클로저 `|x| x + 2`를 `call_with_one`으로 전달한다. 이것은 보다시피: 클로저를 호출하며, `1`을 인자로 주는 것이다.
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
suggests: it calls the closure, giving it `1` as an argument.

`call_with_one`이란 서명을 좀더 깊게 살펴보자.
Let’s examine the signature of `call_with_one` in more depth:

```rust
fn call_with_one(some_closure: F) -> i32
# where F : Fn(i32) -> i32 {
# some_closure(1) }
```

우리는 하나의 인자를 취하고, 타입은 `F`다. 또한 우리는 `i32`를 반환한다. 이 부분은 그닥 중요하진 않고 다음으로 넘어가자:
We take one parameter, and it has the type `F`. We also return a `i32`. This part
isn’t interesting. The next part is:

```rust
# fn call_with_one(some_closure: F) -> i32
where F : Fn(i32) -> i32 {
# some_closure(1) }
```

`Fn`이 trait이기 때문에, 이를 통해 우리의 제네릭의 범위를 정할 수 있다. 이번 예에서, 우리의 클로저는 `i32`를 인자로 취하고 `i32`를 반환하기에 제네릭의 범위를 `Fn(i32) -> i32`로 사용한다.
Because `Fn` is a trait, we can bound our generic with it. In this case, our closure
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`.

여기에는 또 하나의 키 포인트가 있다: 우리가 trait과 함께 제네릭의 범위를 정하기에, 이것은 다형성을 갖게 되므로, 우리는 static dispatch 를 클로저에서 사용할 수 있다. 이건 훌륭하다! 많은 언어들이, 클로저는 본질적으로 heap 할당을 받고, dynamic dispatch 가 되게 된다. 러스트에서는 클로저 환경을 stack에 할당할 수 있고, static한 방식으로 dispatch 호출을 할 수 있다. 이는 많은 iterator와 그들의 adapter들에서 클로저를 인자로 받는 방식으로 많이 사용된다.
There’s one other key point here: because we’re bounding a generic with a
trait, this will get monomorphized, and therefore, we’ll be doing static
dispatch into the closure. That’s pretty neat. In many languages, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often
take closures as arguments.

당연하게 우리가 dynamic dispatch를 하는 것도 가능하다. trait object를 이렇게 다루면 된다:
Of course, if we want dynamic dispatch, we can get that too. A trait object
handles this case, as usual:

```rust
fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
some_closure(1)
}

let answer = call_with_one(&|x| x + 2);

assert_eq!(3, answer);
```

이번에 우리는 trait object를 `&Fn`으로 취한다. 그리고 우리의 클로저를 `call_with_one`의 인자로 전할 때 `&||`로 참조하여 보낸다.
Now we take a trait object, a `&Fn`. And we have to make a reference
to our closure when we pass it to `call_with_one`, so we use `&||`.


## Function pointers and closures
함수 포인터와 클로저

함수 포인터는 환경없는 클로저의 형태이다. 그렇기에, 우리는 함수 포인터를 클로저를 인자로 기대하는 어떤 함수에도 전달할 수 있고 동작할 것이다:

A function pointer is kind of like a closure that has no environment. As such,
you can pass a function pointer to any function expecting a closure argument,
and it will work:

```rust
fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
some_closure(1)
}

fn add_one(i: i32) -> i32 {
i + 1
}

let f = add_one;

let answer = call_with_one(&f);

assert_eq!(2, answer);
```

이번 예제에서, 우리는 `f`라는 중간 매개가 필요하다고 제약하진 않고, 함수 이름을 사용해도 문제 없다 :
In this example, we don’t strictly need the intermediate variable `f`,
the name of the function works just fine too:

```ignore
let answer = call_with_one(&add_one);
```

## Returning closures
클로저를 반환하기

다양한 상황에서 함수 스타일의 코드에서 클로저를 반환하는 매우 일반적이다. 만약 당신이 클로저를 반한하고자 한다면, 에러를 볼 수 있을 것이다. 처음에는, 낯설게 느껴지겠지만 이해할 수 있을 것이다. 클로저를 함수에서 반환하는 방법을 알아보자:

It’s very common for functional-style code to return closures in various
situations. If you try to return a closure, you may run into an error. At
first, it may seem strange, but we’ll figure it out. Here’s how you’d probably
try to return a closure from a function:

```rust,ignore
fn factory() -> (Fn(i32) -> i32) {
let num = 5;

|x| x + num
}

let f = factory();

let answer = f(1);
assert_eq!(6, answer);
```

위의 코드는 다음과 같은 긴 에러를 보여준다:
This gives us these long, related errors:

```text
error: the trait `core::marker::Sized` is not implemented for the type
`core::ops::Fn(i32) -> i32` [E0277]
fn factory() -> (Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~
note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
fn factory() -> (Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~
error: the trait `core::marker::Sized` is not implemented for the type `core::ops::Fn(i32) -> i32` [E0277]
let f = factory();
^
note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time

let f = factory();
^
```

함수에서 뭔가를 반환하는 경우, 러스트는 타입의 사이즈를 알아야 할 필요가 있다. 하지만 `Fn`이 trait이 된 이후, 이는 많은 다양한 형태의 크기의 사이즈를 갖을 수 있게 됐다: 많은 다양한 형태가 `Fn`으로 구현될 수 있다. 간단한 방법은 사이즈로 뭔가 전해주기 위해, 참조를 취하는 것이고, 참조의 사이즈는 알고 있다. 그래서 다음과 같이 작성해보자:
In order to return something from a function, Rust needs to know what
size the return type is. But since `Fn` is a trait, it could be various
things of various sizes: many different types can implement `Fn`. An easy
way to give something a size is to take a reference to it, as references
have a known size. So we’d write this:

```rust,ignore
fn factory() -> &(Fn(i32) -> i32) {
let num = 5;

|x| x + num
}

let f = factory();

let answer = f(1);
assert_eq!(6, answer);
```

하지만 또 다른 에러가 보이게 된다:
But we get another error:

```text
error: missing lifetime specifier [E0106]
fn factory() -> &(Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~~
```

맞아! 우리가 참조를 취했기에 이에 대한 시한을 설정할 필요가 있다. 하지만 우리 `factory()` 함수는 아무 인자도 없기에 생략하면 발로 차이게 되는 것이다. 어떤 시한을 우리가 선택할 수 있을까? `'static`:
Right. Because we have a reference, we need to give it a lifetime. But
our `factory()` function takes no arguments, so elision doesn’t kick in
here. What lifetime can we choose? `'static`:

```rust,ignore
fn factory() -> &'static (Fn(i32) -> i32) {
let num = 5;

|x| x + num
}

let f = factory();

let answer = f(1);
assert_eq!(6, answer);
```

하지만 또 다른 에러가 난다:
But we get another error:

```text
error: mismatched types:
expected `&'static core::ops::Fn(i32) -> i32`,
found `[closure :7:9: 7:20]`
(expected &-ptr,
found closure) [E0308]
|x| x + num
^~~~~~~~~~~

```
이번 에러는 우리에게 `&'static Fn(i32) -> i32` 가 아니라 `[closure :7:9: 7:20]`를 다루고 있다고 알려준다. 잠깐, 뭐라?
This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
we have a `[closure :7:9: 7:20]`. Wait, what?

이유는 각 클로저가 그들 고유의 `struct`환경을 갖고 `Fn`을 함께 구현된 코드를 생산하기 때문에, 이 타입들은 익명이 된다. 이들은 고유하게 해당 클로저를 위해서만 존재한다. 그래서 러스트는 `closure `라고 보여주고, 이는 자동으로 생성된 이름이다.
Because each closure generates its own environment `struct` and implementation
of `Fn` and friends, these types are anonymous. They exist just solely for
this closure. So Rust shows them as `closure `, rather than some
autogenerated name.

그렇다고 하더라도 왜 클로저는 `&'static Fn`이 아닐까? 글쎄, 우리가 이전에 토의했 듯, 클로저는 그들의 환경을 대여한다. 그리고 이번 케이스에서 우리의 환경은 stack 할당된 `num` 변수에 바인딩 되어 있는 `5`를 기반하고 있다. 그래서 시한은 stack frame에 달려있다. (역주:stack이 해제되면 자동으로 소멸) 그래서 우리가 해당 클로저를 반환하게 되면, 함수 호출이 끝나고, stack frame이 소멸되고, 우리의 클로저 환경은 쓰레기 메모리에 위치하게 될 것이다!
But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before,
closures borrow their environment. And in this case, our environment is based
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
of the stack frame. So if we returned this closure, the function call would be
over, the stack frame would go away, and our closure is capturing an environment
of garbage memory!

그래서 어떻게 해야 할까? 이는 거의 될 것 같다:
So what to do? This _almost_ works:

```rust,ignore
fn factory() -> Box i32> {
let num = 5;

Box::new(|x| x + num)
}
# fn main() {
let f = factory();

let answer = f(1);
assert_eq!(6, answer);
# }
```

우리는 trait object를 `Box` 포장한 `Fn`을 통해 사용한다. 여기에 마지막 문제가 있다:
We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:

```text
error: closure may outlive the current function, but it borrows `num`,
which is owned by the current function [E0373]
Box::new(|x| x + num)
^~~~~~~~~~~
```

우리는 아직 기원 stack frame의 참조를 하고 있다. 마지막 수정을 해보자:
We still have a reference to the parent stack frame. With one last fix, we can
make this work:

```rust
fn factory() -> Box i32> {
let num = 5;

Box::new(move |x| x + num)
}
# fn main() {
let f = factory();

let answer = f(1);
assert_eq!(6, answer);
# }
```

내부 클로저를 `move Fn`으로 만듬으로, 우리는 새로운 stack frame을 클로저에게 주어줬다. `Box`포장을 통해, 우리는 사이즈를 알 수 있게 해줬고, 이는 stack frame에서 빠져나오게 한다.

By making the inner closure a `move Fn`, we create a new stack frame for our
closure. By `Box`ing it up, we’ve given it a known size, and allowing it to
escape our stack frame.