diff --git a/ko/documentation/faq/1/index.md b/ko/documentation/faq/1/index.md index 429e5d4c16..ecfa521563 100644 --- a/ko/documentation/faq/1/index.md +++ b/ko/documentation/faq/1/index.md @@ -15,7 +15,7 @@ header: | | 4 | - 5 + 5 | 6 | diff --git a/ko/documentation/faq/2/index.md b/ko/documentation/faq/2/index.md index 87efee44e1..0545a12435 100644 --- a/ko/documentation/faq/2/index.md +++ b/ko/documentation/faq/2/index.md @@ -15,7 +15,7 @@ header: | | 4 | - 5 + 5 | 6 | diff --git a/ko/documentation/faq/3/index.md b/ko/documentation/faq/3/index.md index a629fb2517..0b609bfba5 100644 --- a/ko/documentation/faq/3/index.md +++ b/ko/documentation/faq/3/index.md @@ -15,7 +15,7 @@ header: | | 4 | - 5 + 5 | 6 | diff --git a/ko/documentation/faq/4/index.md b/ko/documentation/faq/4/index.md index 5c93fad7d7..3539d4f41c 100644 --- a/ko/documentation/faq/4/index.md +++ b/ko/documentation/faq/4/index.md @@ -15,7 +15,7 @@ header: | | 4 | - 5 + 5 | 6 | diff --git a/ko/documentation/faq/5/index.md b/ko/documentation/faq/5/index.md new file mode 100644 index 0000000000..27f50bb88e --- /dev/null +++ b/ko/documentation/faq/5/index.md @@ -0,0 +1,232 @@ +--- +layout: page +title: "공식 Ruby FAQ" +lang: ko + +header: | +
+ 콘텐츠 + | + 1 + | + 2 + | + 3 + | + 4 + | + 5 + | + 6 + | + 7 + | + 8 + | + 9 + | + 10 + | + 11 +
+

공식 Ruby FAQ

+ +--- + +{% include faq-notice.md %} + +## 이터레이터 + +### 이터레이터란 무엇인가요? + +이터레이터는 블록 또는 `Proc` 객체를 받는 메서드입니다. 소스 파일에서 +블록은 메서드 호출 직후에 위치합니다. 이터레이터는 사용자 정의 제어 +구조, 특히 루프를 생성하는 데 사용됩니다. + +이터레이터가 어떻게 작동하는지 예시를 통해 살펴봅시다. 이터레이터는 다음과 같이 +컬렉션의 각 요소에 대해 동일한 작업을 반복하는 데 자주 사용됩니다. + +~~~ +data = [1, 2, 3] +data.each do |i| + puts i +end +~~~ + +결과: + +~~~ +1 +2 +3 +~~~ + +배열 `data`의 each 메서드에는 `do ... end` 블록이 전달되어 반복적으로 +실행됩니다. 호출할 때마다 블록은 배열의 연속적인 요소를 전달받습니다. + +블록을 정의할 때 `do ... end` 대신 `{ ... }`를 쓸 수 있습니다. + +~~~ +data = [1, 2, 3] +data.each { |i| + puts i +} +~~~ + +결과: + +~~~ +1 +2 +3 +~~~ + +이 코드는 전 예제와 동일한 의미를 갖습니다. 그러나 경우에 따라 우선순위 +문제로 인해 `do ... end`와 `{ ... }`가 다르게 동작할 수 있습니다. + +~~~ +foobar a, b do ... end # foobar가 이터레이터. +foobar a, b { ... } # b가 이터레이터. +~~~ + +이는 `{ ... }`는 `do ... end` 블록보다 앞의 표현식에 더 강하게 바인딩되기 +때문입니다. 첫 번째 예는 `foobar(a, b) do ... end`와 같고, 두 번째 예는 +`foobar(a, b { ... })`와 같습니다. + +### 블록을 이터레이터에 전달하려면 어떻게 해야 하나요? + +반복자 호출 뒤에 블록을 배치하기만 하면 됩니다. `Proc`을 참조하는 변수나 상수 +이름 앞에 `&`를 붙여 `Proc` 객체를 전달할 수도 있습니다. + +### 블록은 이터레이터에서 어떻게 사용되나요? + +{% include faq-out-of-date.html %} + +이터레이터 메서드에서 블록을 실행하는 방법에는 세 가지가 있습니다: +(1) `yield` 제어 구조, (2) `call`을 사용하여 (블록으로 만든) `Proc` 인자를 +호출하는 것, (3) `Proc.new`를 사용한 후 호출하는 것 등이 있습니다. + +`yield` 문은 블록을 호출하며, 하나 이상의 인수를 전달할 수 있습니다. + +~~~ +def my_iterator + yield 1, 2 +end + +my_iterator {|a, b| puts a, b } +~~~ + +결과: + +~~~ +1 +2 +~~~ + +메서드 정의에 블록 인수가 있는 경우(마지막 형식 매개 변수 앞에 앰퍼샌드(`&`)가 +붙은 경우) `Proc` 객체로 변환된 첨부된 블록을 받습니다. 이것은 +`proc.call(args)`을 사용하여 호출할 수 있습니다. + +~~~ +def my_iterator(&b) + b.call(1, 2) +end + +my_iterator {|a, b| puts a, b } +~~~ + +결과: + +~~~ +1 +2 +~~~ + +이터레이터 정의에서 `Proc.new`(또는 동치인 `proc`, `lambda` 호출)를 사용하면 +메서드에 주어진 블록을 인수로 받아 프로시저 객체를 생성합니다. (`proc`과 +`lambda`는 사실상 동의어입니다.) + +_[업데이트 필요: `lambda`는 약간 다른 방식으로 작동하며 블록 없이 Proc 객체를 +생성하려고 시도했습니다(`tried to create Proc object without a block`)라는 +경고가 표시됩니다.]_ + +~~~ +def my_iterator + Proc.new.call(3, 4) + proc.call(5, 6) + lambda.call(7, 8) +end + +my_iterator {|a, b| puts a, b } +~~~ + +결과: + +~~~ +3 +4 +5 +6 +7 +8 +~~~ + +놀랍게도 `Proc.new`와 친구들은 메서드에 연결된 블록을 전혀 소비하지 않으며, +`Proc.new`를 호출할 때마다 동일한 블록에서 새 프로시저 객체를 생성합니다. + +블록이 메서드와 연관되어 있는지 여부는 `block_given?`을 호출하여 확인할 수 +있습니다. + +### 블록이 없는 `Proc.new`는 어떤 기능을 하나요? + +블록이 없는 `Proc.new`는 프로시저 객체를 생성할 수 없으며 오류가 발생합니다. +그러나 메서드 정의에서 블록이 없는 `Proc.new`는 메서드가 호출될 때 블록이 +존재한다는 것을 의미하므로 오류가 발생하지 않습니다. + + +### 이터레이터를 병렬로 실행하려면 어떻게 해야 하나요? + +여기 [\[ruby-talk:5252\]][ruby-talk:5252]에서 Matz가 스레드를 사용하는 해결책을 +채택했습니다. + +~~~ +require "thread" + +def combine(*iterators) + queues = [] + threads = [] + + iterators.each do |it| + queue = SizedQueue.new(1) + th = Thread.new(it, queue) do |i, q| + send(i) {|x| q << x } + end + queues << queue + threads << th + end + + loop do + ary = [] + queues.each {|q| ary << q.pop } + yield ary + + iterators.size.times do |i| + return if !threads[i].status && queues[i].empty? + end + end +end + +def it1 + yield 1; yield 2; yield 3 +end + +def it2 + yield 4; yield 5; yield 6 +end + +combine(:it1, :it2) do |x| + # x is [1, 4], then [2, 5], then [3, 6] +end +~~~ + +[ruby-talk:5252]: https://blade.ruby-lang.org/ruby-talk/5252 diff --git a/ko/documentation/faq/index.md b/ko/documentation/faq/index.md index 273977e48e..cc9bc3fdb8 100644 --- a/ko/documentation/faq/index.md +++ b/ko/documentation/faq/index.md @@ -15,7 +15,7 @@ header: | | 4 | - 5 + 5 | 6 | @@ -53,7 +53,7 @@ Stollsteimer에게 감사드립니다. * [Ruby의 경쟁 상대는...?](2/) * [Ruby 설치하기](3/) * [변수, 상수, 인수](4/) -* [이터레이터](/en/documentation/faq/5/) +* [이터레이터](5/) * [구문](/en/documentation/faq/6/) * [메서드](/en/documentation/faq/7/) * [클래스 및 모듈](/en/documentation/faq/8/) diff --git a/ko/documentation/index.md b/ko/documentation/index.md index 471e81f351..843f3ab17f 100644 --- a/ko/documentation/index.md +++ b/ko/documentation/index.md @@ -18,7 +18,7 @@ Ruby를 배울 수 있는 매뉴얼과 튜토리얼, 코딩할 때 도움이 되 ### 초보자용 문서 -[공식 FAQ](/en/documentation/faq/) (영문) +[공식 FAQ](faq/) : 자주 묻는 질문들을 모았습니다. [Ruby Koans][2] (영문) @@ -173,7 +173,7 @@ Ruby를 코딩할 때 운영체제의 기본 편집기를 사용할 수 있습 [kdevelop]: https://www.kdevelop.org/ [kate]: https://kate-editor.org/ -[ko-1]: http://docs.google.com/View?docid=ajb44wcvmjj8_2fg33f2 +[ko-1]: https://docs.google.com/document/d/15yEpi2ZMB2Lld5lA1TANt13SJ_cKygP314cqyKhELwQ/preview [ko-2]: https://web.archive.org/web/20190521035426/http://beyond.daesan.com/pages/ruby-faq [ko-3]: https://groups.google.com/forum/#!forum/rubykr [ko-4]: https://www.facebook.com/groups/rubykr/