Хороший стиль для явного возврата в Ruby?

Исходя из фона Python, где всегда есть "правильный способ сделать это" ( "Pythonic" ), когда дело доходит до стиля, мне интересно, что же такое для Ruby. Я использую свои собственные правила стиля, но я думаю о выпуске исходного кода, и я хотел бы, чтобы он придерживался любых неписаных правил, которые могут существовать.

Является ли это "Рубиновый путь" для явного ввода return в методах? Я видел, как это делается с и без, но есть ли правильный способ сделать это? Возможно, подходящее время для этого? Например:

def some_func(arg1, arg2, etc)
  # Do some stuff...
  return value # <-- Is the 'return' needed here?
end

Ответ 1

Старый (и "ответивший" ) вопрос, но я отвечу за два цента в качестве ответа.

TL; DR - вам это не обязательно, но в некоторых случаях ваш код может стать более понятным.

Хотя использование явного возврата не может быть "рубиновым", оно запутывает программистов, работающих с незнакомым кодом, или незнаком с этой особенностью Ruby.

Например, у вас может быть такая небольшая функция, которая добавляет ее к переданному числу и присваивает ее переменной экземпляра.

def plus_one_to_y(x)
    @y = x + 1
end

Было ли это функцией, возвращающей значение, или нет? Очень сложно сказать, что означал разработчик, поскольку он присваивает переменную экземпляра, и возвращает также присвоенное значение.

Предположим намного позже, другой программист (возможно, не знакомый с тем, как Ruby действительно возвращается на основе последней строки выполняемого кода) приходит и хочет помещать некоторые инструкции печати для ведения журнала, а функция становится такой...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
end

Теперь функция прерывается, если что-то ожидает возвращенного значения. Если ничего не ожидает возвращенного значения, это нормально. Ясно, что если где-то дальше по цепочке кода что-то вызывает это, то ожидает возвращаемое значение, оно будет терпеть неудачу, поскольку оно не вернет ожидаемое.

Реальный вопрос заключается в следующем: действительно ли ожидалось возвращаемое значение? Это что-то сломало? Разве это сломает что-то в будущем? Кто знает! Только полный обзор кодов всех вызовов позволит вам узнать.

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

Итак, в случае нашей маленькой демонстрационной функции, предполагая, что мы хотим, чтобы она вернула значение, оно было бы написано так:

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    return @y
end

И для любого программиста было бы очень понятно, что он возвращает значение, и гораздо труднее их разбить, не осознавая этого.

В качестве альтернативы можно написать это так и оставить инструкцию return...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    @y
end

Но зачем беспокоиться о том, чтобы вернуть слово? Почему бы просто не положить его туда и сделать на 100% понятным, что происходит? Это буквально не повлияет на вашу способность кода выполнять.

Ответ 2

Нет. Хороший стиль Ruby обычно использует только явные возвращения для раннего возвращения. Ruby большой по минимализму кода/неявной магии.

Тем не менее, если явное возвращение сделает вещи более ясными или более легкими для чтения, это ничего не повредит.

Ответ 3

Я лично использую ключевое слово return, чтобы различать то, что я называю функциональными методами, то есть методы, которые выполняются в основном для их возвращаемого значения, и процедурные методы, которые выполняются в основном для их побочных эффектов. Таким образом, методы, в которых важно значение возврата, получают дополнительное ключевое слово return, чтобы обратить внимание на возвращаемое значение.

Я использую одно и то же различие при вызове методов: функциональные методы получают круглые скобки, процедурные методы этого не делают.

И последнее, но не менее важное: я также использую это различие с блоками: функциональные блоки получают фигурные скобки, процедурные блоки (т.е. блоки, которые "что-то делают" ) получают do/end.

Однако я стараюсь не быть религиозным: блоки, фигурные скобки и do/end имеют разный приоритет, и вместо того, чтобы добавлять явные скобки для устранения неоднозначности выражения, я просто переключаюсь на другой стиль. То же самое касается вызова метода: если добавление круглых скобок вокруг списка параметров делает код более читаемым, я делаю это, даже если рассматриваемый метод носит процедурный характер.

Ответ 4

На самом деле важно различать:

  • Функции - методы, выполняемые для возвращаемого значения
  • Процедуры - методы, выполняемые для их побочных эффектов

Ruby не имеет собственного способа их отличия, что оставляет вас уязвимым для написания процедуры side_effect(), а другой разработчик решает злоупотреблять неявным возвратным значением вашей процедуры (в основном рассматривая ее как нечистую функцию).

Чтобы решить эту проблему, выньте лист из книги Scala и Haskell, и ваши процедуры явно возвращают nil (aka Unit или () на других языках).

Если вы выполните это, то использование явного синтаксиса return или не просто станет вопросом личного стиля.

Для дальнейшего различения функций и процедур:

  • Скопируйте Jörg W Mittag с хорошей идеей писать функциональные блоки с фигурными фигурными скобками и процедурные блоки с do/end
  • При вызове процедур используйте (), тогда как при вызове функций не

Обратите внимание, что Jörg W Mittag фактически выступал против другого - избегая () для процедур, но это не рекомендуется, потому что вы хотите, чтобы побочные эффекты, вызывающие метод, были четко различимы от переменных, особенно когда arity равно 0. См. Scala руководство по стилю при вызове метода.

Ответ 5

В руководстве по стилю указано, что вы не должны использовать return в своем последнем заявлении. Вы все равно можете использовать его если он не последний. Это одно из соглашений, которое сообщество строго придерживается, и вы должны, если вы планируете сотрудничать с кем-либо, использующим Ruby.


Как говорится, основным аргументом для использования явного return является то, что он запутывает людей, поступающих с других языков.

  • Во-первых, это не полностью исключает Ruby. Например, Perl также имеет неявные возвращения.
  • Во-вторых, большинство людей, к которым это относится, поступают с языков Алгола. Большинство из них являются "более низким уровнем", чем Ruby, поэтому вам нужно написать больше кода, чтобы что-то сделать.

Общая эвристика для длины метода (исключая геттеры/сеттеры) в java - это один экран. В этом случае вы, возможно, не увидите определение метода и/или уже забыли о том, откуда вы возвращались.

С другой стороны, в Ruby лучше придерживаться методов длиной менее 10 строк. Учитывая это, можно было бы задаться вопросом, почему он должен писать на 10% больше заявлений, когда они явно подразумеваются.


Так как Ruby не имеет методов void, и все гораздо более кратким, вы просто добавляете накладные расходы ни для одного из преимуществ, если вы идете с явным return s.

Ответ 6

Я согласен с Бен Хьюзом и не согласен с Тимом Холтом, потому что в вопросе упоминается окончательный способ, которым это делает Python, и спрашивает, имеет ли Ruby аналогичный стандарт.

Он делает.

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

Ответ 7

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

Ответ 8

Как сказал Бен. Тот факт, что "возвращаемое значение метода ruby ​​является возвращаемым значением последнего оператора в теле функции", приводит к тому, что ключевое слово return редко используется в большинстве методов ruby.

def some_func_which_returns_a_list( x, y, z)
  return nil if failed_some_early_check


  # function code 

  @list     # returns the list
end