Подтвердить что ты не робот

Ruby Exceptions - Почему "еще"?

Я пытаюсь понять исключения в Ruby, но я немного смущен. Учебное пособие, которое я использую, говорит, что если возникает исключение, которое не соответствует ни одному из исключений, идентифицированных операциями спасения, вы можете использовать "else", чтобы поймать его:

begin  
# -  
rescue OneTypeOfException  
# -  
rescue AnotherTypeOfException  
# -  
else  
# Other exceptions
ensure
# Always will be executed
end

Тем не менее, я также видел позже в учебнике "Спасение", которое используется без указанного исключения:

begin
    file = open("/unexistant_file")
    if file
         puts "File opened successfully"
    end
rescue
    file = STDIN
end
print file, "==", STDIN, "\n"

Если вы можете это сделать, тогда мне нужно использовать еще? Или я могу просто использовать общее спасение в конце, как это?

begin  
# -  
rescue OneTypeOfException  
# -  
rescue AnotherTypeOfException  
# -  
rescue
# Other exceptions
ensure
# Always will be executed
end
4b9b3361

Ответ 1

else - это когда блок завершается без исключения. Выполняется запуск ensure, завершится ли блок успешно или нет. Пример:

begin
  puts "Hello, world!"
rescue
  puts "rescue"
else
  puts "else"
ensure
  puts "ensure"
end

Это напечатает Hello, world!, затем else, затем ensure.

Ответ 2

Здесь конкретный прецедент для else в выражении begin. Предположим, вы пишете автоматические тесты, и вы хотите написать метод, который возвращает ошибку, вызванную блоком. Но вы также хотите, чтобы тест завершился неудачей, если блок не вызвал ошибку. Вы можете сделать это:

def get_error_from(&block)
  begin
    block.call
  rescue => err
    err  # we want to return this
  else
    raise "No error was raised"
  end
end

Обратите внимание, что вы не можете переместить raise внутри блока begin, потому что он получит rescue d. Конечно, есть другие способы, не используя else, например, проверить, <<27 > nil после end, но это не так лаконично.

Лично я редко использую else таким образом, потому что я думаю, что он редко нужен, но он очень пригодится в этих редких случаях.

Ответ 3

Блок else в начальном блоке начала восстановления используется, когда вы, возможно, ожидаете, что произойдет какое-то исключение. Если вы выполняете все ожидаемые исключения, но по-прежнему ничего не поднимаете, то в своем блоке else вы можете делать все, что нужно сейчас, когда вы знаете, что ваш исходный код бежал без ошибок.

Ответ 4

Единственная причина, по которой я могу наблюдать за блоком else, - это если вы хотите выполнить что-то перед блоком ensure, когда код в блоке begin не вызвал никаких ошибок.

begin
  puts "Hello"
rescue
  puts "Error"
else
  puts "Success"
ensure
  puts "my old friend"
  puts "I've come to talk with you again."
end

Ответ 5

Благодаря else вы иногда можете объединить два вложенных блока begin end.
Итак (упрощенный пример из моего текущего кода) вместо:

  begin
    html = begin
      NetHTTPUtils.request_data url
    rescue NetHTTPUtils::Error => e
      raise unless 503 == e.code
      sleep 60
      retry
    end
    redo unless html["market"]
  end

вы пишете:

  begin
    html = NetHTTPUtils.request_data url
  rescue NetHTTPUtils::Error => e
    raise unless 503 == e.code
    sleep 60
    retry
  else
    redo unless html["market"]
  end