17.7. Wyrażenie return w anonimowych funkcjach

Anonimowe funkcje są w rzeczywistości pewnymi obiektami zawierającymi metodę apply. Jeśli taka anonimowa funkcja zawiera wyrażenie return, to wyrażenie to powoduje zakończenie nie tylko działania samej anonimowej funkcji (a więc metody apply zawierającej jej kod), ale również metody, w której ta funkcja była zdefiniowana. Metoda hello, zdefiniowana w pliku Return4.scala, definiuje i wywołuje funkcję anonimową przypisaną do wartości greet. Ta funkcja anonimowa zawiera wyrażenie return.

Plik Return4.scala:
def hello(n: Int): String = {
  val greet = (greeting: String, n: Int) => {
    if (n <= 0) return "wrong parameter value: "+n 
    (greeting+" ") * n
  }
  val result = greet("Hello!",n)
  println("returning: "+result) 
  result
}

Metoda hello pobiera argument w postaci liczby całkowitej i jeśli podana wartość jest dodatnia, to zwraca łańcuch znaków zawierający pozdrowienie powtórzone odpowiednią liczbę razy. Ponieważ metoda zawiera wywołanie metody println, to przed przekazaniem rezultatu, na ekranie zostaje wyświetlona odpowiednia informacja.

scala> :load Return4.scala
Loading Return4.scala...
hello: (n: Int)String

scala> hello(4)
returning: Hello! Hello! Hello! Hello! 
res0: String = "Hello! Hello! Hello! Hello! "

Jeśli jednak metodzie hello zostanie podany argument w postaci liczby zero lub liczby ujemnej, to zwrócony łańcuch znaków będzie zawierał informację o błędnych danych wejściowych. Ponieważ informacja o błędzie jest zwracana z funkcji anonimowej przy pomocy wyrażenia return, to w takim przypadku nie zostanie wywołana metoda println z wiersza . Zamiast tego, wyrażenie return powoduje natychmiastowe zakończenie działania metody hello.

scala> hello(0)
res1: String = wrong parameter value: 0

Implementacja wyrażenia return — takiego jak w wierszu — wykorzystuje mechanizm wyjątków. Wyjście z metody hello jest zaimplementowane przy użyciu wyjątku będącego instancją klasy scala.runtime.NonLocalReturnControl. W pliku Return5.scala znajduje się zmodyfikowana wersja metody hello, w której dodane zostało wyrażenie try z klauzulą catch (wiersz i kolejne). W tej klauzuli następuje przechwycenie tego wyjątku, wypisanie informacji na ekranie i ponowne wyrzucenie wyjątku. Dzięki temu można przekonać się, że rzeczywiście implementacja metody korzysta z takiego wyjątku.

Plik Return5.scala:
def hello(n: Int): String = {
  val greet = (greeting: String, n: Int) => {
    if (n <= 0) return "wrong parameter value: "+n
    (greeting+" ") * n
  }
  val result =
    try greet("Hello!",n) 
    catch { case ex: scala.runtime.NonLocalReturnControl[_] =>
              println("ex: "+ex); throw ex }
  println("returning: "+result)
  result
}

Poniższy przykład ilustruje fakt wykorzystania wyjątku NonLocalReturnControl.

scala> :load Return5.scala
Loading Return5.scala...
hello: (n: Int)String

scala> hello(0)
ex: scala.runtime.NonLocalReturnControl
res2: String = wrong parameter value: 0

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.