14.15. Definiowanie funkcji za pomocą ciągu klauzul case

Scala umożliwia zastosowanie specjalnej składni do tworzenia funkcji anonimowych, która polega na umieszczeniu w nawiasach klamrowych ciągu klauzul case, takich jak używane w wyrażeniu match. Plik CaseFunctions1.scala zawiera definicję funkcji zwracającej pozdrowienie w różnych językach, zdefiniowanej przy użyciu takiej składni.

Plik CaseFunctions1.scala:
val hello1: PartialFunction[String,String] = { 
  case "en" => "Hello!"
  case "it" => "Ciao!"
}

Poniższe polecenia ilustrują sposoby wykorzystania funkcji hello1.

scala> :load CaseFunctions1.scala
Loading CaseFunctions1.scala...
hello1: PartialFunction[String,String] = <function1>

scala> hello1.isDefinedAt("en")
res0: Boolean = true

scala> hello1("en")
res1: String = Hello!

scala> hello1("it")
res2: String = Ciao!

Wywołanie funkcji dla nieobsługiwanego argumentu skutkuje wystąpieniem wyjątku.

scala> hello1.isDefinedAt("fr")
res3: Boolean = false

scala> hello1("fr")
scala.MatchError: fr (of class java.lang.String)
  at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:253)
  at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:251)
  at $anonfun$1.applyOrElse(<console>:10)
  at $anonfun$1.applyOrElse(<console>:10)
  at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
  ... 33 elided

Kod z pliku CaseFunctions1.scala definiuje funkcję mającą typ ogólny PartialFunction, a w konsekwencji posiadającą metodę isDefinedAt. Za pomocą składni wyrażeń case można również utworzyć funkcję, która nie implementuje isDefinedAt. W przykładzie z pliku CaseFunctions2.scala kontekst wymaga funkcji typu String => String.

Plik CaseFunctions2.scala:
val hello2: String => String = { 
  case "en" => "Hello!"
  case "it" => "Ciao!"
}

W konsekwencji metoda isDefinedAt nie zostaje dla tej funkcji wygenerowana, co można sprawdzić odwołując się do mechanizmu refleksji dostępnego na platformie JVM.

scala> :load CaseFunctions2.scala
Loading CaseFunctions2.scala...
hello2: String => String = <function1>

scala> hello1.getClass.getMethods.exists(_.toString.contains("isDefinedAt"))
res5: Boolean = true

scala> hello2.getClass.getMethods.exists(_.toString.contains("isDefinedAt"))
res6: Boolean = false

Specyfikacja języka Scala opisuje notację wykorzystującą ciąg klauzul case do tworzenia funkcji w punkcie 8.5.

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.