#programminglanguage #rust
> [!introduction]
> 러스트에서는 마치 어떤 값을 다루는 것처럼 함수를 변수에 저장하거나, 다른 함수에 인자로 전달할 수도 있습니다. 이번 글에서는 값처럼 다루어지는 익명 함수, 클로저*closure*에 대해 알아봅니다.
## 논리를 저장하다
```rust
//unwrap_or_else를 사용하면 Result가 Ok일 때 Ok 안의 값을 반환하고, Err일 때 클로저 안의 코드를 호출한다.
let config = Config::build(&args).unwrap_or_else(|err| {
//표준 에러 출력을 위한 eprintln! 매크로
eprintln!("Problem parsing arguments: {err}");
process::exit(1);
});
```
위에 주어진 예시 코드에서 `unwrap_or_else` 메서드 안에 클로저 표현식이 사용되었는데, 이 메서드를 호출한 인스턴스가 의도된 타입이 아닐 때 인자로 주어진 클로저를 실행하게 된다.
사실 클로저 표현식은 함수와 유사한데, `fn`과 소괄호`()`를 쓰지 않는 대신. `||` 사이에 매개변수가 들어가고 중괄호를 통해 함수 본문을 정의하면 된다. 그럼에도 불구하고 클로저가 함수와 동떨어져 보이는 것은 일반적으로 클로저를 작성할 때 매개변수와 반환 값의 타입을 명시하지 않고 때에 따라서는 중괄호`{}`도 생략하기 때문인데, 생략된 코드를 추가하면 다음과 같다.
```rust
let config = Config::build(&args).unwrap_or_else(|err: &str| {
//표준 에러 출력을 위한 eprintln! 매크로
eprintln!("Problem parsing arguments: {err}");
process::exit(1);
});
```
이렇듯 클로저에서 사용되는 매개변수와 반환 값의 타입은 컴파일러가 알아서 추론하기 때문에, 같은 클로저를 여러 번 사용할 때 처음과 다른 타입의 인자를 넣으면 에러가 발생한다.
```rust
// closure-example/main.rs
let example_closure = |x| x;
let s = example_closure(String::from("hello"));
let n = example_closure(5);
```
```bash
$ cargo run
Compiling closure-example v0.1.0 (file:///projects/closure-example)
error[E0308]: mismatched types
--> src/main.rs:5:29
|
5 | let n = example_closure(5);
| --------------- ^- help: try using a conversion method: `.to_string()`
| | |
| | expected struct `String`, found integer
| arguments to this function are incorrect
|
note: closure parameter defined here
--> src/main.rs:2:28
|
2 | let example_closure = |x| x;
| ^
For more information about this error, try `rustc --explain E0308`.
error: could not compile `closure-example` due to previous error
```
---
## 참고 자료 & 더보기
+ [The Rust Programming Language(한국어판), 13. 함수형 언어의 특성: 반복자와 클로저](https://doc.rust-kr.org/ch13-00-functional-features.html)
+ [The Rust Programming Language(한국어판), 19.4. 고급 함수와 클로저](https://doc.rust-kr.org/ch19-05-advanced-functions-and-closures.html)