почему использование return является плохой привычкой в ​​scala

Я делаю Scala через курс функционального программирования на Coursera. Я заметил, что автоматическая проверка стиля говорит мне, что использование «возврата» — плохая привычка. Почему это? Мне кажется, что использование return сделало бы код более читабельным, потому что любой другой программист может сразу увидеть это и то, что возвращает функция.

Пример, почему это;

def sum(xs: List[Int]): Int = {
    if( xs.length == 0){
      return 0
    }else{
      return xs.head + sum(xs.tail)
    }
}

Считается хуже этого;

def sum(xs: List[Int]): Int = {
    if( xs.length == 0){
      0
    }else{
      xs.head + sum(xs.tail)
    }
}

Я привык к javascript, так что это может быть причиной, почему я чувствую себя неловко. Тем не менее, кто-нибудь может объяснить, почему добавление оператора return делает мой код хуже? Если да, то почему в языке есть оператор возврата?


person cantdutchthis    schedule 05.05.2014    source источник
comment
Самый простой ответ заключается в том, что вы не должны использовать return. И как обычно для меня, я хотел бы отметить, что ни одна из фигурных скобок в вашем коде не нужна, и если бы это был мой код, они были бы опущены.   -  person Randall Schulz    schedule 06.05.2014
comment
@RandallSchulz великие умы! Я также предложил использовать сопоставление с образцом, а не if...else. (смотри мой ответ)   -  person Boris the Spider    schedule 06.05.2014


Ответы (3)


В Java, Javascript и других императивных языках if...else является оператором управления потоком.

Это означает, что вы можете сделать это

public int doStuff(final boolean flag) {
    if(flag)
        return 1;
    else
        return 5;
}

Но ты не можешь этого сделать

public int doStuff(final boolean flag) {
    return if(flag)
        1;
    else
        5;
}

Потому что if...else — это инструкция, а не выражение. Для этого вам нужно использовать тернарный оператор (строго говоря, «условный оператор»), например:

public int doStuff(final boolean flag) {
    return flag ? 1 : 5;
}

В Scala все иначе. Конструкция if...else — это выражение, поэтому она больше похожа на условный оператор в языках, к которым вы привыкли. Итак, на самом деле ваш код лучше написать как:

def sum(xs: List[Int]): Int = {
    return if(xs.length == 0) {
      0
    } else {
      xs.head + sum(xs.tail)
    }
}

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

def sum(xs: List[Int]): Int = 
    if(xs.length == 0) 0
    else xs.head + sum(xs.tail)

Итак, чтобы ответить на ваш вопрос: это не рекомендуется, потому что это неправильное толкование природы конструкции if...else в Scala.

Но это все немного не по делу, вы действительно должны использовать сопоставление с образцом

def sum(xs: List[Int]): Int = xs match {
   case Nil => 0
   case head::tail => head + sum(tail)
}

Это гораздо более идиоматический Scala. Узнайте, как использовать сопоставление с образцом (и злоупотреблять им), и вы сэкономите себе огромное количество строк кода.

person Boris the Spider    schedule 05.05.2014
comment
+1 за сопоставление с образцом, указатель действителен и высоко ценится. - person cantdutchthis; 06.05.2014

Я думаю, еще один ответ на вопрос, почему

почему использование return является плохой привычкой в ​​scala

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

Например, рассмотрим этот код:

def sumElements(xs: List[Int]): Int = { 
  val ys: List[Int] = xs.map { x => 
    return x + 1
  }
  return ys.sum 
}

Легко упустить из виду, что когда этот код вызывается с помощью sumElements(List(1, 2, 3, 4)), результатом будет 2, а не 10. Это связано с тем, что return в пределах map вернется из sumElements, а не из вызова map.

person lpiepiora    schedule 05.05.2014

В scala каждая строка является выражением, а не утверждение. Операторы обычно не имеют возвращаемого значения, но выражения имеют.

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

def sum(xs: List[Int]): Int = { if(xs.isEmpty) return 0 xs.head + sum(xs.tail) }

Оператор return заставит функцию отказаться от этого возврата и, как правило, приведет к менее понятному коду, чем если бы вы написали его с логикой if/else, как вы делали ранее. Я считаю, что рациональное решение стиля заключается в том, чтобы препятствовать этому типу программирования, поскольку он делает программы более трудными для понимания.

person BeepDog    schedule 05.05.2014