защо използването на 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) }

Операторът за връщане там би накарал функцията да се спаси при това връщане и обикновено води до по-малко разбираем код, отколкото ако сте го написали с логиката if/else, както направихте по-рано. Вярвам, че рационалното решение за стила е да се обезсърчи този тип програмиране, тъй като прави програмите по-трудни за разбиране.

person BeepDog    schedule 05.05.2014