From 836fa133b704ecff127dcf3eeca5f1c63c276ebe Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 10 Dec 2020 08:30:14 -0800 Subject: [PATCH 1/3] reboot the Scala FAQ gah, nobody has touched this thing in years. and, perhaps, because it's so neglected, nobody in our chat rooms and forums ever refers anyone here. let's do something about it. changes so far: * don't duplicate content from Stack Overflow; this is a worthy but IMO failed experiment * discourage long writeups; encourage links to answers elsewhere * add a few general questions at the top that I know to be especially frequently asked * drop the question about `breakOut`, it is not an FAQ these days this PR is just a start, much room for improvement remains, but IMO this is already mergeable --- _overviews/FAQ/breakout.md | 233 -------------- _overviews/FAQ/chaining-implicits.md | 109 ------- _overviews/FAQ/collections.md | 382 ----------------------- _overviews/FAQ/context-bounds.md | 103 ------ _overviews/FAQ/finding-implicits.md | 415 ------------------------- _overviews/FAQ/finding-symbols.md | 205 ------------ _overviews/FAQ/index.md | 80 ++++- _overviews/FAQ/stream-view-iterator.md | 45 --- _overviews/FAQ/yield.md | 179 ----------- 9 files changed, 77 insertions(+), 1674 deletions(-) delete mode 100644 _overviews/FAQ/breakout.md delete mode 100644 _overviews/FAQ/chaining-implicits.md delete mode 100644 _overviews/FAQ/collections.md delete mode 100644 _overviews/FAQ/context-bounds.md delete mode 100644 _overviews/FAQ/finding-implicits.md delete mode 100644 _overviews/FAQ/finding-symbols.md delete mode 100644 _overviews/FAQ/stream-view-iterator.md delete mode 100644 _overviews/FAQ/yield.md diff --git a/_overviews/FAQ/breakout.md b/_overviews/FAQ/breakout.md deleted file mode 100644 index dfb41380ab..0000000000 --- a/_overviews/FAQ/breakout.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -layout: multipage-overview -title: What is breakOut, and how does it work? -overview-name: FAQ -partof: FAQ - -num: 5 -permalink: /tutorials/FAQ/:title.html ---- -You might have encountered some code like the one below, and wonder what is -`breakOut`, and why is it being passed as parameter? - - import scala.collection.breakOut - val map : Map[Int,String] = List("London", "France").map(x => (x.length, x))(breakOut) - - -The answer is found on the definition of `map`: - - def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That - -Note that it has two parameters. The first is your function and the second is -an implicit. If you do not provide that implicit, Scala will choose the most -_specific_ one available. - -### About breakOut - -So, what's the purpose of `breakOut`? Consider the example given at the -beginning , You take a list of strings, transform each string into a tuple -`(Int, String)`, and then produce a `Map` out of it. The most obvious way to do -that would produce an intermediary `List[(Int, String)]` collection, and then -convert it. - -Given that `map` uses a `Builder` to produce the resulting collection, wouldn't -it be possible to skip the intermediary `List` and collect the results directly -into a `Map`? Evidently, yes, it is. To do so, however, we need to pass a -proper `CanBuildFrom` to `map`, and that is exactly what `breakOut` does. - -Let's look, then, at the definition of `breakOut`: - - def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) = - new CanBuildFrom[From, T, To] { - def apply(from: From) = b.apply() ; def apply() = b.apply() - } - -Note that `breakOut` is parameterized, and that it returns an instance of -`CanBuildFrom`. As it happens, the types `From`, `T` and `To` have already been -inferred, because we know that `map` is expecting `CanBuildFrom[List[String], -(Int, String), Map[Int, String]]`. Therefore: - - From = List[String] - T = (Int, String) - To = Map[Int, String] - -To conclude let's examine the implicit received by `breakOut` itself. It is of -type `CanBuildFrom[Nothing,T,To]`. We already know all these types, so we can -determine that we need an implicit of type -`CanBuildFrom[Nothing,(Int,String),Map[Int,String]]`. But is there such a -definition? - -Let's look at `CanBuildFrom`'s definition: - - trait CanBuildFrom[-From, -Elem, +To] - extends AnyRef - -So `CanBuildFrom` is contra-variant on its first type parameter. Because -`Nothing` is a bottom class (ie, it is a subclass of everything), that means -*any* class can be used in place of `Nothing`. - -Since such a builder exists, Scala can use it to produce the desired output. - -### About Builders - -A lot of methods from Scala's collections library consists of taking the -original collection, processing it somehow (in the case of `map`, transforming -each element), and storing the results in a new collection. - -To maximize code reuse, this storing of results is done through a _builder_ -(`scala.collection.mutable.Builder`), which basically supports two operations: -appending elements, and returning the resulting collection. The type of this -resulting collection will depend on the type of the builder. Thus, a `List` -builder will return a `List`, a `Map` builder will return a `Map`, and so on. -The implementation of the `map` method need not concern itself with the type of -the result: the builder takes care of it. - -On the other hand, that means that `map` needs to receive this builder somehow. -The problem faced when designing Scala 2.8 Collections was how to choose the -best builder possible. For example, if I were to write `Map('a' -> -1).map(_.swap)`, I'd like to get a `Map(1 -> 'a')` back. On the other hand, a -`Map('a' -> 1).map(_._1)` can't return a `Map` (it returns an `Iterable`). - -The magic of producing the best possible `Builder` from the known types of the -expression is performed through this `CanBuildFrom` implicit. - -### About CanBuildFrom - -To better explain what's going on, I'll give an example where the collection -being mapped is a `Map` instead of a `List`. I'll go back to `List` later. For -now, consider these two expressions: - - Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length) - Map(1 -> "one", 2 -> "two") map (_._2) - -The first returns a `Map` and the second returns an `Iterable`. The magic of -returning a fitting collection is the work of `CanBuildFrom`. Let's consider -the definition of `map` again to understand it. - -The method `map` is inherited from `TraversableLike`. It is parameterized on -`B` and `That`, and makes use of the type parameters `A` and `Repr`, which -parameterize the class. Let's see both definitions together: - -The class `TraversableLike` is defined as: - - trait TraversableLike[+A, +Repr] - extends HasNewBuilder[A, Repr] with AnyRef - - def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That - - -To understand where `A` and `Repr` come from, let's consider the definition of -`Map` itself: - - trait Map[A, +B] - extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]] - -Because `TraversableLike` is inherited by all traits which extend `Map`, `A` -and `Repr` could be inherited from any of them. The last one gets the -preference, though. So, following the definition of the immutable `Map` and all -the traits that connect it to `TraversableLike`, we have: - - trait Map[A, +B] - extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]] - - trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] - extends MapLike[A, B, This] - - trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] - extends PartialFunction[A, B] with IterableLike[(A, B), This] with Subtractable[A, This] - - trait IterableLike[+A, +Repr] - extends Equals with TraversableLike[A, Repr] - - trait TraversableLike[+A, +Repr] - extends HasNewBuilder[A, Repr] with AnyRef - -If you pass the type parameters of `Map[Int, String]` all the way down the -chain, we find that the types passed to `TraversableLike`, and, thus, used by -`map`, are: - - A = (Int,String) - Repr = Map[Int, String] - -Going back to the example, the first map is receiving a function of type -`((Int, String)) => (Int, Int)` and the second map is receiving a function of -type `((Int, String)) => String`. I use the double parenthesis to emphasize it is -a tuple being received, as that's the type of `A` as we saw. - -With that information, let's consider the other types. - - map Function.tupled(_ -> _.length): - B = (Int, Int) - - map (_._2): - B = String - -We can see that the type returned by the first `map` is `Map[Int,Int]`, and the -second is `Iterable[String]`. Looking at `map`'s definition, it is easy to see -that these are the values of `That`. But where do they come from? - -If we look inside the companion objects of the classes involved, we see some -implicit declarations providing them. On object `Map`: - - implicit def canBuildFrom [A, B] : CanBuildFrom[Map, (A, B), Map[A, B]] - -And on object `Iterable`, whose class is extended by `Map`: - - implicit def canBuildFrom [A] : CanBuildFrom[Iterable, A, Iterable[A]] - -These definitions provide factories for parameterized `CanBuildFrom`. - -Scala will choose the most specific implicit available. In the first case, it -was the first `CanBuildFrom`. In the second case, as the first did not match, -it chose the second `CanBuildFrom`. - -### Back to the first example - -Let's see the first example, `List`'s and `map`'s definition (again) to -see how the types are inferred: - - val map : Map[Int,String] = List("London", "France").map(x => (x.length, x))(breakOut) - - sealed abstract class List[+A] - extends LinearSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqLike[A, List[A]] - - trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] - extends SeqLike[A, Repr] - - trait SeqLike[+A, +Repr] - extends IterableLike[A, Repr] - - trait IterableLike[+A, +Repr] - extends Equals with TraversableLike[A, Repr] - - trait TraversableLike[+A, +Repr] - extends HasNewBuilder[A, Repr] with AnyRef - - def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That - -The type of `List("London", "France")` is `List[String]`, so the types `A` and -`Repr` defined on `TraversableLike` are: - - A = String - Repr = List[String] - -The type for `(x => (x.length, x))` is `(String) => (Int, String)`, so the type -of `B` is: - - B = (Int, String) - -The last unknown type, `That` is the type of the result of `map`, and we -already have that as well: - - val map : Map[Int,String] = - -So, - - That = Map[Int, String] - -That means `breakOut` must, necessarily, return a type or subtype of -`CanBuildFrom[List[String], (Int, String), Map[Int, String]]`. - -This answer was originally submitted in response to [this question on Stack Overflow][1]. - - [1]: https://stackoverflow.com/q/1715681/53013 diff --git a/_overviews/FAQ/chaining-implicits.md b/_overviews/FAQ/chaining-implicits.md deleted file mode 100644 index cf8f513174..0000000000 --- a/_overviews/FAQ/chaining-implicits.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -layout: multipage-overview -title: How can I chain/nest implicit conversions? -overview-name: FAQ -partof: FAQ - -num: 6 -permalink: /tutorials/FAQ/:title.html ---- - -The enrich-my-library pattern allows one to seemingly add a method to a class by -making available an implicit conversion from that class to one that implements -the method. - -Scala does not allow two such implicit conversions taking place, however, so -one cannot got from `A` to `C` using an implicit `A` to `B` and another -implicit `B` to `C`. Is there a way around this restriction? - -Scala has a restriction on automatic conversions to add a method, which is that -it won't apply more than one conversion in trying to find methods. For example: - - class A(val n: Int) - class B(val m: Int, val n: Int) - class C(val m: Int, val n: Int, val o: Int) { - def total = m + n + o - } - - import scala.language.implicitConversions - - // This demonstrates implicit conversion chaining restrictions - object T1 { // to make it easy to test on REPL - implicit def toA(n: Int): A = new A(n) - implicit def aToB(a: A): B = new B(a.n, a.n) - implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n) - - // won't work - println(5.total) - println(new A(5).total) - - // works - println(new B(5, 5).total) - println(new C(5, 5, 10).total) - } - -However, if an implicit definition requires an implicit parameter itself, Scala -_will_ look for additional implicit values for as long as needed. Continuing from -the last example: - - object T2 { - implicit def toA(n: Int): A = new A(n) - implicit def aToB[A1](a: A1)(implicit f: A1 => A): B = - new B(a.n, a.n) - implicit def bToC[B1](b: B1)(implicit f: B1 => B): C = - new C(b.m, b.n, b.m + b.n) - - // works - println(5.total) - println(new A(5).total) - println(new B(5, 5).total) - println(new C(5, 5, 10).total) - } - -_"Magic!"_, you might say. Not so. Here is how the compiler would translate each -one: - - object T1Translated { - implicit def toA(n: Int): A = new A(n) - implicit def aToB(a: A): B = new B(a.n, a.n) - implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n) - - // Scala won't do this - println(bToC(aToB(toA(5))).total) - println(bToC(aToB(new A(5))).total) - - // Just this - println(bToC(new B(5, 5)).total) - - // No implicits required - println(new C(5, 5, 10).total) - } - - object T2Translated { - implicit def toA(n: Int): A = new A(n) - implicit def aToB[A1](a: A1)(implicit f: A1 => A): B = - new B(a.n, a.n) - implicit def bToC[B1](b: B1)(implicit f: B1 => B): C = - new C(b.m, b.n, b.m + b.n) - - // Scala does this - println(bToC(5)(x => aToB(x)(y => toA(y))).total) - println(bToC(new A(5))(x => aToB(x)(identity)).total) - println(bToC(new B(5, 5))(identity).total) - - // no implicits required - println(new C(5, 5, 10).total) - } - -So, while `bToC` is being used as an implicit conversion, `aToB` and `toA` are -being passed as _implicit parameters_, instead of being chained as implicit -conversions. - -See also: - -* [Context bounds](context-bounds.html) -* [A discussion on types, origin and precedence of implicits](finding-implicits.html) - -This question and answer were originally submitted on [Stack Overflow][1]. - - [1]: https://stackoverflow.com/questions/5332801/how-can-i-chain-implicits-in-scala/5332804 diff --git a/_overviews/FAQ/collections.md b/_overviews/FAQ/collections.md deleted file mode 100644 index 6c0ad3355d..0000000000 --- a/_overviews/FAQ/collections.md +++ /dev/null @@ -1,382 +0,0 @@ ---- -layout: multipage-overview -title: How are the collections structured? Which one should I choose? -overview-name: FAQ -partof: FAQ - -num: 8 -permalink: /tutorials/FAQ/:title.html ---- -## Foreword - -There's a [2.8 collection walk-through][1] by Martin Odersky which should -probably be your first reference. It has been supplemented as well with -[architectural notes][2], which will be of particular interest to those who -want to design their own collections. - -The rest of this answer was written way before any such thing existed (in fact, -before 2.8.0 itself was released). - -You can find a paper about it as [Scala SID #3][3]. Other papers in that area -should be interesting as well to people interested in the differences between -Scala 2.7 and 2.8. - -I'll quote from the paper, selectively, and complement with some thoughts of -mine. There are also some images, generated by Matthias at decodified.com, and -the original SVG files can be found [here][4]. - -## The collection classes/traits themselves - -There are actually three hierarchies of traits for the collections: one for -mutable collections, one for immutable collections, and one which doesn't make -any assumptions about the collections. - -There's also a distinction between parallel, serial and maybe-parallel -collections, which was introduced with Scala 2.9. I'll talk about them in the -next section. The hierarchy described in this section refers _exclusively to -non-parallel collections_. - -The following image shows the non-specific hierarchy as of Scala 2.10: - -[![General collection hierarchy][5]][5] - -All elements shown are traits. In the other two hierarchies there are also -classes directly inheriting the traits as well as classes which can be _viewed -as_ belonging in that hierarchy through implicit conversion to wrapper classes. -The legend for these graphs can be found after them. - -Graph for immutable hierarchy: - -[![Immutable collection hierarchy][10]][10] - -Graph for mutable hierarchy: - -[![Mutable collection hierarchy][11]][11] - -Legend: - -[![Graph legend][8]][8] - -Here's an abbreviated ASCII depiction of the collection hierarchy, for those who can't see the images. - - Traversable - | - | - Iterable - | - +------------------+--------------------+ - Map Set Seq - | | | - | | +------+-------+ - SortedMap SortedSet Buffer Vector LinearSeq - | - | - BitSet - -## Parallel Collections - -When Scala 2.9 introduced parallel collections, one of the design goals was to -make their use as seamless as possible. In the simplest terms, one can replace -a non-parallel (serial) collection with a parallel one, and instantly reap the -benefits. - -However, since all collections until then were serial, many algorithms using -them assumed and depended on the fact that they _were_ serial. Parallel -collections fed to the methods with such assumptions would fail. For this -reason, all the hierarchy described in the previous section _mandates serial -processing_. - -Two new hierarchies were created to support the parallel collections. - -The parallel collections hierarchy has the same names for traits, but preceded -with `Par`: `ParIterable`, `ParSeq`, `ParMap` and `ParSet`. Note that there is -no `ParTraversable`, since any collection supporting parallel access is capable -of supporting the stronger `ParIterable` trait. It doesn't have some of the -more specialized traits present in the serial hierarchy either. This whole -hierarchy is found under the directory `scala.collection.parallel`. - -The classes implementing parallel collections also differ, with `ParHashMap` -and `ParHashSet` for both mutable and immutable parallel collections, plus -`ParRange` and `ParVector` implementing `immutable.ParSeq` and `ParArray` -implementing `mutable.ParSeq`. - -Another hierarchy also exists that mirrors the traits of serial and parallel -collections, but with a prefix `Gen`: `GenTraversable`, `GenIterable`, -`GenSeq`, `GenMap` and `GenSet`. These traits are _parents_ to both parallel -and serial collections. This means that a method taking a `Seq` cannot receive -a parallel collection, but a method taking a `GenSeq` is expected to work with -both serial and parallel collections. - -Given the way these hierarchies were structured, code written for Scala 2.8 was -fully compatible with Scala 2.9, and demanded serial behavior. Without being -rewritten, it cannot take advantage of parallel collections, but the changes -required are very small. - -### Using Parallel Collections - -Any collection can be converted into a parallel one by calling the method `par` -on it. Likewise, any collection can be converted into a serial one by calling -the method `seq` on it. - -If the collection was already of the type requested (parallel or serial), no -conversion will take place. If one calls `seq` on a parallel collection or -`par` on a serial collection, however, a new collection with the requested -characteristic will be generated. - -Do not confuse `seq`, which turns a collection into a non-parallel collection, -with `toSeq`, which returns a `Seq` created from the elements of the -collection. Calling `toSeq` on a parallel collection will return a `ParSeq`, -not a serial collection. - -## The Main Traits - -While there are many implementing classes and subtraits, there are some basic -traits in the hierarchy, each of which providing more methods or more specific -guarantees, but reducing the number of classes that could implement them. - -In the following subsections, I'll give a brief description of the main traits -and the idea behind them. - -### Trait TraversableOnce - -This trait is pretty much like trait `Traversable` described below, but with -the limitation that you can only use it _once_. That is, any methods called on -a `TraversableOnce` _may_ render it unusable. - -This limitation makes it possible for the same methods to be shared between the -collections and `Iterator`. This makes it possible for a method that works with -an `Iterator` but not using `Iterator`-specific methods to actually be able to -work with any collection at all, plus iterators, if rewritten to accept -`TraversableOnce`. - -Because `TraversableOnce` unifies collections and iterators, and iterators are -not considered collections, it does not appear in the previous graphs, which -concern themselves only with collections. - -### Trait Traversable - -At the top of the _collection_ hierarchy is trait `Traversable`. Its only -abstract operation is - - def foreach[U](f: Elem => U) - -The operation is meant to traverse all elements of the collection, and apply -the given operation f to each element. The application is done for its side -effect only; in fact any function result of f is discarded by foreach. - -Traversable objects can be finite or infinite. An example of an infinite -traversable object 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. - -This class defines methods which can be efficiently implemented in terms of -`foreach` (over 40 of them). - -### Trait Iterable - -This trait declares an abstract method `iterator` that returns an iterator that -yields all the collection’s elements one by one. The `foreach` method in -`Iterable` is implemented in terms of `iterator`. Subclasses of `Iterable` -often override foreach with a direct implementation for efficiency. - -Class `Iterable` also adds some less-often used methods to `Traversable`, which -can be implemented efficiently only if an `iterator` is available. They are -summarized below. - - xs.iterator An iterator that yields every element in xs, in the same order as foreach traverses elements. - xs takeRight n A collection consisting of the last n elements of xs (or, some arbitrary n elements, if no order is defined). - xs dropRight n The rest of the collection except xs takeRight n. - xs sameElements ys A test whether xs and ys contain the same elements in the same order - -### Seq, Set and Map - -After `Iterable` there come three base traits which inherit from it: `Seq`, -`Set`, and `Map`. All three have an `apply` method and all three implement the -`PartialFunction` trait, but the meaning of `apply` is different in each case. - -I trust the meaning of `Seq`, `Set` and `Map` is intuitive. After them, the -classes break up in specific implementations that offer particular guarantees -with regards to performance, and the methods it makes available as a result of -it. Also available are some traits with further refinements, such as -`LinearSeq`, `IndexedSeq` and `SortedSet`. - -## Complete Overview - -### Base Classes and Traits - -* `TraversableOnce` -- All methods and behavior common to collections and iterators. - - * `Traversable` -- Basic collection class. Can be implemented just with `foreach`. - - * `TraversableProxy` -- Proxy for a `Traversable`. Just point `self` to the real collection. - * `TraversableView` -- A Traversable with some non-strict methods. - * `TraversableForwarder` -- Forwards most methods to `underlying`, except `toString`, `hashCode`, `equals`, `stringPrefix`, `newBuilder`, `view` and all calls creating a new iterable object of the same kind. - * `mutable.Traversable` and `immutable.Traversable` -- same thing as `Traversable`, but restricting the collection type. - * Other special-cases `Iterable` classes, such as `MetaData`, exists. - * `Iterable` -- A collection for which an `Iterator` can be created (through `iterator`). - * `IterableProxy`, `IterableView`, `mutable` and `immutable.Iterable`. - - * `Iterator` -- A trait which is not descendant of `Traversable`. Define `next` and `hasNext`. - * `CountedIterator` -- An `Iterator` defining `count`, which returns the elements seen so far. - * `BufferedIterator` -- Defines `head`, which returns the next element without consuming it. - * Other special-cases `Iterator` classes, such as `Source`, exists. - -### The Sequences - -* `Seq` -- A sequence of elements. One assumes a well-defined size and element repetition. Extends `PartialFunction` as well. - - * `IndexedSeq` -- Sequences that support O(1) element access and O(1) length computation. - * `IndexedSeqView` - * `immutable.PagedSeq` -- An implementation of `IndexedSeq` where the elements are produced on-demand by a function passed through the constructor. - * `immutable.IndexedSeq` - - * `immutable.Range` -- A delimited sequence of integers, closed on the lower end, open on the high end, and with a step. - * `immutable.Range.Inclusive` -- A `Range` closed on the high end as well. - * `immutable.NumericRange` -- A more generic version of `Range` which works with any `Integral`. - * `immutable.NumericRange.Inclusive`, `immutable.NumericRange.Exclusive`. - * `immutable.WrappedString`, `immutable.RichString` -- Wrappers which enables seeing a `String` as a `Seq[Char]`, while still preserving the `String` methods. I'm not sure what the difference between them is. - - * `mutable.IndexedSeq` - * `mutable.GenericArray` -- An `Seq`-based array-like structure. Note that the "class" `Array` is Java's `Array`, which is more of a memory storage method than a class. - * `mutable.ResizableArray` -- Internal class used by classes based on resizable arrays. - * `mutable.PriorityQueue`, `mutable.SynchronizedPriorityQueue` -- Classes implementing prioritized queues -- queues where the elements are dequeued according to an `Ordering` first, and order of queueing last. - * `mutable.PriorityQueueProxy` -- an abstract `Proxy` for a `PriorityQueue`. - - * `LinearSeq` -- A trait for linear sequences, with efficient time for `isEmpty`, `head` and `tail`. - - * `immutable.LinearSeq` - * `immutable.List` -- An immutable, singly-linked, list implementation. - * `immutable.Stream` -- A lazy-list. Its elements are only computed on-demand, but memoized (kept in memory) afterwards. It can be theoretically infinite. - * `mutable.LinearSeq` - * `mutable.DoublyLinkedList` -- A list with mutable `prev`, `head` (`elem`) and `tail` (`next`). - * `mutable.LinkedList` -- A list with mutable `head` (`elem`) and `tail` (`next`). - * `mutable.MutableList` -- A class used internally to implement classes based on mutable lists. - * `mutable.Queue`, `mutable.QueueProxy` -- A data structure optimized for FIFO (First-In, First-Out) operations. - * `mutable.QueueProxy` -- A `Proxy` for a `mutable.Queue`. - - * `SeqProxy`, `SeqView`, `SeqForwarder` - - * `immutable.Seq` - - * `immutable.Queue` -- A class implementing a FIFO-optimized (First-In, First-Out) data structure. There is no common superclass of both `mutable` and `immutable` queues. - * `immutable.Stack` -- A class implementing a LIFO-optimized (Last-In, First-Out) data structure. There is no common superclass of both `mutable` `immutable` stacks. - * `immutable.Vector` -- ? - * `scala.xml.NodeSeq` -- A specialized XML class which extends `immutable.Seq`. - * `immutable.IndexedSeq` -- As seen above. - * `immutable.LinearSeq` -- As seen above. - - * `mutable.ArrayStack` -- A class implementing a LIFO-optimized data structure using arrays. Supposedly significantly faster than a normal stack. - * `mutable.Stack`, `mutable.SynchronizedStack` -- Classes implementing a LIFO-optimized data structure. - * `mutable.StackProxy` -- A `Proxy` for a `mutable.Stack`.. - * `mutable.Seq` - - * `mutable.Buffer` -- Sequence of elements which can be changed by appending, prepending or inserting new members. - * `mutable.ArrayBuffer` -- An implementation of the `mutable.Buffer` class, with constant amortized time for the append, update and random access operations. It has some specialized subclasses, such as `NodeBuffer`. - * `mutable.BufferProxy`, `mutable.SynchronizedBuffer`. - * `mutable.ListBuffer` -- A buffer backed by a list. It provides constant time append and prepend, with most other operations being linear. - * `mutable.ObservableBuffer` -- A *mixin* trait which, when mixed to a `Buffer`, provides notification events through a `Publisher` interfaces. - * `mutable.IndexedSeq` -- As seen above. - * `mutable.LinearSeq` -- As seen above. - -### The Sets - -* `Set` -- A set is a collection that includes at most one of any object. - - * `SortedSet` -- A set whose elements are ordered. - * `immutable.SortedSet` - * `immutable.BitSet` -- A set of integers stored as a bitset. - * `immutable.TreeSet` -- An implementation of a `SortedSet` based on a tree. - * `mutable.SortedSet` - * `mutable.BitSet` -- A set of integers stored as a bitset. - - * `SetProxy` -- A `Proxy` for a `Set`. - - * `immutable.Set` - * `immutable.HashSet` -- An implementation of `Set` based on element hashing. - * `immutable.ListSet` -- An implementation of `Set` based on lists. - * Additional set classes exists to provide optimized implementations for sets from 0 to 4 elements. - * `immutable.SetProxy` -- A `Proxy` for an immutable `Set`. - - * `mutable.Set` - * `mutable.HashSet` -- An implementation of `Set` based on element hashing. - * `mutable.ImmutableSetAdaptor` -- A class implementing a mutable `Set` from an immutable `Set`. - * `LinkedHashSet` -- An implementation of `Set` based on lists. - * `ObservableSet` -- A *mixin* trait which, when mixed with a `Set`, provides notification events through a `Publisher` interface. - * `SetProxy` -- A `Proxy` for a `Set`. - * `SynchronizedSet` -- A *mixin* trait which, when mixed with a `Set`, provides notification events through a `Publisher` interface. - -### The Maps - -* `Map` -- An `Iterable` of `Tuple2`, which also provides methods for retrieving a value (the second element of the tuple) given a key (the first element of the tuple). Extends `PartialFunction` as well. - * `MapProxy` -- A `Proxy` for a `Map`. - * `DefaultMap` -- A trait implementing some of `Map`'s abstract methods. - * `SortedMap` -- A `Map` whose keys are sorted. - * `immutable.SortMap` - * `immutable.TreeMap` -- A class implementing `immutable.SortedMap`. - * `immutable.Map` - * `immutable.MapProxy` - * `immutable.HashMap` -- A class implementing `immutable.Map` through key hashing. - * `immutable.IntMap` -- A class implementing `immutable.Map` specialized for `Int` keys. Uses a tree based on the binary digits of the keys. - * `immutable.ListMap` -- A class implementing `immutable.Map` through lists. - * `immutable.LongMap` -- A class implementing `immutable.Map` specialized for `Long` keys. See `IntMap`. - * There are additional classes optimized for an specific number of elements. - * `mutable.Map` - * `mutable.HashMap` -- A class implementing `mutable.Map` through key hashing. - * `mutable.ImmutableMapAdaptor` -- A class implementing a `mutable.Map` from an existing `immutable.Map`. - * `mutable.LinkedHashMap` -- ? - * `mutable.ListMap` -- A class implementing `mutable.Map` through lists. - * `mutable.MultiMap` -- A class accepting more than one distinct value for each key. - * `mutable.ObservableMap` -- A *mixin* which, when mixed with a `Map`, publishes events to observers through a `Publisher` interface. - * `mutable.OpenHashMap` -- A class based on an open hashing algorithm. - * `mutable.SynchronizedMap` -- A *mixin* which should be mixed with a `Map` to provide a version of it with synchronized methods. - * `mutable.MapProxy`. - -## Bonus Questions - -* Why the Like classes exist (e.g. TraversableLike)? - -This was done to achieve maximum code reuse. The concrete *generic* -implementation for classes with a certain structure (a traversable, a map, etc) -is done in the Like classes. The classes intended for general consumption, -then, override selected methods that can be optimized. - -* What the companion methods are for (e.g. List.companion)? - -The builder for the classes, ie, the object which knows how to create instances -of that class in a way that can be used by methods like `map`, is created by a -method in the companion object. So, in order to build an object of type X, I -need to get that builder from the companion object of X. Unfortunately, there -is no way, in Scala, to get from class X to object X. Because of that, there is -a method defined in each instance of X, `companion`, which returns the -companion object of class X. - -While there might be some use for such method in normal programs, its target is -enabling code reuse in the collection library. - -* How I know what implicit objects are in scope at a given point? - -You aren't supposed to care about that. They are implicit precisely so that you -don't need to figure out how to make it work. - -These implicits exists to enable the methods on the collections to be defined -on parent classes but still return a collection of the same type. For example, -the `map` method is defined on `TraversableLike`, but if you used on a `List` -you'll get a `List` back. - -This answer was originally submitted in response to [this question][9] on Stack -Overflow. - - - [1]: https://docs.scala-lang.org/overviews/collections/introduction.html - [2]: https://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html - [3]: https://www.scala-lang.org/sid/3 - [4]: https://github.com/sirthias/scala-collections-charts/downloads - [5]: /resources/images/tour/collections-diagram.svg - [6]: https://i.stack.imgur.com/2fjoA.png - [7]: https://i.stack.imgur.com/Dsptl.png - [8]: /resources/images/tour/collections-legend-diagram.svg - [9]: https://stackoverflow.com/q/1722137/53013 - [10]: /resources/images/tour/collections-immutable-diagram.svg - [11]: /resources/images/tour/collections-mutable-diagram.svg diff --git a/_overviews/FAQ/context-bounds.md b/_overviews/FAQ/context-bounds.md deleted file mode 100644 index 16c3732be4..0000000000 --- a/_overviews/FAQ/context-bounds.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -layout: multipage-overview -title: What are Scala context bounds? -overview-name: FAQ -partof: FAQ - -num: 3 -permalink: /tutorials/FAQ/:title.html ---- - -What is a Context Bound? ------------------------- - -Context bounds were introduced in Scala 2.8.0, and are typically used with the -so-called _type class pattern_, a pattern of code that emulates the -functionality provided by Haskell type classes, though in a more verbose -manner. - -A context bound requires a _parameterized type_, such as `Ordered[A]`. - -A context bound describes an implicit _value_. It is used to declare that for -some type `A`, there is an -implicit value of type `B[A]` available. The syntax goes like this: - - def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A] - -The common example of usage in Scala is this: - - def f[A : ClassTag](n: Int) = new Array[A](n) - -An `Array` initialization on a parameterized type requires a `ClassTag` to -be available, for arcane reasons related to type erasure and the non-erasure -nature of arrays. - -Another very common example in the library is a bit more complex: - - def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b) - -Here, `implicitly` is used to retrieve the implicit value we want, one of type -`Ordering[A]`, which class defines the method `compare(a: A, b: A): Int`. - -We'll see another way of doing this below. - -How are Context Bounds implemented? ---------------------------------------------------- - -It shouldn't be surprising that context bounds are -implemented with implicit parameters, given their definition. Actually, the -syntax I showed are syntactic sugars for what really happens. See below how -they de-sugar: - - def g[A : B](a: A) = h(a) - def g[A](a: A)(implicit ev: B[A]) = h(a) - -So, naturally, one can write them in their full syntax, which is specially -useful for context bounds: - - def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b) - -What are Context Bounds used for? ---------------------------------- - -Context bounds are mainly used in what has become known as _typeclass pattern_, -as a reference to Haskell's type classes. Basically, this pattern implements an -alternative to inheritance by making functionality available through a sort of -implicit adapter pattern. - -The classic example is Scala 2.8's `Ordering`. The usage is: - - def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b - -Though you'll usually see that written like this: - - def f[A](a: A, b: A)(implicit ord: Ordering[A]) = { - import ord._ - if (a < b) a else b - } - -Which take advantage of some implicit conversions inside `Ordering` that enable -the traditional operator style. Another example in Scala 2.8 is the `Numeric`: - - def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b) - -A more complex example is the new collection usage of `CanBuildFrom`, but -there's already a very long answer about that, so I'll avoid it here. And, as -mentioned before, there's the `ClassTag` usage, which is required to -initialize new arrays without concrete types. - -Though it has been possible for a long time, the use of context bounds has -really taken off in 2010, and is now found to some degree in most of Scala's -most important libraries and frameworks. The most extreme example of its usage, -though, is the Scalaz library, which brings a lot of the power of Haskell to -Scala. I recommend reading up on typeclass patterns to get more acquainted it -all the ways in which it can be used. - -Related questions of interest: - -* [A discussion on types, origin and precedence of implicits](finding-implicits.html) -* [Chaining implicits](chaining-implicits.html) - -This answer was originally submitted in response to [this question on Stack Overflow][1]. - - [1]: https://stackoverflow.com/q/4465948/53013 diff --git a/_overviews/FAQ/finding-implicits.md b/_overviews/FAQ/finding-implicits.md deleted file mode 100644 index 5be593d931..0000000000 --- a/_overviews/FAQ/finding-implicits.md +++ /dev/null @@ -1,415 +0,0 @@ ---- -layout: multipage-overview -title: Where does Scala look for implicits? -overview-name: FAQ -partof: FAQ - -num: 7 -permalink: /tutorials/FAQ/:title.html ---- - -Newcomers to Scala often ask: Where does the compiler look for implicits? - -For example, where do the values for `integral` below come from? - - scala> import scala.math._ - import scala.math._ - - scala> def foo[T](t: T)(implicit integral: Integral[T]): Unit = { - println(integral) - } - foo: [T](t: T)(implicit integral: scala.math.Integral[T])Unit - - scala> foo(0) - scala.math.Numeric$IntIsIntegral$@3dbea611 - - scala> foo(0L) - scala.math.Numeric$LongIsIntegral$@48c610af - -The natural continuation of this line of inquiry leads to a second question: How -does the compiler choose which implicit to use, in certain situations of apparent -ambiguity (but that compile anyway)? - -For instance, `scala.Predef` defines two conversions from `String`: one to -`WrappedString` and another to `StringOps`. Both classes, however, share a lot -of methods, so why doesn't Scala complain about ambiguity when, say, calling -`map`? - -**Note:** this question was inspired by [this other question on Stack -Overflow][4], but states the problem in more general terms. The example was -copied from there, because it is referred to in the answer. - -## Types of Implicits - -Implicits in Scala refers to either a value that can be passed "automatically", -so to speak, or a conversion from one type to another that is made -automatically. - -### Implicit Conversion - -Speaking very briefly about the latter type, if one calls a method `m` on an -object `o` of a class `C`, and that class does not support method `m`, then -Scala will look for an implicit conversion from `C` to something that _does_ -support `m`. A simple example would be the method `map` on `String`: - - "abc".map(_.toInt) - -`String` does not support the method `map`, but `StringOps` does, and there's -an implicit conversion from `String` to `StringOps` available (see `implicit -def augmentString` on `Predef`). - -### Implicit Parameters - -The other kind of implicit is the implicit _parameter_. These are passed to -method calls like any other parameter, but the compiler tries to fill them in -automatically. If it can't, it will complain. One _can_ pass these parameters -explicitly, which is how one uses `breakOut`, for example (see question about -`breakOut`, on a day you are feeling up for a challenge). - -In this case, one has to declare the need for an implicit, such as the `foo` -method declaration: - - def foo[T](t: T)(implicit integral: Integral[T]): Unit = { - println(integral) - } - -### Implicit conversions as implicit parameters - -There's one situation where an implicit is both an implicit conversion and an -implicit parameter. For example: - - def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value) - - getIndex("abc", 'a') - -The method `getIndex` can receive any object, as long as there is an implicit -conversion available from its class to `Seq[T]`. Because of that, a `String` can be -passed to `getIndex`, and it will work. - -Behind the scenes, the compiler changes `seq.IndexOf(value)` to -`conv(seq).indexOf(value)`. - -### Context Bounds - -Another common pattern in implicit parameters is the _type class pattern_. This -pattern enables the provision of common interfaces to classes which did not -declare them. It can both serve as a bridge pattern -- gaining separation of -concerns -- and as an adapter pattern. - -The `Integral` class mentioned above is a classic example of type class pattern. -Another example on Scala's standard library is `Ordering`. Scalaz is a library -that makes heavy use of this pattern. - -This is an example of its use: - - def sum[T](list: List[T])(implicit integral: Integral[T]): T = { - import integral._ // get the implicits in question into scope - list.foldLeft(integral.zero)(_ + _) - } - -There is also a syntactic sugar for it, called a _context bound_, which is made -less useful by the need to refer to the implicit. A straight conversion of that -method looks like this: - - def sum[T : Integral](list: List[T]): T = { - val integral = implicitly[Integral[T]] - import integral._ // get the implicits in question into scope - list.foldLeft(integral.zero)(_ + _) - } - -Context bounds are more useful when you just need to _pass_ them to other -methods that use them. For example, the method `sorted` on `Seq` needs an -implicit `Ordering`. To create a method `reverseSort`, one could write: - - def reverseSort[T : Ordering](seq: Seq[T]) = seq.sorted.reverse - -Because `Ordering[T]` was implicitly passed to `reverseSort`, it can then pass -it implicitly to `sorted`. - -## Where do Implicits Come From? - -As described above, there are several contexts in which an implicit value may be required -for an expression to typecheck. The required implicit type is what determines -which value is selected. That value is found either in lexical scope or, -failing that, in what is called implicit scope. - -### Implicits Defined in Lexical Scope - -When a value of a certain name is required, lexical scope is searched for -a value with that name. Similarly, when an implicit value of a certain type is required, -lexical scope is searched for a value with that type. - -Any such value which can be referenced with its "simple" name, without -selecting from another value using dotted syntax, is an eligible implicit value. - -For example, here is a function that takes an implicit scaling factor. -The function requires a parameter of type `Int`, and there is a value -of that type in scope. The variable name `n` does not matter in this -case. - - implicit val n: Int = 5 - def scale(x: Int)(implicit y: Int) = x * y - scale(5) // takes n from the current scope, with the result 25 - -The invocation can be rewritten `scale(5)(n)`. If `n` can be referenced -using its simple name, as shown here, it is eligible as an implicit value. - -An implicit value can be introduced into scope by an import statement: - - import scala.collection.JavaConverters._ - def env = System.getenv().asScala // extension method enabled by imported implicit - val term = env("TERM") // it's a Scala Map - -There may be more than one such value because they have different names. - -In that case, overload resolution is used to pick one of them. The algorithm -for overload resolution is the same used to choose the reference for a -given name, when more than one term in scope has that name. For example, -`println` is overloaded, and each overload takes a different parameter type. -An invocation of `println` requires selecting the correct overloaded method. - -In implicit search, overload resolution chooses a value among more than one -that have the same required type. Usually this entails selecting a narrower -type or a value defined in a subclass relative to other eligible values. - -The rule that the value must be accessible using its simple name means -that the normal rules for name binding apply. - -In summary, a definition for `x` shadows a definition in -an enclosing scope. But a binding for `x` can also be introduced by -local imports. Imported symbols can't override definitions of the same -name in an enclosing scope. Similarly, wildcard imports can't override -an import of a specific name, and names in the current package that are -visible from other source files can't override imports or local definitions. - -These are the normal rules for deciding what `x` means in a given context, -and also determine which value `x` is accessible by its simple name and -is eligible as an implicit. - -This means that an implicit in scope can be disabled by shadowing it with -a term of the same name. - -For example, here, `X.f` is supplied the imported `X.s`: `X.f(s)`. -The body of `f` uses an implicit `Int`, from the immediate scope, -which shadows the `n` from `Y`, which is therefore not an eligible -implicit value. The parameter `s` shadows the member `s`. - -The method `g` does not compile because the implicit `t` is shadowed -by a `t` that is not implicit, so no implicit `T` is in scope. - - object Y { - implicit val n: Int = 17 - trait T { - implicit val i: Int = 17 - implicit def t: T = ??? - } - object X extends T { - implicit val n: Int = 42 - implicit val s: String = "hello, world\n" - def f(implicit s: String) = implicitly[String] * implicitly[Int] - override def t: T = ??? - def g = implicitly[T] - } - } - import Y.X._ - f - -The invocation of `f` was enabled by importing from `Y.X.`. But it is -not convenient to require an import to access implicit values -provided by a package. - -If an implicit value is not found in lexical scope, implicit search -continues in implicit scope. - -### Implicits Defined in Implicit Scope - -Implicit syntax can avoid the [import tax][1], which of course is a "sin tax," -by leveraging "implicit scope", which depends on the type of the implicit -instead of imports in lexical scope. - -When an implicit of type `T` is required, implicit scope includes -the companion object `T`: - - trait T - object T { implicit val t: T = new T { } } - -When an `F[T]` is required, implicit scope includes both the companion -of `F` and the companion of the type argument, e.g., `object C` for `F[C]`. - -In addition, implicit scope includes the companions of the base classes -of `F` and `C`, including package objects, such as `p` for `p.F`. - -### Companion Objects of a Type - -There are two object companions of note here. First, the object companion of -the "source" type is looked into. For instance, inside the object `Option` -there is an implicit conversion to `Iterable`, so one can call `Iterable` -methods on `Option`, or pass `Option` to something expecting an `Iterable`. For -example: - - for { - x <- List(1, 2, 3) - y <- Some('x') - } yield (x, y) - -That expression is translated by the compiler into - - List(1, 2, 3).flatMap(x => Some('x').map(y => (x, y))) - -However, `List.flatMap` expects a `TraversableOnce`, which `Option` is not. The -compiler then looks inside `Option`'s object companion and finds the conversion -to `Iterable`, which is a `TraversableOnce`, making this expression correct. - -Second, the companion object of the expected type: - - List(1, 2, 3).sorted - -The method `sorted` takes an implicit `Ordering`. In this case, it looks inside -the object `Ordering`, companion to the class `Ordering`, and finds an implicit -`Ordering[Int]` there. - -Note that companion objects of super classes are also looked into. For example: - - class A(val n: Int) - object A { - implicit def str(a: A) = "A: %d" format a.n - } - class B(val x: Int, y: Int) extends A(y) - val b = new B(5, 2) - val s: String = b // s == "A: 2" - -This is how Scala found the implicit `Numeric[Int]` and `Numeric[Long]` in the -opening example, by the way, as they are found inside `Numeric`, not `Integral`. - -### Implicit scope of an argument's type - -If you have a method with an argument type `A`, then the implicit scope of type -`A` will also be considered. Here "implicit scope" means all these rules -will be applied recursively -- for example, the companion object of `A` will be -searched for implicits, as per the rule above. - -Note that this does not mean the implicit scope of `A` will be searched for -conversions of that parameter alone, but of the whole expression. For example: - - class A(val n: Int) { - def +(other: A) = new A(n + other.n) - } - object A { - implicit def fromInt(n: Int) = new A(n) - } - - // This becomes possible: - 1 + new A(1) - // because it is converted into this: - A.fromInt(1) + new A(1) - -### Implicit scope of type arguments - -This is required to make the type class pattern really work. Consider -`Ordering`, for instance... it comes with some implicits in its companion -object, but you can't add stuff to it. So how can you make an `Ordering` for -your own class that is automatically found? - -Let's start with the implementation: - - class A(val n: Int) - object A { - implicit val ord = new Ordering[A] { - def compare(x: A, y: A) = implicitly[Ordering[Int]].compare(x.n, y.n) - } - } - -So, consider what happens when you call - - List(new A(5), new A(2)).sorted - -As we saw, the method `sorted` expects an `Ordering[A]` (actually, it expects -an `Ordering[B]`, where `B >: A`). There isn't any such thing inside -`Ordering`, and there is no "source" type on which to look. Obviously, it is -finding it inside `A`, which is a _type argument_ of `Ordering`. - -This is also how various collection methods expecting `CanBuildFrom` work: the -implicits are found inside companion objects to the type parameters of -`CanBuildFrom`. - -**Note**: `Ordering` is defined as `trait Ordering[T]`, where `T` is a type -parameter. The implicit looked for above is `Ordering[A]`, where -`A` is an actual type, not type parameter: it is a _type argument_ to -`Ordering`. See section 7.2 of the [Scala Specification][6]. - -### Outer Objects for Nested Types - -The principle is simple: - - class A(val n: Int) { - class B(val m: Int) { require(m < n) } - } - object A { - implicit def bToString(b: A#B) = "B: %d" format b.m - } - val a = new A(5) - val b = new a.B(3) - val s: String = b // s == "B: 3" - -A real world example of this would be welcome. Please share your example! - -### Package Objects Can Contribute Implicit Values - -An implicit value in a package object can be made available either -in lexical scope or in implicit scope. - -To be available in lexical scope, the packages must be declared as nested packages: - - package object p { implicit val s: String = "hello, world" } - package p { - package q { - object X { def f = implicitly[String] } - } - } - -This is sensitive to name binding rules. The following example compiles -only if the package object is in a separate file, in which case the import is used: - - package object p { implicit val s: String = "hello, world" } - package p { - package q { - object Y { - implicit val s: String = "bye" - } - object X { - import Y._ - def f = implicitly[String] - } - } - } - -A package object can also offer implicit values of types in subpackages: - - package object p { implicit val c: q.C = new q.C } - package p.q { - class C - object X { def f = implicitly[C] } - } - -Here, the implicit is supplied in implicit scope of `C`. - -### Call To Action - -Avoid taking this question as being the final arbiter of what is happening. -If you do notice it has become out-of-date, do [open a ticket about it][7], or, if -you know how to correct it, please fix it. - -Related questions of interest: - -* [Context bounds](context-bounds.html) -* [Chaining implicits](chaining-implicits.html) - -This question and answer were originally submitted on [Stack Overflow][3]. - - [1]: https://jsuereth.com/scala/2011/02/18/2011-implicits-without-tax.html - [2]: https://issues.scala-lang.org/browse/SI-4427 - [3]: https://stackoverflow.com/q/5598085/53013 - [4]: https://stackoverflow.com/questions/5512397/passing-scala-math-integral-as-implicit-parameter - [5]: https://scala-lang.org/files/archive/spec/2.11/06-expressions.html - [6]: https://scala-lang.org/files/archive/spec/2.11/07-implicits.html - [7]: https://github.com/scala/docs.scala-lang/issues diff --git a/_overviews/FAQ/finding-symbols.md b/_overviews/FAQ/finding-symbols.md deleted file mode 100644 index c9737400c0..0000000000 --- a/_overviews/FAQ/finding-symbols.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -layout: multipage-overview -title: How do I find what some symbol means or does? -overview-name: FAQ -partof: FAQ - -num: 1 - -permalink: /tutorials/FAQ/:title.html ---- -We can divide the operators in Scala, for the purpose of teaching, into four categories: - -* Keywords/reserved symbols -* Normal methods or values -* Methods provided by implicit conversion -* Syntactic sugars/composition - -And let's see some arbitrary examples: - - <- // Keyword - -> // Method provided by implicit conversion - <= // Common method - ++= // Can be a common method or syntactic sugar involving ++ method - :: // Common method or object - _+_ // Not really a single operator; it's parsed as _ + _ - -The exact meaning of most of these methods depends on the class they are defined -on. For example, `<=` on `Int` means _"less than or equal to"_, but it might -mean something else in another class. `::` in an expression is probably the method of the class -`List` but it can also refer to the object of the same name (and in a pattern it -definitely does). - -So, let's discuss these categories. - -Keywords/reserved symbols -------------------------- - -There are a few symbols in Scala that are special and cannot be defined or used as method names. -Two of them are considered proper keywords, while others are just "reserved". They are: - - // Keywords - <- // Used on for-comprehensions, to separate pattern from generator - => // Used for function types, function literals and import renaming - - // Reserved - ( ) // Delimit expressions and parameters - [ ] // Delimit type parameters - { } // Delimit blocks - . // Method call and path separator - // /* */ // Comments - # // Used in type notations - : // Type ascription or context bounds - <: >: // Upper and lower bounds - <% // View bounds (deprecated) - " """ // Strings - ' // Indicate symbols and characters - @ // Annotations and variable binding on pattern matching - ` // Denote constant or enable arbitrary identifiers - , // Parameter separator - ; // Statement separator - _* // vararg expansion - _ // Many different meanings - -These are all _part of the language_, and, as such, can be found in any text -that properly describe the language, such as [Scala Specification][1](PDF) -itself. - -The last one, the underscore, deserve a special description, because it is -widely used, and has different meanings depending on the context. Here's a sample: - - import scala._ // Wild card -- all of Scala is imported - import scala.{ Predef => _, _ } // Exclusion, everything except Predef - def f[M[_]] // Higher kinded type parameter - def f(m: M[_]) // Existential type - _ + _ // Anonymous function placeholder parameter - m _ // Eta expansion of method into method value - m(_) // Partial function application - _ => 5 // Discarded parameter - case _ => // Wild card pattern -- matches anything - f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*) - case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence - -Common methods --------------- - -Many symbols are simply methods of a class, a trait, or an object. For instance, if you do - - List(1, 2) ++ List(3, 4) - -You'll find the method `++` right on the Scaladoc for [List][5]. However, -there's one convention that you must be aware when searching for methods. -Methods ending in colon (`:`) bind _to the right_ instead of the left. In other -words, while the above method call is equivalent to: - - List(1, 2).++(List(3, 4)) - -If I had, instead `1 :: List(2, 3)`, that would be equivalent to: - - List(2, 3).::(1) - -So you need to look at the type found _on the right_ when looking for methods -ending in colon. Consider, for instance: - - 1 +: List(2, 3) :+ 4 - -The first method (`+:`) binds to the right, and is found on `List`. The second -method (`:+`) is just a normal method, and binds to the left -- again, on -`List`. - -If the name ends in `=`, look for the method called the same without `=` and -read the last section. - -If you aren't sure what the type of the receiver is, you can look up the symbol -on the Scaladoc [index page for identifiers not starting with letters][2] (for -standard Scala library; of course, third-party libraries can add their own -symbolic methods, for which you should look at the corresponding page of _their_ -Scaladoc). - -Types and objects can also have symbolic names; in particular, it should be mentioned -that for types with two type parameters the name can be written _between_ parameters, -so that e.g. `Int <:< Any` is the same as `<:<[Int, Any]`. - -Methods provided by implicit conversion ---------------------------------------- - -If you did not find the symbol you are looking for in the list of reserved symbols, then -it must be a method, or part of one. But, often, you'll see some symbol and the -documentation for the class will not have that method. When this happens, -either you are looking at a composition of one or more methods with something -else, or the method has been imported into scope, or is available through an -imported implicit conversion. - -These can also be found in Scaladoc's [index][2], as mentioned above. - -All Scala code has three automatic imports: - - // Not necessarily in this order - import java.lang._ - import scala._ - import scala.Predef._ - -The first two only make classes and singleton objects available, none of which -look like operators. [`Predef`][3] is the only interesting one for this post. - -Looking inside `Predef` shows some symbolic names: - - class <:< - class =:= - object =:= - object <%< // removed in Scala 2.10 - def ??? - -There is also `::`, which doesn't appear in the Scaladoc, but is mentioned in the comments. -In addition, `Predef` makes some methods available through _implicit conversions_. Just -look at the methods and classes with `implicit` modifier that receive, as parameter, an -object of type that is receiving the method. For example, consider `"a" -> 1`. We need -to look for an implicit which works on `"a"`, and so it can take `String`, one of its -supertypes (`AnyRef` or `Any`) or a type parameter. In this case, we find -`implicit final class ArrowAssoc[A](private val self: A)` which makes this implicit -available on all types. - -Other implicit conversions may be visible in your scope depending on imports, extended types or -self-type annotations. See [Finding implicits](finding-implicits.html) for details. - -Syntactic sugars/composition ------------------------------ - -So, here's a few syntactic sugars that may hide a method: - - class Example(arr: Array[Int] = Array.fill(5)(0)) { - def apply(n: Int) = arr(n) - def update(n: Int, v: Int) = arr(n) = v - def a = arr(0); def a_=(v: Int) = arr(0) = v - def b = arr(1); def b_=(v: Int) = arr(1) = v - def c = arr(2); def c_=(v: Int) = arr(2) = v - def d = arr(3); def d_=(v: Int) = arr(3) = v - def e = arr(4); def e_=(v: Int) = arr(4) = v - def +(v: Int) = new Example(arr map (_ + v)) - def unapply(n: Int) = if (arr.indices contains n) Some(arr(n)) else None - } - - val ex = new Example - println(ex(0)) // means ex.apply(0) - ex(0) = 2 // means ex.update(0, 2) - ex.b = 3 // means ex.b_=(3) - val ex(c) = 2 // calls ex.unapply(2) and assigns result to c, if it's Some; throws MatchError if it's None - ex += 1 // means ex = ex + 1; if Example had a += method, it would be used instead - -The last one is interesting, because *any* symbolic method can be combined with `=` in that way. - -And, of course, all of the above can be combined in various combinations, e.g. - - (_+_) // An expression, or parameter, that is an anonymous function with - // two parameters, used exactly where the underscores appear, and - // which calls the "+" method on the first parameter passing the - // second parameter as argument. - -This answer was originally submitted in response to [this question on Stack Overflow][6]. - - [1]: https://scala-lang.org/files/archive/spec/2.11/ - [2]: https://www.scala-lang.org/api/current/index.html#index.index-_ - [3]: https://www.scala-lang.org/api/current/scala/Predef$.html - [4]: https://www.scala-lang.org/api/current/scala/Predef$$ArrowAssoc.html - [5]: https://www.scala-lang.org/api/current/scala/collection/immutable/List.html - [6]: https://stackoverflow.com/q/7888944/53013 diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index 91ab76367b..82d624f374 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -4,10 +4,84 @@ title: Scala FAQs permalink: /tutorials/FAQ/index.html --- -A collection of frequently asked questions and their answers! Graciously -provided by Daniel Sobral, adapted from his StackOverflow posts. +Frequently asked questions, with _brief_ answers and/or links to +longer answers. -## FAQs +This list only includes questions that _actually_ come up over and +over again in Scala chat rooms and forums. + +## General questions + +### Where can I ask Scala questions? + +see our [Community page](https://scala-lang.org/community/) + +### Should I learn Scala 2, or Scala 3? + +The default choice remains Scala 2 for now. Most Scala jobs are Scala +2 jobs; most Scala books and online learning materials cover Scala 2; +tooling and library support is strongest in Scala 2; and so on. + +Scala 3.0 is planned for release in early 2021, and a number of +Scala 3 books will come out in 2021 as well. In time, there will +be more and more Scala 3 jobs as well. + +### What's a good book about Scala? + +Our [Books page](https://docs.scala-lang.org/books.html) lists a few +especially popular, well-known books. + +We don't have a list of all the Scala books that +are out there; there are many. + +You can go on the [Scala room on +Gitter](https://gitter.im/scala/scala) or another community forum and +ask for book recommendations, but note that you'll get more helpful +answers if you provide some information about your background and your +reasons for wanting to learn Scala. + +### How do I find what some symbol means or does? + +A [Stack Overflow answer](https://stackoverflow.com/a/7890032) lays +out what the different kinds of symbol in Scala are and explains the +most commonly used symbols. + +Scala allows symbolic method names. So if you see a random-looking +operator like `>=@=>` in Scala code, it might simply be a method in +some library, rather than having any special meaning in the language +itself. + +You can search for symbols on Google. For example, if you want to +know what `<:<` means, searching for `scala <:<` works fine. If you +get poor results, try surrounding the symbol with double quotes. + +## Specific technical questions + +### Which type of collection should I choose? + +see the [Scala Collections Guide](https://docs.scala-lang.org/overviews/collections/introduction.html) + +### What are Scala context bounds (`[T : Foo]`)? + +[answer on Stack Overflow](https://stackoverflow.com/a/4467012) + +### How does `yield` work? + +[answer on Stack Overflow](https://stackoverflow.com/a/1059501) + +### What is the difference between view, stream and iterator? + +[answer on Stack Overflow](https://stackoverflow.com/a/5159356) + +### How can I chain/nest implicit conversions? + +[answer on Stack Overflow](https://stackoverflow.com/a/5332804) + +### Where does Scala look for implicits? + +[answer on Stack Overflow](https://stackoverflow.com/a/5598107) + +## More questions {% assign overviews = site.overviews | sort: 'num' %}