2010-09-22 10 views

Odpowiedz

47

Ignorując zagnieżdżone funkcje, zawsze można zamienić obliczenia Scala na zwroty z równoważnymi obliczeniami bez zwracanych danych. Wynik ten sięga początków "programowania strukturalnego" i nazywa się on sprytnie.

W przypadku funkcji zagnieżdżonych sytuacja ulega zmianie. Scala pozwala umieścić "powrót" głęboko w szeregu funkcji zagnieżdżonych. Po wykonaniu return, kontrola przeskakuje ze wszystkich zagnieżdżonych funkcji do najbardziej wewnętrznej metody, z której się zwraca (zakładając, że metoda nadal jest wykonywana, w przeciwnym razie zostanie zgłoszony wyjątek). Tego rodzaju rozwijanie stosu może odbywać się z wyjątkami, ale nie można tego zrobić poprzez mechaniczną restrukturyzację obliczeń (jak to jest możliwe bez funkcji zagnieżdżonych).

Najczęstszym powodem, dla którego rzeczywiście chciałbyś powrócić z funkcji zagnieżdżonej, jest przełamanie imperatywu dla zrozumienia lub blokady zasobów. (Ciało imperatyw dla-pojmowania zostanie przetłumaczony na zagnieżdżonej funkcji, mimo że wygląda jak oświadczeniu.)

for(i<- 1 to bezillion; j <- i to bezillion+6){ 
if(expensiveCalculation(i, j)){ 
    return otherExpensiveCalculation(i, j) 
} 

withExpensiveResource(urlForExpensiveResource){ resource => 
// do a bunch of stuff 
if(done) return 
//do a bunch of other stuff 
if(reallyDoneThisTime) return 
//final batch of stuff 
} 
+0

Dzięki za odpowiedź.Jest to bardzo pouczające. – Jus12

+0

Myślę, że jest to bardziej formalna odpowiedź. Jestem zainteresowany dowodem wyniku, o którym wspomniałeś. Czy możesz podać referencje? – Jus12

+0

Dodano link do wikipedii dla twierdzenia o programie strukturalnym. –

26

Dostarcza się w celu dostosowania do tych okoliczności, w których utrudnione lub uciążliwe jest ustalenie wszystkich ścieżek przepływu sterowania w celu zejścia na leksykalny koniec metody.

Chociaż z pewnością jest tak, jak mówi Dave Griffith, że można wyeliminować jakiekolwiek użycie return, często może to być bardziej zaciemnione, niż proste obcięcie skrótu wykonawczego z widocznym return.

Należy również pamiętać, że return powraca z metod, a nie z funkcji (literałów), które można zdefiniować w ramach metody.

+0

Wiedziałem, że to była odpowiedź .. Po prostu nie mogę wymyślić żadnych przykładów. – Jus12

+8

Na szczęście dla mnie nie prosiłeś o żadne przykłady ... –

+0

+1 za zaciemnienie –

2

wyświetlić return jako przydatny przy pisaniu nadrzędny kod styl, który zazwyczaj oznacza, że ​​/ Kod O. Jeśli robisz czysty kod funkcjonalny, nie potrzebujesz (i nie powinieneś używać) return. Ale dzięki funkcjonalnemu kodowi możesz potrzebować lenistwa, aby uzyskać wydajność równoważną z imperatywnym kodem, który może "uciec wcześniej" z użyciem return.

3

Oto przykład

Ta metoda ma wiele if-else do sterowania przepływem, ponieważ nie ma powrotu (czyli to, co ja przyszedłem z, można użyć wyobraźni, aby go przedłużyć). Wziąłem to z prawdziwym przykład życia i modyfikowane to być kod manekina (w rzeczywistości jest on dłuższy niż to):

Bez powrotu:

def process(request: Request[RawBuffer]): Result = { 
     if (condition1) { 
     error() 
     } else { 
     val condition2 = doSomethingElse() 
     if (!condition2) { 
      error() 
     } else { 
      val reply = doAnotherThing() 
      if (reply == null) { 
      Logger.warn("Receipt is null. Send bad request") 
      BadRequest("Coudln't receive receipt") 
      } else { 
      reply.hede = initializeHede() 
      if (reply.hede.isGood) { 
       success() 
      } else { 
       error() 
      } 
      } 
     } 
     } 
    } 

ze zwrotem:

def process(request: Request[RawBuffer]): Result = { 
     if (condition1) { 
     return error() 
     } 

     val condition2 = doSomethingElse() 
     if (!condition2) { 
     return error() 
     } 

     val reply = doAnotherThing() 

     if (reply == null) { 
     Logger.warn("Receipt is null. Send bad request") 
     return BadRequest("Coudln't receive receipt") 
     } 

     reply.hede = initializeHede() 
     if (reply.hede.isGood) 
     return success() 

     return error() 
    } 

W moich oczach ten drugi jest bardziej czytelny, a nawet łatwiejszy w zarządzaniu niż pierwszy. Głębokość wcięcia (z dobrze sformatowanym kodem) idzie głęboko i głęboko, jeśli nie używasz instrukcji return. I nie podoba mi się to :)

+2

Myślę, że dobrze wytrawni programiści Scala (nie ja) mogą lepiej śledzić pierwszy fragment. – Jus12

+0

Rzeczywiście jest to trochę "smaku", zależy od deweloperów punktu widzenia. na przykład Najbardziej podobają mi się płaskie – yerlilbilgin