Циклические различия в Ruby с использованием Range vs. Times

Я пытаюсь решить проблему Project Euler с помощью Ruby, я использовал 4 разных метода цикла, метод for-loop, times, range и upto, однако метод times только дает ожидаемый ответ, а for-loop, диапазон и выше метод нет. Я предполагаю, что они несколько одинаковы, но я этого не узнал. Может кто-нибудь объяснить различия между этими методами?

Здесь структура цикла, в которой я использовал

# for-loop method
for n in 0..1
  puts n
end

0
1
=> 0..1

# times method
2.times do |n|
  puts n
end

0
1
=> 2

# range method
(0..1).each do |n|
  puts n
end

0
1
=> 0..1

# upto method
0.upto(1) do |n|
  puts n
end

0
1
=> 0

Ответы

Ответ 1

Эта информация может быть легко получена путем проверки документации.

Array#each имеет подпись array.each {|item| block } → array, поэтому мы можем видеть, что возвращаемое значение foo.each { ... } равно foo.

Аналогично, Int#upto имеет подпись int.upto(limit) {|i| block } => int, так что x.upto(y) { ... } всегда будет возвращать x.

Затем мы также видим, что 2.times { ... } вернет 2 из-за Integer#times подпись.

У меня возникли проблемы с поиском нужной документации, но for x in y... переводится на y.each do |x| ..., поэтому ваш цикл for-in возвращает то же, что и ваш цикл .each.

В любом случае, в зависимости от возвращаемых значений этих циклов построения... странный подход. Я не думаю, что это происходит много (вообще?) В идиоматическом коде Ruby.

Ответ 2

Если я правильно вас понял, вы спрашиваете, почему n.times - единственный метод, который выполняет итерацию до, но не включает n. В этом случае:

Для диапазонов это просто: x..y определяет диапазон от x до y включительно, а x...y определяет диапазон от x до y exclusive. Поэтому, если вы хотите, чтобы такое же поведение, как времена, использовало 0...n.

Для x.upto(y) существует только одна версия, которая будет выполнять итерацию до и включая y. Это просто, как upto определяется и документируется для работы.

Также совершенно понятно, почему n.times не содержит n: если он итерировал от 0 до n (включительно), он дал бы n+1 раз. Но так как метод называется n.times, он должен явно давать только n раз.