Scala 3: Contextual Abstractions, Part III
In my last post, before the revolution, I discussed the Scala 3 way of defining type classes.
Update, November 18, 2020: I added new information about importing given instances.
Update: December 27, 2020. The syntax for given instances and extension methods was refined slightly in Scala 3.0.0-M3.
This post finishes this quick overview of contextual abstractions with a discussion of the new using clauses that replace implicit parameter lists.
But first, Scala 3 reached its first milestone release this past week, Scala
3.0.0-M1
. The book examples now use it. The Scala team hopes to have the first release candidate ready by Christmas.
Consider the following contrived example that wraps sequences with a sorting functionality. Never mind that sequences already provide this ability, which the implementation actually uses.
The first method, sortByImplicits
, uses a Scala 2 implicit parameter list. This is still supported in Scala 3, but will be deprecated eventually. Note that the ordering instance o
is passed explicitly to Seq.sortBy
.
The second and third methods, sortBy1a
and sortBy1b
, show the new using clause syntax. The first one just replaces the keyword implicit
with using
, while the second shows that you can leave the value anonymous. In this case, the new summon
method is used to bind the anonymous instance. In fact, I only need this because I’m passing the instance explicitly, but of course I wanted to show you the new way of binding an instance when needed. In fact, summon
is identical to the Scala 2 method implicitly
, but with a new name.
Finally, sortBy2
shows the context bound syntax for writing the same thing. This syntax is the same as for Scala 2, but now it’s a shorthand way of writing using clauses.
Let’s try it:
The given evenOdd
ordering returns even numbers first, then odds, sorted descending. The comment shows an alternative way of defining the given instance, using the syntax discussed in the previous post.
The two groups of assert
statements use the given instance implicitly, then explicitly.
If the given instance is anonymous, you can bind it using summon
, which behaves exactly like the previous method for this purpose, implicitly
. (A new name for a rebranded concept.)
Importing Given Instances
We all like the convenience of using wild-card imports, like import foo.bar._
, but we might prefer more control over given instances and older implicit definitions. Scala 3 introduces a new syntax for this purpose:
The comments describe the import behaviors. In Scala 3.0, _
will still import everything, for backwards compatibility, but Scala 3.1 will begin transitioning to the specific behavior described in the comments. You can also force the compiler to use the 3.1 behavior now by adding the -source:3.1
or similar flags.
What’s Next?
In the next several posts, I’ll explore changes in the type system.
You can start reading the rough draft of Programming Scala, Third Edition on the O’Reilly Learning Platform. Currently, the first eight chapters are available, including the two (five and six) that cover contextual abstractions.