diff --git a/ko/documentation/faq/1/index.md b/ko/documentation/faq/1/index.md index a6d4fe6b4d..e98913f95c 100644 --- a/ko/documentation/faq/1/index.md +++ b/ko/documentation/faq/1/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

@@ -310,7 +310,7 @@ Ruby의 구문은 Ruby 1.0 이후 상당히 안정적이지만 때때로 새로 문제가 있는 소스 코드와 함께 `ruby -v`의 출력을 첨부하세요. -[`irb`](/en/documentation/faq/10/#irb)를 사용하는 데 문제가 있는 경우 몇 가지 +[`irb`](../10/#irb)를 사용하는 데 문제가 있는 경우 몇 가지 제한 사항이 있다는 점에 유의하세요. `irb --single-irb`를 사용하거나 `ruby` 명령을 직접 사용하여 스크립트를 사용해 보세요. diff --git a/ko/documentation/faq/10/index.md b/ko/documentation/faq/10/index.md new file mode 100644 index 0000000000..d8202c9deb --- /dev/null +++ b/ko/documentation/faq/10/index.md @@ -0,0 +1,140 @@ +--- +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 %} + +## 확장 라이브러리 + +### Ruby를 대화형으로 사용하려면 어떻게 해야 하나요? +{: #irb} + +{% include faq-out-of-date.html %} + +`irb`를 사용해 보세요. 다음은 고토 켄타로(Gotoken)의 글을 의역한 것으로, +원래는 [\[ruby-talk:444\]][ruby-talk:444]에 실린 내용입니다. + +1. Ruby 아카이브의 [contrib 디렉터리](ftp://ftp.netlab.co.jp/pub/lang/ruby/contrib/)에서 + `irb`의 최신 타볼을 가져옵니다. +2. `irb` 디렉터리 트리를 압축해제합니다. +3. `irb/` 디렉터리 위치를 `$RUBYLIB` 환경 변수에 추가합니다. +4. 경로 어딘가에 `$RUBYLIB/irb/irb.rb`를 가리키는 `irb`라는 심볼릭 링크를 + 만듭니다. +5. `chmod +x $RUBYLIB/irb/irb.rb` +6. 'rehash'를 사용하여 로그인 셸에 새 명령에 대해 알려줄 수 있습니다. +7. `irb`를 입력합니다. + +readline 확장 모듈이 인터프리터와 함께 작동하면 `irb`를 훨씬 더 재미있게 사용할 +수 있습니다. + +Ruby 배포판의 `samples/` 디렉터리에 `eval`이라는 간단한 프로그램도 있습니다. +이 프로그램을 사용하면 표현식을 입력하고 그 값을 볼 수 있습니다. `eval`을 +Ruby 트리의 `site_ruby` 디렉터리에 복사하고 다음을 통해 호출할 수 +있습니다. + +~~~ +ruby -r eval -e0 +~~~ + +[ruby-talk:444]: https://blade.ruby-lang.org/ruby-talk/444 + +### Ruby용 디버거가 있나요? + +Ruby용 gdb와 유사한 디버거가 있습니다. + +~~~ +ruby -r debug your_program +~~~ + +### Ruby에서 C로 작성된 라이브러리를 사용하려면 어떻게 해야 하나요? + +모든 스크립팅 언어 중에서 Ruby는 아마도 가장 확장하기 쉬운 언어일 것입니다. +참조 카운팅과 변수 유형에 대한 문제가 없고 배울 인터페이스도 거의 없습니다. +실제로 Ruby를 확장하는 데 사용되는 C 코드는 놀랍게도 Ruby 코드 자체와 비슷하게 +보이는 경우가 많습니다. + +먼저 Ruby 소스에서 `doc/extension.rdoc` 파일을 읽거나 +[docs.ruby-lang.org][extension-rdoc]의 extension.rdoc을 읽어보세요. 확장 +라이브러리를 작성하는 경우뿐만 아니라 Ruby를 더 깊이 이해하고자 하는 경우에도 +좋은 문서입니다. + +그런 다음 RubyGems 사이트에서 [확장을 사용한 젬 생성 가이드][rubygems-guide]를 +제공합니다. +여기에는 설치 시 빌드되는 C 확장을 사용하여 젬을 설정하는 방법이 나와 있습니다. +또한 C 라이브러리를 래핑하는 일부 기존 젬에 대한 링크와 추가 읽을거리에 대한 +링크도 있습니다. + +인터프리터 자체의 소스와 `ext/` 디렉터리에서 제공되는 다양한 확장기능을 +살펴볼 수도 있습니다(GitHub에서 [Ruby 저장소][ruby-github]를 찾아볼 수 있습니다). + +[extension-rdoc]: https://docs.ruby-lang.org/en/master/extension_rdoc.html +[rubygems-guide]: http://guides.rubygems.org/gems-with-extensions/ +[ruby-github]: https://github.com/ruby/ruby + +### Ruby에서 Tcl/Tk를 사용할 수 있나요? + +{% include faq-out-of-date.html %} + +표준 배포판에는 Tcl/Tk에 대한 두 개의 인터페이스가 포함되어 있습니다. 하나는 +`ext/tcltk/` 아래에 있으며 `require "tcltk"`로 로드됩니다. 이 구문은 Tcl +인터프리터에 전달되는 Tcl과 매우 유사합니다. 안타깝게도 이 라이브러리에 대한 +설명은 일본어로 작성되어 있습니다. + +다른 하나는 `ext/tk/` 아래에 있으며 `require "tk"`로 로드됩니다. 이 구문은 +Perl 및 Python 인터페이스에서 제공하는 Tk 인터페이스 스타일에 더 가깝습니다. + +### Tk가 작동하지 않습니다. 왜 그럴까요? + +{% include faq-out-of-date.html %} + +Tk 버전이 오래되었을 수 있으니 최신 버전을 사용해 보세요. + +### Ruby에서 gtk+나 xforms 인터페이스를 사용할 수 있나요? + +{% include faq-out-of-date.html %} + +Ruby ftp 사이트의 `contrib/`에서 `ruby-gtk-x.xx.tar.gz`, +`ruby-forms-x.x.tar.gz`를 찾을 수 있습니다. + +### 날짜 계산은 어떻게 하나요? + +{% include faq-out-of-date.html %} + +`Time` 개체는 1970년 1월 1일부터 2038년 1월 19일 사이의 날짜만 표현 +할 수 있습니다. + +두 가지 표준 확장 라이브러리 모듈이 제공됩니다. 단순하고 영어 달력을 사용하는 +`require "date"`와 보다 일반적인 용도의 `require "date2"`가 있습니다. + +`sample/cal.rb`도 참조하세요. diff --git a/ko/documentation/faq/11/index.md b/ko/documentation/faq/11/index.md new file mode 100644 index 0000000000..943079cb61 --- /dev/null +++ b/ko/documentation/faq/11/index.md @@ -0,0 +1,187 @@ +--- +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 %} + +## 기타 기능 + +### `a ? b : c`는 무엇을 의미하나요? + +이것은 "삼항 연산자"라고 하며, 'if a then b else c end'와 +동일합니다. + +### 파일의 줄 수를 계산하려면 어떻게 해야 하나요? + +다음 코드가 가장 빠른 결과를 제공할 수 있습니다. + +~~~ +File.readlines("example").size # => 3 +~~~ + +### `MatchData#begin`과 `MatchData#end`는 무엇을 반환하나요? + +이 함수는 `$~`와 함께 작동하며 원본 문자열에서 일치하는 데이터의 시작 인덱스와 +끝 인덱스를 반환합니다. [탭 확장](../9/#tab-expansion)에서 예제를 참조하세요. + +### 배열의 요소를 합산하려면 어떻게 해야 하나요? + +{% include faq-out-of-date.html %} + +특정 문제를 해결하기보다는 일반적인 경우를 해결해 봅시다. 가장 먼저 할 일은 +`Enumerable` 객체를 반복하고 단일 결과를 수집하는 메서드를 생성하는 것입니다. +Smalltalk는 이 메소드를 inject라고 부르기 때문에 우리도 그렇게 부르겠습니다. + +~~~ +module Enumerable + + # inject(n) {|n, i| ...} + def inject(n) + each {|i| n = yield(n, i) } + + n + end +end +~~~ + +`Enumerable`에 메서드를 추가한 것을 주목하세요. 즉, Enumerable을 포함하는 모든 +곳에서 이제 `inject`를 사용할 수 있습니다. 하지만 어떻게 사용할까요? 하나의 +인자 `n`과 블록이 필요합니다. 열거되는 대상의 각 요소에 대해 `n`과 요소 자체를 +전달하면서 블록을 호출합니다. 블록의 결과는 다시 `n`에 할당됩니다. 따라서 +`sum`을 정의하기 위해 다음과 같이 작성할 수 있습니다: + +~~~ +module Enumerable + def sum + inject(0) {|n, i| n + i } + end +end + +[1,3,5,7,9].sum # => 25 +(1..100).sum # => 5050 +~~~ + +### 연속은 어떻게 사용하나요? + +{% include faq-out-of-date.html %} + +Ruby의 연속을 사용하면 Ruby 프로그램에서 특정 장소를 나타내는 객체를 생성한 +다음 언제든지 해당 장소로 돌아갈 수 있습니다(범위를 벗어난 것처럼 보이 +는 경우에도). 연속은 복잡한 제어 구조를 구현하는 데 사용할 수 있지만 +일반적으로는 사람들에게 혼란을 더하기만 합니다. + +[\[ruby-talk:4482\]][ruby-talk:4482]에서 Jim Weirich가 다음과 같은 연속 예제를 +게시했습니다. + +~~~ +# -------------------------------------------------------------------- +# 단순 생산자/소비자 +# -------------------------------------------------------------------- +# 연속을 사용하여 단순 계산 작업과 인쇄 작업을 함께 연결합니다. +# +# 사용법: count(limit) + +def count_task(count, consumer) + (1..count).each do |i| + callcc {|cc| consumer.call cc, i } + end + nil +end + +def print_task() + producer, i = callcc { |cc| return cc } + print "#{i} " + callcc { |cc| producer.call } +end + +def count(limit) + count_task(limit, print_task()) + print "\n" +end +~~~ + + +~~~ +# -------------------------------------------------------------------- +# 주어진 숫자의 배수 필터링하기 +# -------------------------------------------------------------------- +# 소비자이면서 동시에 생산자인 필터를 만듭니다. 카운팅 작업과 인쇄 작업 사이에 +# 삽입합니다. +# +# 사용법: omit(2, limit) + +def filter_task(factor, consumer) + producer, i = callcc { |cc| return cc } + if (i%factor) != 0 then + callcc { |cc| consumer.call cc, i } + end + producer.call +end + +def omit(factor, limit) + printer = print_task() + filter = filter_task(factor, printer) + count_task(limit, filter) + print "\n" +end +~~~ + + +~~~ +# -------------------------------------------------------------------- +# 소수 생성기 +# -------------------------------------------------------------------- +# 소수 생성기를 생성합니다. 새로운 소수가 발견되면 +# 생산자와 소비자의 체인에 새로운 다중 필터를 동적으로 추가합니다. +# +# 사용법: primes(limit) + +def prime_task(consumer) + producer, i = callcc { |cc| return cc } + if i >= 2 then + callcc { |cc| consumer.call cc, i } + consumer = filter_task(i, consumer) + end + producer.call +end + +def primes(limit) + printer = print_task() + primes = prime_task(printer) + count_task(limit, primes) + print "\n" +end +~~~ + +[ruby-talk:4482]: https://blade.ruby-lang.org/ruby-talk/4482 diff --git a/ko/documentation/faq/2/index.md b/ko/documentation/faq/2/index.md index 8a85dbda84..e8b5e322be 100644 --- a/ko/documentation/faq/2/index.md +++ b/ko/documentation/faq/2/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/3/index.md b/ko/documentation/faq/3/index.md index aee05f53c9..e001e4456b 100644 --- a/ko/documentation/faq/3/index.md +++ b/ko/documentation/faq/3/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/4/index.md b/ko/documentation/faq/4/index.md index 7a3ee03b25..d71cc82152 100644 --- a/ko/documentation/faq/4/index.md +++ b/ko/documentation/faq/4/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/5/index.md b/ko/documentation/faq/5/index.md index 1d198861e6..6057a6862d 100644 --- a/ko/documentation/faq/5/index.md +++ b/ko/documentation/faq/5/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/6/index.md b/ko/documentation/faq/6/index.md index 579b51b3b5..10d5a4b550 100644 --- a/ko/documentation/faq/6/index.md +++ b/ko/documentation/faq/6/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/7/index.md b/ko/documentation/faq/7/index.md index ea95d2981f..6b95abee24 100644 --- a/ko/documentation/faq/7/index.md +++ b/ko/documentation/faq/7/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

diff --git a/ko/documentation/faq/8/index.md b/ko/documentation/faq/8/index.md new file mode 100644 index 0000000000..f4490efbf9 --- /dev/null +++ b/ko/documentation/faq/8/index.md @@ -0,0 +1,371 @@ +--- +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 %} + +## 클래스와 모듈 + +### 클래스 정의를 반복할 수 있나요? + +클래스는 반복해서 정의할 수 있습니다. 각 정의는 마지막 정의에 추가됩니다. +메서드가 재정의되면 이전 메서드가 재정의되고 사라집니다. + +### 클래스 변수가 있나요? + +있습니다. 앞에 기호(`@@`) 두 개가 붙은 변수는 클래스 변수로, 클래스의 인스턴스 +메서드와 클래스 메서드 모두에서 접근할 수 있습니다. + +~~~ +class Entity + + @@instances = 0 + + def initialize + @@instances += 1 + @number = @@instances + end + + def who_am_i + "I'm #{@number} of #{@@instances}" + end + + def self.total + @@instances + end +end + +entities = Array.new(9) { Entity.new } + +entities[6].who_am_i # => "I'm 7 of 9" +Entity.total # => 9 +~~~ + +하지만 클래스 변수 대신 _클래스 인스턴스 변수_를 사용해야 합니다. + +### 클래스 인스턴스 변수는 무엇인가요? + +여기서는 클래스 인스턴스 변수를 사용하여 이전 섹션의 예제를 다시 작성했습니다. + +~~~ +class Entity + + @instances = 0 + + class << self + attr_accessor :instances # 읽기/쓰기를 위한 클래스 메서드 제공 + end + + def initialize + self.class.instances += 1 + @number = self.class.instances + end + + def who_am_i + "I'm #{@number} of #{self.class.instances}" + end + + def self.total + @instances + end +end + +entities = Array.new(9) { Entity.new } + +entities[6].who_am_i # => "I'm 7 of 9" +Entity.instances # => 9 +Entity.total # => 9 +~~~ + +여기서 `@instances`는 _클래스_ 인스턴스 변수입니다. 이 변수는 `Entity` +클래스의 인스턴스에 속하는 것이 아니라 `Class` 클래스의 인스턴스인 +클래스 객체 `Entity`에 속합니다. + +클래스 인스턴스 변수는 클래스의 클래스 메서드 내에서만 직접 접근할 수 +있습니다. + +### 클래스 변수와 클래스 인스턴스 변수의 차이점은 무엇인가요? + +주요 차이점은 상속과 관련된 동작입니다. 클래스 변수는 클래스와 모든 서브클래스 +간에 공유되는 반면, 클래스 인스턴스 변수는 특정 클래스 하나에만 속합니다. + +클래스 변수는 어떤 식으로든 상속 계층 구조에서의 전역 변수로 볼 수 +있으며, 전역 변수가 가진 모든 문제가 존재합니다. +예를 들어, 클래스 변수가 (실수로) 서브클래스에 의해 재할당되어 다른 모든 +클래스에 영향을 미칠 수 있습니다. + +~~~ +class Woof + + @@sound = "woof" + + def self.sound + @@sound + end +end + +Woof.sound # => "woof" + +class LoudWoof < Woof + @@sound = "WOOF" +end + +LoudWoof.sound # => "WOOF" +Woof.sound # => "WOOF" (!) +~~~ + +또는 조상 클래스가 나중에 다시 정의되고 변경되어 예상치 못한 효과가 나타날 수도 +있습니다. + +~~~ +class Foo + + @@var = "foo" + + def self.var + @@var + end +end + +Foo.var # => "foo" (as expected) + +class Object + @@var = "object" +end + +Foo.var # => "object" (!) +~~~ + +따라서 수행 중인 작업을 정확히 알고 있고 이러한 종류의 동작이 명시적으로 필요한 +경우가 아니라면 클래스 인스턴스 변수를 사용하는 것이 좋습니다. + +### Ruby에는 클래스 메서드가 있나요? +{: #class-method} + +클래스 객체의 [싱글톤 메서드](../7/#singleton-method)를 클래스 메서드라고 합니다. +(사실 클래스 메서드는 메타클래스에 정의되어 있지만, 이는 거의 투명합니다). +이를 다른 방식으로 보면 클래스 메서드는 수신자가 클래스인 메서드라고 말할 수 +있습니다. + +이 모든 것은 해당 클래스를 인스턴스(객체)가 없어도 수신자로서 클래스 메서드를 +호출할 수 있다는 사실로 귀결됩니다. + +클래스 `Foo`의 싱글톤 메서드를 만들어 봅시다. + +~~~ +class Foo + def self.test + "this is foo" + end +end + +# 이런 식으로 호출됩니다. + +Foo.test # => "this is foo" +~~~ + +이 예제에서 `Foo.test`는 클래스 메서드입니다. + +`Class`에 정의된 인스턴스 메서드는 모든(!) 클래스에 대한 클래스 + 메서드로 사용할 수 있습니다. + +### 싱글톤 클래스란 무엇인가요? + +싱글톤 클래스는 특정 객체와 연관된 클래스를 서브클래싱하여 생성되는 익명 +클래스입니다. 싱글톤 클래스는 하나의 객체와 관련된 기능을 확장하는 또 다른 +방법입니다. + +`Foo`가 있다고 합시다. + +~~~ +class Foo + def hello + "hello" + end +end + +foo = Foo.new +foo.hello # => "hello" +~~~ + +이제 이 인스턴스 하나에만 클래스 수준 기능을 추가해야 한다고 가정해 보 +겠습니다. + +~~~ +class << foo + attr_accessor :name + + def hello + "hello, I'm #{name}" + end +end + +foo.name = "Tom" +foo.hello # => "hello, I'm Tom" +Foo.new.hello # => "hello" +~~~ + +`Foo`의 특성을 변경하지 않고 `foo`를 재정의했습니다. + +### 모듈 함수란 무엇인가요? + +{% include faq-out-of-date.html %} + +모듈 함수는 모듈에 정의된 비공개 싱글톤 메서드입니다. 사실상 +[클래스 메서드](#class-method)와 유사하며, `Module.method` 표기법을 +사용하여 호출할 수 있습니다. + +~~~ +Math.sqrt(2) # => 1.414213562 +~~~ + +그러나 모듈을 클래스에 믹스인할 수 있기 때문에 접두사 없이 모듈 함수를 사용 +할 수도 있습니다(모든 `Kernel` 함수를 객체에서 사용할 수 있는 방식입니다). + +~~~ +include Math +sqrt(2) # => 1.414213562 +~~~ + +메서드를 모듈 함수로 만들려면 `module_function`을 사용합니다. + +~~~ +module Test + def thing + # ... + end + module_function :thing +end +~~~ + +### 클래스와 모듈의 차이점은 무엇인가요? + +모듈은 메서드와 상수의 모음입니다. 인스턴스를 생성할 수 없습니다. 클래스는 +인스턴스(객체)를 생성할 수 있으며 인스턴스별 상태(인스턴스 변수)를 가질 수 +있습니다. + +모듈을 클래스 및 다른 모듈에 믹스인할 수 있습니다. 믹스인된 모듈의 상수와 메서드는 +해당 클래스의 상수와 메서드에 섞여서 클래스의 기능을 보강합니다. +그러나 클래스는 다른 어떤 것과도 섞일 수 없습니다. + +클래스는 다른 클래스에서 상속할 수 있지만 모듈에서는 상속할 수 없습니다. + +모듈은 아무 것도 상속할 수 없습니다. + +### 모듈을 상속할 수 있나요? + +그러나 모듈을 클래스나 다른 모듈에 포함시켜 다중 상속(믹스인 기능)을 모방할 +수 있습니다. + +이렇게 하면 상속이 필요한 하위 클래스가 생성되지는 않지만 클래스와 모듈 사이 +에 `is_a?` 관계가 생성됩니다. + +### 믹스인의 예를 보여주세요. + +`Comparable` 모듈은 다양한 비교 연산자(`<`, `<=`, `==`, `>=`, `>`, `between?`)를 +제공합니다. 이는 일반적인 비교 메서드인 `<=>`에 대한 호출로 정의됩니다. 그러나 +`<=>` 자체를 정의하지는 않습니다. + + +동물의 다리 개수를 비교하는 클래스를 만들고 싶다고 가정해 보겠습니다. + +~~~ +class Animal + include Comparable + + attr_reader :legs + + def initialize(name, legs) + @name, @legs = name, legs + end + + def <=>(other) + legs <=> other.legs + end + + def inspect + @name + end +end + +c = Animal.new("cat", 4) +s = Animal.new("snake", 0) +p = Animal.new("parrot", 2) + +c < s # => false +s < c # => true +p >= s # => true +p.between?(s, c) # => true +[p, s, c].sort # => [snake, parrot, cat] +~~~ + +`Animal`은 `<=>` 연산자에 대한 자체 시맨틱을 정의하고 `Comparable` 모듈을 +믹스인하면 됩니다. 이제 `Comparable`의 메서드는 `Animal`의 메서드와 +구분할 수 없게 되고 클래스에 새로운 기능이 갑자기 생겨납니다. 그리고 +많은 클래스에서 동일한 `Comparable` 모듈을 사용하기 때문에 새 클래스는 +일관되고 잘 이해되는 의미를 공유하게 됩니다. + +### 클래스 메서드를 정의하는 방법이 두 가지인 이유는 무엇인가요? + +클래스 정의에서 클래스 메서드를 정의할 수 있으며, 최상위 수준에서 클래스 +메서드를 정의할 수 있습니다. + +~~~ +class Demo + def self.class_method + end +end + +def Demo.another_class_method +end +~~~ + +둘 사이에는 단 한 가지 중요한 차이점이 있습니다. 클래스 정의에서는 상수가 +범위 내에 있으므로 클래스의 상수를 직접 참조할 수 있습니다. 최상위 레벨에서는 +`Class::CONST` 표기법을 사용해야 합니다. + +### 'include'과 'extend'의 차이점은 무엇인가요? + +{% include faq-out-of-date.html %} + +`include`는 모듈을 클래스나 다른 모듈에 믹스인합니다. 해당 모듈의 메서드는 함수 +스타일(수신자 없이)로 호출됩니다. + +`extend`는 객체(인스턴스)에 모듈을 포함할 때 사용됩니다. +모듈의 메서드는 객체의 메서드가 됩니다. + +### `self`는 무슨 뜻인가요? + +`self`는 현재 실행 중인 수신자, 즉 메서드가 적용되는 객체입니다. 함수형 +메서드 호출의 수신자는 `self`입니다. diff --git a/ko/documentation/faq/9/index.md b/ko/documentation/faq/9/index.md new file mode 100644 index 0000000000..77dfe4c3ad --- /dev/null +++ b/ko/documentation/faq/9/index.md @@ -0,0 +1,361 @@ +--- +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 %} + +## 내장 라이브러리 + +### `instance_methods(false)`는 무엇을 반환하나요? + +인스턴스 메서드 `instance_methods`는 수신 클래스 또는 모듈의 인스턴스 +메서드 이름이 포함된 배열을 반환합니다. 여기에는 슈퍼클래스와 모듈에 +믹스인된 메서드가 포함됩니다. + +`instance_methods(false)`나 `instance_methods(nil)`는 수신자에 정의된 메소드의 +이름만 반환합니다. + +### 난수 시드는 어떻게 작동하나요? + +`srand`를 미리 호출하지 않고 `rand`가 호출되면, 루비의 의사 난수 생성기는 +무엇보다도 OS에서 제공하는 엔트로피 소스를 사용하는 랜덤(에 가까운) 시드를 +사용합니다(사용 가능한 경우). +`srand` 를 사용하지 않는 프로그램을 연속적으로 실행하면 다른 난수 시퀀스가 +생성됩니다. + +테스트 목적으로, 상수 시드를 사용하여 `srand`를 호출하면 프로그램을 실행할 +때마다 동일한 일련의 숫자로 예측 가능한 동작을 얻을 수 있습니다. + +### 파일을 읽고 변경했지만 디스크의 파일은 변경되지 않았습니다. + +~~~ +File.open("example", "r+").readlines.each_with_index do |line, i| + line[0,0] = "#{i+1}: " +end +~~~ + +이 프로그램은 `example` 파일에 줄 번호를 추가하지 _않습니다_. 파일의 내용을 읽 +고 각 줄마다 줄 번호를 앞에 붙이기는 하지만 데이터를 다시 쓰지는 않습니다. +아래 코드는 파일을 _업데이트_합니다(업데이트를 시작하기 전에 백업을 하지 않기 +때문에 다소 위험할 수 있습니다). + +~~~ +File.open("example", "r+") do |f| + lines = f.readlines + lines.each_with_index {|line, i| line[0,0] = "#{i+1}: " } + f.rewind + f.puts lines +end +~~~ + +### 파일을 처리하고 내용을 업데이트하려면 어떻게 해야 하나요? + +명령줄 옵션 `-i` 또는 내장 변수 `$-i`를 사용하여 파일을 읽고 바꿀 수 있습니다. + +파일에 줄 번호를 추가한 이전 질문의 코드는 이 기법을 사용하여 작성하는 +것이 가장 좋습니다. + +~~~ +$ ruby -i -ne 'print "#$.: #$_"' example +~~~ + +원본 파일을 보존하려면 `-i.bak`을 사용하여 백업을 만드세요. + +### 파일을 작성하고 복사했는데 복사본의 끝 부분이 손실된 것 같습니다. + +이 코드는 제대로 작동하지 않습니다. + +~~~ +require "fileutils" + +File.open("file", "w").puts "This is a file." +FileUtils.cp("file", "newfile") +~~~ + +I/O가 버퍼링되어 있기 때문에 `file`의 내용이 디스크에 기록되기 전에 복사되고 +있습니다. `newfile`은 아마도 비어 있을 것입니다. 그러나 프로그램이 종료되면 +버퍼가 플러시되고 파일에는 예상되는 콘텐츠가 있습니다. + +복사하기 전에 '파일'이 닫혀 있는지 확인하면 문제가 발생하지 않습니다. + +~~~ +require "fileutils" + +File.open("file", "w") {|f| f.puts "This is a file." } +FileUtils.cp("file", "newfile") +~~~ + +### 현재 입력 파일에서 줄 번호를 얻으려면 어떻게 해야 하나요? + +파일에서 읽을 때 Ruby는 전역 변수 `$.`의 줄 번호 카운터를 증가시킵니다. 이 +기능은 `File` 객체의 `lineno` 속성을 사용하여 사용할 수도 있습니다. + +특수 상수 `ARGF`는 명령줄에 지정된 모든 입력 파일(파일이 없는 경우 표준 입력)을 +읽는 데 사용할 수 있는 파일과 유사한 객체입니다. `ARGF`는 다음과 같은 코드에서 +암시적으로 사용됩니다. + +~~~ +while gets + print $_ +end +~~~ + +이 경우 `$.`는 모든 입력 파일에서 읽은 누적 줄 수가 됩니다. 현재 파일에서 +줄 번호를 가져오려면 다음 코드를 사용하세요. + +~~~ +ARGF.file.lineno +~~~ + +`ARGF.file.path`를 사용하여 현재 파일의 이름을 가져올 수도 있습니다. + +### 프로그램 출력을 표시하기 위해 `less`를 사용하려면 어떻게 해야 하나요? + +다음을 시도했지만 아무것도 나오지 않았습니다. + +~~~ +open("|less", "w").puts "abc" +~~~ + +프로그램이 즉시 종료되어서 `less`는 작성한 내용을 볼 기회를 얻지 못 +하며 표시할 수도 없기 때문입니다. IO가 제대로 닫혔는지 확인하고 `less`가 끝날 +때까지 기다리세요. + +~~~ +open("|less", "w") {|f| f.puts "abc" } +~~~ + +### 더 이상 참조되지 않는 `File` 객체는 어떻게 되나요? + +더 이상 참조되지 않는 `File` 객체는 가비지 컬렉션 대상이 됩니다. `File` 객체가 +가비지 컬랙션되면 파일은 자동으로 닫힙니다. + +### 파일을 닫지 않으면 불안한 기분이 들어요. + +파일을 닫는 데는 최소한 네 가지의 좋은 방법이 있습니다. + +~~~ +# (1) +f = File.open("file") +begin + f.each {|line| print line } +ensure + f.close +end + +# (2) +File.open("file") do |f| + f.each {|line| print line } +end + +# (3) +File.foreach("file") {|line| print line } + +# (4) +File.readlines("file").each {|line| print line } +~~~ + +### 수정 시간별로 파일을 정렬하려면 어떻게 해야 하나요? + +~~~ +Dir.glob("*").sort {|a, b| File.mtime(b) <=> File.mtime(a) } +~~~ + +이 방법은 작동하지만(시간 역순으로 목록을 반환), 비교할 때마다 운영 체제 +에서 파일의 수정 시간을 가져오기 때문에 효율적이지 않습니다. + +약간의 복잡성을 추가하면 더 효율적일 수 있습니다. + +~~~ +Dir.glob("*").map {|f| [File.mtime(f), f] }. + sort {|a, b| b[0] <=> a[0] }.map(&:last) +~~~ + +### 파일에서 단어의 빈도를 계산하려면 어떻게 해야 하나요? + +~~~ +freq = Hash.new(0) +File.read("example").scan(/\w+/) {|word| freq[word] += 1 } +freq.keys.sort.each {|word| puts "#{word}: #{freq[word]}" } +~~~ + +결과: + +~~~ +and: 1 +is: 3 +line: 3 +one: 1 +this: 3 +three: 1 +two: 1 +~~~ + +### 문자열을 알파벳 순서로 정렬하려면 어떻게 해야 하나요? + +문자열을 'AAA', 'BBB', ..., 'ZZZ', 'aaa', 'bbb'로 정렬하려는 경우 추가 구현없이 +내장 비교를 사용하는 것으로 충분합니다. + +대/소문자 구분을 무시하고 정렬하려면 정렬 블록에서 대/소문자 구분이 없는 문자열 +버전을 비교합니다. + +~~~ +array = %w( z bB Bb bb Aa BB aA AA aa a A ) +array.sort {|a, b| a.downcase <=> b.downcase } + # => ["a", "A", "Aa", "aA", "AA", "aa", "bB", "Bb", "bb", "BB", "z"] +~~~ + +'A'와 'a'가 함께 나오지만 'a'가 'A'보다 큰 것으로 간주되도록 정렬하려면 +(즉, 'Aa'가 'AA' 뒤에 오지만 'AB' 앞에 오도록) 이렇게 하세요. + +~~~ +array.sort {|a, b| (a.downcase <=> b.downcase).nonzero? || a <=> b } + # => ["A", "a", "AA", "Aa", "aA", "aa", "BB", "Bb", "bB", "bb", "z"] +~~~ + +### 탭을 스페이스로 확장하려면 어떻게 해야 하나요? +{: #tab-expansion} + +확장할 문자열이 `a`인 경우 다음 중 하나를 사용할 수 있습니다. + +~~~ +1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+" "*(8-$1.size%8+8*$2.size)} +# 또는 +1 while a.sub!(/\t(\t*)/){" "*(8-$~.begin(0)%8+8*$1.size)} +# 또는 +a.gsub!(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")} +~~~ + +### 정규식에서 백슬래시를 이스케이프하려면 어떻게 해야 하나요? + +`Regexp.quote('\\')`는 백슬래시를 이스케이프합니다. + +`sub`와 `gsub`를 사용하는 경우 더 까다로워집니다. 백슬래시를 각각 +두 개로 바꾸기 위해 `gsub(/\\/, '\\\\')`를 작성한다고 가정해 보겠습니다. +두 번째 인수는 구문 분석에서 `'\\'`로 변환됩니다. 치환이 발생하면 정규식 +엔진이 이를 `'\'`로 변환하므로 결과적으로 백슬래시 하나씩을 다른 백슬래시 +하나로 대체하게 됩니다. 그래서 `gsub(/\\/, '\\\\\\')`로 작성해야 합니다! + +그러나 `\&`는 매칭한 문자열을 포함한다는 사실을 사용하여 `gsub(/\\/, '\&\&')`라 +적을 수도 있습니다. + +`gsub`의 블록 형식, 즉 `gsub(/\\/) { '\\\\' }`를 사용하면 대체 문자열은 구문 +전달 중에 한 번만 분석되며 결과는 사용자가 의도한 대로 나타납니다. + +### `sub`와 `sub!`의 차이점은 무엇인가요? + +`sub`에서는 수신자의 복사본이 생성되고 치환되어 반환됩니다. + +`sub!`에서는 수신자가 변경되고 일치하는 항목이 발견되면 반환됩니다. +그렇지 않으면 `nil`이 반환됩니다. + +수신자의 속성을 변경하는 `sub!`와 같은 메서드를 +[파괴적 메서드](../7/#destructive-method)라고 합니다. 일반적으로 유사한 +메서드가 두 개 있고 하나가 파괴적인 경우, 파괴적인 메서드에는 접미사 `!`가 +붙습니다. + +~~~ +def foo(str) + str.sub(/foo/, "baz") +end + +obj = "foo" +foo(obj) # => "baz" +obj # => "foo" + +def foo(str) + str.sub!(/foo/, "baz") +end + +foo(obj) # => "baz" +obj # => "baz" +~~~ + +### `\Z`는 어디에 일치하나요? + +문자열이 `\n`으로 끝나면 마지막 `\n`(줄 바꿈) 바로 앞에 `\Z`가 일치하고, +그렇지 않으면 문자열 끝에서 일치합니다. + +### `thread`와 `fork`의 차이점은 무엇인가요? + +{% include faq-out-of-date.html %} + +Ruby 스레드는 인터프리터 내에서 구현되는 반면, `fork`는 운영 체제를 호출하여 +별도로 실행되는 서브 프로세스를 생성합니다. + +스레드와 `fork`에는 다음과 같은 특징이 있습니다. + +* `fork`는 느리지만 `thread`는 그렇지 않습니다. +* `fork`는 메모리 공간을 공유하지 않습니다. +* `thread`는 쓰레싱을 일으키지 않습니다. +* `thread`는 DOS에서 작동합니다. +* `thread`가 교착상태에 빠지면 전체 프로세스가 멈춥니다. +* `fork`는 I/O가 완료되기를 기다리는 일시 중지를 이용할 수 있지만, + `thread`는 그렇지 않습니다 (적어도 약간의 도움 없이는). + +`fork`와 `thread`를 혼용해서는 안 됩니다. + +### `Marshal`은 어떻게 사용하나요? + +`Marshal`은 객체를 파일이나 문자열에 저장하고 나중에 재구성하는 데 사용됩니다. +객체는 다음을 사용하여 저장할 수 있습니다. + +~~~ +Marshal.dump( obj [, io ] [, lev] ) +~~~ + +`io`는 쓰기 가능한 `IO` 객체이고, `lev`는 객체가 역참조되어 저장되는 레벨을 +지정합니다. `lev` 레벨의 역참조가 완료되고 객체 참조가 여전히 존재하는 경우 +`dump`는 참조된 객체가 아닌 참조만 저장합니다. 이렇게 참조된 객체는 나중에 +재구성할 수 없으므로 좋지 않습니다. + +`io`가 생략되면 마샬링된 객체가 문자열로 반환됩니다. + +다음을 사용하여 개체를 다시 로드할 수 있습니다. + +~~~ +obj = Marshal.load(io) +# 아니면 +obj = Marshal.load(str) +~~~ + +여기서 `io`는 읽을 수 있는 `IO` 객체, `str`은 덤프된 문자열입니다. + +### `trap`은 어떻게 사용하나요? + +`trap`은 코드 블록을 외부 이벤트(신호)와 연결합니다. + +~~~ +trap("PIPE") { raise "SIGPIPE" } +~~~ diff --git a/ko/documentation/faq/index.md b/ko/documentation/faq/index.md index de2f0bf791..1e8681eb61 100644 --- a/ko/documentation/faq/index.md +++ b/ko/documentation/faq/index.md @@ -21,13 +21,13 @@ header: | | 7 | - 8 + 8 | - 9 + 9 | - 10 + 10 | - 11 + 11

공식 Ruby FAQ

@@ -56,7 +56,7 @@ Stollsteimer에게 감사드립니다. * [이터레이터](5/) * [구문](6/) * [메서드](7/) -* [클래스 및 모듈](/en/documentation/faq/8/) -* [빌트인 라이브러리](/en/documentation/faq/9/) -* [확장 라이브러리](/en/documentation/faq/10/) -* [기타 기능](/en/documentation/faq/11/) +* [클래스 및 모듈](8/) +* [내장 라이브러리](9/) +* [확장 라이브러리](10/) +* [기타 기능](11/)