Как работает оператор повтора в Ruby? - PullRequest
1 голос
/ 08 мая 2019

Я только начинаю работать в Ruby, но руководство, которому я следую, похоже, устарело.Я проводил некоторые исследования, но не смог найти четкого ответа.

В руководстве использовалось ключевое слово retry внутри метода, который должен действовать как цикл, но он используется безблок begin / rescue, и поведение кажется довольно разным, когда вы заставляете ключевое слово retry находиться внутри блока begin / rescue.

Я пробовал много вещей: -Первый использовал "ключевое слово begin в начале метода и повышение в точке повтора, за которым следует соответствующее спасение;повторить попытку;конец;'.-Последний использовал блок 'begin / rescue' снаружи, оборачивая вызов метода.

Следуя логике в руководстве, только последний работал должным образом.

Вот несколько примеров:

Код в руководстве выглядит следующим образом:

def WHILE(cond)
  return if not cond
  yield
  retry
end
i=0; WHILE(i<3) {print i; i+=1}

Результат: 012

Я пробовал следующее:

def WHILE(cond)
  begin
    return if not cond
    yield
    raise
  rescue
    retry
  end
end
i=0; WHILE(i<3) {print i; i+=1}

результат: бесконечные числа

def WHILE(cond)
  return if not cond
  yield
end
i=0; begin; WHILE(i<3) {print i; i+=1}; raise; rescue; retry; end

результат: 012 (плюс очевидный бесконечный цикл печати ничего)

Я ожидаю вас отизбавив меня от этого экзистенциального сомнения, но вот мой вывод.

До обязательного использования блока begin / rescue для ключевого слова 'retry' его можно было использовать таким образом, которого он больше не может, повторение вызова метода, несмотря на то, что находится внутри этого метода .

Теперь он просто переходит к оператору 'begin'.

Но я не уверен в этом, и мне нужно подтверждение.И если да, существует ли какая-либо форма для восстановления такого рода использования?

Спасибо.

1 Ответ

3 голосов
/ 08 мая 2019

Ваш WHILE не ведет себя как обычный while, поскольку в вашем случае i<3 оценивается во время вызова один раз .Оператор while оценивает его каждый раз.

Если вы хотите написать while эквивалент, важно, чтобы ваше условие было чем-то, что может быть оценено , а не чем-то уже оценено.

Это можно исправить, приняв Proc в качестве условия:

def so_long_as(cond)
  loop do
    return unless cond.call

    yield
  end
end

Затем вы называете его так:

i = 0
so_long_as(-> { i < 3 }) do
  print i
  i += 1
end

Где это теперь печатает 012 и завершается должным образом.

Важно отметить, что retry работает только в контексте begin / end, а не в обычном методе, который теперь вы должны использоватьredo вместо:

i = 0
redone = false
so_long_as(-> { i < 3 }) do
  print i
  unless (redone)
    redone = true
    redo
  end
  i += 1
end

Где это печатает 0012 сейчас.

Произошли некоторые существенные изменения в том, как redo и retry работают , чтостоит читать дальше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...