18.6. Inne obiekty
Łańcuchy znakowe mogą w wielu przypadkach być traktowane jako sekwencje znaków, co pozwala wykorzystać na nich wiele z metod biblioteki kolekcji. Ilustrują to poniższe przykłady.
scala> "hello world".sorted res0: String = " dehllloorw" scala> "abc de f".filterNot(_.isWhitespace).reverse res1: String = fedcba scala> "ab12cde45fhg".filter(_.isDigit).map(c => (c+1).toChar) res2: String = 2356 scala> "hello world".map(c => if (c=='h'||c=='w') c.toUpper else c) res3: String = Hello World
Instancje typów Option, Try i Either umożliwiają użycie niektórych spośród metod spotykanych w kolekcjach. W przypadku Either należy najpierw wybrać, za pomocą metod left lub right, którą z wartości chcemy przetwarzać. Ilustrują to poniższe przykłady.
scala> val o: Option[Int] = Some(5) o: Option[Int] = Some(5) scala> o.map(_+1) res4: Option[Int] = Some(6) scala> o.flatMap(x => if(x>0) Some(x*2) else None) res5: Option[Int] = Some(10) scala> o.map(_-5).flatMap(x => if(x>0) Some(x*2) else None) res6: Option[Int] = None
scala> val n = o.filter(_ == 10) n: Option[Int] = None scala> scala.util.Try(5).map(_+1) res7: scala.util.Try[Int] = Success(6) scala> scala.util.Try(5).filter(_ < 0) res8: scala.util.Try[Int] = Failure(java.util.NoSuchElementException: Predicate does not hold for 5) scala> val e1: Either[Long,String] = Left(5L) e1: Either[Long,String] = Left(5) scala> val e2: Either[Long,String] = Right("hello") e2: Either[Long,String] = Right(hello) scala> e1.left.map(_+1) res9: Product with Serializable with scala.util.Either[Long,String] = Left(6) scala> e1.left.foreach(println) 5 res10: Any = () scala> e2.right.map(_+" world") res11: Product with Serializable with scala.util.Either[Long,String] = Right(hello world)
Klasy Option i Either udostępniają metody o nazwie fold, podobne do metod foldRight dla sekwencji. Za pomocą tych metod można przekształcić wartość typu Option lub Either na jakąś inną wartość. Metoda fold dla opcji ma dwie listy parametrów. W pierwszej podajemy wartość, którą ma zostać zastąpiona opcja pusta. W drugiej należy podać funkcję, która przekształci wartość przechowywaną przez instancję klasy Some. Poniższe wyrażenia tworzą napis o długości takiej, jak wartość przechowywana w opcji, lub łańcuch pusty, jeśli opcja jest pusta.
scala> o.fold("")("x" * _) res12: String = xxxxx scala> n.fold("")("x" * _) res13: String = ""
Metoda fold dla klasy Either przyjmuje dwa argumenty, z których każdy jest funkcją przekształcającą jedną ze stron (pierwszy argument lewą, a drugi prawą) na wartość wynikową. Ilustrują to kolejne przykłady.
scala> e1.fold(n => "x" * n.toInt, s => s.toUpperCase) res14: String = xxxxx scala> e2.fold(n => "x" * n.toInt, s => s.toUpperCase) res15: String = HELLO