Ответ 1
(1) &.
обычно короче try(...)
В зависимости от сценария это может сделать ваш код более читаемым.
(2) &.
является стандартным Ruby, в отличие от try
Метод try
не определен в основной библиотеке Ruby, а скорее в библиотеке Rails. Когда вы не разрабатываете веб-приложение RoR, а вместо этого пишете, например. небольшие вспомогательные скрипты, это будет очень актуально.
(Например, я предпочитаю Ruby над Bash.)
(3) &.
упрощает отладку
Оператор безопасного обхода выдает ошибку, если вызывается несуществующий метод.
>> "s"&.glubsch
NoMethodError: undefined method `glubsch' for "s":String
Только на nil
он будет проявлять снисходительность:
>> nil&.glubsch
=> nil
Метод try
всегда будет возвращать nil
.
>> "s".try(:glubsch)
=> nil
Обратите внимание, что это относится к самым последним версиям Ruby и Rails.
Теперь представьте сценарий, в котором существует метод с именем glubsch
. Затем вы решите переименовать этот метод, но забудьте переименовать его в одном месте. (К сожалению, это может случиться с рубином...) С оператором безопасного обхода вы заметите ошибку почти сразу (как только эта строка кода будет выполнена в первый раз). Метод try
, однако, с радостью предоставит вам nil
, и вы получите сообщение об ошибке nil
где-то ниже по течению при выполнении программы. Выяснить, откуда пришел такой nil
, может быть сложно время от времени.
Неудача с быстрым и жестким с &.
делает отладку проще, чем беспечно возвращая nil
с помощью try
.
EDIT: Существует также вариант try!
(с помехой), который ведет себя так же, как &.
в этом отношении. Используйте это, если вам не нравится &.
.
(4) Что делать, если мне неважно, реализован ли метод?
Это было бы странно. Поскольку это будет неожиданным способом программирования, пожалуйста, сделайте это явным. Например, путем выделения двух случаев (реализованных или нет) с использованием respond_to?
и отклонением от него.
(5) Как насчет try
блочной формы?
Вместо имени метода блок можно передать в try
. Блок будет выполнен в контексте получателя; и внутри блока не применяется смягчение. Таким образом, с помощью всего одного вызова метода он будет действовать так же, как &.
.
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch' for "s":String
Для более сложных вычислений вы можете предпочесть эту блочную форму, вводя множество локальных переменных. Например. цепь
foo.try{ glubsch.blam }.try{ bar }.to_s
позволяет foo
быть nil
, но требует foo.glubsch
для возврата значения nil
. Опять же, вы можете сделать то же самое с оператором безопасного обхода в более сжатой форме:
foo&.glubsch.blam&.bar.to_s
Использование блочной формы try
для сложных вычислений IMHO - запах кода, хотя, поскольку это затрудняет читаемость. Когда вам нужно реализовать сложную логику, введите локальные переменные с описательными именами и, возможно, используйте if
для ветки от случая nil
. Ваш код будет более удобным.
НТН!