diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index 7026e7e15b..7f3e5c2a78 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -3,6 +3,6 @@ title: Bug fixes link: /contribute/guide.html icon: fa fa-bug --- -Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs][bug-reporting-guide]. +Issues with the tools, core libraries and compiler. Also, you can help us by [reporting bugs][bug-reporting-guide]. [bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} diff --git a/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md b/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md index 9b99acabd3..cc7eb73add 100644 --- a/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md +++ b/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md @@ -34,7 +34,7 @@ you'll need to install a Scala SDK. To the right of the Scala SDK field, click the **Create** button. 1. Select the highest version number (e.g. {{ site.scala-version }}) and click **Download**. This might take a few minutes but subsequent projects can use the same SDK. -1. Once the SDK is created and you're back to the "New Project" window click **Finish**. +1. Once the SDK is created, and you're back to the "New Project" window, click **Finish**. ## Writing code diff --git a/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md b/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md index bfc23717f8..1b765824b6 100644 --- a/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md +++ b/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md @@ -28,7 +28,7 @@ This assumes you know [how to build a project in IntelliJ](building-a-scala-proj unrecognized. 1. On the project pane on the left, expand `src` => `main`. 1. Right-click on `scala` and select **New** => **Scala class**. -1. Call it `CubeCalculator`, change the **Kind** to `object`, and hit enter or double click on `object`. +1. Call it `CubeCalculator`, change the **Kind** to `object`, and hit enter or double-click on `object`. 1. Replace the code with the following: ``` object CubeCalculator extends App { @@ -41,7 +41,7 @@ This assumes you know [how to build a project in IntelliJ](building-a-scala-proj ## Creating a test 1. On the project pane on the left, expand `src` => `test`. 1. Right-click on `scala` and select **New** => **Scala class**. -1. Name the class `CubeCalculatorTest` and hit enter or double click on `class`. +1. Name the class `CubeCalculatorTest` and hit enter or double-click on `class`. 1. Replace the code with the following: ``` import org.scalatest.funsuite.AnyFunSuite diff --git a/_glossary/index.md b/_glossary/index.md index 3eba952f88..75b5c98081 100644 --- a/_glossary/index.md +++ b/_glossary/index.md @@ -44,7 +44,7 @@ You can assign an object to a variable. Afterwards, the variable will refer to t Extra constructors defined inside the curly braces of the class definition, which look like method definitions named `this`, but with no result type. * #### block -One or more expressions and declarations surrounded by curly braces. When the block evaluates, all of its expressions and declarations are processed in order, and then the block returns the value of the last expression as its own value. Blocks are commonly used as the bodies of functions, [for expressions](#for-expression), `while` loops, and any other place where you want to group a number of statements together. More formally, a block is an encapsulation construct for which you can only see side effects and a result value. The curly braces in which you define a class or object do not, therefore, form a block, because fields and methods (which are defined inside those curly braces) are visible from the out- side. Such curly braces form a template. +One or more expressions and declarations surrounded by curly braces. When the block evaluates, all of its expressions and declarations are processed in order, and then the block returns the value of the last expression as its own value. Blocks are commonly used as the bodies of functions, [for expressions](#for-expression), `while` loops, and any other place where you want to group a number of statements together. More formally, a block is an encapsulation construct for which you can only see side effects and a result value. The curly braces in which you define a class or object do not, therefore, form a block, because fields and methods (which are defined inside those curly braces) are visible from the outside. Such curly braces form a template. * #### bound variable A bound variable of an expression is a variable that’s both used and defined inside the expression. For instance, in the function literal expression `(x: Int) => (x, y)`, both variables `x` and `y` are used, but only `x` is bound, because it is defined in the expression as an `Int` and the sole argument to the function described by the expression. @@ -299,7 +299,7 @@ A _self type_ of a trait is the assumed type of `this`, the receiver, to be used XML data is semi-structured. It is more structured than a flat binary file or text file, but it does not have the full structure of a programming language’s data structures. * #### serialization -You can _serialize_ an object into a byte stream which can then be saved to files or transmitted over the network. You can later _deserialize_ the byte stream, even on different computer, and obtain an object that is the same as the original serialized object. +You can _serialize_ an object into a byte stream which can then be saved to a file or transmitted over the network. You can later _deserialize_ the byte stream, even on different computer, and obtain an object that is the same as the original serialized object. * #### shadow A new declaration of a local variable _shadows_ one of the same name in an enclosing scope. diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index 89595bf4c5..44fb12f398 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -82,7 +82,7 @@ fatal. opinionated sbt plugin that sets many options automatically, depending on Scala version; you can see [here](https://github.com/DavidGregory084/sbt-tpolecat/blob/master/src/main/scala/io/github/davidgregory084/TpolecatPlugin.scala) -what it sets. Some of the choices it makes are oriented towards +what it sets. Some choices it makes are oriented towards pure-functional programmers. ### How do I find what some symbol means or does? @@ -205,7 +205,7 @@ So for example, a `List[Int]` in Scala code will appear to Java as a appear as type parameters, but couldn't they appear as their boxed equivalents, such as `List[java.lang.Integer]`? -One would hope so, but doing it that way was tried and it proved impossible. +One would hope so, but doing it that way was tried, and it proved impossible. [This SO question](https://stackoverflow.com/questions/11167430/why-are-primitive-types-such-as-int-erased-to-object-in-scala) sadly lacks a concise explanation, but it does link to past discussions. diff --git a/_overviews/FAQ/initialization-order.md b/_overviews/FAQ/initialization-order.md index ece62c6b9f..787281f0db 100644 --- a/_overviews/FAQ/initialization-order.md +++ b/_overviews/FAQ/initialization-order.md @@ -94,7 +94,7 @@ Usually the best answer. Unfortunately you cannot declare an abstract lazy val. 2. Declare an abstract def, and hope subclasses will implement it as a lazy val. If they do not, it will be re-evaluated on every access. 3. Declare a concrete lazy val which throws an exception, and hope subclasses override it. If they do not, it will... throw an exception. -An exception during initialization of a lazy val will cause the right hand side to be re-evaluated on the next access: see SLS 5.2. +An exception during initialization of a lazy val will cause the right-hand side to be re-evaluated on the next access: see SLS 5.2. Note that using multiple lazy vals creates a new risk: cycles among lazy vals can result in a stack overflow on first access. diff --git a/_overviews/collections-2.13/arrays.md b/_overviews/collections-2.13/arrays.md index 64d96a95db..b06b4c9361 100644 --- a/_overviews/collections-2.13/arrays.md +++ b/_overviews/collections-2.13/arrays.md @@ -59,9 +59,9 @@ The `ArrayOps` object gets inserted automatically by the implicit conversion. So scala> intArrayOps(a1).reverse res5: Array[Int] = Array(3, 2, 1) -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 `ArraySeq` 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 `ArraySeq` conversion. The first is defined in the `Predef` object whereas the second is defined in a class `scala.LowPriorityImplicits`, which is inherited by `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. +where `intArrayOps` is the implicit conversion that was inserted previously. This raises the question of how the compiler picked `intArrayOps` over the other implicit conversion to `ArraySeq` 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 `ArraySeq` conversion. The first is defined in the `Predef` object whereas the second is defined in a class `scala.LowPriorityImplicits`, which is inherited by `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 to 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 of help from you. To illustrate the issue, consider the following attempt to write a generic method that creates an array. // this is wrong! def evenElems[T](xs: Vector[T]): Array[T] = { @@ -71,7 +71,7 @@ So now you know how arrays can be compatible with sequences and how they can sup arr } -The `evenElems` method returns a new array that consist of all elements of the argument vector `xs` which are at even positions in the vector. The first line of the body of `evenElems` creates the result array, which has the same element type as the argument. So depending on the actual type parameter for `T`, this could be an `Array[Int]`, or an `Array[Boolean]`, or an array of some of the other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter `T` is erased at runtime. That's why you will get the following error message if you compile the code above: +The `evenElems` method returns a new array that consist of all elements of the argument vector `xs` which are at even positions in the vector. The first line of the body of `evenElems` creates the result array, which has the same element type as the argument. So depending on the actual type parameter for `T`, this could be an `Array[Int]`, or an `Array[Boolean]`, or an array of some other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter `T` is erased at runtime. That's why you will get the following error message if you compile the code above: error: cannot find class manifest for element type T val arr = new Array[T]((arr.length + 1) / 2) diff --git a/_overviews/collections-2.13/concrete-immutable-collection-classes.md b/_overviews/collections-2.13/concrete-immutable-collection-classes.md index 152605d760..24f1b70648 100644 --- a/_overviews/collections-2.13/concrete-immutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-immutable-collection-classes.md @@ -84,7 +84,7 @@ the original array’s elements. ## Vectors We have seen in the previous sections that `List` and `ArraySeq` are efficient data structures in some specific -use cases but they are also inefficient in other use cases: for instance, prepending an element is constant for `List`, +use cases, but they are also inefficient in other use cases: for instance, prepending an element is constant for `List`, but linear for `ArraySeq`, and, conversely, indexed access is constant for `ArraySeq` but linear for `List`. [Vector](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html) is a collection type that provides good performance for all its operations. Vectors allow accessing any element of the sequence in "effectively" constant time. It's a larger constant than for access to the head of a List or for reading an element of an ArraySeq, but it's a constant nonetheless. As a result, algorithms using vectors do not have to be careful about accessing just the head of the sequence. They can access and modify elements at arbitrary locations, and thus they can be much more convenient to write. diff --git a/_overviews/collections-2.13/concrete-mutable-collection-classes.md b/_overviews/collections-2.13/concrete-mutable-collection-classes.md index ddc5daf609..e0d9c5fb19 100644 --- a/_overviews/collections-2.13/concrete-mutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-mutable-collection-classes.md @@ -107,7 +107,7 @@ It is supported by class [mutable.Stack](https://www.scala-lang.org/api/{{ site. Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArraySeq.html). -You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({% link _overviews/collections-2.13/arrays.md %}). +You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements, and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({% link _overviews/collections-2.13/arrays.md %}). ## Hash Tables diff --git a/_overviews/collections-2.13/creating-collections-from-scratch.md b/_overviews/collections-2.13/creating-collections-from-scratch.md index 729b3008f9..660830dd99 100644 --- a/_overviews/collections-2.13/creating-collections-from-scratch.md +++ b/_overviews/collections-2.13/creating-collections-from-scratch.md @@ -41,7 +41,7 @@ Besides `apply`, every collection companion object also defines a member `empty` The operations provided by collection companion objects are summarized in the following table. In short, there's * `concat`, which concatenates an arbitrary number of collections together, -* `fill` and `tabulate`, which generate single or multi-dimensional collections of given dimensions initialized by some expression or tabulating function, +* `fill` and `tabulate`, which generate single or multidimensional collections of given dimensions initialized by some expression or tabulating function, * `range`, which generates integer collections with some constant step length, and * `iterate` and `unfold`, which generates the collection resulting from repeated application of a function to a start element or state. diff --git a/_overviews/collections-2.13/equality.md b/_overviews/collections-2.13/equality.md index 3ce85f4815..3f6d249f83 100644 --- a/_overviews/collections-2.13/equality.md +++ b/_overviews/collections-2.13/equality.md @@ -14,7 +14,7 @@ permalink: /overviews/collections-2.13/:title.html The collection libraries have a uniform approach to equality and hashing. The idea is, first, to divide collections into sets, maps, and sequences. Collections in different categories are always unequal. For instance, `Set(1, 2, 3)` is unequal to `List(1, 2, 3)` even though they contain the same elements. On the other hand, within the same category, collections are equal if and only if they have the same elements (for sequences: the same elements in the same order). For example, `List(1, 2, 3) == Vector(1, 2, 3)`, and `HashSet(1, 2) == TreeSet(2, 1)`. -It does not matter for the equality check whether a collection is mutable or immutable. For a mutable collection one simply considers its current elements at the time the equality test is performed. This means that a mutable collection might be equal to different collections at different times, depending what elements are added or removed. This is a potential trap when using a mutable collection as a key in a hashmap. Example: +It does not matter for the equality check whether a collection is mutable or immutable. For a mutable collection one simply considers its current elements at the time the equality test is performed. This means that a mutable collection might be equal to different collections at different times, depending on what elements are added or removed. This is a potential trap when using a mutable collection as a key in a hashmap. Example: scala> import collection.mutable.{HashMap, ArrayBuffer} import collection.mutable.{HashMap, ArrayBuffer} diff --git a/_overviews/collections-2.13/introduction.md b/_overviews/collections-2.13/introduction.md index 477f8ffb10..7341e31ff5 100644 --- a/_overviews/collections-2.13/introduction.md +++ b/_overviews/collections-2.13/introduction.md @@ -48,7 +48,7 @@ lines run at first try. **Fast:** Collection operations are tuned and optimized in the libraries. As a result, using collections is typically quite -efficient. You might be able to do a little bit better with carefully +efficient. You might be able to do a little better with carefully hand-tuned data structures and operations, but you might also do a lot worse by making some suboptimal implementation decisions along the way. diff --git a/_overviews/collections-2.13/iterators.md b/_overviews/collections-2.13/iterators.md index 0f88475625..7af6bc9d0c 100644 --- a/_overviews/collections-2.13/iterators.md +++ b/_overviews/collections-2.13/iterators.md @@ -170,7 +170,7 @@ A lazy operation does not immediately compute all of its results. Instead, it co So the expression `(1 to 10).iterator.map(println)` would not print anything to the screen. The `map` method in this case doesn't apply its argument function to the values in the range, it returns a new `Iterator` that will do this as each one is requested. Adding `.toList` to the end of that expression will actually print the elements. -A consequence of this is that a method like `map` or `filter` won't necessarily apply its argument function to all of the input elements. The expression `(1 to 10).iterator.map(println).take(5).toList` would only print the values `1` to `5`, for instance, since those are only ones that will be requested from the `Iterator` returned by `map`. +A consequence of this is that a method like `map` or `filter` won't necessarily apply its argument function to all the input elements. The expression `(1 to 10).iterator.map(println).take(5).toList` would only print the values `1` to `5`, for instance, since those are only ones that will be requested from the `Iterator` returned by `map`. This is one of the reasons why it's important to only use pure functions as arguments to `map`, `filter`, `fold` and similar methods. Remember, a pure function has no side-effects, so one would not normally use `println` in a `map`. `println` is used to demonstrate laziness as it's not normally visible with pure functions. diff --git a/_overviews/collections-2.13/trait-iterable.md b/_overviews/collections-2.13/trait-iterable.md index bd219ec746..4e67903189 100644 --- a/_overviews/collections-2.13/trait-iterable.md +++ b/_overviews/collections-2.13/trait-iterable.md @@ -144,6 +144,6 @@ Two more methods exist in `Iterable` that return iterators: `grouped` and `slidi In the inheritance hierarchy below `Iterable` you find three traits: [Seq](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [SetOps](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/SetOps.html). -For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. +For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally, for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. In the following, we will explain each of the three kinds of collections in more detail. diff --git a/_overviews/collections-2.13/views.md b/_overviews/collections-2.13/views.md index 0b0e3f2c1e..dbaad18128 100644 --- a/_overviews/collections-2.13/views.md +++ b/_overviews/collections-2.13/views.md @@ -87,7 +87,7 @@ The main reason for using views is performance. You have seen that by switching def isPalindrome(x: String) = x == x.reverse def findPalindrome(s: Seq[String]) = s find isPalindrome -Now, assume you have a very long sequence words and you want to find a palindrome in the first million words of that sequence. Can you re-use the definition of `findPalindrome`? Of course, you could write: +Now, assume you have a very long sequence words, and you want to find a palindrome in the first million words of that sequence. Can you re-use the definition of `findPalindrome`? Of course, you could write: findPalindrome(words take 1000000) diff --git a/_overviews/collections/arrays.md b/_overviews/collections/arrays.md index 019ac91248..637806b014 100644 --- a/_overviews/collections/arrays.md +++ b/_overviews/collections/arrays.md @@ -24,7 +24,7 @@ permalink: /overviews/collections/:title.html Given that Scala arrays are represented just like Java arrays, how can these additional features be supported in Scala? In fact, the answer to this question differs between Scala 2.8 and earlier versions. Previously, the Scala compiler somewhat "magically" wrapped and unwrapped arrays to and from `Seq` objects when required in a process called boxing and unboxing. The details of this were quite complicated, in particular when one created a new array of generic type `Array[T]`. There were some puzzling corner cases and the performance of array operations was not all that predictable. -The Scala 2.8 design is much simpler. Almost all compiler magic is gone. Instead the Scala 2.8 array implementation makes systematic use of implicit conversions. In Scala 2.8 an array does not pretend to _be_ a sequence. It can't really be that because the data type representation of a native array is not a subtype of `Seq`. Instead there is an implicit "wrapping" conversion between arrays and instances of class `scala.collection.mutable.WrappedArray`, which is a subclass of `Seq`. Here you see it in action: +The Scala 2.8 design is much simpler. Almost all compiler magic is gone. Instead, the Scala 2.8 array implementation makes systematic use of implicit conversions. In Scala 2.8 an array does not pretend to _be_ a sequence. It can't really be that because the data type representation of a native array is not a subtype of `Seq`. Instead, there is an implicit "wrapping" conversion between arrays and instances of class `scala.collection.mutable.WrappedArray`, which is a subclass of `Seq`. Here you see it in action: scala> val seq: Seq[Int] = a1 seq: Seq[Int] = WrappedArray(1, 2, 3) @@ -60,9 +60,9 @@ The `ArrayOps` object gets inserted automatically by the implicit conversion. So scala> intArrayOps(a1).reverse res5: Array[Int] = Array(3, 2, 1) -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 by `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. +where `intArrayOps` is the implicit conversion that was inserted previously. This raises the question of 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 by `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 to 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 of help from you. To illustrate the issue, consider the following attempt to write a generic method that creates an array. // this is wrong! def evenElems[T](xs: Vector[T]): Array[T] = { @@ -72,7 +72,7 @@ So now you know how arrays can be compatible with sequences and how they can sup arr } -The `evenElems` method returns a new array that consist of all elements of the argument vector `xs` which are at even positions in the vector. The first line of the body of `evenElems` creates the result array, which has the same element type as the argument. So depending on the actual type parameter for `T`, this could be an `Array[Int]`, or an `Array[Boolean]`, or an array of some of the other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter `T` is erased at runtime. That's why you will get the following error message if you compile the code above: +The `evenElems` method returns a new array that consist of all elements of the argument vector `xs` which are at even positions in the vector. The first line of the body of `evenElems` creates the result array, which has the same element type as the argument. So depending on the actual type parameter for `T`, this could be an `Array[Int]`, or an `Array[Boolean]`, or an array of some other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter `T` is erased at runtime. That's why you will get the following error message if you compile the code above: error: cannot find class manifest for element type T val arr = new Array[T]((arr.length + 1) / 2) diff --git a/_overviews/collections/concrete-immutable-collection-classes.md b/_overviews/collections/concrete-immutable-collection-classes.md index 95a76570d1..6324128e48 100644 --- a/_overviews/collections/concrete-immutable-collection-classes.md +++ b/_overviews/collections/concrete-immutable-collection-classes.md @@ -19,7 +19,7 @@ A [List](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/colle Lists have always been the workhorse for Scala programming, so not much needs to be said about them here. The major change in 2.8 is that the `List` class together with its subclass `::` and its subobject `Nil` is now defined in package `scala.collection.immutable`, where it logically belongs. There are still aliases for `List`, `Nil`, and `::` in the `scala` package, so from a user perspective, lists can be accessed as before. -Another change is that lists now integrate more closely into the collections framework, and are less of a special case than before. For instance all of the numerous methods that originally lived in the `List` companion object have been deprecated. They are replaced by the [uniform creation methods]({{ site.baseurl }}/overviews/collections/creating-collections-from-scratch.html) inherited by every collection. +Another change is that lists now integrate more closely into the collections framework, and are less of a special case than before. For instance all the numerous methods that originally lived in the `List` companion object have been deprecated. They are replaced by the [uniform creation methods]({{ site.baseurl }}/overviews/collections/creating-collections-from-scratch.html) inherited by every collection. ## Streams diff --git a/_overviews/collections/concrete-mutable-collection-classes.md b/_overviews/collections/concrete-mutable-collection-classes.md index bc7bf02567..108b531c9a 100644 --- a/_overviews/collections/concrete-mutable-collection-classes.md +++ b/_overviews/collections/concrete-mutable-collection-classes.md @@ -54,7 +54,7 @@ Just like an array buffer is useful for building arrays, and a list buffer is us ## Linked Lists -Linked lists are mutable sequences that consist of nodes which are linked with next pointers. They are supported by class [LinkedList](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/LinkedList.html). In most languages `null` would be picked as the empty linked list. That does not work for Scala collections, because even empty sequences must support all sequence methods. In particular `LinkedList.empty.isEmpty` should return `true` and not throw a `NullPointerException`. Empty linked lists are encoded instead in a special way: Their `next` field points back to the node itself. Like their immutable cousins, linked lists are best traversed sequentially. In addition linked lists make it easy to insert an element or linked list into another linked list. +Linked lists are mutable sequences that consist of nodes which are linked with next pointers. They are supported by class [LinkedList](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/LinkedList.html). In most languages `null` would be picked as the empty linked list. That does not work for Scala collections, because even empty sequences must support all sequence methods. In particular `LinkedList.empty.isEmpty` should return `true` and not throw a `NullPointerException`. Empty linked lists are encoded instead in a special way: Their `next` field points back to the node itself. Like their immutable cousins, linked lists are best traversed sequentially. In addition, linked lists make it easy to insert an element or linked list into another linked list. ## Double Linked Lists @@ -85,7 +85,7 @@ Scala provides mutable queues in addition to immutable ones. You use a `mQueue` Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArraySeq.html). -You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({{ site.baseurl }}/overviews/collections/arrays.html). +You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements, and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({{ site.baseurl }}/overviews/collections/arrays.html). ## Stacks diff --git a/_overviews/collections/creating-collections-from-scratch.md b/_overviews/collections/creating-collections-from-scratch.md index a7c1a7ff5b..2468bf9e27 100644 --- a/_overviews/collections/creating-collections-from-scratch.md +++ b/_overviews/collections/creating-collections-from-scratch.md @@ -40,7 +40,7 @@ Besides `apply`, every collection companion object also defines a member `empty` Descendants of `Seq` classes provide also other factory operations in their companion objects. These are summarized in the following table. In short, there's * `concat`, which concatenates an arbitrary number of traversables together, -* `fill` and `tabulate`, which generate single or multi-dimensional sequences of given dimensions initialized by some expression or tabulating function, +* `fill` and `tabulate`, which generate single or multidimensional sequences of given dimensions initialized by some expression or tabulating function, * `range`, which generates integer sequences with some constant step length, and * `iterate`, which generates the sequence resulting from repeated application of a function to a start element. diff --git a/_overviews/collections/equality.md b/_overviews/collections/equality.md index c949d7aac5..bb9abc6f06 100644 --- a/_overviews/collections/equality.md +++ b/_overviews/collections/equality.md @@ -13,7 +13,7 @@ permalink: /overviews/collections/:title.html The collection libraries have a uniform approach to equality and hashing. The idea is, first, to divide collections into sets, maps, and sequences. Collections in different categories are always unequal. For instance, `Set(1, 2, 3)` is unequal to `List(1, 2, 3)` even though they contain the same elements. On the other hand, within the same category, collections are equal if and only if they have the same elements (for sequences: the same elements in the same order). For example, `List(1, 2, 3) == Vector(1, 2, 3)`, and `HashSet(1, 2) == TreeSet(2, 1)`. -It does not matter for the equality check whether a collection is mutable or immutable. For a mutable collection one simply considers its current elements at the time the equality test is performed. This means that a mutable collection might be equal to different collections at different times, depending what elements are added or removed. This is a potential trap when using a mutable collection as a key in a hashmap. Example: +It does not matter for the equality check whether a collection is mutable or immutable. For a mutable collection one simply considers its current elements at the time the equality test is performed. This means that a mutable collection might be equal to different collections at different times, depending on what elements are added or removed. This is a potential trap when using a mutable collection as a key in a hashmap. Example: scala> import collection.mutable.{HashMap, ArrayBuffer} import collection.mutable.{HashMap, ArrayBuffer} diff --git a/_overviews/collections/introduction.md b/_overviews/collections/introduction.md index d61806d127..5fc2e3f301 100644 --- a/_overviews/collections/introduction.md +++ b/_overviews/collections/introduction.md @@ -55,7 +55,7 @@ lines run at first try. **Fast:** Collection operations are tuned and optimized in the libraries. As a result, using collections is typically quite -efficient. You might be able to do a little bit better with carefully +efficient. You might be able to do a little better with carefully hand-tuned data structures and operations, but you might also do a lot worse by making some suboptimal implementation decisions along the way. What's more, collections have been recently adapted to parallel diff --git a/_overviews/collections/iterators.md b/_overviews/collections/iterators.md index f08e65d5a3..78dfcc69f0 100644 --- a/_overviews/collections/iterators.md +++ b/_overviews/collections/iterators.md @@ -26,7 +26,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 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 or 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: @@ -166,7 +166,7 @@ A lazy operation does not immediately compute all of its results. Instead, it co So the expression `(1 to 10).iterator.map(println)` would not print anything to the screen. The `map` method in this case doesn't apply its argument function to the values in the range, it returns a new `Iterator` that will do this as each one is requested. Adding `.toList` to the end of that expression will actually print the elements. -A consequence of this is that a method like `map` or `filter` won't necessarily apply its argument function to all of the input elements. The expression `(1 to 10).iterator.map(println).take(5).toList` would only print the values `1` to `5`, for instance, since those are only ones that will be requested from the `Iterator` returned by `map`. +A consequence of this is that a method like `map` or `filter` won't necessarily apply its argument function to all the input elements. The expression `(1 to 10).iterator.map(println).take(5).toList` would only print the values `1` to `5`, for instance, since those are only ones that will be requested from the `Iterator` returned by `map`. This is one of the reasons why it's important to only use pure functions as arguments to `map`, `filter`, `fold` and similar methods. Remember, a pure function has no side-effects, so one would not normally use `println` in a `map`. `println` is used to demonstrate laziness as it's not normally visible with pure functions. diff --git a/_overviews/collections/migrating-from-scala-27.md b/_overviews/collections/migrating-from-scala-27.md index d621c78899..5e1efc7822 100644 --- a/_overviews/collections/migrating-from-scala-27.md +++ b/_overviews/collections/migrating-from-scala-27.md @@ -12,7 +12,7 @@ permalink: /overviews/collections/:title.html 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 be 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 @@ -38,7 +38,7 @@ Generally, the old functionality of Scala 2.7 collections has been left in place There are two parts of the old libraries which have been replaced wholesale, and for which deprecation warnings were not feasible. -1. The previous `scala.collection.jcl` package is gone. This package tried to mimick some of the Java collection library design in Scala, but in doing so broke many symmetries. Most people who wanted Java collections bypassed `jcl` and used `java.util` directly. Scala 2.8 offers automatic conversion mechanisms between both collection libraries in the [JavaConversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html) object which replaces the `jcl` package. +1. The previous `scala.collection.jcl` package is gone. This package tried to mimic aspects of the Java collection library design in Scala, but in doing so broke many symmetries. Most people who wanted Java collections bypassed `jcl` and used `java.util` directly. Scala 2.8 offers automatic conversion mechanisms between both collection libraries in the [JavaConversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html) object which replaces the `jcl` package. 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/trait-iterable.md b/_overviews/collections/trait-iterable.md index abc8051703..ac72783f41 100644 --- a/_overviews/collections/trait-iterable.md +++ b/_overviews/collections/trait-iterable.md @@ -62,6 +62,6 @@ Trait `Iterable` also adds some other methods to `Traversable` that can be imple In the inheritance hierarchy below Iterable you find three traits: [Seq](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [GenSetLike](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/GenSetLike.html). -For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. +For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally, for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. In the following, we will explain each of the three kinds of collections in more detail. diff --git a/_overviews/collections/trait-traversable.md b/_overviews/collections/trait-traversable.md index 11aaa6b349..d2173cb789 100644 --- a/_overviews/collections/trait-traversable.md +++ b/_overviews/collections/trait-traversable.md @@ -25,7 +25,7 @@ The `foreach` method is meant to traverse all elements of the collection, and ap * **Conversions** `toArray`, `toList`, `toIterable`, `toSeq`, `toIndexedSeq`, `toStream`, `toSet`, `toMap`, which turn a `Traversable` collection into something more specific. All these conversions return their receiver argument unchanged if the run-time type of the collection already matches the demanded collection type. For instance, applying `toList` to a list will yield the list itself. * **Copying operations** `copyToBuffer` and `copyToArray`. As their names imply, these copy collection elements to a buffer or array, respectively. * **Size info** operations `isEmpty`, `nonEmpty`, `size`, and `hasDefiniteSize`: Traversable collections can be finite or infinite. An example of an infinite traversable collection is the stream of natural numbers `Stream.from(0)`. The method `hasDefiniteSize` indicates whether a collection is possibly infinite. If `hasDefiniteSize` returns true, the collection is certainly finite. If it returns false, the collection has not been fully elaborated yet, so it might be infinite or finite. -* **Element retrieval** operations `head`, `last`, `headOption`, `lastOption`, and `find`. These select the first or last element of a collection, or else the first element matching a condition. Note, however, that not all collections have a well-defined meaning of what "first" and "last" means. For instance, a hash set might store elements according to their hash keys, which might change from run to run. In that case, the "first" element of a hash set could also be different for every run of a program. A collection is _ordered_ if it always yields its elements in the same order. Most collections are ordered, but some (_e.g._ hash sets) are not-- dropping the ordering gives a little bit of extra efficiency. Ordering is often essential to give reproducible tests and to help in debugging. That's why Scala collections give ordered alternatives for all collection types. For instance, the ordered alternative for `HashSet` is `LinkedHashSet`. +* **Element retrieval** operations `head`, `last`, `headOption`, `lastOption`, and `find`. These select the first or last element of a collection, or else the first element matching a condition. Note, however, that not all collections have a well-defined meaning of what "first" and "last" means. For instance, a hash set might store elements according to their hash keys, which might change from run to run. In that case, the "first" element of a hash set could also be different for every run of a program. A collection is _ordered_ if it always yields its elements in the same order. Most collections are ordered, but some (_e.g._ hash sets) are not-- dropping the ordering gives a little extra efficiency. Ordering is often essential to give reproducible tests and to help in debugging. That's why Scala collections give ordered alternatives for all collection types. For instance, the ordered alternative for `HashSet` is `LinkedHashSet`. * **Sub-collection retrieval operations** `tail`, `init`, `slice`, `take`, `drop`, `takeWhile`, `dropWhile`, `filter`, `filterNot`, `withFilter`. These all return some sub-collection identified by an index range or some predicate. * **Subdivision operations** `splitAt`, `span`, `partition`, `groupBy`, which split the elements of this collection into several sub-collections. * **Element tests** `exists`, `forall`, `count` which test collection elements with a given predicate. diff --git a/_overviews/collections/views.md b/_overviews/collections/views.md index dd3c128657..1798d77cf4 100644 --- a/_overviews/collections/views.md +++ b/_overviews/collections/views.md @@ -73,7 +73,7 @@ There are two reasons why you might want to consider using views. The first is p def isPalindrome(x: String) = x == x.reverse def findPalindrome(s: Seq[String]) = s find isPalindrome -Now, assume you have a very long sequence words and you want to find a palindrome in the first million words of that sequence. Can you re-use the definition of `findPalindrome`? Of course, you could write: +Now, assume you have a very long sequence of words, and you want to find a palindrome in the first million words of that sequence. Can you re-use the definition of `findPalindrome`? Of course, you could write: findPalindrome(words take 1000000) diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md index 5d4f6622e2..f52764736e 100644 --- a/_overviews/contribute/add-guides.md +++ b/_overviews/contribute/add-guides.md @@ -12,7 +12,7 @@ involved with complex tools like the compiler. ## Architecture -This documentation website is backed by an open-source [github repository](https://github.com/scala/docs.scala-lang), +This documentation website is backed by an open-source [GitHub repository](https://github.com/scala/docs.scala-lang), and is always contribution-ready. ### Content @@ -34,10 +34,10 @@ The website is statically generated from [Markdown](https://en.wikipedia.org/wik This workflow was chosen to help contributors to focus on writing helpful content, rather than on configuration and boilerplate. It also aids publishing a static site in a central location. -The markdown syntax being used supports [Maruku](https://github.com/bhollis/maruku) extensions, and has automatic +The Markdown syntax being used supports [Maruku](https://github.com/bhollis/maruku) extensions, and has automatic syntax highlighting, without the need for any tags. -Additionally [mdoc](https://github.com/scalameta/mdoc) is used during pull requests to validate Scala code blocks. +Additionally, [mdoc](https://github.com/scalameta/mdoc) is used during pull requests to validate Scala code blocks. To use this feature you must use the backtick notation as documented by mdoc, [see here](#code-blocks) for an example. @@ -271,7 +271,7 @@ the metadata of `/tutorials.md`. e.g. it could look like icon: code --- -You must also add the tutorial to the drop down list in the navigation bar. To do this, add an extra entry to +You must also add the tutorial to the drop-down list in the navigation bar. To do this, add an extra entry to `_data/doc-nav-header.yml`. i.e. --- @@ -290,7 +290,7 @@ You must also add the tutorial to the drop down list in the navigation bar. To d ### Cheatsheets -Cheatsheets have a special layout, and the content is expected to be a markdown table. To contribute a cheatsheet, +Cheatsheets have a special layout, and the content is expected to be a Markdown table. To contribute a cheatsheet, you should use the following format: --- diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index 6830c18ab9..41f349016e 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -34,7 +34,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 1. Gradually remove parts from the original failing code snippet until you believe you have the simplest representation of your problem. - 2. Ensure that you have decoupled your code snippet from any library that could be introducing the incorrect behavior. One way to achieve this is to try to recompile the offending code snippet in isolation, outside of the context of any complex build environment. If your code depends on some strictly Java library and source code is available for it, make sure that the latter is also minimized. + 2. Ensure that you have decoupled your code snippet from any library that could be introducing the incorrect behavior. One way to achieve this is to try to recompile the offending code snippet in isolation, outside the context of any complex build environment. If your code depends on some strictly Java library and source code is available for it, make sure that the latter is also minimized. 3. Make sure you are compiling your project from a clean slate. Your problem could be related to separate compilation, which is difficult to detect without a clean build with new `.class` files. @@ -42,7 +42,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents][sips] or in the [Scala Language Specification](https://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether the language behavior is intended is either in the [Scala Improvement Proposal Documents][sips] or in the [Scala Language Specification](https://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). In general, if you find yourself stuck on any of these steps, asking on [Scala Contributors](https://contributors.scala-lang.org/) can be helpful: diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index be8e66ba46..c4c44c9981 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -19,7 +19,7 @@ own pull requests. * Attach comments to particular lines or regions they pertain to whenever possible. * Short code examples are often more descriptive than prose. * If you have thoroughly reviewed the PR and thought through all angles, LGTM (Looks Good To Me) is the preferred acceptance response. -* Additional reviews should try to offer additional insights: "I also thought about it from this angle and it still looks good.." +* Additional reviews should try to offer additional insights: "I also thought about it from this angle, and it still looks good.." * Above all, remember that the people you are reviewing might be reviewing your PRs one day too. * If you are receiving the review, consider that the advice is being given to make you, and Scala, better rather than as a negative critique. Assume the best, rather than the worst. @@ -39,7 +39,7 @@ own pull requests.
NEW Thread safety issues have been fixed in Scala 2.11.0-RC1, but we are going to keep this document available for now, since the problem still remains in the Scala 2.10.x series, and we currently don't have concrete plans on when the fix is going to be backported.
-Currently we know about two kinds of races associated with reflection. First of all, reflection initialization (the code that is called +Currently, we know about two kinds of races associated with reflection. First of all, reflection initialization (the code that is called when `scala.reflect.runtime.universe` is accessed for the first time) cannot be safely called from multiple threads. Secondly, symbol initialization (the code that is called when symbol's flags or type signature are accessed for the first time) isn't safe as well. Here's a typical manifestation: diff --git a/_overviews/repl/overview.md b/_overviews/repl/overview.md index 38d5008dd6..c462643399 100644 --- a/_overviews/repl/overview.md +++ b/_overviews/repl/overview.md @@ -79,4 +79,4 @@ Its facilities can be witnessed using `:imports` or `-Xprint:parser`. ### Contributing to Scala REPL The REPL source is part of the Scala project. Issues are tracked by the standard -mechanism for the project and pull requests are accepted at [the github repository](https://github.com/scala/scala). +mechanism for the project and pull requests are accepted at [the GitHub repository](https://github.com/scala/scala). diff --git a/_overviews/scala3-book/ca-given-using-clauses.md b/_overviews/scala3-book/ca-given-using-clauses.md index 704f83bd82..c47d14fc25 100644 --- a/_overviews/scala3-book/ca-given-using-clauses.md +++ b/_overviews/scala3-book/ca-given-using-clauses.md @@ -32,7 +32,7 @@ Let us assume that the configuration does not change throughout most of our code Passing `c` to each and every method call (like `renderWidget`) becomes very tedious and makes our program more difficult to read, since we need to ignore the `c` argument. #### Using `using` to mark parameters as contextual -In Scala 3, we can mark some of the parameters of our methods as _contextual_. +In Scala 3, we can mark some parameters of our methods as _contextual_. ```scala def renderWebsite(path: String)(using c: Config): String = "" + renderWidget(List("cart")) + "" @@ -65,7 +65,7 @@ Like we specified our parameter section with `using`, we can also explicitly pro ```scala renderWebsite("/home")(using config) ``` -Explicitly providing contextual parameters can be useful if we have multiple different values in scope that would make sense and we want to make sure that the correct one is passed to the function. +Explicitly providing contextual parameters can be useful if we have multiple different values in scope that would make sense, and we want to make sure that the correct one is passed to the function. For all other cases, as we will see in the next Section, there is also another way to bring contextual values into scope. diff --git a/_overviews/scala3-book/ca-multiversal-equality.md b/_overviews/scala3-book/ca-multiversal-equality.md index a106ed0856..215f2e2a7c 100644 --- a/_overviews/scala3-book/ca-multiversal-equality.md +++ b/_overviews/scala3-book/ca-multiversal-equality.md @@ -192,7 +192,7 @@ println(aBook == pBook) // true (works because of `equals` in `AudioBook`) println(pBook == aBook) // false ``` -Currently the `PrintedBook` book doesn’t have an `equals` method, so the second comparison returns `false`. +Currently, the `PrintedBook` book doesn’t have an `equals` method, so the second comparison returns `false`. To enable that comparison, just override the `equals` method in `PrintedBook`. You can find additional information on [multiversal equality][ref-equal] in the reference documentation. diff --git a/_overviews/scala3-book/collections-classes.md b/_overviews/scala3-book/collections-classes.md index e9b7adec45..f3dc1d03b4 100644 --- a/_overviews/scala3-book/collections-classes.md +++ b/_overviews/scala3-book/collections-classes.md @@ -55,7 +55,7 @@ And this figure shows all collections in package _scala.collection.mutable_: ![Mutable collection hierarchy][collections3] -Having seen that detailed view of all of the collections types, the following sections introduce some of the common types you’ll use on a regular basis. +Having seen that detailed view of all the collections types, the following sections introduce some common types you’ll use on a regular basis. {% comment %} NOTE: those images come from this page: https://docs.scala-lang.org/overviews/collections-2.13/overview.html @@ -150,7 +150,7 @@ val things: List[Any] = List(1, "two", 3.0) ### Adding elements to a List Because `List` is immutable, you can’t add new elements to it. -Instead you create a new list by prepending or appending elements to an existing `List`. +Instead, you create a new list by prepending or appending elements to an existing `List`. For instance, given this `List`: ```scala @@ -300,7 +300,7 @@ val people = Vector( ``` Because `Vector` is immutable, you can’t add new elements to it. -Instead you create a new sequence by appending or prepending elements to an existing `Vector`. +Instead, you create a new sequence by appending or prepending elements to an existing `Vector`. These examples show how to _append_ elements to a `Vector`: ```scala @@ -338,7 +338,7 @@ Ed ## ArrayBuffer Use `ArrayBuffer` when you need a general-purpose, mutable indexed sequence in your Scala applications. -It’s mutable so you can change its elements, and also resize it. +It’s mutable, so you can change its elements, and also resize it. Because it’s indexed, random access of elements is fast. ### Creating an ArrayBuffer @@ -453,7 +453,7 @@ val ak = states("AK") // ak: String = Alaska val al = states("AL") // al: String = Alabama ``` -In practice you’ll also use methods like `keys`, `keySet`, `keysIterator`, `for` loops, and higher-order functions like `map` to work with `Map` keys and values. +In practice, you’ll also use methods like `keys`, `keySet`, `keysIterator`, `for` loops, and higher-order functions like `map` to work with `Map` keys and values. ### Adding elements to a Map diff --git a/_overviews/scala3-book/collections-methods.md b/_overviews/scala3-book/collections-methods.md index 4316dea761..6d09f2f1bf 100644 --- a/_overviews/scala3-book/collections-methods.md +++ b/_overviews/scala3-book/collections-methods.md @@ -76,7 +76,7 @@ In those numbered examples: This much verbosity is _rarely_ required, and only needed in the most complex usages. 2. The compiler knows that `a` contains `Int`, so it’s not necessary to restate that here. 3. Parentheses aren’t needed when you have only one parameter, such as `i`. -4. When you have a single parameter and it appears only once in your anonymous function, you can replace the parameter with `_`. +4. When you have a single parameter, and it appears only once in your anonymous function, you can replace the parameter with `_`. The [Anonymous Function][lambdas] provides more details and examples of the rules related to shortening lambda expressions. @@ -245,7 +245,7 @@ Because of this you may want to use `headOption` instead of `head`, especially w emptyList.headOption // None ``` -As shown, it doesn’t throw an exception, it simply returns the type `Option` that has the value `None`. +As shown, it doesn't throw an exception, it simply returns the type `Option` that has the value `None`. You can learn more about this programming style in the [Functional Programming][fp-intro] chapter. @@ -270,7 +270,7 @@ Just like `head`, `tail` also works on strings: "bar".tail // "ar" ``` -`tail` throws an _java.lang.UnsupportedOperationException_ if the list is empty, so just like `head` and `headOption`, there’s also a `tailOption` method, which is preferred in functional programming. +`tail` throws a _java.lang.UnsupportedOperationException_ if the list is empty, so just like `head` and `headOption`, there’s also a `tailOption` method, which is preferred in functional programming. A list can also be matched, so you can write expressions like this: diff --git a/_overviews/scala3-book/concurrency.md b/_overviews/scala3-book/concurrency.md index bda65f21a9..3cbe50c4e0 100644 --- a/_overviews/scala3-book/concurrency.md +++ b/_overviews/scala3-book/concurrency.md @@ -8,7 +8,7 @@ next-page: scala-tools --- -When you want to write parallel and concurrent applications in Scala, you _can_ use the native Java `Thread`---but the Scala [Future](https://www.scala-lang.org/api/current/scala/concurrent/Future$.html) offers a more high level and idiomatic approach so it’s preferred, and covered in this chapter. +When you want to write parallel and concurrent applications in Scala, you _can_ use the native Java `Thread`---but the Scala [Future](https://www.scala-lang.org/api/current/scala/concurrent/Future$.html) offers a more high level and idiomatic approach, so it’s preferred, and covered in this chapter. @@ -48,7 +48,7 @@ val x = aShortRunningTask() println("Here") ``` -Conversely, if `aShortRunningTask` is created as a `Future`, the `println` statement is printed almost immediately because `aShortRunningTask` is spawned off on some other thread---it doesn’t block. +Conversely, if `aShortRunningTask` is created as a `Future`, the `println` statement is printed almost immediately because `aShortRunningTask` is spawned off on some other thread---it doesn't block. In this chapter you’ll see how to use futures, including how to run multiple futures in parallel and combine their results in a `for` expression. You’ll also see examples of methods that are used to handle the value in a future once it returns. @@ -83,7 +83,7 @@ def longRunningAlgorithm() = 42 ``` -That fancy algorithm returns the integer value `42` after a ten second delay. +That fancy algorithm returns the integer value `42` after a ten-second delay. Now call that algorithm by wrapping it into the `Future` constructor, and assigning the result to a variable: ```scala @@ -92,7 +92,7 @@ eventualInt: scala.concurrent.Future[Int] = Future(