From c98de531fa0d1ad4b6b70591e16ce86bcecc1b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Wy=C5=82uda?= Date: Wed, 18 May 2016 18:51:13 +0200 Subject: [PATCH] Fix typos in collections overview --- overviews/collections/arrays.md | 3 +-- overviews/collections/iterators.md | 6 +++--- overviews/collections/migrating-from-scala-27.md | 3 +-- overviews/collections/overview.md | 16 ++++++++-------- .../collections/performance-characteristics.md | 3 +-- overviews/collections/sets.md | 5 ++--- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/overviews/collections/arrays.md b/overviews/collections/arrays.md index 415ec62498..423b877423 100644 --- a/overviews/collections/arrays.md +++ b/overviews/collections/arrays.md @@ -60,7 +60,7 @@ The `ArrayOps` object gets inserted automatically by the implicit conversion. So where `intArrayOps` is the implicit conversion that was inserted previously. This raises the question how the compiler picked `intArrayOps` over the other implicit conversion to `WrappedArray` in the line above. After all, both conversions map an array to a type that supports a reverse method, which is what the input specified. The answer to that question is that the two implicit conversions are prioritized. The `ArrayOps` conversion has a higher priority than the `WrappedArray` conversion. The first is defined in the `Predef` object whereas the second is defined in a class `scala.LowPriorityImplicits`, which is inherited from `Predef`. Implicits in subclasses and subobjects take precedence over implicits in base classes. So if both conversions are applicable, the one in `Predef` is chosen. A very similar scheme works for strings. -So now you know how arrays can be compatible with sequences and how they can support all sequence operations. What about genericity? In Java you cannot write a `T[]` where `T` is a type parameter. How then is Scala's `Array[T]` represented? In fact a generic array like `Array[T]` could be at run-time any of Java's eight primitive array types `byte[]`, `short[]`, `char[]`, `int[]`, `long[]`, `float[]`, `double[]`, `boolean[]`, or it could be an array of objects. The only common run-time type encompassing all of these types is `AnyRef` (or, equivalently `java.lang.Object`), so that's the type to which the Scala compiler maps `Array[T]`. At run-time, when an element of an array of type `Array[T]` is accessed or updated there is a sequence of type tests that determine the actual array type, followed by the correct array operation on the Java array. These type tests slow down array operations somewhat. You can expect accesses to generic arrays to be three to four times slower than accesses to primitive or object arrays. This means that if you need maximal performance, you should prefer concrete over generic arrays. Representing the generic array type is not enough, however, There must also be a way to create generic arrays. This is an even harder problem, which requires a little bit of help from you. To illustrate the problem, consider the following attempt to write a generic method that creates an array. +So now you know how arrays can be compatible with sequences and how they can support all sequence operations. What about genericity? In Java you cannot write a `T[]` where `T` is a type parameter. How then is Scala's `Array[T]` represented? In fact a generic array like `Array[T]` could be at run-time any of Java's eight primitive array types `byte[]`, `short[]`, `char[]`, `int[]`, `long[]`, `float[]`, `double[]`, `boolean[]`, or it could be an array of objects. The only common run-time type encompassing all of these types is `AnyRef` (or, equivalently `java.lang.Object`), so that's the type to which the Scala compiler maps `Array[T]`. At run-time, when an element of an array of type `Array[T]` is accessed or updated there is a sequence of type tests that determine the actual array type, followed by the correct array operation on the Java array. These type tests slow down array operations somewhat. You can expect accesses to generic arrays to be three to four times slower than accesses to primitive or object arrays. This means that if you need maximal performance, you should prefer concrete over generic arrays. Representing the generic array type is not enough, however, there must also be a way to create generic arrays. This is an even harder problem, which requires a little bit of help from you. To illustrate the problem, consider the following attempt to write a generic method that creates an array. // this is wrong! def evenElems[T](xs: Vector[T]): Array[T] = { @@ -115,4 +115,3 @@ What happened here is that the `evenElems` demands a class manifest for the type This example also shows that the context bound in the definition of `U` is just a shorthand for an implicit parameter named here `evidence$1` of type `ClassManifest[U]`. In summary, generic array creation demands class manifests. So whenever creating an array of a type parameter `T`, you also need to provide an implicit class manifest for `T`. The easiest way to do this is to declare the type parameter with a `ClassManifest` context bound, as in `[T: ClassManifest]`. - diff --git a/overviews/collections/iterators.md b/overviews/collections/iterators.md index 466f256e0a..69621666ba 100644 --- a/overviews/collections/iterators.md +++ b/overviews/collections/iterators.md @@ -13,7 +13,7 @@ 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) + while (it.hasNext) println(it.next()) 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: @@ -24,7 +24,7 @@ As always, for-expressions can be used as an alternate syntax for expressions in for (elem <- it) println(elem) -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 on a collection, `foreach` leaves the number of elements in the collection unchanged (unless the passed function adds to removes elements, but this is discouraged, because it may lead to surprising results). +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 to removes elements, but this is discouraged, because it may lead to surprising results). The other operations that Iterator has in common with `Traversable` have the same property. For instance, iterators provide a `map` method, which returns a new iterator: @@ -151,7 +151,7 @@ Sometimes you want an iterator that can "look ahead", so that you can inspect th def skipEmptyWordsNOT(it: Iterator[String]) = while (it.next().isEmpty) {} - + 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](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](http://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. diff --git a/overviews/collections/migrating-from-scala-27.md b/overviews/collections/migrating-from-scala-27.md index c99bd40e09..5d349eb8b4 100644 --- a/overviews/collections/migrating-from-scala-27.md +++ b/overviews/collections/migrating-from-scala-27.md @@ -12,7 +12,7 @@ languages: [ja, zh-cn] Porting your existing Scala applications to use the new collections should be almost automatic. There are only a couple of possible issues to take care of. -Generally, the old functionality of Scala 2.7 collections has been left in place. Some features have been deprecated, which means they will removed in some future release. You will get a _deprecation warning_ when you compile code that makes use of these features in Scala 2.8. In a few places deprecation was unfeasible, because the operation in question was retained in 2.8, but changed in meaning or performance characteristics. These cases will be flagged with _migration warnings_ when compiled under 2.8. To get full deprecation and migration warnings with suggestions how to change your code, pass the `-deprecation` and `-Xmigration` flags to `scalac` (note that `-Xmigration` is an extended option, so it starts with an `X`.) You can also pass the same options to the `scala` REPL to get the warnings in an interactive session. Example: +Generally, the old functionality of Scala 2.7 collections has been left in place. Some features have been deprecated, which means they will removed in some future release. You will get a _deprecation warning_ when you compile code that makes use of these features in Scala 2.8. In a few places deprecation was unfeasible, because the operation in question was retained in 2.8, but changed in meaning or performance characteristics. These cases will be flagged with _migration warnings_ when compiled under 2.8. To get full deprecation and migration warnings with suggestions how to change your code, pass the `-deprecation` and `-Xmigration` flags to `scalac` (note that `-Xmigration` is an extended option, so it starts with an `X`). You can also pass the same options to the `scala` REPL to get the warnings in an interactive session. Example: >scala -deprecation -Xmigration Welcome to Scala version 2.8.0.final @@ -42,4 +42,3 @@ There are two parts of the old libraries which have been replaced wholesale, and 2. Projections have been generalized and cleaned up and are now available as views. It seems that projections were used rarely, so not much code should be affected by this change. So, if your code uses either `jcl` or projections there might be some minor rewriting to do. - diff --git a/overviews/collections/overview.md b/overviews/collections/overview.md index b733880b74..5d2e4e141b 100644 --- a/overviews/collections/overview.md +++ b/overviews/collections/overview.md @@ -69,8 +69,8 @@ versions of collections is to import just the package import scala.collection.mutable -Then a word like `Set` without a prefix still refers to an an immutable collection, -whereas `mutable.Set` refers to the mutable counterpart. +Then a word like `Set` without a prefix still refers to an immutable collection, +whereas `mutable.Set` refers to the mutable counterpart. The last package in the collection hierarchy is `collection.generic`. This package contains building blocks for implementing @@ -82,19 +82,19 @@ classes in `generic` only in exceptional circumstances. For convenience and backwards compatibility some important types have aliases in the `scala` package, so you can use them by their simple names without needing an import. An example is the `List` type, which -can be accessed alternatively as +can be accessed alternatively as scala.collection.immutable.List // that's where it is defined scala.List // via the alias in the scala package - List // because scala._ + List // because scala._ // is always automatically imported -Other types so aliased are +Other types so aliased are [Traversable](http://www.scala-lang.org/api/current/scala/collection/Traversable.html), [Iterable](http://www.scala-lang.org/api/current/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/current/scala/collection/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/current/scala/collection/Iterator.html), [Stream](http://www.scala-lang.org/api/current/scala/collection/immutable/Stream.html), [Vector](http://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/current/scala/collection/mutable/StringBuilder.html), and [Range](http://www.scala-lang.org/api/current/scala/collection/immutable/Range.html). The following figure shows all collections in package `scala.collection`. These are all high-level abstract classes or traits, which -generally have mutable as well as immutable implementations. +generally have mutable as well as immutable implementations. []({{ site.baseurl }}/resources/images/collections.png) @@ -130,7 +130,7 @@ All these collections get displayed with `toString` in the same way they are wri All collections support the API provided by `Traversable`, but specialize types wherever this makes sense. For instance the `map` method in class `Traversable` returns another `Traversable` as its result. But this result type is overridden in subclasses. For instance, calling `map` on a `List` yields again a `List`, calling it on a `Set` yields again a `Set` and so on. - scala> List(1, 2, 3) map (_ + 1) + scala> List(1, 2, 3) map (_ + 1) res0: List[Int] = List(2, 3, 4) scala> Set(1, 2, 3) map (_ * 2) res0: Set[Int] = Set(2, 4, 6) @@ -139,4 +139,4 @@ This behavior which is implemented everywhere in the collections libraries is ca Most of the classes in the collections hierarchy exist in three variants: root, mutable, and immutable. The only exception is the Buffer trait which only exists as a mutable collection. -In the following, we will review these classes one by one. \ No newline at end of file +In the following, we will review these classes one by one. diff --git a/overviews/collections/performance-characteristics.md b/overviews/collections/performance-characteristics.md index 65e349403c..2b148e6940 100644 --- a/overviews/collections/performance-characteristics.md +++ b/overviews/collections/performance-characteristics.md @@ -69,7 +69,7 @@ The first table treats sequence types--both immutable and mutable--with the foll | **head** | Selecting the first element of the sequence. | | **tail** | Producing a new sequence that consists of all elements except the first one. | | **apply** | Indexing. | -| **update** | Functional update (with `updated`) for immutable sequences, side-effecting update (with `update` for mutable sequences. | +| **update** | Functional update (with `updated`) for immutable sequences, side-effecting update (with `update` for mutable sequences). | | **prepend**| Adding an element to the front of the sequence. For immutable sequences, this produces a new sequence. For mutable sequences it modified the existing sequence. | | **append** | Adding an element and the end of the sequence. For immutable sequences, this produces a new sequence. For mutable sequences it modified the existing sequence. | | **insert** | Inserting an element at an arbitrary position in the sequence. This is only supported directly for mutable sequences. | @@ -82,4 +82,3 @@ The second table treats mutable and immutable sets and maps with the following o | **add** | Adding a new element to a set or key/value pair to a map. | | **remove** | Removing an element from a set or a key from a map. | | **min** | The smallest element of the set, or the smallest key of a map. | - diff --git a/overviews/collections/sets.md b/overviews/collections/sets.md index a6fda8fbaa..2b862fc3d0 100644 --- a/overviews/collections/sets.md +++ b/overviews/collections/sets.md @@ -11,7 +11,7 @@ languages: [ja, zh-cn] `Set`s are `Iterable`s that contain no duplicate elements. The operations on sets are summarized in the following table for general sets and in the table after that for mutable sets. They fall into the following categories: -* **Tests** `contains`, `apply`, `subsetOf`. The `contains` method asks whether a set contains a given element. The `apply` method for a set is the same as `contains`, so `set(elem)` is the same as `set contains elem`. That means sets can also be used as test functions that return true for the elements they contain. +* **Tests** `contains`, `apply`, `subsetOf`. The `contains` method asks whether a set contains a given element. The `apply` method for a set is the same as `contains`, so `set(elem)` is the same as `set contains elem`. That means sets can also be used as test functions that return true for the elements they contain. For example: @@ -97,7 +97,7 @@ We used `+=` and `-=` on a `var` of type `immutable.Set`. A statement such as `s scala> s -= 2 res4: s.type = Set(1, 4, 3) -The end effect is very similar to the previous interaction; we start with a `Set(1, 2, 3)` end end up with a `Set(1, 3, 4)`. However, even though the statements look the same as before, they do something different. `s += 4` now invokes the `+=` method on the mutable set value `s`, changing the set in place. Likewise, `s -= 2` now invokes the `-=` method on the same set. +The end effect is very similar to the previous interaction; we start with a `Set(1, 2, 3)` and end up with a `Set(1, 3, 4)`. However, even though the statements look the same as before, they do something different. `s += 4` now invokes the `+=` method on the mutable set value `s`, changing the set in place. Likewise, `s -= 2` now invokes the `-=` method on the same set. Comparing the two interactions shows an important principle. You often can replace a mutable collection stored in a `val` by an immutable collection stored in a `var`, and _vice versa_. This works at least as long as there are no alias references to the collection through which one can observe whether it was updated in place or whether a new collection was created. @@ -146,4 +146,3 @@ Sorted sets also support ranges of elements. For instance, the `range` method re Bitsets are sets of non-negative integer elements that are implemented in one or more words of packed bits. The internal representation of a [BitSet](http://www.scala-lang.org/api/current/scala/collection/BitSet.html) uses an array of `Long`s. The first `Long` covers elements from 0 to 63, the second from 64 to 127, and so on (Immutable bitsets of elements in the range of 0 to 127 optimize the array away and store the bits directly in a one or two `Long` fields.) For every `Long`, each of its 64 bits is set to 1 if the corresponding element is contained in the set, and is unset otherwise. It follows that the size of a bitset depends on the largest integer that's stored in it. If `N` is that largest integer, then the size of the set is `N/64` `Long` words, or `N/8` bytes, plus a small number of extra bytes for status information. Bitsets are hence more compact than other sets if they contain many small elements. Another advantage of bitsets is that operations such as membership test with `contains`, or element addition and removal with `+=` and `-=` are all extremely efficient. -