Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Have you picked a tough nut to crack as a beginner to Scala! :-)</p> <p>Ok, brief tour, don't expect to fully understand it right now. First, note that the problem happens at the method <code>++</code>. Searching for its definition, we find it at the trait <code>MapLike</code>, receiving either an <code>Iterator</code> or a <code>Traversable</code>. Since <code>y</code> is a <code>SortedMap</code>, then it is the <code>Traversable</code> version being used.</p> <p>Note in its extensive type signature that there is a <code>CanBuildFrom</code> being passed. It is being passed implicitly, so you don't normally need to worry about it. However, to understand what is going on, this time you do.</p> <p>You can locate CanBuildFrom by either clicking on it where it appears in the definition of <code>++</code>, or by filtering. As mentioned by Randall on the comments, there's an unmarked blank field on the upper left of the scaladoc page. You just have to click there and type, and it will return matches for whatever it is you typed.</p> <p>So, look up the trait <code>CanBuildFrom</code> on ScalaDoc and select it. It has a large number of subclasses, each one responsible for building a specific type of collection. Search for and click on the subclass <code>SortedMapCanBuildFrom</code>. This is the class of the object you need to produce a <code>SortedMap</code> from a <code>Traversable</code>. Note on the instance constructor (the constructor for the class) that it receives an implicit <code>Ordering</code> parameter. Now we are getting closer.</p> <p>This time, use the filter filter to search for <code>Ordering</code>. Its companion object (click on the small "o" the name) hosts an implicit that will generate <code>Ordering</code>s, as companion objects are examined for implicits generating instances or conversions for that class. It is defined inside the trait <code>LowPriorityOrderingImplicits</code>, which object <code>Ordering</code> extends, and looking at it you'll see the method <code>ordered[A &lt;: Ordered[A]]</code>, which will produce the <code>Ordering</code> required... or would produce it, if only there wasn't a problem.</p> <p>One might assume the implicit conversion from <code>X</code> to <code>Ordered[X]</code> would be enough, just as I had before looking more carefully into this. That, however, is a conversion of <em>objects</em>, and <code>ordered</code> expects to receive a <em>type</em> which is a subtype of <code>Ordered[X]</code>. While one can convert an object of type <code>X</code> to an object of type <code>Ordered[X]</code>, <code>X</code>, itself, is not a subtype of <code>Ordered[X]</code>, so it can't be passed as a parameter to <code>ordered</code>. </p> <p>On the other hand, you can create an implicit <code>val</code> <code>Ordering[X]</code>, instead of the <code>def</code> <code>Ordered[X]</code>, and you'll get around the problem. Specifically:</p> <pre><code>object ViewBoundExample { class X def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = { a ++ b } implicit val orderingX = new Ordering[X] { def compare(x: X, y: X) = 0 } } </code></pre> <p>I think most people initial reaction to <code>Ordered</code>/<code>Ordering</code> must be one of perplexity: why have classes for the same thing? The former extends <code>java.lang.Comparable</code>, whereas the latter extends <code>java.util.Comparator</code>. Alas, the type signature for <code>compare</code> pretty much sums the main difference:</p> <pre><code>def compare(that: A): Int // Ordered def compare(x: T, y: T): Int // Ordering </code></pre> <p>The use of an <code>Ordered[A]</code> requires for either <code>A</code> to extend <code>Ordered[A]</code>, which would require one to be able to <em>modify</em> <code>A</code>'s definition, or to pass along a method which can convert an <code>A</code> into an <code>Ordered[A]</code>. Scala is perfectly capable of doing the latter easily, but then you <em>have</em> to convert each instance before comparing.</p> <p>On the other hand, the use of <code>Ordering[A]</code> requires the creation of a single object, such as demonstrated above. When you use it, you just pass two objects of type <code>A</code> to <code>compare</code> -- no objects get created in the process.</p> <p>So there are some performance gains to be had, but there is a much more important reason for Scala's preference for <code>Ordering</code> over <code>Ordered</code>. Look again on the companion object to <code>Ordering</code>. You'll note that there are several implicits for many of Scala classes defined in there. You may recall I mentioned earlier that an implicit for class <code>T</code> will be searched for inside the companion object of <code>T</code>, and that's exactly what is going on.</p> <p>This <em>could</em> be done for <code>Ordered</code> as well. However, and this is the sticking point, that means every method supporting both <code>Ordering</code> and <code>Ordered</code> would fail! That's because Scala would look for an implicit to make it work, and would find two: one for <code>Ordering</code>, one for <code>Ordered</code>. Being unable to decide which is it you wanted, Scala gives up with an error message. So, a choice had to be made, and <code>Ordering</code> had more going on for it.</p> <p>Duh, I forgot to explain why the signature isn't defined as <code>ordered[A &lt;% Ordered[A]]</code>, instead of <code>ordered[A &lt;: Ordered[A]]</code>. I suspect doing so would cause the double implicits failure I have mentioned before, but I'll ask the guy who actually did this stuff and had the double implicit problems whether this particular method is problematic.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload