_If you wish to report errors or suggest improvements for this FAQ,
please go to our
[GitHub repository](https://github.com/ruby/www.ruby-lang.org/)
and open an issue or pull request._


## Встроенные библиотеки

### Что возвращает `instance_methods(false)`?

Метод `instance_methods` возвращает массив, содержащий имена методов экземпляра в получающем классе или модуле. Сюда входят методы в суперклассах и в подмешанных модулях.

`instance_methods(false)` или `instance_methods(nil)` возвращает имена только тех методов, которые определены в самом получателе.

### Как работают начальные числа (seeds) для случайных чисел?

Если вы вызываете `rand` без предварительного вызова `srand`, генератор псевдослучайных чисел Ruby использует случайное (или близкое к нему) начальное число, которое, помимо прочего, использует источник энтропии, предоставляемый ОС, если он доступен. Последовательные запуски программы, которая не использует `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")
~~~

Поскольку ввод-вывод буферизуется, `file` копируется до того, как его содержимое будет записано на диск. `newfile`, скорее всего, будет пустым. Однако, когда программа завершается, буферы сбрасываются (flushed), и файл обретает ожидаемое содержимое.

Проблема не возникает, если вы убедитесь, что файл `file` закрыт перед копированием:

~~~
require "fileutils"

File.open("file", "w") {|f| f.puts "This is a file." }
FileUtils.cp("file", "newfile")
~~~

### Как я могу получить номер строки в текущем входном файле?

По мере чтения из файла Ruby увеличивает счетчик номеров строк в глобальной переменной `$.`. Он также доступен через атрибут `lineno` объекта `File`.

Специальная константа `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)}
# or
1 while a.sub!(/\t(\t*)/){" "*(8-$~.begin(0)%8+8*$1.size)}
# or
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`?

`\Z` совпадает непосредственно перед последним `\n` (символом новой строки), если строка заканчивается на `\n`, в противном случае оно совпадает в конце строки.

### В чем разница между `thread` и `fork`?

<div class="not-prose bg-ruby-100 dark:bg-ruby-800 rounded-lg p-8 my-6">
  <div class="flex items-start gap-3">
    <svg class="w-6 h-6 text-ruby-700 dark:text-ruby-200 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
      <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/>
    </svg>
    <p class="text-sm text-ruby-700 dark:text-ruby-200 italic">
      This section or parts of it might be out-dated or in need of confirmation.
    </p>
  </div>
</div>


Потоки Ruby (threads) реализованы внутри интерпретатора, в то время как `fork` обращается к операционной системе для создания отдельно выполняемого подпроцесса.

Потоки и форки имеют следующие характеристики:

* `fork` работает медленно, `thread` — нет.
* `fork` не разделяет пространство памяти.
* `thread` не вызывает «пробуксовки» (thrashing).
* `thread` работает под DOS.
* Когда `thread` попадает в состояние взаимной блокировки (deadlock), останавливается весь процесс.
* `fork` может использовать паузы при ожидании завершения ввода-вывода, `thread` — нет (по крайней мере, не без некоторой помощи).

Вам, вероятно, не стоит смешивать `fork` и `thread`.

### Как я могу использовать `Marshal`?

`Marshal` используется для сохранения объекта в файл или строку и его последующего восстановления. Объекты можно сохранять с помощью:

~~~
Marshal.dump( obj [, io ] [, lev] )
~~~

`io` — это объект `IO`, доступный для записи, `lev` указывает уровень, до которого объекты разыменовываются и сохраняются. Если выполнено `lev` уровней разыменования, а ссылки на объекты все еще существуют, то `dump` сохраняет только ссылку, а не сам объект, на который она указывает. Это плохо, так как такие объекты не могут быть впоследствии восстановлены.

Если `io` опущено, маршалированные объекты возвращаются в виде строки.

Вы можете загрузить объекты обратно, используя:

~~~
obj = Marshal.load(io)
# or
obj = Marshal.load(str)
~~~

где `io` — это объект `IO`, доступный для чтения, `str` — это дамп строки.

### Как я могу использовать `trap`?

`trap` связывает блоки кода с внешними событиями (сигналами).

~~~
trap("PIPE") { raise "SIGPIPE" }
~~~
