You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: overviews/collections/arrays.md
+1-2Lines changed: 1 addition & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -60,7 +60,7 @@ The `ArrayOps` object gets inserted automatically by the implicit conversion. So
60
60
61
61
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.
62
62
63
-
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.
63
+
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.
64
64
65
65
// this is wrong!
66
66
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
115
115
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]`.
116
116
117
117
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]`.
Copy file name to clipboardExpand all lines: overviews/collections/iterators.md
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ An iterator is not a collection, but rather a way to access the elements of a co
13
13
14
14
The most straightforward way to "step through" all the elements returned by an iterator `it` uses a while-loop:
15
15
16
-
while (it.hasNext)
16
+
while (it.hasNext)
17
17
println(it.next())
18
18
19
19
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
24
24
25
25
for (elem <- it) println(elem)
26
26
27
-
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).
27
+
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).
28
28
29
29
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:
30
30
@@ -151,7 +151,7 @@ Sometimes you want an iterator that can "look ahead", so that you can inspect th
151
151
152
152
def skipEmptyWordsNOT(it: Iterator[String]) =
153
153
while (it.next().isEmpty) {}
154
-
154
+
155
155
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!
156
156
157
157
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.
Copy file name to clipboardExpand all lines: overviews/collections/migrating-from-scala-27.md
+1-2Lines changed: 1 addition & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ languages: [ja, zh-cn]
12
12
13
13
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.
14
14
15
-
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:
15
+
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:
16
16
17
17
>scala -deprecation -Xmigration
18
18
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
42
42
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.
43
43
44
44
So, if your code uses either `jcl` or projections there might be some minor rewriting to do.
@@ -130,7 +130,7 @@ All these collections get displayed with `toString` in the same way they are wri
130
130
131
131
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.
132
132
133
-
scala> List(1, 2, 3) map (_ + 1)
133
+
scala> List(1, 2, 3) map (_ + 1)
134
134
res0: List[Int] = List(2, 3, 4)
135
135
scala> Set(1, 2, 3) map (_ * 2)
136
136
res0: Set[Int] = Set(2, 4, 6)
@@ -139,4 +139,4 @@ This behavior which is implemented everywhere in the collections libraries is ca
139
139
140
140
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.
141
141
142
-
In the following, we will review these classes one by one.
142
+
In the following, we will review these classes one by one.
Copy file name to clipboardExpand all lines: overviews/collections/performance-characteristics.md
+1-2Lines changed: 1 addition & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -69,7 +69,7 @@ The first table treats sequence types--both immutable and mutable--with the foll
69
69
|**head**| Selecting the first element of the sequence. |
70
70
|**tail**| Producing a new sequence that consists of all elements except the first one. |
71
71
|**apply**| Indexing. |
72
-
|**update**| Functional update (with `updated`) for immutable sequences, side-effecting update (with `update` for mutable sequences. |
72
+
|**update**| Functional update (with `updated`) for immutable sequences, side-effecting update (with `update` for mutable sequences). |
73
73
|**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. |
74
74
|**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. |
75
75
|**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
82
82
|**add**| Adding a new element to a set or key/value pair to a map. |
83
83
|**remove**| Removing an element from a set or a key from a map. |
84
84
|**min**| The smallest element of the set, or the smallest key of a map. |
Copy file name to clipboardExpand all lines: overviews/collections/sets.md
+2-3Lines changed: 2 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ languages: [ja, zh-cn]
11
11
12
12
`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:
13
13
14
-
***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.
14
+
***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.
15
15
16
16
For example:
17
17
@@ -97,7 +97,7 @@ We used `+=` and `-=` on a `var` of type `immutable.Set`. A statement such as `s
97
97
scala> s -= 2
98
98
res4: s.type = Set(1, 4, 3)
99
99
100
-
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.
100
+
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.
101
101
102
102
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.
103
103
@@ -146,4 +146,3 @@ Sorted sets also support ranges of elements. For instance, the `range` method re
146
146
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.
147
147
148
148
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.
0 commit comments