який сенс повернення в Ruby?


79

У чому різниця між returnпростою введенням такої змінної, як наступне:

повернення немає

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  mood
end

повернення

def write_code(number_of_errors)
  if number_of_errors > 1
    mood =  "Ask me later"
  else
    mood = puts "No Problem"
  end  
  return mood
end

Відповіді:


118

return дозволяє прорватися рано:

def write_code(number_of_errors)
  return "No problem" if number_of_errors == 0
  badness = compute_badness(number_of_errors)
  "WHAT?!  Badness = #{badness}."
end

Якщо number_of_errors == 0, тоді "No problem"буде негайно повернуто. В кінці методу, однак, це непотрібно, як ви помітили.


Редагувати: Щоб продемонструвати, що returnнегайно виходить, розглянемо цю функцію:

def last_name(name)
  return nil unless name
  name.split(/\s+/)[-1]
end

Якщо ви викликаєте цю функцію як last_name("Antal S-Z"), вона повернеться "S-Z". Якщо ви називаєте це як last_name(nil), воно повертається nil. Якщо return не негайно перервати, він спробує виконати nil.split(/\s+/)[-1], що призведе до помилки.


добре, хороший приклад. тому return зберігає повернене значення, але дозволяє виконувати решту методу. Не можу дочекатися його використання.
thenengah

4
Ні, навпаки: return негайно виходить із методу. Якщо ви задумаєтесь над цим прикладом, не було б корисно обчислити шкоду, якщо ви знаєте, що все в порядку. Я відредагую свою відповідь, щоб зробити це зрозумілішим.
Antal Spector-Zabusky

8
Ви можете використовувати return, і breakт.д. без параметра - вони будуть повертатися nilза замовчуванням.
Накілон

38

Використання "return" непотрібне, якщо це останній рядок, який слід виконати в методі, оскільки Ruby автоматично повертає останній обчислюваний вираз.

Вам навіть не потрібен цей остаточний "настрій", а також не потрібні ці доручення у твердженні IF.

def write_code(number_of_errors)
    if number_of_errors > 1
       "ERROR"
    else
       "No Problem"
    end  
end

puts write_code(10)

Вихід:

ПОМИЛКА


37
Виходячи з нерубійського фону, цей результат, безумовно, є WTF. :)
Патрік

return може завершити виконання достроково. Це робота для.
Joe.wang

1
Повернення також може бути корисним для того, щоб метод повернув nil замість того, яким був останній обчислюваний вираз, тому іноді ви побачите повернення без аргументу в кінці методів.
garythegoat

1
@garythegoat: або ти можеш просто написати nil.
Karoly Horvath

4

Я використовую return, коли переглядаю список, і хочу вийти з функції, якщо будь-який член списку відповідає критеріям. Я міг би досягти цього за допомогою одного твердження, наприклад:

list.select{|k| k.meets_criteria}.length == 0

в деяких ситуаціях, але

list.each{|k| return false if k.meets_criteria}

це теж один рядок - з, на мій погляд, деякою додатковою гнучкістю. Наприклад, перший приклад передбачає, що це єдиний рядок у методі, і що ми хочемо повернутися з цього пункту, незважаючи ні на що. Але якщо це тест, щоб перевірити, чи безпечно приступати до решти методів, у першому прикладі потрібно буде по-іншому обробити це.

РЕДАГУВАТИ:

Щоб додати деяку гнучкість, розгляньте такий рядок коду:

list_of_method_names_as_symbols.each{|k| list_of_objects.each{|j| return k if j.send(k)}}

Я впевнений, що це можна зробити, одним рядком, без цього return, але я не розумію, як це зробити.

Але це зараз досить гнучкий рядок коду, який можна викликати з будь-яким переліком логічних методів та списком об’єктів, що реалізують ці методи.

РЕДАГУВАТИ

Слід зазначити, що я припускаю, що цей рядок знаходиться всередині методу, а не блоку.


Але це здебільшого стилістичний вибір, я думаю, що в більшості ситуацій можна і, можливо, слід уникати використання return.


breakще корисніше в цих випадках.
Накілон

4

Рубі повертається завжди! найкращий спосіб

def write_code(number_of_errors)
  (number_of_errors > 1)? "ERROR" : "No Problem"
end

це означає, що якщо number_of_errors> 1, це поверне ПОМИЛКУ, інакше Немає проблем


3

Його приємний рубін дає цю хорошу властивість не чітко вказувати оператор return, але я просто вважаю, що як стандарт програмування потрібно завжди прагнути вказати оператори return, де це потрібно. Це допомагає зробити код більш читабельним для тих, хто походить з різних країн, таких як C ++, Java, PHP тощо, і вивчає ruby. оператор "return" нічого не зашкодить, то чому ж пропускати звичайний і більш стандартний спосіб повернення з функцій.


4
"так навіщо ж пропускати звичайний і більш стандартний спосіб повернення з функцій" ←, оскільки в Ruby пропущення return - це звичайний стандарт. Якщо ви бачите returnдобре стилізований код Ruby, він повинен бути там з якоїсь причини, наприклад, збиватися рано . Спроба застосувати конвенції стилю коду з однієї мови на іншу просто ускладнює залучення досвідчених програмістів та дотримання власного стилю коду.
Девід Моулз

Я все ще ловлю себе, ставлячи
крапки з

Хіба це не номер 2 у дзені Рубі, "неявний краще, ніж явний"? ;-)
Марк

1

Одне невелике застереження для тих, хто походить з інших мов. Скажімо, у вас є така функція, як OP, і ви використовуєте правило "останнє, що обчислюється", щоб автоматично встановити своє повернене значення:

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
end

і припустимо, ви додаєте оператор налагодження (або ведення журналу):

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  puts "### mood = #{mood}"
end

А тепер вгадайте, що. Ви зламали свій код, тому що putsповертає nil, яке тепер стає значенням повернення з функції.

Рішення полягає в тому, щоб мати звичку завжди чітко ставити значення повернення в останній рядок, як це робив OP:

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  puts "### mood = #{mood}"
  mood
end

-1

Непотрібність returnостаннього рядка у функції - це просто синтаксичний цукор Ruby. У більшості процедурних мов вам потрібно писати returnу кожній (не порожній в C ++) функції.


3
Я б не назвав це синтаксичним цукром ... головна особливість тут полягає в тому, що майже все - це вираз . ifоператори, блоки операторів. Ось що дозволяє ця виразність.
Karoly Horvath

Я згоден з Каролі - це не синтаксичний цукор, тому що все є виразом.
Фатухоку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.