diff --git a/_overviews/collections-2.13/conversion-between-option-and-the-collections.md b/_overviews/collections-2.13/conversion-between-option-and-the-collections.md index 7fff2ea548..d1b2e771cf 100644 --- a/_overviews/collections-2.13/conversion-between-option-and-the-collections.md +++ b/_overviews/collections-2.13/conversion-between-option-and-the-collections.md @@ -13,6 +13,8 @@ permalink: /overviews/collections-2.13/:title.html Hence `Option` can be used everywhere an `IterableOnce` is expected, for example, when calling `flatMap` on a collection (or inside a for-comprehension) +{% tabs options_1 class=tabs-scala-version %} +{% tab 'Scala 2' for=options_1 %} ```scala mdoc for { a <- Set(1) @@ -20,33 +22,59 @@ for { } yield (a + b) // : Set[Int] = Set(42) ``` +{% endtab %} +{% tab 'Scala 3' for=options_1 %} +```scala +for + a <- Set(1) + b <- Option(41) +yield (a + b) +// : Set[Int] = Set(42) +``` +{% endtab %} +{% endtabs %} since the operation `flatMap` on the type `Set[Int]` takes a function returning an `IterableOnce`: +{% tabs options_2 %} +{% tab 'Scala 2 and 3' for=options_2 %} ``` def flatMap[B](f: Int => IterableOnce[B]): Set[B] ``` +{% endtab %} +{% endtabs %} Although `Option` does not extend `Iterable`, there exists an [implicit conversion](https://github.com/scala/scala/blob/6c68c2825e893bb71d6dc78465ac8c6f415cbd93/src/library/scala/Option.scala#L19) between `Option` and `Iterable` - +{% tabs options_3 %} +{% tab 'Scala 2 and 3' for=options_3 %} ``` implicit def option2Iterable[A](xo: Option[A]): Iterable[A] ``` +{% endtab %} +{% endtabs %} so although `Option[A]` is not a full collection it can be _viewed_ as one. For example, +{% tabs options_4 %} +{% tab 'Scala 2 and 3' for=options_4 %} ```scala mdoc Some(42).drop(1) // : Iterable[Int] = List() ``` +{% endtab %} +{% endtabs %} expands to +{% tabs options_5 %} +{% tab 'Scala 2 and 3' for=options_5 %} ```scala mdoc Option.option2Iterable(Some(42)).drop(1) // : Iterable[Int] = List() ``` +{% endtab %} +{% endtabs %} because `drop` is not defined on `Option`. A downside of the above implicit conversion is that instead of getting back an `Option[A]` we are left with an `Iterable[A]`. For this reason, `Option`’s documentation carries the following note: diff --git a/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md b/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md index b4090053ba..d66183d84a 100644 --- a/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md +++ b/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md @@ -16,49 +16,101 @@ Like Scala, Java also has a rich collections library. There are many similaritie Sometimes you might need to pass from one collection framework to the other. For instance, you might want to access an existing Java collection as if it were a Scala collection. Or you might want to pass one of Scala's collections to a Java method that expects its Java counterpart. It is quite easy to do this, because Scala offers implicit conversions between all the major collection types in the [CollectionConverters](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/jdk/CollectionConverters$.html) object. In particular, you will find bidirectional conversions between the following types. +``` +Iterator <=> java.util.Iterator +Iterator <=> java.util.Enumeration +Iterable <=> java.lang.Iterable +Iterable <=> java.util.Collection +mutable.Buffer <=> java.util.List +mutable.Set <=> java.util.Set +mutable.Map <=> java.util.Map +mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap +``` + +To enable these conversions, import them from the [CollectionConverters](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/jdk/CollectionConverters$.html) object: + +{% tabs java_scala_1 class=tabs-scala-version %} +{% tab 'Scala 2' for=java_scala_1 %} + +```scala +scala> import scala.jdk.CollectionConverters._ +import scala.jdk.CollectionConverters._ +``` + +{% endtab %} +{% tab 'Scala 3' for=java_scala_1 %} + +```scala +scala> import scala.jdk.CollectionConverters.* +import scala.jdk.CollectionConverters.* +``` + +{% endtab %} +{% endtabs %} - Iterator <=> java.util.Iterator - Iterator <=> java.util.Enumeration - Iterable <=> java.lang.Iterable - Iterable <=> java.util.Collection - mutable.Buffer <=> java.util.List - mutable.Set <=> java.util.Set - mutable.Map <=> java.util.Map - mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap +This enables conversions between Scala collections and their corresponding Java collections by way of extension methods called `asScala` and `asJava`: -To enable these conversions, simply import them from the [CollectionConverters](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/jdk/CollectionConverters$.html) object: +{% tabs java_scala_2 class=tabs-scala-version %} +{% tab 'Scala 2' for=java_scala_2 %} - scala> import scala.jdk.CollectionConverters._ - import scala.jdk.CollectionConverters._ +```scala +scala> import collection.mutable._ +import collection.mutable._ -This enables conversions between Scala collections and their corresponding Java collections by way of extension methods called `asScala` and `asJava`: +scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava +val jul: java.util.List[Int] = [1, 2, 3] + +scala> val buf: Seq[Int] = jul.asScala +val buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) + +scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava +val m: java.util.Map[String,Int] = {abc=1, hello=2} +``` - scala> import collection.mutable._ - import collection.mutable._ +{% endtab %} +{% tab 'Scala 3' for=java_scala_2 %} - scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava - jul: java.util.List[Int] = [1, 2, 3] +```scala +scala> import collection.mutable.* +import collection.mutable.* - scala> val buf: Seq[Int] = jul.asScala - buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) +scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava +val jul: java.util.List[Int] = [1, 2, 3] - scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava - m: java.util.Map[String,Int] = {abc=1, hello=2} +scala> val buf: Seq[Int] = jul.asScala +val buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) + +scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava +val m: java.util.Map[String,Int] = {abc=1, hello=2} +``` + +{% endtab %} +{% endtabs %} Internally, these conversion work by setting up a "wrapper" object that forwards all operations to the underlying collection object. So collections are never copied when converting between Java and Scala. An interesting property is that if you do a round-trip conversion from, say a Java type to its corresponding Scala type, and back to the same Java type, you end up with the identical collection object you have started with. Certain other Scala collections can also be converted to Java, but do not have a conversion back to the original Scala type: - Seq => java.util.List - mutable.Seq => java.util.List - Set => java.util.Set - Map => java.util.Map +``` +Seq => java.util.List +mutable.Seq => java.util.List +Set => java.util.Set +Map => java.util.Map +``` Because Java does not distinguish between mutable and immutable collections in their type, a conversion from, say, `scala.immutable.List` will yield a `java.util.List`, where all mutation operations throw an "UnsupportedOperationException". Here's an example: - scala> val jul = List(1, 2, 3).asJava - jul: java.util.List[Int] = [1, 2, 3] +{% tabs java_scala_3 %} +{% tab 'Scala 2 and 3' for=java_scala_3 %} + +```scala +scala> val jul = List(1, 2, 3).asJava +val jul: java.util.List[Int] = [1, 2, 3] + +scala> jul.add(7) +java.lang.UnsupportedOperationException + at java.util.AbstractList.add(AbstractList.java:148) +``` - scala> jul.add(7) - java.lang.UnsupportedOperationException - at java.util.AbstractList.add(AbstractList.java:148) +{% endtab %} +{% endtabs %} diff --git a/_overviews/collections-2.13/creating-collections-from-scratch.md b/_overviews/collections-2.13/creating-collections-from-scratch.md index 660830dd99..9f10410750 100644 --- a/_overviews/collections-2.13/creating-collections-from-scratch.md +++ b/_overviews/collections-2.13/creating-collections-from-scratch.md @@ -14,27 +14,53 @@ permalink: /overviews/collections-2.13/:title.html You have syntax `List(1, 2, 3)` to create a list of three integers and `Map('A' -> 1, 'C' -> 2)` to create a map with two bindings. This is actually a universal feature of Scala collections. You can take any collection name and follow it by a list of elements in parentheses. The result will be a new collection with the given elements. Here are some more examples: - Iterable() // An empty collection - List() // The empty list - List(1.0, 2.0) // A list with elements 1.0, 2.0 - Vector(1.0, 2.0) // A vector with elements 1.0, 2.0 - Iterator(1, 2, 3) // An iterator returning three integers. - Set(dog, cat, bird) // A set of three animals - HashSet(dog, cat, bird) // A hash set of the same animals - Map('a' -> 7, 'b' -> 0) // A map from characters to integers +{% tabs creating_1 %} +{% tab 'Scala 2 and 3' for=creating_1 %} + +```scala +val a = Iterable() // An empty collection +val b = List() // The empty list +val c = List(1.0, 2.0) // A list with elements 1.0, 2.0 +val d = Vector(1.0, 2.0) // A vector with elements 1.0, 2.0 +val e = Iterator(1, 2, 3) // An iterator returning three integers. +val f = Set(dog, cat, bird) // A set of three animals +val g = HashSet(dog, cat, bird) // A hash set of the same animals +val h = Map('a' -> 7, 'b' -> 0) // A map from characters to integers +``` + +{% endtab %} +{% endtabs %} "Under the covers" each of the above lines is a call to the `apply` method of some object. For instance, the third line above expands to - List.apply(1.0, 2.0) +{% tabs creating_2 %} +{% tab 'Scala 2 and 3' for=creating_2 %} + +```scala +val c = List.apply(1.0, 2.0) +``` + +{% endtab %} +{% endtabs %} So this is a call to the `apply` method of the companion object of the `List` class. That method takes an arbitrary number of arguments and constructs a list from them. Every collection class in the Scala library has a companion object with such an `apply` method. It does not matter whether the collection class represents a concrete implementation, like `List`, `LazyList` or `Vector`, or whether it is an abstract base class such as `Seq`, `Set` or `Iterable`. In the latter case, calling apply will produce some default implementation of the abstract base class. Examples: - scala> List(1, 2, 3) - res17: List[Int] = List(1, 2, 3) - scala> Iterable(1, 2, 3) - res18: Iterable[Int] = List(1, 2, 3) - scala> mutable.Iterable(1, 2, 3) - res19: scala.collection.mutable.Iterable[Int] = ArrayBuffer(1, 2, 3) +{% tabs creating_3 %} +{% tab 'Scala 2 and 3' for=creating_3 %} + +```scala +scala> List(1, 2, 3) +val res17: List[Int] = List(1, 2, 3) + +scala> Iterable(1, 2, 3) +val res18: Iterable[Int] = List(1, 2, 3) + +scala> mutable.Iterable(1, 2, 3) +val res19: scala.collection.mutable.Iterable[Int] = ArrayBuffer(1, 2, 3) +``` + +{% endtab %} +{% endtabs %} Besides `apply`, every collection companion object also defines a member `empty`, which returns an empty collection. So instead of `List()` you could write `List.empty`, instead of `Map()`, `Map.empty`, and so on. diff --git a/_overviews/collections-2.13/iterators.md b/_overviews/collections-2.13/iterators.md index 7af6bc9d0c..a72716740d 100644 --- a/_overviews/collections-2.13/iterators.md +++ b/_overviews/collections-2.13/iterators.md @@ -16,46 +16,99 @@ An iterator is not a collection, but rather a way to access the elements of a co The most straightforward way to "step through" all the elements returned by an iterator `it` uses a while-loop: - while (it.hasNext) - println(it.next()) +{% tabs iterators_1 class=tabs-scala-version %} +{% tab 'Scala 2' for=iterators_1 %} +```scala +while (it.hasNext) + println(it.next()) +``` +{% endtab %} +{% tab 'Scala 3' for=iterators_1 %} +```scala +while it.hasNext do + println(it.next()) +``` +{% endtab %} +{% endtabs %} + +Iterators in Scala also provide analogues of most of the methods that you find in the `Iterable` and `Seq` classes. For instance, they provide a `foreach` method which executes a given procedure on each element returned by an iterator. Using `foreach`, the loop above could be abbreviated to: + +{% tabs iterators_2 %} +{% tab 'Scala 2 and 3' for=iterators_2 %} + +```scala +it.foreach(println) +``` + +{% endtab %} +{% endtabs %} -Iterators in Scala also provide analogues of most of the methods that you find in the `Traversable`, `Iterable` and `Seq` classes. For instance, they provide a `foreach` method which executes a given procedure on each element returned by an iterator. Using `foreach`, the loop above could be abbreviated to: +As always, for-expressions can be used as an alternate syntax for expressions involving `foreach`, `map`, `withFilter`, and `flatMap`, so yet another way to print all elements returned by an iterator would be: - it foreach println +{% tabs iterators_3 class=tabs-scala-version %} +{% tab 'Scala 2' for=iterators_3 %} +```scala +for (elem <- it) println(elem) +``` +{% endtab %} +{% tab 'Scala 3' for=iterators_3 %} +```scala +for elem <- it do println(elem) +``` +{% endtab %} +{% endtabs %} + +There's an important difference between the foreach method on iterators and the same method on iterable collections: When called on an iterator, `foreach` will leave the iterator at its end when it is done. So calling `next` again on the same iterator will fail with a `NoSuchElementException`. By contrast, when called on a collection, `foreach` leaves the number of elements in the collection unchanged (unless the passed function adds or removes elements, but this is discouraged, because it may lead to surprising results). -As always, for-expressions can be used as an alternate syntax for expressions involving `foreach`, `map`, `withFilter`, and `flatMap`, so yet another way to print all elements returned by an iterator would be: +The other operations that `Iterator` has in common with `Iterable` have the same property. For instance, iterators provide a `map` method, which returns a new iterator: - for (elem <- it) println(elem) +{% tabs iterators_4 %} +{% tab 'Scala 2 and 3' for=iterators_4 %} -There's an important difference between the foreach method on iterators and the same method on traversable collections: When called on an iterator, `foreach` will leave the iterator at its end when it is done. So calling `next` again on the same iterator will fail with a `NoSuchElementException`. By contrast, when called on a collection, `foreach` leaves the number of elements in the collection unchanged (unless the passed function adds or removes elements, but this is discouraged, because it may lead to surprising results). +```scala +scala> val it = Iterator("a", "number", "of", "words") +val it: Iterator[java.lang.String] = -The other operations that `Iterator` has in common with `Iterable` have the same property. For instance, iterators provide a `map` method, which returns a new iterator: +scala> it.map(_.length) +val res1: Iterator[Int] = + +scala> it.hasNext +val res2: Boolean = true + +scala> res1.foreach(println) +1 +6 +2 +5 - scala> val it = Iterator("a", "number", "of", "words") - it: Iterator[java.lang.String] = - scala> it.map(_.length) - res1: Iterator[Int] = - scala> it.hasNext - res2: Boolean = true - scala> res1 foreach println - 1 - 6 - 2 - 5 - scala> it.hasNext - res4: Boolean = false +scala> it.hasNext +val res4: Boolean = false +``` + +{% endtab %} +{% endtabs %} As you can see, after the call to `it.map`, the `it` iterator hasn’t advanced to its end, but traversing the iterator resulting from the call to `res1.foreach` also traverses `it` and advances it to its end. Another example is the `dropWhile` method, which can be used to find the first elements of an iterator that has a certain property. For instance, to find the first word in the iterator above that has at least two characters you could write: - scala> val it = Iterator("a", "number", "of", "words") - it: Iterator[java.lang.String] = - scala> it dropWhile (_.length < 2) - res4: Iterator[java.lang.String] = - scala> res4.next() - res5: java.lang.String = number +{% tabs iterators_5 %} +{% tab 'Scala 2 and 3' for=iterators_5 %} + +```scala +scala> val it = Iterator("a", "number", "of", "words") +val it: Iterator[java.lang.String] = + +scala> it.dropWhile(_.length < 2) +val res4: Iterator[java.lang.String] = + +scala> res4.next() +val res5: java.lang.String = number +``` + +{% endtab %} +{% endtabs %} Note again that `it` was changed by the call to `dropWhile`: it now points to the second word "number" in the list. In fact, `it` and the result `res4` returned by `dropWhile` will return exactly the same sequence of elements. @@ -63,15 +116,23 @@ In fact, `it` and the result `res4` returned by `dropWhile` will return exactly One way to circumvent this behavior is to `duplicate` the underlying iterator instead of calling methods on it directly. The _two_ iterators that result will each return exactly the same elements as the underlying iterator `it`: - scala> val (words, ns) = Iterator("a", "number", "of", "words").duplicate - words: Iterator[String] = - ns: Iterator[String] = +{% tabs iterators_6 %} +{% tab 'Scala 2 and 3' for=iterators_6 %} + +```scala +scala> val (words, ns) = Iterator("a", "number", "of", "words").duplicate +val words: Iterator[String] = +val ns: Iterator[String] = - scala> val shorts = words.filter(_.length < 3).toList - shorts: List[String] = List(a, of) +scala> val shorts = words.filter(_.length < 3).toList +val shorts: List[String] = List(a, of) - scala> val count = ns.map(_.length).sum - count: Int = 14 +scala> val count = ns.map(_.length).sum +val count: Int = 14 +``` + +{% endtab %} +{% endtabs %} The two iterators work independently: advancing one does not affect the other, so that each can be destructively modified by invoking arbitrary methods. This creates the illusion of iterating over @@ -87,31 +148,31 @@ All operations on iterators are summarized below. | WHAT IT IS | WHAT IT DOES | | ------ | ------ | | **Abstract Methods:** | | -| `it.next()` | Returns next element on iterator and advances past it. | -| `it.hasNext` | Returns `true` if `it` can return another element. | +| `it.next()` | Returns next element on iterator and advances past it. | +| `it.hasNext` | Returns `true` if `it` can return another element. | | **Variations:** | | | `it.buffered` | A buffered iterator returning all elements of `it`. | -| `it grouped size` | An iterator that yields the elements returned by `it` in fixed-sized sequence "chunks". | -| `it sliding size` | An iterator that yields the elements returned by `it` in sequences representing a sliding fixed-sized window. | +| `it.grouped(size)` | An iterator that yields the elements returned by `it` in fixed-sized sequence "chunks". | +| `it.sliding(size)` | An iterator that yields the elements returned by `it` in sequences representing a sliding fixed-sized window. | | **Duplication:** | | | `it.duplicate` | A pair of iterators that each independently return all elements of `it`. | | **Additions:** | | -| `it concat jt`
or `it ++ jt` | An iterator returning all elements returned by iterator `it`, followed by all elements returned by iterator `jt`. | -| `it.padTo(len, x)` | The iterator that first returns all elements of `it` and then follows that by copies of `x` until length `len` elements are returned overall. | +| `it.concat(jt)`
or `it ++ jt` | An iterator returning all elements returned by iterator `it`, followed by all elements returned by iterator `jt`. | +| `it.padTo(len, x)` | The iterator that first returns all elements of `it` and then follows that by copies of `x` until length `len` elements are returned overall. | | **Maps:** | | -| `it map f` | The iterator obtained from applying the function `f` to every element returned from `it`. | -| `it flatMap f` | The iterator obtained from applying the iterator-valued function `f` to every element in `it` and appending the results. | -| `it collect f` | The iterator obtained from applying the partial function `f` to every element in `it` for which it is defined and collecting the results. | +| `it.map(f)` | The iterator obtained from applying the function `f` to every element returned from `it`. | +| `it.flatMap(f)` | The iterator obtained from applying the iterator-valued function `f` to every element in `it` and appending the results. | +| `it.collect(f)` | The iterator obtained from applying the partial function `f` to every element in `it` for which it is defined and collecting the results. | | **Conversions:** | | | `it.toArray` | Collects the elements returned by `it` in an array. | | `it.toList` | Collects the elements returned by `it` in a list. | | `it.toIterable` | Collects the elements returned by `it` in an iterable. | | `it.toSeq` | Collects the elements returned by `it` in a sequence. | | `it.toIndexedSeq` | Collects the elements returned by `it` in an indexed sequence. | -| `it.toLazyList` | Collects the elements returned by `it` in a lazy list. | +| `it.toLazyList` | Collects the elements returned by `it` in a lazy list. | | `it.toSet` | Collects the elements returned by `it` in a set. | | `it.toMap` | Collects the key/value pairs returned by `it` in a map. | -| **Copying:** | | +| **Copying:** | | | `it.copyToArray(arr, s, n)`| Copies at most `n` elements returned by `it` to array `arr` starting at index `s`. The last two arguments are optional. | | **Size Info:** | | | `it.isEmpty` | Test whether the iterator is empty (opposite of `hasNext`). | @@ -120,44 +181,44 @@ All operations on iterators are summarized below. | `it.length` | Same as `it.size`. | | `it.knownSize` |The number of elements, if this one is known without modifying the iterator’s state, otherwise `-1`. | | **Element Retrieval Index Search:**| | -| `it find p` | An option containing the first element returned by `it` that satisfies `p`, or `None` is no element qualifies. Note: The iterator advances to after the element, or, if none is found, to the end. | -| `it indexOf x` | The index of the first element returned by `it` that equals `x`. Note: The iterator advances past the position of this element. | -| `it indexWhere p` | The index of the first element returned by `it` that satisfies `p`. Note: The iterator advances past the position of this element. | +| `it.find(p)` | An option containing the first element returned by `it` that satisfies `p`, or `None` is no element qualifies. Note: The iterator advances to after the element, or, if none is found, to the end. | +| `it.indexOf(x)` | The index of the first element returned by `it` that equals `x`. Note: The iterator advances past the position of this element. | +| `it.indexWhere(p)` | The index of the first element returned by `it` that satisfies `p`. Note: The iterator advances past the position of this element. | | **Subiterators:** | | -| `it take n` | An iterator returning of the first `n` elements of `it`. Note: it will advance to the position after the `n`'th element, or to its end, if it contains less than `n` elements. | -| `it drop n` | The iterator that starts with the `(n+1)`'th element of `it`. Note: `it` will advance to the same position. | -| `it.slice(m,n)` | The iterator that returns a slice of the elements returned from it, starting with the `m`'th element and ending before the `n`'th element. | -| `it takeWhile p` | An iterator returning elements from `it` as long as condition `p` is true. | -| `it dropWhile p` | An iterator skipping elements from `it` as long as condition `p` is `true`, and returning the remainder. | -| `it filter p` | An iterator returning all elements from `it` that satisfy the condition `p`. | -| `it withFilter p` | Same as `it` filter `p`. Needed so that iterators can be used in for-expressions. | -| `it filterNot p` | An iterator returning all elements from `it` that do not satisfy the condition `p`. | +| `it.take(n)` | An iterator returning of the first `n` elements of `it`. Note: it will advance to the position after the `n`'th element, or to its end, if it contains less than `n` elements. | +| `it.drop(n)` | The iterator that starts with the `(n+1)`'th element of `it`. Note: `it` will advance to the same position. | +| `it.slice(m,n)` | The iterator that returns a slice of the elements returned from it, starting with the `m`'th element and ending before the `n`'th element. | +| `it.takeWhile(p)` | An iterator returning elements from `it` as long as condition `p` is true. | +| `it.dropWhile(p)` | An iterator skipping elements from `it` as long as condition `p` is `true`, and returning the remainder. | +| `it.filter(p)` | An iterator returning all elements from `it` that satisfy the condition `p`. | +| `it.withFilter(p)` | Same as `it` filter `p`. Needed so that iterators can be used in for-expressions. | +| `it.filterNot(p)` | An iterator returning all elements from `it` that do not satisfy the condition `p`. | | `it.distinct` | An iterator returning the elements from `it` without duplicates. | | **Subdivisions:** | | -| `it partition p` | Splits `it` into a pair of two iterators: one returning all elements from `it` that satisfy the predicate `p`, the other returning all elements from `it` that do not. | -| `it span p` | Splits `it` into a pair of two iterators: one returning all elements of the prefix of `it` that satisfy the predicate `p`, the other returning all remaining elements of `it`. | +| `it.partition(p)` | Splits `it` into a pair of two iterators: one returning all elements from `it` that satisfy the predicate `p`, the other returning all elements from `it` that do not. | +| `it.span(p)` | Splits `it` into a pair of two iterators: one returning all elements of the prefix of `it` that satisfy the predicate `p`, the other returning all remaining elements of `it`. | | **Element Conditions:** | | -| `it forall p` | A boolean indicating whether the predicate p holds for all elements returned by `it`. | -| `it exists p` | A boolean indicating whether the predicate p holds for some element in `it`. | -| `it count p` | The number of elements in `it` that satisfy the predicate `p`. | +| `it.forall(p)` | A boolean indicating whether the predicate p holds for all elements returned by `it`. | +| `it.exists(p)` | A boolean indicating whether the predicate p holds for some element in `it`. | +| `it.count(p)` | The number of elements in `it` that satisfy the predicate `p`. | | **Folds:** | | | `it.foldLeft(z)(op)` | Apply binary operation `op` between successive elements returned by `it`, going left to right and starting with `z`. | | `it.foldRight(z)(op)` | Apply binary operation `op` between successive elements returned by `it`, going right to left and starting with `z`. | -| `it reduceLeft op` | Apply binary operation `op` between successive elements returned by non-empty iterator `it`, going left to right. | -| `it reduceRight op` | Apply binary operation `op` between successive elements returned by non-empty iterator `it`, going right to left. | +| `it.reduceLeft(op)` | Apply binary operation `op` between successive elements returned by non-empty iterator `it`, going left to right. | +| `it.reduceRight(op)` | Apply binary operation `op` between successive elements returned by non-empty iterator `it`, going right to left. | | **Specific Folds:** | | | `it.sum` | The sum of the numeric element values returned by iterator `it`. | | `it.product` | The product of the numeric element values returned by iterator `it`. | | `it.min` | The minimum of the ordered element values returned by iterator `it`. | | `it.max` | The maximum of the ordered element values returned by iterator `it`. | | **Zippers:** | | -| `it zip jt` | An iterator of pairs of corresponding elements returned from iterators `it` and `jt`. | -| `it.zipAll(jt, x, y)` | An iterator of pairs of corresponding elements returned from iterators `it` and `jt`, where the shorter iterator is extended to match the longer one by appending elements `x` or `y`. | +| `it.zip(jt)` | An iterator of pairs of corresponding elements returned from iterators `it` and `jt`. | +| `it.zipAll(jt, x, y)` | An iterator of pairs of corresponding elements returned from iterators `it` and `jt`, where the shorter iterator is extended to match the longer one by appending elements `x` or `y`. | | `it.zipWithIndex` | An iterator of pairs of elements returned from `it` with their indices. | | **Update:** | | -| `it.patch(i, jt, r)` | The iterator resulting from `it` by replacing `r` elements starting with `i` by the patch iterator `jt`. | +| `it.patch(i, jt, r)` | The iterator resulting from `it` by replacing `r` elements starting with `i` by the patch iterator `jt`. | | **Comparison:** | | -| `it sameElements jt` | A test whether iterators `it` and `jt` return the same elements in the same order. Note: Using the iterators after this operation is undefined and subject to change. | +| `it.sameElements(jt)` | A test whether iterators `it` and `jt` return the same elements in the same order. Note: Using the iterators after this operation is undefined and subject to change. | | **Strings:** | | | `it.addString(b, start, sep, end)`| Adds a string to `StringBuilder` `b` which shows all elements returned by `it` between separators `sep` enclosed in strings `start` and `end`. `start`, `sep`, `end` are all optional. | | `it.mkString(start, sep, end)` | Converts the collection to a string which shows all elements returned by `it` between separators `sep` enclosed in strings `start` and `end`. `start`, `sep`, `end` are all optional. | @@ -176,38 +237,82 @@ This is one of the reasons why it's important to only use pure functions as argu Laziness is still valuable, despite often not being visible, as it can prevent unneeded computations from happening, and can allow for working with infinite sequences, like so: - def zipWithIndex[A](i: Iterator[A]): Iterator[(Int, A)] = - Iterator.from(0).zip(i) +{% tabs iterators_7 %} +{% tab 'Scala 2 and 3' for=iterators_7 %} + +```scala +def zipWithIndex[A](i: Iterator[A]): Iterator[(Int, A)] = + Iterator.from(0).zip(i) +``` + +{% endtab %} +{% endtabs %} ### Buffered iterators Sometimes you want an iterator that can "look ahead", so that you can inspect the next element to be returned without advancing past that element. Consider for instance, the task to skip leading empty strings from an iterator that returns a sequence of strings. You might be tempted to write the following - - def skipEmptyWordsNOT(it: Iterator[String]) = - while (it.next().isEmpty) {} +{% tabs iterators_8 class=tabs-scala-version %} +{% tab 'Scala 2' for=iterators_8 %} +```scala mdoc +def skipEmptyWordsNOT(it: Iterator[String]) = + while (it.next().isEmpty) {} +``` +{% endtab %} +{% tab 'Scala 3' for=iterators_8 %} +```scala +def skipEmptyWordsNOT(it: Iterator[String]) = + while it.next().isEmpty do () +``` +{% endtab %} +{% endtabs %} But looking at this code more closely, it's clear that this is wrong: The code will indeed skip leading empty strings, but it will also advance `it` past the first non-empty string! The solution to this problem is to use a buffered iterator. Class [BufferedIterator](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html), which provides one extra method, `head`. Calling `head` on a buffered iterator will return its first element but will not advance the iterator. Using a buffered iterator, skipping empty words can be written as follows. - def skipEmptyWords(it: BufferedIterator[String]) = - while (it.head.isEmpty) { it.next() } +{% tabs iterators_9 class=tabs-scala-version %} +{% tab 'Scala 2' for=iterators_9 %} +```scala +def skipEmptyWords(it: BufferedIterator[String]) = + while (it.head.isEmpty) { it.next() } +``` +{% endtab %} +{% tab 'Scala 3' for=iterators_9 %} +```scala +def skipEmptyWords(it: BufferedIterator[String]) = + while it.head.isEmpty do it.next() +``` +{% endtab %} +{% endtabs %} Every iterator can be converted to a buffered iterator by calling its `buffered` method. Here's an example: - scala> val it = Iterator(1, 2, 3, 4) - it: Iterator[Int] = - scala> val bit = it.buffered - bit: scala.collection.BufferedIterator[Int] = - scala> bit.head - res10: Int = 1 - scala> bit.next() - res11: Int = 1 - scala> bit.next() - res12: Int = 2 - scala> bit.headOption - res13: Option[Int] = Some(3) +{% tabs iterators_10 %} +{% tab 'Scala 2 and 3' for=iterators_10 %} + +```scala +scala> val it = Iterator(1, 2, 3, 4) +val it: Iterator[Int] = + +scala> val bit = it.buffered +val bit: scala.collection.BufferedIterator[Int] = + +scala> bit.head +val res10: Int = 1 + +scala> bit.next() +val res11: Int = 1 + +scala> bit.next() +val res12: Int = 2 + +scala> bit.headOption +val res13: Option[Int] = Some(3) +``` + +{% endtab %} +{% endtabs %} Note that calling `head` on the buffered iterator `bit` does not advance it. Therefore, the subsequent call `bit.next()` returns the same value as `bit.head`. @@ -217,21 +322,50 @@ The buffered iterator only buffers the next element when `head` is invoked. Othe such as those produced by `duplicate` and `partition`, may buffer arbitrary subsequences of the underlying iterator. But iterators can be efficiently joined by adding them together with `++`: - scala> def collapse(it: Iterator[Int]) = if (!it.hasNext) Iterator.empty else { - | var head = it.next - | val rest = if (head == 0) it.dropWhile(_ == 0) else it - | Iterator.single(head) ++ rest - | } - collapse: (it: Iterator[Int])Iterator[Int] - - scala> def collapse(it: Iterator[Int]) = { - | val (zeros, rest) = it.span(_ == 0) - | zeros.take(1) ++ rest - | } - collapse: (it: Iterator[Int])Iterator[Int] - - scala> collapse(Iterator(0, 0, 0, 1, 2, 3, 4)).toList - res14: List[Int] = List(0, 1, 2, 3, 4) +{% tabs iterators_11 class=tabs-scala-version %} +{% tab 'Scala 2' for=iterators_11 %} + +```scala +scala> def collapse(it: Iterator[Int]) = if (!it.hasNext) Iterator.empty else { + | var head = it.next + | val rest = if (head == 0) it.dropWhile(_ == 0) else it + | Iterator.single(head) ++ rest + |} +def collapse(it: Iterator[Int]): Iterator[Int] + +scala> def collapse(it: Iterator[Int]) = { + | val (zeros, rest) = it.span(_ == 0) + | zeros.take(1) ++ rest + |} +def collapse(it: Iterator[Int]): Iterator[Int] + +scala> collapse(Iterator(0, 0, 0, 1, 2, 3, 4)).toList +val res14: List[Int] = List(0, 1, 2, 3, 4) +``` + +{% endtab %} +{% tab 'Scala 3' for=iterators_11 %} + +```scala +scala> def collapse(it: Iterator[Int]) = if !it.hasNext then Iterator.empty else + | var head = it.next + | val rest = if head == 0 then it.dropWhile(_ == 0) else it + | Iterator.single(head) ++ rest + | +def collapse(it: Iterator[Int]): Iterator[Int] + +scala> def collapse(it: Iterator[Int]) = + | val (zeros, rest) = it.span(_ == 0) + | zeros.take(1) ++ rest + | +def collapse(it: Iterator[Int]): Iterator[Int] + +scala> collapse(Iterator(0, 0, 0, 1, 2, 3, 4)).toList +val res14: List[Int] = List(0, 1, 2, 3, 4) +``` + +{% endtab %} +{% endtabs %} In the second version of `collapse`, the unconsumed zeros are buffered internally. In the first version, any leading zeros are dropped and the desired result constructed diff --git a/_overviews/collections-2.13/maps.md b/_overviews/collections-2.13/maps.md index 030850e835..81580815b7 100644 --- a/_overviews/collections-2.13/maps.md +++ b/_overviews/collections-2.13/maps.md @@ -16,7 +16,7 @@ A [Map](https://www.scala-lang.org/api/current/scala/collection/Map.html) is an The fundamental operations on maps are similar to those on sets. They are summarized in the following table and fall into the following categories: -* **Lookup** operations `apply`, `get`, `getOrElse`, `contains`, and `isDefinedAt`. These turn maps into partial functions from keys to values. The fundamental lookup method for a map is: `def get(key): Option[Value]`. The operation `m get key` tests whether the map contains an association for the given `key`. If so, it returns the associated value in a `Some`. If no key is defined in the map, `get` returns `None`. Maps also define an `apply` method that returns the value associated with a given key directly, without wrapping it in an `Option`. If the key is not defined in the map, an exception is raised. +* **Lookup** operations `apply`, `get`, `getOrElse`, `contains`, and `isDefinedAt`. These turn maps into partial functions from keys to values. The fundamental lookup method for a map is: `def get(key): Option[Value]`. The operation `m.get(key)` tests whether the map contains an association for the given `key`. If so, it returns the associated value in a `Some`. If no key is defined in the map, `get` returns `None`. Maps also define an `apply` method that returns the value associated with a given key directly, without wrapping it in an `Option`. If the key is not defined in the map, an exception is raised. * **Additions and updates** `+`, `++`, `updated`, which let you add new bindings to a map or change existing bindings. * **Removals** `-`, `--`, which remove bindings from a map. * **Subcollection producers** `keys`, `keySet`, `keysIterator`, `values`, `valuesIterator`, which return a map's keys and values separately in various forms. @@ -64,7 +64,7 @@ Mutable maps support in addition the operations summarized in the following tabl | **Additions and Updates:** | | | `ms(k) = v` |(Or, written out, `ms.update(k, v)`). Adds mapping from key `k` to value `v` to map ms as a side effect, overwriting any previous mapping of `k`.| | `ms.addOne(k -> v)`
or `ms += (k -> v)` |Adds mapping from key `k` to value `v` to map `ms` as a side effect and returns `ms` itself.| -| `ms addAll xvs`
or `ms ++= kvs` |Adds all mappings in `kvs` to `ms` as a side effect and returns `ms` itself.| +| `ms.addAll(xvs)`
or `ms ++= kvs` |Adds all mappings in `kvs` to `ms` as a side effect and returns `ms` itself.| | `ms.put(k, v)` |Adds mapping from key `k` to value `v` to `ms` and returns any value previously associated with `k` as an option.| | `ms.getOrElseUpdate(k, d)` |If key `k` is defined in map `ms`, return its associated value. Otherwise, update `ms` with the mapping `k -> d` and return `d`.| | **Removals:** | | diff --git a/_overviews/collections-2.13/seqs.md b/_overviews/collections-2.13/seqs.md index 4123b59fb1..a5fe562ad5 100644 --- a/_overviews/collections-2.13/seqs.md +++ b/_overviews/collections-2.13/seqs.md @@ -32,17 +32,17 @@ If a sequence is mutable, it offers in addition a side-effecting `update` method | WHAT IT IS | WHAT IT DOES | | ------ | ------ | | **Indexing and Length:** | | -| `xs(i)` |(or, written out, `xs apply i`). The element of `xs` at index `i`.| -| `xs isDefinedAt i` |Tests whether `i` is contained in `xs.indices`.| +| `xs(i)` |(or, written out, `xs.apply(i)`). The element of `xs` at index `i`.| +| `xs.isDefinedAt(i)` |Tests whether `i` is contained in `xs.indices`.| | `xs.length` |The length of the sequence (same as `size`).| -| `xs lengthCompare n` |Returns `-1` if `xs` is shorter than `n`, `+1` if it is longer, and `0` if it is of length `n`. Works even if the sequence is infinite, for example `LazyList.from(1) lengthCompare 42` returns a positive value.| +| `xs.lengthCompare(n)` |Returns `-1` if `xs` is shorter than `n`, `+1` if it is longer, and `0` if it is of length `n`. Works even if the sequence is infinite, for example `LazyList.from(1).lengthCompare(42)` returns a positive value.| | `xs.indices` |The index range of `xs`, extending from `0` to `xs.length - 1`.| | **Index Search:** | | -| `xs indexOf x` |The index of the first element in `xs` equal to `x` (several variants exist).| -| `xs lastIndexOf x` |The index of the last element in `xs` equal to `x` (several variants exist).| -| `xs indexOfSlice ys` |The first index of `xs` such that successive elements starting from that index form the sequence `ys`.| -| `xs lastIndexOfSlice ys` |The last index of `xs` such that successive elements starting from that index form the sequence `ys`.| -| `xs indexWhere p` |The index of the first element in xs that satisfies `p` (several variants exist).| +| `xs.indexOf(x)` |The index of the first element in `xs` equal to `x` (several variants exist).| +| `xs.lastIndexOf(x)` |The index of the last element in `xs` equal to `x` (several variants exist).| +| `xs.indexOfSlice(ys)` |The first index of `xs` such that successive elements starting from that index form the sequence `ys`.| +| `xs.lastIndexOfSlice(ys)` |The last index of `xs` such that successive elements starting from that index form the sequence `ys`.| +| `xs.indexWhere(p)` |The index of the first element in xs that satisfies `p` (several variants exist).| | `xs.segmentLength(p, i)`|The length of the longest uninterrupted segment of elements in `xs`, starting with `xs(i)`, that all satisfy the predicate `p`.| | **Additions:** | | | `xs.prepended(x)`
or `x +: xs` |A new sequence that consists of `x` prepended to `xs`.| @@ -56,24 +56,24 @@ If a sequence is mutable, it offers in addition a side-effecting `update` method | `xs(i) = x` |(or, written out, `xs.update(i, x)`, only available for `mutable.Seq`s). Changes the element of `xs` at index `i` to `x`.| | **Sorting:** | | | `xs.sorted` |A new sequence obtained by sorting the elements of `xs` using the standard ordering of the element type of `xs`.| -| `xs sortWith lt` |A new sequence obtained by sorting the elements of `xs` using `lt` as comparison operation.| -| `xs sortBy f` |A new sequence obtained by sorting the elements of `xs`. Comparison between two elements proceeds by mapping the function `f` over both and comparing the results.| +| `xs.sortWith(lt)` |A new sequence obtained by sorting the elements of `xs` using `lt` as comparison operation.| +| `xs.sortBy(f)` |A new sequence obtained by sorting the elements of `xs`. Comparison between two elements proceeds by mapping the function `f` over both and comparing the results.| | **Reversals:** | | | `xs.reverse` |A sequence with the elements of `xs` in reverse order.| | `xs.reverseIterator` |An iterator yielding all the elements of `xs` in reverse order.| | **Comparisons:** | | -| `xs sameElements ys` |A test whether `xs` and `ys` contain the same elements in the same order| -| `xs startsWith ys` |Tests whether `xs` starts with sequence `ys` (several variants exist).| -| `xs endsWith ys` |Tests whether `xs` ends with sequence `ys` (several variants exist).| -| `xs contains x` |Tests whether `xs` has an element equal to `x`.| -| `xs search x` |Tests whether a sorted sequence `xs` has an element equal to `x`, possibly in a more efficient way than `xs contains x`.| -| `xs containsSlice ys` |Tests whether `xs` has a contiguous subsequence equal to `ys`.| -| `(xs corresponds ys)(p)` |Tests whether corresponding elements of `xs` and `ys` satisfy the binary predicate `p`.| +| `xs.sameElements(ys)` |A test whether `xs` and `ys` contain the same elements in the same order| +| `xs.startsWith(ys)` |Tests whether `xs` starts with sequence `ys` (several variants exist).| +| `xs.endsWith(ys)` |Tests whether `xs` ends with sequence `ys` (several variants exist).| +| `xs.contains(x)` |Tests whether `xs` has an element equal to `x`.| +| `xs.search(x)` |Tests whether a sorted sequence `xs` has an element equal to `x`, possibly in a more efficient way than `xs.contains(x)`.| +| `xs.containsSlice(ys)` |Tests whether `xs` has a contiguous subsequence equal to `ys`.| +| `xs.corresponds(ys)(p)` |Tests whether corresponding elements of `xs` and `ys` satisfy the binary predicate `p`.| | **Multiset Operations:** | | -| `xs intersect ys` |The multi-set intersection of sequences `xs` and `ys` that preserves the order of elements in `xs`.| -| `xs diff ys` |The multi-set difference of sequences `xs` and `ys` that preserves the order of elements in `xs`.| +| `xs.intersect(ys)` |The multi-set intersection of sequences `xs` and `ys` that preserves the order of elements in `xs`.| +| `xs.diff(ys)` |The multi-set difference of sequences `xs` and `ys` that preserves the order of elements in `xs`.| | `xs.distinct` |A subsequence of `xs` that contains no duplicated element.| -| `xs distinctBy f` |A subsequence of `xs` that contains no duplicated element after applying the transforming function `f`. For instance, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "quux")`| +| `xs.distinctBy(f)` |A subsequence of `xs` that contains no duplicated element after applying the transforming function `f`. For instance, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "quux")`| Trait [Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html) has two subtraits [LinearSeq](https://www.scala-lang.org/api/current/scala/collection/LinearSeq.html), and [IndexedSeq](https://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html). These do not add any new operations to the immutable branch, but each offers different performance characteristics: A linear sequence has efficient `head` and `tail` operations, whereas an indexed sequence has efficient `apply`, `length`, and (if mutable) `update` operations. Frequently used linear sequences are `scala.collection.immutable.List` and `scala.collection.immutable.LazyList`. Frequently used indexed sequences are `scala.Array` and `scala.collection.mutable.ArrayBuffer`. The `Vector` class provides an interesting compromise between indexed and linear access. It has both effectively constant time indexing overhead and constant time linear access overhead. Because of this, vectors are a good foundation for mixed access patterns where both indexed and linear accesses are used. You'll learn more on vectors [later]({% link _overviews/collections-2.13/concrete-immutable-collection-classes.md %}). @@ -102,20 +102,20 @@ Two often used implementations of buffers are `ListBuffer` and `ArrayBuffer`. A | WHAT IT IS | WHAT IT DOES| | ------ | ------ | | **Additions:** | | -| `buf append x`
or `buf += x` |Appends element `x` to buffer, and returns `buf` itself as result.| -| `buf appendAll xs`
or`buf ++= xs` |Appends all elements in `xs` to buffer.| -| `buf prepend x`
or `x +=: buf` |Prepends element `x` to buffer.| -| `buf prependAll xs`
or `xs ++=: buf` |Prepends all elements in `xs` to buffer.| +| `buf.append(x)`
or `buf += x` |Appends element `x` to buffer, and returns `buf` itself as result.| +| `buf.appendAll(xs)`
or`buf ++= xs` |Appends all elements in `xs` to buffer.| +| `buf.prepend(x)`
or `x +=: buf` |Prepends element `x` to buffer.| +| `buf.prependAll(xs)`
or `xs ++=: buf` |Prepends all elements in `xs` to buffer.| | `buf.insert(i, x)` |Inserts element `x` at index `i` in buffer.| | `buf.insertAll(i, xs)` |Inserts all elements in `xs` at index `i` in buffer.| | `buf.padToInPlace(n, x)` |Appends element `x` to buffer until it has `n` elements in total.| | **Removals:** | | -| `buf subtractOne x`
or `buf -= x` |Removes element `x` from buffer.| -| `buf subtractAll xs`
or `buf --= xs` |Removes elements in `xs` from buffer.| -| `buf remove i` |Removes element at index `i` from buffer.| +| `buf.subtractOne(x)`
or `buf -= x` |Removes element `x` from buffer.| +| `buf.subtractAll(xs)`
or `buf --= xs` |Removes elements in `xs` from buffer.| +| `buf.remove(i)` |Removes element at index `i` from buffer.| | `buf.remove(i, n)` |Removes `n` elements starting at index `i` from buffer.| -| `buf trimStart n` |Removes first `n` elements from buffer.| -| `buf trimEnd n` |Removes last `n` elements from buffer.| +| `buf.trimStart(n)` |Removes first `n` elements from buffer.| +| `buf.trimEnd(n)` |Removes last `n` elements from buffer.| | `buf.clear()` |Removes all elements from buffer.| | **Replacement:** | | | `buf.patchInPlace(i, xs, n)` |Replaces (at most) `n` elements of buffer by elements in `xs`, starting from index `i` in buffer.| diff --git a/_overviews/collections-2.13/trait-iterable.md b/_overviews/collections-2.13/trait-iterable.md index 66a8bdcb41..f1d01e2865 100644 --- a/_overviews/collections-2.13/trait-iterable.md +++ b/_overviews/collections-2.13/trait-iterable.md @@ -72,15 +72,15 @@ res7: List[Int] = List(3, 4, 5) | **Abstract Method:** | | | `xs.iterator` |An `iterator` that yields every element in `xs`.| | **Other Iterators:** | | -| `xs foreach f` |Executes function `f` for every element of `xs`.| -| `xs grouped size` |An iterator that yields fixed-sized "chunks" of this collection.| -| `xs sliding size` |An iterator that yields a sliding fixed-sized window of elements in this collection.| +| `xs.foreach(f)` |Executes function `f` for every element of `xs`.| +| `xs.grouped(size)` |An iterator that yields fixed-sized "chunks" of this collection.| +| `xs.sliding(size)` |An iterator that yields a sliding fixed-sized window of elements in this collection.| | **Addition:** | | -| `xs concat ys`
(or `xs ++ ys`) |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [IterableOnce](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IterableOnce.html) collection, i.e., either an [Iterable](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) or an [Iterator](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html).| +| `xs.concat(ys)`
(or `xs ++ ys`) |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [IterableOnce](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IterableOnce.html) collection, i.e., either an [Iterable](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) or an [Iterator](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html).| | **Maps:** | | -| `xs map f` |The collection obtained from applying the function f to every element in `xs`.| -| `xs flatMap f` |The collection obtained from applying the collection-valued function `f` to every element in `xs` and concatenating the results.| -| `xs collect f` |The collection obtained from applying the partial function `f` to every element in `xs` for which it is defined and collecting the results.| +| `xs.map(f)` |The collection obtained from applying the function f to every element in `xs`.| +| `xs.flatMap(f)` |The collection obtained from applying the collection-valued function `f` to every element in `xs` and concatenating the results.| +| `xs.collect(f)` |The collection obtained from applying the partial function `f` to every element in `xs` for which it is defined and collecting the results.| | **Conversions:** | | | `xs.to(SortedSet)` | Generic conversion operation that takes a collection factory as parameter. | | `xs.toList` |Converts the collection to a list. | @@ -106,36 +106,36 @@ res7: List[Int] = List(3, 4, 5) | `xs.headOption` |The first element of `xs` in an option value, or None if `xs` is empty.| | `xs.last` |The last element of the collection (or, some element, if no order is defined).| | `xs.lastOption` |The last element of `xs` in an option value, or None if `xs` is empty.| -| `xs find p` |An option containing the first element in `xs` that satisfies `p`, or `None` if no element qualifies.| +| `xs.find(p)` |An option containing the first element in `xs` that satisfies `p`, or `None` if no element qualifies.| | **Subcollections:** | | | `xs.tail` |The rest of the collection except `xs.head`. | | `xs.init` |The rest of the collection except `xs.last`. | | `xs.slice(from, to)` |A collection consisting of elements in some index range of `xs` (from `from` up to, and excluding `to`).| -| `xs take n` |A collection consisting of the first `n` elements of `xs` (or, some arbitrary `n` elements, if no order is defined).| -| `xs drop n` |The rest of the collection except `xs take n`.| -| `xs takeWhile p` |The longest prefix of elements in the collection that all satisfy `p`.| -| `xs dropWhile p` |The collection without the longest prefix of elements that all satisfy `p`.| -| `xs takeRight n` |A collection consisting of the last `n` elements of `xs` (or, some arbitrary `n` elements, if no order is defined).| -| `xs dropRight n` |The rest of the collection except `xs takeRight n`.| -| `xs filter p` |The collection consisting of those elements of xs that satisfy the predicate `p`.| -| `xs withFilter p` |A non-strict filter of this collection. Subsequent calls to `map`, `flatMap`, `foreach`, and `withFilter` will only apply to those elements of `xs` for which the condition `p` is true.| -| `xs filterNot p` |The collection consisting of those elements of `xs` that do not satisfy the predicate `p`.| +| `xs.take(n)` |A collection consisting of the first `n` elements of `xs` (or, some arbitrary `n` elements, if no order is defined).| +| `xs.drop(n)` |The rest of the collection except `xs.take(n)`.| +| `xs.takeWhile(p)` |The longest prefix of elements in the collection that all satisfy `p`.| +| `xs.dropWhile(p)` |The collection without the longest prefix of elements that all satisfy `p`.| +| `xs.takeRight(n)` |A collection consisting of the last `n` elements of `xs` (or, some arbitrary `n` elements, if no order is defined).| +| `xs.dropRight(n)` |The rest of the collection except `xs.takeRight(n)`.| +| `xs.filter(p)` |The collection consisting of those elements of xs that satisfy the predicate `p`.| +| `xs.withFilter(p)` |A non-strict filter of this collection. Subsequent calls to `map`, `flatMap`, `foreach`, and `withFilter` will only apply to those elements of `xs` for which the condition `p` is true.| +| `xs.filterNot(p)` |The collection consisting of those elements of `xs` that do not satisfy the predicate `p`.| | **Subdivisions:** | | -| `xs splitAt n` |Split `xs` at a position, giving the pair of collections `(xs take n, xs drop n)`.| -| `xs span p` |Split `xs` according to a predicate, giving the pair of collections `(xs takeWhile p, xs.dropWhile p)`.| -| `xs partition p` |Split `xs` into a pair of collections; one with elements that satisfy the predicate `p`, the other with elements that do not, giving the pair of collections `(xs filter p, xs.filterNot p)`| -| `xs groupBy f` |Partition `xs` into a map of collections according to a discriminator function `f`.| +| `xs.splitAt(n)` |Split `xs` at a position, giving the pair of collections `(xs take n, xs drop n)`.| +| `xs.span(p)` |Split `xs` according to a predicate, giving the pair of collections `(xs takeWhile p, xs.dropWhile p)`.| +| `xs.partition(p)` |Split `xs` into a pair of collections; one with elements that satisfy the predicate `p`, the other with elements that do not, giving the pair of collections `(xs filter p, xs.filterNot p)`| +| `xs.groupBy(f)` |Partition `xs` into a map of collections according to a discriminator function `f`.| | `xs.groupMap(f)(g)`|Partition `xs` into a map of collections according to a discriminator function `f`, and applies the transformation function `g` to each element in a group.| | `xs.groupMapReduce(f)(g)(h)`|Partition `xs` according to a discriminator function `f`, and then combine the results of applying the function `g` to each element in a group using the `h` function.| | **Element Conditions:** | | -| `xs forall p` |A boolean indicating whether the predicate `p` holds for all elements of `xs`.| -| `xs exists p` |A boolean indicating whether the predicate `p` holds for some element in `xs`.| -| `xs count p` |The number of elements in `xs` that satisfy the predicate `p`.| +| `xs.forall(p)` |A boolean indicating whether the predicate `p` holds for all elements of `xs`.| +| `xs.exists(p)` |A boolean indicating whether the predicate `p` holds for some element in `xs`.| +| `xs.count(p)` |The number of elements in `xs` that satisfy the predicate `p`.| | **Folds:** | | | `xs.foldLeft(z)(op)` |Apply binary operation `op` between successive elements of `xs`, going left to right and starting with `z`.| | `xs.foldRight(z)(op)` |Apply binary operation `op` between successive elements of `xs`, going right to left and ending with `z`.| -| `xs reduceLeft op` |Apply binary operation `op` between successive elements of non-empty collection `xs`, going left to right.| -| `xs reduceRight op` |Apply binary operation `op` between successive elements of non-empty collection `xs`, going right to left.| +| `xs.reduceLeft(op)` |Apply binary operation `op` between successive elements of non-empty collection `xs`, going left to right.| +| `xs.reduceRight(op)` |Apply binary operation `op` between successive elements of non-empty collection `xs`, going right to left.| | **Specific Folds:** | | | `xs.sum` |The sum of the numeric element values of collection `xs`.| | `xs.product` |The product of the numeric element values of collection `xs`.| @@ -148,7 +148,7 @@ res7: List[Int] = List(3, 4, 5) | `xs.mkString(start, sep, end)`|Converts the collection to a string that shows all elements of `xs` between separators `sep` enclosed in strings `start` and `end`. `start`, `sep`, `end` are all optional.| | `xs.stringPrefix` |The collection name at the beginning of the string returned from `xs.toString`.| | **Zippers:** | | -| `xs zip ys` |A collection of pairs of corresponding elements from `xs` and `ys`.| +| `xs.zip(ys)` |A collection of pairs of corresponding elements from `xs` and `ys`.| | `xs.zipAll(ys, x, y)` |A collection of pairs of corresponding elements from `xs` and `ys`, where the shorter sequence is extended to match the longer one by appending elements `x` or `y`.| | `xs.zipWithIndex` |An collection of pairs of elements from `xs` with their indices.| | **Views:** | |