|
| 1 | +--- |
| 2 | +layout: blog-page |
| 3 | +title: Announcing Dotty 0.18.1-RC1 – switch to the 2.13 standard library, indentation-based syntax and other experiments |
| 4 | +author: Anatolii Kmetiuk |
| 5 | +authorImg: /images/anatolii.png |
| 6 | +date: 2019-08-30 |
| 7 | +--- |
| 8 | + |
| 9 | +Greetings! With this post, we are proud to announce the 18th release of Dotty. With this release, we have switched to the 2.13 standard library (which is why the patch version of Dotty is now `1`)🎉. We are also conducting more experiments with the language syntax which will hopefully result in a better, cleaner way to write Scala programs. |
| 10 | + |
| 11 | +This release serves as a technology preview that demonstrates new |
| 12 | +language features and the compiler supporting them. |
| 13 | + |
| 14 | +Dotty is the project name for technologies that are being considered for |
| 15 | +inclusion in Scala 3. Scala has pioneered the fusion of object-oriented and |
| 16 | +functional programming in a typed setting. Scala 3 will be a big step towards |
| 17 | +realising the full potential of these ideas. Its main objectives are to |
| 18 | + |
| 19 | +- become more opinionated by promoting programming idioms we found to work well, |
| 20 | +- simplify where possible, |
| 21 | +- eliminate inconsistencies and surprising behaviours, |
| 22 | +- build on strong foundations to ensure the design hangs together well, |
| 23 | +- consolidate language constructs to improve the language’s consistency, safety, ergonomics, and |
| 24 | + performance. |
| 25 | + |
| 26 | +You can learn more about Dotty on our [website](https://dotty.epfl.ch). |
| 27 | + |
| 28 | +<!--more--> |
| 29 | + |
| 30 | +This is our 18th scheduled release according to our |
| 31 | +[6-week release schedule](https://dotty.epfl.ch/docs/contributing/release.html). |
| 32 | + |
| 33 | +# What’s new in the 0.18.1-RC1 technology preview? |
| 34 | +The hottest change of this release is a series of experiments with the language syntax. Some of them are controversial, some of them are almost unanimously considered useful. Regardless, the underlying motivation for all of them is something all of us want, we believe d: to make programming in Scala easier to write and read, drop unnecessary boilerplate, facilitate idiomatic programming. |
| 35 | + |
| 36 | +We are thrilled to have this unique opportunity to experiment while Scala 3 is still in its inception and malleable. This is the only time we can try out significant language changes, and we are determined to make the most out of it. |
| 37 | + |
| 38 | +Our view on these trials is that, like with any big change, we need time to see if these are good ideas. We don't know if they will work or not. We believe that the only way to find out is to play with them for some time. |
| 39 | + |
| 40 | +Some of these changes will end up in Scala 3, some of them will be deemed not worth it. One way or another, trying the new look of an old language is an educational and fun experience. |
| 41 | + |
| 42 | +Keeping that in mind, let us proceed to the nitty-gritty! |
| 43 | + |
| 44 | +## Switch to Standard Library 2.13 |
| 45 | +Dotty is now using the standard library 2.13 instead of the previous 2.12.8. This fact is reflected in the patch version 1 in 0.18.1-RC1 which Dotty will be using from now on. |
| 46 | + |
| 47 | +## `@main` functions |
| 48 | +Bootstrapping a new Scala application is as hard as a new Java application. How do you write a main method? Normally, something like that: |
| 49 | + |
| 50 | +```scala |
| 51 | +object Test { |
| 52 | + def main(args: Array[String]): Unit = println(s"Hello World") |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +You need to define at least two things that serve no real purpose: an object and `(args: Array[String])`. |
| 57 | + |
| 58 | +Not anymore! Meet the `@main` functions: |
| 59 | + |
| 60 | + |
| 61 | +```scala |
| 62 | +@main def test: Unit = println(s"Hello World") |
| 63 | +``` |
| 64 | + |
| 65 | +The above generates the following code at the top-level of the compilation unit (source file): |
| 66 | + |
| 67 | +```scala |
| 68 | +final class test { |
| 69 | + <static> def main(args: Array[String]): Unit = |
| 70 | + try Main$package.test() catch |
| 71 | + { |
| 72 | + case |
| 73 | + error @ _:scala.util.CommandLineParser.CommandLineParser$ParseError |
| 74 | + => scala.util.CommandLineParser.showError(error) |
| 75 | + } |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +So, a `final class` is generated with the same name as the `@main` method and the `def main(args: Array[String])` inside. The body of this method calls the original `test()` method. Since it is a top-level definition, it resides in the synthetic `Main$package` object generated for the `Main.scala` source being compiled. |
| 80 | + |
| 81 | +An astute reader has probably noticed the mentions of things like `CommandLineParser` in the body of the generated method, which hints to certain features. That's right, we support a basic ability for command-line args parsing: |
| 82 | + |
| 83 | +```scala |
| 84 | +@main def sayHello(name: String, age: Int): Unit = |
| 85 | + println(s"Hello $name, you are $age years old") |
| 86 | +``` |
| 87 | + |
| 88 | +If you run the above with command line arguments "Jack 25", the output will be "Hello Jack, you are 25 years old". And here is how you can define a custom parser for your own class: |
| 89 | + |
| 90 | +```scala |
| 91 | +case class Address(city: String, street: String) |
| 92 | + |
| 93 | +given as scala.util.FromString[Address] { |
| 94 | + /** Can throw java.lang.IllegalArgumentException */ |
| 95 | + def fromString(s: String): T = |
| 96 | + s.split(",").toList match { |
| 97 | + case city :: street :: Nil => Address(city, street) |
| 98 | + case _ => throw new IllegalArgumentException(s"Please specify address in the format 'city, street'") |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +@main def sayHello(addr: Address): Unit = |
| 103 | + println(s"You are living at $addr") |
| 104 | +``` |
| 105 | + |
| 106 | +The motivation for the `@main` functions is to make Scala scripting friendly. So far we do not plan to support something more complex than the above – we believe if a user needs a complex command line parsing capability, they can always fall back to the conventional `def main(args: Array[String])` syntax plus a dedicated library like [scopt](https://github.com/scopt/scopt). The changes described above, however, are already enough to make script development much less tedious than before. |
| 107 | + |
| 108 | +To learn more, see the [documentation](http://dotty.epfl.ch/docs/reference/changed-features/main-functions.html). |
| 109 | + |
| 110 | +## Allow infix operators at the start of the line |
| 111 | +A small change yet relevant to many. Now, you can write the following code: |
| 112 | + |
| 113 | +```scala |
| 114 | +def isABorC(x: Char) = x == 'A' |
| 115 | + || x == 'B' |
| 116 | + || x == 'C' |
| 117 | +``` |
| 118 | + |
| 119 | +Prior to this change, it was only possible to express infix operators at the beginning of the line as follows: |
| 120 | + |
| 121 | +```scala |
| 122 | +def isABorC(x: Char) = (x == 'A' |
| 123 | + || x == 'B' |
| 124 | + || x == 'C') |
| 125 | +``` |
| 126 | + |
| 127 | +## Drop do-while syntax |
| 128 | +Remember that obscure `do-while` feature of Scala 2 where you could write: |
| 129 | + |
| 130 | +```scala |
| 131 | +scala> var x = 0 |
| 132 | +x: Int = 0 |
| 133 | + |
| 134 | +scala> val iterator = Iterator.from(10, -1) |
| 135 | +iterator: Iterator[Int] = <iterator> |
| 136 | + |
| 137 | +scala> do { |
| 138 | + | x = iterator.next() |
| 139 | + | println(x) |
| 140 | + | } while (x > 0) |
| 141 | +10 |
| 142 | +9 |
| 143 | +8 |
| 144 | +7 |
| 145 | +6 |
| 146 | +5 |
| 147 | +4 |
| 148 | +3 |
| 149 | +2 |
| 150 | +1 |
| 151 | +0 |
| 152 | +``` |
| 153 | + |
| 154 | +Well, it is no more! That is the only place where the `do` token is used in Scala, the feature itself is rarely employed, and it would be nice to reclaim the `do` token for other uses (described in details in the section on the new syntax for control expressions). |
| 155 | + |
| 156 | +The language does not lose its expressiveness though – you can still write the following to achieve the same functionality: |
| 157 | + |
| 158 | +```scala |
| 159 | +val iterator = Iterator.from(10, -1) |
| 160 | + |
| 161 | +@main def test = { |
| 162 | + var x: Int = 0 |
| 163 | + while ({ |
| 164 | + x = iterator.next |
| 165 | + println(x) |
| 166 | + x > 0 |
| 167 | + }) () |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +For more information, see PR [#6994](https://github.com/lampepfl/dotty/pull/6994). |
| 172 | + |
| 173 | +## Brace-less syntax for control expressions |
| 174 | +This is an effort to clean-up the control expressions. Scala 2 has two ways of writing `if` statements – with and without parentheses. Parentheses can be dropped in Scala 2 `if`s inside `match` or `for` statements. We'd like to have a single style of writing all of the control expressions, and the cleaner the better. |
| 175 | + |
| 176 | +This release, hence, brings the ability to write all of the control expressions without braces. E.g.: |
| 177 | + |
| 178 | +```scala |
| 179 | +@main def testFor = { |
| 180 | + val xs = 0 to 10 |
| 181 | + val xsFiltered = for x <- xs if x > 1 yield x |
| 182 | + for |
| 183 | + x <- xsFiltered |
| 184 | + y <- xsFiltered |
| 185 | + do println(s"$x * $y = ${x * y}") |
| 186 | +} |
| 187 | + |
| 188 | +@main def testIf(day: String) = { |
| 189 | + if day == "Sunday" || day == "Saturday" then println("Today is a weekend, hooray!") |
| 190 | + else println(s"Today is a workday.") |
| 191 | +} |
| 192 | + |
| 193 | +@main def testWhile(bound: Int) = { |
| 194 | + var x = 0 |
| 195 | + def incrementX() = { |
| 196 | + x += 1 |
| 197 | + println(x) |
| 198 | + } |
| 199 | + while x <= bound do incrementX() |
| 200 | +} |
| 201 | +``` |
| 202 | + |
| 203 | +Moreover, the compiler can automatically rewrite your sources from the old syntax to the new syntax and vice versa. To rewrite the sources to the new syntax, run the compiler with the `-rewrite -new-syntax` flags, and to rewrite to the old syntax, use `-rewrite -old-syntax`. So far, both syntaxes are supported. |
| 204 | + |
| 205 | +For more information and the precise rules, see PR [#7024](https://github.com/lampepfl/dotty/pull/7024). |
| 206 | + |
| 207 | +## Significant indentation syntax |
| 208 | +Significant indentations syntax is here! A logical continuation of the brace-less syntax for control expressions described above, meant as an exploration into a better way to write Scala, it allows writing Scala programs without braces. For example: |
| 209 | + |
| 210 | +```scala |
| 211 | +enum Day: |
| 212 | + case Monday, Tuesday, Wednesdey, Thursday, Friday, Saturday, Sunday |
| 213 | + def isWeekend: Boolean = this match |
| 214 | + case Saturday | Sunday => true |
| 215 | + case _ => false |
| 216 | + |
| 217 | +given as scala.util.FromString[Day]: |
| 218 | + def fromString(str: String): Day = |
| 219 | + try Day.valueOf(str) |
| 220 | + catch |
| 221 | + case _: IllegalArgumentException => |
| 222 | + throw new IllegalArgumentException(s"$str is not a valid day") |
| 223 | + |
| 224 | +@main def test(day: Day) = |
| 225 | + if day.isWeekend then |
| 226 | + println("Today is a weekend") |
| 227 | + println("I will rest") |
| 228 | + else |
| 229 | + println("Today is a workday") |
| 230 | + println("I will work") |
| 231 | +``` |
| 232 | + |
| 233 | +So far, it is a purely experimental effort. This means there is no final decision yet on whether or not it will be included in Scala 3. However, we treat this feature seriously enough to give it an extended period of trial and see if it is viable as the new look and feel for Scala. |
| 234 | + |
| 235 | +For more details and the discussion, see PRs [#7083](https://github.com/lampepfl/dotty/pull/7083) and [#7114](https://github.com/lampepfl/dotty/pull/7114). |
| 236 | + |
| 237 | +## Generic Number Literals |
| 238 | +It is now possible to seamlessly integrate with different number formats: that is, to write a number and get it automatically converted to your class of choice. E.g.: |
| 239 | + |
| 240 | +```scala |
| 241 | +import scala.util.FromDigits |
| 242 | + |
| 243 | +case class Digits(ds: List[Char]) |
| 244 | + |
| 245 | +given as FromDigits[Digits] = (digits: String) => Digits(digits.toList) |
| 246 | + |
| 247 | +@main def test = |
| 248 | + val x: Digits = 1234 |
| 249 | + println(x) // Digits(List('1', '2', '3', '4')) |
| 250 | +``` |
| 251 | + |
| 252 | +If a number is written in place where a non-numeric type is expected and there is an `FromDigits` given in scope, this given will be used to convert the number (presented as `String`) to that type. |
| 253 | + |
| 254 | +For precise rules, semantics and a larger example of `BigFloat`, see [the documentation](http://dotty.epfl.ch/docs/reference/changed-features/numeric-literals.html). |
| 255 | + |
| 256 | +## Metaprogramming Progress |
| 257 | +We are making steady progress with the language metaprogramming features. The metaprogramming spotlights of this release are as follows: |
| 258 | + |
| 259 | +- `toExprOfTuple` method which allows converting a `Seq[Expr[_]]` to `Expr[Tuple]`. The types of the expressions will be preserved in the tuple. See [#7037](https://github.com/lampepfl/dotty/pull/7037) and [#7076](https://github.com/lampepfl/dotty/pull/7076) for the details. |
| 260 | +- `toExprOfTuple` method that converts a tuple of expressions to an expression of tuple – see [#7047](https://github.com/lampepfl/dotty/pull/7047). |
| 261 | +- `toExprOfSeq` which converts an `Seq[Expr[A]]` to `Expr[Seq[A]]` – see [#6935](https://github.com/lampepfl/dotty/pull/6935). |
| 262 | +- More `Liftable` instances – for Tuples of arity greater than 22, `BigInt` and `BigDecimal` – see [#6947](https://github.com/lampepfl/dotty/pull/6947) and [#6944](https://github.com/lampepfl/dotty/pull/6944). |
| 263 | +- Leverage implicit lambdas to simplify `Liftable.toExpr` method – see [#6924](https://github.com/lampepfl/dotty/pull/6924) to learn how it is done. |
| 264 | +- Runtime staging `run` moved to `scala.quoted.staging` in [#7077](https://github.com/lampepfl/dotty/pull/7077). |
| 265 | +- Runtime staging factored out to a separate library in [#7080](https://github.com/lampepfl/dotty/pull/7080). |
| 266 | + |
| 267 | +## Type class Derivation |
| 268 | +Type class derivation has received a major rework and an [updated documentation](http://dotty.epfl.ch/docs/reference/contextual/derivation.html). We have dropped the usage of the `Shape` type to describe the shape of a type. Instead, all the relevant information is now encoded in the `Mirror` type and its subtypes as tuples. |
| 269 | + |
| 270 | +For more information, see the [documentation](http://dotty.epfl.ch/docs/reference/contextual/derivation.html). |
| 271 | + |
| 272 | +## Other |
| 273 | +- This release also features the new version of the SBT Dotty Plugin – 0.3.4. It contains some bug fixes – see [#7120](https://github.com/lampepfl/dotty/pull/7120) for details. |
| 274 | +- Scala Days 2019 talks related to Dotty are now [mentioned](http://dotty.epfl.ch/docs/resources/talks.html) at our website – this allows to systematize the knowledge about the next generation of Scala in one place – see [#6984](https://github.com/lampepfl/dotty/pull/6984). |
| 275 | +- ScalaJS needs your help! We would like to have robust support for ScalaJS in Dotty, which unfortunately is not the case so far. If you are interested in contributing, please see [the getting started tutorial](https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c) and [the discussion](https://github.com/lampepfl/dotty/issues/7113). |
| 276 | + |
| 277 | +# Let us know what you think! |
| 278 | + |
| 279 | +If you have questions or any sort of feedback, feel free to send us a message on our |
| 280 | +[Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please |
| 281 | +[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). |
| 282 | + |
| 283 | +## Contributing |
| 284 | + |
| 285 | +Thank you to all the contributors who made this release possible! |
| 286 | + |
| 287 | +According to `git shortlog -sn --no-merges 0.17.0-RC1..0.18.0-RC1` these are: |
| 288 | + |
| 289 | +``` |
| 290 | + 106 Nicolas Stucki |
| 291 | + 84 Martin Odersky |
| 292 | + 68 Guillaume Martres |
| 293 | + 26 Liu Fengyun |
| 294 | + 24 Jamie Thompson |
| 295 | + 23 Miles Sabin |
| 296 | + 16 Anatolii |
| 297 | + 8 Sébastien Doeraene |
| 298 | + 7 bishabosha |
| 299 | + 4 Aggelos Biboudis |
| 300 | + 4 Michał Gutowski |
| 301 | + 2 odersky |
| 302 | + 2 Nikolay |
| 303 | + 1 Master-Killer |
| 304 | + 1 Ashwin Bhaskar |
| 305 | + 1 Carlos Quiroz |
| 306 | + 1 = |
| 307 | + 1 Olivier Blanvillain |
| 308 | + 1 SrTobi |
| 309 | +``` |
| 310 | + |
| 311 | +If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! |
| 312 | +Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), |
| 313 | +and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). |
| 314 | +They make perfect entry points into hacking on the compiler. |
| 315 | + |
| 316 | +We are looking forward to having you join the team of contributors. |
| 317 | + |
| 318 | +## Library authors: Join our community build |
| 319 | + |
| 320 | +Dotty now has a set of widely-used community libraries that are built against every nightly Dotty |
| 321 | +snapshot. Currently, this includes ScalaPB, algebra, scalatest, scopt and squants. |
| 322 | +Join our [community build](https://github.com/lampepfl/dotty-community-build) |
| 323 | +to make sure that our regression suite includes your library. |
| 324 | + |
| 325 | +[Scastie]: https://scastie.scala-lang.org/?target=dotty |
| 326 | + |
| 327 | +[@odersky]: https://github.com/odersky |
| 328 | +[@DarkDimius]: https://github.com/DarkDimius |
| 329 | +[@smarter]: https://github.com/smarter |
| 330 | +[@felixmulder]: https://github.com/felixmulder |
| 331 | +[@nicolasstucki]: https://github.com/nicolasstucki |
| 332 | +[@liufengyun]: https://github.com/liufengyun |
| 333 | +[@OlivierBlanvillain]: https://github.com/OlivierBlanvillain |
| 334 | +[@biboudis]: https://github.com/biboudis |
| 335 | +[@allanrenucci]: https://github.com/allanrenucci |
| 336 | +[@Blaisorblade]: https://github.com/Blaisorblade |
| 337 | +[@Duhemm]: https://github.com/Duhemm |
| 338 | +[@AleksanderBG]: https://github.com/AleksanderBG |
| 339 | +[@milessabin]: https://github.com/milessabin |
| 340 | +[@anatoliykmetyuk]: https://github.com/anatoliykmetyuk |
0 commit comments