From 9ff6a34edaecda2a36d0e157c582ed0bf35caa76 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 3 May 2012 14:30:40 +0200 Subject: [PATCH 0001/2265] Pushing uncommitted footprint --- contribute/bug-reporting-guide.md | 4 ++ contribute/git-guide.md | 4 ++ contribute/index.md | 70 +++++++++++++++++++++++++++++++ contribute/partest-guide.md | 4 ++ contribute/workflow.md | 4 ++ 5 files changed, 86 insertions(+) create mode 100644 contribute/bug-reporting-guide.md create mode 100644 contribute/git-guide.md create mode 100644 contribute/index.md create mode 100644 contribute/partest-guide.md create mode 100644 contribute/workflow.md diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md new file mode 100644 index 0000000000..33640bcd47 --- /dev/null +++ b/contribute/bug-reporting-guide.md @@ -0,0 +1,4 @@ +--- +layout: page +title: Bug Reporting +--- \ No newline at end of file diff --git a/contribute/git-guide.md b/contribute/git-guide.md new file mode 100644 index 0000000000..a66fb33190 --- /dev/null +++ b/contribute/git-guide.md @@ -0,0 +1,4 @@ +--- +layout: page +title: Using git +--- \ No newline at end of file diff --git a/contribute/index.md b/contribute/index.md new file mode 100644 index 0000000000..b11a73bcbf --- /dev/null +++ b/contribute/index.md @@ -0,0 +1,70 @@ +--- +layout: page +title: Contribute +--- + +- This page should contain the introduction as mentioned in the Scala Doc team google document +- Subpages or subsections for contributing for each project (i.e. how to find tickets/features to work on) +- Building and contributing code (contributor's workflow) + - link to a proper git etiquette page + - link to CLA + - how to run and use partest + - compiler page (links to compiler-related docs i.e. reflection/macros/compiler-plugin guides, links to compiler internal videos, and useful info from wiki) (or should this go on docs.scala-lang?) +- Link to how to make a bug report + +The Scala programming langauge is an open source project from École +Polytechnique Fédérale de Lausanne (EPFL) in Switzerland. The source of the +compiler and libraries is hosted on [github](http://github.com/scala/scala). + +Some aspects of the language are easier to contribute to than others-- the +compiler, for example, is arguably the most difficult part of the Scala +project to successfully submit patches to. + +If you're interested in joining our community and contributing to the project, +start simple-- often Scaladoc (Scala's javadoc-like tool, Example: [Scala +Standard Library API](www.scala-lang.org/api/current/index.html#package)) is +the best place to get started. + + + EPFL Typesafe Stack + _______________ ___________ + | | | | + | stdlib | | Akka | + | compiler | | Play! | + | scaladoc | | SBT | + | documentation | | .... | + |_______________| |___________| + + +## Testing + +Partest how-tos. + +### Lukas's new build machine + +Link, needs repo name and github username and builds/tests for you. + +## Community tickets + +- for scaladoc +- for the stdlib +- for the compiler +- for the doc site + +## Process + +"gitting stuff done" document. + +Where to ask questions. How-tos to mailing list, discussion pertaining to a +specific ticket on the issue tracker. + +## CLA + +## FAQ + +### OSX + +### Linux + +### Windows + diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md new file mode 100644 index 0000000000..1b3c098cca --- /dev/null +++ b/contribute/partest-guide.md @@ -0,0 +1,4 @@ +--- +layout: page +title: Running the Test Suite +--- \ No newline at end of file diff --git a/contribute/workflow.md b/contribute/workflow.md new file mode 100644 index 0000000000..89c71102a9 --- /dev/null +++ b/contribute/workflow.md @@ -0,0 +1,4 @@ +--- +layout: page +title: Contributor's Workflow +--- \ No newline at end of file From fc99948bd01ccad7310366e17a16d3a75b4a3c94 Mon Sep 17 00:00:00 2001 From: ingoem Date: Thu, 27 Sep 2012 11:45:57 +0200 Subject: [PATCH 0002/2265] Some work on the contribute section --- contribute/git-guide.md | 76 ++++++++++++++++++++++++++++++++++++++++- contribute/index.md | 61 +++++++++++++++++++++++++++++---- 2 files changed, 130 insertions(+), 7 deletions(-) diff --git a/contribute/git-guide.md b/contribute/git-guide.md index a66fb33190..2e173ec7ec 100644 --- a/contribute/git-guide.md +++ b/contribute/git-guide.md @@ -1,4 +1,78 @@ --- layout: page title: Using git ---- \ No newline at end of file +--- + +This is a step-by-step guide on how to use [git](http://git-scm.com/) and [github](http://github.com/) if you want to contribute to the Scala project. If you are new to git, make yourself familiar first. We recommend the [Git Pro]()http://git-scm.com/book/en/) online book. + +### Signup + +First create an account on [github](http://github.com/). You can also use your existing account, of course. + +### Fork + +Now, go to [https://github.com/scala/scala]() and click the "Fork" button at the top of the page. + +![image](images/fork.png) + +If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` is your github user name. Make sure you read [http://help.github.com/fork-a-repo/](), which covers some of the things that will follow below. + +### Clone + +Clone your repository. Run the following on the command line: + + $ git clone https://github.com/username/scala + +This will create a local directory called `scala`, which contains a clone of the remote repository. + +### Branch + +Before you start making changes, always create your own branch. Never work on the `master` branch. Think of a name that describes the changes you plan on doing. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. + + - For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). + - For a new feature use `topic/XXX` for feature XXX. + +Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaldoc-diagrams` instead of just `topic/diagrams`. + +For your initial contribution, try work on something manageable (TODO: link to the subproject overview page). + +Now, it's time to create your branch. Run the following on the command line + + $ git checkout -b topic/XXX + +If you are new to git and branching, please read the [Branching Chapter](http://git-scm.com/book/en/Git-Branching) in the Git Pro book. + +### Change + +Now, you are ready to make changes ot the code base. The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. + +TODO: refer to other development stuff, partest and so on. + +### Sync and Rebase + +Before you can submit your patch, make sure that your commit structure is clean. We won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so your commits are against the latest revision of `master`. + +Occassionally, you also want to sync with `master` so you don't fall behind too much. Otherwise, creating a clean pull request can become a lot of work. It is often a good idea to use `git rebase` instead of `git merge` to stay on top of `master` and keep a linear commit structure (TODO: do we actually REQUIRE this???). Read more about this approach [here](http://git-scm.com/book/en/Git-Branching-Rebasing). + +### Push + +For now, you might have committed your changes only locally (or maybe you have pushed your changes already to your fork on github because you want others to see it). Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. First, make sure you have pushed all of your local changes to your fork on github. + + $ git push username + # This pushes all of your local branches to your fork on github. + +Again, `username` stands for your github user name. + +### Submit pull request + +Now it's time to send your changes to the Scala project for review. To do so, you ask for your changes to be pulled into the main repository by submitting a pull request. Go to your own Scala project page at `https://github.com/username/scala` and switch to the branch that contains your changes. + +![image](images/switchbranch.png) + +Then click on the "Pull Request" button at the top. + +![image](images/pullrequest.png) + +The github help page at [http://help.github.com/send-pull-requests/]() covers sending pull requests in more detail. Make sure you submit your request against the right branch. Strictly follow our [Pull Request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). + +A pull request is rarely accepted right away, so don't be depressed if the reviewer of your pull request will reject it or asks you to make additional changes before your request can be eventually accepted into the main repository. diff --git a/contribute/index.md b/contribute/index.md index b11a73bcbf..9f90154c85 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -26,6 +26,14 @@ Standard Library API](www.scala-lang.org/api/current/index.html#package)) is the best place to get started. +## Overview of the Scala Ecosystem + +TODO: I feel this section belongs somewhere else and should be linked here. + +[Scala Project](http://scala-lang.org) + +[Typesafe Stack](http://typesafe.com/stack) + EPFL Typesafe Stack _______________ ___________ | | | | @@ -34,21 +42,42 @@ the best place to get started. | scaladoc | | SBT | | documentation | | .... | |_______________| |___________| + + + +## Basic Workflow + +The Scala project, including the compiler, standard library and Scaladoc is hosted on [https://github.com/scala/scala](). As usual on github, developers work in personal forks that are merged into the main repository via pull request after having successfully completed a review process. As a contributor, your basic workflow is as follows: + + 1. [Fork](https://help.github.com/articles/fork-a-repo) the [Scala Project](https://github.com/scala/scala) + - Create a [topic branch](http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches) + - Fix a [bug](https://issues.scala-lang.org/secure/IssueNavigator.jspa?reset=true&jqlQuery=labels+%3D+community), implement a feature + - Push your changes to your fork on github + - Submit [pull request](https://help.github.com/articles/using-pull-requests) + - Work with a reviewer on [getting your request merged](https://github.com/scala/scala/wiki/Pull-Request-Policy) + - Celebrate! +Read our [Git Commit Guide](git-guide.html) for details. + +## Building + +The Scala compiler and libraries are built using Ant. Read the [README](https://github.com/scala/scala/blob/master/README.rst) on how to build, test and create a distribution. ## Testing -Partest how-tos. +We maintain an extensive test suite that is run via our parallel testing tool `partest`. Read our [Partest Guide](partest-guide.html) for details. ### Lukas's new build machine Link, needs repo name and github username and builds/tests for you. -## Community tickets +## What to work on -- for scaladoc -- for the stdlib -- for the compiler +If you want to become a contributor but you don't know what to work on, here are a few ideas. Generally, it is a good idea to start with fixing bugs! To get some idea, head over to our [Scala issue tracker](https://issues.scala-lang.org/) and search for some unresolved bugs assigned to the community or click [here](https://issues.scala-lang.org/secure/IssueNavigator.jspa?reset=true&jqlQuery=labels+%3D+community) for a direct link. Here is a breakdown into different subprojects: + + - [Scaladoc](https://issues.scala-lang.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=labels+%3D+scaladoc+and+labels+%3D+community&runQuery=true&clear=true) +- [Standard Library](https://issues.scala-lang.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=labels+%3D+community+and+labels+%3D+library&runQuery=true&clear=true) +- [Compiler](https://issues.scala-lang.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=labels+%3D+community+and+labels+%3D+compiler&runQuery=true&clear=true) - for the doc site ## Process @@ -58,8 +87,28 @@ Link, needs repo name and github username and builds/tests for you. Where to ask questions. How-tos to mailing list, discussion pertaining to a specific ticket on the issue tracker. -## CLA +## Contributor's License Agreement + +Before we can accept your pull request you have to sign our Contributor's License Agreement (CLA). + +TODO: Heather + +## Compiler Internals + +The files below are recordings of code walk-through sessions by Martin Odersky about the Scala compiler internals. Some of the information is somewhat outdated, but the clips are still a good introduction to some parts of the compiler architecture. + - [Scala Internals 2008-10-29 (Symbols 1)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2008-10-29.avi) + + Handling of Symbols in the Scala compiler: some details on the symtab subdir, Symbols, Definitions, StdNames, Types (Lazy Types). + + - [Scala Internals 2008-11-05 (Symbols 2)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2008-11-05.avi) + + Handling of Symbols part deux: more information on Symbols, Flags, Definitions. + + - [Scala Internals 2009-03-04 (Types)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2009-03-04.avi) + + A detailed explanation about how types are represented and manipulated within the Scala compiler: data structures, manipulations of types, coding conventions (audio is not perfect, but intelligible). + ## FAQ ### OSX From 02337f4add685cbe0155d8e7e0f12ea29e536aaa Mon Sep 17 00:00:00 2001 From: ingoem Date: Thu, 27 Sep 2012 16:42:23 +0200 Subject: [PATCH 0003/2265] Add partest guide --- contribute/partest-guide.md | 64 ++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index 1b3c098cca..e681c569fe 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -1,4 +1,66 @@ --- layout: page title: Running the Test Suite ---- \ No newline at end of file +--- + +Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go the scala project folder from your local checkout and run it via `ant` or standalone as follows. + +## Using ant + +The test suite can be run by using ant from the command line: + + $ ant test.suite + +## Standalone + +There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use + + ./test/partest --show-diff --show-log --failed + +You can get a summary of the usage by running partest without arguments. + +* Most commonly you want to invoke partest with an option that tells it which part of the tests to run. For example `--all`, `--pos`, `--neg` or `--run`. +* You can test individual files by specifying individual test files (`.scala` files) as options. Several files can be tested if they are from the same category, e.g., `pos`. +* You can enable output of log and diff using the `-show-log` and `-show-diff` options. +* If you get into real trouble, and want to find out what partest does, you can run it with option `--verbose`. This info is useful as part of bug reports. +* Set custom path from where to load classes: `-classpath ` and `-buildpath `. +* You can use the `SCALAC_OPTS` environment variable to pass command line options to the compiler. +* You can use the `JAVA_OPTS` environment variable to pass command line options to the runner (e.g., for `run/jvm` tests). +* The launch scripts run partest as follows: + + scala -cp scala.tools.partest.nest.NestRunner + + Partest classes from a `quick` build, e.g., can be found in `./build/quick/classes/partest/`. + + Partest will tell you where it loads compiler/library classes from by adding the `partest.debug` property: + + scala -Dpartest.debug=true -cp scala.tools.partest.nest.NestRunner + + + +## ScalaCheck tests + +Tests that depend on [ScalaCheck](https://github.com/rickynils/scalacheck) can be added under folder `./test/files/scalacheck`. A sample test: + + import org.scalacheck._ + import Prop._ + + object Test { + val prop_ConcatLists = property{ (l1: ListInt, l2: ListInt) => + l1.size + l2.size == (l1 ::: l2).size + } + + val tests = List(("prop_ConcatLists", prop_ConcatLists)) + } + +## Troubleshooting + +### Windows + +Some tests might fail because line endings in the `.check` files and the produced results do not match. In that case, set either + + git config core.autocrlf false + +or + + git config core.autocrlf input \ No newline at end of file From 9ea42c156a8025f1a5d436d390586eca4422a33e Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 1 Mar 2013 16:41:26 +0100 Subject: [PATCH 0004/2265] first 1.5 steps of the hacker guide --- contribute/01-post.png | Bin 0 -> 172693 bytes contribute/03-fork.png | Bin 0 -> 46172 bytes contribute/hacker-guide.md | 106 +++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 contribute/01-post.png create mode 100644 contribute/03-fork.png create mode 100644 contribute/hacker-guide.md diff --git a/contribute/01-post.png b/contribute/01-post.png new file mode 100644 index 0000000000000000000000000000000000000000..cef3dcaa46d8d4206f3b601ff7157c127d7eb55a GIT binary patch literal 172693 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 V{he5NlyEMeCkpEFC9+1o{{!U6U)2Br literal 0 HcmV?d00001 diff --git a/contribute/03-fork.png b/contribute/03-fork.png new file mode 100644 index 0000000000000000000000000000000000000000..abf86df0199e4d59dc27bbf4d0c2e93d976f1a66 GIT binary patch literal 46172 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 Date: Fri, 1 Mar 2013 18:26:56 +0100 Subject: [PATCH 0005/2265] "Contribute" landing page and sketches for two pages: - bug reporting - documentation contributions --- contribute/bug-reporting-guide.md | 53 ++++++++++++++++- contribute/documentation.md | 29 ++++++++++ contribute/index.md | 94 +++++++++++++++++++++++-------- contribute/scala-fame.md | 9 +++ 4 files changed, 162 insertions(+), 23 deletions(-) create mode 100644 contribute/documentation.md create mode 100644 contribute/scala-fame.md diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 33640bcd47..a60fb15b07 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -1,4 +1,55 @@ --- layout: page title: Bug Reporting ---- \ No newline at end of file +--- + +# Reporting bugs to the Scala project + +The Scala project tracker is located at: + +> [http://issues.scala-lang.org](http://issues.scala-lang.org) + + + diff --git a/contribute/documentation.md b/contribute/documentation.md new file mode 100644 index 0000000000..05b2455a5f --- /dev/null +++ b/contribute/documentation.md @@ -0,0 +1,29 @@ +--- +layout: page +title: Documentation Contributions +--- +# Contributing documentation to the Scala project + +TODO + + diff --git a/contribute/index.md b/contribute/index.md index 9f90154c85..a92c5f37cc 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -2,8 +2,66 @@ layout: page title: Contribute --- +# Contributing to the Scala project + +The Scala programming langauge is an open source project with a very +diverse community, where people from all over the world contribute their work, +with everyone benefitting from friendly help and advice, and +kindly helping others in return. So why not join the Scala community and help +everyone make things better? + +The following are typical questions you might ask when first contributing to Scala. +If you have other questions not addressed here, feel free to ask on the [scala-internals mailing list](http://groups.google.com/group/scala-internals). + +
+ +### I found something that doesn't work as expected. How to file a bug report? + +[The reporting bugs page](bug-reporting-guide.html) describes the steps to take when you find something that doesn't work +as expected. Filing in a good bug report increases the chances the ticket is fixed quickly. + +
+ +### Why contribute a patch to Scala? + +Just to name a few common reasons: + - contributing a patch is the best way to make sure your desired changes will be available in the next Scala version + - Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu + - last but not least, you will make it into the [Scala Contribuitor Hall of Fame](scala-fame.html). + +
+ +### I'd like to start hacking the Scala project, how to find something to work on? + +Depending on your skillset, you may want to contribute documentation and/or code. Documentation has always been very +appreciated work in the Scala community, as most code contributions tend to be quite scarce in explanations of how +things work and how everyone else is supposed to use them. To contribute documentation, have a look at the +[documentation page](documentation.html). + +The main Scala project consists of the standard Scala library, the Scala reflection and macros library, +the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. +Typically the scaladoc tool provides a low entry point for new committers, so it is a good first step into contributing. + +On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. + +
+ +### I have this idea that I'd like to add to Scala, how do I start? + +The first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea +and on the implementation plan. Starting point ("community") bugs are usually uncontroversial, so you can jump right +ahead to hacking the scala source tree and filing a pull request. For larger changes it is best to announce the change +on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list. + +Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against +the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. + +
+ + \ No newline at end of file diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md new file mode 100644 index 0000000000..75317be820 --- /dev/null +++ b/contribute/scala-fame.md @@ -0,0 +1,9 @@ +--- +layout: page +title: Scala Contribuitor Hall of Fame +--- +# Scala Hall of Fame + +A big thank you to everyone who contributed to: + - [the Scala library and compiler](https://github.com/scala/scala/contributors) + - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) \ No newline at end of file From b09e5f106986a3fafdd42d5ad0ae0f61982b58a5 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 1 Mar 2013 18:29:10 +0100 Subject: [PATCH 0006/2265] 1.5 more sections --- contribute/02-post.png | Bin 0 -> 114529 bytes contribute/hacker-guide.md | 153 ++++++++++++++++++++++++++++++++----- 2 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 contribute/02-post.png diff --git a/contribute/02-post.png b/contribute/02-post.png new file mode 100644 index 0000000000000000000000000000000000000000..533ac99538d153d433129e59513a708d02fcc429 GIT binary patch literal 114529 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 Date: Fri, 1 Mar 2013 19:57:46 +0100 Subject: [PATCH 0007/2265] tentative fin --- contribute/04-submit.png | Bin 0 -> 166407 bytes contribute/05-review.png | Bin 0 -> 29682 bytes contribute/hacker-guide.md | 116 ++++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 contribute/04-submit.png create mode 100644 contribute/05-review.png diff --git a/contribute/04-submit.png b/contribute/04-submit.png new file mode 100644 index 0000000000000000000000000000000000000000..80acc36cf93e380c7257203ba879ef1636c82641 GIT binary patch literal 166407 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

f?AQ{Dupipdlg;C}}=T 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

5V-fPj1J=6v-5Ui*9vLJ^IReprT1O{yZE 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 z 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 BSkM3f literal 0 HcmV?d00001 diff --git a/contribute/05-review.png b/contribute/05-review.png new file mode 100644 index 0000000000000000000000000000000000000000..330cb519ac2c6945b9e480262568025fe49b7c1f GIT binary patch literal 29682 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 literal 0 HcmV?d00001 diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 298ac6a307..9805ad8795 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -136,8 +136,6 @@ with your hardware). [exec] Resolving [943cd5c8802b2a3a64a010efb86ec19bac142e40/lib/ant/ant-contrib.jar] ... - ... - ... pack.bin: [mkdir] Created dir: /Users/xeno_by/Projects/scala/build/pack/bin @@ -188,6 +186,7 @@ reproducible by throwing together a simple test and feeding it into the Scala di } 17:27 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala 17:28 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test + 1%n1 ### Implement ### @@ -219,5 +218,118 @@ exclusively as a folklore. However the situation is steadily improving. Here are * [scala-internals](http://groups.google.com/group/scala-internals), a mailing list which hosts discussions about the core internal design and implementation of the Scala system. +### Interlude ### + +To fix [the bug I'm interested in](https://issues.scala-lang.org/browse/SI-6725) I've tracked the `StringContext.f` interpolator +down to a macro implemented in `MacroImplementations.scala`. There I noticed that the interpolator only processes conversions, +but not tokens like `%n`. Looks like an easy fix. + + 18:44 ~/Projects/scala/sandbox (ticket/6725)$ git diff + diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/ + index 002a3fce82..4e8f02084d 100644 + --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala + +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala + @@ -117,7 +117,8 @@ abstract class MacroImplementations { + if (!strIsEmpty) { + val len = str.length + while (idx < len) { + - if (str(idx) == '%') { + + def notPercentN = str(idx) != '%' || (idx + 1 < len && str(idx + 1) != 'n') + + if (str(idx) == '%' && notPercentN) { + bldr append (str substring (start, idx)) append "%%" + start = idx + 1 + } + +After I applied the fix and running `ant`, my simple test case in `sandbox/Test.scala` started working! + + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ cd .. + 18:51 ~/Projects/scala (ticket/6725)$ ant + Buildfile: /Users/xeno_by/Projects/scala/build.xml + + ... + + quick.comp: + [scalacfork] Compiling 1 file to /Users/xeno_by/Projects/scala/build/quick/classes/compiler + [propertyfile] Updating property file: /Users/xeno_by/Projects/scala/build/quick/classes/compiler/compiler.properties + [stopwatch] [quick.comp.timer: 6.588 sec] + + ... + + BUILD SUCCESSFUL + Total time: 18 seconds + + 18:51 ~/Projects/scala (ticket/6725)$ cd sandbox + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test + 1 + 1 + ### Verify ### +Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. +Read up [the partest guide](/contribute/partest-guide.html) to learn the details about partest, but in a nutshell you can either +run `ant test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: + + 18:52 ~/Projects/scala/sandbox (ticket/6725)$ cd ../test + 18:56 ~/Projects/scala/test (ticket/6725)$ partest files/run/*interpol* + Testing individual files + testing: [...]/files/run/interpolationArgs.scala [ OK ] + testing: [...]/files/run/interpolationMultiline1.scala [ OK ] + testing: [...]/files/run/interpolationMultiline2.scala [ OK ] + testing: [...]/files/run/sm-interpolator.scala [ OK ] + testing: [...]/files/run/interpolation.scala [ OK ] + testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] + All of 6 tests were successful (elapsed time: 00:00:08) + +### 4. Publish ### + +After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. +In a nutshell this involves: 1) making sure that your code and commit messages are of high quality, 2) clicking a few buttons in the +Github interface, 3) assigning one or more reviewers which will look through your pull request. Now all that in more details. + +### Commit ### + +The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. +There are two things you should know here: + +1) Commit messages are frequently the only way to communicate with the authors of the code written a few years ago. Therefore, we give them +big importance. Be creative and eloquent - the more context your provide about the change you've introduced, the bigger the probability that +some future maintainer will understand you right. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) +for more information about the desired style of your commits. + +2) Clean history is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. +For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, +you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so your commits are against +the latest revision of `master`. + +Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. + + 19:22 ~/Projects/scala/test (ticket/6725)$ git add ../src/compiler/scala/tools/reflect/MacroImplementations.scala + 19:22 ~/Projects/scala/test (ticket/6725)$ git commit + [ticket/6725 3c3098693b] SI-6725 `f` interpolator now supports %n tokens + 1 file changed, 2 insertions(+), 1 deletion(-) + 19:34 ~/Projects/scala/test (ticket/6725)$ git push origin ticket/6725 + Username for 'https://github.com': xeno-by + Password for 'https://xeno-by@github.com': + Counting objects: 15, done. + Delta compression using up to 8 threads. + Compressing objects: 100% (8/8), done. + Writing objects: 100% (8/8), 1.00 KiB, done. + Total 8 (delta 5), reused 0 (delta 0) + To https://github.com/xeno-by/scala + * [new branch] ticket/6725 -> ticket/6725 + +### Submit ### + +This part is very easy and enjoyable. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) +and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will +need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. + +![Submit a pull request](/contribute/04-submit.png) + +### Discuss ### + +After the pull request has been submitted, you need to pick a reviewer (probably, the person you've contacted in the beginning of your +workflow) and be ready to elaborate and adjust your patch if necessary. I picked Martin, because we had such a nice chat on the mailing list: + +![Assign the reviewer](/contribute/05-review.png) From a541a62b5602dcd4aea855867ad3f03b7c1d65d3 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 1 Mar 2013 20:18:15 +0100 Subject: [PATCH 0008/2265] polishing the hacker guide --- contribute/hacker-guide.md | 62 ++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 9805ad8795..f5a4f8724e 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -10,12 +10,15 @@ to a nightly and, ultimately, to a production release of Scala incorporating you influence a programming language of your choice is amazing, and I'm excited to demonstrate that it's easier than one might think. +### The running example ### + I like string interpolation a lot. Doing debug prints with interpolators introduced in Scala 2.10.0 is so enjoyable that I often wonder how we ever lived without that feature. However there's an annoying issue which I occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) new line tokens `%n`. I could go the mailing list, ask to fix this bug and then indefinitely wait for the fix. Or I could instead patch Scala myself and get the fix in a subsequent release (nightly builds get produced, well, every -night, minor releases are pumped every few months and major releases happen once a year). Let's get to work! +night, minor releases are pumped every few months and major releases happen once a year). The latter option sounds cool, so let's see +how it works! ### 1. Connect ### @@ -47,7 +50,7 @@ list of people (Github usernames and real-life names) and their specialties: documentation: @heathermiller (Heather Miller) cps: @TiarkRompf (Tiark Rompf) -Martin is the one who submitted the string interpolation proposal and implemented this language features for Scala 2.10.0. +Martin is the one who submitted the string interpolation proposal and implemented this language feature for Scala 2.10.0. (TODO: how to choose a mailing list) Therefore now I'm going to [the scala-user mailing list](http://groups.google.com/group/scala-user) and will post a topic about my issue. Note that I put Martin in the cc list of the email. If I didn't do that, he would probably miss it in a bunch @@ -57,19 +60,19 @@ of emails, which get posted to scala-user every day. ![Response from Martin](/contribute/02-post.png) -Now when I have an approval of the feature's author, it makes sense to start doing something. +Now when I have the approval of the feature's author, I'll get to work! ### 2. Set up ### -Hacking Scala begins with creating a branch for your work item. In our workflow we use [Git](http://git-scm.com/) -and [GitHub](http://github.com/). This section of the guide provides a short walkthrough on how to use them. -If you are new to Git, it might make sense to familiarize with it first. We recommend the [Git Pro](http://git-scm.com/book/en/) +Hacking Scala begins with creating a branch for your work item. To develop Scala we use [Git](http://git-scm.com/) +and [GitHub](http://github.com/). This section of the guide provides a short walkthrough, but if you are new to Git, +it probably makes sense to familiarize with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) online book. ### Fork ### Log into [GitHub](http://github.com/), go to [https://github.com/scala/scala](https://github.com/scala/scala) and click the `Fork` -button at the top of the page. This will create your own copy of our repository that will serve as a scratchpad for your experiments. +button at the top of the page. This will create your own copy of our repository that will serve as a scratchpad for your hackings. If you're new to Git, don't be afraid of messing it up - there is no way you can corrupt our repository. ![Fork scala/scala](/contribute/03-fork.png) @@ -113,13 +116,13 @@ The next step after cloning your fork is setting up your machine to build Scala. [https://github.com/scala/scala/blob/master/README.rst](https://github.com/scala/scala/blob/master/README.rst), but here's the summary: * It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). -* The build tool we use is `ant`. -* The build script runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. -* The majority of our team works on Linux and OS X. +* The build tool is `ant`. +* The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. +* The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. * Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter them. -In a nutshell, build Scala is as easy as running `ant` in the root of your clone. Be prepared to wait for a while - a full rebuild -takes 7+ minutes depending on your machine. Incremental builds are usually within 30-90 seconds range (again, your mileage might vary +In a nutshell, building Scala is as easy as running `ant` in the root of your clone. Be prepared to wait for a while - a full rebuild +takes 8+ minutes depending on your machine. Incremental builds are usually within 30-120 seconds range (again, your mileage might vary with your hardware). 16:50 ~/Projects/scala (ticket/6725)$ ant @@ -149,7 +152,7 @@ with your hardware). ### IDE ### -There's no single editor of choice to work with Scala sources, as there are trade-offs imposed by each available option. +There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. Both Eclipse and Intellij IDEA have Scala plugins, which are known to work with our codebase. Here are [instructions for Eclipse](https://github.com/scala/scala/blob/master/src/eclipse/README.md) and @@ -158,7 +161,7 @@ navigation, refactoring and error reporting functionality as well as integrated of occasional sluggishness. On the other hand, lightweight editors such as Emacs, Sublime or jEdit provide unparalleled scriptability and performance, while -lacking semantic services and debugging. To address this shortcoming, one can integrate with ENSIME, +lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite having significantly matured over the last year, its support for our particular codebase is still far from being great. @@ -168,12 +171,13 @@ Therefore it's hard to recommend a particular tool here, and your choice should ### 3. Hack ### When hacking on your topic of choice, you'll be modifying Scala, compiling it and testing it on relevant input files. -Typically you would want to first make sure that your changes work on a few small example and afterwards verify that nothing break -by running the comprehensive test suite. +Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break +by running a comprehensive test suite. I'm going to start by creating a `sandbox` directory (this particular name doesn't bear any special meaning - it's just a tribute to -my first days in Scala team), which will hold a single test file and its compilation results. First I make sure that the bug is indeed -reproducible by throwing together a simple test and feeding it into the Scala distribution assembled by ant in `build/pack/bin`. +my first days in Scala team), which will hold a single test file and its compilation results. First I make sure that +[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by throwing together a simple test and feeding it +into the Scala distribution assembled by ant in `build/pack/bin`. 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox @@ -186,7 +190,7 @@ reproducible by throwing together a simple test and feeding it into the Scala di } 17:27 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala 17:28 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test - 1%n1 + 1%n1 // %n should've been replaced by a newline here ### Implement ### @@ -198,17 +202,17 @@ Here are also some tips & tricks that have proven useful in Scala development: try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile just that trait, but it might also be necessary to recompile its users. Ant is not smart enough to do that, which might lead to very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take significant time. -* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. There are quite a few - people in our team, who do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. +* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, + some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's useful to print stack traces to understand the flow of execution. + to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. -Docs. Right, the docs. The documentation about internal workings of the compiler is scarce, and a lot of knowledge gets passed -exclusively as a folklore. However the situation is steadily improving. Here are the resources that might help: +Docs. Right, the docs. The documentation about internal workings of the compiler is scarce, and most of the knowledge is passed around +in the form of folklore. However the situation is steadily improving. Here are the resources that might help: * [Compiler internals videos by Martin Odersky](TODO) are quite dated, but still very useful. In this three-video - series Martin explains inner working of the part of the compiler, which has recently become Scala reflection API. + series Martin explains inner workings of the part of the compiler, which has recently become Scala reflection API. * [Reflection and Compilers by Martin Odersky](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the reflection API. * [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures that @@ -262,7 +266,7 @@ After I applied the fix and running `ant`, my simple test case in `sandbox/Test. 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test 1 - 1 + 1 // no longer getting the %n here - it got transformed into a newline ### Verify ### @@ -293,13 +297,13 @@ The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git onlin There are two things you should know here: 1) Commit messages are frequently the only way to communicate with the authors of the code written a few years ago. Therefore, we give them -big importance. Be creative and eloquent - the more context your provide about the change you've introduced, the bigger the probability that -some future maintainer will understand you right. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) +big importance. Be creative and eloquent - the more context your provide for the change you've introduced, the bigger the probability that +some future maintainer will get you right. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. 2) Clean history is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, -you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so your commits are against +you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. From edc6f1520130fe52496f48109bf2fd2a1eb4fdb3 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 1 Mar 2013 20:19:06 +0100 Subject: [PATCH 0009/2265] removes the git guide - it's been subsumed by the hacker's guide --- contribute/git-guide.md | 78 ----------------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 contribute/git-guide.md diff --git a/contribute/git-guide.md b/contribute/git-guide.md deleted file mode 100644 index 2e173ec7ec..0000000000 --- a/contribute/git-guide.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -layout: page -title: Using git ---- - -This is a step-by-step guide on how to use [git](http://git-scm.com/) and [github](http://github.com/) if you want to contribute to the Scala project. If you are new to git, make yourself familiar first. We recommend the [Git Pro]()http://git-scm.com/book/en/) online book. - -### Signup - -First create an account on [github](http://github.com/). You can also use your existing account, of course. - -### Fork - -Now, go to [https://github.com/scala/scala]() and click the "Fork" button at the top of the page. - -![image](images/fork.png) - -If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` is your github user name. Make sure you read [http://help.github.com/fork-a-repo/](), which covers some of the things that will follow below. - -### Clone - -Clone your repository. Run the following on the command line: - - $ git clone https://github.com/username/scala - -This will create a local directory called `scala`, which contains a clone of the remote repository. - -### Branch - -Before you start making changes, always create your own branch. Never work on the `master` branch. Think of a name that describes the changes you plan on doing. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. - - - For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). - - For a new feature use `topic/XXX` for feature XXX. - -Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaldoc-diagrams` instead of just `topic/diagrams`. - -For your initial contribution, try work on something manageable (TODO: link to the subproject overview page). - -Now, it's time to create your branch. Run the following on the command line - - $ git checkout -b topic/XXX - -If you are new to git and branching, please read the [Branching Chapter](http://git-scm.com/book/en/Git-Branching) in the Git Pro book. - -### Change - -Now, you are ready to make changes ot the code base. The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. - -TODO: refer to other development stuff, partest and so on. - -### Sync and Rebase - -Before you can submit your patch, make sure that your commit structure is clean. We won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so your commits are against the latest revision of `master`. - -Occassionally, you also want to sync with `master` so you don't fall behind too much. Otherwise, creating a clean pull request can become a lot of work. It is often a good idea to use `git rebase` instead of `git merge` to stay on top of `master` and keep a linear commit structure (TODO: do we actually REQUIRE this???). Read more about this approach [here](http://git-scm.com/book/en/Git-Branching-Rebasing). - -### Push - -For now, you might have committed your changes only locally (or maybe you have pushed your changes already to your fork on github because you want others to see it). Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. First, make sure you have pushed all of your local changes to your fork on github. - - $ git push username - # This pushes all of your local branches to your fork on github. - -Again, `username` stands for your github user name. - -### Submit pull request - -Now it's time to send your changes to the Scala project for review. To do so, you ask for your changes to be pulled into the main repository by submitting a pull request. Go to your own Scala project page at `https://github.com/username/scala` and switch to the branch that contains your changes. - -![image](images/switchbranch.png) - -Then click on the "Pull Request" button at the top. - -![image](images/pullrequest.png) - -The github help page at [http://help.github.com/send-pull-requests/]() covers sending pull requests in more detail. Make sure you submit your request against the right branch. Strictly follow our [Pull Request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). - -A pull request is rarely accepted right away, so don't be depressed if the reviewer of your pull request will reject it or asks you to make additional changes before your request can be eventually accepted into the main repository. From ca55cb4757fa02c89bdd469ca4a66a0b2476b5a1 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 1 Mar 2013 20:20:17 +0100 Subject: [PATCH 0010/2265] removes the workflow page - it's been subsumed by the hacker's guide --- contribute/workflow.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 contribute/workflow.md diff --git a/contribute/workflow.md b/contribute/workflow.md deleted file mode 100644 index 89c71102a9..0000000000 --- a/contribute/workflow.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -layout: page -title: Contributor's Workflow ---- \ No newline at end of file From de59612fefb92a5e76c50594070e5d1cb297387e Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Sun, 3 Mar 2013 14:06:49 +0100 Subject: [PATCH 0011/2265] Fixing issues with images, formatting fixups, moving maintainers list into an include for future reuse --- contribute/01-post.png | Bin 172693 -> 0 bytes contribute/02-post.png | Bin 114529 -> 0 bytes contribute/03-fork.png | Bin 46172 -> 0 bytes contribute/04-submit.png | Bin 166407 -> 0 bytes contribute/05-review.png | Bin 29682 -> 0 bytes contribute/hacker-guide.md | 32 ++++++++------------------------ 6 files changed, 8 insertions(+), 24 deletions(-) delete mode 100644 contribute/01-post.png delete mode 100644 contribute/02-post.png delete mode 100644 contribute/03-fork.png delete mode 100644 contribute/04-submit.png delete mode 100644 contribute/05-review.png diff --git a/contribute/01-post.png b/contribute/01-post.png deleted file mode 100644 index cef3dcaa46d8d4206f3b601ff7157c127d7eb55a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172693 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 V{he5NlyEMeCkpEFC9+1o{{!U6U)2Br diff --git a/contribute/02-post.png b/contribute/02-post.png deleted file mode 100644 index 533ac99538d153d433129e59513a708d02fcc429..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114529 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

f?AQ{Dupipdlg;C}}=T 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

5V-fPj1J=6v-5Ui*9vLJ^IReprT1O{yZE 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 z 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 BSkM3f diff --git a/contribute/05-review.png b/contribute/05-review.png deleted file mode 100644 index 330cb519ac2c6945b9e480262568025fe49b7c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29682 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 diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index f5a4f8724e..52bb75dd37 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -31,24 +31,7 @@ about things you want to implement. People proficient is certain areas of Scala by simply posting a message. But the most efficient way to connect is to cc your message to one of the go-to persons in your area. Here's the list of people (Github usernames and real-life names) and their specialties: - library: @phaller (Philipp Haller), @axel22 (Aleksandar Prokopec -- concurrent & collection) - specialisation: @axel22 (Aleksander Prokopec), @vladureche (Vlad Ureche), @dragos (Iulian Dragos) - named / default args, annotations, plugins: @lrytz (Lukas Rytz) - macros, reflection, manifests, type tags: @xeno-by (Eugene Burmako), @cvogt (Christopher Vogt) - type checker, inference: @odersky (Martin Odersky), @adriaanm (Adriaan Moors) - language specification, string interpolation, value classes: @odersky (Martin Odersky) - new pattern matcher, implicit search: @adriaanm (Adriaan Moors) - partest, Continuations Plugin: @phaller (Philipp Haller) - error handling, lazy vals: @hubertp (Hubert Plociniczak) - backend: @magarciaEPFL (Miguel Garcia), @gkossakowski (Grzegorz Kossakowski), @dragos (Iulian Dragos) - repl, compiler performance: @paulp (Paul Phillips) - swing: @ingoem (Ingo Maier) - scaladoc: @vladureche (Vlad Ureche) - optimizer: @vladureche (Vlad Ureche), @magarciaEPFL (Miguel Garcia) - build: @jsuereth (Josh Suereth) - random compiler bugs: @lrytz, @adriaanm, @hubertp - documentation: @heathermiller (Heather Miller) - cps: @TiarkRompf (Tiark Rompf) +{% include maintainers.html %} Martin is the one who submitted the string interpolation proposal and implemented this language feature for Scala 2.10.0. (TODO: how to choose a mailing list) @@ -56,9 +39,9 @@ Therefore now I'm going to [the scala-user mailing list](http://groups.google.co about my issue. Note that I put Martin in the cc list of the email. If I didn't do that, he would probably miss it in a bunch of emails, which get posted to scala-user every day. -![Posting to scala-user](/contribute/01-post.png) - -![Response from Martin](/contribute/02-post.png) +

Posting to scala-user
+
+
Response from Martin
Now when I have the approval of the feature's author, I'll get to work! @@ -75,7 +58,7 @@ Log into [GitHub](http://github.com/), go to [https://github.com/scala/scala](ht button at the top of the page. This will create your own copy of our repository that will serve as a scratchpad for your hackings. If you're new to Git, don't be afraid of messing it up - there is no way you can corrupt our repository. -![Fork scala/scala](/contribute/03-fork.png) +
Fork scala/scala
### Clone ### @@ -329,11 +312,12 @@ This part is very easy and enjoyable. Navigate to your branch in Github (for me and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. -![Submit a pull request](/contribute/04-submit.png) +
Submit a pull request
### Discuss ### After the pull request has been submitted, you need to pick a reviewer (probably, the person you've contacted in the beginning of your workflow) and be ready to elaborate and adjust your patch if necessary. I picked Martin, because we had such a nice chat on the mailing list: -![Assign the reviewer](/contribute/05-review.png) +
SAssign the reviewer
+ From 42987ddbaa2ad4e53ca1f2a05cbcf961040b881b Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Sun, 3 Mar 2013 14:49:30 +0100 Subject: [PATCH 0012/2265] Fixes to the wording in the hacker guide. Just trying to clean up and fill in holes in the hacker guide. Review @xeno_by --- contribute/hacker-guide.md | 47 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 52bb75dd37..db7b64a820 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -5,45 +5,46 @@ title: Scala hacker guide **Eugene Burmako** -This guide is intended to help you get from an idea of fixing a bug or implementing a new feature -to a nightly and, ultimately, to a production release of Scala incorporating your idea. Being able to -influence a programming language of your choice is amazing, and I'm excited to demonstrate that it's easier -than one might think. +This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. + +This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. ### The running example ### -I like string interpolation a lot. Doing debug prints with interpolators introduced in Scala 2.10.0 -is so enjoyable that I often wonder how we ever lived without that feature. However there's an annoying issue -which I occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) -new line tokens `%n`. I could go the mailing list, ask to fix this bug and then indefinitely -wait for the fix. Or I could instead patch Scala myself and get the fix in a subsequent release (nightly builds get produced, well, every -night, minor releases are pumped every few months and major releases happen once a year). The latter option sounds cool, so let's see -how it works! +Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. + +Though, there's an annoying issue +which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) +new line tokens `%n`. + +One approach would be to go the mailing list, request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala oneself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. + +**_Of note_**: There are several types of releases/builds. Nightly builds are produced every night at a fixed time. Minor releases happen once every few months. Major releases typically happen once per year. ### 1. Connect ### -Sometimes it's appealing to hack alone and not to have to interact with humans, but in the context of such a big project like Scala -this might not be the very best idea. Our community has people who spent years accumulating knowledge about Scala. They might provide -unique insights and, what's even better, direct assistance in their areas. +Sometimes it's appealing to hack alone and not to have to interact with others out of fear, or out of comfort. However, in the context a big project such as Scala, +this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide +unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and especially new features beging with posting to one of [our mailing lists](TODO) to find out how people feel +Typically bug fixes new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel about things you want to implement. People proficient is certain areas of Scala usually monitor mailing lists, so you'll often get some help -by simply posting a message. But the most efficient way to connect is to cc your message to one of the go-to persons in your area. Here's the -list of people (Github usernames and real-life names) and their specialties: +by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. + +This is the list of language features/libraries along with their maintainers's full names and github usernames: {% include maintainers.html %} -Martin is the one who submitted the string interpolation proposal and implemented this language feature for Scala 2.10.0. -(TODO: how to choose a mailing list) -Therefore now I'm going to [the scala-user mailing list](http://groups.google.com/group/scala-user) and will post a topic -about my issue. Note that I put Martin in the cc list of the email. If I didn't do that, he would probably miss it in a bunch -of emails, which get posted to scala-user every day. +Since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. + +As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, +in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user)about our issue.
Posting to scala-user

Response from Martin
-Now when I have the approval of the feature's author, I'll get to work! +Now that we have the approval of the feature's author, we can get to work! ### 2. Set up ### From 2ce31f91a6ec123bd020250ab5987b1894775881 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Sun, 3 Mar 2013 19:22:57 +0100 Subject: [PATCH 0013/2265] Continuing to tweak the hacker guide, and to add info where needed. Review @xeno_by --- contribute/hacker-guide.md | 100 +++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index db7b64a820..4f8ca20604 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -9,7 +9,7 @@ This guide is intended to help you get from an idea of fixing a bug or implement This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. -### The running example ### +## The Running Example Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. @@ -21,7 +21,7 @@ One approach would be to go the mailing list, request that the bug be fixed, and **_Of note_**: There are several types of releases/builds. Nightly builds are produced every night at a fixed time. Minor releases happen once every few months. Major releases typically happen once per year. -### 1. Connect ### +## 1. Connect Sometimes it's appealing to hack alone and not to have to interact with others out of fear, or out of comfort. However, in the context a big project such as Scala, this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide @@ -46,26 +46,27 @@ in this example, we post to the [the scala-user mailing list](http://groups.goog Now that we have the approval of the feature's author, we can get to work! -### 2. Set up ### +## 2. Set up Hacking Scala begins with creating a branch for your work item. To develop Scala we use [Git](http://git-scm.com/) and [GitHub](http://github.com/). This section of the guide provides a short walkthrough, but if you are new to Git, -it probably makes sense to familiarize with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) +it probably makes sense to familiarize yourself with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) online book. -### Fork ### +### Fork Log into [GitHub](http://github.com/), go to [https://github.com/scala/scala](https://github.com/scala/scala) and click the `Fork` -button at the top of the page. This will create your own copy of our repository that will serve as a scratchpad for your hackings. -If you're new to Git, don't be afraid of messing it up - there is no way you can corrupt our repository. +button in the top right corner of the page. This will create your own copy of our repository that will serve as a scratchpad for your work. + +If you're new to Git, don't be afraid of messing up-- there is no way you can corrupt our repository.
Fork scala/scala
-### Clone ### +### Clone If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), -which covers some of the things that will follow below. Then clone your repository by running something like the following on the command line: +which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from github to your local machine) by running the following on the command line: 16:35 ~/Projects$ git clone https://github.com/xeno-by/scala Cloning into 'scala'... @@ -76,25 +77,25 @@ which covers some of the things that will follow below. Then clone your reposito Resolving deltas: 100% (182155/182155), done. This will create a local directory called `scala`, which contains a clone of your own copy of our repository. The changes that you make -in this directory can be propagated back to your copy and, ultimately, pushed into Scala. +in this directory can be propagated back to your copy hosted on github and, ultimately, pushed into Scala when your patch is ready. -### Branch ### +### Branch Before you start making changes, always create your own branch. Never work on the `master` branch. Think of a name that describes -the changes you plan on doing. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: +the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. * For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). -* For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams`. +* For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. -Since I'm going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), I'll create a branch named `ticket/6725`. +Since in our example, we're going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), we'll create a branch named `ticket/6725`. 16:39 ~/Projects/scala (master)$ git checkout -b ticket/6725 Switched to a new branch 'ticket/6725' If you are new to Git and branching, read the [Branching Chapter](http://git-scm.com/book/en/Git-Branching) in the Git Pro book. -### Build ### +### Build The next step after cloning your fork is setting up your machine to build Scala. The definitive guide on building Scala is located at [https://github.com/scala/scala/blob/master/README.rst](https://github.com/scala/scala/blob/master/README.rst), but here's the summary: @@ -103,10 +104,10 @@ The next step after cloning your fork is setting up your machine to build Scala. * The build tool is `ant`. * The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. * The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. -* Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter them. +* Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. -In a nutshell, building Scala is as easy as running `ant` in the root of your clone. Be prepared to wait for a while - a full rebuild -takes 8+ minutes depending on your machine. Incremental builds are usually within 30-120 seconds range (again, your mileage might vary +Building Scala is as easy as running `ant` in the root of your cloned repository. Be prepared to wait for a while-- a full "clean" build +takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary with your hardware). 16:50 ~/Projects/scala (ticket/6725)$ ant @@ -134,34 +135,30 @@ with your hardware). BUILD SUCCESSFUL Total time: 9 minutes 41 seconds -### IDE ### +### IDE There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. -Both Eclipse and Intellij IDEA have Scala plugins, which are known to work with our codebase. Here are +Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. Here are [instructions for Eclipse](https://github.com/scala/scala/blob/master/src/eclipse/README.md) and [instructions for Intellij](https://github.com/scala/scala/blob/master/src/intellij/README). Both of those Scala plugins provide -navigation, refactoring and error reporting functionality as well as integrated debugging. Unfortunately this comes at a cost -of occasional sluggishness. +navigation, refactoring and error reporting functionality as well as integrated debugging. -On the other hand, lightweight editors such as Emacs, Sublime or jEdit provide unparalleled scriptability and performance, while +There also exist lighter-weight editors such as Emacs, Sublime or jEdit which provide unparalleled are faster and much less memory/compute-intensive to run, while lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite -having significantly matured over the last year, its support for our particular codebase is still far from being great. +having significantly matured over the last year, support for our particular code base is still being improved, and is not as mature as for Eclipse and IntelliJ. -We know of both novices and experienced Scala hackers who've been effective with using both IDEs and lightweight editors. -Therefore it's hard to recommend a particular tool here, and your choice should boil down to your personal preferences. +Due to the immense variability in personal preference between IDE/editor experience, it's difficult to recommend a particular tool, and your choice should boil down to your personal preferences. -### 3. Hack ### +## 3. Hack When hacking on your topic of choice, you'll be modifying Scala, compiling it and testing it on relevant input files. Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break by running a comprehensive test suite. -I'm going to start by creating a `sandbox` directory (this particular name doesn't bear any special meaning - it's just a tribute to -my first days in Scala team), which will hold a single test file and its compilation results. First I make sure that -[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by throwing together a simple test and feeding it -into the Scala distribution assembled by ant in `build/pack/bin`. +We'll start by creating a `sandbox` directory (this particular name doesn't bear any special meaning), which will hold a single test file and its compilation results. First, let's make sure that +[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `ant`. The Scala compiler that we just built is located in `build/pack/bin`. 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox @@ -176,36 +173,53 @@ into the Scala distribution assembled by ant in `build/pack/bin`. 17:28 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test 1%n1 // %n should've been replaced by a newline here -### Implement ### +### Implement -There's not much to be said about this step, which is bread & butter software development. +Now, implement your bugfix or new feature! Here are also some tips & tricks that have proven useful in Scala development: -* If after introducing changes or updating your clone, you're getting `AbstractMethodError` or other linkage exceptions, +* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile - just that trait, but it might also be necessary to recompile its users. Ant is not smart enough to do that, which might lead to - very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take significant time. + just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to + very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. * Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. -Docs. Right, the docs. The documentation about internal workings of the compiler is scarce, and most of the knowledge is passed around -in the form of folklore. However the situation is steadily improving. Here are the resources that might help: +### Documentation + +There are several areas that one could contribute to-- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. + +##### The Scala Library + +Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it.) + +If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. + +If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](http://docs.scala-lang.org/overviews/core/collections.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](http://docs.scala-lang.org/overviews/core/parallel-collections.html). (TODO double check these links!) + +##### The Scala Compiler + +Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email (scala-internals mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: * [Compiler internals videos by Martin Odersky](TODO) are quite dated, but still very useful. In this three-video - series Martin explains inner workings of the part of the compiler, which has recently become Scala reflection API. + series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. +* [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that + are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. * [Reflection and Compilers by Martin Odersky](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk - at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the reflection API. -* [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures that - are used to represent Scala programs and operations defined on then. + at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. * [Scala compiler corner](http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/) contains extensive documentation about - most of the post-typer phases in the Scala compiler. + most of the post-typer phases (i.e. the backend) in the Scala compiler. * [scala-internals](http://groups.google.com/group/scala-internals), a mailing list which hosts discussions about the core internal design and implementation of the Scala system. +##### Other Projects + +Tools like Scaladoc also welcome contributions. Unfortunately these smaller projects have less developer documentation. In these cases, the best thing to do is to directly explore the code base (which often contains documentation as inline comments) or to write to the appropriate maintainers for pointers. + ### Interlude ### To fix [the bug I'm interested in](https://issues.scala-lang.org/browse/SI-6725) I've tracked the `StringContext.f` interpolator From 023f0b01cdca944b429348820aeed9de4766521b Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Mon, 4 Mar 2013 23:36:44 -0500 Subject: [PATCH 0014/2265] Final tweaks to the hacker guide. Mostly wording --- contribute/hacker-guide.md | 45 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 4f8ca20604..bd7ac60e71 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -182,7 +182,7 @@ Here are also some tips & tricks that have proven useful in Scala development: * If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to - very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. + very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. * Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how @@ -220,10 +220,10 @@ Documentation about the internal workings of the Scala compiler is scarce, and m Tools like Scaladoc also welcome contributions. Unfortunately these smaller projects have less developer documentation. In these cases, the best thing to do is to directly explore the code base (which often contains documentation as inline comments) or to write to the appropriate maintainers for pointers. -### Interlude ### +### Interlude -To fix [the bug I'm interested in](https://issues.scala-lang.org/browse/SI-6725) I've tracked the `StringContext.f` interpolator -down to a macro implemented in `MacroImplementations.scala`. There I noticed that the interpolator only processes conversions, +To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725). Let's say we've tracked the `StringContext.f` interpolator +down to a macro implemented in `MacroImplementations.scala`, and there we notice that the interpolator only processes conversions, but not tokens like `%n`. Looks like an easy fix. 18:44 ~/Projects/scala/sandbox (ticket/6725)$ git diff @@ -242,7 +242,7 @@ but not tokens like `%n`. Looks like an easy fix. start = idx + 1 } -After I applied the fix and running `ant`, my simple test case in `sandbox/Test.scala` started working! +After applying the fix and running `ant`, our simple test case in `sandbox/Test.scala` started working! 18:51 ~/Projects/scala/sandbox (ticket/6725)$ cd .. 18:51 ~/Projects/scala (ticket/6725)$ ant @@ -266,7 +266,7 @@ After I applied the fix and running `ant`, my simple test case in `sandbox/Test. 1 1 // no longer getting the %n here - it got transformed into a newline -### Verify ### +### Verify Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. Read up [the partest guide](/contribute/partest-guide.html) to learn the details about partest, but in a nutshell you can either @@ -283,26 +283,25 @@ run `ant test` to go through the entire test suite (30+ minutes) or use wildcard testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] All of 6 tests were successful (elapsed time: 00:00:08) -### 4. Publish ### +## 4. Publish After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. -In a nutshell this involves: 1) making sure that your code and commit messages are of high quality, 2) clicking a few buttons in the -Github interface, 3) assigning one or more reviewers which will look through your pull request. Now all that in more details. +In a nutshell, this involves: -### Commit ### + 1. making sure that your code and commit messages are of high quality, + 2. clicking a few buttons in the Github interface, + 3. assigning one or more reviewers which will look through your pull request. + + Let's go into each of these points in more detail. + +### Commit The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. There are two things you should know here: -1) Commit messages are frequently the only way to communicate with the authors of the code written a few years ago. Therefore, we give them -big importance. Be creative and eloquent - the more context your provide for the change you've introduced, the bigger the probability that -some future maintainer will get you right. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) -for more information about the desired style of your commits. + 1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. -2) Clean history is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. -For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, -you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against -the latest revision of `master`. + 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. @@ -321,18 +320,18 @@ Once you are satisfied with your work, synced with `master` and cleaned up your To https://github.com/xeno-by/scala * [new branch] ticket/6725 -> ticket/6725 -### Submit ### +### Submit -This part is very easy and enjoyable. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) +Now, we must simply submit our proposed patch. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes.
Submit a pull request
-### Discuss ### +### Discuss -After the pull request has been submitted, you need to pick a reviewer (probably, the person you've contacted in the beginning of your -workflow) and be ready to elaborate and adjust your patch if necessary. I picked Martin, because we had such a nice chat on the mailing list: +After the pull request has been submitted, you need to pick a reviewer (usually the person you've contacted in the beginning of your +workflow) and be ready to elaborate and adjust your patch if necessary. In this example, we picked Martin, because we had such a nice chat on the mailing list:
SAssign the reviewer
From 36ce3092e825d72b9b2af3b68b2f78dfd7c04b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 7 Mar 2013 11:54:07 +0100 Subject: [PATCH 0015/2265] Fixed a build error Maruku did not like that big HTML comment, for some reason. --- contribute/bug-reporting-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index a60fb15b07..345dc03034 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -10,7 +10,7 @@ The Scala project tracker is located at: > [http://issues.scala-lang.org](http://issues.scala-lang.org) - +{% endcomment %} From 3a415b797a650cfd06f80b1d771822651fed0866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 7 Mar 2013 18:27:20 +0100 Subject: [PATCH 0016/2265] First shot at a 'community tickets' feed fetched from JIRA. --- contribute/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contribute/index.md b/contribute/index.md index a92c5f37cc..14a4117631 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -44,6 +44,8 @@ Typically the scaladoc tool provides a low entry point for new committers, so it On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. +
+
### I have this idea that I'd like to add to Scala, how do I start? From af5a53cac3e5dc217f2c73f662a95374833ab6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Fri, 8 Mar 2013 11:14:27 +0100 Subject: [PATCH 0017/2265] Added a dynamic pager in the community tickets feed. --- contribute/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index 14a4117631..05696f5165 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -44,7 +44,8 @@ Typically the scaladoc tool provides a low entry point for new committers, so it On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. -
+{% comment %} Keep the space in the
@@ -40,11 +32,10 @@ title: Contributing guide ### Why contribute a patch to Scala? Just to name a few common reasons: - - contributing a patch is the best way to make sure your desired changes will be available in the next Scala version - - Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu - - last but not least, you will make it into the [Scala Contributor Hall of Fame](scala-fame.html). -
+* contributing a patch is the best way to make sure your desired changes will be available in the next Scala version +* Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu +* last but not least, you will make it into the [Scala Contributor Hall of Fame](scala-fame.html). The main Scala project consists of the standard Scala library, the Scala reflection and macros library, the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. @@ -57,100 +48,37 @@ If you are interested in contributing code, we ask you to sign the which allows us to ensure that all code submitted to the project is unencumbered by copyrights or patents. -
- -### I have this idea that I'd like to add to Scala, how do I start? - -The first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea -and on the implementation plan. Starting point ("community") bugs are usually uncontroversial, so you can jump right -ahead to hacking the scala source tree and filing a pull request. For larger changes it is best to announce the change -on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list. - -Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. - - diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 08f5d40c09..ecdbd2fc27 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -30,7 +30,7 @@ Typically bug fixes and new features start out as an idea or an experiment poste about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. -This is the list of language features/libraries along with their maintainers's full names and GitHub usernames: +This is the list of language features/libraries along with their maintainer's full names and GitHub usernames: {% include maintainers.html %} @@ -182,7 +182,7 @@ Here are also some tips & tricks that have proven useful in Scala development: just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. * Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, - some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts ([here](https://github.com/adriaanm/binfu/blob/master/scafu.sh) are some examples to get you strarted) to launch Scala from `build/quick/classes`. + some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts ([here](https://github.com/adriaanm/binfu/blob/master/scafu.sh) are some examples to get you started) to launch Scala from `build/quick/classes`. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. @@ -415,6 +415,6 @@ workflow) and be ready to elaborate and adjust your patch if necessary. In this ## Merge -After your reviewer is happy with your code (usually signalled by a LGTM — “Looks good to me”), your job is done. +After your reviewer is happy with your code (usually signaled by a LGTM — “Looks good to me”), your job is done. Note that there can be a gap between a successful review and the merge, because not every reviewer has merge rights. In that case, someone else from the team will pick up your pull request and merge it. So don't be confused if your reviewer says “LGTM”, but your code doesn't get merged immediately. diff --git a/contribute/index.md b/contribute/index.md index 338ff06a06..433c579620 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -11,21 +11,56 @@ everyone make things better? ## How to help? -### Reporting bugs +That depends on what you want to contribute. Below are some getting started resources for different contribution domains. Please read all of the documentation and follow all the links from the topic pages below before attempting to contribute, as many of the questions you have will already be answered. -See our [bug reporting guide](./bug-reporting-guide.html) to learn -how to efficiently report a bug. +### Contribute -### Help with the documentation +Coordination of contribution efforts takes place on the +[scala-internals Google group](./scala-internals.html). -An easy but very important way to contribute to Scala is to -[help with the guide/tutorial-style documentation on docs.scala-lang.org](http://docs.scala-lang.org/contribute.html). -If you want to [contribute to Scala standard library API documentation](./scala-standard-library-api-documentation.html), the -process is slightly different, since API documentation lives within Scala standard library source code. +
+
+ +
+

Bug Fixes

+

Issues with the tools, core libraries and compiler. Also you can help us by reporting bugs

+
+
-### Compiler and other tools +
+
+

Tools

+

Enhance the Scala tooling ecosystem with features for build tools, IDE plug-ins and other related tools.

+
+
+

Core Libraries

+

Update and expand the capabilities of the core (and associated) Scala libraries.

+
+
+ +
+
+

Compiler/Language

+

Larger language features and compiler enhancements including language specification and SIPs.

+
+
+

Contributor Hall of Fame

+

Get your props, and find your place in the leader-board.

+
+
+
-More info in our [contributing guide](./guide.html). + +### Reporting bugs + +See our [bug reporting guide](./bug-reporting-guide.html) to learn +how to efficiently report a bug. ### Community Tickets @@ -35,33 +70,33 @@ various contributor activities:
-

Documentation

+

Documentation

Help augment or correct the documentation.

-

Core Libraries

+

Core Libraries

Community bugs and enhancements on the core libs.

-

Tools

+

Tools

Help with the Scala tool chain.

-

Compiler

+

Compiler

Ready for a challenge? Here's the compiler bugs.

-

Bugs

+

Bugs

All bugs marked with the label community.

-

All Issues

+

All Issues

Bugs + Enhancements marked with the label community.

diff --git a/contribute/scala-internals.md b/contribute/scala-internals.md new file mode 100644 index 0000000000..fa7faa9dc3 --- /dev/null +++ b/contribute/scala-internals.md @@ -0,0 +1,45 @@ +--- +layout: page +title: Scala Internals Mailing List +--- + +## scala-internals + +The [scala-internals mailing list](https://groups.google.com/d/forum/scala-internals) is where technical and logistical discussions concerning bugs, bug fixes, documentation, improvements, new features and other contributor related topics occur. + +### Coordinating on scala-internals + +Prior to commencing on contribution work for the Scala project, even for documentation and bugfixing, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. + +To help subscribers on the scala-internals list to sort through the postings, we request that the following topic labels are applied when you start a new post please: + +| Label | Topics | +|-----------|-------------------------------------------------------| +| [docs] | Documentation, e.g. docs.scala-lang.org, API (scaladoc), etc. | +| [issues] | Bug reporting/fixing | +| [tools] | Tools including sbt, IDE plugins, testing, scaladoc generator, etc. | +| [libs] | Core libraries, extension libraries | +| [compiler] | Scala compiler discussions/features/issues | +| [admin] | Administrative/coordination topics | + +So, to talk about this list (an admin activity primarily) one might use: + +`[admin] more suggested labels for topic differentiation.` + +as a title, which then shows up on the mailing lists as + +`[scala-internals] [admin] more suggested labels for topic differentiation.` + +### Why It's a Good Idea + +While it is optional to announce your intentions/work items on scala-internals before starting, it is recommended and a smart thing to do for a number of reasons: + +* To attempt to cut down on duplicate effort (i.e. to avoid two people working on the same bug at the same time without coordinating effort). +* Related to the above: to allow the compiler team and core committers to warn of or smooth over potential merge conflicts between separate bugs that might affect the same code. +* Potentially someone has already thought about or even worked on that issue or a related one, and has valuable insight that might save you time (including warnings about what you might find and may want to avoid - dead ends that have already been explored). +* You might find a group of impassioned individuals want to volunteer to help you, since you got there first with your post it's up to you to decide if you want help or not. +* Posting could start a dialog with a potential reviewer, smoothing the latter, merge stages of the issue. +* There are a lot of nice people waiting to talk to you on scala-internals, you might be surprised how valuable and pleasant you find the experience of talking to them. + +If all of this has not convinced you then, please, go ahead and work on contributions anyway. It *is* less important to post to scala-internals first for small, self contained bugs than it is for larger issues or features, and not having posted first will not be a reason for your PR to be rejected, it just might be a rougher review/merge process than if you had posted first. It's your choice. + diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 519c85a030..14eb55845c 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -72,7 +72,7 @@ component so that they show up in the correct issue filters. ### Required Reading -Please familiarize yourself with **all** of the following before contributing +Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. * [Forking the Repo](./hacker-guide.html#2_set_up) - follow the setup steps through @@ -86,7 +86,7 @@ new API documentation to save time, effort, mistakes and repetition. companions, browsing package object documentation, searching, token searches and so on. * Prior to commit, be sure to read - [A note about git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). + [A note about git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) and the [Scala Project & Developer Guidelines](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md). * Also read the Scala [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). Some of this document will clearly not apply (like the sections on providing tests, however see below for some special requirements for documentation). Do still read @@ -95,7 +95,7 @@ new API documentation to save time, effort, mistakes and repetition. cleanly. Remember that the title of the pull request will become the commit message when merged. **Also**, be sure to assign one or more reviewers to the PR, list of reviewers is at the bottom of this document, but the quick version is to add - `Review by @dickwall` **in the pull request comments**. + `Review by @heathermiller` or `Review by @dickwall` **in the pull request comments**. ### Extra Requirements for Scaladoc Documentation Commits diff --git a/contribute/tools.md b/contribute/tools.md new file mode 100644 index 0000000000..4378d6f568 --- /dev/null +++ b/contribute/tools.md @@ -0,0 +1,8 @@ +--- +layout: page +title: Tool Contributions +--- +## Under Construction + +If you would like to help complete this document, welcome, and please head over and read [Documentation Contributions](./documentation.html#the-scala-language-site), +and let us know on the [scala-internals](https://groups.google.com/forum/#!forum/scala-internals) forum (suggested post title: `[docs] Tool Contributions`) so that we can get you hooked up with the right people. \ No newline at end of file From 0083e203436a2f64c8d50029b93cda39bba5c125 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 10 Feb 2015 12:01:59 -0800 Subject: [PATCH 0061/2265] Alter when documentation/bug fix scala-internals postings are recommended. --- contribute/scala-internals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-internals.md b/contribute/scala-internals.md index fa7faa9dc3..5bd97ed8a8 100644 --- a/contribute/scala-internals.md +++ b/contribute/scala-internals.md @@ -9,7 +9,7 @@ The [scala-internals mailing list](https://groups.google.com/d/forum/scala-inter ### Coordinating on scala-internals -Prior to commencing on contribution work for the Scala project, even for documentation and bugfixing, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. +Prior to commencing on contribution work on larger changes to the Scala project, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. For smaller bug fixes or documentation changes where the risk of effort duplication is minimal, you can skip this post. To help subscribers on the scala-internals list to sort through the postings, we request that the following topic labels are applied when you start a new post please: From d7c254b48255eda00420e38d1273e46e88213bc3 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 10 Feb 2015 13:50:21 -0800 Subject: [PATCH 0062/2265] Correct scala-internals link and remove missing resource links. --- contribute/guide.md | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index 809c6558d5..90f16082d6 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -54,7 +54,7 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu 1. [Select a bug to fix from JIRA](https://issues.scala-lang.org/issues/?filter=12111), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please [make sure it's not a duplicate](./bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](./scala-internals#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with +2. Optional ([but recommended](./scala-internals.html#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with [these friendly people](./hacker-guide.html#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](./hacker-guide.html#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](./hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. @@ -78,19 +78,3 @@ on the [scala-internals](http://groups.google.com/group/scala-internals) mailing Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. -### Further Reading for Larger Changes - -The files below are recordings of code walk-through sessions by Martin Odersky about the Scala compiler internals. Some of the information is somewhat outdated, but the clips are still a good introduction to some parts of the compiler architecture. - - - [Scala Internals 2008-10-29 (Symbols 1)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2008-10-29.avi) - - Handling of Symbols in the Scala compiler: some details on the symtab subdir, Symbols, Definitions, StdNames, Types (Lazy Types). - - - [Scala Internals 2008-11-05 (Symbols 2)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2008-11-05.avi) - - Handling of Symbols part deux: more information on Symbols, Flags, Definitions. - - - [Scala Internals 2009-03-04 (Types)](http://www.scala-lang.org/sites/default/files/martin_ordersky_scala_internals_2009-03-04.avi) - - A detailed explanation about how types are represented and manipulated within the Scala compiler: data structures, manipulations of types, coding conventions (audio is not perfect, but intelligible). - From a4fb06f631262af3f87b6efd14d5078ac992c761 Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Mon, 16 Feb 2015 09:55:48 +0100 Subject: [PATCH 0063/2265] Add scala-fame data --- .../_posts/2015-02-01-scala-fame-2015-01.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md diff --git a/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md b/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md new file mode 100644 index 0000000000..4af6e3d778 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md @@ -0,0 +1,56 @@ +--- +layout: famearchive +title: Contributors of January 2015 +fame-year: 2015 +fame-month: 1 +fame-month-str: January +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 + commits: 10 + linesAdded: 222 + linesDeleted: 26 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 + commits: 4 + linesAdded: 819 + linesDeleted: 636 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 + commits: 4 + linesAdded: 470 + linesDeleted: 152 + rank: 1 + newContributor: false + - category: Community + authors: + - username: kanielc + gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 + commits: 2 + linesAdded: 58 + linesDeleted: 2 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 + commits: 2 + linesAdded: 35 + linesDeleted: 41 + rank: 1 + newContributor: false + - username: dickwall + gravatar: https://avatars2.githubusercontent.com/u/56453?v=3&s=60 + commits: 1 + linesAdded: 74 + linesDeleted: 0 + rank: 2 + newContributor: false +--- From db78065ef0defcd7b863409625974509c687ba3a Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Feb 2015 11:50:40 -0800 Subject: [PATCH 0064/2265] Re-org and simplify contribution section pages. * Removed hall of fame links (as the feature is being removed) * Temporarily disabled tools page link until we work out what to do for tools * Shuffled documentation contrib order to emphasize scaladoc over activator --- contribute/documentation.md | 16 ++++++++-------- contribute/guide.md | 2 +- contribute/index.md | 32 +++++++++++++------------------- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index da20b9360d..cb2f7a46fb 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -6,9 +6,9 @@ title: Documentation Contributions There are several ways you can help out with the improvement of Scala documentation. These include: +* API Documentation in Scaladoc * Code examples and tutorials in activator templates. * The Scala Wiki -* API Documentation in Scaladoc * Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site * Updating Documents on the Main Scala Language Site (this one) @@ -18,13 +18,6 @@ Please read this page, and the pages linked from this one, fully before contribu Thanks -### Examples/Tutorials in Activator Templates - -[Typesafe Activator](https://typesafe.com/community/core-tools/activator-and-sbt) -is a tool based on SBT, with a UI mode that is ideal for code based tutorials, overviews and walk-throughs. To contribute an example in activator, you can fork an existing template, edit it, add a tutorial, upload it to github and then submit the github project into the template repository. It's the fastest way to produce a working code example with tutorial. - -Please see [Contributing an Activator Template](https://typesafe.com/activator/template/contribute) for more details. - ### API Documentation (Scaladoc) The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: @@ -36,6 +29,13 @@ Please *follow the issue submission process closely* to help prevent duplicate i [submit new Scaladoc](./scala-standard-library-api-documentation.html) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. +### Examples/Tutorials in Activator Templates + +[Typesafe Activator](https://typesafe.com/community/core-tools/activator-and-sbt) +is a tool based on SBT, with a UI mode that is ideal for code based tutorials, overviews and walk-throughs. To contribute an example in activator, you can fork an existing template, edit it, add a tutorial, upload it to github and then submit the github project into the template repository. It's the fastest way to produce a working code example with tutorial. + +Please see [Contributing an Activator Template](https://typesafe.com/activator/template/contribute) for more details. + ### The Scala Wiki The [Scala wiki](https://wiki.scala-lang.org/) could be a useful resource, but tends to get out of date quickly. It is perhaps best viewed as a place for information to temporarily live while it is constructed and refined, but with an aim to putting the material into the [docs.scala-lang.org](http://docs.scala-lang.org) site eventually (see the next section). Nonetheless, it is a fast way to add some public documentation. diff --git a/contribute/guide.md b/contribute/guide.md index 90f16082d6..bf323c39e5 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -65,7 +65,7 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) 9. [Submit a pull request](./hacker-guide.html#submit) following the [Scala project pull-request guidelines](http://docs.scala-lang.org/scala/pull-request-policy.html). 10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](./hacker-guide.html#review). -11. [Bask in the glow of a job well done](./scala-fame.html). +11. Celebrate! Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](./hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). diff --git a/contribute/index.md b/contribute/index.md index 433c579620..405a675ea6 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -13,6 +13,11 @@ everyone make things better? That depends on what you want to contribute. Below are some getting started resources for different contribution domains. Please read all of the documentation and follow all the links from the topic pages below before attempting to contribute, as many of the questions you have will already be answered. +### Reporting bugs + +See our [bug reporting guide](./bug-reporting-guide.html) to learn +how to efficiently report a bug. + ### Contribute Coordination of contribution efforts takes place on the @@ -22,8 +27,7 @@ Coordination of contribution efforts takes place on the
@@ -35,33 +39,23 @@ Coordination of contribution efforts takes place on the
-

Tools

-

Enhance the Scala tooling ecosystem with features for build tools, IDE plug-ins and other related tools.

-
-

Core Libraries

Update and expand the capabilities of the core (and associated) Scala libraries.

-
- -
-

Compiler/Language

+

Compiler/Language

Larger language features and compiler enhancements including language specification and SIPs.

-
-

Contributor Hall of Fame

-

Get your props, and find your place in the leader-board.

+ +
- -### Reporting bugs - -See our [bug reporting guide](./bug-reporting-guide.html) to learn -how to efficiently report a bug. - ### Community Tickets The following links provide starting points for From 090c9de45ab7a8c810469853699292aafe0ca865 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Feb 2015 13:19:18 -0800 Subject: [PATCH 0065/2265] Remove wiki info, use scala-lang.org. --- contribute/documentation.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index cb2f7a46fb..81ebba7b3f 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -8,9 +8,8 @@ There are several ways you can help out with the improvement of Scala documentat * API Documentation in Scaladoc * Code examples and tutorials in activator templates. -* The Scala Wiki * Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site -* Updating Documents on the Main Scala Language Site (this one) +* Updating scala-lang.org Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [scala-internals Google group](https://groups.google.com/forum/#!forum/scala-internals) and then, please, submit a pull request with updated documentation reflecting that answer. @@ -36,12 +35,6 @@ is a tool based on SBT, with a UI mode that is ideal for code based tutorials, o Please see [Contributing an Activator Template](https://typesafe.com/activator/template/contribute) for more details. -### The Scala Wiki - -The [Scala wiki](https://wiki.scala-lang.org/) could be a useful resource, but tends to get out of date quickly. It is perhaps best viewed as a place for information to temporarily live while it is constructed and refined, but with an aim to putting the material into the [docs.scala-lang.org](http://docs.scala-lang.org) site eventually (see the next section). Nonetheless, it is a fast way to add some public documentation. - -The wiki is self documenting, so make sure to take a look at the [home page](https://wiki.scala-lang.org/) to get started. Please consider contributions to [docs.scala-lang.org](docs.scala-lang.org) for more enduring documentation, even though it is more work to get through the review process for the main doc site. - ### The Main Scala Documentation Site [docs.scala-lang.org](https://wiki.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a github project that you can fork and submit pull requests from. It includes: @@ -59,7 +52,7 @@ and more Please read [contributing to the docs.scala-lang.org site](http://docs.scala-lang.org/contribute.html) through before embarking on changes. The site uses the [Jekyll](http://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. -### The Scala Language Site +### Updating scala-lang.org Additional high-level documentation (including documentation on contributing to Scala and related projects) is provided on the main From e172523885936286894c661fc450ff3378135dd5 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Wed, 18 Feb 2015 14:46:54 -0800 Subject: [PATCH 0066/2265] Add IDEs and Build Tools page * IDEs and Build Tools page consists of links out to important scala projects * Restored link to above page, and renamed to IDEs and Build Tools * Added a missing link into the documentation.md page --- contribute/documentation.md | 2 +- contribute/index.md | 12 ++-- contribute/tools.md | 123 ++++++++++++++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index 81ebba7b3f..c4704eee0b 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -60,5 +60,5 @@ to Scala and related projects) is provided on the main [scala-lang github project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the scala-lang.org github README file before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the [scala-lang.org github README](https://github.com/dickwall/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/contribute/index.md b/contribute/index.md index 405a675ea6..2d98744a6f 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -43,17 +43,17 @@ Coordination of contribution efforts takes place on the

Update and expand the capabilities of the core (and associated) Scala libraries.

-

Compiler/Language

-

Larger language features and compiler enhancements including language specification and SIPs.

+

IDE and Build Tools

+

Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects.

- ### Community Tickets diff --git a/contribute/tools.md b/contribute/tools.md index 4378d6f568..53b097a696 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -1,8 +1,123 @@ --- layout: page -title: Tool Contributions +title: IDE and Build Tool Contributions --- -## Under Construction +## Contributing to IDE and Build Tools -If you would like to help complete this document, welcome, and please head over and read [Documentation Contributions](./documentation.html#the-scala-language-site), -and let us know on the [scala-internals](https://groups.google.com/forum/#!forum/scala-internals) forum (suggested post title: `[docs] Tool Contributions`) so that we can get you hooked up with the right people. \ No newline at end of file +The links below are to a number of Scala build and IDE related projects that are important in the larger Scala space, and which welcome contributions. + +Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](./hacker-guide.html) and [Bug-fixing](guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. + +Typically, issues for these projects will be reported and kept in the github project issue tracker for that project rather than in the Scala project JIRA. +Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. + +### Broken Links? + +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating-scala-langorg) to fix it. + +### Projects + +
+
+
+

Scala IDE

+

The Eclipse Scala IDE project.

+

Home | +Issues | +ReadMe | +Contributing

+
+
+ +

sbt

+

Interactive build tool.

+

Home | +Issues | +ReadMe | +Contributing

+
+
+ +
+
+ +

Scaladoc Tool

+

(Contribute through scala/scala)

+

Home | +Issues | +ReadMe | +Contributing

+
+
+

DBuild

+

Multi-project build tool.

+

Home | +Issues | +ReadMe | +Contributing

+
+
+ +
+
+

Ensime

+

Scala Support for Text Editors

+

Home | +Issues | +ReadMe | +Contributing

+
+
+ +

Abide

+

Lint tooling for Scala

+

Home | +Issues | +ReadMe | +Contributing

+
+
+ +
+
+ +

Partest

+

Scala Compiler/Library Testing

+

Home | +Issues | +ReadMe

+
+
+

Scoverage

+

Scala code coverage tool

+

Home | +Issues | +ReadMe | +Contributing

+
+
+
+ +### Projects in Particular Need + +The following projects are important to the Scala community but are particularly in need of contributors to continue their development. + +
+
+
+ +

Scalap

+

Scala Decoder (part of scala/scala)

+Issues | +ReadMe | +Contributing

+
+
+

Scalariform

+

Scala code formatter

+

Home | +Issues | +ReadMe

+
+
+
From 391caec69a325cdac6c1531a717bc21cc001605d Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 10 Mar 2015 10:16:07 -0700 Subject: [PATCH 0067/2265] Respond to review comments - correct link, reorder projects * Re-order the projects in approximate order of importance * Corrected scala docs link to correct github project --- contribute/documentation.md | 2 +- contribute/tools.md | 60 ++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index c4704eee0b..c0de56d9b1 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -60,5 +60,5 @@ to Scala and related projects) is provided on the main [scala-lang github project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the [scala-lang.org github README](https://github.com/dickwall/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the [scala-lang.org github README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/contribute/tools.md b/contribute/tools.md index 53b097a696..dab8244d0f 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -11,6 +11,10 @@ Since these tools are in separate projects, they may (and likely will) have thei Typically, issues for these projects will be reported and kept in the github project issue tracker for that project rather than in the Scala project JIRA. Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. +There are some projects in this section that are in +[particular need](#projects-in-particular-need) so please check those out +if you would like to help revive them. + ### Broken Links? Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating-scala-langorg) to fix it. @@ -20,14 +24,6 @@ Stuff changes. Found a broken link or something that needs updating on this page
-

Scala IDE

-

The Eclipse Scala IDE project.

-

Home | -Issues | -ReadMe | -Contributing

-
-

sbt

Interactive build tool.

@@ -36,9 +32,6 @@ Stuff changes. Found a broken link or something that needs updating on this page ReadMe | Contributing

-
- -

Scaladoc Tool

@@ -48,6 +41,17 @@ Stuff changes. Found a broken link or something that needs updating on this page ReadMe | Contributing

+
+ +
+
+

Scala IDE

+

The Eclipse Scala IDE project.

+

Home | +Issues | +ReadMe | +Contributing

+

DBuild

Multi-project build tool.

@@ -60,6 +64,14 @@ Stuff changes. Found a broken link or something that needs updating on this page
+ +

Partest

+

Scala Compiler/Library Testing

+

Home | +Issues | +ReadMe

+
+

Ensime

Scala Support for Text Editors

Home | @@ -67,27 +79,10 @@ Stuff changes. Found a broken link or something that needs updating on this page ReadMe | Contributing

-
- -

Abide

-

Lint tooling for Scala

-

Home | -Issues | -ReadMe | -Contributing

-
- -

Partest

-

Scala Compiler/Library Testing

-

Home | -Issues | -ReadMe

-
-

Scoverage

Scala code coverage tool

Home | @@ -95,6 +90,15 @@ Stuff changes. Found a broken link or something that needs updating on this page ReadMe | Contributing

+
+ +

Abide

+

Lint tooling for Scala

+

Home | +Issues | +ReadMe | +Contributing

+
From 78759cd80f9a25baef7d9b437b829a8ac66261c4 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Wed, 11 Mar 2015 09:44:19 -0700 Subject: [PATCH 0068/2265] Tweak the all community bugs link * No longer sort by component - sort by votes instead. --- contribute/guide.md | 2 +- contribute/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index bf323c39e5..8c07448ba7 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -52,7 +52,7 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](https://issues.scala-lang.org/issues/?filter=12111), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please +1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please [make sure it's not a duplicate](./bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). 2. Optional ([but recommended](./scala-internals.html#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with [these friendly people](./hacker-guide.html#connect) - it's one of the perks of contributing. diff --git a/contribute/index.md b/contribute/index.md index 2d98744a6f..0a37b87a73 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -90,7 +90,7 @@ various contributor activities:

All bugs marked with the label community.

-

All Issues

+

All Issues

Bugs + Enhancements marked with the label community.

From 84da163c3d36575459983b9d2d59fba25dfbea10 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Mar 2015 13:28:27 -0700 Subject: [PATCH 0069/2265] Add fix me links and core lib page. * Add a fix this page link under contents list * Create a simple landing page for core libs - direct to docs.scala.lang --- contribute/corelibs.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index 1429ec87ff..6e1abbb0d7 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -2,7 +2,20 @@ layout: page title: Core Library Contributions --- -## Under Construction +## Core Library Contributions -If you would like to help complete this document, welcome, and please head over and read [Documentation Contributions](./documentation.html#the-scala-language-site), -and let us know on the [scala-internals](https://groups.google.com/forum/#!forum/scala-internals) forum (suggested post title: `[docs] Core Library Contributions`) so that we can get you hooked up with the right people. \ No newline at end of file +There are several options for contributing to Scala's core libraries. You can: + +* Help with [Documentation](./scala-standard-library-api-documentation.html). +* [Report Bugs or Issues](./bug-reporting-guide.html) against the core libraries. +* [Fix Bugs or Issues](./guide.html) against the + [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). +* Contribute significant new functionality or a new API by submitting + a Scala Library Improvement Process (SLIP) Document. + +### Submitting a SLIP + +For significant new functionality or a whole new API to be considered for +inclusion in the core Scala distribution, you will be asked to submit a SLIP (Scala Library Improvement Process) document. + +Please see [instructions for submitting a new SLIP](http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the [pre-requisites](http://docs.scala-lang.org/sips/slip-submission.html) before submitting a SLIP. From 66c5272ca07370c7c6448a30c24da2c66455dcd0 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Mar 2015 13:54:39 -0700 Subject: [PATCH 0070/2265] Add a missing paragraph opener on tools.md --- contribute/tools.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contribute/tools.md b/contribute/tools.md index dab8244d0f..023c638082 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -112,7 +112,7 @@ The following projects are important to the Scala community but are particularly

Scalap

Scala Decoder (part of scala/scala)

-Issues | +

Issues | ReadMe | Contributing

@@ -125,3 +125,5 @@ The following projects are important to the Scala community but are particularly + + \ No newline at end of file From cde252c3e88bdb803f48c4bf30e33c8ffe6da1de Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Mar 2015 14:50:34 -0700 Subject: [PATCH 0071/2265] Fix intra-page links for main markdown engine. * Local jekyll uses - but main site uses _ for intra-page anchors --- contribute/guide.md | 8 ++++---- contribute/index.md | 2 +- contribute/tools.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index 8c07448ba7..04fe50ae5b 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -17,7 +17,7 @@ title: Contributing guide
-

Community issues

+

Community issues

Get cracking on some easy to approach issues.

@@ -52,9 +52,9 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please -[make sure it's not a duplicate](./bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](./scala-internals.html#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with +1. [Select a bug to fix from JIRA](/contribute/index.html#community_tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please +[make sure it's not a duplicate](./bug-reporting-guide.html#reporting_confirmed_bugs_is_a_sin)). +2. Optional ([but recommended](./scala-internals.html#why_its_a_good_idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with [these friendly people](./hacker-guide.html#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](./hacker-guide.html#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](./hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. diff --git a/contribute/index.md b/contribute/index.md index 0a37b87a73..a272a8b98d 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -50,7 +50,7 @@ Coordination of contribution efforts takes place on the
-

Compiler/Language

+

Compiler/Language

Larger language features and compiler enhancements including language specification and SIPs.

diff --git a/contribute/tools.md b/contribute/tools.md index 023c638082..92207f4da2 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -12,12 +12,12 @@ Typically, issues for these projects will be reported and kept in the github pro Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. There are some projects in this section that are in -[particular need](#projects-in-particular-need) so please check those out +[particular need](#projects_in_particular_need) so please check those out if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating_scala_langorg) to fix it. ### Projects From 70673bb169853d0caf796d63e4aa3030238f1ba1 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Mar 2015 15:01:50 -0700 Subject: [PATCH 0072/2265] Remove extra _ in fix-page link. --- contribute/tools.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/tools.md b/contribute/tools.md index 92207f4da2..1757ae1005 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -17,7 +17,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating_scala_langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating_scalalangorg) to fix it. ### Projects From fa3402a41320cbfb6c0ba3c3f4970e8633e5b596 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 17 Mar 2015 15:20:28 -0700 Subject: [PATCH 0073/2265] Fix documentation page intra-link. --- contribute/documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index c0de56d9b1..d7597d8884 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -21,7 +21,7 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute_api_documentation_bug_reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. * [Claim Scaladoc Issues and Provide Documentation](./scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just From fc02b4d49bcc4d85f59fa0f1d1df913b2e102521 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Mon, 23 Mar 2015 15:22:16 -0700 Subject: [PATCH 0074/2265] Add contribute PR review page to /contribute * Pull request reviewing was overlooked in recent contribute changes --- contribute/codereviews.md | 60 +++++++++++++++++++++++++++++++++++++++ contribute/index.md | 12 ++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 contribute/codereviews.md diff --git a/contribute/codereviews.md b/contribute/codereviews.md new file mode 100644 index 0000000000..87ab392f1c --- /dev/null +++ b/contribute/codereviews.md @@ -0,0 +1,60 @@ +--- +layout: page +title: Code Review Contributions +--- +## Code Review Contributions + +In addition to [bug fixing](./guide.html), you can help us review +[waiting pull requests](#pull_requests_awaiting_comment). This is also a good (and recommended) way to get to know the feel of +the bug-fixing and submissions process before jumping in (lurk for a while, +reading pull requests from others and maybe commenting on them). + +### Etiquette + +[Code of Conduct Reminder](http://docs.scala-lang.org/conduct.html) + +There are many coding approaches and styles. Asserting that yours is the only correct one is not likely to lead to a smooth interaction with others. Code review is where programmers (often volunteers) surrender up their efforts for public scrutiny. + +Code reviewing is a great way to both learn and mentor, and *all* comments made during pull request reviews should bear those two aims in mind. + +Assuming the pull request has been made following the guidelines laid out in the rest of the contributor documentation (e.g. for Scala bug fixes, the PR is against an open issue, and has adhered to the guidelines for code changes and submitting the PR), then the comments for the pull request are *not* the correct place to discuss on whether this PR is even needed or other broad, negative assertions. + +The comments are for looking for potential problems in the code, suggesting improvements, looking for items that might have been missed by the submitter and so on. If you feel it necessary to discuss whether the issue should even be addressed, that should be carried out ([in a professional manner](http://docs.scala-lang.org/conduct.html)) on the comments for that Issue rather than the PR. General discussions should likewise be directed to forums like [scala-debate](https://groups.google.com/d/forum/scala-debate), [scala-user](https://groups.google.com/d/forum/scala-user), [scala-language](https://groups.google.com/d/forum/scala-language) or [scala-internals](https://groups.google.com/d/forum/scala-internals). + +Conversely if you are receiving a review, consider that the advice is being given to make you, and Scala, better rather than as a negative critique. Assume the best, rather than the worst. + +### Review Guidelines + +* Keep comments on-topic, concise and precise. +* Attach comments to particular lines or regions they pertain to whenever possible. +* Short code examples are often more descriptive than prose. +* If (and only if) you have thoroughly reviewed the PR and thought through all angles, and you want to accept it, LGTM (Looks Good To Me) is the preferred acceptance response. If there are already LGTMs on the PR, consider whether you are adding anything or just being "me too". +* Above all, remember that the people you are reviewing might be reviewing your PRs one day too :-). + +## Pull Requests Awaiting Comment + +
+
+
+

scala/scala

+

Scala bug fixes and changes in the language, core libs and included tools.

+
+
+

scala/github.scala.com

+

Scala documentation site.

+
+
+ +
+
+

scala/scala-lang

+

The Scala language web site.

+
+
+

All Scala Github Projects

+

For other PRs, follow the scala project from here.

+
+
+
+ +Also note that the [Tools contributions](./tools.html) page has more projects that will generate pull requests. \ No newline at end of file diff --git a/contribute/index.md b/contribute/index.md index a272a8b98d..fd94af5de2 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -39,16 +39,22 @@ Coordination of contribution efforts takes place on the
+

Code Reviews

+

Review pull requests against scala/scala, +scala/scala-lang, +scala/scala.github.com and others.

+
+

Core Libraries

Update and expand the capabilities of the core (and associated) Scala libraries.

+
+ +

IDE and Build Tools

Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects.

-
- -

Compiler/Language

Larger language features and compiler enhancements including language specification and SIPs.

From 77cd3f5f78cb9ed89311ff2f5a811b6e25cf52c1 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 24 Mar 2015 14:07:31 -0700 Subject: [PATCH 0075/2265] Incorporate comments, reduce wordiness * Cut etiquette section * Include Code of Conduct link in Review Guidelines section * Change wording aroung LGTM and additional reviews --- contribute/codereviews.md | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 87ab392f1c..949cb11300 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -5,31 +5,23 @@ title: Code Review Contributions ## Code Review Contributions In addition to [bug fixing](./guide.html), you can help us review -[waiting pull requests](#pull_requests_awaiting_comment). This is also a good (and recommended) way to get to know the feel of -the bug-fixing and submissions process before jumping in (lurk for a while, -reading pull requests from others and maybe commenting on them). +[waiting pull requests](#pull_requests_awaiting_comment). +This is also a good (and recommended) way to get to know the feel of +the bug-fixing and submissions process before jumping in with your +own pull requests. -### Etiquette - -[Code of Conduct Reminder](http://docs.scala-lang.org/conduct.html) - -There are many coding approaches and styles. Asserting that yours is the only correct one is not likely to lead to a smooth interaction with others. Code review is where programmers (often volunteers) surrender up their efforts for public scrutiny. - -Code reviewing is a great way to both learn and mentor, and *all* comments made during pull request reviews should bear those two aims in mind. - -Assuming the pull request has been made following the guidelines laid out in the rest of the contributor documentation (e.g. for Scala bug fixes, the PR is against an open issue, and has adhered to the guidelines for code changes and submitting the PR), then the comments for the pull request are *not* the correct place to discuss on whether this PR is even needed or other broad, negative assertions. - -The comments are for looking for potential problems in the code, suggesting improvements, looking for items that might have been missed by the submitter and so on. If you feel it necessary to discuss whether the issue should even be addressed, that should be carried out ([in a professional manner](http://docs.scala-lang.org/conduct.html)) on the comments for that Issue rather than the PR. General discussions should likewise be directed to forums like [scala-debate](https://groups.google.com/d/forum/scala-debate), [scala-user](https://groups.google.com/d/forum/scala-user), [scala-language](https://groups.google.com/d/forum/scala-language) or [scala-internals](https://groups.google.com/d/forum/scala-internals). - -Conversely if you are receiving a review, consider that the advice is being given to make you, and Scala, better rather than as a negative critique. Assume the best, rather than the worst. ### Review Guidelines +[Code of Conduct Reminder](http://docs.scala-lang.org/conduct.html) + * Keep comments on-topic, concise and precise. * Attach comments to particular lines or regions they pertain to whenever possible. * Short code examples are often more descriptive than prose. -* If (and only if) you have thoroughly reviewed the PR and thought through all angles, and you want to accept it, LGTM (Looks Good To Me) is the preferred acceptance response. If there are already LGTMs on the PR, consider whether you are adding anything or just being "me too". -* Above all, remember that the people you are reviewing might be reviewing your PRs one day too :-). +* If you have thoroughly reviewed the PR and thought through all angles, LGTM (Looks Good To Me) is the preferred acceptance response. +* Additional reviews should try to offer additional insights: "I also thought about it from this angle and it still looks good.." +* Above all, remember that the people you are reviewing might be reviewing your PRs one day too. +* If you are receiving the review, consider that the advice is being given to make you, and Scala, better rather than as a negative critique. Assume the best, rather than the worst. ## Pull Requests Awaiting Comment @@ -57,4 +49,4 @@ Conversely if you are receiving a review, consider that the advice is being give
-Also note that the [Tools contributions](./tools.html) page has more projects that will generate pull requests. \ No newline at end of file +Also note that the [Tools contributions](./tools.html) page has more projects that will generate pull requests. From 3c9d4cd4b8587642f5d0b59f7a4ae7100d799904 Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Tue, 14 Apr 2015 11:43:49 +0200 Subject: [PATCH 0076/2265] Add scala-fame data --- .../_posts/2015-03-01-scala-fame-2015-02.md | 70 ++++++++++++++ .../_posts/2015-04-01-scala-fame-2015-03.md | 91 +++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md create mode 100644 contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md diff --git a/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md b/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md new file mode 100644 index 0000000000..3fe846623b --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md @@ -0,0 +1,70 @@ +--- +layout: famearchive +title: Contributors of February 2015 +fame-year: 2015 +fame-month: 2 +fame-month-str: February +fame-categories: + - category: Typesafe + authors: + - username: adriaanm + gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 + commits: 15 + linesAdded: 1199 + linesDeleted: 588 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 + commits: 13 + linesAdded: 557 + linesDeleted: 64 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 + commits: 10 + linesAdded: 1629 + linesDeleted: 276 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://avatars0.githubusercontent.com/u/609152?v=3&s=60 + commits: 2 + linesAdded: 108 + linesDeleted: 15 + rank: 2 + newContributor: false + - username: axel22 + gravatar: https://avatars0.githubusercontent.com/u/151774?v=3&s=60 + commits: 1 + linesAdded: 61 + linesDeleted: 0 + rank: 3 + newContributor: false + - category: Community + authors: + - username: Ichoran + gravatar: https://avatars2.githubusercontent.com/u/2298644?v=3&s=60 + commits: 3 + linesAdded: 62 + linesDeleted: 25 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 + commits: 2 + linesAdded: 121 + linesDeleted: 30 + rank: 2 + newContributor: false + - username: milessabin + gravatar: https://avatars1.githubusercontent.com/u/131183?v=3&s=60 + commits: 1 + linesAdded: 123 + linesDeleted: 37 + rank: 3 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md b/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md new file mode 100644 index 0000000000..62e7ea2f58 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md @@ -0,0 +1,91 @@ +--- +layout: famearchive +title: Contributors of March 2015 +fame-year: 2015 +fame-month: 3 +fame-month-str: March +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 + commits: 9 + linesAdded: 553 + linesDeleted: 27 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 + commits: 6 + linesAdded: 12 + linesDeleted: 72 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 + commits: 18 + linesAdded: 2857 + linesDeleted: 916 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://avatars0.githubusercontent.com/u/609152?v=3&s=60 + commits: 1 + linesAdded: 7 + linesDeleted: 5 + rank: 2 + newContributor: false + - category: Community + authors: + - username: gourlaysama + gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 + commits: 4 + linesAdded: 132 + linesDeleted: 22 + rank: 1 + newContributor: false + - username: gbasler + gravatar: https://avatars0.githubusercontent.com/u/273035?v=3&s=60 + commits: 3 + linesAdded: 1986 + linesDeleted: 111 + rank: 2 + newContributor: false + - username: kzys + gravatar: https://avatars3.githubusercontent.com/u/19111?v=3&s=60 + commits: 2 + linesAdded: 37 + linesDeleted: 18 + rank: 3 + newContributor: false + - username: som-snytt + gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 + commits: 2 + linesAdded: 91 + linesDeleted: 7 + rank: 3 + newContributor: false + - username: sschaef + gravatar: https://avatars3.githubusercontent.com/u/488530?v=3&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: khernyo + gravatar: https://avatars2.githubusercontent.com/u/447532?v=3&s=60 + commits: 1 + linesAdded: 27 + linesDeleted: 8 + rank: 4 + newContributor: false + - username: soc + gravatar: https://avatars1.githubusercontent.com/u/42493?v=3&s=60 + commits: 1 + linesAdded: 7 + linesDeleted: 7 + rank: 4 + newContributor: false +--- From 4bada26848285509763810ee5f2895123ced406c Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Mon, 20 Apr 2015 16:41:40 -0700 Subject: [PATCH 0077/2265] Fix transposition of github.scala.com. --- contribute/codereviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 949cb11300..8f86815eec 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -32,7 +32,7 @@ own pull requests.

Scala bug fixes and changes in the language, core libs and included tools.

-

scala/github.scala.com

+

scala/scala.github.com

Scala documentation site.

From 57b4392ae555e8d21edbd82e566813d30d38a6d2 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 13 Jul 2015 18:45:33 -0400 Subject: [PATCH 0078/2265] phase out old GitHub wiki pages https://github.com/scala/scala/wiki is going away --- contribute/hacker-guide.md | 2 +- contribute/scala-standard-library-api-documentation.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index ecdbd2fc27..3f84feee81 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -378,7 +378,7 @@ Let's go into each of these points in more detail. The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. There are two things you should know here: -1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. +1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policies](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md) for more information about the desired style of your commits. 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on GitHub. diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 14eb55845c..bc57a163df 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -87,8 +87,7 @@ new API documentation to save time, effort, mistakes and repetition. and so on. * Prior to commit, be sure to read [A note about git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) and the [Scala Project & Developer Guidelines](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md). -* Also read the Scala [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). - Some of this document will clearly not apply (like the sections on providing tests, + Some of this latter document will clearly not apply (like the sections on providing tests, however see below for some special requirements for documentation). Do still read the whole document though, and pay close attention to the title and commit message formats, noting *present tense*, *length limits* and that it must merge From 6a53d0605cb30cff874843aac7ce9a82855c783a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 18 Jul 2015 14:03:43 -0400 Subject: [PATCH 0079/2265] hacker's guide: replace out-of-date reviewer list with link --- contribute/hacker-guide.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 3f84feee81..e8aa8f0db4 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -30,11 +30,9 @@ Typically bug fixes and new features start out as an idea or an experiment poste about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. -This is the list of language features/libraries along with their maintainer's full names and GitHub usernames: +A list of language features/libraries along with their maintainer's full names and GitHub usernames is [in the Scala repo README](https://github.com/scala/scala#get-in-touch). -{% include maintainers.html %} - -Since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. +In our running example, since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user) about our issue. From 23f62743fffe21945f8c6cb454b2925b59fc960c Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 30 Sep 2015 13:18:35 +1000 Subject: [PATCH 0080/2265] SI-9495 Add note about configuring Ant for HTTP proxies --- contribute/hacker-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index e8aa8f0db4..3a01b6a676 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -99,7 +99,7 @@ If you are new to Git and branching, read the [Branching Chapter](http://git-scm The next step after cloning your fork is setting up your machine to build Scala. * It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). -* The build tool is `ant`. +* The build tool is `ant`. If you are behind a HTTP proxy, include [`ANT_ARGS=-autoproxy`]( https://ant.apache.org/manual/proxy.html) in your environment. * The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. * The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. * Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. From 4d8f053757a0feee1ac3d1b8e7bcb0f174b30203 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 30 Sep 2015 08:53:16 -0400 Subject: [PATCH 0081/2265] fix slightly malformed Markdown --- contribute/hacker-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 3a01b6a676..54e62c1a0e 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -99,7 +99,7 @@ If you are new to Git and branching, read the [Branching Chapter](http://git-scm The next step after cloning your fork is setting up your machine to build Scala. * It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). -* The build tool is `ant`. If you are behind a HTTP proxy, include [`ANT_ARGS=-autoproxy`]( https://ant.apache.org/manual/proxy.html) in your environment. +* The build tool is `ant`. If you are behind a HTTP proxy, include [`ANT_ARGS=-autoproxy`](https://ant.apache.org/manual/proxy.html) in your environment. * The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. * The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. * Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. From 50b14af581b26cce03f972a2d00a384d2f81ab08 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 6 Oct 2015 18:35:13 -0400 Subject: [PATCH 0082/2265] SI-9501 add prominent links to relevant docs in main Scala repo the text of the guide already links to the same documents at appropriate places in the narrative, but I also think it's worth having the same links right up front --- contribute/hacker-guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 54e62c1a0e..fb79d8166d 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -8,6 +8,8 @@ This guide is intended to help you get from an idea of fixing a bug or implement This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. +Other good starting points for first-time contributors include the [Scala README](https://github.com/scala/scala#get-in-touch) and [contributor's guidelines](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md). + ## The Running Example Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. From 0feb67ace760707b19b2c91a5f3afea1a9045ea7 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 6 Nov 2015 15:30:38 -0500 Subject: [PATCH 0083/2265] fix typo --- contribute/scala-fame.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index 81bb76ee3a..f30784c13f 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -1,6 +1,6 @@ --- layout: page-full-width -title: Scala Contribuitor Hall of Fame +title: Scala Contributor Hall of Fame --- A big thank you to everyone who contributed to: From c80d07050db560e6aafadc659f9ca4d0b42ef3d2 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 6 Nov 2015 16:01:22 -0500 Subject: [PATCH 0084/2265] October 2015 hall of fame --- .../_posts/2015-11-01-scala-fame-2015-10.md | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md diff --git a/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md b/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md new file mode 100644 index 0000000000..41698296db --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md @@ -0,0 +1,42 @@ +--- +layout: famearchive +title: Contributors of October 2015 +fame-year: 2015 +fame-month: 10 +fame-month-str: October +fame-categories: + - category: Typesafe + authors: + - username: SethTisue + gravatar: https://avatars.githubusercontent.com/u/161079?v=3 + commits: 9 + linesAdded: 80 + linesDeleted: 55 + rank: 1 + newContributor: false + - category: EPFL + authors: + - username: sjrd + gravatar: https://avatars.githubusercontent.com/u/535934?v=3 + commits: 1 + linesAdded: 1 + linesDeleted: 4 + rank: 1 + newContributor: false + - category: Community + authors: + - username: performantdata + gravatar: https://avatars.githubusercontent.com/u/6363453?v=3 + commits: 6 + linesAdded: 97 + linesDeleted: 50 + rank: 1 + newContributor: true + - username: janekdb + gravatar: https://avatars.githubusercontent.com/u/1123855?v=3 + commits: 1 + linesAdded: 86 + linesDeleted: 71 + rank: 2 + newContributor: false +--- From 761af814fe12baff772dcf47cb03c7943105d65d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 6 Nov 2015 16:14:14 -0500 Subject: [PATCH 0085/2265] tweak Hall of Fame page * clarify what the stats show * link to the GitHub Pulse page, which is actually a lot better --- contribute/scala-fame.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index f30784c13f..ffaf0980d7 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -3,10 +3,17 @@ layout: page-full-width title: Scala Contributor Hall of Fame --- -A big thank you to everyone who contributed to: +A big thank you to everyone who has contributed over the years to: - [the Scala library and compiler](https://github.com/scala/scala/contributors) - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) +What follows are the commit totals, to the 2.11.x branch of the scala/scala repo only, +for last month. (For a commit to be counted, it must have been both committed and merged +in the same month.) + +For more a detailed view of recent activity, see the repo's +[GitHub Pulse page](https://github.com/scala/scala/pulse/monthly). + {% for data in site.categories.scala-fame-data limit:1 %} {% assign famedata = data %} {% include render-scala-fame.html %} From 7a039ae25b191ce5733491062cf2f37d27192a9f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 10 Nov 2015 15:16:42 -0500 Subject: [PATCH 0086/2265] tiny fix --- contribute/scala-fame.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index ffaf0980d7..0352e6e7c7 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -11,7 +11,7 @@ What follows are the commit totals, to the 2.11.x branch of the scala/scala repo for last month. (For a commit to be counted, it must have been both committed and merged in the same month.) -For more a detailed view of recent activity, see the repo's +For a more detailed view of recent activity, see the repo's [GitHub Pulse page](https://github.com/scala/scala/pulse/monthly). {% for data in site.categories.scala-fame-data limit:1 %} From 749a690e43b43d9ff0aac267647eab842cd55045 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 4 Dec 2015 12:46:47 -0500 Subject: [PATCH 0087/2265] hall of fame: 2.12.x is default branch now --- contribute/scala-fame.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index 0352e6e7c7..2be9e7d69d 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -7,7 +7,7 @@ A big thank you to everyone who has contributed over the years to: - [the Scala library and compiler](https://github.com/scala/scala/contributors) - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) -What follows are the commit totals, to the 2.11.x branch of the scala/scala repo only, +What follows are the commit totals, to the 2.12.x branch of the scala/scala repo only, for last month. (For a commit to be counted, it must have been both committed and merged in the same month.) From f0fb46ca9be30fc365b875d5ab2c9f171a55041b Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 4 Dec 2015 12:46:53 -0500 Subject: [PATCH 0088/2265] November 2015 contributors hall of fame --- .../_posts/2015-12-01-scala-fame-2015-11.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md diff --git a/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md b/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md new file mode 100644 index 0000000000..8f9b7ff3b1 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md @@ -0,0 +1,63 @@ +--- +layout: famearchive +title: Contributors of November 2015 +fame-year: 2015 +fame-month: 11 +fame-month-str: November +fame-categories: + - category: Typesafe + authors: + - username: szeiger + gravatar: https://avatars.githubusercontent.com/u/54262?v=3 + commits: 5 + linesAdded: 427 + linesDeleted: 116 + rank: 1 + newContributor: false + - username: SethTisue + gravatar: https://avatars.githubusercontent.com/u/161079?v=3 + commits: 3 + linesAdded: 21 + linesDeleted: 21 + rank: 2 + newContributor: false + - username: retronym + gravatar: https://avatars.githubusercontent.com/u/65551?v=3 + commits: 3 + linesAdded: 44 + linesDeleted: 28 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://avatars.githubusercontent.com/u/91083?v=3 + commits: 2 + linesAdded: 22 + linesDeleted: 25 + rank: 3 + newContributor: false + - username: lrytz + gravatar: https://avatars.githubusercontent.com/u/119636?v=3 + commits: 1 + linesAdded: 7 + linesDeleted: 18 + rank: 4 + newContributor: false + - category: EPFL + authors: + - category: Community + authors: + - username: janekdb + gravatar: https://avatars.githubusercontent.com/u/1123855?v=3 + commits: 6 + linesAdded: 76 + linesDeleted: 63 + rank: 1 + newContributor: false + - username: soc + gravatar: https://avatars.githubusercontent.com/u/42493?v=3 + commits: 2 + linesAdded: 14 + linesDeleted: 19 + rank: 2 + newContributor: false +--- From f928c829f2e0dad88a7f0cfaabfd2d4ce87d8da5 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 17 Dec 2015 15:35:33 -0500 Subject: [PATCH 0089/2265] fix bad Markdown our Markdown processor needs a blank line before the start of a bullet list --- contribute/scala-fame.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index 2be9e7d69d..4b6591004a 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -4,6 +4,7 @@ title: Scala Contributor Hall of Fame --- A big thank you to everyone who has contributed over the years to: + - [the Scala library and compiler](https://github.com/scala/scala/contributors) - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) From 719edc3d277d67b41aef833f4edf568b47ae90d8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 17 Dec 2015 18:43:23 -0500 Subject: [PATCH 0090/2265] add text about community libraries, Scala community build --- contribute/index.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/contribute/index.md b/contribute/index.md index fd94af5de2..c03405e489 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -101,3 +101,31 @@ various contributor activities: + +### Tools and Libraries + +The Scala ecosystem includes a great many diverse open-source projects +with their own maintainers and community of contributors. Helping out +one of these projects is another way to help Scala. Consider lending +on a hand on a project you're already using. Or, to find out about +other projects, see the +[Libraries and Tools section](../community/index.html#community-libraries-and-tools) +on our Community page. + +### Scala Community Build + +The Scala community build enables us to build and test a corpus of +Scala open source projects together, using Typesafe's +[dbuild](https://github.com/typesafehub/dbuild) tool +(which leverages [sbt](http://www.scala-sbt.org)). + +The main goal is to guard against regressions in new versions of Scala +(language, standard library, and modules). It's also a service to the +open source community, providing early notice of issues and +incompatibilities. + +If you're the maintainer -- or just an interested user! -- of an +open-source Scala library or tool, please visit the +[community build documentation](https://github.com/scala/community-builds/wiki) +for guidelines on what projects are suitable for the community build +and how projects can be added. From eeee725f7c666a969e823f128dd6893a34a3d0d8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 17 Dec 2015 18:56:12 -0500 Subject: [PATCH 0091/2265] Code of Conduct page, relocated from docs site with updated links, and addition of link to site footer --- contribute/codereviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 8f86815eec..1b9a881b0c 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -13,7 +13,7 @@ own pull requests. ### Review Guidelines -[Code of Conduct Reminder](http://docs.scala-lang.org/conduct.html) +[Code of Conduct reminder](../conduct.html) * Keep comments on-topic, concise and precise. * Attach comments to particular lines or regions they pertain to whenever possible. From cc3d461d8fe51112d5d5b6b721f078025469a795 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 18 Dec 2015 07:48:57 -0500 Subject: [PATCH 0092/2265] tweak wording of community build section based on Heather's feedback --- contribute/index.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/contribute/index.md b/contribute/index.md index c03405e489..137838aba4 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -114,15 +114,14 @@ on our Community page. ### Scala Community Build -The Scala community build enables us to build and test a corpus of -Scala open source projects together, using Typesafe's -[dbuild](https://github.com/typesafehub/dbuild) tool -(which leverages [sbt](http://www.scala-sbt.org)). - -The main goal is to guard against regressions in new versions of Scala -(language, standard library, and modules). It's also a service to the -open source community, providing early notice of issues and -incompatibilities. +The Scala community build enables the Scala compiler team +to build and test a corpus of +Scala open source projects +against development versions of the Scala compiler and standard +library in order to discover regressions prior to releases. +The build uses Typesafe's +[dbuild](https://github.com/typesafehub/dbuild) tool, +which leverages [sbt](http://www.scala-sbt.org). If you're the maintainer -- or just an interested user! -- of an open-source Scala library or tool, please visit the From 856fc9cb2f903ad3353ed49e15d15e70de01e07f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 4 Jan 2016 17:27:39 -0500 Subject: [PATCH 0093/2265] retire the Scala Contributor Hall of Fame https://api.github.com/repos/scala/scala/stats/contributors wasn't giving us good information to base this on, because it only gives you the top 100 contributors by number of all-time commits so e.g. Felix Mulder's great Scaladoc contribution for December wasn't even showing up in the data, since it was just one commit. one of the main purposes of this page was supposed to be recognizing new contributors, but the 100-contributor limit prevents that. the result was embarrassingly empty pages (which we usually forgot to even update anyway) if people are interested in all-time stats, they can visit https://github.com/scala/scala/graphs/contributors , and if people want to see recent activity, they can visit https://github.com/scala/scala/pulse --- contribute/guide.md | 2 +- .../_posts/2013-02-01-scala-fame-2013-01.md | 175 ---------------- .../_posts/2013-03-01-scala-fame-2013-02.md | 189 ------------------ .../_posts/2013-04-01-scala-fame-2013-03.md | 147 -------------- .../_posts/2013-05-01-scala-fame-2013-04.md | 126 ------------ .../_posts/2013-06-01-scala-fame-2013-05.md | 105 ---------- .../_posts/2013-07-01-scala-fame-2013-06.md | 126 ------------ .../_posts/2013-08-01-scala-fame-2013-07.md | 119 ----------- .../_posts/2013-09-01-scala-fame-2013-08.md | 98 --------- .../_posts/2013-10-01-scala-fame-2013-09.md | 105 ---------- .../_posts/2013-11-01-scala-fame-2013-10.md | 105 ---------- .../_posts/2013-12-01-scala-fame-2013-11.md | 126 ------------ .../_posts/2014-01-01-scala-fame-2013-12.md | 147 -------------- .../_posts/2014-02-01-scala-fame-2014-01.md | 147 -------------- .../_posts/2014-03-01-scala-fame-2014-02.md | 133 ------------ .../_posts/2014-04-01-scala-fame-2014-03.md | 112 ----------- .../_posts/2014-05-01-scala-fame-2014-04.md | 91 --------- .../_posts/2014-06-01-scala-fame-2014-05.md | 112 ----------- .../_posts/2014-07-01-scala-fame-2014-06.md | 98 --------- .../_posts/2014-08-01-scala-fame-2014-07.md | 98 --------- .../_posts/2014-09-01-scala-fame-2014-08.md | 70 ------- .../_posts/2014-10-01-scala-fame-2014-09.md | 84 -------- .../_posts/2014-11-01-scala-fame-2014-10.md | 63 ------ .../_posts/2014-12-01-scala-fame-2014-11.md | 112 ----------- .../_posts/2015-01-01-scala-fame-2014-12.md | 70 ------- .../_posts/2015-02-01-scala-fame-2015-01.md | 56 ------ .../_posts/2015-03-01-scala-fame-2015-02.md | 70 ------- .../_posts/2015-04-01-scala-fame-2015-03.md | 91 --------- .../_posts/2015-11-01-scala-fame-2015-10.md | 42 ---- .../_posts/2015-12-01-scala-fame-2015-11.md | 63 ------ contribute/scala-fame.md | 21 -- 31 files changed, 1 insertion(+), 3102 deletions(-) delete mode 100644 contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md delete mode 100644 contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md delete mode 100644 contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md delete mode 100644 contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md delete mode 100644 contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md delete mode 100644 contribute/scala-fame-data/_posts/2013-07-01-scala-fame-2013-06.md delete mode 100644 contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md delete mode 100644 contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md delete mode 100644 contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md delete mode 100644 contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md delete mode 100644 contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md delete mode 100644 contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md delete mode 100644 contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md delete mode 100644 contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md delete mode 100644 contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md delete mode 100644 contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md delete mode 100644 contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md delete mode 100644 contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md delete mode 100644 contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md delete mode 100644 contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md delete mode 100644 contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md delete mode 100644 contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md delete mode 100644 contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md delete mode 100644 contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md delete mode 100644 contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md delete mode 100644 contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md delete mode 100644 contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md delete mode 100644 contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md delete mode 100644 contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md delete mode 100644 contribute/scala-fame.md diff --git a/contribute/guide.md b/contribute/guide.md index 04fe50ae5b..148ceb7570 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -35,7 +35,7 @@ Just to name a few common reasons: * contributing a patch is the best way to make sure your desired changes will be available in the next Scala version * Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu -* last but not least, you will make it into the [Scala Contributor Hall of Fame](scala-fame.html). +* last but not least, it only takes a few accepted commits to make it into the [Scala Contributor Hall of Fame](https://github.com/scala/scala/contributors). The main Scala project consists of the standard Scala library, the Scala reflection and macros library, the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. diff --git a/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md b/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md deleted file mode 100644 index 68e990a7b7..0000000000 --- a/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -layout: famearchive -title: Contributors of January 2013 -fame-year: 2013 -fame-month: 1 -fame-month-str: January -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 67 - linesAdded: 7112 - linesDeleted: 3063 - rank: 1 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 37 - linesAdded: 1812 - linesDeleted: 1158 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 22 - linesAdded: 1397 - linesDeleted: 561 - rank: 3 - newContributor: false - - username: JamesIry - gravatar: https://avatars0.githubusercontent.com/u/478012?v=2&s=60 - commits: 20 - linesAdded: 1156 - linesDeleted: 208 - rank: 4 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 5 - linesAdded: 422 - linesDeleted: 9 - rank: 5 - newContributor: false - - username: viktorklang - gravatar: https://avatars0.githubusercontent.com/u/10871?v=2&s=60 - commits: 2 - linesAdded: 187 - linesDeleted: 12 - rank: 6 - newContributor: false - - username: phaller - gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 - commits: 2 - linesAdded: 21 - linesDeleted: 42 - rank: 6 - newContributor: false - - username: dragos - gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 - commits: 1 - linesAdded: 6 - linesDeleted: 26 - rank: 7 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 28 - linesAdded: 8416 - linesDeleted: 2758 - rank: 1 - newContributor: false - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 8 - linesAdded: 1189 - linesDeleted: 418 - rank: 2 - newContributor: false - - username: heathermiller - gravatar: https://avatars0.githubusercontent.com/u/687163?v=2&s=60 - commits: 2 - linesAdded: 100 - linesDeleted: 15 - rank: 3 - newContributor: false - - username: namin - gravatar: https://avatars2.githubusercontent.com/u/6441?v=2&s=60 - commits: 1 - linesAdded: 23 - linesDeleted: 4 - rank: 4 - newContributor: false - - username: vjovanov - gravatar: https://avatars3.githubusercontent.com/u/352820?v=2&s=60 - commits: 1 - linesAdded: 38 - linesDeleted: 2 - rank: 4 - newContributor: false - - category: Community - authors: - - username: soc - gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 - commits: 13 - linesAdded: 886 - linesDeleted: 3152 - rank: 1 - newContributor: false - - username: kzys - gravatar: https://avatars2.githubusercontent.com/u/19111?v=2&s=60 - commits: 7 - linesAdded: 79 - linesDeleted: 40 - rank: 2 - newContributor: false - - username: danielhopkins - gravatar: https://avatars3.githubusercontent.com/u/91909?v=2&s=60 - commits: 2 - linesAdded: 146 - linesDeleted: 146 - rank: 3 - newContributor: true - - username: ViniciusMiana - gravatar: https://avatars1.githubusercontent.com/u/2053546?v=2&s=60 - commits: 2 - linesAdded: 47 - linesDeleted: 8 - rank: 3 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 2 - linesAdded: 53 - linesDeleted: 6 - rank: 3 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 2 - linesAdded: 236 - linesDeleted: 183 - rank: 3 - newContributor: false - - username: eed3si9n - gravatar: https://avatars1.githubusercontent.com/u/184683?v=2&s=60 - commits: 1 - linesAdded: 35 - linesDeleted: 2 - rank: 4 - newContributor: false - - username: mt2309 - gravatar: https://avatars2.githubusercontent.com/u/816245?v=2&s=60 - commits: 1 - linesAdded: 24 - linesDeleted: 0 - rank: 4 - newContributor: false - - username: puffnfresh - gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 - commits: 1 - linesAdded: 39 - linesDeleted: 3 - rank: 4 - newContributor: false - - username: khernyo - gravatar: https://avatars3.githubusercontent.com/u/447532?v=2&s=60 - commits: 1 - linesAdded: 2 - linesDeleted: 3 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md b/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md deleted file mode 100644 index 376563abce..0000000000 --- a/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -layout: famearchive -title: Contributors of February 2013 -fame-year: 2013 -fame-month: 2 -fame-month-str: February -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 38 - linesAdded: 2578 - linesDeleted: 2114 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 31 - linesAdded: 7110 - linesDeleted: 9889 - rank: 2 - newContributor: false - - username: JamesIry - gravatar: https://secure.gravatar.com/avatar/72b1a6b08fd8bb3068bd281974461c3e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 23 - linesAdded: 1673 - linesDeleted: 740 - rank: 3 - newContributor: false - - username: paulp - gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 10 - linesAdded: 1466 - linesDeleted: 1097 - rank: 4 - newContributor: false - - username: viktorklang - gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 84 - linesDeleted: 53 - rank: 5 - newContributor: false - - username: gkossakowski - gravatar: https://secure.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 4 - linesDeleted: 1 - rank: 6 - newContributor: false - - username: huitseeker - gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 26 - linesDeleted: 0 - rank: 7 - newContributor: false - - username: rkuhn - gravatar: https://secure.gravatar.com/avatar/262b1ab25e66b1e15a48fa3f68703aad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 2 - rank: 7 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 36 - linesAdded: 3379 - linesDeleted: 1635 - rank: 1 - newContributor: false - - username: lrytz - gravatar: https://secure.gravatar.com/avatar/d807dd5133a6fc14c821178e53c34091?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 213 - linesDeleted: 31 - rank: 2 - newContributor: false - - username: heathermiller - gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 2 - linesDeleted: 1333 - rank: 3 - newContributor: false - - username: VladUreche - gravatar: https://secure.gravatar.com/avatar/5658ed1cea041577df360fd663c570fa?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 86 - linesDeleted: 32 - rank: 3 - newContributor: false - - username: hubertp - gravatar: https://secure.gravatar.com/avatar/e0dec64f93778e5c689c3873078a406f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 297 - linesDeleted: 100 - rank: 3 - newContributor: false - - username: axel22 - gravatar: https://secure.gravatar.com/avatar/e9bdb4fada7e635fffb5e6f26e70cd1d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 9 - linesDeleted: 106 - rank: 4 - newContributor: false - - category: Community - authors: - - username: vigdorchik - gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 4 - linesAdded: 471 - linesDeleted: 410 - rank: 1 - newContributor: false - - username: vy - gravatar: https://secure.gravatar.com/avatar/bb8d759cf4230bcaa238fac0018af80c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 21 - linesDeleted: 21 - rank: 2 - newContributor: true - - username: u-abramchuk - gravatar: https://secure.gravatar.com/avatar/c70eb13a60582914b51966fdc1a18536?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 47 - linesDeleted: 13 - rank: 2 - newContributor: true - - username: jozic - gravatar: https://secure.gravatar.com/avatar/41fbba6d48e543a7dfa8c231b2d0286d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 8 - linesDeleted: 8 - rank: 3 - newContributor: true - - username: rnix - gravatar: https://secure.gravatar.com/avatar/0dcbf348a28f2295164c53a40d48a958?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 3 - newContributor: true - - username: mergeconflict - gravatar: https://secure.gravatar.com/avatar/9a58682929b182af7b01f0180e072fcd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 22 - linesDeleted: 15 - rank: 3 - newContributor: false - - username: mt2309 - gravatar: https://secure.gravatar.com/avatar/f70e1d36b9c1b9290d31e810fa1502f3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 0 - rank: 3 - newContributor: false - - username: ViniciusMiana - gravatar: https://secure.gravatar.com/avatar/e05e828a92458c4075b498c7d2957ddd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 16 - linesDeleted: 0 - rank: 3 - newContributor: false - - username: Blaisorblade - gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 0 - linesDeleted: 3 - rank: 3 - newContributor: false - - username: khernyo - gravatar: https://secure.gravatar.com/avatar/0e0d750a49edb4b16e8ec83816ea356e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 25 - linesDeleted: 1 - rank: 3 - newContributor: false - - username: som-snytt - gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 3 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md b/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md deleted file mode 100644 index 0feb88618a..0000000000 --- a/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -layout: famearchive -title: Contributors of March 2013 -fame-year: 2013 -fame-month: 3 -fame-month-str: March -fame-categories: - - category: Typesafe - authors: - - username: paulp - gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 51 - linesAdded: 38101 - linesDeleted: 37753 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 46 - linesAdded: 4908 - linesDeleted: 3092 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 27 - linesAdded: 2675 - linesDeleted: 5043 - rank: 3 - newContributor: false - - username: JamesIry - gravatar: https://secure.gravatar.com/avatar/72b1a6b08fd8bb3068bd281974461c3e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 7 - linesAdded: 1218 - linesDeleted: 171 - rank: 4 - newContributor: false - - username: dragos - gravatar: https://secure.gravatar.com/avatar/fbd384e9626d28d1648f023a5e22672f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 169 - linesDeleted: 2 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 11 - linesAdded: 295 - linesDeleted: 129 - rank: 1 - newContributor: false - - username: magarciaEPFL - gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 6 - linesAdded: 89 - linesDeleted: 44 - rank: 2 - newContributor: false - - category: Community - authors: - - username: vigdorchik - gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 9 - linesAdded: 714 - linesDeleted: 619 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 7 - linesAdded: 2103 - linesDeleted: 2068 - rank: 2 - newContributor: false - - username: soc - gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 6 - linesAdded: 166 - linesDeleted: 96 - rank: 3 - newContributor: false - - username: kzys - gravatar: https://secure.gravatar.com/avatar/7828b45f8396aa361d85cead01fd99ca?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 129 - linesDeleted: 41 - rank: 4 - newContributor: false - - username: Blaisorblade - gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 72 - linesDeleted: 20 - rank: 5 - newContributor: false - - username: starblood - gravatar: https://secure.gravatar.com/avatar/bd3514b960213c6a7ff5fd3186675429?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 6 - newContributor: true - - username: srinivasreddy - gravatar: https://secure.gravatar.com/avatar/1f542afb3240b82fdf08632bf6cd5384?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 6 - newContributor: true - - username: mesagie - gravatar: https://secure.gravatar.com/avatar/6e7dc465ed74b5250147168a0178d91c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 4 - linesDeleted: 5 - rank: 6 - newContributor: true - - username: mergeconflict - gravatar: https://secure.gravatar.com/avatar/9a58682929b182af7b01f0180e072fcd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 22 - linesDeleted: 15 - rank: 6 - newContributor: false - - username: sschaef - gravatar: https://secure.gravatar.com/avatar/dd80aab570fdb5f37e62de5422f44ed4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 13 - linesDeleted: 0 - rank: 6 - newContributor: false - - username: ihji - gravatar: https://secure.gravatar.com/avatar/866a258f0c9fa9529aa47ebd96fe599c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 33 - linesDeleted: 6 - rank: 6 - newContributor: false - - username: chuvoks - gravatar: https://secure.gravatar.com/avatar/415869059046602f37803890bd992fc0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 45 - linesDeleted: 24 - rank: 6 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md b/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md deleted file mode 100644 index e2cd419e9b..0000000000 --- a/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -layout: famearchive -title: Contributors of April 2013 -fame-year: 2013 -fame-month: 4 -fame-month-str: April -fame-categories: - - category: Typesafe - authors: - - username: paulp - gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 38 - linesAdded: 3745 - linesDeleted: 2973 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 37 - linesAdded: 1309 - linesDeleted: 777 - rank: 2 - newContributor: false - - username: huitseeker - gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 16 - linesDeleted: 24 - rank: 3 - newContributor: false - - username: adriaanm - gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 35 - linesDeleted: 82 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: magarciaEPFL - gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 11 - linesAdded: 238 - linesDeleted: 204 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 4 - linesAdded: 208 - linesDeleted: 121 - rank: 2 - newContributor: false - - username: namin - gravatar: https://secure.gravatar.com/avatar/f2adf4eb83e1221b519d23bf0bdc98d2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 6 - linesDeleted: 11 - rank: 3 - newContributor: false - - username: heathermiller - gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 3 - newContributor: false - - username: hubertp - gravatar: https://secure.gravatar.com/avatar/e0dec64f93778e5c689c3873078a406f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 54 - linesDeleted: 46 - rank: 3 - newContributor: false - - category: Community - authors: - - username: som-snytt - gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 16 - linesAdded: 2561 - linesDeleted: 1150 - rank: 1 - newContributor: false - - username: vigdorchik - gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 9 - linesAdded: 235 - linesDeleted: 321 - rank: 2 - newContributor: false - - username: soc - gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 4 - linesAdded: 38 - linesDeleted: 26 - rank: 3 - newContributor: false - - username: ihji - gravatar: https://secure.gravatar.com/avatar/866a258f0c9fa9529aa47ebd96fe599c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 13 - linesDeleted: 2 - rank: 4 - newContributor: false - - username: bjornregnell - gravatar: https://secure.gravatar.com/avatar/b1d20c98b0eeb72829523144b9174ca2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 2 - rank: 5 - newContributor: true - - username: aldenml - gravatar: https://secure.gravatar.com/avatar/bbf061bd484515c156f662a65820c226?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 4 - linesDeleted: 4 - rank: 5 - newContributor: true - - username: eed3si9n - gravatar: https://secure.gravatar.com/avatar/8f41595db400be30176f6f04630c2842?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 304 - linesDeleted: 6 - rank: 5 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md b/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md deleted file mode 100644 index 2829d6a4aa..0000000000 --- a/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -layout: famearchive -title: Contributors of May 2013 -fame-year: 2013 -fame-month: 5 -fame-month-str: May -fame-categories: - - category: Typesafe - authors: - - username: paulp - gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 54 - linesAdded: 3465 - linesDeleted: 2035 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 13 - linesAdded: 525 - linesDeleted: 66 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 245 - linesDeleted: 81 - rank: 3 - newContributor: false - - username: viktorklang - gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 51 - linesDeleted: 32 - rank: 4 - newContributor: false - - username: phaller - gravatar: https://secure.gravatar.com/avatar/3b84657fdb075382e3781310ca8a9a70?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 1965 - linesDeleted: 1086 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 19 - linesAdded: 742 - linesDeleted: 468 - rank: 1 - newContributor: false - - username: magarciaEPFL - gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 11 - linesAdded: 1214 - linesDeleted: 1069 - rank: 2 - newContributor: false - - username: heathermiller - gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 10 - linesDeleted: 7 - rank: 3 - newContributor: false - - category: Community - authors: - - username: soc - gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 12 - linesAdded: 254 - linesDeleted: 1135 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 6 - linesAdded: 454 - linesDeleted: 403 - rank: 2 - newContributor: false - - username: vigdorchik - gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 42 - linesDeleted: 32 - rank: 3 - newContributor: false - - username: dcsobral - gravatar: https://secure.gravatar.com/avatar/6d43da5df0e52fc31c55e6a227bb23f4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 6 - linesDeleted: 2 - rank: 4 - newContributor: false - - username: kzys - gravatar: https://secure.gravatar.com/avatar/7828b45f8396aa361d85cead01fd99ca?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 25 - linesDeleted: 9 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-07-01-scala-fame-2013-06.md b/contribute/scala-fame-data/_posts/2013-07-01-scala-fame-2013-06.md deleted file mode 100644 index e2fa22bf84..0000000000 --- a/contribute/scala-fame-data/_posts/2013-07-01-scala-fame-2013-06.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -layout: famearchive -title: Contributors of June 2013 -fame-year: 2013 -fame-month: 6 -fame-month-str: June -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 18 - linesAdded: 3583 - linesDeleted: 60 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 13 - linesAdded: 12207 - linesDeleted: 11500 - rank: 2 - newContributor: false - - username: paulp - gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 6 - linesAdded: 264 - linesDeleted: 1625 - rank: 3 - newContributor: false - - username: gkossakowski - gravatar: https://secure.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 296 - linesDeleted: 176 - rank: 4 - newContributor: false - - username: viktorklang - gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 197 - linesDeleted: 546 - rank: 5 - newContributor: false - - username: huitseeker - gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 32 - linesDeleted: 1 - rank: 6 - newContributor: false - - category: EPFL - authors: - - username: magarciaEPFL - gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 29 - linesDeleted: 27 - rank: 1 - newContributor: false - - username: VladUreche - gravatar: https://secure.gravatar.com/avatar/5658ed1cea041577df360fd663c570fa?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 4 - linesAdded: 383 - linesDeleted: 68 - rank: 2 - newContributor: false - - username: xeno-by - gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 57 - linesDeleted: 15 - rank: 3 - newContributor: false - - category: Community - authors: - - username: soc - gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 12 - linesAdded: 1071 - linesDeleted: 1200 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 273 - linesDeleted: 44 - rank: 2 - newContributor: false - - username: lexspoon - gravatar: https://secure.gravatar.com/avatar/d00741a2082647573efc2c15022ad15c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 90 - linesDeleted: 29 - rank: 2 - newContributor: false - - username: jedesah - gravatar: https://secure.gravatar.com/avatar/188a972e1c0a6d678a59bd6bce46da9a?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 23 - linesDeleted: 2 - rank: 3 - newContributor: false - - username: yllan - gravatar: https://secure.gravatar.com/avatar/ad23f5809b32c9dade553f80d6d7b2b9?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 124 - linesDeleted: 4 - rank: 4 - newContributor: true - - username: jannic - gravatar: https://secure.gravatar.com/avatar/c85c7cbcc9d464e178ba751449f893c7?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 9 - linesDeleted: 0 - rank: 5 - newContributor: false - - username: xuwei-k - gravatar: https://secure.gravatar.com/avatar/18d8b1bf73827b2a15e2bd3e75b4b34a?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 2 - linesDeleted: 2 - rank: 5 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md b/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md deleted file mode 100644 index b6670c42ce..0000000000 --- a/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -layout: famearchive -title: Contributors of July 2013 -fame-year: 2013 -fame-month: 7 -fame-month-str: July -fame-categories: - - category: Typesafe - authors: - - username: gkossakowski - gravatar: https://0.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?d=https%3A%2F%2Fidenticons.github.com%2F8196e8d0f9ee7dfdfc7e11dbbfa30d77.png&s=60 - commits: 11 - linesAdded: 522 - linesDeleted: 311 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 - commits: 9 - linesAdded: 1068 - linesDeleted: 11436 - rank: 2 - newContributor: false - - username: retronym - gravatar: https://0.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 - commits: 8 - linesAdded: 416 - linesDeleted: 134 - rank: 3 - newContributor: false - - username: paulp - gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png - commits: 2 - linesAdded: 46 - linesDeleted: 27 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: magarciaEPFL - gravatar: https://2.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?d=https%3A%2F%2Fidenticons.github.com%2F8b7440eff98d923640c99b5535429144.png&s=60 - commits: 12 - linesAdded: 1208 - linesDeleted: 1069 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://2.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 - commits: 8 - linesAdded: 321 - linesDeleted: 95 - rank: 2 - newContributor: false - - username: VladUreche - gravatar: https://2.gravatar.com/avatar/5658ed1cea041577df360fd663c570fa?d=https%3A%2F%2Fidenticons.github.com%2Fa1ef2fed16f85a1af890467a80c30226.png&s=60 - commits: 2 - linesAdded: 104 - linesDeleted: 2 - rank: 3 - newContributor: false - - username: cvogt - gravatar: https://1.gravatar.com/avatar/669fb4eab529fba02f390051ddf3c8d3?d=https%3A%2F%2Fidenticons.github.com%2F78d9e7d7c73ac19ca8da9805762e5bb0.png&s=60 - commits: 1 - linesAdded: 19 - linesDeleted: 0 - rank: 4 - newContributor: false - - category: Community - authors: - - username: soc - gravatar: https://0.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?d=https%3A%2F%2Fidenticons.github.com%2F29f7ac3adbe1d3500c9404388aedcbfd.png&s=60 - commits: 19 - linesAdded: 2818 - linesDeleted: 4377 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://2.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 - commits: 16 - linesAdded: 1049 - linesDeleted: 553 - rank: 2 - newContributor: false - - username: densh - gravatar: https://0.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 - commits: 9 - linesAdded: 2632 - linesDeleted: 178 - rank: 3 - newContributor: false - - username: folone - gravatar: https://2.gravatar.com/avatar/50e7e3f60b3507383d2b327857b66a62?d=https%3A%2F%2Fidenticons.github.com%2F6c2bcbccd23191b40f4932e2b8450681.png&s=60 - commits: 3 - linesAdded: 106 - linesDeleted: 261 - rank: 4 - newContributor: false - - username: xuwei-k - gravatar: https://2.gravatar.com/avatar/18d8b1bf73827b2a15e2bd3e75b4b34a?d=https%3A%2F%2Fidenticons.github.com%2Fdab0069935d770e6285411ed1f4398b9.png&s=60 - commits: 3 - linesAdded: 5 - linesDeleted: 5 - rank: 4 - newContributor: false - - username: gourlaysama - gravatar: https://2.gravatar.com/avatar/8acf3c87222f89b18786c8db60eb365d?d=https%3A%2F%2Fidenticons.github.com%2F76004d7b1fac3a2b262caa5e6bdf15c9.png&s=60 - commits: 2 - linesAdded: 67 - linesDeleted: 3 - rank: 5 - newContributor: false - - username: ScrapCodes - gravatar: https://0.gravatar.com/avatar/e9813bbbab2caa993bf7e2b2d60de894?d=https%3A%2F%2Fidenticons.github.com%2F38c660c74f82a216b75167debab770ed.png&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 6 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md b/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md deleted file mode 100644 index c876e815d1..0000000000 --- a/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -layout: famearchive -title: Contributors of August 2013 -fame-year: 2013 -fame-month: 8 -fame-month-str: August -fame-categories: - - category: Typesafe - authors: - - username: paulp - gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png - commits: 50 - linesAdded: 3703 - linesDeleted: 2269 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://0.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 - commits: 30 - linesAdded: 990 - linesDeleted: 167 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 - commits: 6 - linesAdded: 224 - linesDeleted: 11001 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://0.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?d=https%3A%2F%2Fidenticons.github.com%2F0777acff7c9ab34562699e4e1d05affb.png&s=60 - commits: 2 - linesAdded: 6 - linesDeleted: 6 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://2.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 - commits: 9 - linesAdded: 579 - linesDeleted: 419 - rank: 1 - newContributor: false - - username: magarciaEPFL - gravatar: https://2.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?d=https%3A%2F%2Fidenticons.github.com%2F8b7440eff98d923640c99b5535429144.png&s=60 - commits: 4 - linesAdded: 319 - linesDeleted: 105 - rank: 2 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://0.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 - commits: 19 - linesAdded: 687 - linesDeleted: 322 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://2.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 - commits: 12 - linesAdded: 455 - linesDeleted: 91 - rank: 2 - newContributor: false - - username: soc - gravatar: https://0.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?d=https%3A%2F%2Fidenticons.github.com%2F29f7ac3adbe1d3500c9404388aedcbfd.png&s=60 - commits: 4 - linesAdded: 64 - linesDeleted: 27 - rank: 3 - newContributor: false - - username: gourlaysama - gravatar: https://2.gravatar.com/avatar/8acf3c87222f89b18786c8db60eb365d?d=https%3A%2F%2Fidenticons.github.com%2F76004d7b1fac3a2b262caa5e6bdf15c9.png&s=60 - commits: 2 - linesAdded: 50 - linesDeleted: 9 - rank: 4 - newContributor: false - - username: ScrapCodes - gravatar: https://0.gravatar.com/avatar/e9813bbbab2caa993bf7e2b2d60de894?d=https%3A%2F%2Fidenticons.github.com%2F38c660c74f82a216b75167debab770ed.png&s=60 - commits: 1 - linesAdded: 3 - linesDeleted: 0 - rank: 5 - newContributor: false - - username: folone - gravatar: https://2.gravatar.com/avatar/50e7e3f60b3507383d2b327857b66a62?d=https%3A%2F%2Fidenticons.github.com%2F6c2bcbccd23191b40f4932e2b8450681.png&s=60 - commits: 1 - linesAdded: 55 - linesDeleted: 7 - rank: 5 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md b/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md deleted file mode 100644 index 23fa456fc0..0000000000 --- a/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -layout: famearchive -title: Contributors of September 2013 -fame-year: 2013 -fame-month: 9 -fame-month-str: September -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://2.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 - commits: 42 - linesAdded: 1459 - linesDeleted: 476 - rank: 1 - newContributor: false - - username: paulp - gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png - commits: 25 - linesAdded: 6603 - linesDeleted: 7419 - rank: 2 - newContributor: false - - username: huitseeker - gravatar: https://1.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?d=https%3A%2F%2Fidenticons.github.com%2F0777acff7c9ab34562699e4e1d05affb.png&s=60 - commits: 7 - linesAdded: 520 - linesDeleted: 536 - rank: 3 - newContributor: false - - username: gkossakowski - gravatar: https://0.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?d=https%3A%2F%2Fidenticons.github.com%2F8196e8d0f9ee7dfdfc7e11dbbfa30d77.png&s=60 - commits: 2 - linesAdded: 1443 - linesDeleted: 44 - rank: 4 - newContributor: false - - username: dragos - gravatar: https://2.gravatar.com/avatar/fbd384e9626d28d1648f023a5e22672f?d=https%3A%2F%2Fidenticons.github.com%2F6b660454242c937e501b88fd136132f8.png&s=60 - commits: 2 - linesAdded: 95 - linesDeleted: 13 - rank: 4 - newContributor: false - - username: jsuereth - gravatar: https://1.gravatar.com/avatar/5ed293320c06809a24812f56861201ad?d=https%3A%2F%2Fidenticons.github.com%2F11a5b5ef81cff76a0a1f3d042f635df3.png&s=60 - commits: 1 - linesAdded: 18 - linesDeleted: 37 - rank: 5 - newContributor: false - - username: adriaanm - gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 - commits: 1 - linesAdded: 5 - linesDeleted: 5 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://1.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 - commits: 5 - linesAdded: 434 - linesDeleted: 153 - rank: 1 - newContributor: false - - username: sjrd - gravatar: https://1.gravatar.com/avatar/bc554c7355c8476dd63375b314b1bd97?d=https%3A%2F%2Fidenticons.github.com%2F7f7549008d59643d2ce9846ce0364947.png&s=60 - commits: 4 - linesAdded: 30 - linesDeleted: 9 - rank: 2 - newContributor: true - - category: Community - authors: - - username: densh - gravatar: https://1.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 - commits: 20 - linesAdded: 1415 - linesDeleted: 594 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://1.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 - commits: 11 - linesAdded: 367 - linesDeleted: 106 - rank: 2 - newContributor: false - - username: Ichoran - gravatar: https://0.gravatar.com/avatar/3698349ad0b898d398a6573f4d1f867a?d=https%3A%2F%2Fidenticons.github.com%2Ffc12483537f3df99d480423de674e099.png&s=60 - commits: 3 - linesAdded: 75 - linesDeleted: 27 - rank: 3 - newContributor: true - - username: sschaef - gravatar: https://0.gravatar.com/avatar/dd80aab570fdb5f37e62de5422f44ed4?d=https%3A%2F%2Fidenticons.github.com%2Fb5a662bc30d97b377338f5dfb2b4cc66.png&s=60 - commits: 3 - linesAdded: 84 - linesDeleted: 139 - rank: 3 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md b/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md deleted file mode 100644 index 557955d60c..0000000000 --- a/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -layout: famearchive -title: Contributors of October 2013 -fame-year: 2013 -fame-month: 10 -fame-month-str: October -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 52 - linesAdded: 1917 - linesDeleted: 1778 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 18 - linesAdded: 1648 - linesDeleted: 1591 - rank: 2 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 9 - linesAdded: 871 - linesDeleted: 1346 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 1 - linesAdded: 3 - linesDeleted: 0 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 9 - linesAdded: 398 - linesDeleted: 2260 - rank: 1 - newContributor: false - - username: axel22 - gravatar: https://avatars1.githubusercontent.com/u/151774?v=2&s=60 - commits: 1 - linesAdded: 201 - linesDeleted: 74 - rank: 2 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 18 - linesAdded: 766 - linesDeleted: 422 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 4 - linesAdded: 114 - linesDeleted: 58 - rank: 2 - newContributor: false - - username: etaty - gravatar: https://avatars3.githubusercontent.com/u/461170?v=2&s=60 - commits: 2 - linesAdded: 2 - linesDeleted: 2 - rank: 3 - newContributor: false - - username: dotta - gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 - commits: 2 - linesAdded: 68 - linesDeleted: 6 - rank: 3 - newContributor: false - - username: qerub - gravatar: https://avatars2.githubusercontent.com/u/636?v=2&s=60 - commits: 1 - linesAdded: 8 - linesDeleted: 0 - rank: 4 - newContributor: false - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 1 - linesAdded: 31 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 1 - linesAdded: 215 - linesDeleted: 25 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md b/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md deleted file mode 100644 index 7fba955998..0000000000 --- a/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -layout: famearchive -title: Contributors of November 2013 -fame-year: 2013 -fame-month: 11 -fame-month-str: November -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 44 - linesAdded: 1814 - linesDeleted: 1372 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 20 - linesAdded: 1945 - linesDeleted: 1463 - rank: 2 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 4 - linesAdded: 62 - linesDeleted: 659 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 2 - linesAdded: 137 - linesDeleted: 87 - rank: 4 - newContributor: false - - username: phaller - gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 - commits: 1 - linesAdded: 105 - linesDeleted: 101 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 5 - linesAdded: 82 - linesDeleted: 12 - rank: 1 - newContributor: false - - username: heathermiller - gravatar: https://avatars0.githubusercontent.com/u/687163?v=2&s=60 - commits: 1 - linesAdded: 8 - linesDeleted: 5 - rank: 2 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 10 - linesAdded: 1089 - linesDeleted: 884 - rank: 1 - newContributor: false - - username: skyluc - gravatar: https://avatars3.githubusercontent.com/u/1098830?v=2&s=60 - commits: 6 - linesAdded: 1911 - linesDeleted: 53 - rank: 2 - newContributor: false - - username: dotta - gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 - commits: 6 - linesAdded: 64 - linesDeleted: 47 - rank: 2 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 6 - linesAdded: 499 - linesDeleted: 197 - rank: 2 - newContributor: false - - username: soc - gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 - commits: 5 - linesAdded: 280 - linesDeleted: 97 - rank: 3 - newContributor: false - - username: sschaef - gravatar: https://avatars2.githubusercontent.com/u/488530?v=2&s=60 - commits: 4 - linesAdded: 182 - linesDeleted: 12 - rank: 4 - newContributor: false - - username: xuwei-k - gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 - commits: 2 - linesAdded: 3 - linesDeleted: 3 - rank: 5 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 2 - linesAdded: 1179 - linesDeleted: 0 - rank: 5 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 1 - linesAdded: 3 - linesDeleted: 3 - rank: 6 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md b/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md deleted file mode 100644 index 80c4139b10..0000000000 --- a/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -layout: famearchive -title: Contributors of December 2013 -fame-year: 2013 -fame-month: 12 -fame-month-str: December -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 28 - linesAdded: 901 - linesDeleted: 215 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 21 - linesAdded: 1386 - linesDeleted: 16746 - rank: 2 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 9 - linesAdded: 899 - linesDeleted: 409 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 3 - linesAdded: 45 - linesDeleted: 38 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 30 - linesAdded: 2170 - linesDeleted: 984 - rank: 1 - newContributor: false - - username: magarciaEPFL - gravatar: https://avatars2.githubusercontent.com/u/1249748?v=2&s=60 - commits: 5 - linesAdded: 47 - linesDeleted: 17 - rank: 2 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 20 - linesAdded: 1604 - linesDeleted: 703 - rank: 1 - newContributor: false - - username: soc - gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 - commits: 11 - linesAdded: 728 - linesDeleted: 606 - rank: 2 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 8 - linesAdded: 1490 - linesDeleted: 286 - rank: 3 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 6 - linesAdded: 382 - linesDeleted: 224 - rank: 4 - newContributor: false - - username: dotta - gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 - commits: 5 - linesAdded: 265 - linesDeleted: 13 - rank: 5 - newContributor: false - - username: VladimirNik - gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 - commits: 2 - linesAdded: 7 - linesDeleted: 8 - rank: 6 - newContributor: false - - username: rklaehn - gravatar: https://avatars0.githubusercontent.com/u/248257?v=2&s=60 - commits: 2 - linesAdded: 2 - linesDeleted: 83 - rank: 6 - newContributor: false - - username: qerub - gravatar: https://avatars2.githubusercontent.com/u/636?v=2&s=60 - commits: 1 - linesAdded: 10 - linesDeleted: 11 - rank: 7 - newContributor: false - - username: jrudolph - gravatar: https://avatars1.githubusercontent.com/u/9868?v=2&s=60 - commits: 1 - linesAdded: 4 - linesDeleted: 4 - rank: 7 - newContributor: false - - username: skyluc - gravatar: https://avatars3.githubusercontent.com/u/1098830?v=2&s=60 - commits: 1 - linesAdded: 112 - linesDeleted: 54 - rank: 7 - newContributor: false - - username: non - gravatar: https://avatars3.githubusercontent.com/u/218045?v=2&s=60 - commits: 1 - linesAdded: 19 - linesDeleted: 8 - rank: 7 - newContributor: false - - username: xuwei-k - gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 7 - newContributor: false - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 1 - linesAdded: 136 - linesDeleted: 55 - rank: 7 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md b/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md deleted file mode 100644 index ab8e808036..0000000000 --- a/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -layout: famearchive -title: Contributors of January 2014 -fame-year: 2014 -fame-month: 1 -fame-month-str: January -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 37 - linesAdded: 2000 - linesDeleted: 2487 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 8 - linesAdded: 311 - linesDeleted: 175 - rank: 2 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 3 - linesAdded: 15 - linesDeleted: 5 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 2 - linesAdded: 81 - linesDeleted: 79 - rank: 4 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 2 - linesAdded: 7 - linesDeleted: 5 - rank: 4 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 75 - linesAdded: 8908 - linesDeleted: 6023 - rank: 1 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 16 - linesAdded: 722 - linesDeleted: 295 - rank: 1 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 10 - linesAdded: 315 - linesDeleted: 103 - rank: 2 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 9 - linesAdded: 646 - linesDeleted: 201 - rank: 3 - newContributor: false - - username: VladimirNik - gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 - commits: 7 - linesAdded: 1729 - linesDeleted: 350 - rank: 4 - newContributor: false - - username: rklaehn - gravatar: https://avatars0.githubusercontent.com/u/248257?v=2&s=60 - commits: 6 - linesAdded: 1288 - linesDeleted: 39 - rank: 5 - newContributor: false - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 3 - linesAdded: 37 - linesDeleted: 7 - rank: 6 - newContributor: false - - username: cunei - gravatar: https://avatars2.githubusercontent.com/u/686260?v=2&s=60 - commits: 2 - linesAdded: 42 - linesDeleted: 12 - rank: 7 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 2 - linesAdded: 51 - linesDeleted: 33 - rank: 7 - newContributor: false - - username: havocp - gravatar: https://avatars2.githubusercontent.com/u/218689?v=2&s=60 - commits: 1 - linesAdded: 38 - linesDeleted: 2 - rank: 8 - newContributor: false - - username: clhodapp - gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 - commits: 1 - linesAdded: 22 - linesDeleted: 0 - rank: 8 - newContributor: false - - username: rjolly - gravatar: https://avatars3.githubusercontent.com/u/128610?v=2&s=60 - commits: 1 - linesAdded: 45 - linesDeleted: 38 - rank: 8 - newContributor: false - - username: xuwei-k - gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 8 - newContributor: false - - username: dotta - gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 - commits: 1 - linesAdded: 67 - linesDeleted: 67 - rank: 8 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md b/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md deleted file mode 100644 index 065ab45d13..0000000000 --- a/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -layout: famearchive -title: Contributors of February 2014 -fame-year: 2014 -fame-month: 2 -fame-month-str: February -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 47 - linesAdded: 1533 - linesDeleted: 1032 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 25 - linesAdded: 1043 - linesDeleted: 491 - rank: 2 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 4 - linesAdded: 1867 - linesDeleted: 1747 - rank: 3 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 3 - linesAdded: 427 - linesDeleted: 15 - rank: 4 - newContributor: false - - username: dragos - gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 - commits: 1 - linesAdded: 12 - linesDeleted: 3 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 47 - linesAdded: 3989 - linesDeleted: 1545 - rank: 1 - newContributor: false - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 1 - linesAdded: 18 - linesDeleted: 13 - rank: 2 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 23 - linesAdded: 1166 - linesDeleted: 515 - rank: 1 - newContributor: false - - username: VladimirNik - gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 - commits: 10 - linesAdded: 2647 - linesDeleted: 2416 - rank: 2 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 9 - linesAdded: 662 - linesDeleted: 339 - rank: 3 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 8 - linesAdded: 277 - linesDeleted: 75 - rank: 4 - newContributor: false - - username: pavelpavlov - gravatar: https://avatars0.githubusercontent.com/u/1330451?v=2&s=60 - commits: 3 - linesAdded: 44 - linesDeleted: 54 - rank: 5 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 3 - linesAdded: 6 - linesDeleted: 5 - rank: 5 - newContributor: false - - username: soc - gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 - commits: 3 - linesAdded: 476 - linesDeleted: 338 - rank: 5 - newContributor: false - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 2 - linesAdded: 7 - linesDeleted: 7 - rank: 6 - newContributor: false - - username: greenrd - gravatar: https://avatars1.githubusercontent.com/u/164965?v=2&s=60 - commits: 1 - linesAdded: 2 - linesDeleted: 3 - rank: 7 - newContributor: false - - username: clhodapp - gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 - commits: 1 - linesAdded: 228 - linesDeleted: 0 - rank: 7 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md b/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md deleted file mode 100644 index 954a870612..0000000000 --- a/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -layout: famearchive -title: Contributors of March 2014 -fame-year: 2014 -fame-month: 3 -fame-month-str: March -fame-categories: - - category: Typesafe - authors: - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 79 - linesAdded: 24547 - linesDeleted: 24999 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 21 - linesAdded: 622 - linesDeleted: 101 - rank: 2 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 3 - linesAdded: 236 - linesDeleted: 6 - rank: 3 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 2 - linesAdded: 4 - linesDeleted: 2 - rank: 4 - newContributor: false - - username: szeiger - gravatar: https://avatars3.githubusercontent.com/u/54262?v=2&s=60 - commits: 1 - linesAdded: 8 - linesDeleted: 1 - rank: 5 - newContributor: false - - username: viktorklang - gravatar: https://avatars0.githubusercontent.com/u/10871?v=2&s=60 - commits: 1 - linesAdded: 7 - linesDeleted: 2 - rank: 5 - newContributor: false - - username: paulp - gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 - commits: 1 - linesAdded: 20 - linesDeleted: 3 - rank: 5 - newContributor: false - - category: EPFL - authors: - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 10 - linesAdded: 379 - linesDeleted: 76 - rank: 1 - newContributor: false - - category: Community - authors: - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 13 - linesAdded: 589 - linesDeleted: 115 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 4 - linesAdded: 31 - linesDeleted: 23 - rank: 2 - newContributor: false - - username: VladimirNik - gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 - commits: 2 - linesAdded: 1778 - linesDeleted: 1441 - rank: 3 - newContributor: false - - username: mkubala - gravatar: https://avatars0.githubusercontent.com/u/328844?v=2&s=60 - commits: 1 - linesAdded: 247 - linesDeleted: 53 - rank: 4 - newContributor: false - - username: puffnfresh - gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 - commits: 1 - linesAdded: 0 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: iainmcgin - gravatar: https://avatars0.githubusercontent.com/u/309153?v=2&s=60 - commits: 1 - linesAdded: 20 - linesDeleted: 19 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md b/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md deleted file mode 100644 index 66c6819f17..0000000000 --- a/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -layout: famearchive -title: Contributors of April 2014 -fame-year: 2014 -fame-month: 4 -fame-month-str: April -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 9 - linesAdded: 177 - linesDeleted: 34 - rank: 1 - newContributor: false - - username: huitseeker - gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 - commits: 1 - linesAdded: 16 - linesDeleted: 1 - rank: 2 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 1 - linesAdded: 10 - linesDeleted: 3 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 1 - linesAdded: 34 - linesDeleted: 2 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 2 - linesAdded: 202 - linesDeleted: 75 - rank: 1 - newContributor: false - - username: VladUreche - gravatar: https://avatars0.githubusercontent.com/u/428706?v=2&s=60 - commits: 1 - linesAdded: 24 - linesDeleted: 3 - rank: 2 - newContributor: false - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 1 - linesAdded: 12 - linesDeleted: 1 - rank: 2 - newContributor: false - - category: Community - authors: - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 3 - linesAdded: 51 - linesDeleted: 5 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 2 - linesAdded: 110 - linesDeleted: 51 - rank: 2 - newContributor: false - - username: lefou - gravatar: https://avatars2.githubusercontent.com/u/1321393?v=2&s=60 - commits: 1 - linesAdded: 45 - linesDeleted: 8 - rank: 3 - newContributor: false - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 1 - linesAdded: 4 - linesDeleted: 5 - rank: 3 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md b/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md deleted file mode 100644 index f9191afb17..0000000000 --- a/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -layout: famearchive -title: Contributors of May 2014 -fame-year: 2014 -fame-month: 5 -fame-month-str: May -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 32 - linesAdded: 951 - linesDeleted: 136 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 9 - linesAdded: 21 - linesDeleted: 70 - rank: 2 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 3 - linesAdded: 13 - linesDeleted: 18 - rank: 3 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 23 - linesAdded: 6048 - linesDeleted: 2325 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 3 - linesAdded: 93 - linesDeleted: 3 - rank: 2 - newContributor: false - - category: Community - authors: - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 12 - linesAdded: 442 - linesDeleted: 238 - rank: 1 - newContributor: false - - username: lefou - gravatar: https://avatars2.githubusercontent.com/u/1321393?v=2&s=60 - commits: 3 - linesAdded: 14 - linesDeleted: 24 - rank: 2 - newContributor: false - - username: tvierling - gravatar: https://avatars3.githubusercontent.com/u/397857?v=2&s=60 - commits: 2 - linesAdded: 35 - linesDeleted: 11 - rank: 3 - newContributor: true - - username: clhodapp - gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 - commits: 2 - linesAdded: 98 - linesDeleted: 51 - rank: 3 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 2 - linesAdded: 55 - linesDeleted: 16 - rank: 3 - newContributor: false - - username: mkubala - gravatar: https://avatars0.githubusercontent.com/u/328844?v=2&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 0 - rank: 4 - newContributor: false - - username: jedesah - gravatar: https://avatars1.githubusercontent.com/u/1780116?v=2&s=60 - commits: 1 - linesAdded: 23 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: VladimirNik - gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 - commits: 1 - linesAdded: 78 - linesDeleted: 40 - rank: 4 - newContributor: false - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 1 - linesAdded: 14 - linesDeleted: 0 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md b/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md deleted file mode 100644 index 5f051d08a7..0000000000 --- a/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -layout: famearchive -title: Contributors of June 2014 -fame-year: 2014 -fame-month: 6 -fame-month-str: June -fame-categories: - - category: Typesafe - authors: - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 14 - linesAdded: 873 - linesDeleted: 661 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 8 - linesAdded: 166 - linesDeleted: 126 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 16 - linesAdded: 1865 - linesDeleted: 437 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 4 - linesAdded: 164 - linesDeleted: 44 - rank: 2 - newContributor: false - - username: odersky - gravatar: https://avatars2.githubusercontent.com/u/795990?v=2&s=60 - commits: 1 - linesAdded: 36 - linesDeleted: 10 - rank: 3 - newContributor: false - - category: Community - authors: - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 7 - linesAdded: 275 - linesDeleted: 57 - rank: 1 - newContributor: false - - username: jxcoder - gravatar: https://avatars1.githubusercontent.com/u/1075547?v=2&s=60 - commits: 4 - linesAdded: 41 - linesDeleted: 19 - rank: 2 - newContributor: true - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 2 - linesAdded: 20 - linesDeleted: 6 - rank: 3 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 2 - linesAdded: 146 - linesDeleted: 41 - rank: 3 - newContributor: false - - username: jrudolph - gravatar: https://avatars1.githubusercontent.com/u/9868?v=2&s=60 - commits: 1 - linesAdded: 97 - linesDeleted: 4 - rank: 4 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 1 - linesAdded: 6 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 1 - linesAdded: 17 - linesDeleted: 5 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md b/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md deleted file mode 100644 index c57474778d..0000000000 --- a/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -layout: famearchive -title: Contributors of July 2014 -fame-year: 2014 -fame-month: 7 -fame-month-str: July -fame-categories: - - category: Typesafe - authors: - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 31 - linesAdded: 775 - linesDeleted: 712 - rank: 1 - newContributor: false - - username: phaller - gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 - commits: 3 - linesAdded: 161 - linesDeleted: 49 - rank: 2 - newContributor: false - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 1 - linesAdded: 35 - linesDeleted: 34 - rank: 3 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 4 - linesAdded: 84 - linesDeleted: 29 - rank: 1 - newContributor: false - - category: Community - authors: - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 11 - linesAdded: 330 - linesDeleted: 226 - rank: 1 - newContributor: false - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 5 - linesAdded: 217 - linesDeleted: 94 - rank: 2 - newContributor: false - - username: dhgarrette - gravatar: https://avatars2.githubusercontent.com/u/484190?v=2&s=60 - commits: 2 - linesAdded: 1 - linesDeleted: 3 - rank: 3 - newContributor: true - - username: pocket7878 - gravatar: https://avatars1.githubusercontent.com/u/236528?v=2&s=60 - commits: 2 - linesAdded: 21 - linesDeleted: 13 - rank: 3 - newContributor: true - - username: dgruntz - gravatar: https://avatars3.githubusercontent.com/u/1516800?v=2&s=60 - commits: 2 - linesAdded: 4 - linesDeleted: 4 - rank: 3 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 1 - linesAdded: 26 - linesDeleted: 9 - rank: 4 - newContributor: false - - username: kzys - gravatar: https://avatars2.githubusercontent.com/u/19111?v=2&s=60 - commits: 1 - linesAdded: 19 - linesDeleted: 0 - rank: 4 - newContributor: false - - username: densh - gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 - commits: 1 - linesAdded: 3 - linesDeleted: 1 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md b/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md deleted file mode 100644 index afef86d3be..0000000000 --- a/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: famearchive -title: Contributors of August 2014 -fame-year: 2014 -fame-month: 8 -fame-month-str: August -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 3 - linesAdded: 57 - linesDeleted: 4 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 2 - linesAdded: 57 - linesDeleted: 42 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 21 - linesAdded: 3764 - linesDeleted: 2122 - rank: 1 - newContributor: false - - category: Community - authors: - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 10 - linesAdded: 171 - linesDeleted: 7680 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 10 - linesAdded: 917 - linesDeleted: 543 - rank: 1 - newContributor: false - - username: gbasler - gravatar: https://avatars1.githubusercontent.com/u/273035?v=2&s=60 - commits: 1 - linesAdded: 14 - linesDeleted: 22 - rank: 2 - newContributor: false - - username: dgruntz - gravatar: https://avatars3.githubusercontent.com/u/1516800?v=2&s=60 - commits: 1 - linesAdded: 18 - linesDeleted: 18 - rank: 2 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 1 - linesAdded: 26 - linesDeleted: 27 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md b/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md deleted file mode 100644 index ee67016186..0000000000 --- a/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -layout: famearchive -title: Contributors of September 2014 -fame-year: 2014 -fame-month: 9 -fame-month-str: September -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 12 - linesAdded: 182 - linesDeleted: 23 - rank: 1 - newContributor: false - - username: dragos - gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 - commits: 1 - linesAdded: 169 - linesDeleted: 169 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 6 - linesAdded: 262 - linesDeleted: 85 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 - commits: 3 - linesAdded: 1272 - linesDeleted: 1240 - rank: 2 - newContributor: false - - category: Community - authors: - - username: gourlaysama - gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 - commits: 9 - linesAdded: 1782 - linesDeleted: 1227 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 - commits: 4 - linesAdded: 305 - linesDeleted: 125 - rank: 2 - newContributor: false - - username: puffnfresh - gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 - commits: 3 - linesAdded: 42 - linesDeleted: 7 - rank: 3 - newContributor: false - - username: Ichoran - gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 - commits: 2 - linesAdded: 12 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: gbasler - gravatar: https://avatars1.githubusercontent.com/u/273035?v=2&s=60 - commits: 1 - linesAdded: 115 - linesDeleted: 41 - rank: 5 - newContributor: false - - username: soc - gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 - commits: 1 - linesAdded: 4 - linesDeleted: 1 - rank: 5 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md b/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md deleted file mode 100644 index 0c957577fb..0000000000 --- a/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -layout: famearchive -title: Contributors of October 2014 -fame-year: 2014 -fame-month: 10 -fame-month-str: October -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 - commits: 11 - linesAdded: 414 - linesDeleted: 51 - rank: 1 - newContributor: false - - username: gkossakowski - gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 - commits: 2 - linesAdded: 2 - linesDeleted: 2 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 - commits: 2 - linesAdded: 54 - linesDeleted: 18 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 - commits: 4 - linesAdded: 146 - linesDeleted: 171 - rank: 1 - newContributor: false - - category: Community - authors: - - username: roberthoedicke - gravatar: https://avatars0.githubusercontent.com/u/9093826?v=2&s=60 - commits: 9 - linesAdded: 15 - linesDeleted: 15 - rank: 1 - newContributor: true - - username: puffnfresh - gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 - commits: 1 - linesAdded: 19 - linesDeleted: 10 - rank: 2 - newContributor: false - - username: Blaisorblade - gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 - commits: 1 - linesAdded: 0 - linesDeleted: 93 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md b/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md deleted file mode 100644 index 3c95eb2521..0000000000 --- a/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -layout: famearchive -title: Contributors of November 2014 -fame-year: 2014 -fame-month: 11 -fame-month-str: November -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 - commits: 24 - linesAdded: 650 - linesDeleted: 90 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 - commits: 3 - linesAdded: 208 - linesDeleted: 54 - rank: 2 - newContributor: false - - username: phaller - gravatar: https://avatars1.githubusercontent.com/u/289943?v=3&s=60 - commits: 1 - linesAdded: 10 - linesDeleted: 8 - rank: 3 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 - commits: 6 - linesAdded: 782 - linesDeleted: 32 - rank: 1 - newContributor: false - - username: heathermiller - gravatar: https://avatars1.githubusercontent.com/u/687163?v=3&s=60 - commits: 2 - linesAdded: 64 - linesDeleted: 66 - rank: 2 - newContributor: false - - category: Community - authors: - - username: gourlaysama - gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 - commits: 7 - linesAdded: 245 - linesDeleted: 83 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 - commits: 3 - linesAdded: 53 - linesDeleted: 53 - rank: 2 - newContributor: false - - username: advancedxy - gravatar: https://avatars1.githubusercontent.com/u/807537?v=3&s=60 - commits: 2 - linesAdded: 2 - linesDeleted: 2 - rank: 3 - newContributor: true - - username: kanielc - gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 - commits: 2 - linesAdded: 3 - linesDeleted: 3 - rank: 3 - newContributor: true - - username: gdickinson - gravatar: https://avatars3.githubusercontent.com/u/1130928?v=3&s=60 - commits: 2 - linesAdded: 0 - linesDeleted: 380 - rank: 3 - newContributor: true - - username: Ichoran - gravatar: https://avatars2.githubusercontent.com/u/2298644?v=3&s=60 - commits: 2 - linesAdded: 35 - linesDeleted: 18 - rank: 3 - newContributor: false - - username: ruippeixotog - gravatar: https://avatars1.githubusercontent.com/u/613493?v=3&s=60 - commits: 1 - linesAdded: 81 - linesDeleted: 8 - rank: 4 - newContributor: false - - username: mpociecha - gravatar: https://avatars0.githubusercontent.com/u/6143494?v=3&s=60 - commits: 1 - linesAdded: 5 - linesDeleted: 2 - rank: 4 - newContributor: false - - username: soc - gravatar: https://avatars1.githubusercontent.com/u/42493?v=3&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md b/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md deleted file mode 100644 index c11348b33a..0000000000 --- a/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: famearchive -title: Contributors of December 2014 -fame-year: 2014 -fame-month: 12 -fame-month-str: December -fame-categories: - - category: Typesafe - authors: - - username: adriaanm - gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 - commits: 2 - linesAdded: 962 - linesDeleted: 290 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 - commits: 1 - linesAdded: 5 - linesDeleted: 1 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 - commits: 4 - linesAdded: 61 - linesDeleted: 50 - rank: 1 - newContributor: false - - category: Community - authors: - - username: gbasler - gravatar: https://avatars0.githubusercontent.com/u/273035?v=3&s=60 - commits: 2 - linesAdded: 567 - linesDeleted: 1 - rank: 1 - newContributor: false - - username: kanielc - gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 - commits: 1 - linesAdded: 43 - linesDeleted: 6 - rank: 2 - newContributor: false - - username: xuwei-k - gravatar: https://avatars2.githubusercontent.com/u/389787?v=3&s=60 - commits: 1 - linesAdded: 2 - linesDeleted: 2 - rank: 2 - newContributor: false - - username: gourlaysama - gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 2 - newContributor: false - - username: som-snytt - gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 - commits: 1 - linesAdded: 44 - linesDeleted: 3 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md b/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md deleted file mode 100644 index 4af6e3d778..0000000000 --- a/contribute/scala-fame-data/_posts/2015-02-01-scala-fame-2015-01.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -layout: famearchive -title: Contributors of January 2015 -fame-year: 2015 -fame-month: 1 -fame-month-str: January -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 - commits: 10 - linesAdded: 222 - linesDeleted: 26 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 - commits: 4 - linesAdded: 819 - linesDeleted: 636 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 - commits: 4 - linesAdded: 470 - linesDeleted: 152 - rank: 1 - newContributor: false - - category: Community - authors: - - username: kanielc - gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 - commits: 2 - linesAdded: 58 - linesDeleted: 2 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 - commits: 2 - linesAdded: 35 - linesDeleted: 41 - rank: 1 - newContributor: false - - username: dickwall - gravatar: https://avatars2.githubusercontent.com/u/56453?v=3&s=60 - commits: 1 - linesAdded: 74 - linesDeleted: 0 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md b/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md deleted file mode 100644 index 3fe846623b..0000000000 --- a/contribute/scala-fame-data/_posts/2015-03-01-scala-fame-2015-02.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: famearchive -title: Contributors of February 2015 -fame-year: 2015 -fame-month: 2 -fame-month-str: February -fame-categories: - - category: Typesafe - authors: - - username: adriaanm - gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 - commits: 15 - linesAdded: 1199 - linesDeleted: 588 - rank: 1 - newContributor: false - - username: retronym - gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 - commits: 13 - linesAdded: 557 - linesDeleted: 64 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 - commits: 10 - linesAdded: 1629 - linesDeleted: 276 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://avatars0.githubusercontent.com/u/609152?v=3&s=60 - commits: 2 - linesAdded: 108 - linesDeleted: 15 - rank: 2 - newContributor: false - - username: axel22 - gravatar: https://avatars0.githubusercontent.com/u/151774?v=3&s=60 - commits: 1 - linesAdded: 61 - linesDeleted: 0 - rank: 3 - newContributor: false - - category: Community - authors: - - username: Ichoran - gravatar: https://avatars2.githubusercontent.com/u/2298644?v=3&s=60 - commits: 3 - linesAdded: 62 - linesDeleted: 25 - rank: 1 - newContributor: false - - username: som-snytt - gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 - commits: 2 - linesAdded: 121 - linesDeleted: 30 - rank: 2 - newContributor: false - - username: milessabin - gravatar: https://avatars1.githubusercontent.com/u/131183?v=3&s=60 - commits: 1 - linesAdded: 123 - linesDeleted: 37 - rank: 3 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md b/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md deleted file mode 100644 index 62e7ea2f58..0000000000 --- a/contribute/scala-fame-data/_posts/2015-04-01-scala-fame-2015-03.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -layout: famearchive -title: Contributors of March 2015 -fame-year: 2015 -fame-month: 3 -fame-month-str: March -fame-categories: - - category: Typesafe - authors: - - username: retronym - gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 - commits: 9 - linesAdded: 553 - linesDeleted: 27 - rank: 1 - newContributor: false - - username: adriaanm - gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 - commits: 6 - linesAdded: 12 - linesDeleted: 72 - rank: 2 - newContributor: false - - category: EPFL - authors: - - username: lrytz - gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 - commits: 18 - linesAdded: 2857 - linesDeleted: 916 - rank: 1 - newContributor: false - - username: xeno-by - gravatar: https://avatars0.githubusercontent.com/u/609152?v=3&s=60 - commits: 1 - linesAdded: 7 - linesDeleted: 5 - rank: 2 - newContributor: false - - category: Community - authors: - - username: gourlaysama - gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 - commits: 4 - linesAdded: 132 - linesDeleted: 22 - rank: 1 - newContributor: false - - username: gbasler - gravatar: https://avatars0.githubusercontent.com/u/273035?v=3&s=60 - commits: 3 - linesAdded: 1986 - linesDeleted: 111 - rank: 2 - newContributor: false - - username: kzys - gravatar: https://avatars3.githubusercontent.com/u/19111?v=3&s=60 - commits: 2 - linesAdded: 37 - linesDeleted: 18 - rank: 3 - newContributor: false - - username: som-snytt - gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 - commits: 2 - linesAdded: 91 - linesDeleted: 7 - rank: 3 - newContributor: false - - username: sschaef - gravatar: https://avatars3.githubusercontent.com/u/488530?v=3&s=60 - commits: 1 - linesAdded: 1 - linesDeleted: 1 - rank: 4 - newContributor: false - - username: khernyo - gravatar: https://avatars2.githubusercontent.com/u/447532?v=3&s=60 - commits: 1 - linesAdded: 27 - linesDeleted: 8 - rank: 4 - newContributor: false - - username: soc - gravatar: https://avatars1.githubusercontent.com/u/42493?v=3&s=60 - commits: 1 - linesAdded: 7 - linesDeleted: 7 - rank: 4 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md b/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md deleted file mode 100644 index 41698296db..0000000000 --- a/contribute/scala-fame-data/_posts/2015-11-01-scala-fame-2015-10.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -layout: famearchive -title: Contributors of October 2015 -fame-year: 2015 -fame-month: 10 -fame-month-str: October -fame-categories: - - category: Typesafe - authors: - - username: SethTisue - gravatar: https://avatars.githubusercontent.com/u/161079?v=3 - commits: 9 - linesAdded: 80 - linesDeleted: 55 - rank: 1 - newContributor: false - - category: EPFL - authors: - - username: sjrd - gravatar: https://avatars.githubusercontent.com/u/535934?v=3 - commits: 1 - linesAdded: 1 - linesDeleted: 4 - rank: 1 - newContributor: false - - category: Community - authors: - - username: performantdata - gravatar: https://avatars.githubusercontent.com/u/6363453?v=3 - commits: 6 - linesAdded: 97 - linesDeleted: 50 - rank: 1 - newContributor: true - - username: janekdb - gravatar: https://avatars.githubusercontent.com/u/1123855?v=3 - commits: 1 - linesAdded: 86 - linesDeleted: 71 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md b/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md deleted file mode 100644 index 8f9b7ff3b1..0000000000 --- a/contribute/scala-fame-data/_posts/2015-12-01-scala-fame-2015-11.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -layout: famearchive -title: Contributors of November 2015 -fame-year: 2015 -fame-month: 11 -fame-month-str: November -fame-categories: - - category: Typesafe - authors: - - username: szeiger - gravatar: https://avatars.githubusercontent.com/u/54262?v=3 - commits: 5 - linesAdded: 427 - linesDeleted: 116 - rank: 1 - newContributor: false - - username: SethTisue - gravatar: https://avatars.githubusercontent.com/u/161079?v=3 - commits: 3 - linesAdded: 21 - linesDeleted: 21 - rank: 2 - newContributor: false - - username: retronym - gravatar: https://avatars.githubusercontent.com/u/65551?v=3 - commits: 3 - linesAdded: 44 - linesDeleted: 28 - rank: 2 - newContributor: false - - username: adriaanm - gravatar: https://avatars.githubusercontent.com/u/91083?v=3 - commits: 2 - linesAdded: 22 - linesDeleted: 25 - rank: 3 - newContributor: false - - username: lrytz - gravatar: https://avatars.githubusercontent.com/u/119636?v=3 - commits: 1 - linesAdded: 7 - linesDeleted: 18 - rank: 4 - newContributor: false - - category: EPFL - authors: - - category: Community - authors: - - username: janekdb - gravatar: https://avatars.githubusercontent.com/u/1123855?v=3 - commits: 6 - linesAdded: 76 - linesDeleted: 63 - rank: 1 - newContributor: false - - username: soc - gravatar: https://avatars.githubusercontent.com/u/42493?v=3 - commits: 2 - linesAdded: 14 - linesDeleted: 19 - rank: 2 - newContributor: false ---- diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md deleted file mode 100644 index 4b6591004a..0000000000 --- a/contribute/scala-fame.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: page-full-width -title: Scala Contributor Hall of Fame ---- - -A big thank you to everyone who has contributed over the years to: - - - [the Scala library and compiler](https://github.com/scala/scala/contributors) - - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) - -What follows are the commit totals, to the 2.12.x branch of the scala/scala repo only, -for last month. (For a commit to be counted, it must have been both committed and merged -in the same month.) - -For a more detailed view of recent activity, see the repo's -[GitHub Pulse page](https://github.com/scala/scala/pulse/monthly). - -{% for data in site.categories.scala-fame-data limit:1 %} - {% assign famedata = data %} - {% include render-scala-fame.html %} -{% endfor %} From 76fa6b98681ed1603718b99c6c20ec003b11025b Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 24 Feb 2016 16:48:19 -0500 Subject: [PATCH 0094/2265] Typesafe -> Lightbend in a bunch of places --- contribute/documentation.md | 4 ++-- contribute/guide.md | 2 +- contribute/hacker-guide.md | 2 +- contribute/index.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index d7597d8884..6b5c81a0fc 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -30,10 +30,10 @@ without creating an issue, but please look to see if there is an issue already s ### Examples/Tutorials in Activator Templates -[Typesafe Activator](https://typesafe.com/community/core-tools/activator-and-sbt) +[Lightbend Activator](https://www.lightbend.com/community/core-tools/activator-and-sbt) is a tool based on SBT, with a UI mode that is ideal for code based tutorials, overviews and walk-throughs. To contribute an example in activator, you can fork an existing template, edit it, add a tutorial, upload it to github and then submit the github project into the template repository. It's the fastest way to produce a working code example with tutorial. -Please see [Contributing an Activator Template](https://typesafe.com/activator/template/contribute) for more details. +Please see [Contributing an Activator Template](https://www.lightbend.com/activator/template/contribute) for more details. ### The Main Scala Documentation Site diff --git a/contribute/guide.md b/contribute/guide.md index 148ceb7570..b92bd2fe89 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -44,7 +44,7 @@ Typically the scaladoc tool provides a low entry point for new committers, so it On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. If you are interested in contributing code, we ask you to sign the -[Scala Contributor License Agreement](http://typesafe.com/contribute/cla/scala), +[Scala Contributor License Agreement](http://www.lightbend.com/contribute/cla/scala), which allows us to ensure that all code submitted to the project is unencumbered by copyrights or patents. diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index fb79d8166d..47ebafe634 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -402,7 +402,7 @@ Once you are satisfied with your work, synced with `master` and cleaned up your Now, we must simply submit our proposed patch. Navigate to your branch in GitHub (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will -need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. +need to sign the contributor license agreement, which [can be done online](http://www.lightbend.com/contribute/cla/scala) within a few minutes. Submit a pull request diff --git a/contribute/index.md b/contribute/index.md index 137838aba4..925e83248e 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -27,7 +27,7 @@ Coordination of contribution efforts takes place on the
@@ -119,7 +119,7 @@ to build and test a corpus of Scala open source projects against development versions of the Scala compiler and standard library in order to discover regressions prior to releases. -The build uses Typesafe's +The build uses Lightbend's [dbuild](https://github.com/typesafehub/dbuild) tool, which leverages [sbt](http://www.scala-sbt.org). From 55dfcf608ea8e8fd8a648ffa99ee9ccf45ae0486 Mon Sep 17 00:00:00 2001 From: Chase Long Date: Mon, 6 Jun 2016 21:12:56 -0500 Subject: [PATCH 0095/2265] Replace references to ant with corresponding sbt references --- contribute/hacker-guide.md | 105 ++++++++++--------------------------- 1 file changed, 29 insertions(+), 76 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 47ebafe634..dab991eba5 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -100,47 +100,25 @@ If you are new to Git and branching, read the [Branching Chapter](http://git-scm The next step after cloning your fork is setting up your machine to build Scala. -* It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). -* The build tool is `ant`. If you are behind a HTTP proxy, include [`ANT_ARGS=-autoproxy`](https://ant.apache.org/manual/proxy.html) in your environment. -* The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. -* The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. -* Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. +You need the following tools: -Building Scala is as easy as running `ant` in the root of your cloned repository. Be prepared to wait for a while-- a full "clean" build -takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary -with your hardware). - - 16:50 ~/Projects/scala (ticket/6725)$ ant - Buildfile: /Users/xeno_by/Projects/scala/build.xml - - strap.clean: - - pack.clean: - - init.jars.check: - - init.jars: - [echo] Updating bootstrap libs. (To do this by hand, run ./pull-binary-libs.sh) - [exec] Resolving [943cd5c8802b2a3a64a010efb86ec19bac142e40/lib/ant/ant-contrib.jar] - - ... - - pack.bin: - [mkdir] Created dir: /Users/xeno_by/Projects/scala/build/pack/bin +* A Java SDK. The baseline version is 6 for 2.11.x and 8 for 2.12.x. It's possible to use a later SDK for local development, but the continuous integration builds will verify against the baseline version. +* `sbt`, an interactive build tool commonly used in Scala projects. Acquiring sbt manually is not necessary -- the recommended approach is to download the [sbt-extras runner script](https://github.com/paulp/sbt-extras/blob/master/sbt) and use it in place of `sbt`. The script will download and run the correct version of sbt when run from the Scala repository's root directory. +* `curl` -- the build uses `curl` in the `pull-binary-libs.sh` script to download bootstrap libs. - pack.done: +The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. - build: - - BUILD SUCCESSFUL - Total time: 9 minutes 41 seconds +Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. Be prepared to wait for a while -- a full "clean" build +takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary +with your hardware). ### IDE There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. -Both of those Scala plugins provide navigation, refactoring and error reporting functionality as well as integrated debugging. +Both of those Scala plugins provide navigation, refactoring, error reporting functionality, and integrated debugging. +See [the Scala README](https://github.com/scala/scala#ide-setup) for instructions on using Eclipse and IntelliJ IDEA with the Scala repository. There also exist lighter-weight editors such as Emacs, Sublime or jEdit which are faster and much less memory/compute-intensive to run, while lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, @@ -155,8 +133,8 @@ When hacking on your topic of choice, you'll be modifying Scala, compiling it an Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break by running a comprehensive test suite. -We'll start by creating a `sandbox` directory (this particular name doesn't bear any special meaning), which will hold a single test file and its compilation results. First, let's make sure that -[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `ant`. The Scala compiler that we just built is located in `build/pack/bin`. +We'll start by creating a `sandbox` directory (`./sandbox is listed in the .gitignore of the Scala repository), which will hold a single test file and its compilation results. First, let's make sure that +[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `sbt`. The Scala compiler that we just built is located in `build/pack/bin`. 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox @@ -178,31 +156,24 @@ Now, implement your bugfix or new feature! Here are also some tips & tricks that have proven useful in Scala development: * If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, - try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile - just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to - very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. + try doing `sbt clean`. Due to the way Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile + just that trait; it might also be necessary to recompile its users. The `sbt` tool is not smart enough to do that, which might lead to + very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take a lot of time -- the same 8-30 minutes as mentioned above. * Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, - some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts ([here](https://github.com/adriaanm/binfu/blob/master/scafu.sh) are some examples to get you started) to launch Scala from `build/quick/classes`. + some people in our team do `sbt compile` instead of `sbt dist/mkPack` and then create custom scripts using `sbt/mkBin` to launch Scala from `./build/quick/bin`. Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. -* You can publish your newly-built scala version locally to use it from sbt. Here's how: + to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use the Scala `showRaw` to get the `AST` representation. +* You can publish your newly-built scala version locally using `sbt publishLocal` to use it from `sbt`. Here's how: - $ ant publish-local-opt -Dmaven.version.suffix="-test" + $ sbt publishLocal // This may take a while + ... $ sbt - [info] Set current project to test (in build file:/Users/georgii/workspace/test/) - > set resolvers += Resolver.mavenLocal - [info] Defining *:resolvers - [info] The new value will be used by *:externalResolvers - [info] Reapplying settings... - [info] Set current project to test (in build file:/Users/georgii/workspace/test/) - > ++2.12.0-test - [info] Setting version to 2.12.0-test - [info] Set current project to test (in build file:/Users/georgii/workspace/test/) + ... > console [info] Starting scala interpreter... - [info] - Welcome to Scala version 2.12.0-20140623-155543-8bdacad317 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51). + [info] + Welcome to Scala version 2.10.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). Type in expressions to have them evaluated. Type :help for more information. @@ -212,7 +183,7 @@ Here are also some tips & tricks that have proven useful in Scala development: ### Documentation -There are several areas that one could contribute to-- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. +There are several areas that one could contribute to -- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. ##### The Scala Library @@ -263,22 +234,12 @@ but not tokens like `%n`. Looks like an easy fix. start = idx + 1 } -After applying the fix and running `ant`, our simple test case in `sandbox/Test.scala` started working! +After applying the fix and running `sbt compile`, our simple test case in `sandbox/Test.scala` started working! 18:51 ~/Projects/scala/sandbox (ticket/6725)$ cd .. - 18:51 ~/Projects/scala (ticket/6725)$ ant - Buildfile: /Users/xeno_by/Projects/scala/build.xml - + 18:51 ~/Projects/scala (ticket/6725)$ sbt compile ... - - quick.comp: - [scalacfork] Compiling 1 file to /Users/xeno_by/Projects/scala/build/quick/classes/compiler - [propertyfile] Updating property file: /Users/xeno_by/Projects/scala/build/quick/classes/compiler/compiler.properties - [stopwatch] [quick.comp.timer: 6.588 sec] - - ... - - BUILD SUCCESSFUL + [success] Total time: 18 s, completed Jun 6, 2016 9:03:02 PM Total time: 18 seconds 18:51 ~/Projects/scala (ticket/6725)$ cd sandbox @@ -332,15 +293,7 @@ Here are some more testing tips: [mima] } [mima] - BUILD FAILED - /localhome/jenkins/c/workspace/pr-scala-test/scala/build.xml:1530: The following error occurred while executing this line: - /localhome/jenkins/c/workspace/pr-scala-test/scala/build-ant-macros.xml:791: The following error occurred while executing this line: - /localhome/jenkins/c/workspace/pr-scala-test/scala/build-ant-macros.xml:773: Java returned: 2 - - Total time: 6 minutes 46 seconds - Build step 'Execute shell' marked build as failure - Archiving artifacts - Notifying upstream projects of job completion + ... Finished: FAILURE This means your change is backward or forward binary incompatible with the specified version (the check is performed by the [migration manager](https://github.com/typesafehub/migration-manager)). The error message is actually saying what you need to add to `bincompat-backward.whitelist.conf` or `bincompat-forward.whitelist.conf` to make the error go away. If you are getting this on an internal/experimental api, it should be safe to add suggested sections to the config. Otherwise, you might want to target a newer version of scala for this change. @@ -349,7 +302,7 @@ This means your change is backward or forward binary incompatible with the speci Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. Read up [the partest guide](partest-guide.html) to learn the details about partest, but in a nutshell you can either -run `ant test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: +run `sbt test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: 18:52 ~/Projects/scala/sandbox (ticket/6725)$ cd ../test 18:56 ~/Projects/scala/test (ticket/6725)$ partest files/run/*interpol* From 5532eb46c8ccd199485ee7dff88d97ec06f9e30d Mon Sep 17 00:00:00 2001 From: Chase Long Date: Tue, 7 Jun 2016 21:37:25 -0500 Subject: [PATCH 0096/2265] Changes per PR feedback --- contribute/hacker-guide.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index dab991eba5..09eb50a8a3 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -106,10 +106,10 @@ You need the following tools: * `sbt`, an interactive build tool commonly used in Scala projects. Acquiring sbt manually is not necessary -- the recommended approach is to download the [sbt-extras runner script](https://github.com/paulp/sbt-extras/blob/master/sbt) and use it in place of `sbt`. The script will download and run the correct version of sbt when run from the Scala repository's root directory. * `curl` -- the build uses `curl` in the `pull-binary-libs.sh` script to download bootstrap libs. -The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. +OS X and Linux builds should work. Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. Be prepared to wait for a while -- a full "clean" build -takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary +takes 5+ minutes depending on your machine (longer on older machines with less memory). Incremental builds are usually within 20-120 seconds range (again, your mileage might vary with your hardware). ### IDE @@ -155,12 +155,8 @@ Now, implement your bugfix or new feature! Here are also some tips & tricks that have proven useful in Scala development: -* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, - try doing `sbt clean`. Due to the way Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile - just that trait; it might also be necessary to recompile its users. The `sbt` tool is not smart enough to do that, which might lead to - very strange errors. Full rebuilds fix the problem. Fortunately that's rarely necessary, because full rebuilds take a lot of time -- the same 8-30 minutes as mentioned above. -* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, - some people in our team do `sbt compile` instead of `sbt dist/mkPack` and then create custom scripts using `sbt/mkBin` to launch Scala from `./build/quick/bin`. Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. +* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, some people in our team do `sbt compile` instead of `sbt dist/mkPack` and then create custom scripts using `sbt/mkBin` to launch Scala from `./build/quick/bin/`. Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. +* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try doing `sbt clean` and building again. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use the Scala `showRaw` to get the `AST` representation. @@ -300,9 +296,9 @@ This means your change is backward or forward binary incompatible with the speci ### Verify -Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. -Read up [the partest guide](partest-guide.html) to learn the details about partest, but in a nutshell you can either -run `sbt test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: +Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](http://junit.org/junit4/) and [partest](partest-guide.html), a tool we wrote for testing Scala. +Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, respectively. +`partest` (not `sbt partest`) also allows you to run a subset of the tests using wildcards: 18:52 ~/Projects/scala/sandbox (ticket/6725)$ cd ../test 18:56 ~/Projects/scala/test (ticket/6725)$ partest files/run/*interpol* From 1ea529f4b4c2372c17561398ca1927a004daf7d7 Mon Sep 17 00:00:00 2001 From: Chase Long Date: Mon, 13 Jun 2016 20:11:59 -0500 Subject: [PATCH 0097/2265] Correct misleading instructions for publishing a local Scala version --- contribute/hacker-guide.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 09eb50a8a3..3426f37f82 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -160,20 +160,26 @@ Here are also some tips & tricks that have proven useful in Scala development: * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use the Scala `showRaw` to get the `AST` representation. -* You can publish your newly-built scala version locally using `sbt publishLocal` to use it from `sbt`. Here's how: +* You can publish your newly-built scala version locally using `sbt publishLocal`. Then, you can invoke a REPL using your version: $ sbt publishLocal // This may take a while ... $ sbt ... - > console - [info] Starting scala interpreter... - [info] - Welcome to Scala version 2.10.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). - Type in expressions to have them evaluated. - Type :help for more information. - - scala> + > scala + [info] Running scala.tools.nsc.MainGenericRunner -usejavacp + Welcome to Scala 2.12.0-20160613-195040-cd85531 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). + Type in expressions for evaluation. Or try :help. + + scala> + +Alternatively, you can invoke a REPL using the bash script in `./build/quick/bin/`: + + $ ./build/quick/bin/scala + Welcome to Scala 2.12.0-20160613-195040-cd85531 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). + Type in expressions for evaluation. Or try :help. + + scala> * Adding a macro to the `Predef` object is a pretty involved task. Due to bootstrapping, you cannot just throw a macro into it. For this reason, the process is more involved. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you have to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. [Here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. From 2a94e25b660c8eed80c3e412933d61a2a7eb1835 Mon Sep 17 00:00:00 2001 From: Alex Xandra Albert Sim Date: Wed, 14 Sep 2016 16:27:15 +0700 Subject: [PATCH 0098/2265] Update Ensime's contributing and readme page The current "readme" and "contributing" links on Ensime gives us a standard Github 404 page. This commit updates the links to valid URLs. --- contribute/tools.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 1757ae1005..494d2e54cf 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -76,8 +76,8 @@ Stuff changes. Found a broken link or something that needs updating on this page

Scala Support for Text Editors

Home | Issues | -ReadMe | -Contributing

+ReadMe | +Contributing

@@ -126,4 +126,4 @@ The following projects are important to the Scala community but are particularly - \ No newline at end of file + From a41edfc053abb0e97d951e9fdd462ebec99135e8 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 26 Oct 2016 10:54:45 -0700 Subject: [PATCH 0099/2265] Implement some review feedback, some polish of my own Reworks #438 --- contribute/hacker-guide.md | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 3426f37f82..09532edecd 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -108,9 +108,9 @@ You need the following tools: OS X and Linux builds should work. Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. -Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. Be prepared to wait for a while -- a full "clean" build -takes 5+ minutes depending on your machine (longer on older machines with less memory). Incremental builds are usually within 20-120 seconds range (again, your mileage might vary -with your hardware). +Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. In general, it's much more efficient to enter the `sbt` shell once and run the various tasks from there, instead of running each task by launching `sbt some-task` on your command prompt. + +Be prepared to wait for a while -- a full "clean" build takes 5+ minutes depending on your machine (longer on older machines with less memory). On a recent laptop, incremental builds usually complete within 10-30 seconds. ### IDE @@ -155,31 +155,33 @@ Now, implement your bugfix or new feature! Here are also some tips & tricks that have proven useful in Scala development: -* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, some people in our team do `sbt compile` instead of `sbt dist/mkPack` and then create custom scripts using `sbt/mkBin` to launch Scala from `./build/quick/bin/`. Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. -* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try doing `sbt clean` and building again. +* After building your working copy with the `compile` sbt task, there's no need to leave the comfort of your sbt shell to try it out: the REPL is available as the `scala` task, and you can also run the compiler using the `scalac` task. If you prefer to run the REPL outside sbt, you can generate the scripts in `build/quick/bin` using the `dist/mkQuick` task. +* The sbt workflow is also great for debugging, as you can simply create a remote debugging session in your favorite IDE, and then activate the JVM options for the next time you run the `scala` or `scalac` tasks using: + +``` +> set javaOptions in compiler := List("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8002") +> scalac test.scala +[info] Running scala.tools.nsc.Main -usejavacp test.scala +Listening for transport dt_socket at address: 8002 +``` + +* Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. +* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try the `clean` task and building again. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use the Scala `showRaw` to get the `AST` representation. -* You can publish your newly-built scala version locally using `sbt publishLocal`. Then, you can invoke a REPL using your version: - - $ sbt publishLocal // This may take a while - ... - $ sbt - ... - > scala - [info] Running scala.tools.nsc.MainGenericRunner -usejavacp - Welcome to Scala 2.12.0-20160613-195040-cd85531 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). - Type in expressions for evaluation. Or try :help. - - scala> - -Alternatively, you can invoke a REPL using the bash script in `./build/quick/bin/`: - - $ ./build/quick/bin/scala - Welcome to Scala 2.12.0-20160613-195040-cd85531 (OpenJDK 64-Bit Server VM, Java 1.8.0_91). - Type in expressions for evaluation. Or try :help. - - scala> + to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. +* You can publish your newly-built scala version locally using the `publishLocal` task in sbt. +* It's convenient to enable the following local settings to speed up your workflow (put these in `local.sbt` in your working copy): +``` +// skip docs for local publishing +publishArtifact in (Compile, packageDoc) in ThisBuild := false +// set version based on current sha, so that you can easily consume this build from another sbt project +baseVersionSuffix := s"local-${Process("tools/get-scala-commit-sha").lines.head.substring(0, 7)}" +// show more logging during a partest run +testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")) +// if incremental compilation is compiling too much (should be fine under sbt 0.13.13) +// antStyle := true +``` * Adding a macro to the `Predef` object is a pretty involved task. Due to bootstrapping, you cannot just throw a macro into it. For this reason, the process is more involved. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you have to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. [Here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. From 6a5ddf970a857b71779f8e023147ac299f2b0d8d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 8 Nov 2016 14:11:21 -0800 Subject: [PATCH 0100/2265] fix Github -> GitHub --- contribute/codereviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 1b9a881b0c..a2df66bd10 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -43,7 +43,7 @@ own pull requests.

The Scala language web site.

-

All Scala Github Projects

+

All Scala GitHub Projects

For other PRs, follow the scala project from here.

From 78590ba20a3272880bd47994e5a31c7cbae24f01 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 15 Nov 2016 15:27:38 -0800 Subject: [PATCH 0101/2265] recommend sbt, not Activator and remove all mention of Activator from the site (well, except from some old release announcements) --- contribute/documentation.md | 8 -------- contribute/index.md | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index 6b5c81a0fc..b499571154 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -7,7 +7,6 @@ title: Documentation Contributions There are several ways you can help out with the improvement of Scala documentation. These include: * API Documentation in Scaladoc -* Code examples and tutorials in activator templates. * Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site * Updating scala-lang.org @@ -28,13 +27,6 @@ Please *follow the issue submission process closely* to help prevent duplicate i [submit new Scaladoc](./scala-standard-library-api-documentation.html) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. -### Examples/Tutorials in Activator Templates - -[Lightbend Activator](https://www.lightbend.com/community/core-tools/activator-and-sbt) -is a tool based on SBT, with a UI mode that is ideal for code based tutorials, overviews and walk-throughs. To contribute an example in activator, you can fork an existing template, edit it, add a tutorial, upload it to github and then submit the github project into the template repository. It's the fastest way to produce a working code example with tutorial. - -Please see [Contributing an Activator Template](https://www.lightbend.com/activator/template/contribute) for more details. - ### The Main Scala Documentation Site [docs.scala-lang.org](https://wiki.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a github project that you can fork and submit pull requests from. It includes: diff --git a/contribute/index.md b/contribute/index.md index 925e83248e..0a1e2fbaef 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -27,7 +27,7 @@ Coordination of contribution efforts takes place on the
From 891183e26da4c3f9ccbea5b5bb888aa40e682469 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Wed, 16 Nov 2016 14:05:22 +0100 Subject: [PATCH 0102/2265] fix a lot of broken links --- contribute/codereviews.md | 2 +- contribute/documentation.md | 3 +-- contribute/guide.md | 9 ++++----- contribute/hacker-guide.md | 2 +- contribute/index.md | 2 +- contribute/scala-standard-library-api-documentation.md | 2 +- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index a2df66bd10..d0d9a111c3 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -5,7 +5,7 @@ title: Code Review Contributions ## Code Review Contributions In addition to [bug fixing](./guide.html), you can help us review -[waiting pull requests](#pull_requests_awaiting_comment). +[waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your own pull requests. diff --git a/contribute/documentation.md b/contribute/documentation.md index 6b5c81a0fc..27aab024d2 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -21,7 +21,7 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute_api_documentation_bug_reports) - +* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. * [Claim Scaladoc Issues and Provide Documentation](./scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just @@ -61,4 +61,3 @@ to Scala and related projects) is provided on the main Please read both the [docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the [scala-lang.org github README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. - diff --git a/contribute/guide.md b/contribute/guide.md index b92bd2fe89..02b560b7fc 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -17,7 +17,7 @@ title: Contributing guide
-

Community issues

+

Community issues

Get cracking on some easy to approach issues.

@@ -52,9 +52,9 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/index.html#community_tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please -[make sure it's not a duplicate](./bug-reporting-guide.html#reporting_confirmed_bugs_is_a_sin)). -2. Optional ([but recommended](./scala-internals.html#why_its_a_good_idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with +1. [Select a bug to fix from JIRA](/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please +[make sure it's not a duplicate](./bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). +2. Optional ([but recommended](./scala-internals.html#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with [these friendly people](./hacker-guide.html#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](./hacker-guide.html#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](./hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. @@ -77,4 +77,3 @@ on the [scala-internals](http://groups.google.com/group/scala-internals) mailing Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. - diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 09532edecd..897c97b1a2 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -28,7 +28,7 @@ Sometimes it's appealing to hack alone and not to have to interact with others o this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel +Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#mailing-lists) to find out how people feel about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. diff --git a/contribute/index.md b/contribute/index.md index 925e83248e..2fdf75fc71 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -56,7 +56,7 @@ Coordination of contribution efforts takes place on the

Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects.

-

Compiler/Language

+

Compiler/Language

Larger language features and compiler enhancements including language specification and SIPs.

diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index bc57a163df..37e84bd76e 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -75,7 +75,7 @@ component so that they show up in the correct issue filters. Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](./hacker-guide.html#2_set_up) - follow the setup steps through +* [Forking the Repo](./hacker-guide.html#set-up) - follow the setup steps through the Branch section. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated JIRA issue, use `scaladoc/xxxx` instead. From ffe3a69da6552a2a9a56da52b92d97665fb46863 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Thu, 17 Nov 2016 08:52:08 +0100 Subject: [PATCH 0103/2265] fix blank alt tags --- contribute/tools.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 494d2e54cf..877297636c 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -24,7 +24,7 @@ Stuff changes. Found a broken link or something that needs updating on this page
- +sbt logo

sbt

Interactive build tool.

Home | @@ -33,7 +33,7 @@ Stuff changes. Found a broken link or something that needs updating on this page Contributing

- +scala logo

Scaladoc Tool

(Contribute through scala/scala)

Home | @@ -45,7 +45,7 @@ Stuff changes. Found a broken link or something that needs updating on this page

-

Scala IDE

+scala IDE logo

Scala IDE

The Eclipse Scala IDE project.

Home | Issues | @@ -53,7 +53,7 @@ Stuff changes. Found a broken link or something that needs updating on this page Contributing

-

DBuild

+dbuild logo

DBuild

Multi-project build tool.

Home | Issues | @@ -64,7 +64,7 @@ Stuff changes. Found a broken link or something that needs updating on this page

- +scala logo

Partest

Scala Compiler/Library Testing

Home | @@ -72,7 +72,7 @@ Stuff changes. Found a broken link or something that needs updating on this page ReadMe

-

Ensime

+ensime logo

Ensime

Scala Support for Text Editors

Home | Issues | @@ -83,7 +83,7 @@ Stuff changes. Found a broken link or something that needs updating on this page

-

Scoverage

+scoverage logo

Scoverage

Scala code coverage tool

Home | Issues | @@ -91,7 +91,7 @@ Stuff changes. Found a broken link or something that needs updating on this page Contributing

- +scala logo

Abide

Lint tooling for Scala

Home | @@ -109,7 +109,7 @@ The following projects are important to the Scala community but are particularly

- +scala logo

Scalap

Scala Decoder (part of scala/scala)

Issues | @@ -117,7 +117,7 @@ The following projects are important to the Scala community but are particularly Contributing

-

Scalariform

+white line

Scalariform

Scala code formatter

Home | Issues | From c46edc10b100bb44c25a54356e12b708b6975153 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Sat, 19 Nov 2016 09:55:19 -0500 Subject: [PATCH 0104/2265] Fix formatting problems in hacker guide --- contribute/hacker-guide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 897c97b1a2..db4e06e037 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -133,7 +133,7 @@ When hacking on your topic of choice, you'll be modifying Scala, compiling it an Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break by running a comprehensive test suite. -We'll start by creating a `sandbox` directory (`./sandbox is listed in the .gitignore of the Scala repository), which will hold a single test file and its compilation results. First, let's make sure that +We'll start by creating a `sandbox` directory (`./sandbox` is listed in the .gitignore of the Scala repository), which will hold a single test file and its compilation results. First, let's make sure that [the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `sbt`. The Scala compiler that we just built is located in `build/pack/bin`. 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox @@ -172,6 +172,7 @@ Listening for transport dt_socket at address: 8002 to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. * You can publish your newly-built scala version locally using the `publishLocal` task in sbt. * It's convenient to enable the following local settings to speed up your workflow (put these in `local.sbt` in your working copy): + ``` // skip docs for local publishing publishArtifact in (Compile, packageDoc) in ThisBuild := false From c27f49c1cd951c31f7d3f2bf9b07f5d362acb967 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Sun, 20 Nov 2016 09:47:02 +0100 Subject: [PATCH 0105/2265] fix miscellaneous links --- contribute/tools.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 877297636c..008a1425a1 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -12,12 +12,12 @@ Typically, issues for these projects will be reported and kept in the github pro Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. There are some projects in this section that are in -[particular need](#projects_in_particular_need) so please check those out +[particular need](#projects-in-particular-need) so please check those out if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating_scalalangorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating-scala-langorg) to fix it. ### Projects From f2b3a20ec9486c615eed8146248a9c23e450adef Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 7 Dec 2016 12:47:28 -0800 Subject: [PATCH 0106/2265] 2.11 -> 2.12 in some more places --- contribute/hacker-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index db4e06e037..8d7903fbea 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -8,7 +8,7 @@ This guide is intended to help you get from an idea of fixing a bug or implement This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. -Other good starting points for first-time contributors include the [Scala README](https://github.com/scala/scala#get-in-touch) and [contributor's guidelines](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md). +Other good starting points for first-time contributors include the [Scala README](https://github.com/scala/scala#get-in-touch) and [contributor's guidelines](https://github.com/scala/scala/blob/2.12.x/CONTRIBUTING.md). ## The Running Example @@ -336,7 +336,7 @@ Let's go into each of these points in more detail. The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. There are two things you should know here: -1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policies](https://github.com/scala/scala/blob/2.11.x/CONTRIBUTING.md) for more information about the desired style of your commits. +1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policies](https://github.com/scala/scala/blob/2.12.x/CONTRIBUTING.md) for more information about the desired style of your commits. 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on GitHub. From 1a258055bd0966a517c50f8113516e53f2393ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20de=20Sil=C3=B3niz=20Sandino?= Date: Wed, 8 Feb 2017 13:11:11 +0100 Subject: [PATCH 0107/2265] First migration of content pages to new content layout - First migration to using pretty permalinks --- contribute/bug-reporting-guide.md | 4 ++- contribute/codereviews.md | 10 ++++--- contribute/corelibs.md | 10 ++++--- contribute/documentation.md | 10 ++++--- contribute/guide.md | 30 ++++++++++--------- contribute/hacker-guide.md | 4 ++- contribute/index.md | 22 +++++++------- contribute/partest-guide.md | 4 ++- contribute/scala-internals.md | 4 ++- ...cala-standard-library-api-documentation.md | 4 ++- contribute/tools.md | 12 ++++---- 11 files changed, 68 insertions(+), 46 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 960f40b704..f4c8282a78 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -1,6 +1,8 @@ --- -layout: page title: Bug Reporting +layout: inner-page-no-masthead +permalink: /contribute/bug-reporting-guide/ +includeTOC: true --- The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. diff --git a/contribute/codereviews.md b/contribute/codereviews.md index d0d9a111c3..9239fa8c14 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -1,10 +1,12 @@ --- -layout: page title: Code Review Contributions +layout: inner-page-no-masthead +permalink: /contribute/codereviews/ +includeTOC: true --- ## Code Review Contributions -In addition to [bug fixing](./guide.html), you can help us review +In addition to [bug fixing](/contribute/guide/), you can help us review [waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your @@ -13,7 +15,7 @@ own pull requests. ### Review Guidelines -[Code of Conduct reminder](../conduct.html) +[Code of Conduct reminder](/conduct/) * Keep comments on-topic, concise and precise. * Attach comments to particular lines or regions they pertain to whenever possible. @@ -49,4 +51,4 @@ own pull requests.

-Also note that the [Tools contributions](./tools.html) page has more projects that will generate pull requests. +Also note that the [Tools contributions](/contribute/tools/) page has more projects that will generate pull requests. diff --git a/contribute/corelibs.md b/contribute/corelibs.md index 6e1abbb0d7..1f34d150b0 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -1,14 +1,16 @@ --- -layout: page title: Core Library Contributions +layout: inner-page-no-masthead +permalink: /contribute/corelibs/ +includeTOC: true --- ## Core Library Contributions There are several options for contributing to Scala's core libraries. You can: -* Help with [Documentation](./scala-standard-library-api-documentation.html). -* [Report Bugs or Issues](./bug-reporting-guide.html) against the core libraries. -* [Fix Bugs or Issues](./guide.html) against the +* Help with [Documentation](/contribute/scala-standard-library-api-documentation/). +* [Report Bugs or Issues](/contribute/bug-reporting-guide/) against the core libraries. +* [Fix Bugs or Issues](/contribute/guide/) against the [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). * Contribute significant new functionality or a new API by submitting a Scala Library Improvement Process (SLIP) Document. diff --git a/contribute/documentation.md b/contribute/documentation.md index 7657cbf699..2746fa77dc 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -1,6 +1,8 @@ --- -layout: page title: Documentation Contributions +layout: inner-page-no-masthead +permalink: /contribute/documentation/ +includeTOC: true --- ## Contributing Documentation to the Scala project @@ -20,11 +22,11 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation/#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. -* [Claim Scaladoc Issues and Provide Documentation](./scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation/) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just -[submit new Scaladoc](./scala-standard-library-api-documentation.html) +[submit new Scaladoc](/contribute/scala-standard-library-api-documentation/) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. ### The Main Scala Documentation Site diff --git a/contribute/guide.md b/contribute/guide.md index 02b560b7fc..afd3572c53 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -1,6 +1,8 @@ --- -layout: page title: Contributing guide +layout: inner-page-no-masthead +permalink: /contribute/guide/ +includeTOC: true ---
@@ -10,7 +12,7 @@ title: Contributing guide

Get a peek into the inners of the Scala compiler.

-

Report an issue

+

Report an issue

File a bug report or a feature request.

@@ -21,7 +23,7 @@ title: Contributing guide

Get cracking on some easy to approach issues.

-

Hacker's guide

+

Hacker's guide

Learn to write good code and improve your chances of contributing to the Scala galaxy.

@@ -52,19 +54,19 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](./bug-reporting-guide.html) (but please -[make sure it's not a duplicate](./bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](./scala-internals.html#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](./scala-internals.html). After all, don't you want to work on a team with -[these friendly people](./hacker-guide.html#connect) - it's one of the perks of contributing. -3. [Fork the Scala repository](./hacker-guide.html#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](./hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. -5. [Fix the bug, or implement the new small feature](./hacker-guide.html#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](./hacker-guide.html#test) and [test some more](./partest-guide.html) until [all the tests pass](./hacker-guide.html#verify). -7. [Commit your changes](./hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. +1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide/) (but please +[make sure it's not a duplicate](/contribute/bug-reporting-guide/#reporting-confirmed-bugs-is-a-sin)). +2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](/contribute/scala-internals/). After all, don't you want to work on a team with +[these friendly people](/contribute/hacker-guide/#connect) - it's one of the perks of contributing. +3. [Fork the Scala repository](/contribute/hacker-guide/#fork) and clone your fork (if you haven't already). +4. [Create a feature branch](/contribute/hacker-guide/#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. +5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide/#implement), include new tests (yes, for bug fixes too). +6. [Test, rinse](/contribute/hacker-guide/#test) and [test some more](/contribute/partest-guide/) until [all the tests pass](/contribute/hacker-guide/#verify). +7. [Commit your changes](/contribute/hacker-guide#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](http://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) 9. [Submit a pull request](./hacker-guide.html#submit) following the [Scala project pull-request guidelines](http://docs.scala-lang.org/scala/pull-request-policy.html). -10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](./hacker-guide.html#review). +10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide/#review). 11. Celebrate! Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](./hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). @@ -76,4 +78,4 @@ and on the implementation plan. Announce the change on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. +the Scala project source tree. The [hacker guide](/contribute/hacker-guide/) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 8d7903fbea..ebdad9652b 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -1,7 +1,9 @@ --- -layout: page title: Scala hacker guide by: Eugene Burmako +layout: inner-page-no-masthead +permalink: /contribute/hacker-guide/ +includeTOC: true ---
This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. diff --git a/contribute/index.md b/contribute/index.md index 1a2f7c7c5b..dcc78e8149 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,6 +1,8 @@ --- -layout: page title: Contribute +layout: inner-page-no-masthead +permalink: /contribute/ +includeTOC: true --- The Scala programming language is an open source project with a very @@ -26,37 +28,37 @@ Coordination of contribution efforts takes place on the
-

Bug Fixes

-

Issues with the tools, core libraries and compiler. Also you can help us by reporting bugs

+

Bug Fixes

+

Issues with the tools, core libraries and compiler. Also you can help us by reporting bugs

-

Code Reviews

+

Code Reviews

Review pull requests against scala/scala, scala/scala-lang, scala/scala.github.com and others.

-

Core Libraries

+

Core Libraries

Update and expand the capabilities of the core (and associated) Scala libraries.

-

IDE and Build Tools

+

IDE and Build Tools

Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects.

-

Compiler/Language

+

Compiler/Language

Larger language features and compiler enhancements including language specification and SIPs.

@@ -109,7 +111,7 @@ with their own maintainers and community of contributors. Helping out one of these projects is another way to help Scala. Consider lending on a hand on a project you're already using. Or, to find out about other projects, see the -[Libraries and Tools section](../community/index.html#community-libraries-and-tools) +[Libraries and Tools section](../community/#community-libraries-and-tools) on our Community page. ### Scala Community Build diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index e681c569fe..be37d6fc12 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -1,6 +1,8 @@ --- -layout: page title: Running the Test Suite +layout: inner-page-no-masthead +permalink: /contribute/partest-guide/ +includeTOC: true --- Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go the scala project folder from your local checkout and run it via `ant` or standalone as follows. diff --git a/contribute/scala-internals.md b/contribute/scala-internals.md index 5bd97ed8a8..831f2cc864 100644 --- a/contribute/scala-internals.md +++ b/contribute/scala-internals.md @@ -1,6 +1,8 @@ --- -layout: page title: Scala Internals Mailing List +layout: inner-page-no-masthead +permalink: /contribute/scala-internals/ +includeTOC: true --- ## scala-internals diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 37e84bd76e..68df995375 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -1,6 +1,8 @@ --- -layout: page title: Contribute to API Documentation +layout: inner-page-no-masthead +permalink: /contribute/scala-standard-library-api-documentation/ +includeTOC: true --- This page is specific to API documentation contributions – that is, API diff --git a/contribute/tools.md b/contribute/tools.md index 008a1425a1..876ce88c1c 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -1,12 +1,14 @@ --- -layout: page title: IDE and Build Tool Contributions +layout: inner-page-no-masthead +permalink: /contribute/tools/ +includeTOC: true --- ## Contributing to IDE and Build Tools The links below are to a number of Scala build and IDE related projects that are important in the larger Scala space, and which welcome contributions. -Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](./hacker-guide.html) and [Bug-fixing](guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. +Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/contribute/hacker-guide/) and [Bug-fixing](/contribute/guide/) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. Typically, issues for these projects will be reported and kept in the github project issue tracker for that project rather than in the Scala project JIRA. Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. @@ -17,7 +19,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](./documentation.html#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation/#updating-scala-langorg) to fix it. ### Projects @@ -39,7 +41,7 @@ Stuff changes. Found a broken link or something that needs updating on this page

Home | Issues | ReadMe | -Contributing

+Contributing

@@ -114,7 +116,7 @@ The following projects are important to the Scala community but are particularly

Scala Decoder (part of scala/scala)

Issues | ReadMe | -Contributing

+Contributing

white line

Scalariform

From b58955fa85531e7be82639d5d6acf44b779f0f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20de=20Sil=C3=B3niz=20Sandino?= Date: Wed, 8 Feb 2017 17:25:34 +0100 Subject: [PATCH 0108/2265] Short items list for the contribute subpages --- _contribute_resources/1-documentation.md | 6 + _contribute_resources/2-bug-fixes.md | 6 + _contribute_resources/3-code-reviews.md | 8 + _contribute_resources/4-core-libraries.md | 6 + .../5-ide-and-build-tools.md | 6 + _contribute_resources/6-compiler-language.md | 6 + contribute/index.md | 74 +------ contribute/tools.md | 187 ++++++++---------- 8 files changed, 126 insertions(+), 173 deletions(-) create mode 100644 _contribute_resources/1-documentation.md create mode 100644 _contribute_resources/2-bug-fixes.md create mode 100644 _contribute_resources/3-code-reviews.md create mode 100644 _contribute_resources/4-core-libraries.md create mode 100644 _contribute_resources/5-ide-and-build-tools.md create mode 100644 _contribute_resources/6-compiler-language.md diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md new file mode 100644 index 0000000000..27739dee6a --- /dev/null +++ b/_contribute_resources/1-documentation.md @@ -0,0 +1,6 @@ +--- +title: Documentation +link: /contribute/documentation/ +icon: fa fa-file-text +--- +[Scaladoc (API)](/contribute/scala-standard-library-api-documentation/),[docs.scala-lang.org](http://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). \ No newline at end of file diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md new file mode 100644 index 0000000000..d10adb7908 --- /dev/null +++ b/_contribute_resources/2-bug-fixes.md @@ -0,0 +1,6 @@ +--- +title: Bug fixes +link: /contribute/guide/ +icon: fa fa-pencil +--- +Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide/). \ No newline at end of file diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md new file mode 100644 index 0000000000..2ab235993b --- /dev/null +++ b/_contribute_resources/3-code-reviews.md @@ -0,0 +1,8 @@ +--- +title: Code Reviews +link: /contribute/codereviews/ +icon: fa fa-eye +--- +Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), +[scala/scala-lang](https://github.com/scala/scala-lang/pulls), +[scala/scala.github.com](https://github.com/scala/scala.github.com/pulls)and others. \ No newline at end of file diff --git a/_contribute_resources/4-core-libraries.md b/_contribute_resources/4-core-libraries.md new file mode 100644 index 0000000000..7ad75c5752 --- /dev/null +++ b/_contribute_resources/4-core-libraries.md @@ -0,0 +1,6 @@ +--- +title: Core Libraries +link: /contribute/corelibs/ +icon: fa fa-clipboard +--- +Update and expand the capabilities of the core (and associated) Scala libraries. \ No newline at end of file diff --git a/_contribute_resources/5-ide-and-build-tools.md b/_contribute_resources/5-ide-and-build-tools.md new file mode 100644 index 0000000000..4b8bd2ed52 --- /dev/null +++ b/_contribute_resources/5-ide-and-build-tools.md @@ -0,0 +1,6 @@ +--- +title: IDE and Build Tools +link: /contribute/tools/ +icon: fa fa-terminal +--- +Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects. \ No newline at end of file diff --git a/_contribute_resources/6-compiler-language.md b/_contribute_resources/6-compiler-language.md new file mode 100644 index 0000000000..0c4eaa1325 --- /dev/null +++ b/_contribute_resources/6-compiler-language.md @@ -0,0 +1,6 @@ +--- +title: Compiler/Language +link: /contribute/guide/#larger-changes-new-features +icon: fa fa-gears +--- +Larger language features and compiler enhancements including language specification and SIPs. \ No newline at end of file diff --git a/contribute/index.md b/contribute/index.md index dcc78e8149..e843ef2f02 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -25,84 +25,14 @@ how to efficiently report a bug. Coordination of contribution efforts takes place on the [scala-internals Google group](./scala-internals.html). -
-
- -
-

Bug Fixes

-

Issues with the tools, core libraries and compiler. Also you can help us by reporting bugs

-
-
- -
-
-

Code Reviews

-

Review pull requests against scala/scala, -scala/scala-lang, -scala/scala.github.com and others.

-
-
-

Core Libraries

-

Update and expand the capabilities of the core (and associated) Scala libraries.

-
-
- -
-
-

IDE and Build Tools

-

Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects.

-
-
-

Compiler/Language

-

Larger language features and compiler enhancements including language specification and SIPs.

-
-
-
+{% include column-list-of-items.html collection=site.contribute_resources %} ### Community Tickets The following links provide starting points for various contributor activities: -
-
-
-

Documentation

-

Help augment or correct the documentation.

-
-
-

Core Libraries

-

Community bugs and enhancements on the core libs.

-
-
- -
-
-

Tools

-

Help with the Scala tool chain.

-
-
-

Compiler

-

Ready for a challenge? Here's the compiler bugs.

-
-
- -
-
-

Bugs

-

All bugs marked with the label community.

-
-
-

All Issues

-

Bugs + Enhancements marked with the label community.

-
-
-
+{% include column-list-of-items.html collection=site.contribute_community_tickets %} ### Tools and Libraries diff --git a/contribute/tools.md b/contribute/tools.md index 876ce88c1c..420579913e 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -3,6 +3,90 @@ title: IDE and Build Tool Contributions layout: inner-page-no-masthead permalink: /contribute/tools/ includeTOC: true + +# Projects list: +projects: + - title: sbt + description: Interactive build tool. + icon: http://www.scala-sbt.org/assets/typesafe_sbt_svg.svg + link: https://github.com/sbt/sbt + homeLink: http://www.scala-sbt.org/ + issuesLink: https://github.com/sbt/sbt#issues-and-pull-requests + readmeLink: https://github.com/sbt/sbt/blob/0.13/README.md + contributingLink: https://github.com/sbt/sbt/blob/0.13/CONTRIBUTING.md + - title: Scaladoc Tool + description: (Contribute through scala/scala) + icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 + link: https://github.com/scala/scala + homeLink: http://www.scala-lang.org/api + issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20component%20%3D%20%22Scaladoc%20Tool%22 + readmeLink: https://github.com/scala/scala#welcome + contributingLink: http://scala-lang.org/contribute/guide.html + - title: Scala IDE + description: Interactive build tool. + icon: https://avatars2.githubusercontent.com/u/1026788?v=3&s=200 + link: https://github.com/scala-ide/scala-ide + homeLink: http://scala-ide.org/ + issuesLink: http://scala-ide-portfolio.assembla.com/spaces/scala-ide/support/tickets + readmeLink: https://github.com/scala-ide/scala-ide/blob/master/README.md + contributingLink: https://github.com/scala-ide/scala-ide/blob/master/CONTRIBUTING.md + - title: DBuild + description: Multi-project build tool. + icon: https://avatars3.githubusercontent.com/u/784923?v=3&s=200 + link: https://github.com/typesafehub/dbuild + homeLink: http://typesafehub.github.io/dbuild + issuesLink: https://github.com/typesafehub/dbuild/issues + readmeLink: https://github.com/typesafehub/dbuild/blob/master/README.md + contributingLink: https://github.com/typesafehub/dbuild/blob/master/README.md#get-involved + - title: Partest + description: Scala Compiler/Library Testing + icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 + link: https://github.com/scala/scala-partest + homeLink: http://docs.scala-lang.org/tutorials/partest-guide.html + issuesLink: https://github.com/scala/scala-partest/issues + readmeLink: https://github.com/scala/scala-partest/blob/master/README.md + contributingLink: + - title: Ensime + description: Scala Support for Text Editors + icon: https://avatars0.githubusercontent.com/u/5089042?v=3&s=200 + link: https://github.com/ensime/ensime-server + homeLink: http://ensime.github.io/ + issuesLink: https://github.com/ensime/ensime-server/issues + readmeLink: https://github.com/ensime/ensime-server/blob/2.0/README.md + contributingLink: https://ensime.github.io/contributing/ + - title: Scoverage + description: Scala code coverage tool + icon: https://avatars1.githubusercontent.com/u/5998302?v=3&s=200 + link: https://github.com/scoverage/scalac-scoverage-plugin + homeLink: http://scoverage.org/ + issuesLink: https://github.com/scoverage/scalac-scoverage-plugin/issues + readmeLink: https://github.com/scoverage/scalac-scoverage-plugin/blob/master/README.md + contributingLink: https://groups.google.com/forum/#!forum/scala-code-coverage-tool + - title: Abide + description: Lint tooling for Scala + icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 + link: https://github.com/scala/scala-abide + homeLink: https://github.com/scala/scala-abide#abide--lint-tooling-for-scala + issuesLink: https://github.com/scala/scala-abide/issues + readmeLink: https://github.com/scala/scala-abide/blob/master/README.md + contributingLink: https://github.com/scala/scala-abide#extending-abide + +projectsInNeed: + - title: Scalap + description: Scala Decoder (part of scala/scala) + icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 + link: https://github.com/scala/scala + homeLink: + issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20text%20~%20%22scalap%22 + readmeLink: https://github.com/scala/scala#welcome + contributingLink: https://github.com/sbt/sbt/blob/0.13/CONTRIBUTING.md + - title: Scaladoc Tool + description: (Contribute through scala/scala) + icon: /resources/img/white-line.png + link: https://github.com/mdr/scalariform + homeLink: https://github.com/mdr/scalariform/wiki/Command-line-tool + issuesLink: https://github.com/mdr/scalariform/issues + readmeLink: https://github.com/mdr/scalariform/blob/master/README.rst --- ## Contributing to IDE and Build Tools @@ -23,109 +107,10 @@ Stuff changes. Found a broken link or something that needs updating on this page ### Projects -
-
-
-sbt logo -

sbt

-

Interactive build tool.

-

Home | -Issues | -ReadMe | -Contributing

-
-
-scala logo -

Scaladoc Tool

-

(Contribute through scala/scala)

-

Home | -Issues | -ReadMe | -Contributing

-
-
- -
-
-scala IDE logo

Scala IDE

-

The Eclipse Scala IDE project.

-

Home | -Issues | -ReadMe | -Contributing

-
-
-dbuild logo

DBuild

-

Multi-project build tool.

-

Home | -Issues | -ReadMe | -Contributing

-
-
- -
-
-scala logo -

Partest

-

Scala Compiler/Library Testing

-

Home | -Issues | -ReadMe

-
-
-ensime logo

Ensime

-

Scala Support for Text Editors

-

Home | -Issues | -ReadMe | -Contributing

-
-
- -
-
-scoverage logo

Scoverage

-

Scala code coverage tool

-

Home | -Issues | -ReadMe | -Contributing

-
-
-scala logo -

Abide

-

Lint tooling for Scala

-

Home | -Issues | -ReadMe | -Contributing

-
-
-
+{% include contributions-projects-list.html collection=page.projects %} ### Projects in Particular Need The following projects are important to the Scala community but are particularly in need of contributors to continue their development. -
-
-
-scala logo -

Scalap

-

Scala Decoder (part of scala/scala)

-

Issues | -ReadMe | -Contributing

-
-
-white line

Scalariform

-

Scala code formatter

-

Home | -Issues | -ReadMe

-
-
-
- - +{% include contributions-projects-list.html collection=page.projectsInNeed %} \ No newline at end of file From 0aa2f7f9660ea580cc661899ece1f99106f99c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20de=20Sil=C3=B3niz=20Sandino?= Date: Thu, 9 Feb 2017 12:10:38 +0100 Subject: [PATCH 0109/2265] Adding code of conduct --- contribute/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contribute/index.md b/contribute/index.md index e843ef2f02..f0c52986b8 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -17,13 +17,13 @@ That depends on what you want to contribute. Below are some getting started reso ### Reporting bugs -See our [bug reporting guide](./bug-reporting-guide.html) to learn +See our [bug reporting guide](/contribute/bug-reporting-guide/) to learn how to efficiently report a bug. ### Contribute Coordination of contribution efforts takes place on the -[scala-internals Google group](./scala-internals.html). +[scala-internals Google group](/contribute/scala-internals/). {% include column-list-of-items.html collection=site.contribute_resources %} @@ -41,7 +41,7 @@ with their own maintainers and community of contributors. Helping out one of these projects is another way to help Scala. Consider lending on a hand on a project you're already using. Or, to find out about other projects, see the -[Libraries and Tools section](../community/#community-libraries-and-tools) +[Libraries and Tools section](/community/#community-libraries-and-tools) on our Community page. ### Scala Community Build From 32684bae5d915d7bcf7ce69c860c2930c5f89d6b Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Tue, 20 Jun 2017 10:19:33 +0100 Subject: [PATCH 0110/2265] Update bug reporting links --- contribute/bug-reporting-guide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 960f40b704..13a7553c88 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -3,7 +3,7 @@ layout: page title: Bug Reporting --- -The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. +The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. ## Is it a Bug? @@ -43,12 +43,12 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.11/). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) or [stackoveflow](http://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.12/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). -In general, if you find yourself stuck on any of these steps, asking on one of the following Scala mailing lists can be helpful: +In general, if you find yourself stuck on any of these steps, asking on [Scala Contributors](https://contributors.scala-lang.org/) can be helpful: - - For unexpected behavior use [scala-language](https://groups.google.com/forum/?fromgroups#!forum/scala-language), or [scala-user](https://groups.google.com/forum/?fromgroups#!forum/scala-user) mailing lists. - - For compiler bugs use the [scala-internals](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) mailing list. + - For unexpected behavior use the [Community Category](https://contributors.scala-lang.org/c/community). + - For compiler bugs use the [Compiler Category](https://contributors.scala-lang.org/c/compiler). * Examples of exceptions reported by the compiler which usually are not bugs: 1. `StackOverflowError` is typically not a bug unless the stacktrace involves the internal packages of the compiler (like `scala.tools.nsc...`). Try to increase the Java stack size (`-Xss`), in most of the cases it helps. @@ -84,4 +84,4 @@ In the description of your issue, be as detailed as you can. Bug reports which h 2. The expected output. 3. The actual output, including the stacktrace. 4. Related discussion on the mailing lists, if applicable. - 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. + 5. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. From 7390eec1410fbd55523e919450ef8dda1ffa6c87 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Thu, 22 Jun 2017 10:21:22 +0100 Subject: [PATCH 0111/2265] Add scalacheck tips and note removal of partest --- contribute/hacker-guide.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 8d7903fbea..a8e9d2e14c 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -264,11 +264,13 @@ Adding tests to the test suite is as easy as moving them to the appropriate dire * Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/2.12.x/test/files/neg). * Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/2.12.x/test/files/run) and have a corresponding `.check` file with the expected output. You will get test failures if the content of a `.check` file is different from what the test produces while running. If the change in the output is an expected product of your work, you might not want to change the `.check` file by hand. To make partest change the `.check` file, run it with a `--update-check` flag, like so `./test/partest --update-check path/to/test.scala`. For more information on partest, please refer to its [documentation](http://docs.scala-lang.org/tutorials/partest-guide.html). * Everything that can be unit-tested should go to ["junit" directory](https://github.com/scala/scala/tree/2.12.x/test/junit) -* Property-based tests go to the ["scalacheck" directory](https://github.com/scala/scala/tree/2.12.x/test/files/scalacheck) +* Property-based tests go to the ["scalacheck" directory](https://github.com/scala/scala/tree/2.12.x/test/scalacheck) Here are some more testing tips: -* If you have several tests, and want a tool for only running tests that conform to some regular expression, you can use `partest-ack` in the `tools` directory: `./tools/partest-ack "dottype"` +* If you have several tests, and want a tool for only running tests that conform to some regular expression, you can use `partest-ack` in the `tools` directory: `./tools/partest-ack "dottype"`. `partest-ack` was removed in 2.12. +* If you want to run all scalacheck tests from sbt use `scalacheck/testOnly` +* To run scalacheck tests by name when in sbt use `scalacheck/testOnly ... `, for example `scalacheck/testOnly scala.tools.nsc.scaladoc.HtmlFactoryTest` * If your tests fail in the following way: test.bc: @@ -320,6 +322,8 @@ Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, resp testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] All of 6 tests were successful (elapsed time: 00:00:08) +`partest` was removed in 2.12. + ## 4. Publish After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. From c8305a9b4e7279273842e2701bfdb649a872ab88 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 13 Jul 2017 17:23:15 +0200 Subject: [PATCH 0112/2265] Get rid of some of the permalinks that are breaking everything --- contribute/bug-reporting-guide.md | 2 +- contribute/codereviews.md | 8 ++--- contribute/corelibs.md | 6 ++-- contribute/documentation.md | 20 ++++++------- contribute/guide.md | 6 ++-- contribute/hacker-guide.md | 4 +-- contribute/index.md | 4 +-- contribute/partest-guide.md | 30 +++++++++---------- contribute/scala-internals.md | 5 ++-- ...cala-standard-library-api-documentation.md | 2 +- contribute/tools.md | 10 +++---- 11 files changed, 48 insertions(+), 49 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 33b61807c2..05569ff8e4 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -1,7 +1,7 @@ --- title: Bug Reporting layout: inner-page-no-masthead -permalink: /contribute/bug-reporting-guide/ +# permalink: /contribute/bug-reporting-guide/ includeTOC: true --- diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 9239fa8c14..2c56b4ed37 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -1,18 +1,18 @@ --- title: Code Review Contributions layout: inner-page-no-masthead -permalink: /contribute/codereviews/ +# permalink: /contribute/codereviews/ includeTOC: true --- ## Code Review Contributions -In addition to [bug fixing](/contribute/guide/), you can help us review -[waiting pull requests](#pull-requests-awaiting-comment). +In addition to [bug fixing](/contribute/guide/), you can help us review +[waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your own pull requests. - + ### Review Guidelines [Code of Conduct reminder](/conduct/) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index 1f34d150b0..fd69ae196e 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -1,7 +1,7 @@ --- title: Core Library Contributions layout: inner-page-no-masthead -permalink: /contribute/corelibs/ +# permalink: /contribute/corelibs/ includeTOC: true --- ## Core Library Contributions @@ -10,14 +10,14 @@ There are several options for contributing to Scala's core libraries. You can: * Help with [Documentation](/contribute/scala-standard-library-api-documentation/). * [Report Bugs or Issues](/contribute/bug-reporting-guide/) against the core libraries. -* [Fix Bugs or Issues](/contribute/guide/) against the +* [Fix Bugs or Issues](/contribute/guide/) against the [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). * Contribute significant new functionality or a new API by submitting a Scala Library Improvement Process (SLIP) Document. ### Submitting a SLIP -For significant new functionality or a whole new API to be considered for +For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, you will be asked to submit a SLIP (Scala Library Improvement Process) document. Please see [instructions for submitting a new SLIP](http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the [pre-requisites](http://docs.scala-lang.org/sips/slip-submission.html) before submitting a SLIP. diff --git a/contribute/documentation.md b/contribute/documentation.md index 2746fa77dc..8930a3c32c 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -1,7 +1,7 @@ --- title: Documentation Contributions layout: inner-page-no-masthead -permalink: /contribute/documentation/ +# permalink: /contribute/documentation/ includeTOC: true --- ## Contributing Documentation to the Scala project @@ -14,7 +14,7 @@ There are several ways you can help out with the improvement of Scala documentat Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [scala-internals Google group](https://groups.google.com/forum/#!forum/scala-internals) and then, please, submit a pull request with updated documentation reflecting that answer. -**General requirements** for documentation submissions include spell-checking all written language, ensuring code samples compile and run correctly, correct grammar, and clean formatting/layout of the documentation. +**General requirements** for documentation submissions include spell-checking all written language, ensuring code samples compile and run correctly, correct grammar, and clean formatting/layout of the documentation. Thanks @@ -22,12 +22,12 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation/#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation/#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. * [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation/) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. -* You can also just -[submit new Scaladoc](/contribute/scala-standard-library-api-documentation/) -without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. +* You can also just +[submit new Scaladoc](/contribute/scala-standard-library-api-documentation/) +without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. ### The Main Scala Documentation Site @@ -43,15 +43,15 @@ without creating an issue, but please look to see if there is an issue already s * SIP (Scala Improvement Process) Proposals and more -Please read [contributing to the docs.scala-lang.org site](http://docs.scala-lang.org/contribute.html) through before embarking on changes. The site uses +Please read [contributing to the docs.scala-lang.org site](http://docs.scala-lang.org/contribute.html) through before embarking on changes. The site uses the [Jekyll](http://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. ### Updating scala-lang.org Additional high-level documentation (including documentation on contributing -to Scala and related projects) is provided on the main -[Scala Language site](http://scala-lang.org), and is also kept in the -[scala-lang github project](https://github.com/scala/scala-lang) which may be forked to create pull requests. +to Scala and related projects) is provided on the main +[Scala Language site](http://scala-lang.org), and is also kept in the +[scala-lang github project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the [docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the [scala-lang.org github README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/contribute/guide.md b/contribute/guide.md index afd3572c53..9edb289e06 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -1,7 +1,7 @@ --- title: Contributing guide layout: inner-page-no-masthead -permalink: /contribute/guide/ +# permalink: /contribute/guide/ includeTOC: true --- @@ -54,9 +54,9 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide/) (but please +1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide/) (but please [make sure it's not a duplicate](/contribute/bug-reporting-guide/#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](/contribute/scala-internals/). After all, don't you want to work on a team with +2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](/contribute/scala-internals/). After all, don't you want to work on a team with [these friendly people](/contribute/hacker-guide/#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](/contribute/hacker-guide/#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](/contribute/hacker-guide/#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index abfe59b2da..31602a0909 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -2,7 +2,7 @@ title: Scala hacker guide by: Eugene Burmako layout: inner-page-no-masthead -permalink: /contribute/hacker-guide/ +# permalink: /contribute/hacker-guide/ includeTOC: true ---
@@ -54,7 +54,7 @@ it probably makes sense to familiarize yourself with Git first. We recommend * the [Git Pro](http://git-scm.com/book/en/) online book. * the help page on [Forking a Git Repository](https://help.github.com/articles/fork-a-repo). -* this great training tool [LearnGitBranching](http://pcottle.github.io/learnGitBranching/). One hour hands-on training helps more than 1000 hours reading. +* this great training tool [LearnGitBranching](http://pcottle.github.io/learnGitBranching/). One hour hands-on training helps more than 1000 hours reading. ### Fork diff --git a/contribute/index.md b/contribute/index.md index f0c52986b8..3dac16ead4 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,7 +1,7 @@ --- title: Contribute layout: inner-page-no-masthead -permalink: /contribute/ +# permalink: /contribute/ includeTOC: true --- @@ -22,7 +22,7 @@ how to efficiently report a bug. ### Contribute -Coordination of contribution efforts takes place on the +Coordination of contribution efforts takes place on the [scala-internals Google group](/contribute/scala-internals/). {% include column-list-of-items.html collection=site.contribute_resources %} diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index be37d6fc12..ce4f84ecf1 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -1,7 +1,7 @@ --- title: Running the Test Suite layout: inner-page-no-masthead -permalink: /contribute/partest-guide/ +# permalink: /contribute/partest-guide/ includeTOC: true --- @@ -14,11 +14,11 @@ The test suite can be run by using ant from the command line: $ ant test.suite ## Standalone - -There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use - + +There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use + ./test/partest --show-diff --show-log --failed - + You can get a summary of the usage by running partest without arguments. * Most commonly you want to invoke partest with an option that tells it which part of the tests to run. For example `--all`, `--pos`, `--neg` or `--run`. @@ -29,13 +29,13 @@ You can get a summary of the usage by running partest without arguments. * You can use the `SCALAC_OPTS` environment variable to pass command line options to the compiler. * You can use the `JAVA_OPTS` environment variable to pass command line options to the runner (e.g., for `run/jvm` tests). * The launch scripts run partest as follows: - + scala -cp scala.tools.partest.nest.NestRunner - + Partest classes from a `quick` build, e.g., can be found in `./build/quick/classes/partest/`. - + Partest will tell you where it loads compiler/library classes from by adding the `partest.debug` property: - + scala -Dpartest.debug=true -cp scala.tools.partest.nest.NestRunner @@ -46,10 +46,10 @@ Tests that depend on [ScalaCheck](https://github.com/rickynils/scalacheck) can b import org.scalacheck._ import Prop._ - + object Test { val prop_ConcatLists = property{ (l1: ListInt, l2: ListInt) => - l1.size + l2.size == (l1 ::: l2).size + l1.size + l2.size == (l1 ::: l2).size } val tests = List(("prop_ConcatLists", prop_ConcatLists)) @@ -59,10 +59,10 @@ Tests that depend on [ScalaCheck](https://github.com/rickynils/scalacheck) can b ### Windows -Some tests might fail because line endings in the `.check` files and the produced results do not match. In that case, set either +Some tests might fail because line endings in the `.check` files and the produced results do not match. In that case, set either - git config core.autocrlf false + git config core.autocrlf false -or +or - git config core.autocrlf input \ No newline at end of file + git config core.autocrlf input diff --git a/contribute/scala-internals.md b/contribute/scala-internals.md index 831f2cc864..e6fde53a81 100644 --- a/contribute/scala-internals.md +++ b/contribute/scala-internals.md @@ -7,11 +7,11 @@ includeTOC: true ## scala-internals -The [scala-internals mailing list](https://groups.google.com/d/forum/scala-internals) is where technical and logistical discussions concerning bugs, bug fixes, documentation, improvements, new features and other contributor related topics occur. +The [scala-internals mailing list](https://groups.google.com/d/forum/scala-internals) is where technical and logistical discussions concerning bugs, bug fixes, documentation, improvements, new features and other contributor related topics occur. ### Coordinating on scala-internals -Prior to commencing on contribution work on larger changes to the Scala project, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. For smaller bug fixes or documentation changes where the risk of effort duplication is minimal, you can skip this post. +Prior to commencing on contribution work on larger changes to the Scala project, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. For smaller bug fixes or documentation changes where the risk of effort duplication is minimal, you can skip this post. To help subscribers on the scala-internals list to sort through the postings, we request that the following topic labels are applied when you start a new post please: @@ -44,4 +44,3 @@ While it is optional to announce your intentions/work items on scala-internals b * There are a lot of nice people waiting to talk to you on scala-internals, you might be surprised how valuable and pleasant you find the experience of talking to them. If all of this has not convinced you then, please, go ahead and work on contributions anyway. It *is* less important to post to scala-internals first for small, self contained bugs than it is for larger issues or features, and not having posted first will not be a reason for your PR to be rejected, it just might be a rougher review/merge process than if you had posted first. It's your choice. - diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 68df995375..c64a176cde 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -1,7 +1,7 @@ --- title: Contribute to API Documentation layout: inner-page-no-masthead -permalink: /contribute/scala-standard-library-api-documentation/ +# permalink: /contribute/scala-standard-library-api-documentation/ includeTOC: true --- diff --git a/contribute/tools.md b/contribute/tools.md index 420579913e..de96e19fa5 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -1,7 +1,7 @@ --- title: IDE and Build Tool Contributions layout: inner-page-no-masthead -permalink: /contribute/tools/ +# permalink: /contribute/tools/ includeTOC: true # Projects list: @@ -45,7 +45,7 @@ projects: homeLink: http://docs.scala-lang.org/tutorials/partest-guide.html issuesLink: https://github.com/scala/scala-partest/issues readmeLink: https://github.com/scala/scala-partest/blob/master/README.md - contributingLink: + contributingLink: - title: Ensime description: Scala Support for Text Editors icon: https://avatars0.githubusercontent.com/u/5089042?v=3&s=200 @@ -76,7 +76,7 @@ projectsInNeed: description: Scala Decoder (part of scala/scala) icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 link: https://github.com/scala/scala - homeLink: + homeLink: issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20text%20~%20%22scalap%22 readmeLink: https://github.com/scala/scala#welcome contributingLink: https://github.com/sbt/sbt/blob/0.13/CONTRIBUTING.md @@ -103,7 +103,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation/#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation/#updating-scala-langorg) to fix it. ### Projects @@ -113,4 +113,4 @@ Stuff changes. Found a broken link or something that needs updating on this page The following projects are important to the Scala community but are particularly in need of contributors to continue their development. -{% include contributions-projects-list.html collection=page.projectsInNeed %} \ No newline at end of file +{% include contributions-projects-list.html collection=page.projectsInNeed %} From fbca9ca0b3ef20fbb657aa132f88f85b097607b4 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Fri, 14 Jul 2017 17:02:30 +0200 Subject: [PATCH 0113/2265] Bug reporting guide link fixes --- _contribute_resources/2-bug-fixes.md | 2 +- contribute/corelibs.md | 2 +- contribute/guide.md | 6 +++--- contribute/index.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index d10adb7908..8661ab9614 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -3,4 +3,4 @@ title: Bug fixes link: /contribute/guide/ icon: fa fa-pencil --- -Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide/). \ No newline at end of file +Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). diff --git a/contribute/corelibs.md b/contribute/corelibs.md index fd69ae196e..c06a741915 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -9,7 +9,7 @@ includeTOC: true There are several options for contributing to Scala's core libraries. You can: * Help with [Documentation](/contribute/scala-standard-library-api-documentation/). -* [Report Bugs or Issues](/contribute/bug-reporting-guide/) against the core libraries. +* [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. * [Fix Bugs or Issues](/contribute/guide/) against the [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). * Contribute significant new functionality or a new API by submitting diff --git a/contribute/guide.md b/contribute/guide.md index 9edb289e06..bda4fa9ff3 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -12,7 +12,7 @@ includeTOC: true

Get a peek into the inners of the Scala compiler.

-

Report an issue

+

Report an issue

File a bug report or a feature request.

@@ -54,8 +54,8 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide/) (but please -[make sure it's not a duplicate](/contribute/bug-reporting-guide/#reporting-confirmed-bugs-is-a-sin)). +1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide.html) (but please +[make sure it's not a duplicate](/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). 2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](/contribute/scala-internals/). After all, don't you want to work on a team with [these friendly people](/contribute/hacker-guide/#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](/contribute/hacker-guide/#fork) and clone your fork (if you haven't already). diff --git a/contribute/index.md b/contribute/index.md index 3dac16ead4..55563f8ac0 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -17,7 +17,7 @@ That depends on what you want to contribute. Below are some getting started reso ### Reporting bugs -See our [bug reporting guide](/contribute/bug-reporting-guide/) to learn +See our [bug reporting guide](/contribute/bug-reporting-guide.html) to learn how to efficiently report a bug. ### Contribute From e2f7c0712662e555f53f7c77cee608b5aadee722 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Fri, 14 Jul 2017 17:06:56 +0200 Subject: [PATCH 0114/2265] Removing some mentions of scala-internals --- contribute/documentation.md | 4 ++-- contribute/guide.md | 6 +++--- contribute/hacker-guide.md | 6 +++--- contribute/index.md | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index 8930a3c32c..0111c5c15d 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -12,7 +12,7 @@ There are several ways you can help out with the improvement of Scala documentat * Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site * Updating scala-lang.org -Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [scala-internals Google group](https://groups.google.com/forum/#!forum/scala-internals) and then, please, submit a pull request with updated documentation reflecting that answer. +Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and then, please, submit a pull request with updated documentation reflecting that answer. **General requirements** for documentation submissions include spell-checking all written language, ensuring code samples compile and run correctly, correct grammar, and clean formatting/layout of the documentation. @@ -27,7 +27,7 @@ Please *follow the issue submission process closely* to help prevent duplicate i * [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation/) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just [submit new Scaladoc](/contribute/scala-standard-library-api-documentation/) -without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. +without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on [Scala Contributors](https://contributors.scala-lang.org/) so that people know what you are doing. ### The Main Scala Documentation Site diff --git a/contribute/guide.md b/contribute/guide.md index bda4fa9ff3..a824e2297f 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -8,7 +8,7 @@ includeTOC: true
-

Scala Internals

+

Scala Contributors

Get a peek into the inners of the Scala compiler.

@@ -56,7 +56,7 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu 1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide.html) (but please [make sure it's not a duplicate](/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [scala-internals](/contribute/scala-internals/). After all, don't you want to work on a team with +2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with [these friendly people](/contribute/hacker-guide/#connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](/contribute/hacker-guide/#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](/contribute/hacker-guide/#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. @@ -75,7 +75,7 @@ Need more information or a little more hand-holding for the first one? We got yo For larger, more ambitious changes (e.g. new language features), the first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea and on the implementation plan. Announce the change -on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. +on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against the Scala project source tree. The [hacker guide](/contribute/hacker-guide/) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 31602a0909..a10fbb70eb 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -38,7 +38,7 @@ A list of language features/libraries along with their maintainer's full names a In our running example, since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. -As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, +As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the [Scala Contributors](https://contributors.scala-lang.org/) mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user) about our issue. Posting to scala-user @@ -202,7 +202,7 @@ If you intend on contributing to Scala collections, please make sure you're fami ##### The Scala Compiler -Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email (scala-internals mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: +Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email ([Scala Contributors](https://contributors.scala-lang.org/) mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: * [Compiler internals videos by Martin Odersky](http://www.scala-lang.org/old/node/598.html) are quite dated, but still very useful. In this three-video series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. @@ -212,7 +212,7 @@ Documentation about the internal workings of the Scala compiler is scarce, and m at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. * [Scala compiler corner](http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/) contains extensive documentation about most of the post-typer phases (i.e. the backend) in the Scala compiler. -* [scala-internals](http://groups.google.com/group/scala-internals), a mailing list which hosts discussions about the core +* [Scala Contributors](https://contributors.scala-lang.org/), a mailing list which hosts discussions about the core internal design and implementation of the Scala system. ##### Other Projects diff --git a/contribute/index.md b/contribute/index.md index 55563f8ac0..f56a91c163 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -22,8 +22,8 @@ how to efficiently report a bug. ### Contribute -Coordination of contribution efforts takes place on the -[scala-internals Google group](/contribute/scala-internals/). +Coordination of contribution efforts takes place on +[Scala Contributors](https://contributors.scala-lang.org/). {% include column-list-of-items.html collection=site.contribute_resources %} From 5c3fbae7f06170f21acc05a37f278cacc84bdb8d Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Fri, 14 Jul 2017 17:08:59 +0200 Subject: [PATCH 0115/2265] Missing whitespace --- _contribute_resources/1-documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 27739dee6a..0d9c198ffd 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -3,4 +3,4 @@ title: Documentation link: /contribute/documentation/ icon: fa fa-file-text --- -[Scaladoc (API)](/contribute/scala-standard-library-api-documentation/),[docs.scala-lang.org](http://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). \ No newline at end of file +[Scaladoc (API)](/contribute/scala-standard-library-api-documentation/), [docs.scala-lang.org](http://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). From d1d0f26798c64d560e8795343b49db234c7b0969 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 19 Jul 2017 11:29:38 -0400 Subject: [PATCH 0116/2265] fix or remove links to wiki the wiki has been mercifully taken offline --- contribute/documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index 0111c5c15d..a329f67369 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -31,7 +31,7 @@ without creating an issue, but please look to see if there is an issue already s ### The Main Scala Documentation Site -[docs.scala-lang.org](https://wiki.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a github project that you can fork and submit pull requests from. It includes: +[docs.scala-lang.org](https://docs.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a github project that you can fork and submit pull requests from. It includes: * Overviews * Tutorials From 81a9902665dd90bd0b7e4b971e9f358a2bb492ab Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 10 Aug 2017 12:29:30 -0700 Subject: [PATCH 0117/2265] scala.github.com -> docs.scala-lang --- _contribute_resources/3-code-reviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index 2ab235993b..ffdd6d2672 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -5,4 +5,4 @@ icon: fa fa-eye --- Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), [scala/scala-lang](https://github.com/scala/scala-lang/pulls), -[scala/scala.github.com](https://github.com/scala/scala.github.com/pulls)and others. \ No newline at end of file +[scala/docs.scala-lang](https://github.com/scala/docs.scala-lang/pulls)and others. From 287b50a18d6d5cd3f07e6c9de8c7df7fe7a0da0b Mon Sep 17 00:00:00 2001 From: Jimin Hsieh Date: Thu, 17 Aug 2017 21:11:58 +0800 Subject: [PATCH 0118/2265] Fix broken links of https://scala-lang.org/contribute/#contribute. --- _contribute_resources/1-documentation.md | 4 ++-- _contribute_resources/2-bug-fixes.md | 2 +- _contribute_resources/3-code-reviews.md | 2 +- _contribute_resources/4-core-libraries.md | 4 ++-- _contribute_resources/5-ide-and-build-tools.md | 4 ++-- _contribute_resources/6-compiler-language.md | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 0d9c198ffd..54f18c938c 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -1,6 +1,6 @@ --- title: Documentation -link: /contribute/documentation/ +link: /contribute/documentation.html icon: fa fa-file-text --- -[Scaladoc (API)](/contribute/scala-standard-library-api-documentation/), [docs.scala-lang.org](http://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). +[Scaladoc (API)](/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](http://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index 8661ab9614..cca6269e06 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -1,6 +1,6 @@ --- title: Bug fixes -link: /contribute/guide/ +link: /contribute/guide.html icon: fa fa-pencil --- Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index ffdd6d2672..3de87cd929 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -1,6 +1,6 @@ --- title: Code Reviews -link: /contribute/codereviews/ +link: /contribute/codereviews.html icon: fa fa-eye --- Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), diff --git a/_contribute_resources/4-core-libraries.md b/_contribute_resources/4-core-libraries.md index 7ad75c5752..06f1018479 100644 --- a/_contribute_resources/4-core-libraries.md +++ b/_contribute_resources/4-core-libraries.md @@ -1,6 +1,6 @@ --- title: Core Libraries -link: /contribute/corelibs/ +link: /contribute/corelibs.html icon: fa fa-clipboard --- -Update and expand the capabilities of the core (and associated) Scala libraries. \ No newline at end of file +Update and expand the capabilities of the core (and associated) Scala libraries. diff --git a/_contribute_resources/5-ide-and-build-tools.md b/_contribute_resources/5-ide-and-build-tools.md index 4b8bd2ed52..7202f0d953 100644 --- a/_contribute_resources/5-ide-and-build-tools.md +++ b/_contribute_resources/5-ide-and-build-tools.md @@ -1,6 +1,6 @@ --- title: IDE and Build Tools -link: /contribute/tools/ +link: /contribute/tools.html icon: fa fa-terminal --- -Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects. \ No newline at end of file +Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects. diff --git a/_contribute_resources/6-compiler-language.md b/_contribute_resources/6-compiler-language.md index 0c4eaa1325..fcfea35d5a 100644 --- a/_contribute_resources/6-compiler-language.md +++ b/_contribute_resources/6-compiler-language.md @@ -1,6 +1,6 @@ --- title: Compiler/Language -link: /contribute/guide/#larger-changes-new-features +link: /contribute/guide.html#larger-changes-new-features icon: fa fa-gears --- -Larger language features and compiler enhancements including language specification and SIPs. \ No newline at end of file +Larger language features and compiler enhancements including language specification and SIPs. From 18f49fc7d95e020cb39e4c2130299fe5b45b41a6 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 17 Aug 2017 17:33:08 +0200 Subject: [PATCH 0119/2265] More link fixes --- contribute/codereviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 2c56b4ed37..ab321fd2ca 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -15,7 +15,7 @@ own pull requests. ### Review Guidelines -[Code of Conduct reminder](/conduct/) +[Code of Conduct reminder]({{ site.baseurl }}/conduct.html) * Keep comments on-topic, concise and precise. * Attach comments to particular lines or regions they pertain to whenever possible. From aaf513b07215bffa7bd36d76d37922d2655a7767 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 6 Sep 2017 11:17:58 +0100 Subject: [PATCH 0120/2265] Extend partest guide with sbt and mention batch script removals --- contribute/partest-guide.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index ce4f84ecf1..dccee46a1c 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -5,17 +5,37 @@ layout: inner-page-no-masthead includeTOC: true --- -Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go the scala project folder from your local checkout and run it via `ant` or standalone as follows. +Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go to the scala project folder from your local checkout and run it via `sbt`, `ant` or standalone as follows. + +## Using sbt + +The test suite can be run from the sbt console with: + + > partest + +You can get a summary of the usage by running `partest --help`. + +If you would like to run particular tests pass the test paths as arguments + + > partest test/files/pos/bounds.scala test/scaladoc/run/diagrams-base.scala + +To run only the Scaladoc tests use `--srcpath` with the location of the tests + + > partest --srcpath scaladoc ## Using ant +Please note support for ant was removed on the 2.12 branch. + The test suite can be run by using ant from the command line: $ ant test.suite ## Standalone -There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use +Please note the standalone scripts mentioned below were removed in 2.12.2. sbt is the perferred way to run the test suite. + +There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use ./test/partest --show-diff --show-log --failed From 48e43e80173efa233cb422e6e1a888c79c74a12e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 6 Sep 2017 16:23:34 -0700 Subject: [PATCH 0121/2265] fix typo --- contribute/partest-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index dccee46a1c..e7e10621e1 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -33,7 +33,7 @@ The test suite can be run by using ant from the command line: ## Standalone -Please note the standalone scripts mentioned below were removed in 2.12.2. sbt is the perferred way to run the test suite. +Please note the standalone scripts mentioned below were removed in 2.12.2. sbt is the preferred way to run the test suite. There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use From 6f2ca77dae73a6b1ccbedc639c5aed31940c8107 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Wed, 15 Nov 2017 10:59:10 +0100 Subject: [PATCH 0122/2265] Fix links to Hacker guide --- contribute/guide.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index a824e2297f..ae69f50fd2 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -23,7 +23,7 @@ includeTOC: true

Get cracking on some easy to approach issues.

-

Hacker's guide

+

Hacker guide

Learn to write good code and improve your chances of contributing to the Scala galaxy.

@@ -57,16 +57,16 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu 1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide.html) (but please [make sure it's not a duplicate](/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). 2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with -[these friendly people](/contribute/hacker-guide/#connect) - it's one of the perks of contributing. -3. [Fork the Scala repository](/contribute/hacker-guide/#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](/contribute/hacker-guide/#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. -5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide/#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](/contribute/hacker-guide/#test) and [test some more](/contribute/partest-guide/) until [all the tests pass](/contribute/hacker-guide/#verify). -7. [Commit your changes](/contribute/hacker-guide#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. +[these friendly people](/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. +3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). +4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. +5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). +6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide/) until [all the tests pass](/contribute/hacker-guide.html#verify). +7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](http://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) 9. [Submit a pull request](./hacker-guide.html#submit) following the [Scala project pull-request guidelines](http://docs.scala-lang.org/scala/pull-request-policy.html). -10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide/#review). +10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide.html#review). 11. Celebrate! Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](./hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). @@ -78,4 +78,4 @@ and on the implementation plan. Announce the change on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](/contribute/hacker-guide/) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. +the Scala project source tree. The [hacker guide](/contribute/hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. From 3db9bb55a2f392f80f5bdb54c7811f948ade5b33 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:04:51 +0100 Subject: [PATCH 0123/2265] Add missing space --- _contribute_resources/3-code-reviews.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index 3de87cd929..2fc057eb0d 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -5,4 +5,4 @@ icon: fa fa-eye --- Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), [scala/scala-lang](https://github.com/scala/scala-lang/pulls), -[scala/docs.scala-lang](https://github.com/scala/docs.scala-lang/pulls)and others. +[scala/docs.scala-lang](https://github.com/scala/docs.scala-lang/pulls) and others. From 725800ebd3d4e2b71407ea2017428853ce2b96a2 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:11:47 +0100 Subject: [PATCH 0124/2265] Fix links --- contribute/corelibs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index c06a741915..aeb19e89af 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -8,9 +8,9 @@ includeTOC: true There are several options for contributing to Scala's core libraries. You can: -* Help with [Documentation](/contribute/scala-standard-library-api-documentation/). +* Help with [Documentation](/contribute/documentation.html). * [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. -* [Fix Bugs or Issues](/contribute/guide/) against the +* [Fix Bugs or Issues](/contribute/guide.html) against the [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). * Contribute significant new functionality or a new API by submitting a Scala Library Improvement Process (SLIP) Document. From 56abdcb1b0912957fc4e9f5c92018fbed73c04cb Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:12:47 +0100 Subject: [PATCH 0125/2265] Link to GitHub instead of JIRA --- contribute/corelibs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index aeb19e89af..e1f10cb790 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -11,7 +11,7 @@ There are several options for contributing to Scala's core libraries. You can: * Help with [Documentation](/contribute/documentation.html). * [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. * [Fix Bugs or Issues](/contribute/guide.html) against the - [reported library bugs/issues](https://issues.scala-lang.org/issues/?filter=13001). + [reported library bugs/issues](https://github.com/scala/bug). * Contribute significant new functionality or a new API by submitting a Scala Library Improvement Process (SLIP) Document. From 46fc7ea2c1117a6fc9ea612e4cf53d92f802aa5d Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:19:43 +0100 Subject: [PATCH 0126/2265] Reword and link to GitHub instead of JIRA --- contribute/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/guide.md b/contribute/guide.md index ae69f50fd2..1b530a1769 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -43,7 +43,7 @@ The main Scala project consists of the standard Scala library, the Scala reflect the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. Typically the scaladoc tool provides a low entry point for new committers, so it is a good first step into contributing. -On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. +On the [Scala bug tracker](https://github.com/scala/bug) you will find the bugs that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. If you are interested in contributing code, we ask you to sign the [Scala Contributor License Agreement](http://www.lightbend.com/contribute/cla/scala), From 381b641dfb1a00ef2da9d646078cc4e8a85e4501 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:20:28 +0100 Subject: [PATCH 0127/2265] Link to GitHub instead of JIRA --- contribute/scala-standard-library-api-documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index c64a176cde..6467cea947 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -42,7 +42,7 @@ and identify missing, incorrect or inadequate documentation. A good place to sta package objects for important packages (these often get overlooked for documentation and are a good place for API overviews). -If you find an issue, please log it in the [Scala issue tracker](https://issues.scala-lang.org) +If you find an issue, please log it in the [Scala bug tracker](https://github.com/scala/bug) **after making sure it is not already logged as an issue**. To help with disambiguation, please use the following format for issue title: From 74ce0815244088f76cab5e1f3d9cab4e4248a59d Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:39:58 +0100 Subject: [PATCH 0128/2265] Fix ironically broken link --- contribute/tools.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/tools.md b/contribute/tools.md index de96e19fa5..599cbf381e 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -103,7 +103,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation/#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation.html#updating-scala-langorg) to fix it. ### Projects From 832e674c2c10dcf1f1341d50dbcc549e917662f6 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:41:15 +0100 Subject: [PATCH 0129/2265] Link to GitHub instead of JIRA --- contribute/tools.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/tools.md b/contribute/tools.md index 599cbf381e..8337c10935 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -19,7 +19,7 @@ projects: icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 link: https://github.com/scala/scala homeLink: http://www.scala-lang.org/api - issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20component%20%3D%20%22Scaladoc%20Tool%22 + issuesLink: https://github.com/scala/bug/labels/scaladoc readmeLink: https://github.com/scala/scala#welcome contributingLink: http://scala-lang.org/contribute/guide.html - title: Scala IDE From e4f39bf320ae3e8ee2fda6a3e91b94644ae239da Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:42:23 +0100 Subject: [PATCH 0130/2265] Fix Scalariform section --- contribute/tools.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 8337c10935..feb11afa8f 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -80,8 +80,8 @@ projectsInNeed: issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20text%20~%20%22scalap%22 readmeLink: https://github.com/scala/scala#welcome contributingLink: https://github.com/sbt/sbt/blob/0.13/CONTRIBUTING.md - - title: Scaladoc Tool - description: (Contribute through scala/scala) + - title: Scalariform + description: Scala source code formatter icon: /resources/img/white-line.png link: https://github.com/mdr/scalariform homeLink: https://github.com/mdr/scalariform/wiki/Command-line-tool From 4a9c5f05ca7161756ae3b7f1be520908caa53910 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:46:12 +0100 Subject: [PATCH 0131/2265] Remove Scalap --- contribute/tools.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index feb11afa8f..a1e2ef78e2 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -72,14 +72,6 @@ projects: contributingLink: https://github.com/scala/scala-abide#extending-abide projectsInNeed: - - title: Scalap - description: Scala Decoder (part of scala/scala) - icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 - link: https://github.com/scala/scala - homeLink: - issuesLink: https://issues.scala-lang.org/issues/?jql=status%20%3D%20Open%20AND%20text%20~%20%22scalap%22 - readmeLink: https://github.com/scala/scala#welcome - contributingLink: https://github.com/sbt/sbt/blob/0.13/CONTRIBUTING.md - title: Scalariform description: Scala source code formatter icon: /resources/img/white-line.png From 0dc0f0dab8532365fd069f7f3984d66976562635 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sat, 27 Jan 2018 21:52:55 +0100 Subject: [PATCH 0132/2265] Link to GitHub instead of JIRA --- contribute/hacker-guide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index a10fbb70eb..4200df478c 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -17,7 +17,7 @@ Other good starting points for first-time contributors include the [Scala README Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. Though, there's an annoying issue -which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) +which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://github.com/scala/bug/issues/6725) new line tokens `%n`. One approach would be to go the mailing list, request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala oneself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. @@ -88,10 +88,10 @@ Before you start making changes, always create your own branch. Never work on th the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. -* For bug fixes, use `issue/NNNN` or `ticket/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). +* For bug fixes, use `issue/NNNN` or `ticket/NNNN` for bug NNNN from the [Scala bug tracker](https://github.com/scala/bug). * For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. -Since in our example, we're going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), we'll create a branch named `ticket/6725`. +Since in our example, we're going to fix an existing bug [6725](https://github.com/scala/bug/issues/6725), we'll create a branch named `ticket/6725`. 16:39 ~/Projects/scala (master)$ git checkout -b ticket/6725 Switched to a new branch 'ticket/6725' @@ -108,7 +108,7 @@ You need the following tools: * `sbt`, an interactive build tool commonly used in Scala projects. Acquiring sbt manually is not necessary -- the recommended approach is to download the [sbt-extras runner script](https://github.com/paulp/sbt-extras/blob/master/sbt) and use it in place of `sbt`. The script will download and run the correct version of sbt when run from the Scala repository's root directory. * `curl` -- the build uses `curl` in the `pull-binary-libs.sh` script to download bootstrap libs. -OS X and Linux builds should work. Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. +OS X and Linux builds should work. Windows is supported, but it might have issues. Please report to the [Scala bug tracker](https://github.com/scala/bug) if you encounter any. Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. In general, it's much more efficient to enter the `sbt` shell once and run the various tasks from there, instead of running each task by launching `sbt some-task` on your command prompt. @@ -136,7 +136,7 @@ Typically you would want to first make sure that your changes work on a small ex by running a comprehensive test suite. We'll start by creating a `sandbox` directory (`./sandbox` is listed in the .gitignore of the Scala repository), which will hold a single test file and its compilation results. First, let's make sure that -[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `sbt`. The Scala compiler that we just built is located in `build/pack/bin`. +[the bug](https://github.com/scala/bug/issues/6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `sbt`. The Scala compiler that we just built is located in `build/pack/bin`. 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox @@ -221,7 +221,7 @@ Tools like Scaladoc also welcome contributions. Unfortunately these smaller proj ### Interlude -To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725) we've tracked the `StringContext.f` interpolator +To fix [the bug we're interested in](https://github.com/scala/bug/issues/6725) we've tracked the `StringContext.f` interpolator down to a macro implemented in `MacroImplementations.scala` There we notice that the interpolator only processes conversions, but not tokens like `%n`. Looks like an easy fix. From 5ad09fd1367de5fc65748ded6df8c003c636ee84 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 00:11:41 +0100 Subject: [PATCH 0133/2265] Remove link to 'Actors Migration Kit' --- contribute/bug-reporting-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 05569ff8e4..71cb5e7ad8 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -21,7 +21,6 @@ If your issue is related to any of the following external projects, make sure to - [Akka](http://doc.akka.io/docs/akka/current/project/issue-tracking.html) - [Play!](http://github.com/playframework/Play20/issues) - [Slick](http://github.com/slick/slick/issues) - - [Actors Migration Kit](http://github.com/scala/actors-migration/issues?state=open) - [Scala IDE](https://scala-ide-portfolio.assembla.com/spaces/scala-ide/support/tickets) - [sbt](https://github.com/sbt/sbt/issues) From 1b4d548cbcfe92a861d226c07164006e8afb44fe Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 00:16:53 +0100 Subject: [PATCH 0134/2265] Replace references to 'JIRA' with 'GitHub' --- contribute/guide.md | 4 ++-- contribute/scala-standard-library-api-documentation.md | 6 +++--- contribute/tools.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index 1b530a1769..c2949683ae 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -54,12 +54,12 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [github branch](https://github.com/scala/scala) -1. [Select a bug to fix from JIRA](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a JIRA issue](/contribute/bug-reporting-guide.html) (but please +1. [Select a bug to fix from GitHub](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/contribute/bug-reporting-guide.html) (but please [make sure it's not a duplicate](/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). 2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with [these friendly people](/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. +4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. 5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). 6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide/) until [all the tests pass](/contribute/hacker-guide.html#verify). 7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 6467cea947..cae67a5db0 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -22,7 +22,7 @@ contribution steps and guidelines. Thank you.* Since API documentation is located in Scala source code files, the process for contributing API documentation is similar to that of contributing bug-fixes -to the Scala code base, but without the requirement that there be an issue filed on JIRA +to the Scala code base, but without the requirement that there be an issue filed on GitHub first. When forking/branching, just use a `scaladoc/xxxx` branch name, where xxxx is a descriptive, but short branch name (e.g. `scaladoc/future-object`). However, if an issue *does* exist, please use `issue/NNNN`, where NNNN is the ticket number, @@ -78,9 +78,9 @@ Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. * [Forking the Repo](./hacker-guide.html#set-up) - follow the setup steps through - the Branch section. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` + the Branch section. If providing new documentation related to an existing GitHub issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated - JIRA issue, use `scaladoc/xxxx` instead. + GitHub issue, use `scaladoc/xxxx` instead. * [Scaladoc for library authors](http://docs.scala-lang.org/overviews/scaladoc/for-library-authors.html) covers the use of scaladoc tags, markdown and other features. * [Scaladoc's interface](http://docs.scala-lang.org/overviews/scaladoc/interface.html) diff --git a/contribute/tools.md b/contribute/tools.md index a1e2ef78e2..19f953785f 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -86,7 +86,7 @@ The links below are to a number of Scala build and IDE related projects that are Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/contribute/hacker-guide/) and [Bug-fixing](/contribute/guide/) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. -Typically, issues for these projects will be reported and kept in the github project issue tracker for that project rather than in the Scala project JIRA. +Typically, issues for these projects will be reported and kept in the GitHub project issue tracker for that project rather than in the Scala bug tracker. Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. There are some projects in this section that are in From 76665323a75257fc23570b416e1dd102824b5e1d Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 00:30:03 +0100 Subject: [PATCH 0135/2265] Remove 'Community Tickets' section almost completely --- contribute/index.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contribute/index.md b/contribute/index.md index f56a91c163..f8d71a1f69 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -29,10 +29,8 @@ Coordination of contribution efforts takes place on ### Community Tickets -The following links provide starting points for -various contributor activities: - -{% include column-list-of-items.html collection=site.contribute_community_tickets %} +All issues can be found in the [Scala bug tracker](https://github.com/scala/bug). Most issues are labeled +to make it easier to find issues you are interested in. ### Tools and Libraries From 0dda54719465b83ce5267a663ca5e31927c51486 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 11:48:36 +0100 Subject: [PATCH 0136/2265] Fix links to Mailing Lists --- contribute/hacker-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index a10fbb70eb..c6ce1c7eea 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -30,7 +30,7 @@ Sometimes it's appealing to hack alone and not to have to interact with others o this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#mailing-lists) to find out how people feel +Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#forums--mailing-lists) to find out how people feel about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. From 2f7d9fbed9fbb41c9489d5cb22c148e4f16155d1 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 12:43:49 +0100 Subject: [PATCH 0137/2265] Fix broken links --- contribute/codereviews.md | 4 ++-- contribute/guide.md | 2 +- contribute/scala-standard-library-api-documentation.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contribute/codereviews.md b/contribute/codereviews.md index ab321fd2ca..6e0a2592b6 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -6,7 +6,7 @@ includeTOC: true --- ## Code Review Contributions -In addition to [bug fixing](/contribute/guide/), you can help us review +In addition to [bug fixing](/contribute/guide.html), you can help us review [waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your @@ -51,4 +51,4 @@ own pull requests.
-Also note that the [Tools contributions](/contribute/tools/) page has more projects that will generate pull requests. +Also note that the [Tools contributions](/contribute/tools.html) page has more projects that will generate pull requests. diff --git a/contribute/guide.md b/contribute/guide.md index ae69f50fd2..1f1a014a1b 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -61,7 +61,7 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu 3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). 4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the JIRA issue number. 5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide/) until [all the tests pass](/contribute/hacker-guide.html#verify). +6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide.html) until [all the tests pass](/contribute/hacker-guide.html#verify). 7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](http://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index c64a176cde..d7c69ef099 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -77,7 +77,7 @@ component so that they show up in the correct issue filters. Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](./hacker-guide.html#set-up) - follow the setup steps through +* [Forking the Repo](./hacker-guide.html#2-set-up) - follow the setup steps through the Branch section. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated JIRA issue, use `scaladoc/xxxx` instead. From f00b6f35c233152a7d5d3abea317d45369779a96 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 13:26:28 +0100 Subject: [PATCH 0138/2265] Update links for ENSIME --- contribute/tools.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index de96e19fa5..99bc353663 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -52,8 +52,8 @@ projects: link: https://github.com/ensime/ensime-server homeLink: http://ensime.github.io/ issuesLink: https://github.com/ensime/ensime-server/issues - readmeLink: https://github.com/ensime/ensime-server/blob/2.0/README.md - contributingLink: https://ensime.github.io/contributing/ + readmeLink: http://ensime.github.io/ + contributingLink: http://ensime.github.io/server/contributing/ - title: Scoverage description: Scala code coverage tool icon: https://avatars1.githubusercontent.com/u/5998302?v=3&s=200 From 5d99628ed6021cadecb44b96154134f4b3196795 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 16:26:24 +0100 Subject: [PATCH 0139/2265] Remove link to not-existing page --- contribute/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/guide.md b/contribute/guide.md index 1f1a014a1b..73b21ec22b 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -65,7 +65,7 @@ This is the impatient developer's checklist for the steps to submit a bug-fix pu 7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](http://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) -9. [Submit a pull request](./hacker-guide.html#submit) following the [Scala project pull-request guidelines](http://docs.scala-lang.org/scala/pull-request-policy.html). +9. [Submit a pull request](./hacker-guide.html#submit). 10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide.html#review). 11. Celebrate! From d13b13bd0cb4d050f5bada2b510d12b4b326701b Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 28 Jan 2018 17:42:37 +0100 Subject: [PATCH 0140/2265] Update DBuild links --- contribute/tools.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 99bc353663..571005612a 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -33,11 +33,11 @@ projects: - title: DBuild description: Multi-project build tool. icon: https://avatars3.githubusercontent.com/u/784923?v=3&s=200 - link: https://github.com/typesafehub/dbuild - homeLink: http://typesafehub.github.io/dbuild - issuesLink: https://github.com/typesafehub/dbuild/issues - readmeLink: https://github.com/typesafehub/dbuild/blob/master/README.md - contributingLink: https://github.com/typesafehub/dbuild/blob/master/README.md#get-involved + link: https://github.com/lightbend/dbuild + homeLink: http://lightbend.github.io/dbuild + issuesLink: https://github.com/lightbend/dbuild/issues + readmeLink: https://github.com/lightbend/dbuild/blob/master/README.md + contributingLink: https://github.com/lightbend/dbuild/blob/master/README.md#get-involved - title: Partest description: Scala Compiler/Library Testing icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 From df0a9ab333fd0fa892f7ccf6e28fe28cc68a7f72 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Wed, 14 Feb 2018 20:24:48 +0100 Subject: [PATCH 0141/2265] Update broken/outdated links --- contribute/tools.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 4ae371d64e..0a3bd6e80e 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -44,7 +44,7 @@ projects: link: https://github.com/scala/scala-partest homeLink: http://docs.scala-lang.org/tutorials/partest-guide.html issuesLink: https://github.com/scala/scala-partest/issues - readmeLink: https://github.com/scala/scala-partest/blob/master/README.md + readmeLink: https://github.com/scala/scala-partest/blob/1.1.x/README.md contributingLink: - title: Ensime description: Scala Support for Text Editors @@ -84,7 +84,7 @@ projectsInNeed: The links below are to a number of Scala build and IDE related projects that are important in the larger Scala space, and which welcome contributions. -Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/contribute/hacker-guide/) and [Bug-fixing](/contribute/guide/) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. +Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/contribute/hacker-guide.html) and [Bug-fixing](/contribute/guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. Typically, issues for these projects will be reported and kept in the GitHub project issue tracker for that project rather than in the Scala bug tracker. Many of these projects have a gitter channel (usually listed in the README or CONTRIBUTING documents) which is a great place to discuss proposed work before commencing. From d0fc35c74940a14777bf68d393159ebfe56e1ed0 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Fri, 16 Feb 2018 10:59:33 +0100 Subject: [PATCH 0142/2265] s/username/user-name/ to please htmlproofer --- contribute/hacker-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index d63ad12cf4..78af87bbcd 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -67,7 +67,7 @@ If you're new to Git, don't be afraid of messing up-- there is no way you can co ### Clone -If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` +If everything went okay, you will be redirected to your own fork at `https://github.com/user-name/scala`, where `username` is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), which covers some of the things that will follow below. Then, _clone_ your repository (i.e. pull a copy from GitHub to your local machine) by running the following on the command line: From 084649625b4db03be95dcceef418f470bedaabff Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Fri, 16 Feb 2018 12:00:21 +0100 Subject: [PATCH 0143/2265] Fix contribute link --- contribute/documentation.md | 6 +++--- contribute/scala-standard-library-api-documentation.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contribute/documentation.md b/contribute/documentation.md index a329f67369..40f7ad9c6e 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -22,11 +22,11 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation/#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. -* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation/) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just -[submit new Scaladoc](/contribute/scala-standard-library-api-documentation/) +[submit new Scaladoc](/contribute/scala-standard-library-api-documentation.html) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on [Scala Contributors](https://contributors.scala-lang.org/) so that people know what you are doing. ### The Main Scala Documentation Site diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index f05df8663b..33ee4ad558 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -1,7 +1,7 @@ --- title: Contribute to API Documentation layout: inner-page-no-masthead -# permalink: /contribute/scala-standard-library-api-documentation/ +# permalink: /contribute/scala-standard-library-api-documentation.html includeTOC: true --- From 44032b5473103a5cf21a47552398910667898f0d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 19 Jun 2019 07:38:39 +0200 Subject: [PATCH 0144/2265] update spec links and advisements partially addresses scala/bug#11566 --- contribute/bug-reporting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 71cb5e7ad8..bd2f2c70c4 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -44,7 +44,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.12/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). In general, if you find yourself stuck on any of these steps, asking on [Scala Contributors](https://contributors.scala-lang.org/) can be helpful: From 4643f1228a86fb6c347d746267989a73cc89b695 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Tue, 9 Jul 2019 14:41:22 +0100 Subject: [PATCH 0145/2265] Point the hacker guide to 2.13 --- contribute/hacker-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 78af87bbcd..b9e657adfb 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -10,7 +10,7 @@ This guide is intended to help you get from an idea of fixing a bug or implement This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. -Other good starting points for first-time contributors include the [Scala README](https://github.com/scala/scala#get-in-touch) and [contributor's guidelines](https://github.com/scala/scala/blob/2.12.x/CONTRIBUTING.md). +Other good starting points for first-time contributors include the [Scala README](https://github.com/scala/scala#get-in-touch) and [contributor's guidelines](https://github.com/scala/scala/blob/2.13.x/CONTRIBUTING.md). ## The Running Example From 4a881b17668f274112b934d07c719b1e2c21039f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 9 Oct 2019 19:16:52 -0700 Subject: [PATCH 0146/2265] renamed community-builds repo to community-build --- contribute/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index f8d71a1f69..f7b6082226 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -55,6 +55,6 @@ which leverages [sbt](http://www.scala-sbt.org). If you're the maintainer -- or just an interested user! -- of an open-source Scala library or tool, please visit the -[community build documentation](https://github.com/scala/community-builds/wiki) +[community build documentation](https://github.com/scala/community-build/wiki) for guidelines on what projects are suitable for the community build and how projects can be added. From ef84a9323cf7607406a976be1b6956a43b868052 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 12 Oct 2019 07:18:26 -0700 Subject: [PATCH 0147/2265] ENSIME is dead, Abide is dead (#1083) --- contribute/tools.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/contribute/tools.md b/contribute/tools.md index 0a3bd6e80e..4a32124731 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -46,14 +46,6 @@ projects: issuesLink: https://github.com/scala/scala-partest/issues readmeLink: https://github.com/scala/scala-partest/blob/1.1.x/README.md contributingLink: - - title: Ensime - description: Scala Support for Text Editors - icon: https://avatars0.githubusercontent.com/u/5089042?v=3&s=200 - link: https://github.com/ensime/ensime-server - homeLink: http://ensime.github.io/ - issuesLink: https://github.com/ensime/ensime-server/issues - readmeLink: http://ensime.github.io/ - contributingLink: http://ensime.github.io/server/contributing/ - title: Scoverage description: Scala code coverage tool icon: https://avatars1.githubusercontent.com/u/5998302?v=3&s=200 @@ -62,14 +54,6 @@ projects: issuesLink: https://github.com/scoverage/scalac-scoverage-plugin/issues readmeLink: https://github.com/scoverage/scalac-scoverage-plugin/blob/master/README.md contributingLink: https://groups.google.com/forum/#!forum/scala-code-coverage-tool - - title: Abide - description: Lint tooling for Scala - icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 - link: https://github.com/scala/scala-abide - homeLink: https://github.com/scala/scala-abide#abide--lint-tooling-for-scala - issuesLink: https://github.com/scala/scala-abide/issues - readmeLink: https://github.com/scala/scala-abide/blob/master/README.md - contributingLink: https://github.com/scala/scala-abide#extending-abide projectsInNeed: - title: Scalariform From 7fbd26db957db39e4c611d5b7d9d9c7295449088 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 27 Jan 2020 18:16:47 -0800 Subject: [PATCH 0148/2265] fix dead links fixes #1101 --- contribute/bug-reporting-guide.md | 2 +- contribute/corelibs.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index bd2f2c70c4..22642e1289 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -44,7 +44,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](https://docs.scala-lang.org/sips/) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). In general, if you find yourself stuck on any of these steps, asking on [Scala Contributors](https://contributors.scala-lang.org/) can be helpful: diff --git a/contribute/corelibs.md b/contribute/corelibs.md index e1f10cb790..bd6827e438 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -20,4 +20,4 @@ There are several options for contributing to Scala's core libraries. You can: For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, you will be asked to submit a SLIP (Scala Library Improvement Process) document. -Please see [instructions for submitting a new SLIP](http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the [pre-requisites](http://docs.scala-lang.org/sips/slip-submission.html) before submitting a SLIP. +Please see [instructions for submitting a new SLIP](https://web.archive.org/web/20180116192845/http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the [pre-requisites](http://docs.scala-lang.org/sips/slip-submission.html) before submitting a SLIP. From cd0e4fa3ac7bb6206a70ef844d17afad9dd21fe8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 29 Jan 2020 10:58:27 -0800 Subject: [PATCH 0149/2265] fix some 404s --- contribute/corelibs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index bd6827e438..260d49fb2f 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -20,4 +20,4 @@ There are several options for contributing to Scala's core libraries. You can: For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, you will be asked to submit a SLIP (Scala Library Improvement Process) document. -Please see [instructions for submitting a new SLIP](https://web.archive.org/web/20180116192845/http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the [pre-requisites](http://docs.scala-lang.org/sips/slip-submission.html) before submitting a SLIP. +Please see [instructions for submitting a new SLIP](https://web.archive.org/web/20180116192845/http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the pre-requisites in the instructions before submitting a SLIP. From ae348d24df52b095cb0ab8b2c64bc1b03ca69770 Mon Sep 17 00:00:00 2001 From: Philippus Date: Thu, 30 Jan 2020 07:55:03 +0100 Subject: [PATCH 0150/2265] Replace references to SLIP with SIP --- contribute/corelibs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index 260d49fb2f..a63707a8e3 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -13,11 +13,11 @@ There are several options for contributing to Scala's core libraries. You can: * [Fix Bugs or Issues](/contribute/guide.html) against the [reported library bugs/issues](https://github.com/scala/bug). * Contribute significant new functionality or a new API by submitting - a Scala Library Improvement Process (SLIP) Document. + a Scala Improvement Process (SIP) Document. -### Submitting a SLIP +### Submitting a SIP For significant new functionality or a whole new API to be considered for -inclusion in the core Scala distribution, you will be asked to submit a SLIP (Scala Library Improvement Process) document. +inclusion in the core Scala distribution, you will be asked to submit a SIP (Scala Improvement Process) document. -Please see [instructions for submitting a new SLIP](https://web.archive.org/web/20180116192845/http://docs.scala-lang.org/sips/slip-submission.html) and familiarize yourself with the [SIP/SLIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the pre-requisites in the instructions before submitting a SLIP. +Please see [instructions for submitting a new SIP](https://docs.scala-lang.org/sips/sip-submission.html) and familiarize yourself with the [SIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the pre-requisites in the instructions before submitting a SIP. From 6342df91471689c4eb7dfc3d45b91c8140b09d63 Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 1 Feb 2020 09:40:38 +0100 Subject: [PATCH 0151/2265] Reword bit about significant changes --- contribute/corelibs.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/contribute/corelibs.md b/contribute/corelibs.md index a63707a8e3..6b2cc5d95f 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -12,12 +12,8 @@ There are several options for contributing to Scala's core libraries. You can: * [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. * [Fix Bugs or Issues](/contribute/guide.html) against the [reported library bugs/issues](https://github.com/scala/bug). -* Contribute significant new functionality or a new API by submitting - a Scala Improvement Process (SIP) Document. -### Submitting a SIP +### Significant changes -For significant new functionality or a whole new API to be considered for -inclusion in the core Scala distribution, you will be asked to submit a SIP (Scala Improvement Process) document. - -Please see [instructions for submitting a new SIP](https://docs.scala-lang.org/sips/sip-submission.html) and familiarize yourself with the [SIP](http://docs.scala-lang.org/sips/) section of the Scala documentation site. Also please pay particular attention to the pre-requisites in the instructions before submitting a SIP. +For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, +please take into account [https://github.com/scala/scala-dev/issues/661] before doing so. From 67a2234cd8fd0085c49bdee4a3b41f75991ff0b2 Mon Sep 17 00:00:00 2001 From: Jihyung Lee Date: Sun, 2 Aug 2020 00:35:12 +0900 Subject: [PATCH 0152/2265] fixed typo and apply updates in English ver --- _ko/tour/implicit-conversions.md | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/_ko/tour/implicit-conversions.md b/_ko/tour/implicit-conversions.md index d6d211895c..bfad32d888 100644 --- a/_ko/tour/implicit-conversions.md +++ b/_ko/tour/implicit-conversions.md @@ -10,33 +10,35 @@ next-page: polymorphic-methods previous-page: implicit-parameters --- -타입 `S`로부터 타입 `T`로의 암시적 변환는 함수 타입 `S => T`의 암시적 값이나 해당 타입으로 변환 가능한 암시적 메소드로 정의된다. +타입 `S`에서 타입 `T`로의 암시적 변환은 타입이 함수 `S => T`인 암시적 값이나 해당 타입으로 변환 가능한 암시적 메소드로 정의된다. 암시적 변환은 두 가지 상황에 적용된다. * 표현식 `e`의 타입이 `S`이고, `S`는 표현식의 기대 타입 `T`를 따르지 않을 때. -* `e`의 타입이 `T`인 `e.m`를 선택한 상황에서, 선택자 `m`이 `T`의 멤버가 아닐 때. +* 타입이 `S`인 `e`의 `e.m`을 선택한 상황에서, 선택자 `m`이 `S`의 멤버가 아닐 때. 첫 번째 경우에서 변환 `c`가 `e`에 적용되며, 결과 타입이 `T`를 따르는지 탐색한다. 두 번째 경우에선 변환 `c`가 `e`에 적용되며, 결과가 `m`이라는 이름의 멤버를 포함하고 있는지 탐색한다. -타입이 `List[Int]`인 두 리스트 xs와 ys의 아래 연산은 허용된다: +암시적 메서드인 `List[A] => Ordered[List[A]]`와 `Int => Ordered[Int]`가 범위 내에 있을 경우, 아래 타입이 `List[Int]`인 두 리스트의 연산은 허용된다: - xs <= ys + List(1, 2, 3) <= List(4, 5) -아래에 정의된 암시적 메소드 `list2ordered`와 `int2ordered`가 범위 안에 있다고 가정한다. +암시적 메서드 `Int => Ordered[Int]`는 `scala.Predef.intWrapper`를 통해 자동으로 제공된다. 암시적 메서드 `Int => Ordered[Int]`의 예시는 아래와 같다. + import scala.language.implicitConversions + implicit def list2ordered[A](x: List[A]) (implicit elem2ordered: a => Ordered[A]): Ordered[List[A]] = - new Ordered[List[A]] { /* .. */ } - - implicit def int2ordered(x: Int): Ordered[Int] = - new Ordered[Int] { /* .. */ } + new Ordered[List[A]] { + // 더 유용한 구현으로 대체하시오 + def compare(that: List[A]): Int = 1 + } -암시적으로 임포트되는 오브젝트 `scala.Predef`는 미리 정의된 여러 타입(예: `Pair`)과 메소드(예: `assert`)뿐만 아니라 여러 뷰도 함께 선언한다. +암시적으로 임포트되는 객체 `scala.Predef`는 자주 사용되는 타입들의 몇몇 별칭(예: 별칭이 `Map`인 `scala.collection.immutable.Map`)과 메소드(예: `assert`), 그리고 여러 암시적 변환을 선언한다. -예를들면, `java.lang.Integer`를 기대하는 자바 메서드를 호출할때, `scala.Int`를 대신 넘겨도 무방하다. 그 이유는 Predef가 아래 암시적 변환들을 포함하기 때문이다. +예를 들면, `java.lang.Integer`를 기대하는 자바 메서드를 호출할 때, `scala.Int`를 대신 넘겨도 된다. 그 이유는 Predef가 아래 암시적 변환을 포함하기 때문이다. ```tut import scala.language.implicitConversions @@ -45,15 +47,14 @@ implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x) ``` -암시적 변환이 무분별하게 사용될 경우 잠재적인 위험을 가질 수 있기 때문에, 컴파일러는 암시적 변환의 선언을 컴파일할때 경고한다. +암시적 변환이 무분별하게 사용될 경우 잠재적인 위험을 가질 수 있기 때문에, 컴파일러는 암시적 변환의 선언을 컴파일할 시 이를 경고한다. -To turn off the warnings take either of these actions: -경고를 끄기 위해서는 아래 중 하나를 선택해야 한다. +경고를 끄기 위해서는 아래 중 하나를 선택해야 한다: -* `scala.language.implicitConversions` 를 암시적 변환의 선언이 있는 범위로 import +* 암시적 변환의 정의가 있는 범위로 `scala.language.implicitConversions` 임포트 * `-language:implicitConversions` 옵션으로 컴파일러 실행 -변환이 컴팡일러에 의해 적용될때 경고가 발생하지 않는다. +컴파일러가 변환을 적용하면 경고가 발생하지 않는다. 윤창석, 이한욱 옮김, 고광현 업데이트 From c7ec1cfc05ce5ae42aeec90607932aaf46659d69 Mon Sep 17 00:00:00 2001 From: Andrew MacGinitie <40873334+macginitie@users.noreply.github.com> Date: Tue, 1 Sep 2020 09:17:04 -0400 Subject: [PATCH 0153/2265] Update getting-started-with-scala-in-intellij.md The instructions as written did not work for me today, so I edited them so they would have. Presumably IntelliJ has changed its behavior since they were written. Note also, they are still off: "To the right of the Scala SDK field, click the **Create** button." There is no such field or button at that point, I assume there was in older versions of IntelliJ. I don't know how best to fix that issue. --- .../intellij-track/getting-started-with-scala-in-intellij.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md b/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md index 2e24d76826..6bab3d3d14 100644 --- a/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md +++ b/_getting-started/intellij-track/getting-started-with-scala-in-intellij.md @@ -40,7 +40,7 @@ take a few minutes but subsequent projects can use the same SDK. ## Writing code 1. On the **Project** pane on the left, right-click `src` and select -**New** => **Scala class**. If you don't see **Scala class**, right-click on **HelloWorld** and click on **Add Framework Support...**, select **Scala** and proceed. If you see **Error: library is not specified**, you can either click download button, or select the library path manually. +**New** => **Scala class**. If you don't see **Scala class**, right-click on **HelloWorld** and click on **Add Framework Support...**, select **Scala** and proceed. If you see **Error: library is not specified**, you can either click download button, or select the library path manually. If you only see **Scala Worksheet** try expanding the `src` folder and its `main` subfolder, and right-click on the `scala` folder. 1. Name the class `Hello` and change the **Kind** to `object`. 1. Change the code in the class to the following: From cf71386e2ab5d166a72dab2b4e36c9af9da51d87 Mon Sep 17 00:00:00 2001 From: Andrew MacGinitie <40873334+macginitie@users.noreply.github.com> Date: Tue, 1 Sep 2020 14:10:28 -0400 Subject: [PATCH 0154/2265] Update building-a-scala-project-with-intellij-and-sbt.md trying to more accurately reflect what I actually see in 1-Sep-2020 version of IntelliJ on Windows (no OK button, Object with capital O) --- .../building-a-scala-project-with-intellij-and-sbt.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md index d1eab7d4ae..485a4e3c5d 100644 --- a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md +++ b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md @@ -54,9 +54,9 @@ but here's a glance at what everything is for: 1. On the **Project** panel on the left, expand `SbtExampleProject` => `src` => `main` 1. Right-click `scala` and select **New** => **Package** -1. Name the package `example` and click **OK**. +1. Name the package `example` and click **OK** (or just press the Enter or Return key). 1. Right-click the package `example` and select **New** => **Scala class**. -1. Name the class `Main` and change the **Kind** to `object`. +1. Name the class `Main` and change the **Kind** to `Object`. 1. Change the code in the class to the following: ``` From 70e4fc300be8d64c048273b7c42629cadb93e1e5 Mon Sep 17 00:00:00 2001 From: ProductiveRage Date: Mon, 14 Sep 2020 21:54:14 +0100 Subject: [PATCH 0155/2265] I didn't have the New / Scala class even after completing the first tutorial When I followed the first tutorial, the IDEA project allowed me to add a new Scala class after I performed the "Add Framework Support" but I had to do it again when I created the sbt project a described in this step --- .../building-a-scala-project-with-intellij-and-sbt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md index d1eab7d4ae..5178ef82dd 100644 --- a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md +++ b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md @@ -55,7 +55,7 @@ but here's a glance at what everything is for: => `main` 1. Right-click `scala` and select **New** => **Package** 1. Name the package `example` and click **OK**. -1. Right-click the package `example` and select **New** => **Scala class**. +1. Right-click the package `example` and select **New** => **Scala class** (if you don't see this option, right-click the `SbtExampleProject`, click **Add Framewords Support**, select **Scala** and proceed) 1. Name the class `Main` and change the **Kind** to `object`. 1. Change the code in the class to the following: From 9131a98be854367a2f0bed4cd0b3b90c82d120c3 Mon Sep 17 00:00:00 2001 From: Niko Ugarov Date: Fri, 18 Sep 2020 22:08:35 +0200 Subject: [PATCH 0156/2265] Removed mention of String Mention of String doesn't make sense without View Bound example which is no longer here. --- _overviews/FAQ/context-bounds.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_overviews/FAQ/context-bounds.md b/_overviews/FAQ/context-bounds.md index 8efd4174da..16c3732be4 100644 --- a/_overviews/FAQ/context-bounds.md +++ b/_overviews/FAQ/context-bounds.md @@ -16,8 +16,7 @@ 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]`, -but unlike `String`. +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 From 6cb611a11390ae11961df6f527a8e73413862425 Mon Sep 17 00:00:00 2001 From: Jacob Kim Date: Tue, 22 Sep 2020 14:52:48 +0900 Subject: [PATCH 0157/2265] Add info about scala -Yrepl-class-based:false flag to reflection/overview.md --- _overviews/reflection/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/reflection/overview.md b/_overviews/reflection/overview.md index 08dd5dcc58..2a8cbae7e8 100644 --- a/_overviews/reflection/overview.md +++ b/_overviews/reflection/overview.md @@ -130,7 +130,7 @@ available that are loaded by the current classloader, including class The second step involves obtaining a `ClassMirror` for class `Person` using the `reflectClass` method. The `ClassMirror` provides access to the -constructor of class `Person`. +constructor of class `Person`. (If this step causes an exception, the easy workaround is to use these flags when starting REPL. `scala -Yrepl-class-based:false`) scala> val ctor = ru.typeOf[Person].decl(ru.termNames.CONSTRUCTOR).asMethod ctor: scala.reflect.runtime.universe.MethodSymbol = constructor Person From 20651f5d0ecc8c16dcca1edac5cde4b745755cfc Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Thu, 1 Oct 2020 00:58:40 +0100 Subject: [PATCH 0158/2265] Update overview.md (#1784) Java SE 15 has been released --- _overviews/jdk-compatibility/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 09c2ef46cc..60f0f16ff3 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -77,7 +77,7 @@ As far as we know, 12, 13, and 14 are similar to 11 with respect to Scala compat ## JDK 15 -As of September 2020, JDK 15 is in release candidate phase ([reference](https://openjdk.java.net/projects/jdk/15/)). We don't have any compatibility information yet. +As of September 2020, JDK 15 has been released to the general public ([reference](https://openjdk.java.net/projects/jdk/15/)). We don't have any compatibility information yet. ## Scala 3 From 2034779b553daf4768ee8612f097b20b5d887bd9 Mon Sep 17 00:00:00 2001 From: Jihyung Lee Date: Thu, 1 Oct 2020 22:39:33 +0900 Subject: [PATCH 0159/2265] apply review comments --- _ko/tour/implicit-conversions.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_ko/tour/implicit-conversions.md b/_ko/tour/implicit-conversions.md index bfad32d888..3b620ab090 100644 --- a/_ko/tour/implicit-conversions.md +++ b/_ko/tour/implicit-conversions.md @@ -18,25 +18,25 @@ previous-page: implicit-parameters * 타입이 `S`인 `e`의 `e.m`을 선택한 상황에서, 선택자 `m`이 `S`의 멤버가 아닐 때. -첫 번째 경우에서 변환 `c`가 `e`에 적용되며, 결과 타입이 `T`를 따르는지 탐색한다. -두 번째 경우에선 변환 `c`가 `e`에 적용되며, 결과가 `m`이라는 이름의 멤버를 포함하고 있는지 탐색한다. +첫 번째 경우, `e`에 적용되며 결과 타입이 `T`인 변환 `c`를 찾는다. +두 번째 경우, `e`에 적용되며 결과에 `m`이라는 이름의 멤버를 포함하는 변환 `c`를 찾는다. -암시적 메서드인 `List[A] => Ordered[List[A]]`와 `Int => Ordered[Int]`가 범위 내에 있을 경우, 아래 타입이 `List[Int]`인 두 리스트의 연산은 허용된다: +암시적 메서드인 `List[A] => Ordered[List[A]]`와 `Int => Ordered[Int]`가 범위 내에 있을 경우, 아래와 같이 타입이 `List[Int]`인 두 리스트의 연산은 허용된다: List(1, 2, 3) <= List(4, 5) -암시적 메서드 `Int => Ordered[Int]`는 `scala.Predef.intWrapper`를 통해 자동으로 제공된다. 암시적 메서드 `Int => Ordered[Int]`의 예시는 아래와 같다. +`scala.Predef.intWrapper`는 암시적 메서드 암시적 메서드 `Int => Ordered[Int]`를 자동으로 제공한다. 다음은 암시적 메서드 `Int => Ordered[Int]`의 예시이다. import scala.language.implicitConversions implicit def list2ordered[A](x: List[A]) - (implicit elem2ordered: a => Ordered[A]): Ordered[List[A]] = + (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] = new Ordered[List[A]] { // 더 유용한 구현으로 대체하시오 def compare(that: List[A]): Int = 1 } -암시적으로 임포트되는 객체 `scala.Predef`는 자주 사용되는 타입들의 몇몇 별칭(예: 별칭이 `Map`인 `scala.collection.immutable.Map`)과 메소드(예: `assert`), 그리고 여러 암시적 변환을 선언한다. +암시적으로 임포트되는 객체 `scala.Predef`는 자주 사용되는 타입의 별칭(예: `scala.collection.immutable.Map`의 별칭 `Map`)과 메소드(예: `assert`), 그리고 여러 암시적 변환을 선언한다. 예를 들면, `java.lang.Integer`를 기대하는 자바 메서드를 호출할 때, `scala.Int`를 대신 넘겨도 된다. 그 이유는 Predef가 아래 암시적 변환을 포함하기 때문이다. @@ -51,10 +51,10 @@ implicit def int2Integer(x: Int) = 경고를 끄기 위해서는 아래 중 하나를 선택해야 한다: -* 암시적 변환의 정의가 있는 범위로 `scala.language.implicitConversions` 임포트 +* 암시적 변환의 정의가 있는 범위 내에서 `scala.language.implicitConversions` 임포트 * `-language:implicitConversions` 옵션으로 컴파일러 실행 -컴파일러가 변환을 적용하면 경고가 발생하지 않는다. +컴파일러가 변환을 적용할 때에는 경고가 발생하지 않는다. 윤창석, 이한욱 옮김, 고광현 업데이트 From 16fad15ff3d255898799cb0bc2281fad27ee3844 Mon Sep 17 00:00:00 2001 From: Jasper Moeys Date: Fri, 2 Oct 2020 11:36:58 +0200 Subject: [PATCH 0160/2265] update list of compiler phases Generated with GNU sed: ``` scalac -Vphases | tail -n+3 | sed -rn 's|^\s*([a-z]+)\s+[0-9]+\s+([a-z@].+)$|
\1
\n
\2
\n|p' ``` --- _overviews/compiler-options/index.md | 91 +++++++++++++++------------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index 34c1817b29..68084f4f8e 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -122,67 +122,76 @@ scalacOptions ++= Seq( ### Compilation Phases
-
initial
-
initializing compiler
- -
parse
-
parse source files
+
parser
+
parse source into ASTs, perform simple desugaring
namer
-
create symbols
+
resolve names, attach symbols to named trees
+ +
packageobjects
+
load package objects
+ +
typer
+
the meat and potatoes: type the trees
+ +
superaccessors
+
add super accessors in traits and nested classes
+ +
extmethods
+
add extension methods for inline classes
+ +
pickler
+
serialize symbol tables
-
analyze
-
name and type analysis
+
refchecks
+
reference/override checking, translate nested objects
-
refcheck
-
reference checking
+
patmat
+
translate match expressions
uncurry
-
uncurry function types and applications
+
uncurry, translate function values to anonymous classes
-
lambdalift
-
lambda lifter
+
fields
+
synthesize accessors and fields, add bitmaps for lazy vals
-
typesasvalues
-
represent types as values
+
tailcalls
+
replace tail calls by jumps
-
addaccessors
-
add accessors for constructor arguments
+
specialize
+
@specialized-driven class and method specialization
-
explicitouterclasses
-
make links from inner classes to enclosing one explicit
+
explicitouter
+
this refs to outer pointers
-
addconstructors
-
add explicit constructor for each class
+
erasure
+
erase types, add interfaces for traits
-
tailcall
-
add tail-calls
+
posterasure
+
clean up erased inline classes
-
wholeprog
-
perform whole program analysis
+
lambdalift
+
move nested functions to top level
-
addinterfaces
-
add one interface per class
+
constructors
+
move field definitions into constructors
-
expandmixins
-
expand mixins by code copying
+
flatten
+
eliminate inner classes
-
boxing
-
makes boxing explicit
+
mixin
+
mixin composition
-
erasure
-
type eraser
+
cleanup
+
platform-specific cleanups, generate reflective calls
-
icode
-
generate icode
+
delambdafy
+
remove lambdas
-
codegen
-
enable code generation
+
jvm
+
generate JVM bytecode
terminal
-
compilation terminated
- -
all
-
matches all phases
+
the last phase during a compilation run
From 2c77fff5d69b5f3314f413c76c1e49f2e5000e6b Mon Sep 17 00:00:00 2001 From: Jasper Moeys Date: Fri, 2 Oct 2020 11:57:39 +0200 Subject: [PATCH 0161/2265] add bash magic as comment --- _overviews/compiler-options/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index 68084f4f8e..c8d367c28f 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -122,6 +122,10 @@ scalacOptions ++= Seq( ### Compilation Phases
+
parser
parse source into ASTs, perform simple desugaring
From f22319cb25161bdb984387281024ecb654bc804e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 3 Oct 2020 11:36:20 -0700 Subject: [PATCH 0162/2265] update JDK compat page for JDK 15 release --- _overviews/jdk-compatibility/overview.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 60f0f16ff3..604bbb18bf 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -12,7 +12,7 @@ Sometimes new JVM and JDK (Java Development Kit) versions require us to update S | JDK version | Minimum Scala versions | Recommended Scala versions | |:-----------:|:---------------------------------|:-----------------------------------------------------------| -| 13, 14 | 2.13.2, 2.12.11 | 2.13.3, 2.12.12 | +| 13, 14, 15 | 2.13.2, 2.12.11 | 2.13.3, 2.12.12 | | 12 | 2.13.1, 2.12.9 | 2.13.3, 2.12.12 | | 11 | 2.13.0, 2.12.4, 2.11.12 | 2.13.3, 2.12.12, 2.11.12 | | 8 | 2.13.0, 2.12.0, 2.11.0, 2.10.2 | 2.13.3, 2.12.12, 2.11.12, 2.10.7 | @@ -65,19 +65,15 @@ To track progress on JDK 11 related issues, watch: To help with testing on JDK 11, see [scala/scala-dev#559](https://github.com/scala/scala-dev/issues/559). -## JDK 12, 13, and 14 compatibility notes +## JDK 12, 13, 14, and 15 compatibility notes -JDK 14 was released in March 2020. But 12, 13, and 14 are not LTS releases, so the remarks above about non-LTS releases apply. The next LTS release will be JDK 17. +JDK 14 was released in March 2020, and JDK 15 was released in September 2020. But 12, 13, 14, 15 are not LTS releases, so the remarks above about non-LTS releases apply. The next LTS release will be JDK 17. -JDK 12, 13, and 14 are expected to work wherever JDK 11 does. The Scala community build now runs on JDK 14 (as well as 11 and 8). +JDK 12, 13, 14, and 15 are expected to work wherever JDK 11 does. The Scala community build now runs on JDK 15 (as well as 11 and 8). -As of March 2020, the [jdk12](https://github.com/scala/bug/labels/jdk12) and [jdk13](https://github.com/scala/bug/labels/jdk13) labels in scala/bug have no open bugs. New issues will likely be reported against the newer non-LTS [jdk14 label](https://github.com/scala/bug/labels/jdk14) or the LTS [jdk11 label](https://github.com/scala/bug/labels/jdk11). +As of October 2020, the [jdk12](https://github.com/scala/bug/labels/jdk12) and [jdk13](https://github.com/scala/bug/labels/jdk13) labels in scala/bug have no open bugs. New issues will likely be reported against the newer non-LTS [jdk14 label](https://github.com/scala/bug/labels/jdk14) and [jdk15 label](https://github.com/scala/bug/labels/jdk15) or the LTS [jdk11 label](https://github.com/scala/bug/labels/jdk11). -As far as we know, 12, 13, and 14 are similar to 11 with respect to Scala compatibility. - -## JDK 15 - -As of September 2020, JDK 15 has been released to the general public ([reference](https://openjdk.java.net/projects/jdk/15/)). We don't have any compatibility information yet. +As far as we know, 12, 13, 14, and 15 are similar to 11 with respect to Scala compatibility. ## Scala 3 From c6b25b5e5408bb27424993042a8162e17aacce94 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Wed, 23 Sep 2020 10:50:35 -0600 Subject: [PATCH 0163/2265] Added empty initial files. --- _overviews/overview/a-taste-of-scala.md | 17 +++++++++++++++++ .../overview/collections-classes-methods.md | 0 _overviews/overview/concurrency.md | 0 _overviews/overview/contextual-abstractions.md | 0 _overviews/overview/control-structures.md | 0 _overviews/overview/data-modeling.md | 0 _overviews/overview/first-look-at-types.md | 0 _overviews/overview/functional-programming.md | 0 _overviews/overview/interacting-with-java.md | 0 _overviews/overview/methods-and-functions.md | 0 .../overview/packaging-imports-exports.md | 0 _overviews/overview/scala-3-metaprogramming.md | 0 _overviews/overview/scala-features.md | 0 .../overview/scala-for-javascript-devs.md | 0 _overviews/overview/scala-for-python-devs.md | 0 _overviews/overview/scala-forjava-devs.md | 0 _overviews/overview/scala-tools.md | 0 _overviews/overview/two-types-of-variables.md | 0 _overviews/overview/types-and-type-system.md | 0 _overviews/overview/why-scala-3.md | 0 20 files changed, 17 insertions(+) create mode 100644 _overviews/overview/a-taste-of-scala.md create mode 100644 _overviews/overview/collections-classes-methods.md create mode 100644 _overviews/overview/concurrency.md create mode 100644 _overviews/overview/contextual-abstractions.md create mode 100644 _overviews/overview/control-structures.md create mode 100644 _overviews/overview/data-modeling.md create mode 100644 _overviews/overview/first-look-at-types.md create mode 100644 _overviews/overview/functional-programming.md create mode 100644 _overviews/overview/interacting-with-java.md create mode 100644 _overviews/overview/methods-and-functions.md create mode 100644 _overviews/overview/packaging-imports-exports.md create mode 100644 _overviews/overview/scala-3-metaprogramming.md create mode 100644 _overviews/overview/scala-features.md create mode 100644 _overviews/overview/scala-for-javascript-devs.md create mode 100644 _overviews/overview/scala-for-python-devs.md create mode 100644 _overviews/overview/scala-forjava-devs.md create mode 100644 _overviews/overview/scala-tools.md create mode 100644 _overviews/overview/two-types-of-variables.md create mode 100644 _overviews/overview/types-and-type-system.md create mode 100644 _overviews/overview/why-scala-3.md diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md new file mode 100644 index 0000000000..0b725618d0 --- /dev/null +++ b/_overviews/overview/a-taste-of-scala.md @@ -0,0 +1,17 @@ +--- +type: chapter +layout: multipage-overview +title: A Taste of Scala +description: This page provides a high-level overview of the main features of Scala 3. +partof: overview +overview-name: Overview +discourse: true +num: 1 +outof: 20 +previous-page: +next-page: preliminaries +--- + +Text coming soon ... + + diff --git a/_overviews/overview/collections-classes-methods.md b/_overviews/overview/collections-classes-methods.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/concurrency.md b/_overviews/overview/concurrency.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/contextual-abstractions.md b/_overviews/overview/contextual-abstractions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/control-structures.md b/_overviews/overview/control-structures.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/data-modeling.md b/_overviews/overview/data-modeling.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/first-look-at-types.md b/_overviews/overview/first-look-at-types.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/functional-programming.md b/_overviews/overview/functional-programming.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/interacting-with-java.md b/_overviews/overview/interacting-with-java.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/methods-and-functions.md b/_overviews/overview/methods-and-functions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/packaging-imports-exports.md b/_overviews/overview/packaging-imports-exports.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-3-metaprogramming.md b/_overviews/overview/scala-3-metaprogramming.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-features.md b/_overviews/overview/scala-features.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-for-javascript-devs.md b/_overviews/overview/scala-for-javascript-devs.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-for-python-devs.md b/_overviews/overview/scala-for-python-devs.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-forjava-devs.md b/_overviews/overview/scala-forjava-devs.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/scala-tools.md b/_overviews/overview/scala-tools.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/two-types-of-variables.md b/_overviews/overview/two-types-of-variables.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/types-and-type-system.md b/_overviews/overview/types-and-type-system.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_overviews/overview/why-scala-3.md b/_overviews/overview/why-scala-3.md new file mode 100644 index 0000000000..e69de29bb2 From b39b7a450f337bc15d4c35fed05346d74f67f4eb Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Thu, 24 Sep 2020 21:28:55 -0600 Subject: [PATCH 0164/2265] This is an early draft to demonstrate my writing style. --- _overviews/overview/a-taste-of-scala.md | 1170 ++++++++++++++++++++++- 1 file changed, 1160 insertions(+), 10 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index 0b725618d0..3d4a85700f 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -1,17 +1,1167 @@ --- -type: chapter -layout: multipage-overview title: A Taste of Scala description: This page provides a high-level overview of the main features of Scala 3. -partof: overview -overview-name: Overview -discourse: true -num: 1 -outof: 20 -previous-page: -next-page: preliminaries --- -Text coming soon ... + + + + + +Our hope in this Overview documentation is to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax. To help with that demonstration, this “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. + +>In this Overview it’s assumed that you’ve used a language like Java before, and you’re ready to see a series of Scala examples to get a feel for what the language looks like. You’ll also be able to test many of the examples directly on this page, and in addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), in Worksheets with the VS Code or Intellij IDEA editors, or in the Scala REPL, which will be demonstrated shortly. + + + +## Hello, world + + + +Ever since the book, *C Programming Language*, it’s been a tradition to begin programming books with a “Hello, world” example, and not to disappoint, this is one way to write that example in Scala: + +```scala +@main def hello = println("Hello, world") +``` + +To see how this works, put that line of code in a file named *Hello.scala*, and then compile it with `scalac`: + +```sh +$ scalac Hello.scala +``` + +If you’re coming to Scala from Java, `scalac` is just like `javac`, so that command creates several files: + + +```sh +$ ls -1 +Hello$package$.class +Hello$package.class +Hello$package.tasty +Hello.scala +hello.class +hello.tasty +``` + + +Just like Java, the *.class* files are bytecode files, and they’re ready to run in the JVM. Now you can run the main `hello` method with the `scala` command: + +```sh +$ scala hello +Hello, world +``` + +Assuming that worked, congratulations, you just compiled and ran your first Scala application. + + + + +## The Scala REPL + +The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code. We introduce it early here so you can use it with the code examples that follow. + +Assuming that you’ve downloaded and installed Scala — such as from the [Scala download page](https://www.scala-lang.org/download) — you start a REPL session by running the `scala` command at your operating system command line. When you do this you’ll see a “welcome” prompt that looks like this: + + +```scala +$ scala +Welcome to Scala 3.0.0 (OpenJDK 64-Bit Server VM, Java 11.0.7). +Type in expressions for evaluation. Or try :help. + +scala> _ +``` + +Because the REPL is a command-line interpreter, it sits there waiting for you to type something. Inside the REPL you can type Scala expressions to see how they work: + +```scala +scala> val x = 1 +x: Int = 1 + +scala> val y = x + 1 +y: Int = 2 +``` + +As those examples show, after you type your expressions in the REPL, it shows the result of each expression on the line following the prompt. + +As mentioned earlier, if you prefer a browser-based testing environment you can also use [ScalaFiddle.io](https://scalafiddle.io) or [Scastie.scala-lang.org](https://scastie.scala-lang.org). + + + +## Two types of variables + +When you create a new variable in Scala, you declare whether the variable is immutable or mutable: + +- `val` is an *immutable* variable — like `final` in Java. We recommend always creating a variable with `val`, unless there’s a specific reason you need a mutable variable. +- `var` creates a *mutable* variable, and should only be used when you have a variable whose contents will be modified over time. + +These examples show how to create `val` and `var` variables: + +```scala +val x = 1 // immutable +var y = 0 // mutable +``` + +In an application, once you create a `val` field, it can’t be reassigned. The second line of code here creates an error message: + +```scala +val msg = "Hello, world" +msg = "Hello" // "reassignment to val" error; this won’t compile +``` + +Conversely, a `var` field can be reassigned: + +```scala +var msg = "Hello, world" +msg = "Hello" // this compiles because a var can be reassigned +``` + +>Inside the REPL playground area you can reassign a `val` field, but this is just for convenience. In the real world a `val` field can’t be reassigned. + + + +## Declaring variable types + +In Scala you can declare variables without explicitly declaring their type: + +```scala +val x = 1 +val s = "a string" +val p = Person("Richard") +``` + +When you do this, the Scala compiler can usually infer the data type for you, as shown in the output of these REPL examples: + +```scala +scala> val x = 1 +val x: Int = 1 + +scala> val s = "a string" +val s: String = a string + +scala> val nums = List(1,2,3) +val nums: List[Int] = List(1, 2, 3) +``` + +This feature is known as *type inference*, and it’s a great way to help keep this type of code concise. You can also *explicitly* declare a variable’s type: + +```scala +val x: Int = 1 +val s: String = "a string" +val p: Person = new Person("Richard") +``` + +However, as you can see, in simple situations this isn’t needed, and tends to feel more verbose than necessary. + + + +## Built-in data types + +Scala comes with the standard numeric data types you’d expect, and all of these data types are full-blown instances of classes. In Scala, everything is an object. + +These examples show how to declare variables of the basic numeric types: + +```scala +val b: Byte = 1 +val x: Int = 1 +val l: Long = 1 +val s: Short = 1 +val d: Double = 2.0 +val f: Float = 3.0 +``` + +In the first four examples, if you don’t explicitly specify a type, the number `1` will default to an `Int`, so if you want one of the other data types — `Byte`, `Long`, or `Short` — you need to explicitly declare those types, as shown. Numbers with a decimal (like 2.0) will default to a `Double`, so if you want a `Float` you need to declare a `Float`, as shown in the last example. + +Because `Int` and `Double` are the default numeric types, you typically create them without explicitly declaring the data type: + +```scala +val i = 123 // defaults to Int +val x = 1.0 // defaults to Double +``` + + + +### BigInt and BigDecimal + +When you need really large numbers, Scala also includes the types `BigInt` and `BigDecimal`: + +```scala +var b = BigInt(1234567890) +var b = BigDecimal(123456.789) +``` + +A great thing about `BigInt` and `BigDecimal` is that they support all the operators you’re used to using with numeric types: + +```scala +scala> var b = BigInt(1234567890) +b: scala.math.BigInt = 1234567890 + +scala> b + b +res0: scala.math.BigInt = 2469135780 + +scala> b * b +res1: scala.math.BigInt = 1524157875019052100 + +scala> b += 1 + +scala> println(b) +1234567891 +``` + +While you can think of `+`, `*`, and `+=` as being “operators,” because everything in Scala is an object, they’re really methods on their classes. + + +### String and Char + +Scala also has `String` and `Char` data types, which you can generally declare with the implicit form: + +```scala +val name = "Bill" +val c = 'a' +``` + +However, you can use the explicit form, if you prefer: + +```scala +val name: String = "Bill" +val c: Char = 'a' +``` + +As shown, strings are enclosed in double-quotes — or triple-quotes, as you’re about to see — and a character is enclosed in single-quotes. + + + +## Two notes about strings + +Scala strings are similar to Java strings, but they have at least two great additional features: + +- They support string interpolation +- You can create multiline strings + + +### String interpolation + +In its most basic form, string interpolation provides a great way to use variables inside strings. For instance, given these three variables: + +```scala +val firstName = "John" +val mi = 'C' +val lastName = "Doe" +``` + +string interpolation lets you combine those variables in a string like this: + +```scala +val name = s"$firstName $mi $lastName" +``` + +This lets you embed variables inside strings in a very readable way: + +```scala +println(s"Name: $firstName $mi $lastName") +``` + +As shown, all you have to do is to precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. + +It’s important to know that string interpolation goes well beyond this basic use. For instance, you can also access class fields and use equations inside the interpolated string by enclosing those references inside curly braces. This example shows how to reference a class field (or method) inside an interpolated string: + +```scala +class Person(var name: String) +val p = Person("Margaret Hamilton") +println(s"Name: ${p.name}") +``` + +This example shows how to use an equation: + +```scala +println(s"2 + 2 = ${2 + 2}") // prints '4' +``` + +#### Other interpolators + +“Why use the `s` in front of the string,” you may ask. The answer is that the `s` that precedes the strings in these examples is just one possible interpolator. You can also use the letter `f` in front of a string to use `printf`-style string formatting: + +```scala +val name = "Fred" +val age = 33 +val weight = 200.5 +println(f"$name is $age years old, and weighs $weight%.1f pounds.") +``` + + + +Very importantly, because `s` and `f` are really just methods, other developers can write their own interpolators. For instance, Scala database libraries can create an `sql` interpolator that can have special features to support SQL: + +```scala +val query = sql"select * from $table" +``` + + +>For more details about interpolators, see the Scala Reference documentation. + + + + +### Multiline strings + +A second great feature of Scala strings is that you can create multiline strings by including the string inside three double-quotes: + +```scala +val speech = """Four score and + seven years ago + our fathers ...""" +``` + + +That’s very helpful for when you need to work with multiline strings. One drawback of this basic approach is that the lines after the first line are indented, as you can see in the REPL: + +```scala +scala> val speech = """Four score and + | seven years ago + | our fathers ...""" +speech: String = +Four score and + seven years ago + our fathers ... +``` + +A simple way to correct this problem is to put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: + +```scala +val speech = """Four score and + |seven years ago + |our fathers ...""".stripMargin +``` + +The REPL shows that when you do this, all of the lines are left-justified: + +```scala +scala> val speech = """Four score and + | |seven years ago + | |our fathers ...""".stripMargin +speech: String = +Four score and +seven years ago +our fathers ... +``` + +Because this is what you generally want, this is a common way to create multiline strings. + + + +## Control structures + + +Scala has all of the basic programming language control structures you find in other languages, and also has powerful `for` expressions and `match` expressions: + +- if/else +- `for` loops +- `match` expressions +- while, do/while +- try/catch + +These structures are demonstrated in the following examples. + + +### if/else + +Scala’s if/else control structure is similar to other languages. A multiline statement looks like this: + +```scala +if x < 0 then + "negative" +else if x == 0 + "zero" +else + "positive" +``` + +and a single-line expression looks like this: + +```scala +if x < 0 then -x else x +``` + +Note that this really is an *expression* — not a *statement* — meaning that it returns a value, and can therefore be used as a ternary operator: + +```scala +val x = if (a < b) a else b +``` + +In fact, as you’ll see throughout this Overview and in our Reference documentation, *all* Scala control structures can be used as expressions. + + +### for loops and expressions + + +In its most basic use, the `for` keyword can be used to create a `for` loop. For instance, given this list: + +```scala +// TODO introduce ranges first +val ints = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +val ints = List.range(1,10) +``` + +you can print each element in the list like this: + +```scala +for (i <- ints) println(i) +``` + +You can also use one or more *guards* — `if` expressions — inside a `for` loop. This example prints all of the numbers in `ints` that are greater than `5`: + +```scala +for i <- ints if i > 5 +do println(i) +``` + +That statement can be written like this if you prefer: + +```scala +for + i <- ints + if i > 5 +do + println(i) +``` + +This style is commonly used, because it supports the use of multiple generators and guards. For instance, this example prints all of the even numbers in `ints` that are greater than `2`: + +```scala +// prints 4,6,8, and 10 on different lines +for + i <- ints + if i > 2 + if i % 2 == 0 +do + println(i) +``` + + +Simple Scala `for` loops look like this: + +```scala +for (arg <- args) println(arg) + +// "x to y" syntax +for (i <- 0 to 5) println(i) + +// "x to y by" syntax +for (i <- 0 to 10 by 2) println(i) +``` + +As shown in these examples, `for` loops are used for side effects, such as printing to the console. This use of the `for` keyword is just the beginning. When you add the `yield` keyword to `for` loops, you create powerful `for` *expressions* which are used to calculate and yield results. This REPL example shows how to use the for/yield combination to double each value in the sequence `1` to `5`: + +```scala +scala> val x = for i <- 1 to 5 yield i * 2 +val x: IndexedSeq[Int] = Vector(2, 4, 6, 8, 10) +``` + + + +Here’s another `for` expression that iterates over a list of strings: + + +```scala +val fruits = List("apple", "banana", "lime", "orange") + +val fruitLengths = for + f <- fruits + if f.length > 4 +yield + f.length + +// result: List[Int] = List(5, 6, 6) +``` + +Because Scala code generally just makes sense, you can probably guess how this code works, even if you’ve never seen a for-expression or Scala list until now. + + +`for` loops and expressions are covered in more detail in the Control Structures section. + + + + +### match expressions + +Scala has a `match` expression, which in its most basic use is like a Java `switch` statement: + +```scala +val i = 1 + +// later in the code ... +val result = i match + case 1 => "one" + case 2 => "two" + case _ => "not 1 or 2" +``` + +The `match` expression isn’t limited to just integers, it can be used with any data type, including booleans: + +```scala +val booleanAsString = bool match + case true => "true" + case false => "false" +``` + +Here’s an example of `match` being used as the body of a method, and matching against many different types: + +```scala +def getClassAsString(x: Any): String = x match + case s: String => s + " is a String" + case i: Int => "Int" + case f: Float => "Float" + case l: List[_] => "List" + case p: Person => "Person" + case _ => "Unknown" +``` + +Pattern matching is a significant feature of Scala, and you’ll see it used TODO (more here) + + + + + + + +### try/catch + +Scala’s try/catch control structure lets you catch exceptions. It’s similar to Java, but its syntax is consistent with `match` expressions: + + +```scala +try + writeToFile(text) +catch + case fnfe: FileNotFoundException => println(fnfe) + case ioe: IOException => println(ioe) +``` + + +### while loops + +Scala also has a `while` loop. It’s one-line syntax looks like this: + +```scala +while x >= 0 do x = f(x) +``` + +And it’s multiline syntax looks like this: + +```scala +var x = 1 +while (x < 3) + println(x) + x += 1 +``` + + + + + + +### Create your own control structures! + +- whilst +- doubleIfCOnditions + doubleif(age > 18)(numAccidents == 0) { println("Discount!") } + // two 'if' condition tests + def doubleif(test1: => Boolean)(test2: => Boolean)(codeBlock: => Unit) { if (test1 && test2) { + codeBlock + } } + + + +## Data Modeling + +Scala supports both functional programming (FP) and object-oriented programming (OOP), as well as a fusion of the two paradigms. This section provides an overview of data modeling in OOP and FP. + + +### OOP data modeling (traits and classes) + +When writing code in an OOP style, your two main tools will be *traits* and *classes*. + +#### Traits + + +Traits can be used like interfaces and abstract classes in other languages, and they can also be used as mixins. Traits let you break your code down into small, modular units. Traits are like interfaces in other languages, but they can also contain implemented methods. When you want to create concrete implementations of attributes and behaviors, classes and objects can extend traits. + +To demonstrate some things you can do with traits, here are three traits that define well-organized and modular behaviors for animals like dogs and cats: + +```scala +trait Speaker: + def speak(): String // has no body, so it’s abstract + +trait TailWagger: + def startTail(): Unit = println("tail is wagging") + def stopTail(): Unit = println("tail is stopped") + +trait Runner: + def startRunning(): Unit = println("I’m running") + def stopRunning(): Unit = println("Stopped running") +``` + +Once you have those traits, you can create a `Dog` class that extends all three of those traits while providing a behavior for the abstract `speak` method: + +```scala +class Dog(name: String) extends Speaker with TailWagger with Runner: + def speak(): String = "Woof!" +``` + +Similarly, here’s a `Cat` class that shows how to implement those same traits while also overriding two of the methods it inherits: + +```scala +class Cat extends Speaker with TailWagger with Runner: + def speak(): String = "Meow" + override def startRunning(): Unit = println("Yeah ... I don’t run") + override def stopRunning(): Unit = println("No need to stop") +``` + + +If that code makes sense — great, you’re comfortable with traits as interfaces. If not, don’t worry, they’re explained in more detail in the Data Modeling section of the Reference documentation. + + + + +#### Classes + + + +Scala classes are used in OOP-style programming. Here’s an example of a Scala class that models a “person,” where the person’s first and last names can both be modified (mutated): + +```scala +class Person(var firstName: String, var lastName: String): + def printFullName() = println(s"$firstName $lastName") +``` + +This is how you use that class: + +```scala +// TODO: update +val p = Person("Julia", "Kern") +println(p.firstName) +p.lastName = "Manes" +p.printFullName() +``` + + +Notice that the first and last names can be mutated because they’re declared as `var` fields. Also, there’s no need to create “get” and “set” methods to access the fields in the class. You’ll see more details about classes in the Data Modeling section. + +As a more complicated example, here’s a `Pizza` class that you’ll see later in the book: + +```scala +class Pizza ( + var crustSize: CrustSize, + var crustType: CrustType, + val toppings: ArrayBuffer[Topping] +) { + def addTopping(t: Topping): Unit = toppings += t + def removeTopping(t: Topping): Unit = toppings -= t + def removeAllToppings(): Unit = toppings.clear() +} +``` + +In that code, an `ArrayBuffer` is a mutable sequence, like Java’s `ArrayList`. The `CrustSize`, `CrustType`, and `Topping` classes aren’t shown, but you can probably understand how that code works without needing to see those classes. + + +### FP data modeling (TODO) + +When writing code in an FP style, you’ll use these constructs: + +- Traits +- Enums to define ADTs +- Case classes + + +#### Enums + + + + +```scala +enum CrustSize: + case Small, Medium, Large + +enum CrustType: + case Thin, Thick, Regular + +enum Topping: + case Cheese, Pepperoni, Olives +``` + + +```scala +case class Pizza: + crustSize: CrustSize, + crustType: CrustType, + toppings: Seq[Topping] + +@main def pizzaDemo = + import CrustSize._ + import CrustType._ + import Topping._ + + // passing enums as method parameters + val smallThinCheesePizza = Pizza( + Small, Thin, Seq(Cheese) + ) + + val largeThickWorks = Pizza( + Large, Thick, Seq(Cheese, Pepperoni, Olives) + ) + + println(smallThinCheesePizza) + println(largeThickWorks) + + printCrustSize(Small) + + // using an enum as a method parameter and in a match expression + def printCrustSize(cs: CrustSize) = cs match + case Small => println("small") + case Medium => println("medium") + case Large => println("large") +``` + + +##### Enums (WORKING) + +Enums can take parameters: + +```scala +// named values +enum Color: + case Red, Green, Blue + +// parameterized +enum Color(val rgb: Int): + case Red extends Color(0xFF0000) + case Green extends Color(0x00FF00) + case Blue extends Color(0x0000FF) + case Mix(mix: Int) extends Color(mix) + +//TODO show usage +val red = Color.Red +Color.valueOf("Blue") // res0: Color = Blue +Color.values // Array(Red, Green, Blue) + +// user-defined members +enum Planet(mass: Double, radius: Double): + private final val G = 6.67300E-11 + def surfaceGravity = G * mass / (radius * radius) + def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity + + case Mercury extends Planet(3.303e+23, 2.4397e6) + case Venus extends Planet(4.869e+24, 6.0518e6) + case Earth extends Planet(5.976e+24, 6.37814e6) + // more ... +} +``` + + + + + + + + + +#### Case classes + +A *case class* is different than the base Scala class. Case classes provide support for functional programming, and they have all of the functionality of a regular class, and more. When the compiler sees the `case` keyword in front of a `class`, it generates code for you, with the following benefits: + +- Case class constructor parameters are public `val` fields by default, so accessor methods are generated for each parameter. +- An `apply` method is created in the companion object of the class, so you don’t need to use the `new` keyword to create a new instance of the class. +- An `unapply` method is generated, which lets you use case classes in more ways in `match` expressions. +- A `copy` method is generated in the class. You may not use this feature in Scala/OOP code, but it’s used all the time in Scala/FP. +- `equals` and `hashCode` methods are generated, which let you compare objects and easily use them as keys in maps. +- A default `toString` method is generated, which is helpful for debugging. + +// BASIC +case class Person(name: String, relation: String) +val christina = Person("Christina", "niece") +christina.name +christina.name = "Fred" // error + +// MORE +trait Person: + def name: String +case class Student(name: String, year: Int) extends Person +case class Teacher(name: String, specialty: String) extends Person + +def getPrintableString(p: Person): String = p match { + case Student(name, year) => + s"$name is a student in Year $year." + case Teacher(name, whatTheyTeach) => + s"$name teaches $whatTheyTeach." +} + +val s = Student("Al", 1) +val t = Teacher("Bob Donnan", "Mathematics") +getPrintableString(s) +getPrintableString(t) + + +// `copy`: “update as you copy” +case class BaseballTeam(name: String, lastWorldSeriesWin: Int) +val cubs1908 = BaseballTeam("Chicago Cubs", 1908) +val cubs2016 = cubs1908.copy(lastWorldSeriesWin = 2016) + +// `equals` and `hashCode` +case class Person(name: String, relation: String) +val christina = Person("Christina", "niece") +val hannah = Person("Hannah", "niece") +christina == hannah + + + + + +## Scala methods + +Scala classes, case classes, and objects can all contain methods. This is what the Scala method syntax looks like: + +```scala +def sum(a: Int, b: Int): Int = a + b +def concatenate(s1: String, s2: String): String = s1 + s2 +``` + +You don’t have to declare a method’s return type, so it’s perfectly legal to write those two methods like this, if you prefer: + +```scala +def sum(a: Int, b: Int) = a + b +def concatenate(s1: String, s2: String) = s1 + s2 +``` + +This is how you call those methods: + +```scala +val x = sum(1, 2) +val y = concatenate("foo", "bar") +``` + +There are more things you can do with methods, such as providing default values for method parameters and using named parameters when calling methods, and those are shown in TODO + + + + + +## First-class functions (TODO) + +- top-level functions +- functions in objects +- lambdas / function literals / anonymous functions +- HOFs +- HOFs in the standard library + + + + +## Collections classes + +If you’re coming to Scala from Java and you’re ready to really jump in and learn Scala, it’s possible to use the Java collections classes in Scala, and some people do so for several weeks or months while getting comfortable with Scala. But it’s highly recommended that you learn the basic Scala collections classes — `List`, `ListBuffer`, `Vector`, `ArrayBuffer`, `Map`, and `Set` — as soon as possible. A great benefit of the Scala collections classes is that they offer many powerful methods that you’ll want to start using as soon as possible to simplify your code. + + + + +### Populating lists + +There are times when it’s helpful to create sample lists that are populated with data, and Scala offers many ways to populate lists. Here are just a few: + +```scala +val nums = List.range(0, 10) +val nums = (1 to 10 by 2).toList +val letters = ('a' to 'f').toList +val letters = ('a' to 'f' by 2).toList +``` + + +### Sequence methods + +While there are many sequential collections classes you can use — `Array`, `ArrayBuffer`, `Vector`, `List`, and more — let’s look at some examples of what you can do with the `List` class. Given these two lists: + +```scala +val nums = (1 to 10).toList +val names = List("joel", "ed", "chris", "maurice") +``` + +This is the `foreach` method: + +```scala +scala> names.foreach(println) +joel +ed +chris +maurice +``` + +Here’s the `filter` method, followed by `foreach`: + +```scala +scala> nums.filter(_ < 4).foreach(println) +1 +2 +3 +``` + +Here are some examples of the `map` method: + +```scala +scala> val doubles = nums.map(_ * 2) +doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) + +scala> val capNames = names.map(_.capitalize) +capNames: List[String] = List(Joel, Ed, Chris, Maurice) + +scala> val lessThanFive = nums.map(_ < 5) +lessThanFive: List[Boolean] = List(true, true, true, true, false, false, false, false, false, false) +``` + +Even without any explanation you can see how `map` works: It applies an algorithm you supply to every element in the collection, returning a new, transformed value for each element. + +If you’re ready to see one of the most powerful collections methods, here’s `foldLeft`: + +```scala +scala> nums.foldLeft(0)(_ + _) +res0: Int = 55 + +scala> nums.foldLeft(1)(_ * _) +res1: Int = 3628800 +``` + +Once you know that the first parameter to `foldLeft` is a *seed* value, you can guess that the first example yields the *sum* of the numbers in `nums`, and the second example returns the *product* of all those numbers. + +There are many (many!) more methods available to Scala collections classes, and many of them will be demonstrated in the collections lessons that follow, but hopefully this gives you an idea of their power. + +>For more details, jump to [the Scala Book collections lessons]({{site.baseurl}}/overviews/scala-book/collections-101.html), or see [the Mutable and Immutable collections overview]({{site.baseurl}}/overviews/collections-2.13/overview.html) for more details and examples. + + + +## Tuples (TODO: update this section) + +The Scala *tuple* is a class that lets you easily put a collection of different types in the same container. This is how you create a tuple that contains an `Int`, a `String`, and a `Boolean` value: + +```scala +val t = (11, "eleven", true) +``` + +You can see the type in the REPL: + +```` +scala> val t = (11, "eleven", true) +TODO: UPDATE +```` + +You can access the tuple values by number: + +```scala +t._1 +t._2 +t._3 +``` + +TODO: other methods: + +t.head +t.tail +t.drop(1) +t.take(1) +t.size +t.map ... + +Or assign the tuple fields to variables: + +```scala +val (num, string, good) = (11, "eleven", true) +``` + +```` +scala> val (num, string, person) = (11, "eleven", true) +TODO: UPDATE +```` + +Tuples are nice for those times when you need to put a little “bag” of things together for a little while. + + + +## Changes from Scala 2 +## New control syntax +## Optional braces, indentation + + + +## TODO: Other possible topics not in the outline + +- Multiversal equality +- Advanced types +- Ranges +```scala +for (arg <- args) println(arg) + +// "x to y" syntax +for (i <- 0 to 5) println(i) + +// "x to y by" syntax +for (i <- 0 to 10 by 2) println(i) +``` + + +## A small, sample application + +- “Putting it all together” + +- show an sbt example +- show several features +- @main + + + + + + + + + + From 4af19bbff092c40197b7fb86c83206cc4f43263d Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Thu, 24 Sep 2020 21:31:52 -0600 Subject: [PATCH 0165/2265] This is an early draft to demonstrate my writing style. --- _overviews/overview/a-taste-of-scala.md | 26 +------------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index 3d4a85700f..0944d3c1ef 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -8,31 +8,7 @@ description: This page provides a high-level overview of the main features of Sc - test with jekyll on my system --> - - - + Our hope in this Overview documentation is to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax. To help with that demonstration, this “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. >In this Overview it’s assumed that you’ve used a language like Java before, and you’re ready to see a series of Scala examples to get a feel for what the language looks like. You’ll also be able to test many of the examples directly on this page, and in addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), in Worksheets with the VS Code or Intellij IDEA editors, or in the Scala REPL, which will be demonstrated shortly. From 61e26ed7ea7e186ed38cb60f79a0b494b04e1ad9 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Mon, 28 Sep 2020 00:07:47 -0600 Subject: [PATCH 0166/2265] Added more topics while reducing the descriptive text. --- _overviews/overview/a-taste-of-scala.md | 1248 +++++++++++++---------- 1 file changed, 717 insertions(+), 531 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index 0944d3c1ef..cb83bb5b36 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -3,15 +3,18 @@ title: A Taste of Scala description: This page provides a high-level overview of the main features of Scala 3. --- - - -Our hope in this Overview documentation is to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax. To help with that demonstration, this “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. +This “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. ->In this Overview it’s assumed that you’ve used a language like Java before, and you’re ready to see a series of Scala examples to get a feel for what the language looks like. You’ll also be able to test many of the examples directly on this page, and in addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), in Worksheets with the VS Code or Intellij IDEA editors, or in the Scala REPL, which will be demonstrated shortly. +>Throughout this Overview you’ll also be able to test many of the examples directly on this page. In addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), or in the Scala REPL, which is demonstrated shortly. @@ -19,13 +22,13 @@ Our hope in this Overview documentation is to demonstrate that Scala is a beauti -Ever since the book, *C Programming Language*, it’s been a tradition to begin programming books with a “Hello, world” example, and not to disappoint, this is one way to write that example in Scala: +A “Hello, world” example in Scala goes as follows. First, Put this code in a file named *Hello.scala*: ```scala @main def hello = println("Hello, world") ``` -To see how this works, put that line of code in a file named *Hello.scala*, and then compile it with `scalac`: +Next, compile the code with `scalac`: ```sh $ scalac Hello.scala @@ -44,8 +47,7 @@ hello.class hello.tasty ``` - -Just like Java, the *.class* files are bytecode files, and they’re ready to run in the JVM. Now you can run the main `hello` method with the `scala` command: +Like Java, the *.class* files are bytecode files, and they’re ready to run in the JVM. Now you can run the main `hello` method with the `scala` command: ```sh $ scala hello @@ -53,15 +55,12 @@ Hello, world ``` Assuming that worked, congratulations, you just compiled and ran your first Scala application. - ## The Scala REPL -The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code. We introduce it early here so you can use it with the code examples that follow. - -Assuming that you’ve downloaded and installed Scala — such as from the [Scala download page](https://www.scala-lang.org/download) — you start a REPL session by running the `scala` command at your operating system command line. When you do this you’ll see a “welcome” prompt that looks like this: +The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code. You start a REPL session by running the `scala` command at your operating system command line. When you do so, you’ll see a “welcome” prompt like this: ```scala @@ -72,19 +71,36 @@ Type in expressions for evaluation. Or try :help. scala> _ ``` -Because the REPL is a command-line interpreter, it sits there waiting for you to type something. Inside the REPL you can type Scala expressions to see how they work: +The REPL is a command-line interpreter, so it sits there waiting for you to type something. Now you can type Scala expressions to see how they work: -```scala -scala> val x = 1 -x: Int = 1 +```` +scala> 1 + 1 +val res0: Int = 2 -scala> val y = x + 1 -y: Int = 2 -``` +scala> 2 + 2 +val res1: Int = 4 +```` -As those examples show, after you type your expressions in the REPL, it shows the result of each expression on the line following the prompt. +As shown in the output, if you don’t assign a variable to the result of an expression, the REPL creates variables named `res0`, `res1`, etc., for you. You can use these variable names in future expressions: -As mentioned earlier, if you prefer a browser-based testing environment you can also use [ScalaFiddle.io](https://scalafiddle.io) or [Scastie.scala-lang.org](https://scastie.scala-lang.org). +```` +scala> val x = res0 * 10 +val x: Int = 20 +```` + +Notice that the REPL output also shows the result of your expressions. + +You can run all sorts of experiments in the REPL. This example shows how to create and then call a `sum` function: + +```` +scala> def sum(a: Int, b: Int): Int = a + b +def sum(a: Int, b: Int): Int + +scala> sum(2, 2) +val res2: Int = 4 +```` + +As mentioned earlier, if you prefer a browser-based playground environment, you can also use [ScalaFiddle.io](https://scalafiddle.io) or [Scastie.scala-lang.org](https://scastie.scala-lang.org). @@ -92,17 +108,20 @@ As mentioned earlier, if you prefer a browser-based testing environment you can When you create a new variable in Scala, you declare whether the variable is immutable or mutable: -- `val` is an *immutable* variable — like `final` in Java. We recommend always creating a variable with `val`, unless there’s a specific reason you need a mutable variable. -- `var` creates a *mutable* variable, and should only be used when you have a variable whose contents will be modified over time. +- `val` creates an *immutable* variable — like `final` in Java. You should always create a variable with `val`, unless there’s a reason you need a mutable variable. +- `var` creates a *mutable* variable, and should only be used when a variable’s contents will change over time. These examples show how to create `val` and `var` variables: ```scala -val x = 1 // immutable -var y = 0 // mutable +val a = 0 // immutable +val b = "Hello" + +var c = 1 // mutable +var d = "world" ``` -In an application, once you create a `val` field, it can’t be reassigned. The second line of code here creates an error message: +In an application, a `val` field can’t be reassigned. You’ll generate a compiler error if you try to reassign one: ```scala val msg = "Hello, world" @@ -116,21 +135,20 @@ var msg = "Hello, world" msg = "Hello" // this compiles because a var can be reassigned ``` ->Inside the REPL playground area you can reassign a `val` field, but this is just for convenience. In the real world a `val` field can’t be reassigned. +>Inside the REPL playground area you can reassign a `val` field, but this is just for convenience. ## Declaring variable types -In Scala you can declare variables without explicitly declaring their type: +You can declare variables by explicitly declaring their type, or by letting the compiler infer the type: ```scala -val x = 1 -val s = "a string" -val p = Person("Richard") +val x: Int = 1 // explicit +val x = 1 // implicit; the compiler infers the type ``` -When you do this, the Scala compiler can usually infer the data type for you, as shown in the output of these REPL examples: +The second form is known as *type inference*, and it’s a great way to help keep this type of code concise. The Scala compiler can usually infer the data type for you, as shown in the output of these examples: ```scala scala> val x = 1 @@ -143,7 +161,7 @@ scala> val nums = List(1,2,3) val nums: List[Int] = List(1, 2, 3) ``` -This feature is known as *type inference*, and it’s a great way to help keep this type of code concise. You can also *explicitly* declare a variable’s type: +You can always explicitly declare a variable’s type if you prefer, but in simple assignments like these it isn’t necessary: ```scala val x: Int = 1 @@ -151,15 +169,15 @@ val s: String = "a string" val p: Person = new Person("Richard") ``` -However, as you can see, in simple situations this isn’t needed, and tends to feel more verbose than necessary. +Notice that with this approach, the code feels more verbose than necessary. ## Built-in data types -Scala comes with the standard numeric data types you’d expect, and all of these data types are full-blown instances of classes. In Scala, everything is an object. +Scala comes with the standard numeric data types you’d expect, and they’re all full-blown instances of classes. In Scala, everything is an object. -These examples show how to declare variables of the basic numeric types: +These examples show how to declare variables of the numeric types: ```scala val b: Byte = 1 @@ -170,78 +188,48 @@ val d: Double = 2.0 val f: Float = 3.0 ``` -In the first four examples, if you don’t explicitly specify a type, the number `1` will default to an `Int`, so if you want one of the other data types — `Byte`, `Long`, or `Short` — you need to explicitly declare those types, as shown. Numbers with a decimal (like 2.0) will default to a `Double`, so if you want a `Float` you need to declare a `Float`, as shown in the last example. - Because `Int` and `Double` are the default numeric types, you typically create them without explicitly declaring the data type: ```scala val i = 123 // defaults to Int -val x = 1.0 // defaults to Double +val j = 1.0 // defaults to Double ``` - - - -### BigInt and BigDecimal -When you need really large numbers, Scala also includes the types `BigInt` and `BigDecimal`: +In your code you can also use the characters `L`, `D`, and `F` (and their lowercase equivalents) to specify `Long`, `Double`, and `Float` fields: ```scala -var b = BigInt(1234567890) -var b = BigDecimal(123456.789) +val x = 1_000L // val x: Long = 1000 +val y = 2.2D // val y: Double = 2.2 +val z = 3.3F // val z: Float = 3.3 ``` -A great thing about `BigInt` and `BigDecimal` is that they support all the operators you’re used to using with numeric types: +When you need really large numbers, use the `BigInt` and `BigDecimal` types: ```scala -scala> var b = BigInt(1234567890) -b: scala.math.BigInt = 1234567890 - -scala> b + b -res0: scala.math.BigInt = 2469135780 - -scala> b * b -res1: scala.math.BigInt = 1524157875019052100 - -scala> b += 1 - -scala> println(b) -1234567891 -``` - -While you can think of `+`, `*`, and `+=` as being “operators,” because everything in Scala is an object, they’re really methods on their classes. - - -### String and Char - -Scala also has `String` and `Char` data types, which you can generally declare with the implicit form: - -```scala -val name = "Bill" -val c = 'a' +var a = BigInt(1_234_567_890_987_654_321L) +var b = BigDecimal(123_456.789) ``` -However, you can use the explicit form, if you prefer: +Scala also has `String` and `Char` data types: ```scala -val name: String = "Bill" -val c: Char = 'a' +val name = "Bill" // String +val c = 'a' // Char ``` -As shown, strings are enclosed in double-quotes — or triple-quotes, as you’re about to see — and a character is enclosed in single-quotes. - ## Two notes about strings -Scala strings are similar to Java strings, but they have at least two great additional features: +Scala strings are similar to Java strings, but they have two great additional features: - They support string interpolation -- You can create multiline strings +- It’s easy to create multiline strings ### String interpolation -In its most basic form, string interpolation provides a great way to use variables inside strings. For instance, given these three variables: +String interpolation provides a very readable way to use variables inside strings. For instance, given these three variables: ```scala val firstName = "John" @@ -249,32 +237,25 @@ val mi = 'C' val lastName = "Doe" ``` -string interpolation lets you combine those variables in a string like this: +String interpolation lets you combine those variables in a string like this: ```scala -val name = s"$firstName $mi $lastName" +println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" ``` -This lets you embed variables inside strings in a very readable way: +Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. -```scala -println(s"Name: $firstName $mi $lastName") -``` - -As shown, all you have to do is to precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. - -It’s important to know that string interpolation goes well beyond this basic use. For instance, you can also access class fields and use equations inside the interpolated string by enclosing those references inside curly braces. This example shows how to reference a class field (or method) inside an interpolated string: +To enclose class fields, class methods, or equations inside a string, enclose them in curly braces: ```scala class Person(var name: String) val p = Person("Margaret Hamilton") -println(s"Name: ${p.name}") -``` -This example shows how to use an equation: +// a class field or method +println(s"Name: ${p.name}") // "Name: Margaret Hamilton" -```scala -println(s"2 + 2 = ${2 + 2}") // prints '4' +// an equation +println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" ``` #### Other interpolators @@ -285,77 +266,57 @@ println(s"2 + 2 = ${2 + 2}") // prints '4' val name = "Fred" val age = 33 val weight = 200.5 + println(f"$name is $age years old, and weighs $weight%.1f pounds.") ``` + - - -Very importantly, because `s` and `f` are really just methods, other developers can write their own interpolators. For instance, Scala database libraries can create an `sql` interpolator that can have special features to support SQL: +Beyond that, because `s` and `f` are really just methods, developers can write their own interpolators. For instance, Scala database libraries can create an `sql` interpolator that can have special features to support SQL: ```scala val query = sql"select * from $table" ``` - ->For more details about interpolators, see the Scala Reference documentation. - - - ### Multiline strings -A second great feature of Scala strings is that you can create multiline strings by including the string inside three double-quotes: +Multiline strings are created by including the string inside three double-quotes: ```scala -val speech = """Four score and - seven years ago - our fathers ...""" +val quote = """The essence of Scala: + Fusion of functional and object-oriented + programming in a typed setting.""" ``` - -That’s very helpful for when you need to work with multiline strings. One drawback of this basic approach is that the lines after the first line are indented, as you can see in the REPL: +One drawback of this basic approach is that the lines after the first line are indented, and look like this: ```scala -scala> val speech = """Four score and - | seven years ago - | our fathers ...""" -speech: String = -Four score and - seven years ago - our fathers ... +"The essence of Scala: + Fusion of functional and object-oriented + programming in a typed setting." ``` A simple way to correct this problem is to put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: ```scala -val speech = """Four score and - |seven years ago - |our fathers ...""".stripMargin +val quote = """The essence of Scala: + |Fusion of functional and object-oriented + |programming in a typed setting.""".stripMargin ``` -The REPL shows that when you do this, all of the lines are left-justified: +Now all of the lines are left-justified inside the string: ```scala -scala> val speech = """Four score and - | |seven years ago - | |our fathers ...""".stripMargin -speech: String = -Four score and -seven years ago -our fathers ... +"The essence of Scala: +Fusion of functional and object-oriented +programming in a typed setting." ``` -Because this is what you generally want, this is a common way to create multiline strings. - ## Control structures -Scala has all of the basic programming language control structures you find in other languages, and also has powerful `for` expressions and `match` expressions: +Scala has the programming language control structures you find in other languages, and also has powerful `for` expressions and `match` expressions: -- if/else -- `for` loops +- `if`/`else` +- `for` loops and expressions - `match` expressions -- while, do/while -- try/catch +- `while` loops +- `try`/`catch` These structures are demonstrated in the following examples. ### if/else -Scala’s if/else control structure is similar to other languages. A multiline statement looks like this: +Scala’s if/else control structure is similar to other languages: ```scala if x < 0 then - "negative" + println("negative") else if x == 0 - "zero" + println("zero") else - "positive" + println("positive") ``` -and a single-line expression looks like this: - -```scala -if x < 0 then -x else x -``` - -Note that this really is an *expression* — not a *statement* — meaning that it returns a value, and can therefore be used as a ternary operator: +Note that this really is an *expression* — not a *statement* — meaning that it returns a value, so you can assign the result to a variable: ```scala val x = if (a < b) a else b ``` -In fact, as you’ll see throughout this Overview and in our Reference documentation, *all* Scala control structures can be used as expressions. +As you’ll see throughout this Overview and in our Reference documentation, *all* Scala control structures can be used as expressions. + +>An expression returns a result, while a statement does not. Statements are typically used for their side-effects, such as using `println` to print to the console. ### for loops and expressions @@ -412,88 +369,77 @@ In fact, as you’ll see throughout this Overview and in our Reference documenta - for/yield --> -In its most basic use, the `for` keyword can be used to create a `for` loop. For instance, given this list: +The `for` keyword can be used to create a `for` loop. This example shows how to print every element in a `List`: ```scala -// TODO introduce ranges first -val ints = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -val ints = List.range(1,10) -``` +val ints = List(1,2,3,4,5) -you can print each element in the list like this: - -```scala for (i <- ints) println(i) ``` -You can also use one or more *guards* — `if` expressions — inside a `for` loop. This example prints all of the numbers in `ints` that are greater than `5`: + -```scala -for i <- ints if i > 5 -do println(i) -``` +#### Guards -That statement can be written like this if you prefer: +You can also use one or more `if` expressions inside a `for` loop. These are referred to as *guards*. This example prints all of the numbers in `ints` that are greater than `2`: + + ```scala +val ints = List(1,2,3,4,5) + for i <- ints - if i > 5 + if i > 2 do println(i) ``` -This style is commonly used, because it supports the use of multiple generators and guards. For instance, this example prints all of the even numbers in `ints` that are greater than `2`: +You can use multiple generators and guards. This loop iterates over the numbers `1` to `3`, and for each number it also iterates over the characters `a` to `c`. However, it also has two guards, so the only time the print statement is called is when `i` has the value `2` and `j` is the character `b`: -```scala -// prints 4,6,8, and 10 on different lines -for - i <- ints - if i > 2 - if i % 2 == 0 -do - println(i) -``` - +```tut for i <- 1 to 3 j <- 'a' to 'c' if i == 2 if j == 'b' do - println(s"i = $i, j = $j") ---> + println(s"i = $i, j = $j") // prints: "i = 2, j = b" +``` -Simple Scala `for` loops look like this: +We encourage you to make changes to that code to be sure you understand how it works. -```scala -for (arg <- args) println(arg) -// "x to y" syntax -for (i <- 0 to 5) println(i) +#### Using `for` as an expression -// "x to y by" syntax -for (i <- 0 to 10 by 2) println(i) -``` +The `for` keyword has even more power: When you add the `yield` keyword to `for` loops, you create powerful `for` *expressions* which are used to calculate and yield results. -As shown in these examples, `for` loops are used for side effects, such as printing to the console. This use of the `for` keyword is just the beginning. When you add the `yield` keyword to `for` loops, you create powerful `for` *expressions* which are used to calculate and yield results. This REPL example shows how to use the for/yield combination to double each value in the sequence `1` to `5`: +A few examples demonstrate this. Given this list: ```scala -scala> val x = for i <- 1 to 5 yield i * 2 -val x: IndexedSeq[Int] = Vector(2, 4, 6, 8, 10) +val nums = List(1,2,3,4,5) ``` - +This code creates a new list where each element in the new list is twice the amount of the elements in the original list: + +```` +scala> val doubles = for i <- nums yield i * 2 +val doubles: List[Int] = List(2, 4, 6, 8, 10) +```` + +This example shows how to capitalize the first character in each string in the list: -Here’s another `for` expression that iterates over a list of strings: +```scala +val names = List("chris", "ed", "maurice") +val capNames = for name <- names yield name.capitalize +``` + +Finally, this `for` expression iterates over a list of strings, and returns the length of each string, but only if that length is greater than `4`: - + ```scala val fruits = List("apple", "banana", "lime", "orange") @@ -508,18 +454,8 @@ yield Because Scala code generally just makes sense, you can probably guess how this code works, even if you’ve never seen a for-expression or Scala list until now. - -`for` loops and expressions are covered in more detail in the Control Structures section. - - + +`for` loops and expressions are covered in more detail in the Control Structures sections of this Overview and in the Reference documentation. ### match expressions @@ -530,76 +466,68 @@ Scala has a `match` expression, which in its most basic use is like a Java `swit val i = 1 // later in the code ... +i match + case 1 => println("one") + case 2 => println("two") + case _ => println("other") +``` + +However, a `match` expression really is an expression, meaning that it returns a result based on the pattern match: + +```scala val result = i match - case 1 => "one" - case 2 => "two" - case _ => "not 1 or 2" + case 1 => "one" + case 2 => "two" + case _ => "other" ``` The `match` expression isn’t limited to just integers, it can be used with any data type, including booleans: ```scala val booleanAsString = bool match - case true => "true" - case false => "false" + case true => "true" + case false => "false" ``` -Here’s an example of `match` being used as the body of a method, and matching against many different types: +In fact, a `match` expression can be used to test a variable against multiple patterns. This example shows (a) how to use a `match` expression as the body of a method, and (b) how to match all the different types shown: + ```scala def getClassAsString(x: Any): String = x match - case s: String => s + " is a String" - case i: Int => "Int" - case f: Float => "Float" - case l: List[_] => "List" - case p: Person => "Person" - case _ => "Unknown" -``` - -Pattern matching is a significant feature of Scala, and you’ll see it used TODO (more here) - - - + case s: String => s"'$s' is a String" + case i: Int => "Int" + case d: Double => "Double" + case l: List[_] => "List" + case _ => "Unknown" +// examples +getClassAsString(1) // Int +getClassAsString("hello") // 'hello' is a String +getClassAsString(List(1,2,3)) // List +``` +Pattern matches can get as complicated as you need, and you’ll see more examples of it in the Control Structures sections of this Overview and in the Reference documentation. -### try/catch +### try/catch/finally -Scala’s try/catch control structure lets you catch exceptions. It’s similar to Java, but its syntax is consistent with `match` expressions: +Scala’s `try`/`catch` control structure lets you catch exceptions. It’s similar to Java, but its syntax is consistent with `match` expressions: - + ```scala try - writeToFile(text) + writeToFile(text) catch - case fnfe: FileNotFoundException => println(fnfe) - case ioe: IOException => println(ioe) + case fnfe: FileNotFoundException => println(fnfe) + case ioe: IOException => println(ioe) ``` ### while loops -Scala also has a `while` loop. It’s one-line syntax looks like this: + + +Scala also has a `while` loop construct. It’s one-line syntax looks like this: ```scala while x >= 0 do x = f(x) @@ -609,39 +537,32 @@ And it’s multiline syntax looks like this: ```scala var x = 1 + +// parentheses while (x < 3) - println(x) - x += 1 -``` + println(x) + x += 1 - - - - + println(x) + x += 1 +``` ### Create your own control structures! -- whilst -- doubleIfCOnditions - doubleif(age > 18)(numAccidents == 0) { println("Discount!") } - // two 'if' condition tests - def doubleif(test1: => Boolean)(test2: => Boolean)(codeBlock: => Unit) { if (test1 && test2) { - codeBlock - } } +In Scala you can also create code that works just like a control structure. You can learn more about this in the Control Structures chapter in the Reference documentation. + ## Data Modeling -Scala supports both functional programming (FP) and object-oriented programming (OOP), as well as a fusion of the two paradigms. This section provides an overview of data modeling in OOP and FP. +Scala supports both functional programming (FP) and object-oriented programming (OOP), as well as a fusion of the two paradigms. This section provides a quick overview of data modeling in OOP and FP. ### OOP data modeling (traits and classes) @@ -656,49 +577,63 @@ When writing code in an OOP style, your two main tools will be *traits* and *cla - traits as mixins --> -Traits can be used like interfaces and abstract classes in other languages, and they can also be used as mixins. Traits let you break your code down into small, modular units. Traits are like interfaces in other languages, but they can also contain implemented methods. When you want to create concrete implementations of attributes and behaviors, classes and objects can extend traits. +Traits are like interfaces in other languages, but they can also contain implemented methods. They provide a great way for you to organize behaviors into small, modular units. When you want to create concrete implementations of attributes and behaviors, classes and objects can extend traits, mixing in as many traits as needed to achieve the desired behavior. -To demonstrate some things you can do with traits, here are three traits that define well-organized and modular behaviors for animals like dogs and cats: +Here are three traits that define well-organized and modular behaviors for animals like dogs and cats: ```scala trait Speaker: - def speak(): String // has no body, so it’s abstract + def speak(): String // has no body, so it’s abstract trait TailWagger: - def startTail(): Unit = println("tail is wagging") - def stopTail(): Unit = println("tail is stopped") + def startTail(): Unit = println("tail is wagging") + def stopTail(): Unit = println("tail is stopped") trait Runner: - def startRunning(): Unit = println("I’m running") - def stopRunning(): Unit = println("Stopped running") + def startRunning(): Unit = println("I’m running") + def stopRunning(): Unit = println("Stopped running") ``` -Once you have those traits, you can create a `Dog` class that extends all three of those traits while providing a behavior for the abstract `speak` method: +Given those traits, here’s a `Dog` class that extends all of those traits while providing a behavior for the abstract `speak` method: ```scala class Dog(name: String) extends Speaker with TailWagger with Runner: - def speak(): String = "Woof!" + def speak(): String = "Woof!" +``` + +Notice how the class extends the traits with the `extends` and `with` keywords. + +Similarly, here’s a `Cat` class that implements those same traits while also overriding two of the concrete methods it inherits: + +```scala +class Cat(name: String) extends Speaker with TailWagger with Runner: + def speak(): String = "Meow" + override def startRunning(): Unit = println("Yeah ... I don’t run") + override def stopRunning(): Unit = println("No need to stop") ``` -Similarly, here’s a `Cat` class that shows how to implement those same traits while also overriding two of the methods it inherits: +These examples show how those classes are used: ```scala -class Cat extends Speaker with TailWagger with Runner: - def speak(): String = "Meow" - override def startRunning(): Unit = println("Yeah ... I don’t run") - override def stopRunning(): Unit = println("No need to stop") +val d = Dog("Rover") +d.speak() // prints "Woof!" + +val c = Cat("Morris") +c.speak() // "Meow" +c.startRunning() // "Yeah ... I don’t run" +c.stopRunning() // "No need to stop" ``` -If that code makes sense — great, you’re comfortable with traits as interfaces. If not, don’t worry, they’re explained in more detail in the Data Modeling section of the Reference documentation. +If that code makes sense — great, you’re comfortable with traits as interfaces. If not, don’t worry, they’re explained in more detail in the Data Modeling sections of this Overview and the Reference documentation. - + #### Classes -Scala classes are used in OOP-style programming. Here’s an example of a Scala class that models a “person,” where the person’s first and last names can both be modified (mutated): +Scala *classes* are used in OOP-style programming. Here’s an example of a class that models a “person.” The first and last names can both be modified, so they’re declared as `var` parameters: ```scala class Person(var firstName: String, var lastName: String): - def printFullName() = println(s"$firstName $lastName") -``` + def printFullName() = println(s"$firstName $lastName") -This is how you use that class: - -```scala -// TODO: update val p = Person("Julia", "Kern") -println(p.firstName) +println(p.firstName) // "Julia" p.lastName = "Manes" -p.printFullName() -``` - - -Notice that the first and last names can be mutated because they’re declared as `var` fields. Also, there’s no need to create “get” and “set” methods to access the fields in the class. You’ll see more details about classes in the Data Modeling section. - -As a more complicated example, here’s a `Pizza` class that you’ll see later in the book: - -```scala -class Pizza ( - var crustSize: CrustSize, - var crustType: CrustType, - val toppings: ArrayBuffer[Topping] -) { - def addTopping(t: Topping): Unit = toppings += t - def removeTopping(t: Topping): Unit = toppings -= t - def removeAllToppings(): Unit = toppings.clear() -} +p.printFullName() // "Julia Manes" ``` -In that code, an `ArrayBuffer` is a mutable sequence, like Java’s `ArrayList`. The `CrustSize`, `CrustType`, and `Topping` classes aren’t shown, but you can probably understand how that code works without needing to see those classes. - -### FP data modeling (TODO) +### FP data modeling When writing code in an FP style, you’ll use these constructs: -- Traits - Enums to define ADTs - Case classes +- Traits #### Enums @@ -767,182 +678,119 @@ When writing code in an FP style, you’ll use these constructs: - make compatible with java by extending java.lang.Enum --> - +The `enum` construct is a great way to model algebraic data types (ADTs) in Scala 3. For instance, a pizza has three main attributes: + +- Crust size +- Crust type +- Toppings + +These are concisely modeled with enums: ```scala enum CrustSize: - case Small, Medium, Large + case Small, Medium, Large enum CrustType: - case Thin, Thick, Regular + case Thin, Thick, Regular enum Topping: - case Cheese, Pepperoni, Olives + case Cheese, Pepperoni, BlackOlives, GreenOlives, Onions ``` +Once you have an enum you can use it in all of the ways you normally use a trait, class, or object: ```scala -case class Pizza: - crustSize: CrustSize, - crustType: CrustType, - toppings: Seq[Topping] +import CrustSize._ +val currentCrustSize = Small -@main def pizzaDemo = - import CrustSize._ - import CrustType._ - import Topping._ - - // passing enums as method parameters - val smallThinCheesePizza = Pizza( - Small, Thin, Seq(Cheese) - ) +// enums in a `match` expression +currentCrustSize match + case Small => println("Small crust size") + case Medium => println("Medium crust size") + case Large => println("Large crust size") - val largeThickWorks = Pizza( - Large, Thick, Seq(Cheese, Pepperoni, Olives) - ) - - println(smallThinCheesePizza) - println(largeThickWorks) - - printCrustSize(Small) - - // using an enum as a method parameter and in a match expression - def printCrustSize(cs: CrustSize) = cs match - case Small => println("small") - case Medium => println("medium") - case Large => println("large") +// enums in an `if` statement +if currentCrustSize == Small then println("Small crust size") ``` - -##### Enums (WORKING) - -Enums can take parameters: +Enums can also take parameters and have user-defined members like fields and methods. Here’s a sneak-peek of those capabilities: ```scala -// named values -enum Color: - case Red, Green, Blue - -// parameterized -enum Color(val rgb: Int): - case Red extends Color(0xFF0000) - case Green extends Color(0x00FF00) - case Blue extends Color(0x0000FF) - case Mix(mix: Int) extends Color(mix) - -//TODO show usage -val red = Color.Red -Color.valueOf("Blue") // res0: Color = Blue -Color.values // Array(Red, Green, Blue) - -// user-defined members enum Planet(mass: Double, radius: Double): private final val G = 6.67300E-11 def surfaceGravity = G * mass / (radius * radius) - def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity case Mercury extends Planet(3.303e+23, 2.4397e6) case Venus extends Planet(4.869e+24, 6.0518e6) - case Earth extends Planet(5.976e+24, 6.37814e6) // more ... } ``` - - - - - - +Enums are covered in detail in the Data Modeling section of this Overview, and in the Reference documentation. #### Case classes -A *case class* is different than the base Scala class. Case classes provide support for functional programming, and they have all of the functionality of a regular class, and more. When the compiler sees the `case` keyword in front of a `class`, it generates code for you, with the following benefits: +A *case class* is an extension of the base Scala class. Case classes provide features that make them useful for functional programming. They have all of the functionality of a regular class, and more. When the compiler sees the `case` keyword in front of a `class`, it generates code for you, with these benefits: - Case class constructor parameters are public `val` fields by default, so accessor methods are generated for each parameter. - An `apply` method is created in the companion object of the class, so you don’t need to use the `new` keyword to create a new instance of the class. - An `unapply` method is generated, which lets you use case classes in more ways in `match` expressions. -- A `copy` method is generated in the class. You may not use this feature in Scala/OOP code, but it’s used all the time in Scala/FP. -- `equals` and `hashCode` methods are generated, which let you compare objects and easily use them as keys in maps. +- A `copy` method is generated in the class. This provides a way to clone an object while making updates to its values during the cloning process. +- `equals` and `hashCode` methods are generated. - A default `toString` method is generated, which is helpful for debugging. -// BASIC -case class Person(name: String, relation: String) -val christina = Person("Christina", "niece") -christina.name -christina.name = "Fred" // error - -// MORE -trait Person: - def name: String -case class Student(name: String, year: Int) extends Person -case class Teacher(name: String, specialty: String) extends Person - -def getPrintableString(p: Person): String = p match { - case Student(name, year) => - s"$name is a student in Year $year." - case Teacher(name, whatTheyTeach) => - s"$name teaches $whatTheyTeach." -} +This code demonstrates several case class features: + +```scala +// define a case class +case class Person( + name: String, + vocation: String +) -val s = Student("Al", 1) -val t = Teacher("Bob Donnan", "Mathematics") -getPrintableString(s) -getPrintableString(t) +// create an instance of the case class +val p = Person("Reginald Kenneth Dwight", "Singer") +// a good default toString method +p // Person = Person(Reginald Kenneth Dwight,Singer) -// `copy`: “update as you copy” -case class BaseballTeam(name: String, lastWorldSeriesWin: Int) -val cubs1908 = BaseballTeam("Chicago Cubs", 1908) -val cubs2016 = cubs1908.copy(lastWorldSeriesWin = 2016) +// can access its fields, but they are immutable +p.name // "Reginald Kenneth Dwight" +p.name = "Joe" // error: can’t reassign a val field -// `equals` and `hashCode` -case class Person(name: String, relation: String) -val christina = Person("Christina", "niece") -val hannah = Person("Hannah", "niece") -christina == hannah +// when you need to make a change, use the `copy` method +// to “update as you copy” +val p2 = p.copy(name = "Elton John") +p2 // Person = Person(Elton John,Singer) +``` - +See the Data Modeling sections of this Overview and the Reference documentation for many more details on case classes. ## Scala methods -Scala classes, case classes, and objects can all contain methods. This is what the Scala method syntax looks like: + + +Scala classes, case classes, traits, enums, and objects can all contain methods. The general method syntax looks like this: + +```scala +def methodName(param1: Type1, param2: Type2): ReturnType = + // the method body + // goes here +``` + +Here are a few examples of that syntax: ```scala def sum(a: Int, b: Int): Int = a + b def concatenate(s1: String, s2: String): String = s1 + s2 ``` -You don’t have to declare a method’s return type, so it’s perfectly legal to write those two methods like this, if you prefer: +You don’t have to declare a method’s return type, so you can write those methods like this, if you prefer: ```scala def sum(a: Int, b: Int) = a + b @@ -956,172 +804,510 @@ val x = sum(1, 2) val y = concatenate("foo", "bar") ``` -There are more things you can do with methods, such as providing default values for method parameters and using named parameters when calling methods, and those are shown in TODO +Here’s an example of a multiline method: - +```scala +def getStackTraceAsString(t: Throwable): String = + val sw = new StringWriter + t.printStackTrace(new PrintWriter(sw)) + sw.toString +``` +There are more things you can do with methods, such as providing default values for method parameters and using named parameters when calling methods. Those featurs are shown in the Data Modeling section of this Overview and in the Reference documentation. -## First-class functions (TODO) -- top-level functions -- functions in objects -- lambdas / function literals / anonymous functions -- HOFs -- HOFs in the standard library +## First-class functions +Scala has first-class support for functional programming, and included in that is first-class support for everything related to functions: +- Top-level functions +- Functions in objects +- Lambdas +- Higher-order functions (HOFs) + + -## Collections classes -If you’re coming to Scala from Java and you’re ready to really jump in and learn Scala, it’s possible to use the Java collections classes in Scala, and some people do so for several weeks or months while getting comfortable with Scala. But it’s highly recommended that you learn the basic Scala collections classes — `List`, `ListBuffer`, `Vector`, `ArrayBuffer`, `Map`, and `Set` — as soon as possible. A great benefit of the Scala collections classes is that they offer many powerful methods that you’ll want to start using as soon as possible to simplify your code. +### Top-level functions - +Functions don’t have to be in the body of a class, enum, or object. They can also exist on their own as a *top-level function*. For instance, when this code is saved in a file, the functions `add` and `double` would be called top-level functions because they exist outside the scope of a class, enum, or object: +```scala +package foo -### Populating lists +def add(a: Int, b: Int): Int = a + b +def double(a: Int): Int = 2 * a -There are times when it’s helpful to create sample lists that are populated with data, and Scala offers many ways to populate lists. Here are just a few: +@main def topLevelFunctions() = + val x = add(1, 2) + val y = double(x) + println(s"y = $y") +``` + + +### Functions in objects + +Functions can also be placed in objects. Here are a few functions in a “string utilities” object: ```scala -val nums = List.range(0, 10) -val nums = (1 to 10 by 2).toList -val letters = ('a' to 'f').toList -val letters = ('a' to 'f' by 2).toList +object StringUtils: + + // Left-trim a string: `" foo "` becomes `"foo "`. + def leftTrim(s: String) = s.replaceAll("^\\s+", "") + + // Right-trim a string: `" foo "` becomes `" foo"`. + def rightTrim(s: String) = s.replaceAll("\\s+$", "") + + def isNullOrEmpty(s: String): Boolean = + if (s==null || s.trim.equals("")) true else false + +end StringUtils ``` +Those functions can be called like this: -### Sequence methods +```scala +StringUtils.leftTrim(" hi ") // "hi " +``` -While there are many sequential collections classes you can use — `Array`, `ArrayBuffer`, `Vector`, `List`, and more — let’s look at some examples of what you can do with the `List` class. Given these two lists: +or this: ```scala -val nums = (1 to 10).toList -val names = List("joel", "ed", "chris", "maurice") +import StringUtils._ +leftTrim(" hi ") // "hi " ``` -This is the `foreach` method: + +### Lambdas + +Lambdas — also known as *anonymous functions* — are a big part of keeping your code concise but readable. These two examples are equivalent, and show how to multiply each number in a list by `2` by passing a lambda into the `map` method: ```scala -scala> names.foreach(println) -joel -ed -chris -maurice +val a = List(1,2,3).map(i => i * 2) // List(2,4,6) +val b = List(1,2,3).map(_ * 2) // List(2,4,6) ``` -Here’s the `filter` method, followed by `foreach`: +Those examples are also equivalent to that code, but they use a `double` method inside of `map` instead of a lambda: ```scala -scala> nums.filter(_ < 4).foreach(println) -1 -2 -3 +def double(i: Int): Int = i * 2 +val a = List(1,2,3).map(i => double(i)) +val b = List(1,2,3).map(double) ``` -Here are some examples of the `map` method: +>If you haven’t seen the `map` method before, it applies a given function to every element in a list, yielding a new list that contains the new values. + + +### Higher-order functions + +A “higher order function” (HOF) is a function that can take a function as an input parameter, or returns a function as a return value. HOFs are extremely common in Scala, such as being used throughout the standard libraries. These examples show how to pass methods and anonymous functions into the functional methods of Scala collections: ```scala -scala> val doubles = nums.map(_ * 2) -doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) +// a sample list +val nums = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -scala> val capNames = names.map(_.capitalize) -capNames: List[String] = List(Joel, Ed, Chris, Maurice) +// sample methods +def isEven(i: Int): Boolean = i % 2 == 0 +def double(i: Int): Int = i * 2 -scala> val lessThanFive = nums.map(_ < 5) -lessThanFive: List[Boolean] = List(true, true, true, true, false, false, false, false, false, false) +// pass in a method or function +val a = nums.filter(isEven) // List(2, 4, 6, 8, 10) +val b = nums.map(double) // List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) + +// pass in a lambda +val c = nums.filter(_ % 2 == 0) // List(2, 4, 6, 8, 10) +val d = nums.map(_ * 2) // List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) + +// methods can be chained as needed +val e = nums.filter(_ > 3) // List(40, 50, 60) + .filter(_ < 7) + .map(_ * 10) ``` -Even without any explanation you can see how `map` works: It applies an algorithm you supply to every element in the collection, returning a new, transformed value for each element. +In addition to HOFs used all throughout the standard library, you can easily create your own HOFs. This is shown in the Reference documentation. + + -If you’re ready to see one of the most powerful collections methods, here’s `foldLeft`: +## Extension methods + + +*Extension methods* let you add new methods to closed classes. For instance, if you want to add a `hello` method to the `String` class, just create an extension method: + + ```scala -scala> nums.foldLeft(0)(_ + _) -res0: Int = 55 +def (s: String) hello: String = s"Hello, ${s.capitalize}" -scala> nums.foldLeft(1)(_ * _) -res1: Int = 3628800 +"world".hello // "Hello, world" +"friend".hello // "Hello, friend" ``` -Once you know that the first parameter to `foldLeft` is a *seed* value, you can guess that the first example yields the *sum* of the numbers in `nums`, and the second example returns the *product* of all those numbers. +The comments in this code explain the extension method syntax: + +```` +def (s: String) hello: String = s"Hello, ${s.capitalize}" + ---------- ----- ------ ------------------------- + ^ ^ ^ ^ + add method method return method body + to String name type + class +```` + +This next example shows how to add a `makeInt` method to the `String` class. Here, `makeInt` takes a parameter named `radix`. The code doesn’t account for possible string-to-integer conversion errors, but skipping that detail, the examples show how it works: -There are many (many!) more methods available to Scala collections classes, and many of them will be demonstrated in the collections lessons that follow, but hopefully this gives you an idea of their power. + +```scala +def (s: String) makeInt(radix: Int): Int = Integer.parseInt(s, radix) +"1".makeInt(2) // Int = 1 +"10".makeInt(2) // Int = 2 +"100".makeInt(2) // Int = 4 +``` ->For more details, jump to [the Scala Book collections lessons]({{site.baseurl}}/overviews/scala-book/collections-101.html), or see [the Mutable and Immutable collections overview]({{site.baseurl}}/overviews/collections-2.13/overview.html) for more details and examples. +## Collections classes + +Scala has a rich set of collections classes, and those classes have a rich set of methods. Collections classes are available in both immutable and mutable forms. In alphabetical order, the basic collections classes you’ll use on a regular basis are: -## Tuples (TODO: update this section) +| Class | Mutable | Immutable | Description | +| ------------- | :-----: | :-------: | ----------- | +| `ArrayBuffer` | √ | | an indexed, mutable sequence | +| `List` | | √ | a linear (linked list), immutable sequence | +| `Map` | √ | √ | the base `Map` (key/value pairs) class | +| `Set` | √ | √ | the base `Set` class | +| `Vector` | | √ | an indexed, immutable sequence | -The Scala *tuple* is a class that lets you easily put a collection of different types in the same container. This is how you create a tuple that contains an `Int`, a `String`, and a `Boolean` value: +Scala also has a `Range` class which lets you create ordered sequences of integers that are equally spaced apart, such as “1, 2, 3,” and “5, 8, 11, 14.” Ranges are often used in `for` loops, and to create other sequences: ```scala -val t = (11, "eleven", true) +// a range in a for-loop +for (i <- 1 to 3) print(i) // 123 + +// use ranges to create other collections +(1 to 5).toList // List(1, 2, 3, 4, 5) +(1 to 10 by 2).toVector // Vector(1, 3, 5, 7, 9) +(1 to 10).toSet // Set[Int] = HashSet(5, 10, 1, 6, 9, 2, 7, 3, 8, 4) + +('a' to 'f').toList // List[Char] = List(a, b, c, d, e, f) +('a' to 'f' by 2).toList // List[Char] = List(a, c, e) + +List.range(1, 5) // List(1, 2, 3, 4) +List.range(1, 5, 2) // List(1, 3) ``` -You can see the type in the REPL: + + -```` -scala> val t = (11, "eleven", true) -TODO: UPDATE -```` +### Immutable collections classes -You can access the tuple values by number: +Some of the most-commonly used *immutable* collections classes are: + +| Class | Description | +| ------------- | ------------- | +| `List` | A finite immutable linked-list. | +| `LazyList` | Like a `List` except that its elements are computed lazily. Because of this, a lazy list can be infinitely long. | +| `Vector` | A sequential collection type that provides good performance for all its operations. | +| `Map` | Like maps in Java, dictionaries in Python, or a `HashMap` in Rust, `Map` is an `Iterable` that contains pairs of keys and values. | +| `Set` | An `Iterable` sequence that contains no duplicate elements. | +| `Stack` | A last-in-first-out sequence. | +| `Queue` | A first-in-first-out sequence. | +In addition to the previous `Range` examples, here are a few more ways to create immutable collections: + + ```scala -t._1 -t._2 -t._3 +val a = List(1,2,3) +val b = Vector("hello", "world") + +// create a List with a Range +val c = (1 to 5).toList + +val m = Map( + 1 -> "one", + 2 -> "two" +) ``` -TODO: other methods: -t.head -t.tail -t.drop(1) -t.take(1) -t.size -t.map ... +### Mutable collections classes + +Mutable Scala collections classes are located in the *scala.collection.mutable* package. These are some of the most commonly-used: + +| Class | Description | +| ------------- | ------------- | +| `ArrayBuffer` | An indexed mutable buffer backed by an array. | +| `ListBuffer` | A mutable buffer backed by a linked list. Use this class if you’ll use it like a `List`, or if you’ll convert it to a `List` once it’s built up. | +| `Map` | A mutable `Map`, contains pairs of keys and values. | +| `Set` | A mutable `Set`, a sequence that contains no duplicate elements. | +| `Stack` | A mutable, last-in-first-out sequence. | +| `Queue` | A mutable, first-in-first-out sequence. | + +These examples show a few ways to use an `ArrayBuffer`: + +```scala +import scala.collection.mutable.ArrayBuffer + +val a = ArrayBuffer(1,2,3) // ArrayBuffer(1, 2, 3) + +val b = ArrayBuffer[String]() // ArrayBuffer[String] = ArrayBuffer() +b += "Hello" // ArrayBuffer(Hello) +b ++= List("world", "it’s", "me") // ArrayBuffer(Hello, world, it’s, me) +``` + +In addition to those classes, Scala has an `Array` class, which is a special kind of collection. An `Array` corresponds one-to-one to a Java `array`, so its elements can be mutated, but its size can’t be changed. In addition to behaving like a Java `array`, (a) it can hold generic types, and (b) it supports all of the usual sequence methods (which you’re about to see). + + + +### Sequence methods + + + +A great benefit of the Scala collections classes is that they offer dozens of powerful functional methods you can use to simplify your code. These are just a few of the common methods available to sequences: + +| Method | Description | +| ------------- | ------------- | +| `map` | Creates a new collection by applying a function to all the elements of the collection. | +| `filter` | Returns all elements from the collection for which a given predicate is true. | +| `foreach` | Applies a function to all elements of the collection to produce a side effect. | +| `take`, `takeWhile` | Returns elements from the beginning of the collection. | +| `drop`, `dropWhile` | Returns all elements in the collection except the first elements that are specified. | +| `flatten` | Converts a sequence of sequences (such as a list of lists) to a single sequence (single list). | +| `foldLeft` | Applies an operation to successive elements, going from left to right, using an initial seed value | +| `reduce` | The same as `foldLeft`, but without an initial seed value. | + +There are dozens of additional methods, which you’ll see in the Collections section of this Overview, and in the Reference documentation. + +>A key to know about all of these methods is that they are *functional*: they don’t modify the existing sequence; they return a new collection by applying the method to the original sequence. + +These examples demonstrate some of the commonly-used sequence methods: + +```scala +// a sample list +val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) + +a.drop(2) // List(30, 40, 10) +a.dropRight(2) // List(10, 20, 30) +a.dropWhile(_ < 25) // List(30, 40, 10) +a.filter(_ < 25) // List(10, 20, 10) +a.find(_ > 20) // Some(30) +a.head // 10 +a.headOption // Some(10) +a.last // 10 +a.lastOption // Some(10) +a.slice(2,4) // List(30, 40) +a.tail // List(20, 30, 40, 10) +a.take(3) // List(10, 20, 30) +a.takeRight(2) // List(40, 10) +a.takeWhile(_ < 30) // List(10, 20) + +val a = List(List(1,2), List(3,4)) +a.flatten // List(1, 2, 3, 4) + +val nums = List("one", "two") +nums.map(_.toUpperCase) // List("ONE", "TWO") +nums.flatMap(_.toUpperCase) // List('O', 'N', 'E', 'T', 'W', 'O') +``` + +These examples show how the “fold” and “reduce” methods are used to sum up every element in a sequence: + +```scala +val firstTen = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + +firstTen.fold(100)(_ + _) // 155 +firstTen.foldLeft(100)(_ + _) // 155 +firstTen.reduce(_ + _) // 55 +firstTen.reduceLeft(_ + _) // 55 +``` + +There are many (many!) more methods available to Scala collections classes, and they’re demonstrated in the Collections sections of this Overview and in the Reference documentation. + + +### Tuples + + + +The Scala *tuple* is a type that lets you easily put a collection of different types in the same container. For example, given this `Person` case class: + +```scala +case class Person(name: String) +``` -Or assign the tuple fields to variables: +This is how you create a tuple that contains an `Int`, a `String`, and a custom `Person` value: ```scala -val (num, string, good) = (11, "eleven", true) +val t = (11, "eleven", Person("Eleven")) ``` +You can access the tuple values by number: + +```scala +t._1 // 11 +t._2 // "eleven" +t._3 // Person("Eleven") +``` + +You can also assign the tuple fields to variables, as shown in the REPL: + ```` -scala> val (num, string, person) = (11, "eleven", true) -TODO: UPDATE +scala> val (num, string, name) = (11, "eleven", Person("Eleven")) +val num: Int = 11 +val string: String = eleven +val good: Boolean = Person(Eleven) ```` -Tuples are nice for those times when you need to put a little “bag” of things together for a little while. +Tuples are nice for those times when you want to put a collection of heterogenous types in a little collection-like structure. + + + + +## Contextual Abstractions + + +Implicits in Scala 2 were a main distinguishing feature. Following Haskell, Scala was the second popular language to have some form of implicits. Other languages have since followed suit. + +Implicits are a fundamental way to abstract over context. They represent a unified paradigm with a great variety of use cases, among them: + +- Implementing type classes +- Establishing context +- Dependency injection +- Expressing capabilities +- Computing new types and proving relationships between them + +Even though different languages use widely different terminology, they’re all variants of the core idea of *term inference*. Given a type, the compiler synthesizes a “canonical” term that has that type. Scala embodies the idea in a purer form than most other languages: An implicit parameter directly leads to an inferred argument term that could also be written down explicitly. + +In Scala 3 the syntax for these constructs has been changed significantly to make their usage more clear. Implicits are defined with the keyword `given`, and in later code they are referenced with the keyword `using`. + + +### Term inference + +Here’s a quick example of how to use term inference in Scala 3. Imagine that you have a situation where a value is passed into a series of function calls, such as using an `ExecutionContext` when you’re working with parallel programming: + +```scala +doX(a, executionContext) +doY(b, c, executionContext) +doZ(d, executionContext) +``` + +Because this type of code is repetitive and makes the code harder to read, you’d prefer to write it like this instead: + +```scala +doX(a) +doY(b, c) +doZ(d) +``` + +The functions still use the `executionContext` variable, but they don’t require you to explicitly state that. As shown, the shorter code is more easy to read. + +When you want a solution like this, Scala 3’s term inference solution is what you’re looking for. The solution involves multiple steps: + +1. Define the code you want the compiler to discover using the Scala 3 `given` keyword. +1. When declaring the “implicit” parameter your function will use, put it in a separate parameter group and define it with the `using` keyword. +1. Make sure your `given` value is in the current context when your function is called. + +The following example demonstrates these steps with the use of an `Adder` trait and two `given` values that implement the `Adder` trait’s `add` method. + + +### Step 1: Define your “given instances” + +In the first step you’ll typically create a parameterized trait: + +```scala +trait Adder[T]: + def add(a: T, b: T): T +``` + +Then you’ll implement the trait using one or more `given` instances, which you define like this: + +```scala +given intAdder as Adder[Int]: + def add(a: Int, b: Int): Int = a + b + +given stringAdder as Adder[String]: + def add(a: String, b: String): String = "" + (a.toInt + b.toInt) +``` +In this example, `intAdder` is an instance of `Adder[Int]`, and defines an `add` method that works with `Int` values. Similarly, `stringAdder` is an instance of `Adder[String]` and provides an `add` method that takes two strings, converts them to `Int` values, adds them together, and returns the sum as a `String`. (To keep things simple the code doesn’t account for potential string-to-integer errors.) + +If you’re familiar with creating implicits in Scala 2, this new approach is similar to that process. The idea is the same, it’s just that the syntax has changed. + + +### Step 2: Declare the parameter your function will use with the `using` keyword + +Next, define your functions that use the `Adder` instances. When doing this, specify the `Adder` parameter with the `using` keyword. Put the parameter in a separate parameter group, as shown here: + +```scala +def genericAdder[A](x: A, y: A)(using adder: Adder[A]): A = + adder.add(x, y) +``` + +The keys here are that the `adder` parameter is defined with the `using` keyword in that separate parameter group: + +```scala +def genericAdder[A](x: A, y: A)(using adder: Adder[A]): A = + ----------------------- +``` + +Also notice that `genericAdder` declares the generic type `A`. This function doesn’t know if it will be used to add two integers or two strings — it just calls the `add` method of the `adder` parameter. + +>In Scala 2, parameters like this were declared using the `implicit` keyword, but now, as the entire programming industry has various implementations of this concept, this parameter is known in Scala 3 as a *context parameter*. + + +### Step 3: Make sure everything is in the current context + +Finally, assuming that `intAdder`, `stringAdder`, and `genericAdder` are all in scope, your code can call the `genericAdder` function with `Int` and `String` values, without having to pass instances of `intAdder` and `stringAdder` into `genericAdder`: + +```scala +println(genericAdder(1, 1)) // 2 +println(genericAdder("2", "2")) // 4 +``` + +The Scala compiler is smart enough to know that `intAdder` should be used in the first instance, and `stringAdder` should be used in the second instance. This is because the first example uses two `Int` parameters and the second example uses two `String` values. + + + +## Even more! + +Scala has even more features that weren’t covered in this whirlwind tour. See the remainder of this Overview and the Reference documentation for many more details. + + + + + From 8a1d6443a2708ab7d1e1149bbd3eb7c61bc0d0b8 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 29 Sep 2020 15:10:57 -0600 Subject: [PATCH 0167/2265] Worked on the first half of Jonathan's comments. --- _overviews/overview/a-taste-of-scala.md | 90 ++++++++++++------------- 1 file changed, 42 insertions(+), 48 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index cb83bb5b36..c0eba4bdb3 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -10,6 +10,10 @@ description: This page provides a high-level overview of the main features of Sc - show a method with default parameters - show package "exports" - cover Option/Try/Either (functional error handling) + - do a search/replace on the word “field,” make sure it’s only used in classes, + objects, traits + - don’t use "field," do use "variables," "binders," or maybe something + like "assignment" --> This “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. @@ -22,7 +26,7 @@ This “Taste of Scala” section provides a whirlwind tour of Scala’s main fe -A “Hello, world” example in Scala goes as follows. First, Put this code in a file named *Hello.scala*: +A “Hello, world” example in Scala goes as follows. First, put this code in a file named *Hello.scala*: ```scala @main def hello = println("Hello, world") @@ -81,7 +85,7 @@ scala> 2 + 2 val res1: Int = 4 ```` -As shown in the output, if you don’t assign a variable to the result of an expression, the REPL creates variables named `res0`, `res1`, etc., for you. You can use these variable names in future expressions: +As shown in the output, if you don’t assign a variable to the result of an expression, the REPL creates variables named `res0`, `res1`, etc., for you. You can use these variable names in subsequent expressions: ```` scala> val x = res0 * 10 @@ -121,22 +125,20 @@ var c = 1 // mutable var d = "world" ``` -In an application, a `val` field can’t be reassigned. You’ll generate a compiler error if you try to reassign one: +In an application, a `val` can’t be reassigned. You’ll generate a compiler error if you try to reassign one: ```scala val msg = "Hello, world" msg = "Hello" // "reassignment to val" error; this won’t compile ``` -Conversely, a `var` field can be reassigned: +Conversely, a `var` can be reassigned: ```scala var msg = "Hello, world" msg = "Hello" // this compiles because a var can be reassigned ``` ->Inside the REPL playground area you can reassign a `val` field, but this is just for convenience. - ## Declaring variable types @@ -245,16 +247,9 @@ println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. -To enclose class fields, class methods, or equations inside a string, enclose them in curly braces: +For expressions more complex than a single identifier, enclose the expression in curly braces: ```scala -class Person(var name: String) -val p = Person("Margaret Hamilton") - -// a class field or method -println(s"Name: ${p.name}") // "Name: Margaret Hamilton" - -// an equation println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" ``` @@ -417,19 +412,21 @@ We encourage you to make changes to that code to be sure you understand how it w The `for` keyword has even more power: When you add the `yield` keyword to `for` loops, you create powerful `for` *expressions* which are used to calculate and yield results. -A few examples demonstrate this. Given this list: - -```scala -val nums = List(1,2,3,4,5) -``` - -This code creates a new list where each element in the new list is twice the amount of the elements in the original list: +A few examples demonstrate this. Using the same `ints` list as the previous example, this code creates a new list, where the value of each element in the new list is twice the value of the elements in the original list: ```` -scala> val doubles = for i <- nums yield i * 2 +scala> val doubles = for (i <- ints) yield i * 2 val doubles: List[Int] = List(2, 4, 6, 8, 10) ```` +Note that Scala’s syntax is flexible, and that `for` expression can be written in several different ways to make your code more readable: + +```scala +val doubles = for i <- ints yield i * 2 +val doubles = for (i <- ints) yield i * 2 +val doubles = for (i <- ints) yield (i * 2) +``` + This example shows how to capitalize the first character in each string in the list: ```scala @@ -506,7 +503,7 @@ getClassAsString("hello") // 'hello' is a String getClassAsString(List(1,2,3)) // List ``` -Pattern matches can get as complicated as you need, and you’ll see more examples of it in the Control Structures sections of this Overview and in the Reference documentation. +There’s much more to pattern matching in Scala. Patterns can be nested, results of patterns can be bound, and pattern matching can even be user-defined. You can find more pattern matching examples in the Control Structures section of this Overview, and in the Reference documentation. ### try/catch/finally @@ -553,10 +550,7 @@ do ### Create your own control structures! -In Scala you can also create code that works just like a control structure. You can learn more about this in the Control Structures chapter in the Reference documentation. - +Thanks to features like by-name parameters, infix notation, fluent interfaces, optional parentheses, extension methods, and higher-order functions, you can also create code that works just like a control structure. You’ll learn more about this in the Control Structures chapter in the Reference documentation. @@ -645,7 +639,7 @@ If that code makes sense — great, you’re comfortable with traits as interfac - Traits or abstract classes are always open, so open is redundant for them. --> -Scala *classes* are used in OOP-style programming. Here’s an example of a class that models a “person.” The first and last names can both be modified, so they’re declared as `var` parameters: +Scala *classes* are used in OOP-style programming. Here’s an example of a class that models a “person.” In OOP, fields are typically mutable, so `firstName` and `lastName` are both declared as `var` parameters: ```scala class Person(var firstName: String, var lastName: String): @@ -731,6 +725,11 @@ Enums are covered in detail in the Data Modeling section of this Overview, and i #### Case classes + + A *case class* is an extension of the base Scala class. Case classes provide features that make them useful for functional programming. They have all of the functionality of a regular class, and more. When the compiler sees the `case` keyword in front of a `class`, it generates code for you, with these benefits: - Case class constructor parameters are public `val` fields by default, so accessor methods are generated for each parameter. @@ -939,32 +938,27 @@ In addition to HOFs used all throughout the standard library, you can easily cre ## Extension methods -*Extension methods* let you add new methods to closed classes. For instance, if you want to add a `hello` method to the `String` class, just create an extension method: +*Extension methods* let you add new methods to closed classes. For instance, if you want to add two methods named `hello` and `aloha` to the `String` class, just declare them as extension methods: ```scala -def (s: String) hello: String = s"Hello, ${s.capitalize}" +extension (s: String): + def hello: String = s"Hello, ${s.capitalize}" + def aloha: String = s"Aloha, ${s.capitalize}" -"world".hello // "Hello, world" -"friend".hello // "Hello, friend" +"world".hello // "Hello, World" +"friend".aloha // "Aloha, Friend" ``` -The comments in this code explain the extension method syntax: - -```` -def (s: String) hello: String = s"Hello, ${s.capitalize}" - ---------- ----- ------ ------------------------- - ^ ^ ^ ^ - add method method return method body - to String name type - class -```` +The `extension` keyword declares that you’re about to define one or more extension methods. As shown, the `s` parameter can then be used in your methods. This next example shows how to add a `makeInt` method to the `String` class. Here, `makeInt` takes a parameter named `radix`. The code doesn’t account for possible string-to-integer conversion errors, but skipping that detail, the examples show how it works: ```scala -def (s: String) makeInt(radix: Int): Int = Integer.parseInt(s, radix) +extension (s: String) + def makeInt(radix: Int): Int = Integer.parseInt(s, radix) + "1".makeInt(2) // Int = 1 "10".makeInt(2) // Int = 2 "100".makeInt(2) // Int = 4 @@ -978,11 +972,11 @@ Scala has a rich set of collections classes, and those classes have a rich set o | Class | Mutable | Immutable | Description | | ------------- | :-----: | :-------: | ----------- | -| `ArrayBuffer` | √ | | an indexed, mutable sequence | -| `List` | | √ | a linear (linked list), immutable sequence | -| `Map` | √ | √ | the base `Map` (key/value pairs) class | -| `Set` | √ | √ | the base `Set` class | -| `Vector` | | √ | an indexed, immutable sequence | +| `ArrayBuffer` | ✓ | | an indexed, mutable sequence | +| `List` | | ✓ | a linear (linked list), immutable sequence | +| `Map` | ✓ | ✓ | the base `Map` (key/value pairs) class | +| `Set` | ✓ | ✓ | the base `Set` class | +| `Vector` | | ✓ | an indexed, immutable sequence | Scala also has a `Range` class which lets you create ordered sequences of integers that are equally spaced apart, such as “1, 2, 3,” and “5, 8, 11, 14.” Ranges are often used in `for` loops, and to create other sequences: From e4f23902570b378b73ce251e2f3bd0f4a1cf0637 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 29 Sep 2020 15:25:00 -0600 Subject: [PATCH 0168/2265] Update _overviews/overview/a-taste-of-scala.md Co-authored-by: Julien Richard-Foy --- _overviews/overview/a-taste-of-scala.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index c0eba4bdb3..f45d175d67 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -247,11 +247,13 @@ println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. -For expressions more complex than a single identifier, enclose the expression in curly braces: +To enclose expressions inside a string, enclose them in curly braces: -```scala +~~~ scala println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" -``` +val x = -1 +println(s"x.abs = ${x.abs}") // prints "x.abs = 1" +~~~ #### Other interpolators @@ -1320,4 +1322,3 @@ Scala has even more features that weren’t covered in this whirlwind tour. See - From 97e96f85c60f22877676b8a956c841d9a74c0242 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 29 Sep 2020 16:45:35 -0600 Subject: [PATCH 0169/2265] Update _overviews/overview/a-taste-of-scala.md Co-authored-by: Julien Richard-Foy --- _overviews/overview/a-taste-of-scala.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index f45d175d67..d9339224cd 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -349,7 +349,7 @@ else Note that this really is an *expression* — not a *statement* — meaning that it returns a value, so you can assign the result to a variable: ```scala -val x = if (a < b) a else b +val x = if a < b then a else b ``` As you’ll see throughout this Overview and in our Reference documentation, *all* Scala control structures can be used as expressions. @@ -1321,4 +1321,3 @@ Scala has even more features that weren’t covered in this whirlwind tour. See - From 006dac9f00d4390731ea0c9fd80547c0a7a935ce Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 29 Sep 2020 16:46:07 -0600 Subject: [PATCH 0170/2265] Update _overviews/overview/a-taste-of-scala.md Co-authored-by: Julien Richard-Foy --- _overviews/overview/a-taste-of-scala.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index d9339224cd..8b0b4b5b78 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -371,7 +371,7 @@ The `for` keyword can be used to create a `for` loop. This example shows how to ```scala val ints = List(1,2,3,4,5) -for (i <- ints) println(i) +for i <- ints do println(i) ``` -This “Taste of Scala” section provides a whirlwind tour of Scala’s main features. After the initial tour in this section, the rest of the Overview will provide a few more details on the these features, and the Reference documentation will provide *many* more details. ->Throughout this Overview you’ll also be able to test many of the examples directly on this page. In addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), or in the Scala REPL, which is demonstrated shortly. +This “Taste of Scala” section provides a whirlwind tour of the main features of the Scala 3 programming language. After the initial tour in this section, the rest of the Overview provides a few more details on these features, and the Reference documentation provides _many_ more details. +>Throughout this Overview you’ll be able to test many of the examples directly on this page. In addition to that, you can also test anything you’d like on [ScalaFiddle.io](https://scalafiddle.io), [Scastie](https://scastie.scala-lang.org), or in the Scala REPL, which is demonstrated shortly. -## Hello, world - +## Hello, world -A “Hello, world” example in Scala goes as follows. First, put this code in a file named *Hello.scala*: +A Scala “Hello, world” example goes as follows. First, put this code in a file named _Hello.scala_: ```scala @main def hello = println("Hello, world") ``` +In this code, `hello` is a method — defined with `def`, and declared to be a “main” method with the `@main` annotation — that invokes the `println` method to write the `"Hello, world"` string to standard output (STDOUT). + Next, compile the code with `scalac`: ```sh @@ -40,7 +37,6 @@ $ scalac Hello.scala If you’re coming to Scala from Java, `scalac` is just like `javac`, so that command creates several files: - ```sh $ ls -1 Hello$package$.class @@ -51,7 +47,7 @@ hello.class hello.tasty ``` -Like Java, the *.class* files are bytecode files, and they’re ready to run in the JVM. Now you can run the main `hello` method with the `scala` command: +Like Java, the _.class_ files are bytecode files, and they’re ready to run in the JVM. Now you can run the main `hello` method with the `scala` command: ```sh $ scala hello @@ -64,7 +60,7 @@ Assuming that worked, congratulations, you just compiled and ran your first Scal ## The Scala REPL -The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code. You start a REPL session by running the `scala` command at your operating system command line. When you do so, you’ll see a “welcome” prompt like this: +The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code. You start a REPL session by running the `scala` command at your operating system command line, where you’ll see a “welcome” prompt like this: ```scala @@ -94,6 +90,7 @@ val x: Int = 20 Notice that the REPL output also shows the result of your expressions. + You can run all sorts of experiments in the REPL. This example shows how to create and then call a `sum` function: ```` @@ -112,16 +109,18 @@ As mentioned earlier, if you prefer a browser-based playground environment, you When you create a new variable in Scala, you declare whether the variable is immutable or mutable: -- `val` creates an *immutable* variable — like `final` in Java. You should always create a variable with `val`, unless there’s a reason you need a mutable variable. -- `var` creates a *mutable* variable, and should only be used when a variable’s contents will change over time. +- `val` creates an _immutable_ variable — like `final` in Java. You should always create a variable with `val`, unless there’s a reason you need a mutable variable. +- `var` creates a _mutable_ variable, and should only be used when a variable’s contents will change over time. These examples show how to create `val` and `var` variables: ```scala -val a = 0 // immutable +// immutable +val a = 0 val b = "Hello" -var c = 1 // mutable +// mutable +var c = 1 var d = "world" ``` @@ -143,14 +142,14 @@ msg = "Hello" // this compiles because a var can be reassigned ## Declaring variable types -You can declare variables by explicitly declaring their type, or by letting the compiler infer the type: +When you create a variable you can (a) explicitly declare its type, or (b) let the compiler infer the type: ```scala val x: Int = 1 // explicit val x = 1 // implicit; the compiler infers the type ``` -The second form is known as *type inference*, and it’s a great way to help keep this type of code concise. The Scala compiler can usually infer the data type for you, as shown in the output of these examples: +The second form is known as _type inference_, and it’s a great way to help keep this type of code concise. The Scala compiler can usually infer the data type for you, as shown in the output of these examples: ```scala scala> val x = 1 @@ -168,13 +167,13 @@ You can always explicitly declare a variable’s type if you prefer, but in simp ```scala val x: Int = 1 val s: String = "a string" -val p: Person = new Person("Richard") +val p: Person = Person("Richard") ``` Notice that with this approach, the code feels more verbose than necessary. - + ## Built-in data types Scala comes with the standard numeric data types you’d expect, and they’re all full-blown instances of classes. In Scala, everything is an object. @@ -183,7 +182,7 @@ These examples show how to declare variables of the numeric types: ```scala val b: Byte = 1 -val x: Int = 1 +val i: Int = 1 val l: Long = 1 val s: Short = 1 val d: Double = 2.0 @@ -197,7 +196,7 @@ val i = 123 // defaults to Int val j = 1.0 // defaults to Double ``` -In your code you can also use the characters `L`, `D`, and `F` (and their lowercase equivalents) to specify `Long`, `Double`, and `Float` fields: +In your code you can also append the characters `L`, `D`, and `F` (and their lowercase equivalents) to numbers to specify that they are `Long`, `Double`, or `Float` values: ```scala val x = 1_000L // val x: Long = 1000 @@ -212,6 +211,8 @@ var a = BigInt(1_234_567_890_987_654_321L) var b = BigDecimal(123_456.789) ``` +Where `Double` and `Float` are approximate decimal numbers, `BigDecimal` is used for precise arithmetic. + Scala also has `String` and `Char` data types: ```scala @@ -239,7 +240,7 @@ val mi = 'C' val lastName = "Doe" ``` -String interpolation lets you combine those variables in a string like this: +You can combine those variables in a string like this: ```scala println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" @@ -247,8 +248,9 @@ println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. -To enclose expressions inside a string, enclose them in curly braces: +To enclose expressions inside a string, put them in curly braces: + ~~~ scala println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" val x = -1 @@ -257,22 +259,7 @@ println(s"x.abs = ${x.abs}") // prints "x.abs = 1" #### Other interpolators -“Why use the `s` in front of the string,” you may ask. The answer is that the `s` that precedes the strings in these examples is just one possible interpolator. You can also use the letter `f` in front of a string to use `printf`-style string formatting: - -```scala -val name = "Fred" -val age = 33 -val weight = 200.5 - -println(f"$name is $age years old, and weighs $weight%.1f pounds.") -``` - - -Beyond that, because `s` and `f` are really just methods, developers can write their own interpolators. For instance, Scala database libraries can create an `sql` interpolator that can have special features to support SQL: - -```scala -val query = sql"select * from $table" -``` +The `s` that you place before the string is just one possible interpolator. If you use an `f` instead of an `s`, you can use `printf`-style formatting in the string. Furthermore, because `s` and `f` are really just methods, you can write your own interpolators, such as creating a `sql` interpolator for use in a database library. For more details, see the Strings section in this Overview and in the Reference documentation. ### Multiline strings @@ -280,47 +267,39 @@ val query = sql"select * from $table" Multiline strings are created by including the string inside three double-quotes: ```scala -val quote = """The essence of Scala: - Fusion of functional and object-oriented +val quote = """The essence of Scala: + Fusion of functional and object-oriented programming in a typed setting.""" ``` One drawback of this basic approach is that the lines after the first line are indented, and look like this: ```scala -"The essence of Scala: +"The essence of Scala: Fusion of functional and object-oriented programming in a typed setting." ``` -A simple way to correct this problem is to put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: +When spacing is important, put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: ```scala -val quote = """The essence of Scala: - |Fusion of functional and object-oriented +val quote = """The essence of Scala: + |Fusion of functional and object-oriented |programming in a typed setting.""".stripMargin ``` Now all of the lines are left-justified inside the string: ```scala -"The essence of Scala: -Fusion of functional and object-oriented +"The essence of Scala: +Fusion of functional and object-oriented programming in a typed setting." ``` + ## Control structures - Scala has the programming language control structures you find in other languages, and also has powerful `for` expressions and `match` expressions: @@ -333,9 +312,9 @@ Scala has the programming language control structures you find in other language These structures are demonstrated in the following examples. -### if/else +### `if`/`else` -Scala’s if/else control structure is similar to other languages: +Scala’s `if`/`else` control structure is similar to other languages: ```scala if x < 0 then @@ -346,27 +325,20 @@ else println("positive") ``` -Note that this really is an *expression* — not a *statement* — meaning that it returns a value, so you can assign the result to a variable: +Note that this really is an _expression_ — not a _statement_. This means that it returns a value, so you can assign the result to a variable: ```scala val x = if a < b then a else b ``` -As you’ll see throughout this Overview and in our Reference documentation, *all* Scala control structures can be used as expressions. +As you’ll see throughout this Overview and in our Reference documentation, _all_ Scala control structures can be used as expressions. >An expression returns a result, while a statement does not. Statements are typically used for their side-effects, such as using `println` to print to the console. -### for loops and expressions - +### `for` loops and expressions -The `for` keyword can be used to create a `for` loop. This example shows how to print every element in a `List`: +The `for` keyword is used to create a `for` loop. This example shows how to print every element in a `List`: ```scala val ints = List(1,2,3,4,5) @@ -374,21 +346,20 @@ val ints = List(1,2,3,4,5) for i <- ints do println(i) ``` - +The code `i <- ints` is referred to as a _generator_, and if you leave the parentheses off of the generator, the `do` keyword is required before the code that follows it. Otherwise you can write the code like this: + +```scala +for (i <- ints) println(i) +``` + #### Guards -You can also use one or more `if` expressions inside a `for` loop. These are referred to as *guards*. This example prints all of the numbers in `ints` that are greater than `2`: +You can also use one or more `if` expressions inside a `for` loop. These are referred to as _guards_. This example prints all of the numbers in `ints` that are greater than `2`: - - ```scala -val ints = List(1,2,3,4,5) - for - i <- ints + i <- ints if i > 2 do println(i) @@ -407,24 +378,21 @@ do println(s"i = $i, j = $j") // prints: "i = 2, j = b" ``` -We encourage you to make changes to that code to be sure you understand how it works. - #### Using `for` as an expression -The `for` keyword has even more power: When you use the `yield` keyword instead of `do`, you create `for` *expressions* which are used to calculate and yield results. +The `for` keyword has even more power: When you use the `yield` keyword instead of `do`, you create `for` _expressions_ which are used to calculate and yield results. A few examples demonstrate this. Using the same `ints` list as the previous example, this code creates a new list, where the value of each element in the new list is twice the value of the elements in the original list: ```` -scala> val doubles = for (i <- ints) yield i * 2 +scala> val doubles = for i <- nums yield i * 2 val doubles: List[Int] = List(2, 4, 6, 8, 10) ```` -Note that Scala’s syntax is flexible, and that `for` expression can be written in several different ways to make your code more readable: +Scala’s control structure syntax is flexible, and that `for` expression can be written in several other ways, depending on your preference: ```scala -val doubles = for i <- ints yield i * 2 val doubles = for (i <- ints) yield i * 2 val doubles = for (i <- ints) yield (i * 2) ``` @@ -438,7 +406,7 @@ val capNames = for name <- names yield name.capitalize Finally, this `for` expression iterates over a list of strings, and returns the length of each string, but only if that length is greater than `4`: - + ```scala val fruits = List("apple", "banana", "lime", "orange") @@ -446,14 +414,13 @@ val fruitLengths = for f <- fruits if f.length > 4 yield + // you can use multiple lines + // of code here f.length // result: List[Int] = List(5, 6, 6) ``` -Because Scala code generally just makes sense, you can probably guess how this code works, even if you’ve never seen a for-expression or Scala list until now. - - `for` loops and expressions are covered in more detail in the Control Structures sections of this Overview and in the Reference documentation. @@ -471,7 +438,7 @@ i match case _ => println("other") ``` -However, a `match` expression really is an expression, meaning that it returns a result based on the pattern match: +However, `match` really is an expression, meaning that it returns a result based on the pattern match, which you can bind to a variable: ```scala val result = i match @@ -480,7 +447,7 @@ val result = i match case _ => "other" ``` -The `match` expression isn’t limited to just integers, it can be used with any data type, including booleans: +`match` isn’t limited to just integers, it can be used with any data type, including booleans: ```scala val booleanAsString = bool match @@ -488,9 +455,9 @@ val booleanAsString = bool match case false => "false" ``` -In fact, a `match` expression can be used to test a variable against multiple patterns. This example shows (a) how to use a `match` expression as the body of a method, and (b) how to match all the different types shown: +In fact, a `match` expression can be used to test a variable against many different types of patterns. This example shows (a) how to use a `match` expression as the body of a method, and (b) how to match all the different types shown: - + ```scala def getClassAsString(x: Any): String = x match case s: String => s"'$s' is a String" @@ -505,26 +472,25 @@ getClassAsString("hello") // 'hello' is a String getClassAsString(List(1,2,3)) // List ``` -There’s much more to pattern matching in Scala. Patterns can be nested, results of patterns can be bound, and pattern matching can even be user-defined. You can find more pattern matching examples in the Control Structures section of this Overview, and in the Reference documentation. +There’s _much_ more to pattern matching in Scala. Patterns can be nested, results of patterns can be bound, and pattern matching can even be user-defined. See the pattern matching examples in the Control Structures sections of this Overview and the Reference documentation for more details. -### try/catch/finally +### `try`/`catch`/`finally` -Scala’s `try`/`catch` control structure lets you catch exceptions. It’s similar to Java, but its syntax is consistent with `match` expressions: +Scala’s `try`/`catch`/`finally` control structure lets you catch exceptions. It’s similar to Java, but its syntax is consistent with `match` expressions: - ```scala try - writeToFile(text) + writeTextToFile(text) catch - case fnfe: FileNotFoundException => println(fnfe) - case ioe: IOException => println(ioe) + case ioe: IOException => println("Got an IOException.") + case nfe: NumberFormatException => println("Got a NumberFormatException.") +finally + println("Clean up your resources here.") ``` -### while loops - - +### `while` loops Scala also has a `while` loop construct. It’s one-line syntax looks like this: @@ -532,50 +498,56 @@ Scala also has a `while` loop construct. It’s one-line syntax looks like this: while x >= 0 do x = f(x) ``` -And it’s multiline syntax looks like this: +If you leave the parentheses off of the test condition, the `do` keyword is required before the code that follows it. Again, Scala’s control structure syntax is flexible, and you can write this code in different ways depending on your preferences: ```scala -var x = 1 +while (x >= 0) do x = f(x) +while (x >= 0) { x = f(x) } +``` -// parentheses -while (x < 3) - println(x) - x += 1 +The `while` loop multiline syntax looks like this: + +```scala +var x = 1 -// no parens +// without parentheses while x < 3 do println(x) x += 1 + +// with parentheses +while (x < 3) + println(x) + x += 1 ``` -### Create your own control structures! -Thanks to features like by-name parameters, infix notation, fluent interfaces, optional parentheses, extension methods, and higher-order functions, you can also create code that works just like a control structure. You’ll learn more about this in the Control Structures chapter in the Reference documentation. +### Create your own control structures + +Thanks to features like by-name parameters, infix notation, fluent interfaces, optional parentheses, extension methods, and higher-order functions, you can also create your own code that works just like a control structure. You’ll learn more about this in the Control Structures chapter in the Reference documentation. ## Data Modeling + Scala supports both functional programming (FP) and object-oriented programming (OOP), as well as a fusion of the two paradigms. This section provides a quick overview of data modeling in OOP and FP. -### OOP data modeling (traits and classes) +### Data Modeling (Object-Oriented Programming Style) -When writing code in an OOP style, your two main tools will be *traits* and *classes*. +When writing code in an OOP style, your two main tools for data encapsulation are _traits_ and _classes_. + + #### Traits - -Traits are like interfaces in other languages, but they can also contain implemented methods. They provide a great way for you to organize behaviors into small, modular units. When you want to create concrete implementations of attributes and behaviors, classes and objects can extend traits, mixing in as many traits as needed to achieve the desired behavior. +Scala traits can be used as simple interfaces, but they can also contain abstract and concrete methods and fields, and they can have parameters, just like classes. They provide a great way for you to organize behaviors into small, modular units. Later, when you want to create concrete implementations of attributes and behaviors, classes and objects can extend traits, mixing in as many traits as needed to achieve the desired behavior. -Here are three traits that define well-organized and modular behaviors for animals like dogs and cats: + +As an example of how to use traits as interfaces, here are three traits that define well-organized and modular behaviors for animals like dogs and cats: ```scala trait Speaker: @@ -620,42 +592,43 @@ c.startRunning() // "Yeah ... I don’t run" c.stopRunning() // "No need to stop" ``` - If that code makes sense — great, you’re comfortable with traits as interfaces. If not, don’t worry, they’re explained in more detail in the Data Modeling sections of this Overview and the Reference documentation. - - #### Classes - - -Scala *classes* are used in OOP-style programming. Here’s an example of a class that models a “person.” In OOP, fields are typically mutable, so `firstName` and `lastName` are both declared as `var` parameters: +Scala _classes_ are used in OOP-style programming. Here’s an example of a class that models a “person.” In OOP fields are typically mutable, so `firstName` and `lastName` are both declared as `var` parameters: ```scala class Person(var firstName: String, var lastName: String): def printFullName() = println(s"$firstName $lastName") -val p = Person("Julia", "Kern") -println(p.firstName) // "Julia" -p.lastName = "Manes" -p.printFullName() // "Julia Manes" +val p = Person("John", "Stephens") +println(p.firstName) // "John" +p.lastName = "Legend" +p.printFullName() // "John Legend" +``` + +Notice that the class declaration creates a constructor: + +```scala +class Person(var firstName: String, var lastName: String): + // more code here + +// this code uses that constructor +val p = Person("John", "Stephens") ``` +Constructors and other class-related topics are covered in the Data Modeling sections in this Overview, and in the Reference documentation. + ### Data Modeling (Functional Programming Style) + + When writing code in an FP style, you’ll use these constructs: - Enums to define ADTs @@ -664,15 +637,6 @@ When writing code in an FP style, you’ll use these constructs: #### Enums - The `enum` construct is a great way to model algebraic data types (ADTs) in Scala 3. For instance, a pizza has three main attributes: @@ -700,7 +664,7 @@ import CrustSize._ val currentCrustSize = Small // enums in a `match` expression -currentCrustSize match +currentCrustSize match case Small => println("Small crust size") case Medium => println("Medium crust size") case Large => println("Large crust size") @@ -709,17 +673,12 @@ currentCrustSize match if currentCrustSize == Small then println("Small crust size") ``` -Enums can also take parameters and have user-defined members like fields and methods. Here’s a sneak-peek of those capabilities: +Here’s another example of how to create and use an ADT with Scala: ```scala -enum Planet(mass: Double, radius: Double): - private final val G = 6.67300E-11 - def surfaceGravity = G * mass / (radius * radius) - - case Mercury extends Planet(3.303e+23, 2.4397e6) - case Venus extends Planet(4.869e+24, 6.0518e6) - // more ... -} +enum Nat: + case Zero + case Succ(pred: Nat) ``` Enums are covered in detail in the Data Modeling section of this Overview, and in the Reference documentation. @@ -727,26 +686,24 @@ Enums are covered in detail in the Data Modeling section of this Overview, and i #### Case classes - - -A *case class* is an extension of the base Scala class. Case classes provide features that make them useful for functional programming. They have all of the functionality of a regular class, and more. When the compiler sees the `case` keyword in front of a `class`, it generates code for you, with these benefits: +The Scala `case` class lets you model concepts with immutable data structures. A `case` class has all of the functionality of a `class`, and also has additional features baked in that make them useful for functional programming. When the compiler sees the `case` keyword in front of a `class` it has these effects and benefits: -- Case class constructor parameters are public `val` fields by default, so accessor methods are generated for each parameter. -- An `apply` method is created in the companion object of the class, so you don’t need to use the `new` keyword to create a new instance of the class. +- Case class constructor parameters are public `val` fields by default, so the fields are immutable, and accessor methods are generated for each parameter. - An `unapply` method is generated, which lets you use case classes in more ways in `match` expressions. -- A `copy` method is generated in the class. This provides a way to clone an object while making updates to its values during the cloning process. +- A `copy` method is generated in the class. This provides a way to clone an object while making updates to its values as the cloned copy is created. In this way the original object can be used as a template, and the cloned copy can have changed fields, as needed. - `equals` and `hashCode` methods are generated. - A default `toString` method is generated, which is helpful for debugging. -This code demonstrates several case class features: + + +You _can_ manually add all of those methods to a class yourself, but since those features are so commonly used in functional programming, using a `case` class is much more convenient. + +This code demonstrates several `case` class features: ```scala // define a case class case class Person( - name: String, + name: String, vocation: String ) @@ -766,20 +723,16 @@ val p2 = p.copy(name = "Elton John") p2 // Person = Person(Elton John,Singer) ``` -See the Data Modeling sections of this Overview and the Reference documentation for many more details on case classes. +See the Data Modeling sections of this Overview and the Reference documentation for many more details on `case` classes. ## Scala methods - - Scala classes, case classes, traits, enums, and objects can all contain methods. The general method syntax looks like this: ```scala -def methodName(param1: Type1, param2: Type2): ReturnType = +def methodName(param1: Type1, param2: Type2): ReturnType = // the method body // goes here ``` @@ -814,135 +767,179 @@ def getStackTraceAsString(t: Throwable): String = sw.toString ``` -There are more things you can do with methods, such as providing default values for method parameters and using named parameters when calling methods. Those featurs are shown in the Data Modeling section of this Overview and in the Reference documentation. - +Method parameters can also have default values. In this example, if the `timeout` parameter isn’t specified, it defaults to `5000`: +```scala +def makeConnection(url: String, timeout: Int = 5000): Unit = + println(s"url=$url, timeout=$timeout") +``` -## First-class functions +Because a default `timeout` value is supplied in the method declaration, the method can be called in these two ways: -Scala has first-class support for functional programming, and included in that is first-class support for everything related to functions: +```scala +makeConnection("https://localhost") // url=http://localhost, timeout=5000 +makeConnection("https://localhost", 2500) // url=http://localhost, timeout=2500 +``` -- Top-level functions -- Functions in objects -- Lambdas -- Higher-order functions (HOFs) +Scala also supports the use of _named parameters_ when calling a method, so you can also call that method like this, if you prefer: - - +```scala +makeConnection( + url = "https://localhost", + timeout = 2500 +) +``` +Named parameters are particularly useful when multiple method parameters have the same type: -### Top-level functions +```scala +engage(true, true, true, false) +``` -Functions don’t have to be in the body of a class, enum, or object. They can also exist on their own as a *top-level function*. For instance, when this code is saved in a file, the functions `add` and `double` would be called top-level functions because they exist outside the scope of a class, enum, or object: +Without help from an IDE that code can be hard to read, but this code is much more obvious: ```scala -package foo +engage( + speedIsSet = true, + directionIsSet = true, + picardSaidMakeItSo = true, + turnedOffParkingBrake = false +) +``` -def add(a: Int, b: Int): Int = a + b -def double(a: Int): Int = 2 * a +Methods are covered in detail in the Data Modeling section of this Overview, and in the Reference documentation. -@main def topLevelFunctions() = - val x = add(1, 2) - val y = double(x) - println(s"y = $y") -``` -### Functions in objects +## Objects -Functions can also be placed in objects. Here are a few functions in a “string utilities” object: +In Scala, the `object` keyword creates a Singleton object. Put another way, an object is a class that has exactly one instance. -```scala -object StringUtils: +Objects have several uses: + +- They are used to create collections of utility methods. +- A _companion object_ is an object that has the same name as the class it shares a file with. In this situation, that class is also called a _companion class_. +- They’re used to _reify_ traits to create _modules_. - // Left-trim a string: `" foo "` becomes `"foo "`. - def leftTrim(s: String) = s.replaceAll("^\\s+", "") +### Creating a collection of utility methods - // Right-trim a string: `" foo "` becomes `" foo"`. - def rightTrim(s: String) = s.replaceAll("\\s+$", "") +Because an `object` is a Singleton, its methods can be accessed like `static` methods in a Java class. For example, this `StringUtils` object contains a small collection of string-related methods: +```scala +object StringUtils: def isNullOrEmpty(s: String): Boolean = if (s==null || s.trim.equals("")) true else false + def leftTrim(s: String): String = s.replaceAll("^\\s+", "") + def rightTrim(s: String): String = s.replaceAll("\\s+$", "") +``` + +Because `StringUtils` is a singleton, its methods can be called directly on the object: -end StringUtils +```scala +val x = StringUtils.isNullOrEmpty("") // true +val x = StringUtils.isNullOrEmpty("a") // false ``` -Those functions can be called like this: +### Creating a companion object + +A companion class or object can access the private members of its companion. Use a companion object for methods and values which aren’t specific to instances of the companion class. + +This example demonstrates how the `area` method in the companion class can access the private `calculateArea` method in its companion object: ```scala -StringUtils.leftTrim(" hi ") // "hi " +import scala.math._ + +class Circle(radius: Double): + import Circle._ + def area: Double = calculateArea(radius) + +object Circle: + private def calculateArea(radius: Double): Double = + Pi * pow(radius, 2.0) + +val circle1 = Circle(5.0) +circle1.area // Double = 78.53981633974483 ``` -or this: + +### Using objects to reify traits + +Objects can also be used to reify traits to create modules. “Reify” means to turn an abstract concept and turn it into something concrete, and the process with traits and objects looks like this: ```scala -import StringUtils._ -leftTrim(" hi ") // "hi " +trait AddService: + def add(a: Int, b: Int) = a + b + +trait MultiplyService: + def multiply(a: Int, b: Int) = a * b + +// reify those traits into a concrete object +object MathService extends AddService, MultiplyService + +// use the object +import MathService._ +println(add(1,1)) // 2 +println(multiply(2,2)) // 4 ``` + +## First-class functions + +Scala has all of the features you’d expect in a functional programming language, including: + +- Lambdas +- Higher-order functions (HOFs) +- Higher-order functions in the standard library + + ### Lambdas -Lambdas — also known as *anonymous functions* — are a big part of keeping your code concise but readable. These two examples are equivalent, and show how to multiply each number in a list by `2` by passing a lambda into the `map` method: + + +Lambdas, also known as _anonymous functions_, are a big part of keeping your code concise but readable. These two examples — which show how to call higher-order functions (HOFs) on a Scala `List` — are equivalent, and show how to multiply each number in a list by `2` by passing a lambda into the `map` method: ```scala val a = List(1,2,3).map(i => i * 2) // List(2,4,6) val b = List(1,2,3).map(_ * 2) // List(2,4,6) ``` -Those examples are also equivalent to that code, but they use a `double` method inside of `map` instead of a lambda: +Those examples are also equivalent to the following code, which uses a `double` method inside of `map` instead of a lambda: ```scala def double(i: Int): Int = i * 2 -val a = List(1,2,3).map(i => double(i)) -val b = List(1,2,3).map(double) -``` ->If you haven’t seen the `map` method before, it applies a given function to every element in a list, yielding a new list that contains the new values. +val a = List(1,2,3).map(i => double(i)) // List(2,4,6) +val b = List(1,2,3).map(double) // List(2,4,6) +``` +>If you haven’t seen the `map` method before, it applies a given function to every element in a list, yielding a new list that contains the resulting values. -### Higher-order functions +Passing lambdas into higher-order functions on collections classes is a part of the Scala experience, something you’ll do every day. -A “higher order function” (HOF) is a function that can take a function as an input parameter, or returns a function as a return value. HOFs are extremely common in Scala, such as being used throughout the standard libraries. These examples show how to pass methods and anonymous functions into the functional methods of Scala collections: +It’s important to know that these functions don’t mutate the collection they’re called on; instead, they return a new collection with the updated data. As a result, it’s also common to chain them together in a “fluent” style to solve problems. This example shows how to filter a collection twice, and then multiply each element in the remaining collection: ```scala // a sample list -val nums = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - -// sample methods -def isEven(i: Int): Boolean = i % 2 == 0 -def double(i: Int): Int = i * 2 - -// pass in a method or function -val a = nums.filter(isEven) // List(2, 4, 6, 8, 10) -val b = nums.map(double) // List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) +val nums = (1 to 10).toList // List(1,2,3,4,5,6,7,8,9,10) -// pass in a lambda -val c = nums.filter(_ % 2 == 0) // List(2, 4, 6, 8, 10) -val d = nums.map(_ * 2) // List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) - -// methods can be chained as needed -val e = nums.filter(_ > 3) // List(40, 50, 60) +// methods can be chained together as needed +val x = nums.filter(_ > 3) .filter(_ < 7) .map(_ * 10) + +// result: x == List(40, 50, 60) ``` -In addition to HOFs used all throughout the standard library, you can easily create your own HOFs. This is shown in the Reference documentation. +In addition to higher-order functions being used throughout the standard library, you can also create your own. This is shown in the Reference documentation. - ## Extension methods - -*Extension methods* let you add new methods to closed classes. For instance, if you want to add two methods named `hello` and `aloha` to the `String` class, just declare them as extension methods: +_Extension methods_ let you add new methods to closed classes. For instance, if you want to add two methods named `hello` and `aloha` to the `String` class, declare them as extension methods: - + ```scala extension (s: String): def hello: String = s"Hello, ${s.capitalize}" @@ -952,11 +949,11 @@ extension (s: String): "friend".aloha // "Aloha, Friend" ``` -The `extension` keyword declares that you’re about to define one or more extension methods. As shown, the `s` parameter can then be used in your methods. +The `extension` keyword declares that you’re about to define one or more extension methods on the type that’s put in parentheses. As shown with this `String` example, the parameter `s` can then be used in the body of your extension methods. This next example shows how to add a `makeInt` method to the `String` class. Here, `makeInt` takes a parameter named `radix`. The code doesn’t account for possible string-to-integer conversion errors, but skipping that detail, the examples show how it works: - + ```scala extension (s: String) def makeInt(radix: Int): Int = Integer.parseInt(s, radix) @@ -970,170 +967,65 @@ extension (s: String) ## Collections classes -Scala has a rich set of collections classes, and those classes have a rich set of methods. Collections classes are available in both immutable and mutable forms. In alphabetical order, the basic collections classes you’ll use on a regular basis are: - -| Class | Mutable | Immutable | Description | -| ------------- | :-----: | :-------: | ----------- | -| `ArrayBuffer` | ✓ | | an indexed, mutable sequence | -| `List` | | ✓ | a linear (linked list), immutable sequence | -| `Map` | ✓ | ✓ | the base `Map` (key/value pairs) class | -| `Set` | ✓ | ✓ | the base `Set` class | -| `Vector` | | ✓ | an indexed, immutable sequence | - -Scala also has a `Range` class which lets you create ordered sequences of integers that are equally spaced apart, such as “1, 2, 3,” and “5, 8, 11, 14.” Ranges are often used in `for` loops, and to create other sequences: - -```scala -// a range in a for-loop -for (i <- 1 to 3) print(i) // 123 - -// use ranges to create other collections -(1 to 5).toList // List(1, 2, 3, 4, 5) -(1 to 10 by 2).toVector // Vector(1, 3, 5, 7, 9) -(1 to 10).toSet // Set[Int] = HashSet(5, 10, 1, 6, 9, 2, 7, 3, 8, 4) - -('a' to 'f').toList // List[Char] = List(a, b, c, d, e, f) -('a' to 'f' by 2).toList // List[Char] = List(a, c, e) - -List.range(1, 5) // List(1, 2, 3, 4) -List.range(1, 5, 2) // List(1, 3) -``` - - - - -### Immutable collections classes - -Some of the most-commonly used *immutable* collections classes are: - -| Class | Description | -| ------------- | ------------- | -| `List` | A finite immutable linked-list. | -| `LazyList` | Like a `List` except that its elements are computed lazily. Because of this, a lazy list can be infinitely long. | -| `Vector` | A sequential collection type that provides good performance for all its operations. | -| `Map` | Like maps in Java, dictionaries in Python, or a `HashMap` in Rust, `Map` is an `Iterable` that contains pairs of keys and values. | -| `Set` | An `Iterable` sequence that contains no duplicate elements. | -| `Stack` | A last-in-first-out sequence. | -| `Queue` | A first-in-first-out sequence. | - -In addition to the previous `Range` examples, here are a few more ways to create immutable collections: - - -```scala -val a = List(1,2,3) -val b = Vector("hello", "world") - -// create a List with a Range -val c = (1 to 5).toList - -val m = Map( - 1 -> "one", - 2 -> "two" -) -``` - - -### Mutable collections classes - -Mutable Scala collections classes are located in the *scala.collection.mutable* package. These are some of the most commonly-used: - -| Class | Description | -| ------------- | ------------- | -| `ArrayBuffer` | An indexed mutable buffer backed by an array. | -| `ListBuffer` | A mutable buffer backed by a linked list. Use this class if you’ll use it like a `List`, or if you’ll convert it to a `List` once it’s built up. | -| `Map` | A mutable `Map`, contains pairs of keys and values. | -| `Set` | A mutable `Set`, a sequence that contains no duplicate elements. | -| `Stack` | A mutable, last-in-first-out sequence. | -| `Queue` | A mutable, first-in-first-out sequence. | +Scala has a rich set of collections classes, and those classes have a rich set of methods. Collections classes are available in both immutable and mutable forms. -These examples show a few ways to use an `ArrayBuffer`: +To give you a taste of how these work, here are some examples that use the `List` class, which is an immutable, linked-list class. These examples show different ways to create a populated `List`: ```scala -import scala.collection.mutable.ArrayBuffer +val a = List(1,2,3) // a: List[Int] = List(1, 2, 3) -val a = ArrayBuffer(1,2,3) // ArrayBuffer(1, 2, 3) - -val b = ArrayBuffer[String]() // ArrayBuffer[String] = ArrayBuffer() -b += "Hello" // ArrayBuffer(Hello) -b ++= List("world", "it’s", "me") // ArrayBuffer(Hello, world, it’s, me) +// Range methods +val b = (1 to 5).toList // b: List[Int] = List(1, 2, 3, 4, 5) +val c = (1 to 10 by 2).toList // c: List[Int] = List(1, 3, 5, 7, 9) +val e = (1 until 5).toList // e: List[Int] = List(1, 2, 3, 4) +val f = List.range(1, 5) // f: List[Int] = List(1, 2, 3, 4) +val g = List.range(1, 10, 3) // g: List[Int] = List(1, 4, 7) ``` -In addition to those classes, Scala has an `Array` class, which is a special kind of collection. An `Array` corresponds one-to-one to a Java `array`, so its elements can be mutated, but its size can’t be changed. In addition to behaving like a Java `array`, (a) it can hold generic types, and (b) it supports all of the usual sequence methods (which you’re about to see). - - - -### Sequence methods + - - -A great benefit of the Scala collections classes is that they offer dozens of powerful functional methods you can use to simplify your code. These are just a few of the common methods available to sequences: - -| Method | Description | -| ------------- | ------------- | -| `map` | Creates a new collection by applying a function to all the elements of the collection. | -| `filter` | Returns all elements from the collection for which a given predicate is true. | -| `foreach` | Applies a function to all elements of the collection to produce a side effect. | -| `take`, `takeWhile` | Returns elements from the beginning of the collection. | -| `drop`, `dropWhile` | Returns all elements in the collection except the first elements that are specified. | -| `flatten` | Converts a sequence of sequences (such as a list of lists) to a single sequence (single list). | -| `foldLeft` | Applies an operation to successive elements, going from left to right, using an initial seed value | -| `reduce` | The same as `foldLeft`, but without an initial seed value. | - -There are dozens of additional methods, which you’ll see in the Collections section of this Overview, and in the Reference documentation. - ->A key to know about all of these methods is that they are *functional*: they don’t modify the existing sequence; they return a new collection by applying the method to the original sequence. - -These examples demonstrate some of the commonly-used sequence methods: +Once you have a populated list, the following examples show some of the methods you can call on it. Notice that these are all functional methods, meaning that they don’t mutate the collection they’re called on, but instead return a new collection with the updated elements. The result that’s returned by each expression is shown in the comment on each line: ```scala // a sample list val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) a.drop(2) // List(30, 40, 10) -a.dropRight(2) // List(10, 20, 30) a.dropWhile(_ < 25) // List(30, 40, 10) a.filter(_ < 25) // List(10, 20, 10) -a.find(_ > 20) // Some(30) -a.head // 10 -a.headOption // Some(10) -a.last // 10 -a.lastOption // Some(10) a.slice(2,4) // List(30, 40) a.tail // List(20, 30, 40, 10) a.take(3) // List(10, 20, 30) -a.takeRight(2) // List(40, 10) a.takeWhile(_ < 30) // List(10, 20) +// flatten val a = List(List(1,2), List(3,4)) a.flatten // List(1, 2, 3, 4) +// map, flatMap val nums = List("one", "two") -nums.map(_.toUpperCase) // List("ONE", "TWO") -nums.flatMap(_.toUpperCase) // List('O', 'N', 'E', 'T', 'W', 'O') +nums.map(_.toUpperCase) // List("ONE", "TWO") +nums.flatMap(_.toUpperCase) // List('O', 'N', 'E', 'T', 'W', 'O') ``` -These examples show how the “fold” and “reduce” methods are used to sum up every element in a sequence: +These examples show how the “fold” and “reduce” methods are used to sum the values in a sequence of integers: ```scala val firstTen = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -firstTen.fold(100)(_ + _) // 155 -firstTen.foldLeft(100)(_ + _) // 155 firstTen.reduce(_ + _) // 55 firstTen.reduceLeft(_ + _) // 55 +firstTen.fold(100)(_ + _) // 155 (100 is a “seed” value) +firstTen.foldLeft(100)(_ + _) // 155 ``` -There are many (many!) more methods available to Scala collections classes, and they’re demonstrated in the Collections sections of this Overview and in the Reference documentation. +There are many more methods available to Scala collections classes, and they’re demonstrated in the Collections sections of this Overview and in the Reference documentation. -### Tuples - +### Tuples -The Scala *tuple* is a type that lets you easily put a collection of different types in the same container. For example, given this `Person` case class: +The Scala _tuple_ is a type that lets you easily put a collection of different types in the same container. For example, given this `Person` case class: ```scala case class Person(name: String) @@ -1145,7 +1037,7 @@ This is how you create a tuple that contains an `Int`, a `String`, and a custom val t = (11, "eleven", Person("Eleven")) ``` -You can access the tuple values by number: +Once you have a tuple, you can access its values by binding them to variables, or access them by number: ```scala t._1 // 11 @@ -1153,126 +1045,22 @@ t._2 // "eleven" t._3 // Person("Eleven") ``` -You can also assign the tuple fields to variables, as shown in the REPL: - -```` -scala> val (num, string, name) = (11, "eleven", Person("Eleven")) -val num: Int = 11 -val string: String = eleven -val good: Boolean = Person(Eleven) -```` - -Tuples are nice for those times when you want to put a collection of heterogenous types in a little collection-like structure. - - +Tuples are nice for those times when you want to put a collection of heterogenous types in a little collection-like structure. See the Reference documentation for more tuple details. ## Contextual Abstractions - - -Implicits in Scala 2 were a main distinguishing feature. Following Haskell, Scala was the second popular language to have some form of implicits. Other languages have since followed suit. - -Implicits are a fundamental way to abstract over context. They represent a unified paradigm with a great variety of use cases, among them: - -- Implementing type classes -- Establishing context -- Dependency injection -- Expressing capabilities -- Computing new types and proving relationships between them - -Even though different languages use widely different terminology, they’re all variants of the core idea of *term inference*. Given a type, the compiler synthesizes a “canonical” term that has that type. Scala embodies the idea in a purer form than most other languages: An implicit parameter directly leads to an inferred argument term that could also be written down explicitly. - -In Scala 3 the syntax for these constructs has been changed significantly to make their usage more clear. Implicits are defined with the keyword `given`, and in later code they are referenced with the keyword `using`. - - -### Term inference - -Here’s a quick example of how to use term inference in Scala 3. Imagine that you have a situation where a value is passed into a series of function calls, such as using an `ExecutionContext` when you’re working with parallel programming: - -```scala -doX(a, executionContext) -doY(b, c, executionContext) -doZ(d, executionContext) -``` - -Because this type of code is repetitive and makes the code harder to read, you’d prefer to write it like this instead: - -```scala -doX(a) -doY(b, c) -doZ(d) -``` - -The functions still use the `executionContext` variable, but they don’t require you to explicitly state that. As shown, the shorter code is more easy to read. - -When you want a solution like this, Scala 3’s term inference solution is what you’re looking for. The solution involves multiple steps: - -1. Define the code you want the compiler to discover using the Scala 3 `given` keyword. -1. When declaring the “implicit” parameter your function will use, put it in a separate parameter group and define it with the `using` keyword. -1. Make sure your `given` value is in the current context when your function is called. - -The following example demonstrates these steps with the use of an `Adder` trait and two `given` values that implement the `Adder` trait’s `add` method. - - -### Step 1: Define your “given instances” - -In the first step you’ll typically create a parameterized trait: - -```scala -trait Adder[T]: - def add(a: T, b: T): T -``` - -Then you’ll implement the trait using one or more `given` instances, which you define like this: +Under certain circumstances, the Scala compiler can “write” some parts of your programs. For instance, consider a program that sorts a list of addresses by two criteria, city name and then street name: ```scala -given intAdder as Adder[Int]: - def add(a: Int, b: Int): Int = a + b - -given stringAdder as Adder[String]: - def add(a: String, b: String): String = "" + (a.toInt + b.toInt) +val addresses: List[Address] = ... +addresses.sortBy(address => (address.city, address.street)) ``` -In this example, `intAdder` is an instance of `Adder[Int]`, and defines an `add` method that works with `Int` values. Similarly, `stringAdder` is an instance of `Adder[String]` and provides an `add` method that takes two strings, converts them to `Int` values, adds them together, and returns the sum as a `String`. (To keep things simple the code doesn’t account for potential string-to-integer errors.) - -If you’re familiar with creating implicits in Scala 2, this new approach is similar to that process. The idea is the same, it’s just that the syntax has changed. - +The sorting algorithm needs to compare addresses by first comparing their city names, and then also their street names when the city names are the same. However, with the use of contextual abstraction, you don’t need to manually define this ordering relation, because the compiler is able to summon it automatically based on an existing ordering relation for comparing string values. -### Step 2: Declare the parameter your function will use with the `using` keyword - -Next, define your functions that use the `Adder` instances. When doing this, specify the `Adder` parameter with the `using` keyword. Put the parameter in a separate parameter group, as shown here: - -```scala -def genericAdder[A](x: A, y: A)(using adder: Adder[A]): A = - adder.add(x, y) -``` - -The keys here are that the `adder` parameter is defined with the `using` keyword in that separate parameter group: - -```scala -def genericAdder[A](x: A, y: A)(using adder: Adder[A]): A = - ----------------------- -``` - -Also notice that `genericAdder` declares the generic type `A`. This function doesn’t know if it will be used to add two integers or two strings — it just calls the `add` method of the `adder` parameter. - ->In Scala 2, parameters like this were declared using the `implicit` keyword, but now, as the entire programming industry has various implementations of this concept, this parameter is known in Scala 3 as a *context parameter*. - - -### Step 3: Make sure everything is in the current context - -Finally, assuming that `intAdder`, `stringAdder`, and `genericAdder` are all in scope, your code can call the `genericAdder` function with `Int` and `String` values, without having to pass instances of `intAdder` and `stringAdder` into `genericAdder`: - -```scala -println(genericAdder(1, 1)) // 2 -println(genericAdder("2", "2")) // 4 -``` - -The Scala compiler is smart enough to know that `intAdder` should be used in the first instance, and `stringAdder` should be used in the second instance. This is because the first example uses two `Int` parameters and the second example uses two `String` values. +For more details, see the Contextual Abstractions section in this Overview, and also in the Reference documentation. @@ -1280,38 +1068,3 @@ The Scala compiler is smart enough to know that `intAdder` should be used in the Scala has even more features that weren’t covered in this whirlwind tour. See the remainder of this Overview and the Reference documentation for many more details. - - - - - - - - - - - diff --git a/_overviews/overview/control-structures.md b/_overviews/overview/control-structures.md index e69de29bb2..fc4bff784d 100644 --- a/_overviews/overview/control-structures.md +++ b/_overviews/overview/control-structures.md @@ -0,0 +1,555 @@ +--- +title: Control Structures +description: This page provides an introduction to Scala's control structures, including if/then/else, 'for' loops, 'for' expressions, 'match' expressions, try/catch/finally, and 'while' loops. +--- + + + +Scala has the control structures you expect to find in a programming language, including: + +- `if`/`then`/`else` +- `for` loops +- `while` loops +- `try`/`catch`/`finally` + +It also has two other powerful constructs that you may not have seen before, depending on your programming background: + +- `for` expressions (also known as _`for` comprehensions_) +- `match` expressions + +These are all demonstrated in the following sections. + + + +## The if/then/else construct + +A one-line Scala `if` statement looks like this: + +```scala +if x == 1 then println(x) +``` + +When you need to run multiple lines of code after an `if` equality comparison, use this syntax: + +```scala +if x == 1 then + println("x is 1, as you can see:") + println(x) +``` + +The `if`/`else` syntax looks like this: + +```scala +if x == 1 then + println("x is 1, as you can see:") + println(x) +else + println("x was not 1") +``` + +And this is the `if`/`else if`/`else` syntax: + +```scala +if x < 0 then + println("negative") +else if x == 0 + println("zero") +else + println("positive") +``` + +You can optionally include an `end if` statement at the end of each expression, if you prefer: + +```scala +if x == 1 then + println("x is 1, as you can see:") + println(x) +end if +``` + + +### `if`/`else` expressions always return a result + +Note that `if`/`else` comparisons form _expressions_, meaning that they return a value which you can assign to a variable. Because of this, there’s no need for a special ternary operator: + +```scala +val minValue = if a < b then a else b +``` + +Because they return a value, you can use `if`/`else` expressions as the body of a method: + +```scala +def compare(a: Int, b: Int): Int = + if a < b then + -1 + else if a == b then + 0 + else + 1 +``` + +### Aside: Expression-oriented programming + +As a brief note about programming in general, when every expression you write returns a value, that style is referred to as _expression-oriented programming_, or EOP. For example, this is an _expression_: + +```scala +val minValue = if a < b then a else b +``` + +Conversely, lines of code that don’t return values are called _statements_, and they’re used for their _side-effects_. For example, these lines of code don’t return values, so they’re used for their side effects: + +```scala +if a == b then doSomething() +println("Hello") +``` + +The first example runs the `doSomething` method as a side effect when `a` is equal to `b`. The second example is used for the side effect of printing a string to STDOUT. As you learn more about Scala you’ll find yourself writing more _expressions_ and fewer _statements_. + + + +## `for` loops + +In its most simple use, a Scala `for` loop can be used to iterate over the elements in a collection. For example, given a sequence of integers, You can loop over its elements and print their values like this: + +```scala +val ints = Seq(1,2,3) +for i <- ints do println(i) +``` + +The code `i <- ints` is referred to as a _generator_, and if you leave the parentheses off of the generator, the `do` keyword is required before the code that follows it. Otherwise you can write the code like this: + +```scala +for (i <- ints) println(i) +``` + +Regardless of which approach you use, this is what the result looks like in the Scala REPL: + +```` +scala> val ints = Seq(1,2,3) +ints: Seq[Int] = List(1, 2, 3) + +scala> for i <- ints do println(i) +1 +2 +3 +```` + +When you need a multiline block of code following the `if` condition, use either of these approaches: + +```scala +// option 1 +for + i <- ints +do + val x = i * 2 + println(s"i = $i, x = $x") + +// option 2 +for (i <- ints) + val x = i * 2 + println(s"i = $i, x = $x") + +// option 3 +for (i <- ints) { + val x = i * 2 + println(s"i = $i, x = $x") +} +``` + +### Multiple generators + +`for` loops can have multiple generators, as shown in this example: + +```scala +for + i <- 1 to 2 + j <- 'a' to 'b' + k <- 1 to 10 by 5 +do + println(s"i = $i, j = $j, k = $k") +``` + +That expression prints this output: + +```` +i = 1, j = a, k = 1 +i = 1, j = a, k = 6 +i = 1, j = b, k = 1 +i = 1, j = b, k = 6 +i = 2, j = a, k = 1 +i = 2, j = a, k = 6 +i = 2, j = b, k = 1 +i = 2, j = b, k = 6 +```` + +### Guards + +`for` loops can also contain `if` statements, which are known as _guards_: + +```scala +for + i <- 1 to 5 + if i % 2 == 0 +do + println(i) +``` + +The output of that loop is: + +```` +2 +4 +```` + +A `for` loop can have as many guards as needed. This example shows one way to print the number `4`: + +```scala +for + i <- 1 to 10 + if i > 3 + if i < 6 + if i % 2 == 0 +do + println(i) +``` + +### Using `for` with Maps + +You can also use `for` loops with a `Map`. For example, given this `Map` of movie names and ratings: + + +```scala +val ratings = Map( + "Lady in the Water" -> 3.0, + "Snakes on a Plane" -> 4.0, + "You, Me and Dupree" -> 3.5 +) +``` + +You can print the movie names and ratings using `for` like this: + +```scala +for (name,rating) <- ratings do println(s"Movie: $name, Rating: $rating") +``` + +Here’s what that looks like in the REPL: + +```scala +scala> for (name,rating) <- ratings do println(s"Movie: $name, Rating: $rating") +Movie: Lady in the Water, Rating: 3.0 +Movie: Snakes on a Plane, Rating: 4.0 +Movie: You, Me and Dupree, Rating: 3.5 +``` + +As the `for` loop iterates over the map, each rating is bound to the variables `name` and `rating`, which are in a tuple: + +```scala +(name,rating) <- ratings +``` + +As the loop runs, the variable `name` is assigned to the current _key_ in the map, and the variable `rating` is assigned to the current map _value_. + + + + + +## `for` expressions + +In the previous `for` loop examples, those loops were all used for _side effects_, specifically to print those values to STDOUT using `println`. + +It’s important to know that you can also create `for` _expressions_ that return values. You create a `for` expression by adding the `yield` keyword and an expression to return, like this: + +```scala +val list = + for + i <- 10 to 12 + yield + i * 2 + +// result: list == Vector(20,22,24) +``` + +After that `for` expression runs, the variable `list` is a `Vector` that contains the values shown. This is how the expression works: + +1. The `for` expression starts to iterate over the values in the range `(10, 11, 12)`. It first works on the value `10`, multiples it by `2`, then _yields_ that result, the value `20`. +2. Next, it works on the `11` — the second value in the range. It multiples it by `2`, then yields the value `22`. You can think of these yielded values as accumulating in a temporary holding place. +3. Finally the loop gets the number `12` from the range, multiplies it by `2`, yielding the number `24`. The loop completes at this point and yields the final result, the `Vector(20,22,24)`. + +`for` expressions can be used any time you need to traverse all of the elements in a collection and apply an algorithm to those elements to create a new list. + +Here’s an example that shows how to use a block of code after the `yield`: + +```scala +val names = List("_adam", "_david", "_frank") + +val capNames = for name <- names yield + // imagine this algorithm requires multiple lines + val nameWithoutUnderscore = name.drop(1) + val capName = nameWithoutUnderscore.capitalize + capName + +// result: List(Adam, David, Frank) +``` + + +### Using a `for` expression as the body of a method + +Because a `for` expression yields a result, it can be used as the body of a method that returns a useful value. This method returns all of the values in a given list of integers that are between `3` and `10`: + +```scala +def between3and10(xs: List[Int]): List[Int] = + for + x <- xs + if x >= 3 + if x <= 10 + yield x + +between3and10(List(1,3,7,11)) // result: List(3, 7) +``` + + + + + +## `while` loops + +Scala `while` loop syntax looks like this: + +```scala +var i = 0 + +while i < 3 do + println(i) + i += 1 +``` + +If you use parentheses around the test condition, it can also be written like this: + +```scala +var i = 0 + +while (i < 3) { + println(i) + i += 1 +} +``` + + + + + +## `match` expressions + +Pattern matching is a major feature of functional programming languages, and Scala includes a `match` expression that has many capabilities. + +In the most simple case you can use a `match` expression like a Java `switch` statement, matching cases based on an integer value. Notice that this really is an expression, as it evaluates to a result: + +```scala +import scala.annotation.switch + +// `i` is an integer +val day = i match + case 0 => "Sunday" + case 1 => "Monday" + case 2 => "Tuesday" + case 3 => "Wednesday" + case 4 => "Thursday" + case 5 => "Friday" + case 6 => "Saturday" + case _ => "invalid day" // the default, catch-all +``` + +In this example the variable `i` is tested against the cases shown. If it’s between `0` and `6`, `day` is bound to a string that represents one of the days of the week. Otherwise, the catch-all case is represented by the `_` character, and `day` is bound to the string, `"invalid day"`. + +>When writing simple `match` expressions like this, it’s recommended to use the `@switch` annotation on the variable `i`. This annotation provides a compile time warning if the switch can’t be compiled to a `tableswitch` or `lookupswitch`, which are better for performance. See the Reference documentation for more details. + + +### Using the default value + +When you need to access the catch-all, default value in a `match` expression, just provide a variable name on the left side of the `case` statement, and then use that variable name on the right side of the statement as needed: + +```scala +i match + case 0 => println("1") + case 1 => println("2") + case what => println(s"You gave me: $what" ) +``` + +In this example the variable is named `what` to show that it can be given any legal name, but it’s more commonly given a name like `default`. + + +### Handling multiple possible matches on one line + +As mentioned, `match` expressions have many capabilities. This example shows how to use multiple possible pattern matches in each `case` statement: + +```scala +val evenOrOdd = i match + case 1 | 3 | 5 | 7 | 9 => println("odd") + case 2 | 4 | 6 | 8 | 10 => println("even") + case _ => println("some other number") +``` + + +### Using `if` expressions in `case` statements + +You can also use `if` expressions in the `case` statements of `match` expressions. In this example the second and third `case` statements both use `if` expressions to match multiple integer values: + +```scala +i match + case 1 => println("one, a lonely number") + case x if x == 2 || x == 3 => println("two’s company, three’s a crowd") + case x if x > 3 => println("4+, that’s a party") + case _ => println("i’m guessing your number is zero or less") +``` + +Here’s another example that shows how you can use `if` expressions in `case` statements. This example shows how to match a given value against ranges of numbers: + +```scala +i match + case a if 0 to 9 contains a => println(s"0-9 range: $a") + case b if 10 to 19 contains b => println(s"10-19 range: $b") + case c if 20 to 29 contains c => println(s"20-29 range: $c") + case _ => println("Hmmm...") +``` + + +#### Case classes and match expressions + +You can also extract fields from `case` classes — and classes that have properly written `apply`/`unapply` methods — and use those in your guard conditions. Here’s an example using a simple `Person` case class: + +```scala +case class Person(name: String) + +def speak(p: Person) = p match + case Person(name) if name == "Fred" => println(s"$name says, Yubba dubba doo") + case Person(name) if name == "Bam Bam" => println(s"$name says, Bam bam!") + case _ => println("Watch the Flintstones!") + +speak(Person("Fred")) // "Fred says, Yubba dubba doo" +speak(Person("Bam Bam")) // "Bam Bam says, Bam bam!" +``` + + +### Using a `match` expression as the body of a method + +Because `match` expressions return a value, they can be used as the body of a method. This method takes a `Boolean` value as an input parameter, and returns a `String`, based on the result of the `match` expression: + +```scala +def isTrue(a: Any) = a match + case 0 | "" => false + case _ => true +``` + +Because the input parameter `a` is defined to be the `Any` type — which is the root of all Scala classes, like `Object` in Java — this method works with any data type that’s passed in. After that, the body of the method is just two `case` statements, one that equates `0` or an empty string to `false`, and a default case that returns `true` for any other value. These examples show how this method works: + +```scala +isTrue(0) // false +isTrue("") // false +isTrue(1) // true +isTrue(" ") // true +isTrue(2F) // true +``` + +Using a `match` expression as the body of a method is a very common use. + + +#### Match expressions support many different types of patterns + +`match` expressions can work with many different types of patterns. The pattern types that can be matched are: + +- Constant +- Sequence +- Tuple +- Constructor +- Typed +- Default/wildcard + +All of these patterns are shown in the following `pattern` method, which takes an input parameter of tye `Any` and returns a `String`: + +```scala +def pattern(x: Any): String = x match + + // constant patterns + case 0 => "zero" + case true => "true" + case "hello" => "you said 'hello'" + case Nil => "an empty List" + + // sequence patterns + case List(0, _, _) => "a 3-element list with 0 as the first element" + case List(1, _*) => "list, starts with 1, has any number of elements" + case Vector(1, _*) => "vector, starts w/ 1, has any number of elements" + + // tuples + case (a, b) => s"got $a and $b" + case (a, b, c) => s"got $a, $b, and $c" + + // constructor patterns + case Person(first, "Alexander") => s"Alexander, first name = $first" + case Dog("Zeus") => "found a dog named Zeus" + + // typed patterns + case s: String => s"got a string: $s" + case i: Int => s"got an int: $i" + case f: Float => s"got a float: $f" + case a: Array[Int] => s"array of int: ${a.mkString(",")}" + case as: Array[String] => s"string array: ${as.mkString(",")}" + case d: Dog => s"dog: ${d.name}" + case list: List[_] => s"got a List: $list" + case m: Map[_, _] => m.toString + + // the default wildcard pattern + case _ => "Unknown" +``` + +`match` expressions and patterns are discussed in more detail in the Reference documentation. + + + +## try/catch/finally + +Like Java, Scala has a `try`/`catch`/`finally` construct to let you catch and manage exceptions. For consistency, Scala uses the same syntax that `match` expressions use: `case` statements to match the different possible exceptions that can occur. + +Here’s an example of Scala’s `try`/`catch`/`finally` syntax. In this example, `openAndReadAFile` is a method that does what its name implies: it opens a file and reads the text in it, assigning the result to the mutable variable `text`: + +```scala +var text = "" +try + text = openAndReadAFile(filename) +catch + case fnf: FileNotFoundException => fnf.printStackTrace() + case ioe: IOException => ioe.printStackTrace() +finally + // close your resources here + println("Came to the 'finally' clause.") +``` + +Assuming that the `openAndReadAFile` method uses the Java _java.io.*_ classes to read a file and doesn’t catch its exceptions, attempting to open and read a file can result in both a `FileNotFoundException` and an `IOException`, and those two exceptions are caught in the `catch` block of this example. + + + +## More information + +That covers the basics of Scala control structures. For more details, see the Reference documentation. + + + + + diff --git a/_overviews/overview/introduction.md b/_overviews/overview/introduction.md new file mode 100644 index 0000000000..eecc4e8670 --- /dev/null +++ b/_overviews/overview/introduction.md @@ -0,0 +1,11 @@ +--- +title: Introduction +description: This page begins the overview documentation of the Scala 3 language. +--- + +Welcome to the _Overview_ documentation for Scala 3. The goal of this documentation is to provide an informal introduction to the Scala language. It touches on all Scala topics, but as its name implies, generally just provides an overview of each feature. If at any time while you’re reading the Overview and you want more information on a specific feature, you’ll find links to our _Reference_ documentation, which covers all of the language features in detail. + +Our hope in these pages is to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax, and supports functional programming (FP), object-oriented programming (OOP), and a fusion of FP and OOP in a typed setting. Scala’s syntax, grammar, and features have been re-thought, debated in an open process, and updated in 2020 to be more clear and easier to understand than ever before. + +The Overview begins with a whirlwind tour of many of Scala’s features in the “A Taste of Scala” section. After that tour, the sections that follow it provide more details on those language features. + From d2887380914f6c8df1d8d2a3f9a25ec6fb122ec1 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 6 Oct 2020 18:55:38 -0600 Subject: [PATCH 0177/2265] Added the initial version of the Scala Features document --- _overviews/overview/scala-features.md | 496 ++++++++++++++++++++++++++ 1 file changed, 496 insertions(+) diff --git a/_overviews/overview/scala-features.md b/_overviews/overview/scala-features.md index e69de29bb2..9d487f85e6 100644 --- a/_overviews/overview/scala-features.md +++ b/_overviews/overview/scala-features.md @@ -0,0 +1,496 @@ +--- +title: Scala 3 Programming Language Features +description: This page discusses the main features of the Scala 3 programming language. +--- + + + +The name _Scala_ comes from the word _scalable_, and true to that name, the Scala language is used to power busy websites and analyze huge data sets. This section introduces the features that make Scala a scalable language. These features are split into three sections: + +- High-level language features +- Lower-level language features +- Scala ecosystem features + + + + + +## 1) High-level Scala language features + +Looking at Scala from the proverbial “30,000 foot view,” you can make the following statements about it: + +- It’s a high-level programming language +- It has an expressive syntax +- It’s statically-typed (but feels dynamic) +- It has an expressive type system +- It’s a pure functional programming (FP) language +- It’s a pure object-oriented programming (OOP) language +- It supports the fusion of FP and OOP +- Contextual abstractions provide a clear way to implement _term inference_ +- It runs on the JVM (and in the browser) +- It interacts seamlessly with Java code +- It’s used for server-side applications (including microservices), big data applications, and can also be used in the browser with Scala.js +- TODO: add something in this section or in the second section about the consistency of the language (I need help here) + +The following sections take a quick look at these features. + + +### It’s a high-level programming language + +Scala is considered a high-level language in at least two ways. First, like Java and many other modern languages, you don’t deal with low-level concepts like pointers and memory management. + +Second, with the use of lambdas and higher-order functions, you write your code at a very high level. As the functional programming saying goes, in Scala you write _what_ you want, not _how_ to achieve it. That is, we don’t write imperative code like this: + +```scala +def double(ints: List[Int]): List[Int] = { + val buffer = new ListBuffer[Int]() + for (i <- ints) { + buffer += i * 2 + } + buffer.toList + foo + bar +} + +val newNumbers = double(oldNumbers) +``` + +That code instructs the compiler what to do on a step-by-step basis. Instead, we write high-level, functional code using higher-order functions and lambdas like this to achieve the same effect: + +```scala +val newNumbers = oldNumbers.map(_ * 2) +``` + +As you can see, that code is much more concise, easier to read, and easier to maintain. + + +### It has an expressive syntax + +Scala has a concise, readable syntax that is often referred to as _expressive_. For instance, variables are created concisely: + +```scala +val nums = List(1,2,3) +val p = Person("Martin", "Odersky") +``` + +Higher-order functions and lambdas make for expressive code: + +```scala +nums.map(i => i * 2) // long form +nums.map(_ * 2) // short form + +nums.filter(i => i > 1) +nums.filter(_ > 1) +``` + +And traits, classes, and methods are defined with a clean, light syntax: + +```scala +trait Animal: + def speak(): Unit + +trait HasTail: + def wagTail(): Unit + +class Dog extends Animal, HasTail: + def speak() = println("Woof") + def wagTail() = println("⎞⎜⎛ ⎞⎜⎛") +``` + +Studies have shown that the time a developer spends _reading_ code to _writing_ code is at least a 10:1 ratio, so writing code that is concise _and_ readable is important. + + +### It’s statically-typed (but feels dynamic) + +Scala is a statically-typed language, but thanks to its type inference capabilities it feels dynamic. All of these expressions look like a dynamically-typed language like Python or Ruby, but they’re all Scala: + +```scala +val s = "Hello" +val p = Person("Al", "Pacino") +val sum = ints.reduceLeft(_ + _) +val y = for i <- nums yield i * 2 +val z = nums.filter(_ > 100) + .filter(_ < 10_000) + .map(_ * 2) +``` + +Because Scala is considered to be a [strong, statically-typed language](https://heather.miller.am/blog/types-in-scala.html), you get all the benefits of static types: + +- Correctness: you catch most errors at compile-time +- Great IDE support + - Code completion + - Catching errors at compile-time means catching mistakes as you type + - Easy and reliable refactoring + - Reliable code completion +- You can refactor your code with confidence +- Method type declarations tell readers what the method does, and help serve as documentation +- Types make your code easier to maintain +- Scalability: types help ensure correctness across arbitrarily large applications and development teams +- Strong types enable Scala features like implicits (TODO: I need help on this wording and description) + + + + +### Expressive type system + + +Scala’s expressive type system enforces, at compile-time, that abstractions are used in a safe and coherent manner. In particular, the type system supports: + +* [Generic classes](/tour/generic-classes.html) +* [Variance annotations](/tour/variances.html) +* [Upper](/tour/upper-type-bounds.html) and [lower](/tour/lower-type-bounds.html) type bounds +* [Inner classes](/tour/inner-classes.html) and [abstract type members](/tour/abstract-type-members.html) as object members +* [Compound types](/tour/compound-types.html) +* [Explicitly typed self references](/tour/self-types.html) +* [Implicit parameters](/tour/implicit-parameters.html) and [conversions](/tour/implicit-conversions.html) +* [Polymorphic methods](/tour/polymorphic-methods.html) +* [Type inference](/tour/type-inference.html) means the user is not required to annotate code with redundant type information. + +In combination, these features provide a powerful basis for the safe reuse of programming abstractions and for the type-safe extension of software. + + + + +### It’s a pure functional programming language + +Scala is a functional programming (FP) language, meaning: + +- Functions are variables, and can be passed around like any other variable +- Higher-order functions are directly supported +- Lambdas are built in +- Everything in Scala is an expression that returns a value +- Syntactically it’s easy to use immutable variables, and their use is encouraged +- It has a wealth of immutable collections classes in the standard library +- Those collections classes come with dozens of functional methods: they don’t mutate the collection, but instead return an updated copy of the data + + +### It’s a pure object-oriented programming language + +Scala is a _pure_ object-oriented programming (OOP) language. Every variable is an object, and every “operator” is a method. + +In Scala, all types inherit from a top-level class `Any`, whose immediate children are `AnyVal` (_value types_, such as `Int` and `Boolean`) and `AnyRef` (_reference types_, as in Java). This means that the Java distinction between primitive types and boxed types (e.g. `int` vs. `Integer`) isn’t present in Scala. Boxing and unboxing is completely transparent to the user. + + + + +### Scala supports the fusion of FP and OOP + + + +The essence of Scala is the fusion of functional programming and object-oriented programming in a typed settings: + +- Functions for the logic +- Objects for the modularity + +As [Martin Odersky has stated](https://jaxenter.com/current-state-scala-odersky-interview-129495.html), “Scala was designed to show that a fusion of functional and object-oriented programming is possible and practical.” + +For more details on this philosophy, see the TODO section in the Reference documentation. + + +### Contextual abstractions provide a clear way to implement term inference + +Following Haskell, Scala was the second popular language to have some form of _implicits_. In Scala 3 these concepts have been completely re-thought and more clearly implemented. + +The core idea is _term inference_: Given a type, the compiler synthesizes a “canonical” term that has that type. In Scala, an implicit parameter directly leads to an inferred argument term that could also be written down explicitly. + +Use cases for this concept include implementing type classes, establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them. + +Scala 3 makes this process more clear than ever before. See the TODO section of the Reference documentation for more details. + + +### Scala runs on the JVM (and in the browser) + +Scala code runs on the Java Virtual Machine (JVM), so you get all of its benefits: + +- Security +- Performance +- Memory management +- Portability and platform independence +- The ability to use the wealth of existing Java and JVM libraries + +In addition to running on the JVM, Scala also runs in the browser with Scala.js (and open source third-party tools to integrate popular JavaScript libraries), and native executables can be built with Scala Native and GraalVM. + + +### Interacts seamlessly with Java + +You can use Java classes and libraries in your Scala applications, and you can use Scala code in your Java applications. In regards to the second point, large libraries like [Akka](https://akka.io) and the [Play Framework](https://www.playframework.com) are written in Scala, and can be used in Java applications. + +In regards to the first point, Java classes and libraries are used in Scala applications every day. For instance, in Scala you can read files with a Java `BufferedReader` and `FileReader`: + +```scala +import java.io._ +val br = BufferedReader(FileReader(filename)) +// read the file with `br` ... +``` + +Using Java code in Scala is generally seamless. + +Java collections can also be used in Scala, and if you want to use Scala’s rich collection class methods with them, you can convert them with just a few lines of code: + +```scala +import scala.jdk.CollectionConverters._ +val scalaList: Seq[Integer] = JavaClass.getJavaList().asScala.toSeq +``` + + +### Used for server-side apps, big data, Scala.js + +As you’ll see in the third section of this page, Scala libraries and frameworks like these have been written to power busy websites and work with huge datasets: + +1. The [Play Framework](https://www.playframework.com) is a lightweight, stateless, developer-friendly, web-friendly architecture for creating highly-scalable applications +2. [Lagom](https://www.lagomframework.com) is a microservices framework that helps you decompose your legacy monolith and build, test, and deploy entire systems of reactive microservices +3. [Apache Spark](https://spark.apache.org) is a unified analytics engine for big data processing, with built-in modules for streaming, SQL, machine learning and graph processing + +The [Awesome Scala list](https://github.com/lauris/awesome-scala) shows dozens of additional open source tools that developers have created to build Scala applications. + +In addition to server-side programming, [Scala.js](https://www.scala-js.org) is a strongly-typed replacement for writing JavaScript, with open source third-party libraries that include tools to integrate with Facebook’s React library, jQuery, and more. + + + + +## 2) Lower-level language features + +Where the previous section covered high-level features of Scala 3, it’s interesting to note that at a high level you can make the same statements about both Scala 2 and Scala 3. A decade ago Scala started with a strong foundation of desirable features, and as you’ll see in this section, those benefits have been improved with Scala 3. + +At a “sea level” view of the details — i.e., the language features programmers use everyday — Scala 3 has significant advantages over Scala 2: + +- The ability to create algebraic data types (ADTs) more concisely with enums +- An even more concise and readable syntax: + - The “quiet” control structure syntax is easier to read + - Optional braces + - Fewer symbols in the code creates less visual noise, making it easier to read + - The `new` keyword is generally no longer needed when creating class instances + - The formality of package objects have been dropped in favor of simpler “top level” definitions +- A clearer grammar: + - Multiple different uses of the `implicit` keyword have been removed + - Those uses are replaced by more obvious keywords like `given`, `using`, and `extension`, focusing on intent over mechanism + - Extension methods replace implicit classes with a clearer and simpler mechanism + - The addition of the `open` modifier for classes makes the developer intentionally declare that a class is open for modification, thereby limiting ad-hoc extensions to a code base + - Multiversal equality rules out nonsensical comparisons with `==` and `!=` (i.e., attempting to compare a `Person` to a `Planet`) + - Macros are implemented much more easily + - TODO: Benefits of Union and intersection types (I need help here) + - Trait parameters replace and simplify early initializers + - Opaque type aliases replace most uses of value classes, while guaranteeing the absence of boxing + - Export clauses provide a simple and general way to express aggregation, which can replace the previous facade pattern of package objects inheriting from classes + - The procedure syntax has been dropped, and the varargs syntax has been changed, both to make the language more consistent + - The `@infix` annotation makes it obvious how you want a method to be applied + - The `@alpha` method annotation defines an alternate name for the method, improving Java interoperability, and letting you provide aliases for symbolic operators + +It would take too much space to demonstrate all of those features here, but follow the links in those items above to see those features in action. + + + + + + + + +## 3) Scala ecosystem features + +Scala has a vibrant ecosystem, with libraries and frameworks for every need. The [“Awesome Scala” list](https://github.com/lauris/awesome-scala) provides a list of hundreds of open source projects that are available to Scala developers. Some of the more notable are listed below. + + + + +### Web development + +- The [Play Framework](https://www.playframework.com) followed the Ruby on Rails model to become a lightweight, stateless, developer-friendly, web-friendly architecture for highly-scalable applications +- [Scalatra](https://scalatra.org) is a tiny, high-performance, async web framework, inspired by Sinatra +- [Finatra](https://twitter.github.io/finatra) is Scala services built on TwitterServer and Finagle +- [Scala.js](https://www.scala-js.org) is a strongly-typed replacement for JavaScript that provides a safer way to build robust front-end web applications +- [ScalaJs-React](https://github.com/japgolly/scalajs-react) lifts Facebook’s React library into Scala.js, and endeavours to make it as type-safe and Scala-friendly as possible +- [Lagom](https://www.lagomframework.com) is a microservices framework that helps you decompose your legacy monolith and build, test, and deploy entire systems of Reactive microservices + +HTTP(S) libraries: + +- Akka-http +- Finch +- Http4s +- Sttp + +JSON libraries: + +- Argonaut +- Circe +- Jackson/Scala +- Json4s +- Jsoniter +- Play-JSON + +Serialization: + +- ScalaPB + +Science and data analysis: + +- Algebird +- Spire +- Squants + + +### Big data + +- Spark +- Apache Flink +- SCIO, A Scala API for Apache Beam and Google Cloud Dataflow. + + +### AI, machine learning + +- BigDL, Distributed Deep Learning Framework for Apache Spark +- TensorFlow- Scala + + +### Concurrency + +- Akka + - Actor model + - Concurrency + - High throughput + + +### FP + +- Cats +- Zio + + +### Functional reactive programming + +- fs2 +- monix +- ScalaRx + + +### Build tools + +- sbt +- Gradle +- Mill +- Fury? + + + +## Summary + +As this page shows, Scala has many terrific programming language features at a high level, at an everyday programming level, and through its developer ecosystem. + + + + From 8995017de99b4745ba791d3491643fd45d272d58 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Thu, 8 Oct 2020 15:19:28 -0600 Subject: [PATCH 0178/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98Interacting=20With=20Java=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/interacting-with-java.md | 368 +++++++++++++++++++ 1 file changed, 368 insertions(+) diff --git a/_overviews/overview/interacting-with-java.md b/_overviews/overview/interacting-with-java.md index e69de29bb2..df8c7e4555 100644 --- a/_overviews/overview/interacting-with-java.md +++ b/_overviews/overview/interacting-with-java.md @@ -0,0 +1,368 @@ +--- +title: Interacting with Java +description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. +--- + + +## Introduction + +This section looks at how to use Java code in Scala, and the opposite, how to use Scala code in Java. + +In general, using Java code in Scala is pretty seamless. There are only a few points where you’ll want to use Scala utilities to convert Java concepts to Scala, including: + +- Java collections classes +- The Java `Optional` class + +Similarly, if you’re writing Java code and want to use Scala concepts, you’ll want to convert Scala collections and the Scala `Option` class. + +These following sections demonstrate the most common conversions you’ll need: + +- How to use Java collections in Scala +- How to use Java `Optional` in Scala +- Extending Java interfaces in Scala +- How to use Scala collections in Java +- How to use Scala `Option` in Java +- How to use Scala traits in Java +- How to handle Scala methods that throw exceptions in Java code +- How to use Scala varargs parameters in Java +- Create alternate names to use Scala methods in Java + +Note that the Java examples in this section assume that you’re using Java 11 or newer. + + + +## How to use Java collections in Scala + +When you’re writing Scala code and need to use a Java collection class, you _can_ just use the class as-is. However, if you want to use the class in a Scala `for` loop, or want to take advantage of the higher-order functions on the Scala collections classes, you’ll want to convert the Java collection to a Scala collection. + +Here’s an example of how this works. Given this Java `ArrayList`: + + +```java +// java +public class JavaClass { + public static List getStrings() { + return new ArrayList(List.of("a", "b", "c")); + } +} +``` + +You can convert that Java list to a Scala `Seq`, using the conversion utilities in the Scala _scala.jdk.CollectionConverters_ package: + + +```scala +// scala +import scala.jdk.CollectionConverters._ +import java.util.List + +def testList = + println("Using a Java List in Scala") + val javaList: java.util.List[String] = JavaClass.getStrings() + val scalaSeq: Seq[String] = javaList.asScala.toSeq + scalaSeq.foreach(println) + for s <- scalaSeq do println(s) +``` + +Of course that code can be shortened, but the individual steps are shown here to demonstrate exactly how the conversion process works. + + + +## How to use Java `Optional` in Scala + +When you need to use the Java `Optional` class in your Scala code, import the _scala.jdk.OptionConverters_ object, and then use the `toScala` method to convert the `Optional` value to a Scala `Option`. + +To demonstrate this, here’s a Java class with two `Optional` values, one containing a string and the other one empty: + + +```java +// java +import java.util.Optional; + +public class JavaClass { + static Optional oString = Optional.of("foo"); + static Optional oEmptyString = Optional.empty(); +} +``` + +Now in your Scala code you can access those fields. If you just access them directly, they’ll both be `Optional` values: + + +```scala +// scala +import java.util.Optional + +val optionalString = JavaClass.oString // Optional[foo] +val eOptionalString = JavaClass.oEmptyString // Optional.empty +``` + +But by using the _scala.jdk.OptionConverters_ methods, you can convert them to Scala `Option` values: + + +```scala +import java.util.Optional +import scala.jdk.OptionConverters._ + +val optionalString = JavaClass.oString // Optional[foo] +val optionString = optionalString.toScala // Some(foo) + +val eOptionalString = JavaClass.oEmptyString // Optional.empty +val eOptionString = eOptionalString.toScala // None +``` + + + +## Extending Java interfaces in Scala + +If you need to use Java interfaces in your Scala code, extend them just as though they are Scala traits. For example, given these three Java interfaces: + + +```java +// java +interface Animal { + void speak(); +} + +interface Wagging { + void wag(); +} + +interface Running { + // an implemented method + default void run() { + System.out.println("I’m running"); + } +} +``` + +you can create a `Dog` class in Scala just as though you were using traits. All you have to do is implement the `speak` and `wag` methods: + + +```scala +// scala +class Dog extends Animal, Wagging, Running: + def speak = println("Woof") + def wag = println("Tail is wagging") + +@main def useJavaInterfaceInScala = + val d = new Dog + d.speak + d.wag +``` + + + +## How to use Scala collections in Java + +When you need to use a Scala collection class in your Java code, use the methods of Scala’s _scala.javaapi.CollectionConverters_ object in your Java code to make the conversions work. For example, if you have a `List[String]` like this in a Scala class: + + +```scala +// scala +class ScalaClass: + val strings = List("a", "b") +``` + +You can access that Scala `List` in your Java code like this: + + +```java +// java +import scala.jdk.javaapi.CollectionConverters; + +// create an instance of the Scala class +ScalaClass sc = new ScalaClass(); + +// access the `strings` field as `sc.strings()` +scala.collection.immutable.List xs = sc.strings(); + +// convert the Scala `List` a Java `List` +java.util.List listOfStrings = CollectionConverters.asJava(xs); +listOfStrings.forEach(System.out::println); +``` + +That code can be shortened, but the full steps are shown to demonstrate how the process works. Here are a few things to notice in that code: + +- In your Java code, you create an instance of `ScalaClass` just like an instance of a Java class +- `ScalaClass` has a field named `strings`, but from Java you access that field as a method, i.e., as `sc.strings()` + + + +## How to use Scala `Option` in Java + +When you need to use a Scala `Option` in your Java code, you can convert the `Option` to a Java `Optional` value using the `toJava` method of the Scala _scala.jdk.javaapi.OptionConverters_ object. + +To demonstrate this, create a Scala class with two `Option[String]` values, one containing a string and the other one empty: + + +```scala +// scala +object ScalaObject: + val someString = Option("foo") + val noneString: Option[String] = None +``` + +Then in your Java code, convert those `Option[String]` values into `java.util.Optional[String]` using the `toJava` method from the _scala.jdk.javaapi.OptionConverters_ object: + + +```java +// java +import java.util.Optional; +import static scala.jdk.javaapi.OptionConverters.toJava; + +public class JUseScalaOptionInJava { + public static void main(String[] args) { + Optional stringSome = toJava(ScalaObject.someString()); // Optional[foo] + Optional stringNone = toJava(ScalaObject.noneString()); // Optional.empty + System.out.printf("stringSome = %s\n", stringSome); + System.out.printf("stringNone = %s\n", stringNone); + } +} +``` + +The two Scala `Option` fields are now available as Java `Optional` values. + + + +## How to use Scala traits in Java + +With Java 11 you can use a Scala trait just like a Java interface, even if the trait has implemented methods. For example, given these two Scala traits, one with an implemented method and one with only an interface: + + +```scala +// scala +trait ScalaAddTrait: + def sum(x: Int, y: Int) = x + y // implemented + +trait ScalaMultiplyTrait: + def multiply(x: Int, y: Int): Int // abstract +``` + +A Java class can implement both of those interfaces, and implement the `multiply` method: + + +```java +// java +class JavaMath implements ScalaAddTrait, ScalaMultiplyTrait { + public int multiply(int a, int b) { + return a * b; + } +} + +JavaMath jm = new JavaMath(); +System.out.println(jm.sum(3,4)); // 7 +System.out.println(jm.multiply(3,4)); // 12 +``` + + + +## How to handle Scala methods that throw exceptions in Java code + +When you’re writing Scala code using Scala programming idioms, you’ll never write a method that throws an exception. But if for soem reason you have a Scala method that does throw an exception, and you want Java developers to be able to use that method, add the `@throws` annotation to your Scala method so Java consumers will know the exceptions they can throw. + +For example, this Scala `exceptionThrower` method is annotated to declare that it throws an `Exception`: + + +```scala +// scala +object SExceptionThrower: + @throws(classOf[Exception]) + def exceptionThrower = + throw new Exception("Idiomatic Scala methods don’t throw exceptions") +``` + +As a result, you’ll need to handle the exception in your Java code. For instance, this code won’t compile because I don’t handle the exception: + + +```java +// java: won’t compile because the exception isn’t handled +public class ScalaExceptionsInJava { + public static void main(String[] args) { + SExceptionThrower.exceptionThrower(); + } +} +``` + +The compiler gives this error: + +.... +[error] ScalaExceptionsInJava: unreported exception java.lang.Exception; + must be caught or declared to be thrown +[error] SExceptionThrower.exceptionThrower() +.... + +This is good — it’s what you want: the annotation tells the Java compiler that `exceptionThrower` can throw an exception. Now when you’re writing Java code you must handle the exception with a `try` block or declare that your Java method throws an exception. + +Conversely, if you leave the annotation off of the Scala `exceptionThrower` method, the Java code _will compile_. This is probably not what you want, because the Java code may not account for the Scala method throwing the exception. + + + +## How to use Scala varargs parameters in Java + +When a Scala method has a varargs parameter and you want to use that method in Java, mark the Scala method with the `@varargs` annotation. For example, the `printAll` method in this Scala class declares a `String*` varargs field, and the method is marked with the `@varargs` annotation: + + +```scala +// scala +import scala.annotation.varargs + +object VarargsPrinter: + @varargs def printAll(args: String*): Unit = args.foreach(println) +``` + +Because `printAll` is declared with the `@varargs` annotation, it can be called from a Java program with a variable number of parameters, as shown in this example: + + +```scala +// java +public class JVarargs { + public static void main(String[] args) { + VarargsPrinter.printAll("Hello", "world"); + } +} + +``` + +When this code is run, it results in the following output: + +.... +Hello +world +.... + + + +## Create alternate names to use Scala methods in Java + +In Scala you might want to create a method name using a symbolic character: + + +```scala +def +(a: Int, b: Int) = a + b +``` + +That method name won’t work well in Java, but what you can do in Scala 3 is provide an “alternate” name for the method — an alias — that will work in Java: + + +```scala +import scala.annotation.alpha + +class Adder: + @alpha("add") def +(a: Int, b: Int) = a + b +``` + +Now in your Java code you can use the aliased method name `add`: + +```scala +var adder = new Adder(); +int x = adder.add(1,1); +System.out.printf("x = %d\n", x); +``` + + + +## More information + +This section highlights some of the main topics to know when integrating Scala and Java code bases. For more details, including a few other topics not covered here, see the _Interacting with Java_ section in the Reference documentation. + + + From d53ad0e17f5b76ce732831b2b7449d8880b0070a Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Thu, 8 Oct 2020 16:00:09 -0600 Subject: [PATCH 0179/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98First=20Look=20at=20Types=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/first-look-at-types.md | 237 +++++++++++++++++++++ 1 file changed, 237 insertions(+) diff --git a/_overviews/overview/first-look-at-types.md b/_overviews/overview/first-look-at-types.md index e69de29bb2..4cb7ca6ef9 100644 --- a/_overviews/overview/first-look-at-types.md +++ b/_overviews/overview/first-look-at-types.md @@ -0,0 +1,237 @@ +--- +title: A First Look at Scala Types +description: This page provides a brief introduction to Scala's built-in data types, including Int, Double, String, Long, Any, AnyRef, Nothing, and Null. +--- + + + +## All values have a type + +In Scala, all values have a type, including numerical values and functions. The diagram below illustrates a subset of the type hierarchy. + + +Scala Type Hierarchy + + + +## Scala type hierarchy + +[`Any`](https://www.scala-lang.org/api/2.12.1/scala/Any.html) is the supertype of all types, also called the top type. It defines certain universal methods such as `equals`, `hashCode`, and `toString`. `Any` has two direct subclasses: `AnyVal` and `AnyRef`. + +*`AnyVal`* represents value types. There are nine predefined value types and they are non-nullable: `Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit`, and `Boolean`. `Unit` is a value type which carries no meaningful information. There is exactly one instance of `Unit` which can be declared literally like so: `()`. All functions must return something so sometimes `Unit` is a useful return type. + +*`AnyRef`* represents reference types. All non-value types are defined as reference types. Every user-defined type in Scala is a subtype of `AnyRef`. If Scala is used in the context of a Java runtime environment, `AnyRef` corresponds to `java.lang.Object`. + +Here’s an example that demonstrates that strings, integers, characters, boolean values, and functions are all objects just like every other object: + +```tut +val list: List[Any] = List( + "a string", + 732, // an integer + 'c', // a character + true, // a boolean value + () => "an anonymous function returning a string" +) + +list.foreach(element => println(element)) +``` + +It defines a value `list` of type `List[Any]`. The list is initialized with elements of various types, but each is an instance of `scala.Any`, so you can add them to the list. + +Here’s the output of the program: + +``` +a string +732 +c +true + +``` + + + +## Scala’s “value types” + +As shown above, Scala’s numeric types extend `AnyVal`, and they’re all full-blown objects. These examples show how to declare variables of these numeric types: + +```scala +val b: Byte = 1 +val i: Int = 1 +val l: Long = 1 +val s: Short = 1 +val d: Double = 2.0 +val f: Float = 3.0 +``` + +In the first four examples, if you don’t explicitly specify a type, the number `1` will default to an `Int`, so if you want one of the other data types — `Byte`, `Long`, or `Short` — you need to explicitly declare those types, as shown. Numbers with a decimal (like 2.0) will default to a `Double`, so if you want a `Float` you need to declare a `Float`, as shown in the last example. + +Because `Int` and `Double` are the default numeric types, you typically create them without explicitly declaring the data type: + +```scala +val i = 123 // defaults to Int +val x = 1.0 // defaults to Double +``` + +In your code you can also append the characters `L`, `D`, and `F` (and their lowercase equivalents) to numbers to specify that they are `Long`, `Double`, or `Float` values: + +```scala +val x = 1_000L // val x: Long = 1000 +val y = 2.2D // val y: Double = 2.2 +val z = 3.3F // val z: Float = 3.3 +``` + +Scala also has `String` and `Char` types, which you can generally declare with the implicit form: + +```scala +val s = "Bill" +val c = 'a' +``` + +As shown, enclose strings in double-quotes — or triple-quotes for multiline strings — and enclose a character in single-quotes. + +Those data types and their ranges are: + +| Data Type | Possible Values | +| ------------- | --------------- | +| Boolean | `true` or `false` | +| Byte | 8-bit signed two’s complement integer (-2^7 to 2^7-1, inclusive)
-128 to 127 | +| Short | 16-bit signed two’s complement integer (-2^15 to 2^15-1, inclusive)
-32,768 to 32,767 +| Int | 32-bit two’s complement integer (-2^31 to 2^31-1, inclusive)
-2,147,483,648 to 2,147,483,647 | +| Long | 64-bit two’s complement integer (-2^63 to 2^63-1, inclusive)
(-2^63 to 2^63-1, inclusive) | +| Float | 32-bit IEEE 754 single-precision float
1.40129846432481707e-45 to 3.40282346638528860e+38 | +| Double | 64-bit IEEE 754 double-precision float
4.94065645841246544e-324d to 1.79769313486231570e+308d | +| Char | 16-bit unsigned Unicode character (0 to 2^16-1, inclusive)
0 to 65,535 | +| String | a sequence of `Char` | + + + +## `BigInt` and `BigDecimal` + +When you need really large numbers, use the `BigInt` and `BigDecimal` types: + +```scala +var a = BigInt(1_234_567_890_987_654_321L) +var b = BigDecimal(123_456.789) +``` + +Where `Double` and `Float` are approximate decimal numbers, `BigDecimal` is used for precise arithmetic, such as when working with currency. + +A great thing about `BigInt` and `BigDecimal` is that they support all the operators you’re used to using with numeric types: + +```scala +val b = BigInt(1234567890) // scala.math.BigInt = 1234567890 +val c = b + b // scala.math.BigInt = 2469135780 +val d = b * b // scala.math.BigInt = 1524157875019052100 +``` + + + +## Two notes about strings + +Scala strings are similar to Java strings, but they have two great additional features: + +- They support string interpolation +- It’s easy to create multiline strings + +### String interpolation + +String interpolation provides a very readable way to use variables inside strings. For instance, given these three variables: + +```scala +val firstName = "John" +val mi = 'C' +val lastName = "Doe" +``` + +You can combine those variables in a string like this: + +```scala +println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" +``` + +Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. + +To enclose expressions inside a string, put them in curly braces: + +~~~ scala +println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" +val x = -1 +println(s"x.abs = ${x.abs}") // prints "x.abs = 1" +~~~ + +#### Other interpolators + +The `s` that you place before the string is just one possible interpolator. If you use an `f` instead of an `s`, you can use `printf`-style formatting in the string. Furthermore, because `s` and `f` are really just methods, you can write your own interpolators, such as creating a `sql` interpolator for use in a database library. For more details, see the Strings section in this Overview and in the Reference documentation. + + +### Multiline strings + +Multiline strings are created by including the string inside three double-quotes: + +```scala +val quote = """The essence of Scala: + Fusion of functional and object-oriented + programming in a typed setting.""" +``` + +One drawback of this basic approach is that the lines after the first line are indented, and look like this: + +```scala +"The essence of Scala: + Fusion of functional and object-oriented + programming in a typed setting." +``` + +When spacing is important, put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: + +```scala +val quote = """The essence of Scala: + |Fusion of functional and object-oriented + |programming in a typed setting.""".stripMargin +``` + +Now all of the lines are left-justified inside the string: + +```scala +"The essence of Scala: +Fusion of functional and object-oriented +programming in a typed setting." +``` + + + +## Type casting + + +Value types can be cast in the following way: +Scala Type Hierarchy + +For example: + +```tut +val x: Long = 987654321 +val y: Float = x // 9.8765434E8 (note that some precision is lost in this case) + +val face: Char = '☺' +val number: Int = face // 9786 +``` + +Casting is unidirectional. This will not compile: + +``` +val x: Long = 987654321 +val y: Float = x // 9.8765434E8 +val z: Long = y // Does not conform +``` + +You can also cast a reference type to a subtype. This will be covered later in the tour. + + + +## `Nothing` and `null` + +`Nothing` is a subtype of all types, also called the bottom type. There is no value that has the type `Nothing`. A common use is to signal non-termination, such as a thrown exception, program exit, or an infinite loop — i.e., it is the type of an expression which does not evaluate to a value, or a method that does not return normally. + +`Null` is a subtype of all reference types (i.e. any subtype of `AnyRef`). It has a single value identified by the keyword literal `null`. `Null` is provided mostly for interoperability with other JVM languages and should almost never be used in Scala code. Alternatives to `null` are discussed in the TODO section of the Overview and the Reference documentation. + + From 8dc7054e521f14560e2c190dee8e060edd76eda6 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Thu, 8 Oct 2020 16:03:57 -0600 Subject: [PATCH 0180/2265] =?UTF-8?q?Moved=20some=20of=20the=20Types=20con?= =?UTF-8?q?tent=20to=20the=20=E2=80=98First=20Look=20at=20Types=E2=80=99?= =?UTF-8?q?=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/a-taste-of-scala.md | 27 ++----------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index 9d054cf6b1..4e3cec09c3 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -259,7 +259,7 @@ println(s"x.abs = ${x.abs}") // prints "x.abs = 1" #### Other interpolators -The `s` that you place before the string is just one possible interpolator. If you use an `f` instead of an `s`, you can use `printf`-style formatting in the string. Furthermore, because `s` and `f` are really just methods, you can write your own interpolators, such as creating a `sql` interpolator for use in a database library. For more details, see the Strings section in this Overview and in the Reference documentation. +The `s` that you place before the string is just one possible interpolator. If you use an `f` instead of an `s`, you can use `printf`-style formatting syntax in the string. Furthermore, because `s` and `f` are really just methods, you can write your own interpolators, such as creating a `sql` interpolator for use in a database library. For more details, see the Strings section in this Overview and in the Reference documentation (TODO:correct sections and their urls). ### Multiline strings @@ -272,30 +272,7 @@ val quote = """The essence of Scala: programming in a typed setting.""" ``` -One drawback of this basic approach is that the lines after the first line are indented, and look like this: - -```scala -"The essence of Scala: - Fusion of functional and object-oriented - programming in a typed setting." -``` - -When spacing is important, put a `|` symbol in front of all lines after the first line, and call the `stripMargin` method after the string: - -```scala -val quote = """The essence of Scala: - |Fusion of functional and object-oriented - |programming in a typed setting.""".stripMargin -``` - -Now all of the lines are left-justified inside the string: - -```scala -"The essence of Scala: -Fusion of functional and object-oriented -programming in a typed setting." -``` - +The [“First Look at Types” section](TODO:url) provides more details on how to format multiline strings. From ab04eec3e1c82baa4f9b212329c21a71d9733a05 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sun, 11 Oct 2020 15:09:23 -0600 Subject: [PATCH 0181/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98Collections=20Classes=20and=20Methods=E2=80=99=20docum?= =?UTF-8?q?ent.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../overview/collections-classes-methods.md | 871 ++++++++++++++++++ 1 file changed, 871 insertions(+) diff --git a/_overviews/overview/collections-classes-methods.md b/_overviews/overview/collections-classes-methods.md index e69de29bb2..717006e96f 100644 --- a/_overviews/overview/collections-classes-methods.md +++ b/_overviews/overview/collections-classes-methods.md @@ -0,0 +1,871 @@ +--- +title: Common Collections Classes and Methods +description: This page demonstrates the common collections classes and their methods in Scala 3. +--- + + + + +This page demonstrates the common Scala 3 collections classes and their accompanying methods. Scala comes with a wealth of collections classes, but you can go a long way by starting with just a few classes, and using the others as needed. Similarly, each class has dozens of functional methods to make your life easier, but you can achieve a lot by starting with just a handful of them. + +Therefore, this section introduces and demonstrates the most common classes and methods that you’ll need to get started. When you need to understand more classes or more methods, see the Reference documentation for all the details. + + + +## Three main categories of collections classes + +Looking at the Scala collections classes from a high level, there are three main categories to choose from: + +- Sequences +- Maps +- Sets + +A _sequence_ is a linear collection of elements and may be _indexed_ (like an array) or _linear_ (like a linked list). A _map_ contains a collection of key/value pairs, like a Java `Map`, Python dictionary, or Ruby `Hash`. A _set_ is a sequence that contains no duplicate elements. All of those classes have basic types, as well as subsets of those types for specific purposes, such as concurrency, caching, and streaming. + +In addition to these three main categories, there are other useful collection types, including ranges, stacks, and queues. Ranges are demonstrated later in this section. + +The following sections introduce the basic classes you’ll use on a regular basis. + +There are a few other classes that act like collections, including tuples, enumerations, and the `Option`, `Try`, and `Either` families of classes. See the TODO section(s) for more details on these classes. + + + +## Common collections classes + +The main collections classes you’ll use on a regular basis are: + +| Class | Immutable | Mutable | Description | +| ------------- | --------- | ------- | ----------- | +| `List` | ✓ | | A linear (linked list), immutable sequence | +| `Vector` | ✓ | | An indexed, immutable sequence | +| `LazyList` | ✓ | | A lazy immutable linked list, its elements are computed only when they’re needed; Good for large or infinite sequences. | +| `ArrayBuffer` | | ✓ | The go-to class for a mutable, indexed sequence | +| `ListBuffer` | | ✓ | Used when you want a mutable `List`; typically converted to a `List` | +| `Map` | ✓ | ✓ | An iterable sequence that consists of pairs of keys and values. | +| `Set` | ✓ | ✓ | An iterable collection with no duplicate elements | + +As shown, `Map` and `Set` come in both immutable and mutable versions. + +The basics of each class are demonstrated in the following sections. + +>In Scala, a _buffer_ — such as `ArrayBuffer` and `ListBuffer` — is a sequence that can grow and shrink. + + + +### A note about immutable collections + +In the sections that follow, whenever the word _immutable_ is used, it’s safe to assume that the class is intended for use in a _functional programming_ (FP) style. With these classes you don’t modify the collection; you apply functional methods to the collection to create a new result. + + + +## Choosing a sequence class + +When choosing a _sequence_ class — a sequential collection of elements — you have two main decisions: + +- Should the sequence be indexed (like an array), allowing rapid access to any element, or should it be implemented as a linear linked list? +- Do you want a mutable or immutable collection? + +The recommended, general-purpose, “go to” sequential collections for the combinations of mutable/immutable and indexed/linear are shown here: + +| Type/Category | Immutable | Mutable | +| --------------------- | --------- | ------------ | +| Indexed | `Vector` |`ArrayBuffer` | +| Linear (Linked lists) | `List` |`ListBuffer` | + +For example, if you need an immutable, indexed collection, in general you should use a `Vector`. Conversely, if you need a mutable, indexed collection, use an `ArrayBuffer`. + +>`List` and `Vector` are often used when writing code in a functional style. `ArrayBuffer` is commonly used when writing code in a mutable style. `ListBuffer` is used when you’re mixing styles, such as building a list + +The next several sections briefly demonstrate the `List`, `Vector`, and `ArrayBuffer` classes. + + + +## The `List` class + +[The List class](https://www.scala-lang.org/api/current/scala/collection/immutable/List.html) is a linear, immutable sequence. This just means that it’s a linked-list that you can’t modify. Any time you want to add or remove `List` elements, you create a new `List` from an existing `List`. + +### Creating Lists + +This is how you create an initial `List`: + +```scala +val ints = List(1, 2, 3) +val names = List("Joel", "Chris", "Ed") +``` + +You can also declare the `List`’s type, if you prefer, though it generally isn’t necessary: + +```scala +val ints: List[Int] = List(1, 2, 3) +val names: List[String] = List("Joel", "Chris", "Ed") +``` + +One exception is when you have mixed types in a collection; in that case you may want to explicitly specify its type: + +```scala +val things: List[Any] = List(1, "two", 3.0) +``` + +### Adding elements to a List + +Because `List` is immutable, you can’t add new elements to it. Instead you create a new list by prepending or appending elements to an existing `List`. For instance, given this `List`: + +```scala +val a = List(1,2,3) +``` + +You _prepend_ one element with `+:`, and multiple elements with `++:`, as shown here: + +```scala +val b = 0 +: a // List(0, 1, 2, 3) +val c = List(-1, 0) ++: a // List(-1, 0, 1, 2, 3) +``` + +You can also _append_ elements to a `List`, but because `List` is a singly-linked list, you should really only prepend elements to it; appending elements to it is a relatively slow operation, especially when you work with large sequences. + +>Tip: If you want to prepend and append elements to an immutable sequence, use `Vector` instead. + +Because `List` is a linked-list class, you shouldn’t try to access the elements of large lists by their index value. For instance, if you have a `List` with one million elements in it, accessing an element like `myList(999_999)` will take a relatively long time, because that request has to traverse all those elements. If you have a large collection and want to access elements by their index, use a `Vector` or `ArrayBuffer` instead. + +### How to remember the method names + +These days IDEs help us out tremendously, but one way to remember those method names is to think that the `:` character represents the side that the sequence is on, so when you use `+:` you know that the list needs to be on the right, like this: + +```scala +0 +: a +``` + +Similarly, when you use `:+` you know the list needs to be on the left: + +```scala +a :+ 4 +``` + +As explained in the Reference documentation, there are more technical ways to think about this, but this can be a helpful way to remember the method names. + +Also, a good thing about these symbolic method names is that they’re consistent. The same method names are used with other immutable sequence classes, such as `Seq` and `Vector`. You can also use non-symbolic method names to append and prepend elements, if you prefer. + +### How to loop over lists + +Given a `List` of names: + +```scala +val names = List("Joel", "Chris", "Ed") +``` + +you can print each string like this: + +```scala +for name <- names do println(name) +``` + +This is what it looks like in the REPL: + +```scala +scala> for name <- names do println(name) +Joel +Chris +Ed +``` + +A great thing about using `for` loops with collections is that Scala is consistent, and the same approach works with all sequence classes, including `Array`, `ArrayBuffer`, `List`, `Seq`, `Vector`, `Map`, `Set`, etc. + +### A little bit of history + +For those interested in a little bit of history, the `List` class is similar to the `List` from [the Lisp programming language](https://en.wikipedia.org/wiki/Lisp_(programming_language)), which was originally specified in 1958. Indeed, in addition to creating a `List` like this: + +```scala +val ints = List(1, 2, 3) +``` + +you can also create the exact same list this way: + +```scala +val list = 1 :: 2 :: 3 :: Nil +``` + +The REPL shows how this works: + +```scala +scala> val list = 1 :: 2 :: 3 :: Nil +list: List[Int] = List(1, 2, 3) +``` + +This works because a `List` is a singly-linked list that ends with the `Nil` element, and `::` is a `List` class method that works like Lisp’s “cons” operator. For more details on lists, see the Reference documentation. + + +### Aside: The LazyList + +The Scala collections also include a [LazyList](https://www.scala-lang.org/api/current/scala/collection/immutable/LazyList.html), which is a _lazy_ immutable linked list. It’s called “lazy” — or non-strict — because it computes its elements only when they are needed. + +You can see how lazy a `LazyList` is in the REPL: + +```scala +val x = LazyList.range(1, Int.MaxValue) +x.take(1) // LazyList() +x.take(5) // LazyList() +x.map(_ + 1) // LazyList() +``` + +In all of those examples, nothing happens. Indeed, nothing will happen until you force it to happen, such as by calling its `foreach` method: + +```` +scala> x.take(1).foreach(println) +1 +```` + +For more information on the uses, benefits, and drawbacks of strict and non-strict (lazy) collections, see the Reference documentation. + + + + + +## The Vector class + +[The Vector class](https://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html) is an indexed, immutable sequence. The “indexed” part of the description means that it provides random access and updates in effectively constant time, so you can access `Vector` elements rapidly by their index value, such as accessing `listOfPeople(123_456_789)`. + +In general, except for the difference that (a) `Vector` is indexed and `List` is not, and (b) the `List` class has the `::` method, the two classes work the same, so we’ll quickly run through the following examples. + +Here are a few ways you can create a `Vector`: + +```scala +val nums = Vector(1, 2, 3, 4, 5) + +val strings = Vector("one", "two") + +case class Person(val name: String) +val people = Vector( + Person("Bert"), + Person("Ernie"), + Person("Grover") +) +``` + +Because `Vector` is immutable, you can’t add new elements to it. Instead you create a new sequence by appending or prepending elements to an existing `Vector`. These examples show how to _append_ elements to a `Vector`: + +```scala +val a = Vector(1,2,3) // Vector(1, 2, 3) +val b = a :+ 4 // Vector(1, 2, 3, 4) +val c = a ++ Vector(4, 5) // Vector(1, 2, 3, 4, 5) +``` + +This is how you _prepend_ elements: + +```scala +val a = Vector(1,2,3) // Vector(1, 2, 3) +val b = 0 +: a // Vector(0, 1, 2, 3) +val c = Vector(-1, 0) ++: a // Vector(-1, 0, 1, 2, 3) +``` + +In addition to fast random access and updates, `Vector` provides fast append and prepend times, so you can use these features as desired. + +>See the Reference documentation for performance details about `Vector` and other collections classes. + +Finally, you use a `Vector` in a `for` loop just like a `List`, `ArrayBuffer`, or any other sequence: + +```scala +scala> val names = Vector("Joel", "Chris", "Ed") +val names: Vector[String] = Vector(Joel, Chris, Ed) + +scala> for name <- names do println(name) +Joel +Chris +Ed +``` + + + +## The ArrayBuffer class + +Use `ArrayBuffer` when you need a general-purpose, mutable indexed sequence in your Scala applications. It’s mutable so you can change its elements, and also resize it. Because it’s indexed, random access of elements is fast. + +### Creating an ArrayBuffer + +To use an `ArrayBuffer`, first import it: + +```scala +import scala.collection.mutable.ArrayBuffer +``` + +If you need to start with an empty `ArrayBuffer`, just specify its type: + +```scala +var strings = ArrayBuffer[String]() +var ints = ArrayBuffer[Int]() +var people = ArrayBuffer[Person]() +``` + +If you know the approximate size your `ArrayBuffer` eventually needs to be, you can create it with an initial size: + +```scala +// ready to hold 100,000 ints +val buf = new ArrayBuffer[Int](100_000) +``` + +To create a new `ArrayBuffer` with initial elements, just specify its initial elements, just like a `List` or `Vector`: + +```scala +val nums = ArrayBuffer(1, 2, 3) +val people = ArrayBuffer( + Person("Bert"), + Person("Ernie"), + Person("Grover") +) +``` + +### Adding elements to an ArrayBuffer + +Append new elements to an `ArrayBuffer` with the `+=` and `++=` methods. Or if you prefer methods with names you can also use `append`, `appendAll`, `insert`, `insertAll`, `prepend`, and `prependAll`. + +Here are some examples of `+=` and `++=`: + +```scala +var nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) +nums += 4 // ArrayBuffer(1, 2, 3, 4) +nums += (5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) +nums ++= List(7, 8) // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8) +``` + +### Removing elements from an ArrayBuffer + +`ArrayBuffer` is mutable, so it has methods like `-=`, `--=`, `clear`, `remove`, and more. These examples demonstrate the `-=` and `--=` methods: + +```scala +val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g) +a -= 'a' // ArrayBuffer(b, c, d, e, f, g) +a --= Seq('b', 'c') // ArrayBuffer(d, e, f, g) +a --= Set('d', 'e') // ArrayBuffer(f, g) +``` + +### Updating ArrayBuffer elements + +Update elements in an `ArrayBuffer` by either reassigning the desired element, or use the `update` method: + +```scala +val a = ArrayBuffer.range(1,5) // ArrayBuffer(1, 2, 3, 4) +a(2) = 50 // ArrayBuffer(1, 2, 50, 4) +a.update(0, 10) // ArrayBuffer(10, 2, 50, 4) +``` + +See the Reference documentation for more `ArrayBuffer` information and examples. + + + +## Working with Maps + +A `Map` is an iterable sequence that consists of pairs of keys and values. Scala has both mutable and immutable `Map` classes, and this section demonstrates how to use the _immutable_ `Map` class. + +### Creating an immutable Map + +Create an immutable `Map` like this: + +```scala +val states = Map( + "AK" -> "Alaska", + "AL" -> "Alabama", + "AZ" -> "Arizona" +) +``` + +Once you have a `Map` you can traverse its elements in a `for` loop like this: + +```scala +for ((k,v) <- states) println(s"key: $k, value: $v") +``` + +The REPL shows how this works: + +```` +scala> for ((k,v) <- states) println(s"key: $k, value: $v") +key: AK, value: Alaska +key: AL, value: Alabama +key: AZ, value: Arizona +```` + +### Accessing Map elements + +Access map elements by specifying the desired key value in parentheses: + +```scala +val ak = states("AK") // ak: String = Alaska +val al = states("AL") // al: String = Alabama +``` + +In practice you’ll also use methods like `keys`, `keySet`, `keysIterator`, `for` loops, and higher-order functions like `map` to work with `Map` keys and values. + +### Adding elements to a Map + +Add elements to an immutable map using `+` and `++`, remembering to assign the result to a new variable: + +```scala +val a = Map(1 -> "one") // a: Map(1 -> one) +val b = a + (2 -> "two") // b: Map(1 -> one, 2 -> two) +val c = b + ( + 3 -> "three", + 4 -> "four" +) +// c: Map(1 -> one, 2 -> two, 3 -> three, 4 -> four) +``` + +## Removing elements from a Map + +Remove elements from an immutable map using `-` or `--` and the key values to remove, remembering to assign the result to a new variable: + +```scala +val a = Map( + 1 -> "one", + 2 -> "two", + 3 -> "three", + 4 -> "four" +) + +a - 4 // Map(1 -> one, 2 -> two, 3 -> three) +a - 4 - 3 // Map(1 -> one, 2 -> two) +``` + +## Updating Map elements + +To update elements in an immutable map, use the `updated` method while assigning the result to a new variable: + +```scala +val a = Map( + 1 -> "one", + 2 -> "two", + 3 -> "three" +) + +val b = a.updated(3, "THREE!") // Map(1 -> one, 2 -> two, 3 -> THREE!) +``` + +## Traversing a Map + +As shown earlier, this is a common way to manually traverse elements in a map using a `for` loop: + +```scala +val states = Map( + "AK" -> "Alaska", + "AL" -> "Alabama", + "AZ" -> "Arizona" +) + +for ((k,v) <- states) println(s"key: $k, value: $v") +``` + +That being said, there are _many_ ways to work with the keys and values in a map. Common `Map` methods include `foreach`, `map`, `keys`, and `values`. + +Scala has many more specialized `Map` classes available, including `CollisionProofHashMap`, `HashMap`, `LinkedHashMap`, `ListMap`, `SortedMap`, `TreeMap`, `WeakHashMap`, and more. See the Reference documentation for more details on `Map` methods and these specialized subclasses. + + + +## Working with Sets + + +The [Scala Set class]({{site.baseurl}}/overviews/collections-2.13/sets.html) is an iterable collection with no duplicate elements. + +Scala has both mutable and immutable `Set` classes. This section demonstrates the _mutable_ `Set` class. + +### Adding elements to a Set + +The mutable `Set` class isn’t in scope by default, so first you need to import it: + +```scala +val set = scala.collection.mutable.Set[Int]() +``` + +Once in scope, add elements to a mutable `Set` with the `+=`, `++=`, and `add` methods. Here are a few examples: + +```scala +set += 1 // Set(1) +set += 2 += 3 // Set(1, 2, 3) +set ++= Vector(4, 5) // Set(1, 5, 2, 3, 4) +``` + +Notice that if you add a value that’s already in the set, the attempt is quietly ignored: + +```scala +set += 2 // Set(1, 5, 2, 3, 4) (no warning message is shown) +``` + +`Set` also has an `add` method that returns `true` if an element is successfully added to a set, and `false` if it wasn’t added: + +```scala +set.add(6) // true +set.add(5) // false +``` + +## Deleting elements from a Set + +Remove elements from a set using the `-=` and `--=` methods, as shown in the following examples: + +```scala +val set = scala.collection.mutable.Set(1, 2, 3, 4, 5) +// set: mutable.Set[Int] = HashSet(1, 2, 3, 4, 5) + +// remove one element +set -= 1 // HashSet(2, 3, 4, 5) + +// remove multiple elements defined in another sequence +set --= Array(4,5) // HashSet(2, 3) +``` + +There are more methods for working with sets, including `clear` and `remove`, as shown in these examples: + +```scala +// clear +val set1 = scala.collection.mutable.Set(1, 2, 3, 4, 5) +set1.clear() // HashSet() + +// remove +val set2 = scala.collection.mutable.Set(1, 2, 3, 4, 5) +set2.remove(2) // Boolean = true +set2 // HashSet(1, 3, 4, 5) +set2.remove(40) // false +``` + + +## The Range class + +The `Range` class is often used to populate data structures and to iterate over `for` loops. These REPL examples demonstrate how to create ranges: + + +```scala +1 to 5 // Range(1, 2, 3, 4, 5) +1 until 5 // Range(1, 2, 3, 4) +1 to 10 by 2 // Range(1, 3, 5, 7, 9) +'a' to 'c' // NumericRange(a, b, c) +``` + +You can use ranges to populate collections: + +```scala +val x = (1 to 5).toList // List(1, 2, 3, 4, 5) +val x = (1 to 5).toBuffer // ArrayBuffer(1, 2, 3, 4, 5) +``` + +They’re also used in `for` loops: + +```` +scala> for i <- 1 to 3 do println(i) +1 +2 +3 +```` + +There are also `range` methods on collections classes: + +```scala +Vector.range(1,5) // Vector(1, 2, 3, 4) +Vector.range(1,10,2) // Vector(1, 3, 5, 7, 9) +Set.range(1,10) // HashSet(5, 1, 6, 9, 2, 7, 3, 8, 4) +``` + +When you’re running tests, ranges are also useful for generating test collections: + +```scala +val evens = (0 to 10 by 2).toList // List(0, 2, 4, 6, 8, 10) +val odds = (1 to 10 by 2).toList // List(1, 3, 5, 7, 9) +val doubles = (1 to 5).map(_ * 2.0) // Vector(2.0, 4.0, 6.0, 8.0, 10.0) + +// create a Map +val map = (1 to 3).map(e => (e,s"$e")).toMap + // map: Map[Int, String] = Map(1 -> "1", 2 -> "2", 3 -> "3") +``` + + + + +## Common methods on the collections classes + +A great strength of the Scala collections classes is that they come with dozens of pre-built methods, and those methods are consistently available across the immutable and mutable classes. The benefit of this is that you no longer need to write custom `for` loops every time you need to work on a collection. (If that’s not enough of a benefit, it also means that you no longer have to read custom `for` loops.) + +Because there are so many methods available to you, they aren’t all shown here. Instead, only some of the most commonly-used methods will be shown, including: + +- `map` +- `filter` +- `foreach` +- `head` +- `tail` +- `take`, `takeWhile` +- `drop`, `dropWhile` +- `reduce` + +The following methods work on all of the sequence classes, including `Array`, `ArrayBuffer`, `List`, `Vector`, etc., but these examples use a `List` unless otherwise specified. + +### Note: The methods don’t mutate the collection + +As a very important note, none of these methods mutate the collection that they’re called on. They all work in a functional style, meaning that they return a new collection with the modified results. + +### Examples of some common methods + +These examples show some of the most commonly used methods: + +```scala +val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) + +a.distinct // List(10, 20, 30, 40) +a.drop(2) // List(30, 40, 10) +a.dropRight(2) // List(10, 20, 30) +a.dropWhile(_ < 25) // List(30, 40, 10) +a.filter(_ < 25) // List(10, 20, 10) +a.filter(_ > 100) // List() +a.filterNot(_ < 25) // List(30, 40) +a.find(_ > 20) // Some(30) +a.head // 10 +a.headOption // Some(10) +a.init // List(10, 20, 30, 40) +a.intersect(List(19,20,21)) // List(20) +a.last // 10 +a.lastOption // Some(10) +a.slice(2,4) // List(30, 40) +a.tail // List(20, 30, 40, 10) +a.take(3) // List(10, 20, 30) +a.takeRight(2) // List(40, 10) +a.takeWhile(_ < 30) // List(10, 20) +``` + +### Sample lists + +The following examples use these lists: + +```scala +val oneToTen = (1 to 10).toList +val names = List("adam", "brandy", "chris", "david") +``` + +### `map` + +The `map` method steps through each element in the existing list, applying the algorithm you supply to each element, one at a time; it then returns a new list with all of the modified elements. + +Here’s an example of the `map` method being applied to the `oneToTen` list: + +```scala +scala> val doubles = oneToTen.map(_ * 2) +doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) +``` + +You can also write anonymous functions using a long form, like this: + +```scala +scala> val doubles = oneToTen.map(i => i * 2) +doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) +``` + +However, in this lesson we’ll always use the first, shorter form. + +Here are a few more examples of the `map` method being applied to the `oneToTen` and `names` lists: + +```scala +scala> val capNames = names.map(_.capitalize) +capNames: List[String] = List(Adam, Brandy, Chris, David) + +scala> val nameLengthsMap = names.map(s => (s, s.length)).toMap +nameLengthsMap: Map[String, Int] = Map(adam -> 4, brandy -> 6, chris -> 5, david -> 5) + +scala> val isLessThanFive = oneToTen.map(_ < 5) +isLessThanFive: List[Boolean] = List(true, true, true, true, false, false, false, false, false, false) +``` + +As shown in the last two examples, it’s perfectly legal (and common) to use `map` to return a collection that has a different type than the original type. + +### `filter` + +The `filter` method creates a new, filtered list from the given list. Here are a few examples: + +```scala +scala> val lessThanFive = oneToTen.filter(_ < 5) +lessThanFive: List[Int] = List(1, 2, 3, 4) + +scala> val evens = oneToTen.filter(_ % 2 == 0) +evens: List[Int] = List(2, 4, 6, 8, 10) + +scala> val shortNames = names.filter(_.length <= 4) +shortNames: List[String] = List(adam) +``` + +### `foreach` + +The `foreach` method is used to loop over all elements in a collection. Note that `foreach` is used for side-effects, such as printing information. Here’s an example with the `names` list: + +```scala +scala> names.foreach(println) +adam +brandy +chris +david +``` + +A great thing about the functional methods on the collections classes is that you can chain them together to solve problems. For example, this is one way to print the first three elements from `oneToTen`: + +```scala +oneToTen.filter(_ < 4).foreach(println) +``` + +The REPL shows the result: + +```scala +scala> oneToTen.filter(_ < 4).foreach(println) +1 +2 +3 +``` + +### `head` + +The `head` method comes from Lisp and other earlier functional programming languages. It’s used to print the first element (the head element) of a list: + +```scala +oneToTen.head // Int = 1 +names.head // adam +``` + +Because a `String` is a sequence of characters, you can also treat it like a list. This is how `head` works on these strings: + +```scala +"foo".head // f +"bar".head // b +``` + +`head` is a great method to work with, but as a word of caution it can also throw an exception when called on an empty collection: + +```scala +val emptyList = List[Int]() // emptyList: List[Int] = List() +emptyList.head // java.util.NoSuchElementException: head of empty list +``` + +Because of this you may want to use `headOption` instead of `head`, especially when programming in a functional style: + +```scala +emptyList.headOption // Option[Int] = None +``` + +As shown, it doesn’t throw an exception, it simply returns the type `Option` that has the value `None`. You can learn more about this programming style in the Reference documentation. + +### `tail` + +The `tail` method also comes from Lisp, and it’s used to print every element in a list after the head element. A few examples demonstrate this: + +```scala +oneToTen.head // Int = 1 +oneToTen.tail // List(2, 3, 4, 5, 6, 7, 8, 9, 10) + +names.head // adam +names.tail // List(brandy, chris, david) +``` + +Just like `head`, `tail` also works on strings: + +```scala +"foo".tail // "oo" +"bar".tail // "ar" +``` + +Like `head` and `headOption`, there’s also a `tailOption` method, which is preferred in functional programming. + +### `take`, `takeRight`, `takeWhile` + +The `take`, `takeRight`, and `takeWhile` methods give you a nice way of “taking” the elements from a list that you want to use to create a new list. This is `take` and `takeRight`: + +```scala +oneToTen.take(1) // List(1) +oneToTen.take(2) // List(1, 2) + +oneToTen.takeRight(1) // List(10) +oneToTen.takeRight(2) // List(9, 10) +``` + +And this is `takeWhile`, which works with a predicate function: + +```scala +oneToTen.takeWhile(_ < 5) // List(1, 2, 3, 4) +names.takeWhile(_.length < 5) // List(adam) +``` + +### `drop`, `dropRight`, `dropWhile` + +`drop`, `dropRight`, and `dropWhile` are essentially the opposite of their “take” counterparts, dropping elements from a list. Here are some examples: + +```scala +oneToTen.drop(1) // List(2, 3, 4, 5, 6, 7, 8, 9, 10) +oneToTen.drop(5) // List(6, 7, 8, 9, 10) + +oneToTen.dropRight(8) // List(1, 2) +oneToTen.dropRight(7) // List(1, 2, 3) +``` + +And this is `dropWhile`, which works with a predicate function: + +```scala +oneToTen.dropWhile(_ < 5) // List(5, 6, 7, 8, 9, 10) +names.dropWhile(_ != "chris") // List(chris, david) +``` + +### `reduce` + +When you hear the term, “map reduce,” the “reduce” part refers to methods like `reduce`. It takes a function (or anonymous function) and applies that function to successive elements in the list. + +The best way to explain `reduce` is to create a little helper method you can pass into it. For example, this is an `add` method that adds two integers together, and also provides us some nice debug output: + +```scala +def add(x: Int, y: Int): Int = + val theSum = x + y + println(s"received $x and $y, their sum is $theSum") + theSum +``` + +Given that method and this list: + +```scala +val a = List(1,2,3,4) +``` + +this is what happens when you pass the `add` method into `reduce`: + +```scala +scala> a.reduce(add) +received 1 and 2, their sum is 3 +received 3 and 3, their sum is 6 +received 6 and 4, their sum is 10 +res0: Int = 10 +``` + +As that result shows, `reduce` uses `add` to reduce the list `a` into a single value, in this case, the sum of the integers in the list. + +Once you get used to `reduce`, you’ll write a “sum” algorithm like this: + +```scala +scala> a.reduce(_ + _) +res0: Int = 10 +``` + +Similarly, a “product” algorithm looks like this: + +```scala +scala> a.reduce(_ * _) +res1: Int = 24 +``` + +>An important concept to know about `reduce` is that — as its name implies — it’s used to _reduce_ a collection down to a single value. + + + +## Even more + +There are literally dozens of additional methods on the Scala collections classes that will keep you from ever needing to write another `for` loop. See the Reference documentation for more details and examples. + +>As a final note, if you’re using Java code in a Scala project, you can convert Java collections to Scala collections. By doing this you can use those collections in `for` expressions, and can also take advantage of Scala’s functional collections methods. See the [Integrating with Java](TODO) section for more details. + + + + + + + + + From fa1fc2b169352c1aec176bb5a2df8b65ce10e9f8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 13 Oct 2020 09:07:35 -0700 Subject: [PATCH 0182/2265] remove incorrect bit about partest (#1163) --- contribute/hacker-guide.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index b9e657adfb..f2f11d4f71 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -324,8 +324,6 @@ Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, resp testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] All of 6 tests were successful (elapsed time: 00:00:08) -`partest` was removed in 2.12. - ## 4. Publish After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. From 4e049594214cdee6045476cc9dffe8330992e8f4 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Tue, 13 Oct 2020 20:18:22 -0600 Subject: [PATCH 0183/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98Scala=20for=20Java=20Developers=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/scala-for-java-devs.md | 1028 ++++++++++++++++++++ _overviews/overview/scala-forjava-devs.md | 0 2 files changed, 1028 insertions(+) create mode 100644 _overviews/overview/scala-for-java-devs.md delete mode 100644 _overviews/overview/scala-forjava-devs.md diff --git a/_overviews/overview/scala-for-java-devs.md b/_overviews/overview/scala-for-java-devs.md new file mode 100644 index 0000000000..6cc72c93cb --- /dev/null +++ b/_overviews/overview/scala-for-java-devs.md @@ -0,0 +1,1028 @@ + + + +Scala for Java Developers + + +

Notes to reviewers:
+

+
    +
  1. I’m initially submitting this page as HTML because it’s much +easier to work on these side-by-side source code examples with a +Wysiwyg editor (I’m using SeaMonkey). I will convert it to +Markdown when we’re confident with the content in those tables. +If at all possible, I think the side-by-side code examples are +the best approach.
    +
  2. +
  3. I haven’t formatted the multiline source code examples inside +table cells because I think it will be easier to convert them to +Markdown if I don’t do that now. (My initial conversion tests +with Pandoc showed that the conversion will be smoother by not +using <code> tags on those multiline +examples.)
    +
  4. +
  5. This page will eventually link to many other pages. So if you +wonder why I don’t explain certain things in more detail, it’s +because (a) I’m trying to keep this page as short as possible +and (b) I assume this page will eventually link to dozens of +other pages for more details.
  6. +
+
+


+

+

This page provides a comparison between the Java and Scala +programming languages. It’s intended for programmers who know Java +and want to learn about Scala, specifically by seeing how Java +language features compare to Scala.

+

Executive overview (TL;DR)
+

+

This section provides a relatively brief introduction and summary +of the sections that follow. It presents the similarities and +differences between Java and Scala at a high level, and then +introduces the differences you’ll experience every day as you +write code.

+

High level similarities
+

+

At a high level, Scala shares these similarities with Java:
+

+
    +
  • Scala code is compiled to .class files, packaged in +JAR files, and runs on the JVM
  • +
  • It’s an object-oriented programming (OOP) language
  • +
  • It’s statically typed
  • +
  • Both languages have support for immutable collections, +lambdas, and higher-order functions
    +
  • +
  • It has great IDE support
  • +
  • It has great build tools
  • +
  • It has terrific libraries and frameworks for building +server-side, network-intensive applications, including web +server applications, microservices, machine learning, and more
  • +
  • Both Java and Scala can use the Akka actors library to build +actor-based concurrent systems, and Apache Spark to build +data-intensive applications
    +
  • +
  • You can use GraalVM to compile your projects into native +executables
  • +
  • Scala can seamlessly use the wealth of libraries that have +been developed for Java
  • +
+

High level differences
+

+

Also at a high level, the differences between Java and Scala are:
+

+
    +
  • Scala has a concise but readable syntax; we call it expressive
    +
  • +
  • Though it’s statically typed, Scala feels like a dynamic +language
  • +
  • Scala is a pure OOP language, so every object is an instance +of a class, and symbols like + and += +that look like operators are really methods; this means that you +can create your own operators
    +
  • +
  • In addition to being a pure OOP language, Scala is also a pure +FP language; in fact, it encourages a fusion of OOP and FP, with +functions for the logic and objects for modularity
    +
  • +
  • Everything in Scala is an expression: constructs like +if statements, for loops, match +expressions, and even try/catch +expressions all have return values
    +
  • +
  • Scala idioms favor immutability by default: you’re encouraged +to use immutable (final) variables and immutable +collections
    +
  • +
  • In addition to running on the JVM, the Scala.js project lets you +use Scala as a JavaScript replacement
  • +
  • The Scala + +Native project adds low-level constructs to let you write +“systems” level code, and also compiles to native executables
  • +
  • Sound type system (TODO: need a good, simple way to state +this)
    +
  • +
+

Programming level differences
+

+

At a lower level, these are some of the differences you’ll see +every day when writing code:
+

+
    +
  • Scala’s syntax is extremely consistent (TODO: need a good way +to state this)
  • +
  • Variables and parameters are defined as val +(immutable, like final in Java) or var +(mutable)
    +
  • +
  • Type inference makes your code feel dynamic and helps to keep +it as brief as you want it
    +
  • +
  • In addition to simple for loops, Scala has +powerful for comprehensions that yield results +based on your algorithms
    +
  • +
  • Pattern matching and match expressions will +change the way you write code
    +
  • +
  • Scala’s type system lets you express details (TODO: need a +good way to state this)
  • +
  • Writing immutable code by default leads to writing expressions +rather than statements; in time you’ll see that writing +expressions simplifies your code (and your tests)
    +
  • +
  • Toplevel definitions let you put method, field, and +other definitions anywhere, also leading to concise, expressive +code
    +
  • +
  • You can create mixins by “mixing in” multiple traits +(traits are similar to interfaces in Java 8 and newer)
    +
  • +
  • Classes are closed by default, supporting Joshua Bloch’s Effective + +Java idiom, “Design and document for inheritance or else +forbid it”
    +
  • +
  • Scala’s contextual abstractions and term inference +provide a collection of features:
    +
  • +
      +
    • Extension methods let you add new functionality to +closed classes
    • +
    • Given instances let you define terms that the +compiler can synthesize at using points, making your +code less verbose and essentially letting the compiler write +code for you
      +
    • +
    • Multiversal equality lets you limit equality comparisons — +at compile time — to only those comparisons that make sense
      +
    • +
    +
  • First class support for building modules
    +
  • +
  • Scala has state of the art, third-party, open source +functional programming libraries
  • +
  • Case classes are like records in Java 14; they help you model +data when writing FP code, with built-in support for concepts +like pattern matching and cloning
    +
  • +
  • Thanks to features like by-name parameters, infix notation, +optional parentheses, extension methods, and higher-order +functions, you can create your own “control structures” and DSLs
    +
  • +
  • Scala files do not have to be named according to the classes +or traits they contain
  • +
  • Many other goodies: companion classes and objects, macros, +union and intersection types, toplevel definitions, numeric +literals, multiple parameter lists, default values for +parameters, named arguments, and more
    +
  • +
+

Features compared with examples

+

Given that introduction, the following sections provide +side-by-side comparisons of Java and Scala programming language +features.

+

OOP style classes and methods

+

This section provides comparisons of features related to +OOP-style classes and methods.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Java
+
Scala
+
Comments
+(the same in Java and Scala)
+
+
//
+/* ... */
+/** ... */
//
+/* ... */
+/** ... */
OOP style class,
+primary constructor
+
class Person {
+  private String firstName;
+  private String lastName;
+  private int age;
+  public Person(String firstName, String lastName, int +age) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.age = age;
+  }
+  override String toString() {
+    return String.format("%s %s is %d years +old.", firstName, lastName, age);
+  }
+}
class Person (
+  var firstName: String,
+  var lastName: String,
+  var age: Int
+):  
+    override def toString = s"$firstName +$lastName is $age years old."
+
+
Auxiliary constructors
+
public class Person {
+  private String firstName;
+  private String lastName;
+  private int age;
+
+  // primary constructor
+  public Person(String firstName, String lastName, int +age) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.age = age;
+  }
+
+  // zero-arg constructor
+  public Person(String firstName, String lastName, int +age) {
+    this("", "", 0);
+  }
+
+  // one-arg constructor
+  public Person(String firstName) {
+    this(firstName, "", 0);
+  }
+
+  // two-arg constructor
+  public Person(String firstName, String lastName) {
+    this(firstName, lastName, 0);
+  }
+
+}
+
class Person (
+  var firstName: String,
+  var lastName: String,
+  var age: Int
+):
+    // zero-arg auxiliary constructor
+    def this() = this("", "", 0)
+
+    // one-arg auxiliary constructor
+    def this(firstName: String) = +this(firstName, "", 0)
+
+    // two-arg auxiliary constructor
+    def this(firstName: String, lastName: +String) =
+      this(firstName, lastName, 0)
+
+end Person
+
Classes closed by default (“Plan for +inheritance or else forbid it”)
+
final class Person
+
class Person
+
Create a class that’s open for extension
+
class Person
+
open class Person
+
Method, one line
+
public int add(int a, int b) {
+  return a + b;
+}
+
def add(a: Int, b: Int): Int = a + b
+
Method, multiple lines
+
public void walkThenRun() {
+  System.out.println("walk");
+  System.out.println("run");
+}
+
def walkThenRun() =
+  println("walk")
+  println("run")
+
Immutable field
+
final int i = 1;
+
val i = 1
+
Mutable field
+
int i = 1;
+var i = 1;
+
var i = 1
+
+


+

+

Interfaces, traits, and inheritance

+

This section compares Java interfaces to Scala traits, including +how classes extend interfaces and traits.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Java
+
Scala
+
Interfaces/Traits
+
public interface Marker;
+
trait Marker
+
Simple interface
+
public interface Adder {
+  public int add(int a, int b);
+}
+
trait Adder:
+  def add(a: Int, b: Int): Int
+
Interface with a concrete method
+
public interface Adder {
+  int add(int a, int b);
+  default int multiply(int a, int b) {
+    return a * b;
+  }
+}
trait Adder:
+  def add(a: Int, b: Int): Int
+  def multiply(a: Int, b: Int): Int = a * b
+
Inheritance
+
class Dog extends +Animal,HasLegs,HasTail class Dog extends +Animal,HasLegs,HasTail
+
Extending multiple interfaces/traits
+that have implemented methods
+(default methods)
+
interface Adder {
+  default int add(int a, int b) {
+    return a + b;
+  }
+}
+interface Multiplier {
+  default int multiply(int a, int b) {
+    return a * b;
+  }
+}
+public class JavaMath implements Adder, Multiplier {}
+
+JavaMath jm = new JavaMath();
+jm.add(1,1);
+jm.multiply(2,2);
+
trait Adder:
+  def add(a: Int, b: Int) = a + b
+
+trait Multiplier:
+  def multiply(a: Int, b: Int) = a * b
+
+class ScalaMath extends Adder, Multiplier
+
+val sm = new ScalaMath
+sm.add(1,1)
+sm.multiply(2,2)
+
Mixin
+
N/A
+
class DavidBanner
+trait Angry:
+  def beAngry() = println("You won’t like me ...")
+trait Big:
+  println("I’m big")
+trait Green:
+  println("I’m green")
+
+// mix in the traits as DavidBanner is created
+val hulk = new DavidBanner with Big with Angry with Green
+
+

+


+

+

Control structures

+

+

This section compares control structures in Java and Scala.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Java
+
Scala
+
if statement,
+one line
+
if (x == 1) { System.out.println(1); }
+
if x == 1 then println(x)
+
if statement,
+multiline
+
if (x == 1) {
+  System.out.println("x is 1, as you can see:")
+  System.out.println(x)
+}
if x == 1 then
+  println("x is 1, as you can see:")
+  println(x)
+
if/else if/else
+
if (x < 0) {
+  System.out.println("negative")
+} else if (x == 0) {
+  System.out.println("zero")
+} else {
+  System.out.println("positive")
+}
+
if x < 0 then
+  println("negative")
+else if x == 0
+  println("zero")
+else
+  println("positive")
+
if as method body
+
public int min(int a, int b) {
+  return (a < b) ? a : b;
+}
+
def min(a: Int, b: Int): Int =
+  if a < b then a else b
+
Returning a value from if
+
int minVal = (a < b) ? a : b;val minValue = if a < b then a else +b
+
while
+
while (i < 3) {
+  System.out.println(i);
+  i++;
+}
+
while i < 3 do
+  println(i)
+  i += 1
+
for loop,
+single line
+
for (int i: ints) {
+  System.out.println(i);
+}
+
for i <- ints do println(i)   // +preferred
+for (i <- ints) println(i)   // also available
+
for loop,
+multiple lines
for (int i: ints) {
+  int x = i * 2;
+  System.out.println(x);
+}
for
+  i <- ints
+do
+  val x = i * 2
+  println(s"i = $i, x = $x")
+
Multiple generators
+
for (int i: ints1) {
+  for (int j: chars) {
+    for (int k: ints2) {
+      System.out.printf("i = %d, j += %d, k = %d\n", i,j,k);
+    }
+  }
+}
+
for
+  i <- 1 to 2
+  j <- 'a' to 'b'
+  k <- 1 to 10 by 5
+do
+  println(s"i = $i, j = $j, k = $k")
+
Generator with guards (if +expressions)
+
List ints = ArrayList(1,2,3,4,5,6,7,8,9,10);
+for (int i: ints) {
+  if (i % 2 == 0 && i < 5) {
+    System.out.println(x);
+  }
+}
for
+  i <- 1 to 10
+  if i % 2 == 0
+  if i < 5
+do
+  println(i)
+
for comprehension
+
N/A
+
val list =
+  for
+    i <- 1 to 3
+  yield
+    i * 10
+// result: Vector(10, 20, 30)
+
switch/match
+
String monthAsString = "";
+switch(day) {
+  case 1: monthAsString = "January";
+          +break;
+  case 2: monthAsString = "February";
+          +break;
+  default: monthAsString = "Other";
+          +break;
+}
+
val monthAsString = day match {
+  case 1 => "January"
+  case 2 => "February"
+  _ => "Other"
+}
+
switch/match: +handling
+multiple conditions
+per case
+
String numAsString = "";
+switch (i) {
+  case 1: case 3:
+  case 5: case 7: case 9:
+    numAsString = "odd";
+    break;
+  case 2: case 4:
+  case 6: case 8: case 10:
+    numAsString = "even";
+    break;
+  default:
+    numAsString = "too big";
+    break;
+}
+
val numAsString = i match {
+  case 1 | 3 | 5 | 7 | 9 => println("odd")
+  case 2 | 4 | 6 | 8 | 10 => println("even")
+  case _ => println("too big")
+}
+
try/catch/finally
+
try {
+  writeTextToFile(text);
+} catch (IOException ioe) {
+  println("Got an IOException.")
+} catch (NumberFormatException nfe) {
+  println("Got an NumberFormatException.")
+} finally {
+  println("Clean up your resources here.")
+}
+
try
+  writeTextToFile(text)
+catch
+  case ioe: IOException => println("Got an +IOException.")
+  case nfe: NumberFormatException => println("Got a +NumberFormatException.")
+finally
+  println("Clean up your resources here.")
+
+


+

+

Collections classes

+

This section compares the collections classes that are available +in Java and Scala.

+

Immutable collections classes

+

Examples of how to create instances of immutable collections:
+

+ + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Java
+
Scala
+
Sequences
+
List strings = List.of("a", "b", "c");
+
val strings = List("a", "b", "c")
+val strings = Vector("a", "b", "c")
+
Set
+
Set set = Set.of("a", "b", "c"); +val set = Set("a", "b", "c")
+
Map
+
Map map = Map.of("a", 1, "b", 2, "c", +3); val map = Map("a" -> 1, "b" -> 2, +"c" -> 3)
+
+


+

+

Mutable collections classes

+

The table below shows which Java collections classes can be +converted to Scala collections classes with the Scala CollectionConverters +objects. There are two objects in different packages, one for +converting from Java to Scala, and another for converting from +Scala to Java. Here are the conversions:
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Java
+
Scala
+
java.util.Collection
+
scala.collection.Iterable
java.util.List
+
scala.collection.mutable.Buffer
java.util.Set
+
scala.collection.mutable.Set
+
java.util.Map
+
scala.collection.mutable.Map
+
java.util.concurrent.ConcurrentMap + +scala.collection.mutable.ConcurrentMap
+
java.util.Dictionary
+
scala.collection.mutable.Map
+


+

+

Methods on collections classes

+

With the ability to treat Java collections as streams, Java and +Scala now have many of the same common functional methods +available to them:

+
    +
  • map
  • +
  • filter
  • +
  • forEach/foreach
  • +
  • findFirst/find
  • +
  • reduce
    +
  • +
+

If you’re used to using these methods with lambda expressions in +Java, you’ll find it easy to use the same methods on Scala’s +collection classes.
+

+

Tuples
+

+

Java tuples are created like this:
+

+
Pair<String, Integer> pair = new Pair<String, Integer>("Eleven", 11);
Triplet<String, Integer, Double> triplet = Triplet.with("Eleven", 11, 11.0);
Quartet<String, Integer, Double,Person> triplet = Triplet.with("Eleven", 11, 11.0, new Person("Eleven"));
+

Other Java tuple names are Quintet, Sextet, Septet, Octet, +Ennead, Decade.

+

Tuples in Scala are created by putting the values inside +parentheses, like this:
+

+
val a = ("eleven")
val b = ("eleven", 11)
val c = ("eleven", 11, 11.0)
val d = ("eleven", 11, 11.0, Person("Eleven"))
+


+

+

Enums

+

This section compares enums (enumerations) in Java and Scala.
+

+ + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Java
+
Scala
+
Basic enum
+
enum Color {
+  RED, GREEN, BLUE
+}
+
enum Color:
+  case Red, Green, Blue
+
Parameterized enum
+
enum Color {
+  Red(0xFF0000),
+  Green(0x00FF00),
+  Blue(0x0000FF);
+
+  private int rgb;
+
+  Color(int rgb) {
+    this.rgb = rgb;
+  }
+}
+
enum Color(val rgb: Int):
+  case Red   extends Color(0xFF0000)
+  case Green extends Color(0x00FF00)
+  case Blue  extends Color(0x0000FF)
+
User-defined enum members
+
enum Planet {
+  MERCURY (3.303e+23, 2.4397e6),
+  VENUS   (4.869e+24, 6.0518e6),
+  EARTH   (5.976e+24, 6.37814e6);
+  // more planets ...
+
+  private final double mass;
+  private final double radius;
+
+  Planet(double mass, double radius) {
+    this.mass = mass;
+    this.radius = radius;
+  }
+
+  public static final double G = 6.67300E-11;
+
+  private double mass() { return mass; }
+  private double radius() { return radius; }
+
+  double surfaceGravity() {
+    return G * mass / (radius * radius);
+  }
+  double surfaceWeight(double otherMass) {
+    return otherMass * surfaceGravity();
+  }
+
+}
+
+
enum Planet(mass: Double, radius: Double):
+  case Mercury extends Planet(3.303e+23, 2.4397e6)
+  case Venus   extends Planet(4.869e+24, +6.0518e6)
+  case Earth   extends Planet(5.976e+24, +6.37814e6)
+  // more planets ...
+
+  private final val G = 6.67300E-11
+  def surfaceGravity = G * mass / (radius * radius)
+  def surfaceWeight(otherMass: Double) =  +otherMass * surfaceGravity
+
+
+


+

+

Exceptions and error handling

+

Java uses checked exceptions

+

Java uses checked exceptions, so in Java code you’ll see try/catch/finally +blocks, and throws clauses on methods:

+
public int makeInt(String s) throws NumberFormatException {
  // code here to convert a String to an int
}
+

Scala does not use checked exceptions
+

+

The Scala idiom is to not use checked exceptions like +this. When working with code that can throw exceptions, you can +use try/catch/finally +blocks to catch exceptions from code that throws them, but how you +proceed from there is different.

+

The best way to explain this is that Scala code consists of expressions, +which return values. As a result, you end up writing your code as +a series of algebraic expressions:

+
val a = f(x)
val b = g(a,z)
val c = h(b,y)
+

This is nice, it’s just algebra, and a combination of equations. +As you may remember from high school algebra, algebraic +expressions don’t short circuit — they don’t throw exceptions that +blow up the series of equations.

+

Therefore, in Scala our methods don’t throw exceptions. Instead, +they return types like Option. For example, this makeInt +method catches a possible exception and returns an Option +value:
+

+
def makeInt(s: String): Option[Int] =
+try
+Some(s.toInt)
+catch
+case e: NumberFormatException => None
+
+

The Scala Option is similar to the Java Optional +class. As shown, if the string-to-int conversion succeeds, the Int +is returned inside a Some value, and if it fails, a +None value is returned. Some and None +are subtypes of Option, so the method is declared to +return the Option[Int] type.

+

When you have an Option value, such as the one +returned by makeInt, there are many ways to work +with it, depending on your needs. This code shows one possible +approach:
+

+
makeInt(aString) match
  case Some(i) => println(s"i = $i")
  case None => println(s"Could not convert $aString to an Int.")
+

Option is commonly used in Scala, and it’s built +into many classes in the standard library.
+

+

For more information on dealing with errors and exceptions in +Scala, see the Functional Error Handling section in the Reference +documentation.

+

Concepts that are unique to Scala
+

+

There are other concepts in Scala which currently have no equal +in Java 11:

+
    +
  • Everything related to contextual abstractions
  • +
  • Method features:
  • +
      +
    • Multiple parameter lists
    • +
    • Default parameter values
    • +
    • Using named arguments when calling methods
      +
    • +
    +
  • Case classes (like “records” in Java 14) and case objects
  • +
  • Companion classes and objects
  • +
  • The ability to create your own control structures and DSLs
  • +
  • Toplevel definitions
  • +
  • Pattern matching
  • +
  • Advanced features of match expressions
  • +
  • Type lambdas
  • +
  • Trait parameters
  • +
  • Opaque type aliases
  • +
  • Multiversal equality
  • +
  • Type classes
  • +
  • Infix methods
  • +
  • Macros and metaprogramming
  • +
  • More ...
    +
  • +
+
+


+

+

+

+

+


+

+ + + + diff --git a/_overviews/overview/scala-forjava-devs.md b/_overviews/overview/scala-forjava-devs.md deleted file mode 100644 index e69de29bb2..0000000000 From 2b73cff752124af29502813fe9450dfc582894bb Mon Sep 17 00:00:00 2001 From: Leo <4960573+leobenkel@users.noreply.github.com> Date: Wed, 14 Oct 2020 18:49:23 -0700 Subject: [PATCH 0184/2265] Add online resources to learn.html page --- learn.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/learn.md b/learn.md index 5da03071bd..396e89a982 100644 --- a/learn.md +++ b/learn.md @@ -8,6 +8,11 @@ redirect_from: ## Quick Online Exercises [Scala Exercises](https://www.scala-exercises.org/) is a series of lessons and exercises created by [47 Degrees](https://www.47deg.com/). It's a great way to get a brief introduction to Scala while testing your knowledge along the way. +[Tour of Scala](https://tourofscala.com) gives you an introduction to Scala, step by step, from begineer to expert. + +## Scala Learning Communities +[Scala Learning Community on Discord](http://sca.la/learning-community), a growing online community connecting online learning resources in one cohesive flow of learning. + ## Online Courses from EPFL The following courses are available for free. They teach you the main features of the Scala language and introduce you From 4cd8a27f25a7bd6734f53c30c8a80b6725cbe98f Mon Sep 17 00:00:00 2001 From: Vladyslav Pekker Date: Thu, 15 Oct 2020 18:01:32 -0300 Subject: [PATCH 0185/2265] Adds the DevInsideYou YouTube channel --- learn.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/learn.md b/learn.md index 5da03071bd..ddf12bd370 100644 --- a/learn.md +++ b/learn.md @@ -47,5 +47,8 @@ There are a handful of websites where you can interactively run Scala code in yo ## ScalaCourses [Independent Courseware](https://getscala.com), online self-study or instructor-led Scala and Play courses for a fee. +## DevInsideYou +[DevInsideYou](https://youtube.com/devinsideyou) is a YouTube channel with hundreds of hours of free, high quality Scala content. + ## Visual Scala Reference [Visual Scala Reference](https://superruzafa.github.com/visual-scala-reference/), a guide to visually learn about Scala concepts and functions. From bcc5724e736dd5034bb866bf3101dc1a668e2f23 Mon Sep 17 00:00:00 2001 From: Meriam Lachkar Date: Mon, 19 Oct 2020 16:57:48 +0200 Subject: [PATCH 0186/2265] Improve the getting started page (#1675) * Improve the getting started page * making the page self contained: users can have a working "hello-world" without visiting other pages * introducing couriser-cli a recommended way to install jvm requirements * adding Vscode/metals as a possible IDE * advertising only two ways of starting with Scala: interactive with Scastie or with and IDE + sbt * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Update _getting-started/index.md Co-Authored-By: Philippus Baalman * Add a small paragraph after each level 1 heading * minor tweaks to getting started page Co-authored-by: Philippus Baalman Co-authored-by: Seth Tisue --- _getting-started/index.md | 163 +++++++++++++----- ...g-a-scala-project-with-intellij-and-sbt.md | 3 +- 2 files changed, 122 insertions(+), 44 deletions(-) diff --git a/_getting-started/index.md b/_getting-started/index.md index 77147fc08c..f2ea968c32 100644 --- a/_getting-started/index.md +++ b/_getting-started/index.md @@ -7,55 +7,132 @@ includeTOC: true redirect_from: "/getting-started.html" --- +## Try Scala without installing anything +You can [try Scala in your browser](https://scastie.scala-lang.org/MHc7C9iiTbGfeSAvg8CKAA), with access to all Scala compilers and +all published libraries. + +## Install Scala +Installing Scala means installing various command-line tools such as the Scala compiler and build tools. +We recommend using the Scala installer tool that automatically installs all the requirements, but you can still manually install each tool. + +### Using the Scala Installer (recommended way) +The Scala installer is a tool named `cs` that ensures that a JVM and standard Scala tools are installed on your system. + +* Download the `cs` tool and execute the `setup` command + +
+
+

Follow the instructions to install the cs launcher then run:

+

$ ./cs setup

+
+
+ + +Along with managing JVMs, it also installs useful command line tools: +[Ammonite](https://ammonite.io/), +[coursier](https://get-coursier.io/), +scala (the Scala REPL and script runner), +scalac (the Scala compiler), +[sbt](https://www.scala-sbt.org/), and +[scalafmt](https://scalameta.org/scalafmt/). + +For more information, read [coursier-cli documentation](https://get-coursier.io/docs/cli-overview). + +### ...Or manually +1. if you don't have Java 8 or 11 installed, download +Java from [Oracle Java 8](https://www.oracle.com/java/technologies/javase-jdk8-downloads.html), [Oracle Java 11](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html), +or [AdoptOpenJDK 8/11](https://adoptopenjdk.net/). Refer to [JDK Compatibility](/overviews/jdk-compatibility/overview.html) for Scala/Java compatibility detail. +1. Install [sbt](https://www.scala-sbt.org/download.html) + +## Create a Hello-world project with sbt +To create a project, you can either use a command-line tool or an IDE. +If you are familiar with the command line, we recommend that approach. + +### Using command-line +sbt is a build tool for Scala. sbt compiles, runs, +and tests your Scala code. (It can also publish libraries and do many other tasks.) + +1. `cd` to an empty folder. +1. Run the following command `sbt new scala/hello-world.g8`. +This pulls the 'hello-world' template from GitHub. +It will also create a `target` folder, which you can ignore. +1. When prompted, name the application `hello-world`. This will +create a project called "hello-world". +1. Let's take a look at what just got generated: + +``` +- hello-world + - project (sbt uses this for its own files) + - build.properties + - build.sbt (sbt's build definition file) + - src + - main + - scala (all of your Scala code goes here) + - Main.scala (Entry point of program) <-- this is all we need for now +``` + +More documentation about sbt can be found in the [Scala Book](/overviews/scala-book/scala-build-tool-sbt.html) +and in the official sbt [documentation](https://www.scala-sbt.org/1.x/docs/index.html) + +### With an IDE +You can skip the rest of this page and go directly to [Building a Scala Project with IntelliJ and sbt](/getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.html#next-steps) + + +## Open hello-world project +Let's use an IDE to open the project. The most popular ones are IntelliJ and VSCode. +They both offer rich IDE features, but you can still use [many other editors.](https://scalameta.org/metals/docs/editors/overview.html) +### Using IntelliJ +1. Download and install [IntelliJ Community Edition](https://www.jetbrains.com/idea/download/) +1. Install the Scala plugin by following [the instructions on how to install IntelliJ plugins](https://www.jetbrains.com/help/idea/managing-plugins.html) +1. Open the `build.sbt` file then choose *Open as a project* + +### Using VSCode with metals +1. Download [VSCode](https://code.visualstudio.com/Download) +1. Install the Metals extension from [the Marketplace](https://marketplace.visualstudio.com/items?itemName=scalameta.metals) +1. Next, open the directory containing a `build.sbt` file. When prompted to do so, select *Import build*. + +## Run Hello World +Open a terminal +1. `cd` into `hello-world`. +1. Run `sbt`. This will open up the sbt console. +1. Type `~run`. The `~` is optional and causes sbt to re-run on every file save, +allowing for a fast edit/run/debug cycle. sbt will also generate a `target` directory +which you can ignore. -There are __two__ main ways people prefer to work in Scala: - -* Using an IDE. -* Using the command line. - -The following tutorials will walk you through the setup process for whichever way -you prefer. - -However, if you just want to jump directly into Scala without installing anything, skip the guides on this page and check out: - -* [Our interactive introduction to Scala on scala-exercises.com](https://www.scala-exercises.org/scala_tutorial/terms_and_types), or -* [Scastie](https://scastie.scala-lang.org/), Scala in the browser, with access to all Scala compilers and all published libraries! - -## Setting up and getting started with Scala - -### If you prefer working in an IDE... - -IntelliJ is the most commonly-used IDE by Scala developers. In this tutorial, -we'll walk you through downloading and setting up IntelliJ with the Scala -plugin, and we'll get you started with your first Scala project, complete with -unit tests! - -* [Getting Started with Scala in IntelliJ](/getting-started/intellij-track/getting-started-with-scala-in-intellij.html) -* [Building a Scala Project with IntelliJ and sbt](/getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.html) -* [Testing Scala in IntelliJ with ScalaTest](/getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.html) - - -### If you prefer working on the command line... - -If you prefer using a text editor like emacs, Vim, Atom, or Sublime Text, then -the best way to compile, test, and run Scala code is by using _sbt_, Scala's build -tool. - -* [Getting Started with Scala and sbt on the Command Line](/getting-started/sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.html) -* [Testing Scala with sbt and ScalaTest on the Command Line](/getting-started/sbt-track/testing-scala-with-sbt-on-the-command-line.html) - - ## Next Steps -Once you've finished these tutorials, check out: +Once you've finished the above tutorials, consider checking out: -* [The Tour of Scala](/tour/tour-of-scala.html) for bite-sized introductions to Scala's features. * [The Scala Book](/overviews/scala-book/introduction.html), which provides a set of short lessons introducing Scala’s main features. +* [The Tour of Scala](/tour/tour-of-scala.html) for bite-sized introductions to Scala's features. * [Learning Resources](/learn.html), which includes online interactive tutorials and courses. * [Our list of some popular Scala books](/books.html). ## Getting Help -There are a multitude of mailing lists and real-time chat channels in case you want to quickly connect with other Scala users. Check out our [community](https://scala-lang.org/community/) page for a list of these resources, and for where to reach out for help. +There are a multitude of mailing lists and real-time chat rooms in case you want to quickly connect with other Scala users. Check out our [community](https://scala-lang.org/community/) page for a list of these resources, and for where to reach out for help. + + + + + + + + + diff --git a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md index d1eab7d4ae..c575d4bfde 100644 --- a/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md +++ b/_getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.md @@ -105,6 +105,7 @@ Continue to the next tutorial in the _getting started with IntelliJ_ series, and **or** +* [The Scala Book](/overviews/scala-book/introduction.html), which provides a set of short lessons introducing Scala’s main features. +* [The Tour of Scala](/tour/tour-of-scala.html) for bite-sized introductions to Scala's features. - Continue learning Scala interactively online on [Scala Exercises](https://www.scala-exercises.org/scala_tutorial). -- Learn about Scala's features in bite-sized pieces by stepping through our [Tour of Scala]({{ site.baseurl }}/tour/tour-of-scala.html). From 2df87640c2d82df007db912fd65276575122b8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Tue, 20 Oct 2020 07:01:41 +0800 Subject: [PATCH 0187/2265] [zh-cn]add reflect tags (#1783) --- _overviews/reflection/thread-safety.md | 2 +- _overviews/reflection/typetags-manifests.md | 2 +- _zh-cn/overviews/reflection/thread-safety.md | 47 +++++++ .../reflection/typetags-manifests.md | 132 ++++++++++++++++++ 4 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 _zh-cn/overviews/reflection/thread-safety.md create mode 100644 _zh-cn/overviews/reflection/typetags-manifests.md diff --git a/_overviews/reflection/thread-safety.md b/_overviews/reflection/thread-safety.md index 5ea8071637..862d465872 100644 --- a/_overviews/reflection/thread-safety.md +++ b/_overviews/reflection/thread-safety.md @@ -6,7 +6,7 @@ overview-name: Reflection num: 6 -languages: [ja] +languages: [ja, zh-cn] permalink: /overviews/reflection/:title.html --- diff --git a/_overviews/reflection/typetags-manifests.md b/_overviews/reflection/typetags-manifests.md index e1c32a1c8f..6b6febff89 100644 --- a/_overviews/reflection/typetags-manifests.md +++ b/_overviews/reflection/typetags-manifests.md @@ -6,7 +6,7 @@ overview-name: Reflection num: 5 -languages: [ja] +languages: [ja, zh-cn] permalink: /overviews/reflection/:title.html --- diff --git a/_zh-cn/overviews/reflection/thread-safety.md b/_zh-cn/overviews/reflection/thread-safety.md new file mode 100644 index 0000000000..86acc1c247 --- /dev/null +++ b/_zh-cn/overviews/reflection/thread-safety.md @@ -0,0 +1,47 @@ +--- +layout: multipage-overview +title: 线程安全 +partof: reflection +overview-name: Reflection + +num: 6 +language: zh-cn +--- + +EXPERIMENTAL + +**Eugene Burmako** + +遗憾的是,在scala2.10.0发布的现行状态下,反射不是线程安全的。 +这里有个JIRA问题 [SI-6240](https://issues.scala-lang.org/browse/SI-6240),它可以用来跟踪我们的进度和查找技术细节,下面是最新技术的简要总结。 + +

NEWThread safety issues have been fixed in Scala 2.11.0-RC1, but we are going to keep this document available for now, since the problem still remains in the Scala 2.10.x series, and we currently don't have concrete plans on when the fix is going to be backported.

+ +目前,在反射相关方面存在两种竞争状态。 第一是反射的初始化(当调用代码首次访问`scala.reflect.runtime.universe`时)无法从多个线程安全地调用。第二是符号的初始化(当调用代码第一次访问符号的标记或类型签名时)也不安全。 +这是一个典型的表现: + + java.lang.NullPointerException: + at s.r.i.Types$TypeRef.computeHashCode(Types.scala:2332) + at s.r.i.Types$UniqueType.(Types.scala:1274) + at s.r.i.Types$TypeRef.(Types.scala:2315) + at s.r.i.Types$NoArgsTypeRef.(Types.scala:2107) + at s.r.i.Types$ModuleTypeRef.(Types.scala:2078) + at s.r.i.Types$PackageTypeRef.(Types.scala:2095) + at s.r.i.Types$TypeRef$.apply(Types.scala:2516) + at s.r.i.Types$class.typeRef(Types.scala:3577) + at s.r.i.SymbolTable.typeRef(SymbolTable.scala:13) + at s.r.i.Symbols$TypeSymbol.newTypeRef(Symbols.scala:2754) + +好消息是,编译时反射(通过`scala.reflect.macros.Context`暴露给宏的那一种)比运行时反射(通过`scala.reflect.runtime.universe`暴露出的那一种)更不容易受到线程问题的影响。 +第一个原因是,当宏有机会运行时,编译时反射`universe`已经初始化,这规避了我们的竞争条件1。第二个理由是至今为止没有编译程序本身就是线程安全,所以没有并行执行的工具。但是,如果您的宏产生了多个线程,则你仍应该小心。 + + +不过,对于运行时反射来说,情况要糟糕得多。首次初始化`scala.reflect.runtime.universe`时,称为反射初始化,而且这种初始化可以间接发生。 +此处最突出的示例是,调用带有`TypeTag`上下文边界的方法可能会带来问题,因为调用这种方法,Scala通常需要构造一个自动生成的类型标签,该标签需要创建一个类型,并需要初始化反射`universe`。 +这个结果是,如果不采取特殊措施,就无法在测试中可靠地调用基于`TypeTag`的方法,这是因为sbt等很多工具并行执行测试。 + +汇总: +* 如果您正在编写一个没有显式创建线程的宏那就没有问题。 +* 线程或参与者(actors)混在一起的运行时反射可能很危险。 +* 多个带有`TypeTag`上下文边界的线程调用方法可能导致不确定的结果。 +* 请查看 [SI-6240](https://issues.scala-lang.org/browse/SI-6240),以了解我们在此问题上的进展。 \ No newline at end of file diff --git a/_zh-cn/overviews/reflection/typetags-manifests.md b/_zh-cn/overviews/reflection/typetags-manifests.md new file mode 100644 index 0000000000..0830e50839 --- /dev/null +++ b/_zh-cn/overviews/reflection/typetags-manifests.md @@ -0,0 +1,132 @@ +--- +layout: multipage-overview +title: TypeTags 和 Manifests +partof: reflection +overview-name: Reflection + +num: 5 +languages: zh-cn +--- + +与其他JVM语言一样,Scala的类型在运行时被擦除。这意味着,如果要检查某个实例的运行时类型,则可能无法访问Scala编译器在编译时可用的所有类型信息。 + +如`scala.reflect.Manifest`,`TypeTags`可以看作是将编译时可用的所有类型信息携带到运行时的对象。 +例如,`TypeTag[T]`封装了某个编译时类型`T`的运行时类型表示。但是请注意,`TypeTag`应该被认为是对2.10之前的`Manifest`概念的更丰富的替代品,后者还与Scala反射完全集成。 + +有三种不同类型的类型标记: + +1. `scala.reflect.api.TypeTags#TypeTag`。 +Scala类型的完整类型描述符。例如,`TypeTag[List[String]]`包含所有类型信息,在本例中是类型`scala.List[String]`。 + +2. `scala.reflect.ClassTag`。 +Scala类型的部分类型描述符。例如,`ClassTag[List[String]]`只包含已擦除、关于类的类型信息,在本例中为`scala.collection.immutable.List`。`ClassTag`只提供对类型的运行时类的访问。其类似于`scala.reflect.ClassManifest`。 + +3. `scala.reflect.api.TypeTags#WeakTypeTag`。 +抽象类型的类型描述符(参见下面相应的小节)。 + +## 获取`TypeTag` + +与`Manifest`类似,`TypeTag`总是由编译器生成,可以通过三种方式获得。 + +### 通过方法`typeTag`、`classTag`或`weakTypeTag` + +通过使用通过`Universe`提供的方法`typeTag`,就可以直接获得特定类型的`TypeTag`。 + +例如,要获取表示`Int`的`TypeTag`,我们可以执行以下操作: + + import scala.reflect.runtime.universe._ + val tt = typeTag[Int] + +或者类似地,要获得表示`String`的`ClassTag`,我们可以执行以下操作: + + import scala.reflect._ + val ct = classTag[String] + +这些方法中的每个方法都为给定的类型参数`T`构造一个`TypeTag[T]`或`ClassTag[T]`。 + +### 使用类型为`TypeTag[T]`、`ClassTag[T]`或`WeakTypeTag[T]`的隐式参数 + +与`Manifest`一样,实际上可以 _请求_ 编译器生成`TypeTag`。这只需指定一个类型为`TypeTag[T]`的隐式 _证据_ 参数即可完成。如果编译器在隐式搜索期间找不到匹配的隐式值,它将自动生成一个`TypeTag[T]`。 + +_注意_:这通常是通过在方法上使用隐式参数来实现的,并且只能在类上。 + +例如,我们可以编写一个方法,它可以接受任意对象,并且使用`TypeTag`打印有关该对象的类型参数的信息: + + import scala.reflect.runtime.universe._ + + def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = { + val targs = tag.tpe match { case TypeRef(_, _, args) => args } + println(s"type of $x has type arguments $targs") + } + +这里,我们在`T`上编写了一个参数化的泛型方法`paramInfo`,并提供了一个隐式参数`(implicit tag: TypeTag[T])`。 +那我们就可以使用`TypeTag`的方法`tpe`直接访问`tag`表示的类型(`type`类型)。 + +然后,我们可以使用方法`paramInfo`,如下所示: + + scala> paramInfo(42) + type of 42 has type arguments List() + + scala> paramInfo(List(1, 2)) + type of List(1, 2) has type arguments List(Int) + +### 使用类型参数的上下文绑定 + +要实现与上述完全相同的效果,一种不太冗长的方法是在类型参数上使用上下文绑定。不需要提供单独的隐式参数,只需在类型参数列表中包含`TypeTag`,如下所示: + + def myMethod[T: TypeTag] = ... + +给定上下文绑定的`[T: TypeTag]`,编译器只需生成类型为`TypeTag[T]`的隐式参数,这将重写方法以进行查找,就像上一节中使用隐式参数的示例一样。 + +上面重写为使用上下文边界的示例如下: + + + import scala.reflect.runtime.universe._ + + def paramInfo[T: TypeTag](x: T): Unit = { + val targs = typeOf[T] match { case TypeRef(_, _, args) => args } + println(s"type of $x has type arguments $targs") + } + + scala> paramInfo(42) + type of 42 has type arguments List() + + scala> paramInfo(List(1, 2)) + type of List(1, 2) has type arguments List(Int) + +## WeakTypeTags + +`WeakTypeTag[T]`泛化了`TypeTag`(意思是`TypeTag`是继承自`WeakTypeTag`的),`WeakTypeTag`与普通的`TypeTag`不同, + +其类型表示的组件可以是对类型参数或抽象类型的引用。但是,`WeakTypeTag[T]`试图尽可能的具体(意思是如果都存在则优先更加具体的类型(参数)),也就是说,如果类型标记可用于被引用的类型参数或抽象类型,则它们用于将具体类型嵌入到`WeakTypeTag[T]`中。 + +继续上面的例子: + + def weakParamInfo[T](x: T)(implicit tag: WeakTypeTag[T]): Unit = { + val targs = tag.tpe match { case TypeRef(_, _, args) => args } + println(s"type of $x has type arguments $targs") + } + + scala> def foo[T] = weakParamInfo(List[T]()) + foo: [T]=> Unit + + scala> foo[Int] + type of List() has type arguments List(T) + +## TypeTags and Manifests + +`TypeTag`可以大致对应2.10之前的`scala.reflect.Manifest`、 虽然`scala.reflect.ClassTag`对应于`scala.reflect.ClassManifest`而`scala.reflect.api.TypeTags#TypeTag`主要对应于`scala.reflect.Manifest`,但其他2.10版之前的`Manifest`类型与2.10版的`Tag`类型没有直接对应关系。 + +- **不支持scala.reflect.OptManifest。** +这是因为`Tag`可以具体化任意类型,所以它们总是可用的。 + +- **没有对应的scala.reflect.AnyValManifest。** +取而代之的是,可以将其`Tag`与基本`Tag`之一(在相应的伴随对象中定义)进行比较,以找出其是否代表原始值类。此外,可以简单地使用`.tpe.typeSymbol.isPrimitiveValueClass`。 + +- **无法替换Manifest伴随对象中定义的工厂方法。** +取而代之的是,可以使用Java(用于类)和Scala(用于类型)提供的反射API生成相应的类型。 + +- **不支持某些manifest操作(即`<:<`, `>:>`和`typeArguments`)。** +取而代之的是,可以使用Java(用于类)和Scala(用于类型)提供的反射API。 + +在Scala 2.10中,不建议使用`scala.reflect.ClassManifest`,而推荐使用`TypeTag`和`ClassTag`,并且计划在即将发布的版本中弃用`scala.reflect.Manifest`。因此,建议迁移任何基于`Manifest`的API以使用`Tag`。 \ No newline at end of file From d3882d6dda48502e48eb3425be29baa74a3e8948 Mon Sep 17 00:00:00 2001 From: agnesmdev Date: Thu, 1 Oct 2020 17:00:04 +0200 Subject: [PATCH 0188/2265] French translation of tour-of-scala.md --- _data/translations.yml | 2 +- _fr/tour/tour-of-scala.md | 90 +++++++++++++++++++++ _fr/tutorials/scala-for-java-programmers.md | 34 ++++---- 3 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 _fr/tour/tour-of-scala.md diff --git a/_data/translations.yml b/_data/translations.yml index 56d0fd59cf..80ab5afc1c 100644 --- a/_data/translations.yml +++ b/_data/translations.yml @@ -1,2 +1,2 @@ tour: - languages: [ba, es, ko, pt-br, pl, zh-cn, th, ru, ja] + languages: [ba, es, fr, ko, pt-br, pl, zh-cn, th, ru, ja] diff --git a/_fr/tour/tour-of-scala.md b/_fr/tour/tour-of-scala.md new file mode 100644 index 0000000000..b00cab6054 --- /dev/null +++ b/_fr/tour/tour-of-scala.md @@ -0,0 +1,90 @@ +--- +layout: tour +title: Introduction +partof: scala-tour + +num: 1 +language: fr +next-page: basics + +--- + +## Bienvenue au tour +Ce tour contient des introductions par morceaux aux fonctionnalités les plus fréquemment +utilisées en Scala. Il est adressé aux novices de Scala. + +Ceci est un bref tour du language, non pas un tutoriel complet. +Si vous recherchez un guide plus détaillé, il est préférable d'opter pour [un livre](/books.html) ou de consulter +[d'autres ressources](/learn.html). + +## Qu'est-ce que le Scala ? +Scala est un langage de programme à multiples paradigmes désigné pour exprimer des motifs de programmation communs de +façon concise, élégante et robuste. Il intègre sans problème les fonctionnalités des langages orientés objet et des +langages fonctionnels. + +## Scala est orienté objet ## +Scala est un langage purement orienté objet dans le sens où [toute valeur est un objet](unified-types.html). +Les types et les comportements de ces objets sont décrits par des [classes](classes.html) et des trait [traits](traits.html). +Les classes peuvent être étendues à travers des sous-classes et grâce à un système flexible de[composition de classes](mixin-class-composition.html). + +## Scala est fonctionnel ## +Scala est également un langage fonctionnel dans le sen où [toute fonction est une valeur](unified-types.html). +Scala propose une [syntaxe légère](basics.html#functions) pour définir des fonctions anonymes, supporte des +[fonctions de haut niveau](higher-order-functions.html), autorise les fonctions [imbriquées](nested-functions.html) et +supporte le [currying](multiple-parameter-lists.html). +Les [case class](case-classes.html) de Scala et leur système intégré de [reconnaissance de motifs](pattern-matching.html) +permettent de construire des types algébriques utilisés dans nombreux langages de programmation. +Les [objets singleton](singleton-objects.html) fournissent une façon pratique de regrouper des fonctions qui ne sont pas +membres d'une classe. + +De plus, la notion de reconnaissance de motifs de Scala s'étend naturellement au +[traitement des données XML](https://github.com/scala/scala-xml/wiki/XML-Processing) avec l'aide des +[patrons d'expressions régulières](regular-expression-patterns.html), grâce à une extension générale via des +[objets extracteurs](extractor-objects.html). Dans ce contexte, les [for comprehensions](for-comprehensions.html) sont +utiles pour formuler des requêtes. Ces fonctionnalités font de Scala un langage idéal pour développer des applications +comme des services Web. + +## Scala est fortement typé ## +Le système de type expressif de Scala renforce, à la compilation, que les abstractions sont utilisées d'une manière +sécurisée et cohérente. En particulier, ce système de type supporte : + +* Les [classes génériques](generic-classes.html) +* Les [annotations variables](variances.html) +* Les limites de type [supérieures](upper-type-bounds.html) and [inférieures](lower-type-bounds.html) +* Les [classes internes](inner-classes.html) et des membres d'objets de [types abstraits](abstract-type-members.html) +* Les [types composés](compound-types.html) +* Les [auto-références explicitement typées](self-types.html) +* Les [paramètres](implicit-parameters.html) et les [conversions](implicit-conversions.html) implicites +* Les [méthodes polymorphiques](polymorphic-methods.html) + +L'[inférence de type](type-inference.html) signifie que l'utilisateur n'est pas obligé d'annoter son code avec des +informations redondantes. Rassemblées, toutes ces fonctionnalités fournissent une base solide pour la ré-utilisation +sécurisée d'abstractions de programmation et pour une extension sûre au niveau des types de programme. + +## Scala est extensible ## + +En pratique, le développement d'applications dans un domaine spécifique demande souvent des extensions de langage propre +à ce domaine. Scala fournit une combinaison de mécaniques de langage unique qui rend simple l'ajout de nouvelles +constructions de langage avec l'importation de nouvelles librairies. + +Dans beaucoup de cas, cela peut être fait sans utiliser des outils de méta-programmation comme les macros. +En voici quelques exemples : + +* Les [classes implicites](/overviews/core/implicit-classes.html) permettent d'ajouter des méthodes supplémentaires à des types existants. +* L'[interpolation de String](/overviews/core/string-interpolation.html) est extensible par l'utilisateur avec des interpolateurs personnalisés. + +## Scala interagit ## + +Scala est conçu pour interagir proprement avec le populaire Java Runtime Environment (JRE). En particulier, l'interaction +avec le langage de programmation orienté objet le plus populaire du moment, Java, est la plus transparente possible. +Les nouvelles fonctionnalités Java comme les SAMs, les [lambdas](higher-order-functions.html), les [annotations](annotations.html), +et les [classes génériques](generic-classes.html) ont des équivalents directs en Scala. + +Il existe des fonctionnalités Scala sans équivalent Java, comme les [valeurs par défaut](default-parameter-values.html) et les +[paramètres nommés](named-arguments.html), qui se compilent d'une façon la plus proche de Java possible. Scala possède le +même modèle de compilation que Java (compilation séparée, chargement dynamique des classes) et permet d'avoir accès à des +milliers de librairies de haute qualité existantes. + +## Bon tour ! + +Merci de continuer à la [page suivante](basics.html) pour en savoir plus. diff --git a/_fr/tutorials/scala-for-java-programmers.md b/_fr/tutorials/scala-for-java-programmers.md index b89649f1fa..0b9d3ffa63 100644 --- a/_fr/tutorials/scala-for-java-programmers.md +++ b/_fr/tutorials/scala-for-java-programmers.md @@ -20,9 +20,9 @@ des connaissances de base sur la programmation orientée objet, particulièremen ## Un premier exemple -Commençons par écrire le célèbre programme *Hello world*. +Commençons par écrire le célèbre programme *Hello world*. Bien que simple, il permet de découvrir plusieurs fonctionnalités du language -avec peu de de connaissance préalable de Scala. Voilà à quoi il ressemble : +avec peu de connaissance préalable de Scala. Voilà à quoi il ressemble : object HelloWorld { def main(args: Array[String]): Unit = { @@ -106,7 +106,7 @@ l'astérisque (`*`). C'est parce que l'astérisque est un identifiant valide en un nom de méthode), comme nous le verrons plus tard. Par conséquent, la déclaration d'importation dans la seconde ligne importe tous les membres de la classe -`DateFormat`. Cela rend la méthode statique `getDateInstance` et le champ statiques `LONG` +`DateFormat`. Cela rend la méthode statique `getDateInstance` et le champ statique `LONG` directement visibles. Dans la méthode `main`, nous avons tout d'abord créé une instance de la classe Java `Date` @@ -141,7 +141,7 @@ De fait, une expression arithmétique comme la suivante : 1 + 2 * 3 / x -consiste exclusivement en des appels de méthodes, parce qu il est équivalent à l'expression +consiste exclusivement en des appels de méthodes, parce qu'il est équivalent à l'expression suivante, comme nous l'avons vu dans la section précédente : 1.+(2.*(3)./(x) @@ -250,7 +250,7 @@ malheureusement aucune règle simple pour savoir dans quel cas il est capable de ce n'est pas généralement un problème car le compilateur se plaint quand il n'est pas capable d'inférer un type qui n'a pas été donné explicitement. Une règle simple que les développeurs débutant en Scala devraient suivre est d'essayer d'omettre les déclarations de type qui semblent être faciles à -déduire et voir si le compilateur ne renvoie pas d'erreur. Après quelques temps, le développeur devrait +déduire et voir si le compilateur ne renvoie pas d'erreur. Après quelque temps, le développeur devrait avoir une bonne idée de quand il peut omettre les types et quand il faut les spécifier explicitement. ### Les méthodes sans arguments @@ -267,7 +267,7 @@ leur nom pour les appeler, comme démontré dans l'exemple suivant : Il serait plus agréable de pouvoir accéder à la partie réelle et imaginaire comme si elles étaient des champs, sans ajouter une paire de parenthèses vides. C'est parfaitement faisable en Scala, simplement en -les définissant comme des méthodes *sans argument*. De telles méthodes différents des méthodes avec +les définissant comme des méthodes *sans argument*. De telles méthodes diffèrent des méthodes avec aucun argument : elles n'ont pas de parenthèses après leur nom, que ce soit dans leur déclaration ou lors de leur utilisation. Notre classe `Complexe` peut être réécrite de cette façon : @@ -317,11 +317,11 @@ simples composées de sommes, de constantes numériques et de variables. Deux ex sont `1+2` et `(x+x)+(7+y)`. Nous devons d'abord décider d'une représentation pour de telles expressions. -La manière la plus naturelle est un arbre où chaque noeud représente une opération (ici, une addition) et +La manière la plus naturelle est un arbre où chaque nœud représente une opération (ici, une addition) et chaque feuille est une valeur (ici des constantes ou variables). En Java, un tel arbre serait représenté par une super classe abstraite pour les arbres et une -sous classe concrète pour chaque noeud et feuille. Dans un langage de programmation fonctionnelle, +sous classe concrète pour chaque nœud et feuille. Dans un langage de programmation fonctionnelle, on utiliserait plutôt un type de donnée algébrique pour faire la même chose. Scala fournit le concept de *case class* qui est quelque part entre ces deux concepts. Voici comment elles peuvent être utilisées pour définir le type des arbres pour notre exemple : @@ -347,7 +347,7 @@ différent des classes traditionnelles en différents points : comme nous le verrons plus bas. Maintenant que nous avons défini le type de données pour représenter nos expressions arithmétiques, -il est temps de définir des opérations pour les manipuler. Nous allons commencer avec une fonction +il est temps de définir des opérations pour les manipuler. Nous allons commencer par une fonction pour évaluer une expression dans un certain *environnement*. Le but de cet environnement est de donner des valeurs aux variables. Par exemple, l'expression `x+1` évaluée dans un environnement qui associe la valeur `5` à la variable `x`, écrit `{ x -> 5 }`, donne comme résultat `6`. @@ -398,11 +398,11 @@ devrait être claire : motif décrit à gauche de la flèche ; 2. Si la première vérification échoue, c'est-à-dire que l'arbre n'est pas une `Somme`, on continue et on vérifie si `a` est une `Var`. Si c'est le cas, - il relie le nom contenu dans le noeud `Var` à une variable `n` et + il relie le nom contenu dans le nœud `Var` à une variable `n` et il traite l'expression à droite de la flèche ; 3. Si la deuxième vérification échoue, c'est-à-dire que l'arbre n'est ni une `Somme` ni une `Var`, on vérifie si l'arbre est un `Const`. Si - c'est le cas, il relie la valeur contenue dans le noeud `Const` à une + c'est le cas, il relie la valeur contenue dans le nœud `Const` à une variable `v` et il traite l'expression à droite de la flèche ; 4. Enfin, si toutes les vérifications échouent, une exception est levée pour signaler l'échec de l'expression. Dans notre cas, cela pourrait arriver si @@ -420,13 +420,13 @@ la définition de méthodes dans les case class tout comme dans les classes norm Décider d'utiliser un pattern matching ou des méthodes est donc une question de goût mais a aussi des implications importantes sur l'extensibilité : -- quand on utilise des méthodes, il est facile d'ajouter un nouveau type de noeud en même temps +- quand on utilise des méthodes, il est facile d'ajouter un nouveau type de nœud en même temps qu'une nouvelle sous classe de `Arbre` est définie. Par contre, ajouter une nouvelle opération pour manipuler un arbre est fastidieux car il demande de modifier toutes les sous classes de `Arbre` ; - quand on utilise un pattern matching, la situation est inversée : ajouter un - nouveau type de noeud demande la modification de toutes les fonctions qui effectuent - un pattern matching sur un arbre pour prendre en compte le nouveau noeud. + nouveau type de nœud demande la modification de toutes les fonctions qui effectuent + un pattern matching sur un arbre pour prendre en compte le nouveau nœud. Par contre, ajouter une nouvelle opération est facile en la définissant en tant que fonction indépendante. @@ -439,7 +439,7 @@ garder à l'esprit les règles suivantes par rapport à cette opération : variable utilisée pour la dérivation et zéro sinon ; 3. la dérivée d'une constante est zéro. -Ces règles peut être traduites presque littéralement en du code Scala +Ces règles peuvent presque être traduites littéralement en du code Scala pour obtenir la définition suivante : def derivee(a: Arbres, v: String): Arbres = a match { @@ -503,7 +503,7 @@ Notez que depuis Java 8, les interfaces Java peut aussi contenir du code, soit en utilisant le mot clé `default` soit avec des méthodes statiques. Pour s'apercevoir de l'utilité des traits, regardons un exemple classique : -les objets ordonnés. Il est souvent utile de pouvoir comparer entre eux des objets +les objets ordonnés. Il est souvent utile de pouvoir comparer des objets d'une même classe, par exemple pour les trier. En Java, les objets qui sont comparables implémentent l'interface `Comparable`. En Scala, on peut faire un peu mieux qu'en Java en définissant @@ -616,7 +616,7 @@ Les développeurs Java se retrouvent à utiliser `Object`, le super type de tous les objets. Cependant, cette solution est loin d'être idéale, puisqu'elle ne marche pas pour les types basiques (`int`, `long`, `float`, etc.) et cela implique que le développeur -devra faire un certain nombre de conversion de types. +devra faire un certain nombre de conversions de types. Scala rend possible la définition de classes (et de méthodes) génériques pour résoudre ce problème. Examinons ceci au travers d'un exemple d'une From 6de339488e92b47d9d3586dcf687efa4ee2a7160 Mon Sep 17 00:00:00 2001 From: Leo Benkel Date: Mon, 19 Oct 2020 21:26:26 -0700 Subject: [PATCH 0189/2265] Fix french --- _fr/tour/tour-of-scala.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_fr/tour/tour-of-scala.md b/_fr/tour/tour-of-scala.md index b00cab6054..f752f64ed5 100644 --- a/_fr/tour/tour-of-scala.md +++ b/_fr/tour/tour-of-scala.md @@ -10,7 +10,7 @@ next-page: basics --- ## Bienvenue au tour -Ce tour contient des introductions par morceaux aux fonctionnalités les plus fréquemment +Ce tour contient une introduction morceaux par morceaux aux fonctionnalités les plus fréquemment utilisées en Scala. Il est adressé aux novices de Scala. Ceci est un bref tour du language, non pas un tutoriel complet. @@ -18,14 +18,14 @@ Si vous recherchez un guide plus détaillé, il est préférable d'opter pour [u [d'autres ressources](/learn.html). ## Qu'est-ce que le Scala ? -Scala est un langage de programme à multiples paradigmes désigné pour exprimer des motifs de programmation communs de +Scala est un langage de programmation à multiples paradigmes désigné pour exprimer des motifs de programmation communs de façon concise, élégante et robuste. Il intègre sans problème les fonctionnalités des langages orientés objet et des langages fonctionnels. ## Scala est orienté objet ## Scala est un langage purement orienté objet dans le sens où [toute valeur est un objet](unified-types.html). Les types et les comportements de ces objets sont décrits par des [classes](classes.html) et des trait [traits](traits.html). -Les classes peuvent être étendues à travers des sous-classes et grâce à un système flexible de[composition de classes](mixin-class-composition.html). +Les classes peuvent être étendues à travers des sous-classes et grâce à un système flexible de [composition de classes](mixin-class-composition.html). ## Scala est fonctionnel ## Scala est également un langage fonctionnel dans le sen où [toute fonction est une valeur](unified-types.html). @@ -33,7 +33,7 @@ Scala propose une [syntaxe légère](basics.html#functions) pour définir des fo [fonctions de haut niveau](higher-order-functions.html), autorise les fonctions [imbriquées](nested-functions.html) et supporte le [currying](multiple-parameter-lists.html). Les [case class](case-classes.html) de Scala et leur système intégré de [reconnaissance de motifs](pattern-matching.html) -permettent de construire des types algébriques utilisés dans nombreux langages de programmation. +permettent de construire des types algébriques utilisés dans de nombreux langages de programmation. Les [objets singleton](singleton-objects.html) fournissent une façon pratique de regrouper des fonctions qui ne sont pas membres d'une classe. @@ -45,13 +45,13 @@ utiles pour formuler des requêtes. Ces fonctionnalités font de Scala un langag comme des services Web. ## Scala est fortement typé ## -Le système de type expressif de Scala renforce, à la compilation, que les abstractions sont utilisées d'une manière +A la compilation, le système de type expressif de Scala renforce l'utilisation des abstractions d'une manière sécurisée et cohérente. En particulier, ce système de type supporte : * Les [classes génériques](generic-classes.html) * Les [annotations variables](variances.html) * Les limites de type [supérieures](upper-type-bounds.html) and [inférieures](lower-type-bounds.html) -* Les [classes internes](inner-classes.html) et des membres d'objets de [types abstraits](abstract-type-members.html) +* Les [classes internes](inner-classes.html) et les membres d'objets de [types abstraits](abstract-type-members.html) * Les [types composés](compound-types.html) * Les [auto-références explicitement typées](self-types.html) * Les [paramètres](implicit-parameters.html) et les [conversions](implicit-conversions.html) implicites @@ -67,7 +67,7 @@ En pratique, le développement d'applications dans un domaine spécifique demand à ce domaine. Scala fournit une combinaison de mécaniques de langage unique qui rend simple l'ajout de nouvelles constructions de langage avec l'importation de nouvelles librairies. -Dans beaucoup de cas, cela peut être fait sans utiliser des outils de méta-programmation comme les macros. +Dans beaucoup de cas, cela peut être fait sans utiliser des outils de méta-programmation, comme les macros. En voici quelques exemples : * Les [classes implicites](/overviews/core/implicit-classes.html) permettent d'ajouter des méthodes supplémentaires à des types existants. @@ -83,7 +83,7 @@ et les [classes génériques](generic-classes.html) ont des équivalents directs Il existe des fonctionnalités Scala sans équivalent Java, comme les [valeurs par défaut](default-parameter-values.html) et les [paramètres nommés](named-arguments.html), qui se compilent d'une façon la plus proche de Java possible. Scala possède le même modèle de compilation que Java (compilation séparée, chargement dynamique des classes) et permet d'avoir accès à des -milliers de librairies de haute qualité existantes. +milliers de librairies de haute qualité. ## Bon tour ! From f0940acb93b2e33a91ab7001cae3045b9321d0fd Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Wed, 21 Oct 2020 09:57:11 -0600 Subject: [PATCH 0190/2265] =?UTF-8?q?Initial=20versions=20of=20the=20?= =?UTF-8?q?=E2=80=98Methods=E2=80=99=20and=20=E2=80=98Scala=20for=20Python?= =?UTF-8?q?=20Developers=E2=80=99=20documents.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/methods-and-functions.md | 380 ++++++ _overviews/overview/scala-for-python-devs.md | 1094 ++++++++++++++++++ 2 files changed, 1474 insertions(+) diff --git a/_overviews/overview/methods-and-functions.md b/_overviews/overview/methods-and-functions.md index e69de29bb2..86688f6461 100644 --- a/_overviews/overview/methods-and-functions.md +++ b/_overviews/overview/methods-and-functions.md @@ -0,0 +1,380 @@ +--- +title: Scala 3 Methods +description: This section introduces methods and functions in Scala 3. +--- + + + +In Scala 2, _methods_ can be defined inside classes, traits, objects, case classes, and case objects. But it gets better: In Scala 3 they can also be defined _outside_ any of those constructs with a new feature named Toplevel definitions. In short, methods can now be defined anywhere. + +This section demonstrates many of the basic features of defining and calling methods. + + + +## Defining methods + +Scala’s general method syntax looks like this: + +```scala +def methodName(param1: Type1 = defaultValue1, param2: Type2 = defaultValue2): ReturnType = + // the method body + // goes here +end methodName // this is optional +``` + +In that syntax: + +- The keyword `def` is used to define a method +- The Scala standard is to name methods using the camel case convention +- Method parameters are always defined with an accompanying type +- Parameters can also have default values +- Declaring the method return type is optional +- Methods can consist of many lines, or just one line +- Providing the `end methodName` portion after the method body is also optional, and is only recommended for long methods + +Here are two examples of a one-line method named `add` that takes two `Int` input parameters. The first version explicitly shows the method’s `Int` return type, and the second does not: + +```scala +def add(a: Int, b: Int): Int = a + b +def add(a: Int, b: Int) = a + b +``` + +Because Scala is an expressive language, a surprising number of methods end up being only one line. + + + +## Calling methods + +Invoking a method is straightforward: + +```scala +val x = add(1, 2) // 3 +``` + +The Scala collections classes have dozens of built-in methods. Here are a few examples of how to call their methods: + +```scala +val x = List(1,2,3) + +x.size // 3 +x.contains(1) // true +x.map(_ * 10) // List(10, 20, 30) +``` + +Notice: + +- `size` takes no arguments, and returns the number of elements in the list +- The `contains` method takes one argument, the value to search for +- `map` takes one argument, a function; in this case an anonymous function is passed into it + + + +## Multiline methods + +When a method is longer than one line, start the method body on the second line, indented to the right: + +```scala +def addThenDouble(a: Int, b: Int): Int = + // imagine that this takes multiple lines + val sum = a + b + sum * 2 +``` + +In that method: + +- `sum` is an immutable local variable; it can’t be accessed outside of the method +- The last line doubles the value of `sum`; this result is the value that’s yielded by the method + +When you paste that code into the REPL, you’ll see that it works as desired: + +```scala +scala> addThenDouble(1, 1) +res0: Int = 4 +``` + +Notice in this example that there’s no need for a `return` statement at the end of the method. Because everything in Scala is an _expression_ — meaning that each line of code returns (or _evaluates to) a value — there’s no need to add `return` to an expression. + +This becomes more clear when you condense that method and write it on one line: + +```scala +def addThenDouble(a: Int, b: Int): Int = (a + b) * 2 +``` + +Methods can contain any lines of code you desire: + +- `if`/`else` expressions +- `match` expressions +- `while` loops +- `for` loops and `for` expressions +- Variable assignments +- Calls to other methods + +As an example of a real-world multiline method, this `getStackTraceAsString` method converts its `Throwable` input parameter into a well-formatted `String`: + +```scala +def getStackTraceAsString(t: Throwable): String = + val sw = new StringWriter + t.printStackTrace(new PrintWriter(sw)) + sw.toString +``` + +In that method: + +- The first line is a variable-assignment expression +- The second line is a statement; it puts the stack trace content into the `StringWriter` +- The third line yields the `String` representation of the stack trace + +>Lines of code that don’t return values are called _statements_, and they’re used for their side-effects. Conversely, _expressions_ always return a result and generally do not have side effects. As you learn more about Scala you’ll find yourself writing more expressions and fewer statements. + + +## Default parameter values + +Method parameters can have default values. In this example, default values are given for both the `timeout` and `protocol` parameters: + +```scala +def makeConnection(timeout: Int = 5_000, protocol: String = "http") = + println(f"timeout = ${timeout}%d, protocol = ${protocol}%s") + // more code here ... +``` + +Because the parameters have default values, the method can be called in these ways: + +```scala +makeConnection() // timeout = 5000, protocol = http +makeConnection(2_000) // timeout = 2000, protocol = http +makeConnection(3_000, "https") // timeout = 3000, protocol = https +``` + +Here are a few key points about those examples: + +- In the first example no arguments are provided, so the method uses the default parameter values of `5_000` and `http` +- In the second example, `2_000` is supplied for the `timeout` value, so it’s used, along with the default value for the `protocol` +- In the third example, values are provided for both parameters, so they’re both used + +Notice that by using default parameter values, it appears to the consumer that they can use three different overridden methods. + + + +## Using named parameters + +If you prefer, you can also use the names of the method parameters when calling a method. For instance, `makeConnection` can also be called in these ways: + +```scala +makeConnection(timeout=10_000) +makeConnection(protocol="https") +makeConnection(timeout=10_000, protocol="https") +makeConnection(protocol="https", timeout=10_000) +``` + +In some frameworks named parameters heavily used. They’re also very useful when multiple method parameters have the same type: + +```scala +engage(true, true, true, false) +``` + +Without help from an IDE that code can be hard to read, but this code is much more clear and obvious: + +```scala +engage( + speedIsSet = true, + directionIsSet = true, + picardSaidMakeItSo = true, + turnedOffParkingBrake = false +) +``` + + + +## A suggestion about methods that take no parameters + +When a method takes no parameters, it’s said to have an _arity_ level of _arity-0_. Similarly, when a method takes one parameter it’s an _arity-1_ method. When you create arity-0 methods: + +- If the method has side effects, such as calling `println`, declare the method with empty parentheses +- If the method does not have side effects — such as getting the size of a collection, which is similar to accessing a field on the collection — leave the parentheses off + +For example, this method has a side effect, so it’s declared with empty parentheses: + +```scala +def speak() = println("hi") +``` + +Doing this requires callers of the method to use open parentheses when calling the method: + +```scala +speak // error: "method speak must be called with () argument" +speak() // prints "hi" +``` + +While this is just a convention, following it dramatically improves code readability: It makes it easier to understand at a glance that an arity-0 method has side effects. + + + +## Using an `if` expression as a method body + +Because `if`/`else` expressions return a value, they can be used as the body of a method. Here’s a method named `isTrue` that implements the Perl definitions of `true` and `false`: + +```scala +def isTrue(a: Any) = + if a == 0 || a == "" + false + else + true +``` + +These examples show how that method works: + +```scala +isTrue(0) // false +isTrue("") // false +isTrue("hi") // true +isTrue(1.0) // true +``` + + +## Using a `match` expression as a method body + +A `match` expression can also be used as the entire method body, and often is. Here’s another version of `isTrue`, written with a `match` expression : + +```scala +def isTrue(a: Any) = a match + case 0 | "" => false + case _ => true +``` + +This method works just like the previous method that used an `if`/`else` expression. + + + +## Controlling method scope in classes + +In classes, objects, and traits, Scala methods are public by default, so the `Dog` instance created here can access the `speak` method: + +```scala +class Dog: + def speak() = println("Woof") + +val d = new Dog +d.speak() // prints "Woof" +``` + +Methods can also be marked as `private`. This makes them private to the current class, and they can’t be overridden in subclasses: + +```scala +class Animal: + private def breathe() = println("I’m breathing") + +class Cat extends Animal: + // this method won’t compile + override def breathe() = println("Yo, I’m totally breathing") +``` + +If you want to make a method private to the current class and also allow subclasses to override it, mark the method as `protected`, as shown with the `speak` method in this example: + +```scala +class Animal: + private def breathe() = println("I’m breathing") + def walk() = + breathe() + println("I’m walking") + protected def speak() = println("Hello?") + +class Cat extends Animal: + override def speak() = println("Meow") + +val cat = new Cat +cat.walk() +cat.speak() +cat.breathe() // won’t compile because it’s private +``` + +The `protected` setting means: + +- The method (or field) can be accessed by other instances of the same class +- It is not visible by other code in the current package +- It is available to subclasses + +For more details on controlling the scope of methods in classes, traits, and objects, see the Reference documentation. + + + +## Objects can contain methods + +Earlier you saw that traits and classes can have methods. The Scala `object` keyword is used to create a singleton class, and an object can also contain methods. This is a nice way to create a set of “utility” methods. For instance, this object contains a collection of methods that work on strings: + +```scala +object StringUtils: + + /** + * Returns a string that is the same as the input string, but + * truncated to the specified length. + */ + def truncate(s: String, length: Int): String = s.take(length) + + /** + * Returns true if the string contains only letters and numbers. + */ + def lettersAndNumbersOnly_?(s: String): Boolean = s.matches("[a-zA-Z0-9]+") + + /** + * Returns true if the given string contains any whitespace at all. + * Assumes that `s` is not null. + */ + def containsWhitespace(s: String): Boolean = s.matches(".*\\s.*") + +end StringUtils +``` + + + +## Extension methods + +Extension methods let you add methods to a type after the type is defined. This example shows how to create an extension method named `circumference` on a previously-defined `Circle` class: + +```scala +case class Circle(x: Double, y: Double, radius: Double) + +extension (c: Circle) + def circumference: Double = c.radius * math.Pi * 2 +``` + +In this example, you may have written the `Circle` class, or it might be a part of some third-party library. The important part is that this approach adds the `circumference` method to the `Circle` class, so it can be used just as though it was defined inside `Circle`: + +```scala +val circle = Circle(0, 0, 1) +circle.circumference +``` + +The `extension` keyword declares that you’re about to define one or more extension methods on the type that’s put in parentheses. As shown with this example, the parameter `c` can then be used in the body of your extension methods. + +Here’s another example that shows how to define methods with symbolic names — i.e., what appears to be an operator on a `String`: + +```scala +extension (x: String) + def < (y: String): Boolean = x.length < y.length + +"ab" < "c" // false +``` + +In this example the `<` definition overrides the default `<` on the `String` class. + + + +## Even more + +There’s even more to know about methods, including how to: + +- Call methods on superclasses +- Define and use by-name parameters +- Write a method that takes a function parameter +- Create inline methods +- Handle exceptions +- Use vararg input parameters +- Write methods that have multiple parameter groups (partially-applied functions) +- Create methods that have generic type parameters + +See the Reference documentation for more details on these features. + + + + + diff --git a/_overviews/overview/scala-for-python-devs.md b/_overviews/overview/scala-for-python-devs.md index e69de29bb2..2f68168bc8 100644 --- a/_overviews/overview/scala-for-python-devs.md +++ b/_overviews/overview/scala-for-python-devs.md @@ -0,0 +1,1094 @@ +--- +title: Scala for Python Developers +description: This page is for Python developers who are interested in learning about Scala 3. +--- + +

Notes to reviewers:

+
    +
  1. This page will eventually link to many other pages. So if you +wonder why I don’t explain certain things in more detail, it’s +because (a) I’m trying to keep this page short, and (b) I assume +this page will eventually link to dozens of other pages for more +details.
  2. +
  3. I’m initially submitting this page as HTML because it’s much +easier to work on these side-by-side source code examples with a +Wysiwyg editor (I’m using SeaMonkey). I’ll convert it to +Markdown when we’re confident with the content in those tables. +If at all possible, I think the side-by-side code examples are +the best approach.
  4. +
  5. I haven’t formatted the multiline source code examples inside +table cells because I think it will be easier to convert them to +Markdown if I don’t do that now. (My initial conversion tests +with Pandoc showed that the conversion will be smoother by not +using <code> tags on those multiline +examples.)
  6. +
+
+


+

+

This section provides a comparison between the Python and Scala +programming languages. It’s intended for programmers who know +Python and want to learn about Scala, specifically by seeing how +Python language features compare to Scala.

+

Introduction
+

+

This section provides a summary of the similarities and +differences between Python and Scala. The two languages are first +compared at a high level, and then at an everyday programming +level.

+

High level similarities
+

+

At a high level, Scala shares these similarities with +Python:
+

+
    +
  • Both are high-level programming languages, where you don’t +have to concern yourself with low-level concepts like pointers +and manual memory management
  • +
  • Both have a relatively simple, concise syntax
    +
  • +
  • Both are object-oriented programming (OOP) languages
  • +
  • Both have comprehensions: Python has list comprehensions and +Scala has for comprehensions
  • +
  • Both languages have support for lambdas and higher-order +functions
  • +
  • Both can be used with Apache Spark for big data processing
  • +
  • Both have a wealth of terrific libraries
  • +
+

High level differences
+

+

Also at a high level, the differences between Python and +Scala are:
+

+
    +
  • Python is dynamically typed, and Scala is statically typed
    +
  • +
      +
    • Though it’s statically typed, type inference makes Scala +feel like a dynamic language
    • +
    +
  • In addition to being an OOP language, Scala is also a pure FP +language
  • +
  • Python is interpreted, and Scala code is compiled to .class +files, and runs on the Java Virtual Machine (JVM)
  • +
  • In addition to running on the JVM, the Scala.js project lets you +use Scala as a JavaScript replacement
  • +
  • The Scala +Native project adds low-level constructs to let you write +“systems” level code, and compiles to native executables
  • +
  • Everything in Scala is an expression: constructs like +if statements, for loops, match +expressions, and even try/catch +expressions all have return values
    +
  • +
  • Scala idioms favor immutability by default: you’re encouraged +to use immutable variables and immutable collections
  • +
  • Scala has excellent support for concurrent and parallel +programming
    +
  • +
+

Programming level similarities

+

This section looks at the similarities you’ll see between Python +and Scala when you write code on an every day basis:
+

+
    +
  • Scala’s type inference often makes it feel like a dynamically +typed language
    +
  • +
  • Neither language uses semi-colons to end expressions
    +
  • +
  • Both languages support the use of significant indentation +rather than braces and parentheses
  • +
  • The syntax for defining methods is similar
  • +
  • Both have lists, dictionaries (maps), sets, and tuples
  • +
  • Both have comprehensions for mapping and filtering
  • +
  • Both have higher-order functions and strong support for +lambdas
  • +
+

Programming level differences

+

Also at a programming level, these are some of the differences +you’ll see every day when writing code:
+

+
    +
  • Scala’s syntax is extremely consistent
  • +
      +
    • Lists, maps, sets, and tuples are all created and accessed +similarly; they have most of the same higher-order functions; +val and var fields are used +consistently +when defining fields and parameters; pattern matching is used +consistently; more
      +
    • +
    +
  • Scala variables and parameters are defined with the val +(immutable) or var (mutable) keywords
    +
  • +
  • Scala idioms prefer immutable data structures
    +
  • +
  • Scala has terrific IDE support
  • +
  • Comments: Python uses #, Scala uses the C, C++, +and +Java style: //, /*...*/, and /**...*/
    +
  • +
  • Naming conventions: Python is my_list, Scala is +myList
    +
  • +
  • Scala is statically typed, so you declare types for method +parameters, method return values, and in other places
    +
  • +
  • Pattern matching and match expressions are used +extensively in Scala, and will change the way you write code
  • +
  • Toplevel definitions let you put method, field, and +other definitions anywhere, also leading to concise, expressive +code
    +
  • +
  • Traits are used heavily in Scala; interfaces and abstract +classes are used less often in Python
    +
  • +
  • Scala’s contextual abstractions and term inference +provide a collection of different features:
    +
  • +
      +
    • Extension methods let you add new functionality to +closed classes
    • +
    • Given instances let you define terms that the +compiler can synthesize at using points, making your +code less verbose and essentially letting the compiler write +code for you
      +
    • +
    • Multiversal equality lets you limit equality +comparisons — at compile time — to only those comparisons that +make sense
      +
    • +
    +
  • Scala has state-of-the-art open source functional programming +libraries
  • +
  • You can create your own “control structures” and DSLs, thanks +to features like objects, by-name parameters, infix notation, +optional parentheses, extension methods, higher-order functions, +and more
    +
  • +
  • Many other goodies: case classes, companion classes and +objects, macros, union and intersection types, toplevel +definitions, numeric literals, multiple parameter lists, +and more
  • +
+

TODO: mention compiling code; mention performance?

+


+

+
    +
+

Features compared with examples

+

Given that introduction, the following sections provide +side-by-side comparisons of Python and Scala programming language +features.

+


+

+

Comments

+

The Scala comments syntax is the same as languages like C, C++, +and Java:

+ + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Comments
+
#
+
//
+/* ... */
+/** ... */
+


+

+

Variable assignment
+

+

These examples demonstrate how to create variables in Python and +Scala:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Integer,
+String
+
x = 1
+x = "Hi"
+
val x = 1
+val x = "Hi"
+
List
+
x = [1,2,3]
+
val x = List(1,2,3)
+
Dictionary/Map
+
x = {
+  "Toy Story": 8.3,
+  "Forrest Gump": 8.8,
+  "Cloud Atlas": 7.4
+}
+
val movies = Map(
+  "Toy Story" -> 8.3,
+  "Forrest Gump" -> 8.8,
+  "Cloud Atlas" -> 7.4
+)
+
Set
+
x = {1,2,3}
+
val x = Set(1,2,3)
+
Tuple
+
x = (11, "Eleven")val x = (11, "Eleven")
+

If a Scala field is going to be mutable, you should use var +instead of val for variable assignment:

+
var x = 1
x += 1
+

However, the rule of them is to always use val +unless +the variable specifically needs to be mutated.
+

+


+

+

OOP style classes and methods

+

This section provides comparisons of features related to +OOP-style classes and methods.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
OOP style class,
+primary constructor
+
class Person(object):
+  def __init__(self, name):
+    self.name = name
+
+  def speak(self):
+    print('Hello, my name is %s' % self.name)
+
class Person (var name: String):
+  def speak() = println(s"Hello, my name is $name")
+
Create and use an instance
+
p = Person("John")
+p.name   # John
+p.name = 'Fred'
+p.name   # Fred
+p.speak()
+
val p = Person("John")
+p.name   // John
+p.name = "Fred"
+p.name   // Fred
+p.speak()
+
Method, one line
+
def add(a,b) = a + b
+
def add(a: Int, b: Int): Int = a + b
+
Method, multiple lines
+
def walkThenRun():
+    print('walk')
+    print('run')
+
def walkThenRun() =
+  println("walk")
+  println("run")
+
+


+

+

Interfaces, traits, and inheritance

+

If you’re familiar with Java 8 and newer, Scala traits are +similar to those Java interfaces. Traits are used all the time in +Scala, while Python interfaces and abstract classes are used much +less often. Therefore, rather than attempt to compare the two side +by side, this example shows how to use Scala traits to build a +small solution to a simulated math problem.

+
trait Adder:
  def add(a: Int, b: Int) = a + b
+trait Multiplier: +  def multiply(a: Int, b: Int) = a * b

// create a class from the traits +class SimpleMath extends Adder, Multiplier
val sm = new SimpleMath
sm.add(1,1) // 2
sm.multiply(2,2) // 4
+

There are many other ways to use traits with classes and objects, +but this gives you a little idea of how they can be used to +organize concepts into logical groups of behavior, and then merge +them as needed to create a complete solution.
+

+
+

Control structures

+

+

This section compares control structures in Python and Scala. +Both languages have constructs like if/else, +while, +for loops, and try. Scala also has match +expressions.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
if statement,
+one line
+
if x == 1: print(x)
+
if x == 1 then println(x)
+
if statement,
+multiline
+
if x == 1:
+    print("x is 1, as you can see:")
+    print(x)
+
if x == 1 then
+  println("x is 1, as you can see:")
+  println(x)
+
if/else-if/else
+
if x < 0:
+    print("negative")
+elif x == 0:
+    print("zero")
+else:
+    print("positive")
+
if x < 0 then
+  println("negative")
+else if x == 0
+  println("zero")
+else
+  println("positive")
+
Returning a value from ifmin_val = a if a < b else bval minValue = if a < b then a else +b
if as the body of a method
+
def min(a, b):
+    return a if a < b else b
+
def min(a: Int, b: Int): Int =
+  if a < b then a else b
+
while
+
i = 1
+while i < 3:
+    print(i)
+    i += 1
+
var i = 1
+while i < 3 do
+  println(i)
+  i += 1
+
for loop with range
+
for i in range(0,3):
+    print(i)
+
// preferred
+for i <- 0 until 3 do println(i)
+
+// also available
+for (i <- 0 until 3) println(i)
+
+// multiline syntax
+for
+  i <- 0 until 3
+do
+  println(i)
for loop with a list
+
for i in ints: print(i)
+
+for i in ints:
+    print(i)
+
for i <- ints do println(i)   // +preferred
+
+for (i <- ints) println(i)   // also available
for loop,
+multiple lines
for i in ints:
+    x = i * 2
+    s = "i = {}, x = {}"
+    print(s.format(i,x))
for
+  i <- ints
+do
+  val x = i * 2
+  println(s"i = $i, x = $x")
+
Multiple range generators
+
for i in range(1,3):
+    for j in range(4,6):
+        for k in +range(1,10,3):
+            + + +s += "i = {}, j = {}, k = {}"
+            +print(s.format(i,j,k))
+
+
for
+  i <- 1 to 2
+  j <- 4 to 5
+  k <- 1 until 10 by 3
+do
+  println(s"i = $i, j = $j, k = $k")
+
Generator with guards (if +expressions)
+
for i in range(1,11):
+    if i % 2 == 0:
+        if i < 5:
+            +print(i)
+
+
for
+  i <- 1 to 10
+  if i % 2 == 0
+  if i < 5
+do
+  println(i)
+
Same as previous, with the if +statements condensed to one line
+
for i in range(1,11):
+    if i % 2 == 0 and i < 5:
+            +print(i)
+
for
+  i <- 1 to 10
+  if i % 2 == 0 && i < 5
+do
+  println(i)
Comprehensions: list comprehension in +Python, for comprehension in Scala
+
x = [i*10 for i in range(1,4)]
+
+# result: [10,20,30]
+
val x =
+  for
+    i <- 1 to 3
+  yield
+    i * 10
+// result: Vector(10, 20, 30)
+
match expressionsN/A (can use dictionaries for basic switch +functionality)
+
val monthAsString = day match {
+  case 1 => "January"
+  case 2 => "February"
+  _ => "Other"
+}
+
switch/match: +handling
+multiple conditions
+per case
+
N/A
+
val numAsString = i match {
+  case 1 | 3 | 5 | 7 | 9 => println("odd")
+  case 2 | 4 | 6 | 8 | 10 => println("even")
+  case _ => println("too big")
+}
+
try/catch/finally
+
try:
+    print(a)
+except NameError:
+    print("NameError")
+except:
+    print("Other")
+finally:
+    print("Finally")
+
try
+  writeTextToFile(text)
+catch
+  case ioe: IOException => println("Got an +IOException.")
+  case nfe: FileNotFoundException => println("Got a +FileNotFoundException.")
+finally
+  println("Finally")
+
+

Scala has many more match expression features; only +a +few are shown here.

+


+

+

Collections classes

+

This section compares the collections classes that are available +in Python and Scala, including lists, dictionaries/maps, sets, and +tuples.
+

+

Lists
+

+

Where Python has its list, Scala has several different +specialized mutable and immutable sequence classes, depending on +your needs. Because the Python list is mutable, it most directly +compares to Scala’s ArrayBuffer.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Python list,
+Scala sequences
+
a = [1,2,3]
+
// many different sequence classes
+val a = List(1,2,3)
+val a = Vector(1,2,3)
+val a = ArrayBuffer(1,2,3)
+
Access elements
+
a[0]
+a[1]
+
a(0)
+a(1)
+
Update list elements
+
a[0] = 10
+a[1] = 20
+
// ArrayBuffer is mutable
+a(0) = 10
+a(1) = 20
+
Combine two lists
+
c = a + bval c = a ++ b
Iterate over a list with a for +loop
+
for i in ints: print(i)
+
+for i in ints:
+    print(i)
for i <- ints do println(i)   // +preferred
+
+for (i <- ints) println(i)   // also available
+

Scala’s main three sequence classes are List, Vector, +and ArrayBuffer. The List and Vector +classes are the main classes to use when you want an immutable +sequence. The ArrayBuffer class is the main class to +use when you want a mutable sequence. (A “buffer” in Scala is a +sequence that can grow and shrink.)
+

+


+

+

Dictionary/Map

+

The Python dictionary is like the mutable Scala Map +class.

+ + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Creation
+
my_dict = {
+    'a': 1,
+    'b': 2,
+    'c': 3
+}
+
val myMap = Map(
+  "a" -> 1,
+  "b" -> 2,
+  "c" -> 3
+)
+
Access elements
+
my_dict['a']   # 1
+
myMap("a")   // 1
+
for loop
+
for key, value in my_dict.items():
+    print(key)
+    print(value)
+
for
+  (key,value) <- myMap
+do
+  println(key)
+  println(value)
+
+

Scala has other specialized Map classes for +different needs.
+

+

Sets

+

The Python set is like the mutable Scala Set class. +

+ + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Creation
+
+ +set = {"a", "b", "c"} val set = Set(1,2,3)
+

+
set = {1,2,1}
+# result: {1,2}
+
val set = Set(1,2,1)
+// result: Set(1,2)
+
+

Scala has other specialized Set classes for +different needs.

+

Tuples
+

+

The Python and Scala tuples are also similar:

+ + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Creation
+
t = (11, 11.0, "Eleven")
+
val t = (11, 11.0, "Eleven")
+
Access elements
+
t[0]   # 11
+t[1]   # 11.0
+
t(0)   // 11
+t(1)   // 11.0
+
+


+

+

Methods on collections classes

+

Python and Scala have several of the same common functional +methods available to them:

+
    +
  • map
  • +
  • filter
  • +
  • reduce
    +
  • +
+

If you’re used to using these methods with lambda expressions in +Python, you’ll see that Scala has a similar approach with methods +on its collections classes. To demonstrate this functionality, +here are two sample lists:
+

+
list = (1,2,3)    // python
val list = List(1,2,3)   // scala
+

Given those lists, this table shows how to apply mapping and +filtering algorithms to it:
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method
+
Python
+
Scala
+
Mapping with a comprehension
+
x = [i*10 for i in list]val x = for i <- list yield i * 10
+
Filtering with a comprehensionevens = [i for i in list if i % 2 == 0]val evens = list.filter(_ % 2 == 0)
Mapping and filtering with a comprehensionx = [i * 10 for i in list if i % 2 == +0]val x = xs.filter(_ % 2 == 0)
+           +.map(_ * 10)
Mapping with map
+
def times_10(n): return n * 10
+x = map(times_10, list)
+
val x = list.map(_ * 10)
+
Filtering with filter
+
f = lambda x: x if x > 1 else 1
+x = filter(f, list)
+
val x = list.filter(_ > 1)
+

Scala collections classes have over 100 functional methods to +simplify your code. In addition to map, filter, +and reduce, other commonly-used methods are listed +below.

+

Filtering methods:

+
    +
  • diff
  • +
  • distinct
    +
  • +
  • drop
    +
  • +
  • filter
  • +
  • head
  • +
  • slice
    +
  • +
  • tail
    +
  • +
+

Transformer methods:

+
    +
  • collect
  • +
  • flatten
    +
  • +
  • flatMap
  • +
  • fold
    +
  • +
  • map
  • +
  • reduce
    +
  • +
  • sortWith
    +
  • +
+

Grouping methods:

+
    +
  • groupBy
  • +
  • partition
  • +
  • sliding
  • +
  • span
  • +
  • splitAt
    +
  • +
+

Informational and mathematical methods:
+

+
    +
  • containsSlice
    +
  • +
  • count
  • +
  • distinct
  • +
  • exists
  • +
  • find
    +
  • +
  • min
  • +
  • max
  • +
  • slice
  • +
  • sum
    +
  • +
+

Here are a few examples that demonstrate how these methods work +on a list:

+
val a = List(10, 20, 30, 40, 10)      // List(10, 20, 30, 40, 10)
a.distinct                            // List(10, 20, 30, 40)
a.drop(2)                             // List(30, 40, 10)
a.dropRight(2)                        // List(10, 20, 30)
a.dropWhile(_ < 25)                   // List(30, 40, 10)
a.filter(_ < 25)                      // List(10, 20, 10)
a.filter(_ > 100)                     // List()
a.find(_ > 20)                        // Some(30)
a.head                                // 10
a.headOption                          // Some(10)
a.init                                // List(10, 20, 30, 40)
a.intersect(List(19,20,21))           // List(20)
a.last                                // 10
a.lastOption                          // Some(10)
a.slice(2,4)                          // List(30, 40)
a.tail                                // List(20, 30, 40, 10)
a.take(3)                             // List(10, 20, 30)
a.takeRight(2)                        // List(40, 10)
a.takeWhile(_ < 30)                   // List(10, 20)
+

These methods show a common pattern in Scala: Functional methods +that are available on objects. None of these methods mutate the +initial list a; instead, they all return the data +shown +after the comments.
+

+

Enums

+

This section compares enums (enumerations) in Python and Scala 3.
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature
+
Python
+
Scala
+
Simple creation
+
from enum import Enum, auto
+class Color(Enum):
+    RED = auto()
+    GREEN = auto()
+    BLUE = auto()
+
enum Color:
+  case Red, Green, Blue
+
Values and comparison
+
Color.RED == Color.BLUE
+# False
+
Color.Red == Color.Blue  // false
+
Parameterized enum
+
N/A
+
enum Color(val rgb: Int):
+  case Red   extends Color(0xFF0000)
+  case Green extends Color(0x00FF00)
+  case Blue  extends Color(0x0000FF)
+
User-defined enum members
+
N/A
+
enum Planet(mass: Double, radius: Double):
+  case Mercury extends Planet(3.303e+23, 2.4397e6)
+  case Venus   extends Planet(4.869e+24, +6.0518e6)
+  case Earth   extends Planet(5.976e+24, +6.37814e6)
+  // more planets ...
+
+  // fields and methods
+  private final val G = 6.67300E-11
+  def surfaceGravity = G * mass / (radius * radius)
+  def surfaceWeight(otherMass: Double) =  +otherMass * surfaceGravity
+
+
+


+

+

Concepts that are unique to Scala

+

TODO: Someone who knows more about Python than I do should +edit/update this section.
+

+

There are other concepts in Scala which currently don’t have +equivalent functionality in Python. Follow these links for more +details:
+

+
    +
  • Most concepts related to contextual abstractions
  • +
      +
    • Extension methods, type classes, implicit values
      +
    • +
    +
      +
    +
  • Scala allows multiple parameter lists
  • +
      +
    • This enables features like partially-applied functions, and +the ability to create your own DSL
      +
    • +
    +
  • Case classes
  • +
      +
    • Useful for functional programming and pattern matching
      +
    • +
    +
  • The ability to create your own control structures and DSLs
  • +
  • Pattern matching and match expressions
    +
  • +
  • Multiversal equality: the ability to control at compile time +what equality comparisons make sense
    +
  • +
  • Infix methods
  • +
  • Macros and metaprogramming
  • +
  • More ...
    +
  • +
+ From eedcf9554323ba841c7d53ddacb683f161edf345 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Wed, 21 Oct 2020 18:01:00 -0600 Subject: [PATCH 0191/2265] Corrected miscellaneous spelling and syntax errors. --- _overviews/overview/a-taste-of-scala.md | 4 +-- .../overview/collections-classes-methods.md | 14 +++++------ _overviews/overview/control-structures.md | 4 +-- _overviews/overview/interacting-with-java.md | 11 ++++---- _overviews/overview/scala-for-java-devs.md | 25 ++++++------------- _overviews/overview/scala-for-python-devs.md | 4 +-- 6 files changed, 25 insertions(+), 37 deletions(-) diff --git a/_overviews/overview/a-taste-of-scala.md b/_overviews/overview/a-taste-of-scala.md index 4e3cec09c3..f8e04c2cd6 100644 --- a/_overviews/overview/a-taste-of-scala.md +++ b/_overviews/overview/a-taste-of-scala.md @@ -1022,7 +1022,7 @@ t._2 // "eleven" t._3 // Person("Eleven") ``` -Tuples are nice for those times when you want to put a collection of heterogenous types in a little collection-like structure. See the Reference documentation for more tuple details. +Tuples are nice for those times when you want to put a collection of heterogeneous types in a little collection-like structure. See the Reference documentation for more tuple details. @@ -1041,7 +1041,7 @@ For more details, see the Contextual Abstractions section in this Overview, and -## Even more! +## Even more Scala has even more features that weren’t covered in this whirlwind tour. See the remainder of this Overview and the Reference documentation for many more details. diff --git a/_overviews/overview/collections-classes-methods.md b/_overviews/overview/collections-classes-methods.md index 717006e96f..d56c643072 100644 --- a/_overviews/overview/collections-classes-methods.md +++ b/_overviews/overview/collections-classes-methods.md @@ -38,13 +38,13 @@ The main collections classes you’ll use on a regular basis are: | Class | Immutable | Mutable | Description | | ------------- | --------- | ------- | ----------- | -| `List` | ✓ | | A linear (linked list), immutable sequence | -| `Vector` | ✓ | | An indexed, immutable sequence | -| `LazyList` | ✓ | | A lazy immutable linked list, its elements are computed only when they’re needed; Good for large or infinite sequences. | -| `ArrayBuffer` | | ✓ | The go-to class for a mutable, indexed sequence | -| `ListBuffer` | | ✓ | Used when you want a mutable `List`; typically converted to a `List` | -| `Map` | ✓ | ✓ | An iterable sequence that consists of pairs of keys and values. | -| `Set` | ✓ | ✓ | An iterable collection with no duplicate elements | +| `List` | ✓ | | A linear (linked list), immutable sequence | +| `Vector` | ✓ | | An indexed, immutable sequence | +| `LazyList` | ✓ | | A lazy immutable linked list, its elements are computed only when they’re needed; Good for large or infinite sequences. | +| `ArrayBuffer` | | ✓ | The go-to class for a mutable, indexed sequence | +| `ListBuffer` | | ✓ | Used when you want a mutable `List`; typically converted to a `List` | +| `Map` | ✓ | ✓ | An iterable sequence that consists of pairs of keys and values. | +| `Set` | ✓ | ✓ | An iterable collection with no duplicate elements | As shown, `Map` and `Set` come in both immutable and mutable versions. diff --git a/_overviews/overview/control-structures.md b/_overviews/overview/control-structures.md index fc4bff784d..6a384dfd30 100644 --- a/_overviews/overview/control-structures.md +++ b/_overviews/overview/control-structures.md @@ -285,7 +285,7 @@ val list = After that `for` expression runs, the variable `list` is a `Vector` that contains the values shown. This is how the expression works: -1. The `for` expression starts to iterate over the values in the range `(10, 11, 12)`. It first works on the value `10`, multiples it by `2`, then _yields_ that result, the value `20`. +1. The `for` expression starts to iterate over the values in the range `(10, 11, 12)`. It first works on the value `10`, multiplies it by `2`, then _yields_ that result, the value `20`. 2. Next, it works on the `11` — the second value in the range. It multiples it by `2`, then yields the value `22`. You can think of these yielded values as accumulating in a temporary holding place. 3. Finally the loop gets the number `12` from the range, multiplies it by `2`, yielding the number `24`. The loop completes at this point and yields the final result, the `Vector(20,22,24)`. @@ -481,7 +481,7 @@ Using a `match` expression as the body of a method is a very common use. - Typed - Default/wildcard -All of these patterns are shown in the following `pattern` method, which takes an input parameter of tye `Any` and returns a `String`: +All of these patterns are shown in the following `pattern` method, which takes an input parameter of type `Any` and returns a `String`: ```scala def pattern(x: Any): String = x match diff --git a/_overviews/overview/interacting-with-java.md b/_overviews/overview/interacting-with-java.md index df8c7e4555..8276116194 100644 --- a/_overviews/overview/interacting-with-java.md +++ b/_overviews/overview/interacting-with-java.md @@ -257,7 +257,7 @@ System.out.println(jm.multiply(3,4)); // 12 ## How to handle Scala methods that throw exceptions in Java code -When you’re writing Scala code using Scala programming idioms, you’ll never write a method that throws an exception. But if for soem reason you have a Scala method that does throw an exception, and you want Java developers to be able to use that method, add the `@throws` annotation to your Scala method so Java consumers will know the exceptions they can throw. +When you’re writing Scala code using Scala programming idioms, you’ll never write a method that throws an exception. But if for some reason you have a Scala method that does throw an exception, and you want Java developers to be able to use that method, add the `@throws` annotation to your Scala method so Java consumers will know the exceptions they can throw. For example, this Scala `exceptionThrower` method is annotated to declare that it throws an `Exception`: @@ -284,11 +284,11 @@ public class ScalaExceptionsInJava { The compiler gives this error: -.... +```` [error] ScalaExceptionsInJava: unreported exception java.lang.Exception; must be caught or declared to be thrown [error] SExceptionThrower.exceptionThrower() -.... +```` This is good — it’s what you want: the annotation tells the Java compiler that `exceptionThrower` can throw an exception. Now when you’re writing Java code you must handle the exception with a `try` block or declare that your Java method throws an exception. @@ -319,15 +319,14 @@ public class JVarargs { VarargsPrinter.printAll("Hello", "world"); } } - ``` When this code is run, it results in the following output: -.... +```` Hello world -.... +```` diff --git a/_overviews/overview/scala-for-java-devs.md b/_overviews/overview/scala-for-java-devs.md index 6cc72c93cb..0c67d0d863 100644 --- a/_overviews/overview/scala-for-java-devs.md +++ b/_overviews/overview/scala-for-java-devs.md @@ -1,9 +1,8 @@ - - - -Scala for Java Developers - - +--- +title: Scala for Java Developers +description: This page is for Java developers who are interested in learning about Scala 3. +--- +

Notes to reviewers:

    @@ -963,9 +962,9 @@ value:

    def makeInt(s: String): Option[Int] =
     try
    -Some(s.toInt)
    +  Some(s.toInt)
     catch
    -case e: NumberFormatException => None
    +  case e: NumberFormatException => None
     

    The Scala Option is similar to the Java Optional class. As shown, if the string-to-int conversion succeeds, the Int @@ -1014,15 +1013,5 @@ in Java 11:

  1. More ...
  2. -
    -


    -

    -

    -

    -

    -


    -

    - - diff --git a/_overviews/overview/scala-for-python-devs.md b/_overviews/overview/scala-for-python-devs.md index 2f68168bc8..feaeb9c161 100644 --- a/_overviews/overview/scala-for-python-devs.md +++ b/_overviews/overview/scala-for-python-devs.md @@ -91,13 +91,13 @@ programming

    Programming level similarities

    This section looks at the similarities you’ll see between Python -and Scala when you write code on an every day basis:
    +and Scala when you write code on an everyday basis:

    • Scala’s type inference often makes it feel like a dynamically typed language
    • -
    • Neither language uses semi-colons to end expressions
      +
    • Neither language uses semicolons to end expressions
    • Both languages support the use of significant indentation rather than braces and parentheses
    • From b694b4d1ffd796f1d8ae49aece45fd0766784017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Tue, 27 Oct 2020 09:49:45 +0300 Subject: [PATCH 0192/2265] Update annotations.md --- _ru/tour/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ru/tour/annotations.md b/_ru/tour/annotations.md index 50829901d4..23bdb8fad6 100644 --- a/_ru/tour/annotations.md +++ b/_ru/tour/annotations.md @@ -8,7 +8,7 @@ partof: scala-tour num: 32 language: ru -next-page: default-parameter-values +next-page: packages-and-imports previous-page: by-name-parameters --- From 5f54ef08c64bd578c8292f71b76d9cdfc66a988c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Tue, 27 Oct 2020 09:51:11 +0300 Subject: [PATCH 0193/2265] Update packages-and-imports.md --- _ru/tour/packages-and-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ru/tour/packages-and-imports.md b/_ru/tour/packages-and-imports.md index ef7865e3e7..563871406a 100644 --- a/_ru/tour/packages-and-imports.md +++ b/_ru/tour/packages-and-imports.md @@ -8,7 +8,7 @@ partof: scala-tour num: 35 language: ru -previous-page: named-arguments +previous-page: annotations next-page: package-objects --- From 4c8f426313068fc3a12f8ac7a9a8b4bf6a793f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Tue, 27 Oct 2020 10:42:25 +0300 Subject: [PATCH 0194/2265] Update traits.md --- _ru/tour/traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ru/tour/traits.md b/_ru/tour/traits.md index 4fea28e80f..468e2b7f60 100644 --- a/_ru/tour/traits.md +++ b/_ru/tour/traits.md @@ -9,7 +9,7 @@ partof: scala-tour num: 5 language: ru next-page: tuples -previous-page: classes +previous-page: named-arguments topics: traits prerequisite-knowledge: expressions, classes, generics, objects, companion-objects From fb8f9ec57fa285f166f9d4c07b104c0137c0faa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Tue, 27 Oct 2020 10:44:35 +0300 Subject: [PATCH 0195/2265] Update default-parameter-values.md --- _ru/tour/default-parameter-values.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ru/tour/default-parameter-values.md b/_ru/tour/default-parameter-values.md index 7bf61e5430..0286d62e18 100644 --- a/_ru/tour/default-parameter-values.md +++ b/_ru/tour/default-parameter-values.md @@ -9,7 +9,7 @@ partof: scala-tour num: 33 language: ru next-page: named-arguments -previous-page: annotations +previous-page: classes prerequisite-knowledge: named-arguments, function syntax --- From ae6cbbdc0c6dfd3a1bde18f6753df092bc03825b Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Wed, 28 Oct 2020 22:02:10 -0600 Subject: [PATCH 0196/2265] Adding four new Overview chapters. --- _overviews/overview/anonymous-functions.md | 326 +++++++++++++++++++++ _overviews/overview/concurrency.md | 267 +++++++++++++++++ _overviews/overview/eta-expansion.md | 72 +++++ _overviews/overview/scala-tools.md | 320 ++++++++++++++++++++ 4 files changed, 985 insertions(+) create mode 100644 _overviews/overview/anonymous-functions.md create mode 100644 _overviews/overview/eta-expansion.md diff --git a/_overviews/overview/anonymous-functions.md b/_overviews/overview/anonymous-functions.md new file mode 100644 index 0000000000..07f58dabf0 --- /dev/null +++ b/_overviews/overview/anonymous-functions.md @@ -0,0 +1,326 @@ +--- +title: Anonymous Functions (and Function Variables) +description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. +--- + + +This chapter focuses on how to create *anonymous functions* — also known as *function literals*, and called *lambdas* in some languages — in Scala. Creating anonymous functions also helps us demonstrate something else: How to create function variables in Scala. + + + +## Examples + +An anonymous function is like a little mini-function. For example, given a list like this: + +```scala +val ints = List(1,2,3) +``` + +You can create a new list by doubling each element in `ints`, using the `List` class `map` method and your custom anonymous function: + +```scala +val doubledInts = ints.map(_ * 2) // List(2, 4, 6) +``` + +As the comment shows, `doubledInts` contains the list, `List(2, 4, 6)`. In that example, this portion of the code is an anonymous function: + +```scala +_ * 2 +``` + +This is a shorthand way of saying, “Multiply a given element by 2.” + + +### Longer forms + +Once you’re comfortable with Scala, that’s a common way to write anonymous functions, but if you prefer, you can also write them using longer forms. So, in addition to writing that code like this: + +```scala +val doubledInts = ints.map(_ * 2) +``` + +you can also write it using these forms: + +```scala +val doubledInts = ints.map((i: Int) => i * 2) +val doubledInts = ints.map((i) => i * 2) +val doubledInts = ints.map(i => i * 2) +``` + +All of these lines have the exact same meaning: Double each element in `ints` to create a new list, `doubledInts`. The syntax of each form is explained in the next section. + +If you’re familiar with Java, it may help to know that those `map` examples are the equivalent of this Java code: + +```java +List ints = List.of(1,2,3); +List doubledInts = ints.stream() + .map(i -> i * 2) + .collect(Collectors.toList()); +``` + + + +## The rules about shortening anonymous functions + +When you want to be explicit, you can write an anonymous function using this long form: + +```scala +val doubledInts = ints.map((i: Int) => i * 2) +``` + +The anonymous function in that expression is this: + +```scala +(i: Int) => i * 2 +``` + +If you’re not familiar with this syntax, it helps to think of the `=>` symbol as a transformer, because the expression *transforms* the parameter list on the left side of the symbol (an `Int` variable named `i`) into a new result using the algorithm on the right side of the `=>` symbol (in this case, an expression that doubles the `Int`). + + +### Shortening that expression + +Starting with that longest and most explicit form: + +```scala +val doubledInts = ints.map((i: Int) => i * 2) +``` + +Because the Scala compiler can infer from the data in `ints` that `i` is an `Int`, the `Int` declaration can be removed: + +```scala +val doubledInts = ints.map((i) => i * 2) +``` + +Because there’s only one argument, the parentheses around the parameter `i` aren’t needed: + +```scala +val doubledInts = ints.map(i => i * 2) +``` + +Next, because Scala lets you use the `_` symbol instead of a variable name when the parameter appears only once in your function, the code can be simplified even more: + +```scala +val doubledInts = ints.map(_ * 2) +``` + +In other examples, you can simplify your anonymous functions further. For instance, beginning with the most explicit form, you can print each element in `ints` using this anonymous function with the `List` class `foreach` method: + +```scala +ints.foreach((i:Int) => println(i)) +``` + +As before, the `Int` declaration isn’t required, and because there’s only one argument, the parentheses around `i` aren’t needed: + +```scala +ints.foreach(i => println(i)) +``` + +Because `i` is used only once in the body of the function, the expression can be further simplified with the `_` symbol: + +```scala +ints.foreach(println(_)) +``` + +Finally, if a function literal consists of one statement that takes a single argument, you don’t need to explicitly name and specify the argument, so the statement can finally be reduced to this: + +```scala +ints.foreach(println) +``` + + + +## From anonymous functions to function variables + +Going back to this example: + +```scala +val doubledInts = ints.map((i: Int) => i * 2) +``` + +We noted earlier that this part of the expression is an anonymous function: + +```scala +(i: Int) => i * 2 +``` + +The reason it’s called *anonymous* is because it’s not assigned to a variable, and therefore doesn’t have a name. + +What’s interesting now is that you can assign this anonymous function (function literal) to a variable to create a function variable: + +```scala +val double = (i: Int) => i * 2 +``` + +Now we have a function variable named `double`. In this expression, our original function literal is on the right side of the `=` symbol: + +```scala +val double = (i: Int) => i * 2 + ----------------- +``` + +and the new variable name is on the left side: + +```scala +val double = (i: Int) => i * 2 + ------ +``` + +In this expression the function’s parameter list is underlined here: + +```scala +val double = (i: Int) => i * 2 + -------- +``` + +Like the parameter list for a method, this means that the `double` function takes one parameter, an `Int` named `i`. In fact, you can see in the REPL that `double` has the type `Int => Int`, meaning that it takes a single `Int` parameter and returns an `Int`: + +```scala +scala> val double = (i: Int) => i * 2 +val double: Int => Int = ... +``` + +Now you can call the `double` function like this: + +```scala +val x = double(2) // 4 +``` + +You can also pass `double` into a `map` call: + +```scala +List(1,2,3).map(double) // List(2, 4, 6) +``` + +Furthermore, if you happen to have another function that has the `Int => Int` type: + +```scala +val triple = (i: Int) => i * 3 +``` + +You can also store them in a `List` or `Map`: + +```scala +val functionList = List(double, triple) + +val functionMap = Map( + "2x" -> double, + "3x" -> triple +) +``` + +If you paste those expressions into the REPL, you’ll see that they have these types: + +```` +// a List that contains functions of the type `Int => Int` +functionList: List[Int => Int] + +// a Map whose keys have the type `String`, and whose +// values have the type `Int => Int` +functionMap: Map[String, Int => Int] +```` + +The important parts here are: + +- To create a function variable, just assign a variable name to a function literal +- Once you have a function, you can treat it like any other variable, i.e., like a `String` or `Int` variable + +>And thanks to the improved Eta Expansion functionality in Scala 3, you can treat *methods* in the same way. + + + + +## Key points + +The key points of this lesson are: + +- You can write anonymous functions as little snippets of code +- You can pass them into the dozens of higher-order functions (methods) on the collections classes, i.e., methods like `filter`, `map`, etc. +- With these little snippets of code and powerful higher-order functions, you create a lot of functionality with just a little code +- Function variables are simply anonymous functions that have been bound to a variable + + + +## Bonus: Digging a little deeper + +You may be wondering how methods like `map` and `filter` work. Technically, the `map` method on a sequence class like `List` takes a *function* parameter. That function is defined to take a generic parameter `A` as input, and it returns a generic value `B` as its result. Any function that matches this type signature can be used here. When `map` finishes traversing over all of its elements, it returns a `List[B]` as its result. When you see this `map` method signature in the `List` Scaladoc, that’s what it means: + +```scala +def map[B](f: (A) => B): List[B] +``` + +In the case of our `ints` list, the compiler knows that `ints` is a list of integers, i.e., a `List[Int]`. Therefore, the generic parameter `A` must be the type `Int`. + +The parameter `B` is whatever your custom function returns. For instance, while the anonymous function shown previously transformed one `Int` into another `Int` value, this function transforms an `Int` to a `Double`: + +```tut +val intToDouble = (i: Int) => i.toDouble +``` + +So now when you use that function with `ints` and `map`, you get a `List[Double]`: + +```scala +ints.map(intToDouble) // List[Double] = List(1.0, 2.0, 3.0) +``` + +In summary, while generically the `map` method expects this type: + +```scala +f: (A) => B +``` + +in this specific example the `intToDouble` function has this type: + +```scala +f: (Int) => Double +``` + + +### More `map` and `filter` examples + +Here’s another `map` example that transforms a `Seq[String]` into a `Seq[Int]`: + +```tut +Seq("hi", "there").map(_.length) // Seq[Int] = List(2, 5) +``` + +In this case the anonymous function `_.length` transforms each `String` it’s given into an `Int` by calling the `length` function on the `String`. + +Similarly, `filter` also takes a function parameter, but the function it’s given must return a `Boolean` value, so it’s Scaladoc signature looks like this: + +```scala +def filter(p: (A) => Boolean): List[A] +``` + +So any anonymous function used with `filter` must take the type `A` that’s contained in the list and return a `Boolean`, like these examples: + +```scala +val list = Seq(1,2,3,4,5) +list.filter(_ < 3) // List(1, 2) +list.filter(_ % 2 == 0) // List(2, 4) +``` + +If you’re not familiar with it, that last example performs a modulus comparison that returns `true` for even numbers. + +>The letter `p` is used in the `filter` Scaladoc because any function that returns a `Boolean` value is known as a *predicate*. + + +### One more thing + +As a bit of extra credit, you may be interested to know that this expression: + +```scala +val doubledInts = ints.map(_ * 2) +``` + +is equivalent to this expression: + +```scala +val doubledInts = for i <- ints yield i * 2 +``` + +Depending on their background, when some developers come to Scala they may initially feel more comfortable writing this `for` expression, until one day they realize it’s the exact same thing as writing the more concise `map` expression. + + + + + diff --git a/_overviews/overview/concurrency.md b/_overviews/overview/concurrency.md index e69de29bb2..290ac9c304 100644 --- a/_overviews/overview/concurrency.md +++ b/_overviews/overview/concurrency.md @@ -0,0 +1,267 @@ +--- +title: Concurrency with Scala Futures +description: This page discusses how Scala concurrency works, with an emphasis on Scala Futures. +--- + + +When you want to write parallel and concurrent applications in Scala, you *can* use the native Java `Thread` — but the Scala [Future](https://www.scala-lang.org/api/current/scala/concurrent/Future$.html) makes parallel/concurrent programming much simpler, so it’s preferred, and covered in this chapter. + + + +## Introduction + +Here’s a description of the Scala `Future` from its Scaladoc: + +>“A `Future` represents a value which may or may not *currently* be available, but will be available at some point, or an exception if that value could not be made available.” + +To help demonstrate what that means, let’s first look at single-threaded programming. In the single-threaded world you bind the result of a method call to a variable like this: + +```tut +def aShortRunningTask(): Int = 42 +val x = aShortRunningTask() +``` + +In this code, the value `42` is immediately bound to the variable `x`. + +When you’re working with a `Future`, the assignment process looks similar: + +```scala +def aLongRunningTask(): Future[Int] = ??? +val x = aLongRunningTask() +``` + +The main difference in this case is that because `aLongRunningTask` takes an indeterminate amount of time to return, the value in `x` may or may not be *currently* available, but it will be available at some point — in the future. + +In this chapter you’ll see how to use futures, including how to run multiple futures in parallel and combine their results in a `for` expression. You’ll also see other methods that are used to handle the value in a future once it returns. + +>An important point to know about futures is that they’re intended as a one-shot, “Handle this relatively slow computation on some other thread, and call me back with a result when you’re done” construct. As a point of contrast, [Akka](https://akka.io) actors are intended to run for a long time and respond to many requests during their lifetime. While an actor may live forever, a future is intended to be run only once. + + + +## An example in the REPL + +A future is used to create a temporary pocket of concurrency. For instance, you use a future when you need to call an algorithm that runs an indeterminate amount of time — such as calling a remote microservice — so you want to run it off of the main thread. + +To demonstrate how this works, let’s start with a `Future` example in the REPL. First, paste in these required `import` statements: + +```scala +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global +import scala.util.{Failure, Success} +``` + +Now you’re ready to create a future. For this example, first define a long-running, single-threaded algorithm: + +```scala +def longRunningAlgorithm = + Thread.sleep(10_000) + 42 +``` + +That fancy algorithm returns the integer value `42` after a ten second delay. Now call that algorithm by passing it into the `Future` constructor, and assigning the result to a variable: + +```scala +scala> val f = Future(longRunningAlgorithm) +f: scala.concurrent.Future[Int] = Future() +``` + +Right away your future begins running. If you immediately check the value of the variable `f`, you see that the future hasn’t completed yet: + +```scala +scala> f +val res1: scala.concurrent.Future[Int] = Future() +``` + +But if you check again after ten seconds, you’ll see that it completes successfully: + +```scala +scala> f +val res2: scala.concurrent.Future[Int] = Future(Success(42)) +``` + +While that’s a relatively simple example, it shows the basic approach: Just construct a new `Future` with your long-running algorithm. + +One thing to notice is that the `42` you expected is wrapped in a `Success`, which is further wrapped in a `Future`. This is a key concept to understand: The value in a `Future` is always an instance of one of the *scala.util.Try* types: `Success` or `Failure`. Therefore, when you work with the result of a future, you use the usual `Try`-handling techniques. + + + +### Using `map` with futures + +`Future` has a `map` method, which you use just like the `map` method on the collections classes. This is what the result looks like when you call `map` right after creating the variable `f`: + +```scala +scala> val a = f.map(_ * 2) +a: scala.concurrent.Future[Int] = Future() +``` + +As shown, for the future that was created with the `longRunningAlgorithm`, the initial output shows `Future()`. But when you check `a`’s value after ten seconds you’ll see that it contains the expected result of `84`: + +```scala +scala> a +res1: scala.concurrent.Future[Int] = Future(Success(84)) +``` + +Once again, the successful result is wrapped inside a `Success` and a `Future`. + + +### Using callback methods with futures + +In addition to higher-order functions like `map`, you can also use callback methods with futures. One commonly used callback method is `onComplete`, which takes a *partial function* in which you handle the `Success` and `Failure` cases: + +```scala +f.onComplete { + case Success(value) => println(s"Got the callback, value = $value") + case Failure(e) => e.printStackTrace +} +``` + +When you paste that code in the REPL you’ll see the result: + +```scala +Got the callback, value = 42 +``` + + + +## Other Future methods + +The `Future` class has other methods you can use. It has some of the methods that you find on Scala collections classes, including: + +- `filter` +- `flatMap` +- `map` + +Its callback methods are: + +- `onComplete` +- `andThen` +- `foreach` + +Other transformation methods include: + +- `fallbackTo` +- `recover` +- `recoverWith` + + +See the `Future` class Scaladoc for a list of additional methods. Also, see the Concurrency section in the Reference documentation for more details on how futures work. + + + + +## Running multiple futures and joining their results + +To run multiple futures in parallel and join their results when all of the futures complete, use a `for` expression. The correct approach is: + +1. Create the futures +2. Merge their results in a `for` expression +3. Extract the merged result using `onComplete` or a similar technique + + +### An example + +The three steps of the correct approach are shown in the following example. A key is that you first create the futures and then join them in the `for` expression: + +```tut +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global +import scala.util.{Failure, Success} + +val startTime = System.currentTimeMillis +def delta() = System.currentTimeMillis - startTime +def sleep(millis: Long) = Thread.sleep(millis) + +@main def multipleFutures1 = + + println(s"creating the futures: ${delta()}") + + // (1) create the futures + val f1 = Future { sleep(800); 1 } // eventually returns 1 + val f2 = Future { sleep(200); 2 } // eventually returns 2 + val f3 = Future { sleep(400); 3 } // eventually returns 3 + + // (2) run them simultaneously in a `for` expression + val result = + for + r1 <- f1 + r2 <- f2 + r3 <- f3 + yield + println(s"in the 'yield': ${delta()}") + (r1 + r2 + r3) + + // (3) process the result + result.onComplete { + case Success(x) => + println(s"in the Success case: ${delta()}") + println(s"result = $x") + case Failure(e) => + e.printStackTrace + } + + println(s"before the 'sleep(3000)': ${delta()}") + + // important for a little parallel demo: keep the jvm alive + sleep(3000) +``` + +When you run that application, you see output that looks like this: + +```` +creating the futures: 1 +before the 'sleep(3000)': 2 +in the 'yield': 806 +in the Success case: 806 +result = 6 +```` + +As that output shows, the futures are created very rapidly, and in just two milliseconds the print statement right before the `sleep(3000)` statement at the end of the method is reached. All of that code is run on the JVM’s main thread. Then, at 806 ms, the three futures complete and the code in the `yield` block is run. Then the code immediately goes to the `Success` case in the `onComplete` method. + +The 806 ms output is a key to seeing that the three futures are run in parallel. If they were run sequentially, the total time would be about 1,400 ms — the sum of the sleep times of the three futures. But because they’re run in parallel, the total time is just slightly longer than the longest-running future: `f1`, which is 800 ms. + + +### A method that returns a future + +So far you’ve seen how to pass a single-threaded algorithm into a `Future` constructor. You can use the same technique to create a method that returns a `Future`: + +```scala +// simulate a slow-running method +def slowlyDouble(x: Int, delay: Long): Future[Int] = Future { + sleep(delay) + x * 2 +} +``` + +As with the previous examples, just assign the result of the method call to a new variable. Then when you check the result right away you’ll see that it’s not completed, but after the delay time the future will have a result: + +```` +scala> val f = slowlyDouble(2, 5_000L) val f: concurrent.Future[Int] = Future() + +scala> f +val res0: concurrent.Future[Int] = Future() + +scala> f +val res1: concurrent.Future[Int] = Future(Success(4)) +```` + + + +## Key points about futures + +Hopefully those examples give you an idea of how Scala futures work. To summarize, a few key points about futures are: + +- You construct futures to run tasks off of the main thread +- Futures are intended for one-shot, potentially long-running concurrent tasks that *eventually* return a value; they create a temporary pocket of concurrency +- A future starts running as soon as you construct it +- A benefit of futures over threads is that they work with `for` expressions, and come with a variety of callback methods that simplify the process of working with concurrent threads +- When you work with futures you don’t have to concern yourself with the low-level details of thread management +- You handle the result of a future with callback methods like `onComplete` and `andThen`, or transformation methods like `filter`, `map`, etc. +- The value inside a `Future` is always an instance of one of the `Try` types: `Success` or `Failure` +- If you’re using multiple futures to yield a single result, combine them in a `for` expression + +Also, as you saw with the `import` statements in these examples, the Scala `Future` depends on an `ExecutionContext`. This relationship, and many more details about futures, are explained in the Reference documentation. + + + + + diff --git a/_overviews/overview/eta-expansion.md b/_overviews/overview/eta-expansion.md new file mode 100644 index 0000000000..0594370fad --- /dev/null +++ b/_overviews/overview/eta-expansion.md @@ -0,0 +1,72 @@ +--- +title: Eta Expansion in Scala 3 +description: This page discusses Eta Expansion, the Scala technology that automatically and transparently converts methods into functions. +--- + + + +## Background + +When you look at the Scaladoc for the `map` method on Scala collections classes, you see that it’s defined to accept a *function*: + +```scala +def map[B](f: (A) => B): List[B] + ----------- +``` + +Indeed, the Scaladoc clearly states, “`f` is the function to apply to each element.” But despite that, somehow you can pass a *method* into `map`, and it still works: + +```scala +def times10(i: Int) = i * 10 // a method +List(1,2,3).map(times10) // List(10,20,30) +``` + +Have you ever wondered how this works — how you can pass a *method* into `map`, which expects a *function*? + + +### Eta Expansion + +The technology behind this is known as *Eta Expansion*. It converts an expression of method type to an equivalent expression of function type, and it does so seamlessly and quietly. + + +### The differences between methods and functions + + +Technically, *methods* are part of the definition of a class, while *functions* are complete objects themselves, making them first-class entities. For example, functions can be assigned to variables. + +Their syntax is also different. This example shows how to define a method and a function that perform the same task, determining if the given integer is even: + +```scala +def isEvenMethod(i: Int) = i % 2 == 0 // a method +val isEvenFunction = (i: Int) => i % 2 == 0 // a function +``` + +The function truly is an object, so you can use it just like any other variable, such as putting it in a list: + +```scala +val functions = List(isEvenFunction) +``` + +Conversely, a method technically isn’t an object, so in Scala 2 you couldn’t put a method in a `List`, at least not directly, as shown in this error message: + +```scala +// this example shows the Scala 2 error message +val methods = List(isEvenMethod) + ^ +error: missing argument list for method isEvenMethod +Unapplied methods are only converted to functions when a function type is expected. +You can make this conversion explicit by writing `isEvenMethod _` or `isEvenMethod(_)` instead of `isEvenMethod`. +``` + +As shown in that text, there is a manual way to convert a method into a function in Scala 2, but the important part for Scala 3 is that the Eta Expansion technology is improved, so now when you attempt to use a method as a variable, it just works — you don’t have to handle the manual conversion yourself: + +```scala +val functions = List(isEvenFunction) // works +val methods = List(isEvenMethod) // works +``` + + + + diff --git a/_overviews/overview/scala-tools.md b/_overviews/overview/scala-tools.md index e69de29bb2..8c0cdba053 100644 --- a/_overviews/overview/scala-tools.md +++ b/_overviews/overview/scala-tools.md @@ -0,0 +1,320 @@ +--- +title: Scala Tools +description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. +--- + + + +In this chapter you’ll see two tools that are commonly used in Scala projects: + +- [The *sbt* build tool](https://www.scala-sbt.org) +- [ScalaTest](https://www.scalatest.org), a source code testing framework + +We’ll start by showing how to use sbt to build your Scala projects, and then we’ll show how to use sbt and ScalaTest together to test your Scala projects. + + + +## Building Scala projects with sbt + +You can use several different tools to build your Scala projects, including Ant, Maven, Gradle, Mill, and more. But a tool named *sbt* was the first build tool that was specifically created for Scala, and these days it’s supported by [Lightbend](https://www.lightbend.com), the company that also maintains [Akka](https://akka.io), the [Play framework](https://www.playframework.com), the [Lagom framework](https://www.lagomframework.com), and more. + +>To install sbt, see [its download page](https://www.scala-sbt.org/download.html). + + +### The sbt directory structure + +Like Maven, sbt uses a standard project directory structure. A nice benefit of that is that once you’re comfortable with its structure, it makes it easy to work on other Scala/sbt projects. + +The first thing to know is that underneath the root directory of your project, sbt expects a directory structure that looks like this: + +```bash +build.sbt +project/ +src/ +-- main/ + |-- resources/ + |-- scala/ +|-- test/ + |-- resources/ + |-- scala/ +target/ +``` + +The *resources* directories are optional, and you can also add *java* directories at the same level as the *scala* directories if you want to use Java source code in your project. You can also add a *lib* directory under the root directory if you want to add unmanaged dependencies — JAR files — to your project. + + +### Creating a “Hello, world” sbt project directory structure + + + +Creating this directory structure is simple. There are tools to do this for you, but assuming that you’re using a Unix/Linux system, you can use these commands to create your first sbt project directory structure: + +```bash +mkdir HelloWorld +cd HelloWorld +mkdir -p src/{main,test}/{resources,scala} +mkdir project target +``` + +When you run a `find .` command after running those commands, you should see this result: + +```bash +$ find . +. +./project +./src +./src/main +./src/main/resources +./src/main/scala +./src/test +./src/test/resources +./src/test/scala +./target +``` + +If you see that, you’re in great shape for the next step. + +>There are other ways to create the files and directories for an sbt project. One way is to use the `sbt new` command, [which is documented here on scala-sbt.org](https://www.scala-sbt.org/1.x/docs/Hello.html). That approach isn’t shown here because some of the files it creates are more complicated than necessary for an introduction like this. + + +### Creating a first build.sbt file + +At this point you only need two more things to run a “Hello, world” project: + +- A *build.sbt* file +- A *Hello.scala* file + +For a little project like this, the *build.sbt* file only needs to contain a few lines, like this: + +```scala +name := "HelloWorld" +version := "1.0" +scalaVersion := "{{ site.scala-version }}" +``` + +Because sbt projects use a standard directory structure, sbt will be able to find everything else it needs. + +Now you just need to add a little “Hello, world” program. + + +### A “Hello, world” program + +In large projects, all of your Scala source code files will go under the *src/main/scala* and *src/test/scala* directories, but for a little sample project like this, you can put your source code file in the root directory of your project. Therefore, create a file named *HelloWorld.scala* in the root directory with these contents: + +```scala +@main def helloWorld = println("Hello, world") +``` + +Now, use the `sbt run` command to compile and run your project. When you do so, you’ll see output that looks like this: + +```bash +$ sbt run + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition +[info] loading settings for project root from build.sbt ... +[info] Compiling 1 Scala source ... +[info] running helloWorld +Hello, world +[success] Total time: 4 s +``` + +The first time you run `sbt` it downloads everything it needs, and that can take a little while to run, but after that it gets much faster. + +Also, once you get this first step working, you’ll find that it’s much faster to run sbt interactively. To do that, first run the `sbt` command by itself: + +```bash +$ sbt + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition ... +[info] loading settings for project root from build.sbt ... +[info] sbt server started at local:///Users/al/.sbt/1.0/server/7d26bae825c38a31074c/sock +sbt:hello-world> _ +``` + +Then inside this sbt shell, execute its `run` command: + +```` +sbt:hello-world> run + +[info] running helloWorld +Hello, world +[success] Total time: 0 s +```` + +There, that’s much faster. + +If you type `help` at the sbt command prompt you’ll see a list of other commands you can run. But for now, just type `exit` to leave the sbt shell. (You can also press `CTRL-D` instead of typing `exit`.) + + +### Other build tools for Scala + + +While sbt is widely used, there are other tools you can use to build Scala projects: + +- [Ant](https://ant.apache.org/) +- [Gradle](https://gradle.org/) +- [Maven](https://maven.apache.org/) +- [Mill](https://www.lihaoyi.com/mill/) + + + +## Using sbt with ScalaTest + +ScalaTest is one of the main testing libraries for Scala projects, and in this section you’ll see how to create a Scala/sbt project that uses ScalaTest. + + +### Creating the project directory structure + +As with the previous lesson, create an sbt project directory structure for a project named *HelloScalaTest* with the following commands: + +```sh +mkdir HelloScalaTest +cd HelloScalaTest +mkdir -p src/{main,test}/{resources,scala} +mkdir project target +``` + + +### Creating the build.sbt file + +Next, create a *build.sbt* file in the root directory of your project with these contents: + +```scala +name := "HelloScalaTest" +version := "1.0" +scalaVersion := "{{site.scala-version}}" + +libraryDependencies ++= Seq( + "org.scalatest" % "scalatest-core_0.27" % "3.2.2", + "org.scalatest" % "scalatest_0.27" % "3.2.2" % Test +) +``` + +The first three lines of this file are essentially the same as the first example. The `libraryDependencies` lines tell sbt to include the dependencies (JAR files) that are needed to include ScalaTest. + +>The ScalaTest documentation has always been good, and you can always find the up to date information on what those lines should look like on the [Installing ScalaTest](https://www.scalatest.org/install) page. + + +### Create a Scala source code file + +Next, create a Scala program that you can use to demonstrate ScalaTest. First, create a directory under *src/main/scala* named *math*: + +```sh +$ mkdir src/main/scala/math + ---- +``` + +Then, inside that directory, create a file named *MathUtils.scala* with these contents: + +```scala +package math + +object MathUtils: + def double(i: Int) = i * 2 +``` + +There isn’t much that can go wrong with that source code, but it provides a simple way to demonstrate ScalaTest. This object doesn’t have a `main` method, so instead of trying to run the project with `sbt run`, we’ll just compile it with `sbt compile`: + +```` +$ sbt compile + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition ... +[info] loading settings for project ... +[info] Executing in batch mode. For better performance use sbt's shell +[success] Total time: 1 s +```` + +With that compiling, let’s create a ScalaTest file to test the `double` method. + + +### Your first ScalaTest tests + +ScalaTest is very flexible, and there are several different ways to write tests. A simple way to get started is to write tests using the ScalaTest `AnyFunSuite`. To get started, create a directory named *math* under the *src/test/scala* directory, like this: + +```sh +$ mkdir src/test/scala/math + ---- +``` + +Next, create a file named *MathUtilsTests.scala* in that directory with the following contents: + +```scala +package math + +import org.scalatest.funsuite.AnyFunSuite + +class MathUtilsTests extends AnyFunSuite { + + // test 1 + test("'double' should handle 0") { + val result = MathUtils.double(0) + assert(result == 0) + } + + // test 2 + test("'double' should handle 1") { + val result = MathUtils.double(1) + assert(result == 2) + } + + test ("test with Int.MaxValue") (pending) + +} +``` + +This code demonstrates the ScalaTest `AnyFunSuite` approach. A few important points: + +- Your test class should extend `AnyFunSuite` +- You create tests as shown, by giving each `test` a unique name +- At the end of each test you should call `assert` to test that a condition has been satisfied +- When you know you want to write a test, but you don’t want to write it right now, create the test as “pending,” with the syntax shown + +Using ScalaTest like this is similar to JUnit, so if you’re coming to Scala from Java, hopefully this looks similar. + +Now you can run these tests with the `sbt test` command. Skipping the first few lines of output, the result looks like this: + +```` +sbt:HelloScalaTest> test + +[info] Compiling 1 Scala source ... +[info] MathUtilsTests: +[info] - 'double' should handle 0 +[info] - 'double' should handle 1 +[info] - test with Int.MaxValue (pending) +[info] Total number of tests run: 2 +[info] Suites: completed 1, aborted 0 +[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 1 +[info] All tests passed. +[success] Total time: 1 s +```` + +If everything works well, you’ll see output that looks like that. Welcome to the world of testing Scala applications with sbt and ScalaTest. + + +### Multiple types of tests + +This example demonstrated a style of testing that is similar to xUnit testing, with a few benefits of the *Behavior-Driven Development* (BDD) style. But as mentioned, ScalaTest is flexible and you can also write tests using other styles. See the User Guide on the [ScalaTest website](https://www.scalatest.org) for more details on the different testing styles that are available. + + + +## Where to go from here + +For more information about sbt and ScalaTest, see the following resources: + +- [The sbt documentation](https://www.scala-sbt.org/1.x/docs/) +- [The ScalaTest website](https://www.scalatest.org/) + + + From 26eb09657c083ba73f2353a3761ec9a94ecd8df9 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sat, 31 Oct 2020 22:20:04 -0600 Subject: [PATCH 0197/2265] =?UTF-8?q?Initial=20versions=20of=20the=20?= =?UTF-8?q?=E2=80=98Main=20Methods=E2=80=99=20and=20=E2=80=98Higher-Order?= =?UTF-8?q?=20Functions=E2=80=99=20documents.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/higher-order-functions.md | 547 ++++++++++++++++++ _overviews/overview/main-methods.md | 136 +++++ 2 files changed, 683 insertions(+) create mode 100644 _overviews/overview/higher-order-functions.md create mode 100644 _overviews/overview/main-methods.md diff --git a/_overviews/overview/higher-order-functions.md b/_overviews/overview/higher-order-functions.md new file mode 100644 index 0000000000..cb427b3b69 --- /dev/null +++ b/_overviews/overview/higher-order-functions.md @@ -0,0 +1,547 @@ +--- +title: Higher-order Functions +description: This page demonstrates how to create and use higher-order functions in Scala. +--- + + + +A higher-order function is often defined as a function that (a) takes other functions as input parameters or (b) returns a function as a result. In Scala this is possible because functions are first-class values. While we use the term “higher-order function,” in Scala this phrase is used for both *methods* and *functions* because they can generally be used in the same places. + +>The ability to pass functions around as values enables a form of “power” programming that lets you write code that’s concise and still readable. + +In the examples so far you’ve seen how to be the *consumer* of functions that take other functions as input parameters, such as higher-order functions like `map` and `filter`. In this chapter you’ll see how to be the *creator* of higher-order functions, including: + +- How to write methods that take functions as input parameters +- How to return a function from a method + +In the process you’ll see: + +- The syntax you use to define function input parameters +- Multiple examples of that syntax +- How to call a function once you have a reference to it + +As a beneficial side effect of this chapter, once you’re comfortable with the syntax, you’ll use it to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions. + + + +## Recap: Being a consumer of higher-order functions + +As a quick recap, in this Overview you’ve already seen examples of how to use existing higher-order functions in the Scala collections classes, including `map` and `filter`: + +```scala +List(1,2,3).map(_ * 10) // List(10,20,30) + +def isEven(i: Int) = i % 2 == 0 +Vector(1,2,3,4).filter(isEven) // Vector(2,4) +``` + +A few key points of the `filter` example are: + +- `filter` accepts a function, anonymous function, or method as an input parameter. +- The functions you pass into `filter` must match the type signature that `filter` expects — in this example, a function that takes an `Int` input parameter and returns a `Boolean`. + +>Although we use the term “function,” `filter` can accept a *method* as a parameter thanks to Scala’s [Eta Expansion](TODO:LINK) technology. + + +### Understanding `filter`’s Scaladoc + +You can understand the type of functions `filter` accepts by looking at its Scaladoc. For example here’s the `filter` definition on the `List` class: + +```scala +def filter(p: (A) => Boolean): List[A] +``` + +This states that `filter` is a method that takes a predicate parameter named `p` and returns a `List[A]`. (A *predicate* is just a function that returns a `Boolean` value.) Without looking at the internal details of `filter`, all we know is that it somehow uses that predicate to return a new list of the type `List[A]`, where `A` is the type in the list. + +Digging a little deeper, this part of `filter`’s description: + +```scala +p: (A) => Boolean +``` + +means that `filter` takes a function input parameter named `p`, and `p` must transform a generic input `A` into a `Boolean` value. Therefore, if a list holds the type `Int`, you can replace the generic type `A` with `Int`, and read that signature like this: + +```scala +p: (Int) => Boolean +``` + +Because `isEven` has this type — it transforms an input `Int` into a resulting `Boolean` — it can be used with `filter`. + + +### A lot of functionality with a little code + +The great thing about `filter` — and higher-order functions in general — is that they save you from writing a lot of custom code, typically custom `for` loops. For example, if `List` didn’t have a `filter` method, you’d have to write a custom method like this to do the same work: + +```scala +// what you’d have to do if `filter` didn’t exist +def getEvens(list: List[Int]): List[Int] = + val tmpArray = ArrayBuffer[Int]() + for + i <- list + if i % 2 == 0 + do + tmpArray += i + + // return this + tmpArray.toList + +val result = getEvens(aList) +``` + +Compare all of that imperative code to this equivalent functional code: + +```scala +val result = list.filter(_ % 2 == 0) +``` + +As you can see, this is a great advantage of functional programming. The code is much more concise, and it’s also easier to comprehend. + +In short, as they pertain to Scala’s collections classes, higher-order functions: + +- Are generally a replacement for custom traversal algorithms (such as `for` expressions) +- Are easier to read than custom traversal algorithms +- Mostly eliminate the need to write (or read) custom traversal algorithms + +As Martin Odersky wrote in his book, [Programming in Scala](https://www.amazon.com/Programming-Scala-Martin-Odersky/dp/098153161X/): + +>“You can use functions within your code to factor out common control patterns, and you can take advantage of higher-order functions in the Scala library to reuse control patterns that are common across all programmers’ code.” + + + +## Writing methods that take functions as parameters + +>Note: To make the following sections more clear, we’ll refer to the code you’re writing as a *method*, and the code you’re accepting as an input parameter as a *function*. + + +Given that background, let’s start writing methods that take functions as input parameters. + +To define a method that takes a function parameter, all you have to do is: + +1. In your method’s parameter list, define the signature of the function you want to accept +2. Use that function inside your method + +To demonstrate this, here’s a method that that takes an input parameter named `f`, where `f` is a function: + +```scala +def sayHello(f: () => Unit): Unit = f() +``` + +This portion of the code — the *type signature* — defines the types of functions the `sayHello` method will accept: + +```scala +f: () => Unit +``` + +Here’s how this works: + +- `f` is the name of the function input parameter. It’s just like naming a `String` parameter `s`, or an `Int` parameter `i`. +- The type signature of `f` specifies the *type* of the functions this method will accept. +- The `()` portion of `f`’s signature (on the left side of the `=>` symbol) states that `f` takes no input parameters. +- The `Unit` portion of the signature (on the right side of the `=>` symbol) indicates that `f` should return nothing. +- Looking back at the body of the `sayHello` method, the `f()` statement there invokes the function that’s passed in. + +Now that we’ve defined `sayHello`, let’s create a function to match `f`’s signature so we can test it. For instance, the following function takes no input parameters and returns nothing, so it matches `f`’s type signature: + +```scala +def helloJoe(): Unit = println("Hello, Joe") +``` + +Because the type signatures match, you can pass `helloJoe` into `sayHello`: + +```scala +sayHello(helloJoe) // prints "Hello, Joe" +``` + +If you’ve never done this before, congratulations. You just defined a method named `sayHello` that takes another function as an input parameter, and then invokes that function when it’s called. + + +### sayHello can take many functions + +It’s important to know that the beauty of this approach is not that `sayHello` can take *one* function as an input parameter; the beauty is that it can take *any* function that matches `f`’s signature. For instance, because this next function takes no input parameters and returns nothing, it also works with `sayHello`: + +```scala +def bonjourJulien(): Unit = println("Bonjour, Julien") +``` + +Here it is in the REPL: + +```scala +scala> sayHello(bonjourJulien) +Bonjour, Julien +``` + +This is a good start. The only thing to do now is see a few more examples of how to define different type signatures for function parameters. + + +### The general syntax for defining function input parameters + +In this method: + +```scala +def sayHello(f: () => Unit) +``` + +The type signature for `f` is: + +```scala +f: () => Unit +``` + +We know that’s a function that takes no input parameters and returns nothing (given by `Unit`). + +To demonstrate more type signature examples, here’s a function that takes a `String` parameter and returns an `Int`: + +```scala +f: (String) => Int +``` + +That could be something like a string length or checksum function. + +Similarly, this function takes two `Int` parameters and return an `Int`: + +```scala +f: (Int, Int) => Int +``` + +As you can infer from these examples, the general syntax for defining function parameter type signatures is: + +```scala +variableName: (parameterTypes ...) => returnType +``` + +Going back to this type signature: + +```scala +f: (Int, Int) => Int +``` + +Can you imagine what sort of functions match that signature? + +The answer is that any function that takes two `Int` input parameters and returns an `Int` matches that signature, so all of these functions match that signature: + +```scala +def add(a: Int, b: Int): Int = a + b +def subtract(a: Int, b: Int): Int = a - b +def multiply(a: Int, b: Int): Int = a * b +``` + +>Because functional programming is like combining a series of algebraic equations, it’s common to think about types a *lot*. You might say that you “think in types.” + + +### Taking a function parameter along with other parameters + +So far the methods we’ve shown have only taken a function input parameter. But for a method like this to be really interesting, it must also have some data to work on. For a class like `List`, its `map` method already has data to work on: the data in the `List`. But for a standalone method that doesn’t have its own data, it should accept data as another input parameter. + +For instance, here’s a method named `executeNTimes` that has two input parameters: a function, and an `Int`: + +```scala +def executeNTimes(f: () => Unit, n: Int): Unit = + for i <- 1 to n do f() +``` + +As the code shows, `executeNTimes` executes the `f` function `n` times. Because `f` returns `Unit`, `executeNTimes` also returns `Unit`. To test `executeNTimes`, define a method that matches `f`’s signature: + +```scala +// a method of type `() => Unit` +def helloWorld(): Unit = println("Hello, world") +``` + +Then pass the method into `executeNTimes` along with an `Int`: + +```` +scala> executeNTimes(helloWorld, 3) +Hello, world +Hello, world +Hello, world +```` + +Excellent. The `executeNTimes` method executes the `helloWorld` function three times. + +Your methods can continue to get as complicated as necessary. For example, this method takes a function of type `(Int, Int) => Int`, along with two input parameters: + +```scala +def executeAndPrint(f: (Int, Int) => Int, i: Int, j: Int): Unit = + println(f(i, j)) +``` + +Again, because methods like these match that type signature, they can be passed into `executeAndPrint`: + +```scala +def sum(x: Int, y: Int) = x + y +def multiply(x: Int, y: Int) = x * y + +executeAndPrint(sum, 3, 11) // prints 14 +executeAndPrint(multiply, 3, 9) // prints 27 +``` + + +### Consistency in the use of function type signatures + +One of the great things about Scala is the consistency of the language. In this case, this means that the syntax you use to define function input parameters is the same syntax you use to write anonymous functions and function variables. + +For instance, if you were to write an anonymous function that calculates the sum of two integers, you’d write it like this: + +```scala +(Int, Int) => Int = (a, b) => a + b +``` + +That code consists of the type signature: + +```` +(Int, Int) => Int = (a, b) => a + b +----------------- +```` + +The input parameters: + +```` +(Int, Int) => Int = (a, b) => a + b + ------ +```` + +and the body of the function: + +```` +(Int, Int) => Int = (a, b) => a + b + ----- +```` + +The consistency in Scala is shown here, where this anonymous function type signature: + +```` +(Int, Int) => Int = (a, b) => a + b +----------------- +```` + +is the same as the type signature you use to define a function input parameter: + +```` +def executeAndPrint(f: (Int, Int) => Int, ... + ----------------- +```` + +Once you’re comfortable with this syntax, you’ll use it to define function parameters, anonymous functions, and function variables, and it becomes easier to read the Scaladoc for higher-order functions. + + +### How to write your own `map` method + +At this point you can now write your own methods that take function parameters. For instance, if the `List` class didn’t have its own `map` method, you could write your own. + +A good first step for this is to accurately state the problem. Focusing only on a `List[Int]`, you state: + +>I want to write a `map` method that can be used to apply other functions to each element in a `List[Int]` that it’s given, returning the transformed elements as a new list. + +Given that statement, you start to write the method signature. First, you know that you want to accept a function as a parameter, and that function should transform an `Int` into some generic type `A`, so you start to write: + +```scala +def map(f: (Int) => A +``` + +The syntax for using a generic type requires declaring that type symbol before the parameter list: + +```scala +def map[A](f: (Int) => A +``` + +Next, you know that you also want to accept a `List[Int]`: + +```scala +def map[A](f: (Int) => A, xs: List[Int] +``` + +You also know that `map` returns a transformed list of the generic type `A`: + +```scala +def map[A](f: (Int) => A, xs: List[Int]): List[A] = ??? +``` + +That takes care of the method signature. Now all you have to do is write the method body. A `map` method applies the function it’s given to every element in the list it’s given to produce a new, transformed list. One way to do this is with a `for` expression: + +```scala +for x <- xs yield f(x) +``` + +Putting this together with the method signature, you now have a standalone `map` method that works with a `List[Int]`: + +```scala +def map[A](f: (Int) => A, xs: List[Int]): List[A] = + for x <- xs yield f(x) +``` + +As a bonus, because the method body doesn’t care about the type inside the `List`, you can replace `Int` in the type signature with a generic type parameter: + +```scala +def map[A,B](f: (B) => A, xs: List[B]): List[A] = + for x <- xs yield f(x) +``` + +Now you have a `map` method that works with any `List`. + +These examples demonstrate that `map` works as desired: + +```scala +def double(i : Int) = i * 2 +map(double, List(1,2,3)) // List(2,4,6) + +def strlen(s: String) = s.length +map(strlen, List("a", "bb", "ccc")) // List(1, 2, 3) +``` + +Now that you’ve seen how to write methods that accept functions as parameters, let’s look at methods that return functions. + + +## Writing a method that returns a function + +Thanks to Scala’s consistency, writing a method that returns a function is similar to everything you just saw. For instance, to define a “greeting” method that returns a function, start by defining an anonymous function: + +```scala +(name: String) => println(s"Hello, $name") +``` + +This anonymous function takes a `String` input parameter and returns nothing, so it has this type: + +```scala +String => Unit +``` + +Therefore, if you want to write a method that returns this function, first define the method signature: + +```scala +def greet(): String => Unit = ??? +``` + +Now you just need to add in the method body. In this case the method returns that anonymous function, so the complete method looks like this: + +```scala +// a method that returns a function +def greet(): String => Unit = + (name: String) => println(s"Hello, $name") +``` + +Because that method returns a function, you first create your new function: + +```scala +val greetFunction = greet() +``` + +When you put that line of code in the REPL, you see that it has the type `String => Unit`, as expected: + +```` +scala> val greetFunction = greet() +val greetFunction: String => Unit = Lambda.... + ----------------------------- +```` + +Now you can call your new `greetFunction`: + +```scala +greetFunction("Joe") // prints "Hello, Joe" +``` + +Congratulations, you just created a method that returns a function, and then executed that function. + + +### Improving the method + +That function would be more useful if you could pass in a greeting, so let’s do that. All you have to do is pass the greeting in as a parameter to the `greet` method, and use it in the string inside `println`: + +```scala +def greet(theGreeting: String): String => Unit = + (name: String) => println(s"$theGreeting, $name") +``` + +Now when you call your method, the process is more flexible because you can change the greeting. Again, the first step of creating a function from the method is good to show in the REPL because it shows the resulting type: + +```` +scala> val sayHello = greet("Hello") +val sayHello: String => Unit = Lambda..... + ------------------------ +```` + +This shows that `sayHello` is a function that takes a `String` input parameter and returns `Unit` (nothing). So now when you give `sayHello` a `String`, it prints the greeting: + +```scala +sayHello("Joe") // prints "Hello, Joe" +``` + +You can also change the greeting and create a new function, as desired: + +```scala +val sayHey = greet("Hey") +sayHey("Joe") // prints "Hey, Joe" +``` + + + +### A more real-world example + +In a more real-world example, a method like this is more useful when it can return one of many possible functions, like a factory that returns custom-built functions. + +For instance, imagine that you want to write a method that returns functions that greet people in different languages. We’ll limit this to functions that greet in English or French, depending on a parameter that’s passed into the method. + +A first thing you know is that you want to create a method that (a) takes a “desired language” as an input, and (b) returns a function as its result. Furthermore, because that function will print a string that it’s given, you know it has the type `String => Unit`. With that information you can start writing the method signature like this: + +```scala +def createGreetingFunction(desiredLanguage: String): String => Unit = ??? +``` + +That’s a good start. Because you know that the possible functions you’ll return take a string and print it, you can write two anonymous functions like this for the English and French languages: + +```scala +(name: String) => println(s"Hello, $name") +(name: String) => println(s"Bonjour, $name") +``` + +Inside a method it might be a little more readable if you give those anonymous functions some names, so let’s write them like this instead: + +```scala +val englishGreeting = (name: String) => println(s"Hello, $name") +val frenchGreeting = (name: String) => println(s"Bonjour, $name") +``` + +Now all you need to do is (a) return `englishGreeting` if the `desiredLanguage` is English, and (b) return `frenchGreeting` if the `desiredLanguage` is French. One way to do that is with a `match` expression: + +```scala +def createGreetingFunction(desiredLanguage: String): String => Unit = + val englishGreeting = (name: String) => println(s"Hello, $name") + val frenchGreeting = (name: String) => println(s"Bonjour, $name") + desiredLanguage match + case "english" => englishGreeting + case "french" => frenchGreeting +``` + +And that’s the final method. Notice that returning a function value from a method is no different than returning a string or integer value. + +This is how `createGreetingFunction` builds a French-greeting function: + +```scala +val greetInFrench = createGreetingFunction("french") +greetInFrench("Raphael") // prints "Bonjour, Raphael" +``` + +And this is how it builds an English-greeting function: + +```scala +val greetInEnglish = createGreetingFunction("english") +greetInEnglish("Joe") // prints "Hello, Joe" +``` + +If this all makes sense — congratulations — you’ve just seen how to write methods that return functions. + + + +## Summary + +A higher-order function is often defined as a function that takes other functions as input parameters or returns a function as a result. In Scala this is possible because functions are first-class values. + +In previous chapters you saw how to be a *consumer* of higher-order functions, and this chapter showed you how to be a *creator* of higher-order functions. Specifically, you saw: + +- How to write methods that take functions as input parameters +- How to return a function from a method + +A beneficial side effect of this chapter is that you saw many examples of how to declare type signatures for functions. The benefits of that are that you’ll use that same syntax to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions like `map`, `filter`, and others. + + + diff --git a/_overviews/overview/main-methods.md b/_overviews/overview/main-methods.md new file mode 100644 index 0000000000..a32f6d7920 --- /dev/null +++ b/_overviews/overview/main-methods.md @@ -0,0 +1,136 @@ +--- +title: Main Methods +description: This page describes how 'main' methods and the '@main' annotation work in Scala 3. +--- + + + +Scala 3 offers a new way to define programs that can be invoked from the command line: Adding an `@main` annotation to a method turns that method into an executable program: + +```tut +@main def hello = println("Hello, world") +``` + +Just save that line of code in a file named something like *Hello.scala* — the filename doesn’t have to match the method name — and compile it with `scalac`: + +```sh +$ scalac Hello.scala +``` + +Then run it with `scala`: + +```sh +$ scala hello +Hello, world +``` + +An `@main` annotated method can be written either at the top-level (as shown), or inside a statically accessible object. In either case, the name of the program is in each case the name of the method, without any object prefixes. + + + +### Command line arguments + +With this approach your `@main` method can handle command line arguments, and those arguments can have different types. For example, given this `@main` method that takes an `Int`, a `String`, and a varargs `String*` parameter: + +```scala +@main def happyBirthday(age: Int, name: String, others: String*) = { + val suffix = + (age % 100) match { + case 11 | 12 | 13 => "th" + case _ => + (age % 10) match { + case 1 => "st" + case 2 => "nd" + case 3 => "rd" + case _ => "th" + } + } + val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name") + for other <- others do bldr.append(" and ").append(other) + bldr.toString +} +``` + +When you compile that code, it creates a main program named `happyBirthday` that’s called like this: + +``` +$ scala happyBirthday 23 Lisa Peter +Happy 23rd Birthday, Lisa and Peter! +``` + +As shown, the `@main` method can have an arbitrary number of parameters. For each parameter type there must be an instance of the *scala.util.FromString* type class that converts an argument `String` to the required parameter type. Also as shown, a main method’s parameter list can end in a repeated parameter like `String*` that takes all remaining arguments given on the command line. + + +The program implemented from an `@main` method checks that there are enough arguments on the command line to fill in all parameters, and that the argument strings can be converted to the required types. If a check fails, the program is terminated with an error message: + +``` +$ scala happyBirthday 22 +Illegal command line after first argument: more arguments expected + +$ scala happyBirthday sixty Fred +Illegal command line: java.lang.NumberFormatException: For input string: "sixty" +``` + + + + +## The details + +The Scala compiler generates a program from an `@main` method `f` as follows: + +- It creates a class named `f` in the package where the `@main` method was found. +- The class has a static method `main` with the usual signature: It takes an `Array[String]` as argument and returns `Unit`. +- The generated `main` method calls method `f` with arguments converted using methods in the *scala.util.CommandLineParser* object. + +For instance, the `happyBirthday` method above generates additional code equivalent to the following class: + +```scala +final class happyBirthday { + import scala.util.{CommandLineParser => CLP} + def main(args: Array[String]): Unit = + try + happyBirthday( + CLP.parseArgument[Int](args, 0), + CLP.parseArgument[String](args, 1), + CLP.parseRemainingArguments[String](args, 2)) + catch { + case error: CLP.ParseError => CLP.showError(error) + } +} +``` + +>**Note**: In this generated code, the `` modifier expresses that the `main` method is generated as a static method of class `happyBirthday`. This feature is not available for user programs in Scala. Regular “static” members are generated in Scala using objects instead. + + + +## Scala 3 compared to Scala 2 + +`@main` methods are the recommended way to generate programs that can be invoked from the command line in Scala 3. They replace the previous approach in Scala 2, which was to create an `object` that extends the `App` class: + +```scala +// scala 2 +object happyBirthday extends App: + // needs by-hand parsing of the command line arguments ... +``` + +The previous functionality of `App`, which relied on the “magic” `DelayedInit` trait, is no longer available. `App` still exists in limited form for now, but it doesn’t support command line arguments and will be deprecated in the future. + +If programs need to cross-build between Scala 2 and Scala 3, it’s recommended to use an explicit `main` method with an `Array[String]` argument instead: + +```scala +object happyBirthday: + def main(args: Array[String]) = println("Hello, world") +``` + +If you place that code in a file named *happyBirthday.scala*, you can then compile it with `scalac` and run it with `scala`, as shown previously: + +```sh +$ scalac happyBirthday.scala + +$ scala happyBirthday +Hello, world +``` + + + + From 9ac0fb79f15685cc8eb20f4ae1b2611382364a1d Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sat, 31 Oct 2020 22:38:30 -0600 Subject: [PATCH 0198/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98Packaging=20and=20Imports=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/packaging-imports.md | 378 +++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 _overviews/overview/packaging-imports.md diff --git a/_overviews/overview/packaging-imports.md b/_overviews/overview/packaging-imports.md new file mode 100644 index 0000000000..4785a4aafc --- /dev/null +++ b/_overviews/overview/packaging-imports.md @@ -0,0 +1,378 @@ +--- +title: Packaging and Imports +description: A discussion of using packages and imports to organize your code, build related modules of code, control scope, and help prevent namespace collisions. +--- + + + +Scala uses *packages* to create namespaces that let you modularize programs and help prevent namespace collisions. Scala supports the package-naming style used by Java, and also the “curly brace” namespace notation used by languages like C++ and C#. + +The Scala approach to importing members is also similar to Java, and more flexible. With Scala you can: + +- Import packages, classes, objects, traits, and methods +- Place import statements anywhere +- Hide and rename members when you import them + +These features are demonstrated in the following examples. + + + +## Creating a package + +Packages are created by declaring one or more package names at the top of a Scala file. For example, when your domain name is _acme.com_ and you’re working in the _model_ package of an application named _myapp_, your package declaration looks like this: + +```scala +package com.acme.myapp.model + +class Person ... +``` + +By convention, package names should be all lower case, and the formal naming convention is *...*. + +Although it’s not required, package names typically follow directory structure names, so if you follow this convention, a `Person` class in this project will be found in a *MyApp/src/main/scala/com/acme/myapp/model/Person.scala* file. + + +### Curly brace packaging style + +The other way to declare packages in Scala is by using the curly brace namespace notation used in languages like C, C++, and C#: + +```tut +package users { + package administrators { + class AdminUser + } + package normalusers { + class NormalUser + } +} +``` + +The advantages of this approach are that it allows for package nesting, and provides more obvious control of scope and encapsulation, especially within the same file. + + + + +## Import statements, Part 1 + +Import statements are used to access entities in other packages. Import statements fall into two main categories: + +- Importing classes, traits, objects, functions, and methods +- Importing `given` clauses + +If you’re used to a language like Java, the first class of import statements is similar to what Java uses, with a slightly different syntax that allows for more flexibility. These examples demonstrate some of that flexibility: + +```` +import users._ // import everything from the `users` package +import users.User // import only the `User` class +import users.{User, UserPreferences} // only import the selected members +import users.{UserPreferences => UPrefs} // rename a member as you import it +```` + +Those examples are meant to give you a taste of how the first class of `import` statements work. They’re explained more in the subsections that follow. + +Import statements are also used to import `given` instances into scope. Those are discussed at the end of this chapter. + +Two notes before moving on: + +- Import clauses are not required for accessing members of the same package. +- When the `_` character is used in Scala import statements, it’s similar to the `*` character in Java. One reason for this difference is that in Scala, the `*` character can be used for method names. + + +### Importing one or more members + +In Scala you can import one member from a package like this: + +```scala +import java.io.File +``` + +and multiple members like this: + +```scala +import java.io.File +import java.io.IOException +import java.io.FileNotFoundException +``` + +When importing multiple members, you can import them more concisely like this: + +```scala +import java.io.{File, IOException, FileNotFoundException} +``` + +When you want to import everything from the *java.io* package, use this syntax: + +```scala +import java.io._ +``` + + +### Renaming members on import + +Sometimes it can help to rename entities when you import them to avoid name collisions. For instance, if you want to use the Scala `List` class and also the *java.util.List* class at the same time, you can rename the *java.util.List* class when you import it: + +```scala +import java.util.{List => JavaList} +``` + +Now you use the name `JavaList` to refer to that class, and use `List` to refer to the Scala list class. + +You can also rename multiple members at one time using this syntax: + +```scala +import java.util.{Date => JDate, HashMap => JHashMap, _} +``` + +That line of code says, “Rename the `Date` and `HashMap` classes as shown, and import everything else in the _java.util_ package without renaming any other members.” + + +### Hiding members on import + +You can also *hide* members during the import process. This `import` statement hides the *java.util.Random* class, while importing everything else in the *java.util* package: + +```scala +import java.util.{Random => _, _} +``` + +If you try to access the `Random` class it won’t work, but you can access all other members from that package: + +```scala +val r = new Random // won’t compile +new ArrayList // works +``` + +#### Hiding multiple members + +To hide multiple members during the import process, list them before using the final wildcard import: + +```scala +scala> import java.util.{List => _, Map => _, Set => _, _} +import java.util.{List=>_, Map=>_, Set=>_, _} +``` + +Once again those classes are hidden, but you can use all other classes in *java.util*: + +```scala +scala> new ArrayList[String] +val res0: java.util.ArrayList[String] = [] +``` + +Because those Java classes are hidden, you can also use the Scala `List`, `Set`, and `Map` classes without having a naming collision: + +```scala +scala> val a = List(1,2,3) +val a: List[Int] = List(1, 2, 3) + +scala> val b = Set(1,2,3) +val b: Set[Int] = Set(1, 2, 3) + +scala> val c = Map(1->1, 2->2) +val c: Map[Int, Int] = Map(1 -> 1, 2 -> 2) +``` + + +### Use imports anywhere + +In Scala, `import` statements can be anywhere. They can be used at the top of a source code file: + +```scala +package foo + +import scala.util.Random + +class ClassA: + def printRandom: + val r = new Random // use the imported class + // more code here... +``` + +You can also use `import` statements closer to the point where they are needed, if you prefer: + +```scala +package foo + +class ClassA: + import scala.util.Random // inside ClassA + def printRandom { + val r = new Random + // more code here... + +class ClassB: + // the Random class is not visible here + val r = new Random // this code will not compile +``` + + +### “Static” imports + +When you want to import members in a way similar to the Java “static import” approach — so you can refer to the member names directly, without having to prefix them with their class name — use the following approach. + +Use this syntax to import all static members of the Java `Math` class: + +```scala +import java.lang.Math._ +``` + +Now you can access static `Math` class methods like `sin` and `cos` without having to precede them with the class name: + +```scala +import java.lang.Math._ + +val a = sin(0) // 0.0 +val b = cos(PI) // -1.0 +``` + + +### Packages imported by default + +Two packages are implicitly imported into the scope of all of your source code files: + +- java.lang._ +- scala._ + +The Scala `Predef` object is also imported by default. + +>If you ever wondered why you can use classes like `List`, `Vector`, `Map`, etc., without importing them, they’re available because of definitions in the `Predef` object. + + + +### Handling naming conflicts + +In the rare event there’s a naming conflict and you need to import something from the root of the project, prefix the package name with `_root_`: + +``` +package accounts + +import _root_.users._ +``` + + + +## Importing `given` instances + + +As you’ll see in the Contextual Abstractions chapter, a special form of the `import` statement is used to import `given` instances. The basic form is shown in this example: + + +```tut +object A: + class TC + given tc as TC + def f(using TC) = ??? + +object B: + import A._ // import all non-given members + import A.given // import the given instance +``` + +In this code, the `import A._` clause of object `B` imports all members of `A` *except* the `given` instance `tc`. Conversely, the second import, `import A.given`, imports *only* that `given` instance. The two `import` clauses can also be merged into one: + +```scala +object B: + import A.{given, _} +``` + +### Discussion + +The wildcard selector `_` brings all definitions other than givens or extensions into scope, whereas a `given` selector brings all *givens* — including those resulting from extensions — into scope. + +These rules have two main benefits: + +- It’s more clear where givens in scope are coming from. In particular, it’s not possible to hide imported givens in a long list of other wildcard imports. +- It enables importing all givens without importing anything else. This is particularly important since givens can be anonymous, so the usual use of named imports is not practical. + + +### By-type imports + +Since givens can be anonymous, it’s not always practical to import them by their name, and wildcard imports are typically used instead. *By-type imports* provide a more specific alternative to wildcard imports, which makes it more clear what is imported: + +```scala +import A.{given TC} +``` + +This imports any `given` in `A` that has a type which conforms to `TC`. Importing givens of several types `T1,...,Tn` is expressed by multiple `given` selectors: + +```scala +import A.{given T1, ..., given Tn} +``` + +Importing all `given` instances of a parameterized type is expressed by wildcard arguments. For example, when you have this `object`: + +```scala +object Instances: + given intOrd as Ordering[Int] + given listOrd[T: Ordering] as Ordering[List[T]] + given ec as ExecutionContext = ... + given im as Monoid[Int] +``` + +This import statement imports the `intOrd`, `listOrd`, and `ec` instances, but leaves out the `im` instance because it doesn’t fit any of the specified bounds: + +```scala +import Instances.{given Ordering[?], given ExecutionContext} +``` + +By-type imports can be mixed with by-name imports. If both are present in an import clause, by-type imports come last. For instance, this import clause imports `im`, `intOrd`, and `listOrd`, but leaves out `ec`: + +```scala +import Instances.{im, given Ordering[?]} +``` + + +### An example + +As a concrete example, imagine that you have this `MonthConversions` object that contains two `given` definitions: + +```scala +object MonthConversions: + trait MonthConverter[A]: + def convert(a: A): String + + given intMonthConverter as MonthConverter[Int]: + def convert(i: Int): String = + i match + case 1 => "January" + case 2 => "February" + // more cases here ... + + given stringMonthConverter as MonthConverter[String]: + def convert(s: String): String = + s match + case "jan" => "January" + case "feb" => "February" + // more cases here ... +} +``` + +To import those givens into the current scope, use these two `import` statements: + +```scala +import MonthConversions._ +import MonthConversions.{given MonthConverter[?]} +``` + +Now you can create a method that uses those `given` instances: + +```scala +def genericMonthConverter[A](a: A)(using monthConverter: MonthConverter[A]): String = + monthConverter.convert(a) +``` + +Then you can use that method in your application: + +```scala +@main def main = + println(genericMonthConverter(1)) // January + println(genericMonthConverter("jan")) // January +``` + +As mentioned, one of the key design benefits of the “import given” syntax is to make it clear where givens in scope come from, and it’s clear in these `import` statements that the givens come from the `MonthConversions` object. + + + +## Summary + +While that covers almost all of the features of packing and imports, see the Reference documentation for a few more details and features. + + + From 8f3c91e837013c66bd530ca1fa14541792b358bd Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sat, 31 Oct 2020 22:39:06 -0600 Subject: [PATCH 0199/2265] =?UTF-8?q?Renamed=20the=20=E2=80=98Packaging=20?= =?UTF-8?q?and=20Imports=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/packaging-imports-exports.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 _overviews/overview/packaging-imports-exports.md diff --git a/_overviews/overview/packaging-imports-exports.md b/_overviews/overview/packaging-imports-exports.md deleted file mode 100644 index e69de29bb2..0000000000 From a65106b6842313159095d988432ccec42196500a Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sun, 1 Nov 2020 21:14:37 -0700 Subject: [PATCH 0200/2265] =?UTF-8?q?Didn=E2=80=99t=20make=20this=20shorte?= =?UTF-8?q?r,=20but=20improved=20some=20areas.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/higher-order-functions.md | 186 +++++++++--------- 1 file changed, 95 insertions(+), 91 deletions(-) diff --git a/_overviews/overview/higher-order-functions.md b/_overviews/overview/higher-order-functions.md index cb427b3b69..eec8bbab99 100644 --- a/_overviews/overview/higher-order-functions.md +++ b/_overviews/overview/higher-order-functions.md @@ -3,15 +3,15 @@ title: Higher-order Functions description: This page demonstrates how to create and use higher-order functions in Scala. --- - -A higher-order function is often defined as a function that (a) takes other functions as input parameters or (b) returns a function as a result. In Scala this is possible because functions are first-class values. While we use the term “higher-order function,” in Scala this phrase is used for both *methods* and *functions* because they can generally be used in the same places. +A higher-order function is often defined as a function that (a) takes other functions as input parameters or (b) returns a function as a result. In Scala, higher-order functions are possible because functions are first-class values. + +As an important point, while we use the common industry term “higher-order function,” in Scala this phrase applies to both *methods* and *functions* because — thanks to [Eta Expansion](TODO:link) — they can generally be used in the same places. + ->The ability to pass functions around as values enables a form of “power” programming that lets you write code that’s concise and still readable. +### From consumer to creator -In the examples so far you’ve seen how to be the *consumer* of functions that take other functions as input parameters, such as higher-order functions like `map` and `filter`. In this chapter you’ll see how to be the *creator* of higher-order functions, including: +In the examples so far in this Overview, you’ve seen how to be a *consumer* of methods that take other functions as input parameters, such as using higher-order functions like `map` and `filter`. In this chapter you’ll see how to be a *creator* of higher-order functions, including: - How to write methods that take functions as input parameters - How to return a function from a method @@ -19,10 +19,9 @@ In the examples so far you’ve seen how to be the *consumer* of functions that In the process you’ll see: - The syntax you use to define function input parameters -- Multiple examples of that syntax - How to call a function once you have a reference to it -As a beneficial side effect of this chapter, once you’re comfortable with the syntax, you’ll use it to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions. +As a beneficial side effect of this chapter, once you’re comfortable with this syntax, you’ll use it to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions. @@ -30,38 +29,39 @@ As a beneficial side effect of this chapter, once you’re comfortable with the As a quick recap, in this Overview you’ve already seen examples of how to use existing higher-order functions in the Scala collections classes, including `map` and `filter`: -```scala +```tut List(1,2,3).map(_ * 10) // List(10,20,30) def isEven(i: Int) = i % 2 == 0 Vector(1,2,3,4).filter(isEven) // Vector(2,4) ``` -A few key points of the `filter` example are: - -- `filter` accepts a function, anonymous function, or method as an input parameter. -- The functions you pass into `filter` must match the type signature that `filter` expects — in this example, a function that takes an `Int` input parameter and returns a `Boolean`. +A few key points about these examples: ->Although we use the term “function,” `filter` can accept a *method* as a parameter thanks to Scala’s [Eta Expansion](TODO:LINK) technology. +- The functions you pass into them must match their expected type signature +- They take a function, anonymous function, or method as an input parameter +- [Eta Expansion](TODO:link) is the technology that enables you to pass a method into a place where a function is expected ### Understanding `filter`’s Scaladoc -You can understand the type of functions `filter` accepts by looking at its Scaladoc. For example here’s the `filter` definition on the `List` class: +To understand how higher-order functions work, it helps to dig into an example. For instance, you can understand the type of functions `filter` accepts by looking at its Scaladoc. Here’s the `filter` definition in the `List` class: ```scala def filter(p: (A) => Boolean): List[A] ``` -This states that `filter` is a method that takes a predicate parameter named `p` and returns a `List[A]`. (A *predicate* is just a function that returns a `Boolean` value.) Without looking at the internal details of `filter`, all we know is that it somehow uses that predicate to return a new list of the type `List[A]`, where `A` is the type in the list. +This states that `filter` is a method that takes a function parameter named `p`. By convention, `p` stands for a *predicate*, which is just a function that returns a `Boolean` value. So `filter` takes `p` as an input parameter, and returns a `List[A]`, where `A` the type held in the list. If you call `filter` on a `List[Int]`, `A` is the type `Int`. -Digging a little deeper, this part of `filter`’s description: +If you didn’t know how `filter` works, all you’d know is that it somehow uses the predicate to create and return the `List[A]`. + +Digging into the function parameter, this part of `filter`’s description: ```scala p: (A) => Boolean ``` -means that `filter` takes a function input parameter named `p`, and `p` must transform a generic input `A` into a `Boolean` value. Therefore, if a list holds the type `Int`, you can replace the generic type `A` with `Int`, and read that signature like this: +means that whatever function you pass in must take the type `A` as an input parameter and return a `Boolean`. So if your list is a `List[Int]`, you can replace the generic type `A` with `Int`, and read that signature like this: ```scala p: (Int) => Boolean @@ -70,6 +70,7 @@ p: (Int) => Boolean Because `isEven` has this type — it transforms an input `Int` into a resulting `Boolean` — it can be used with `filter`. + ## Writing methods that take functions as parameters ->Note: To make the following sections more clear, we’ll refer to the code you’re writing as a *method*, and the code you’re accepting as an input parameter as a *function*. - +**Note:** To make the following sections more clear, we’ll refer to the code you’re writing as a *method*, and the code you’re accepting as an input parameter as a *function*. Given that background, let’s start writing methods that take functions as input parameters. -To define a method that takes a function parameter, all you have to do is: +To create a method that uses a function parameter, all you have to do is: 1. In your method’s parameter list, define the signature of the function you want to accept 2. Use that function inside your method To demonstrate this, here’s a method that that takes an input parameter named `f`, where `f` is a function: -```scala +```tut def sayHello(f: () => Unit): Unit = f() ``` -This portion of the code — the *type signature* — defines the types of functions the `sayHello` method will accept: +This portion of the code — the *type signature* — states that `f` is a function, and defines the types of functions the `sayHello` method will accept: ```scala f: () => Unit @@ -140,11 +140,11 @@ Here’s how this works: - The type signature of `f` specifies the *type* of the functions this method will accept. - The `()` portion of `f`’s signature (on the left side of the `=>` symbol) states that `f` takes no input parameters. - The `Unit` portion of the signature (on the right side of the `=>` symbol) indicates that `f` should return nothing. -- Looking back at the body of the `sayHello` method, the `f()` statement there invokes the function that’s passed in. +- Looking back at the body of the `sayHello` method (on the right side of the `=` symbol), the `f()` statement there invokes the function that’s passed in. -Now that we’ve defined `sayHello`, let’s create a function to match `f`’s signature so we can test it. For instance, the following function takes no input parameters and returns nothing, so it matches `f`’s type signature: +Now that we’ve defined `sayHello`, let’s create a function to match `f`’s signature so we can test it. The following function takes no input parameters and returns nothing, so it matches `f`’s type signature: -```scala +```tut def helloJoe(): Unit = println("Hello, Joe") ``` @@ -154,23 +154,23 @@ Because the type signatures match, you can pass `helloJoe` into `sayHello`: sayHello(helloJoe) // prints "Hello, Joe" ``` -If you’ve never done this before, congratulations. You just defined a method named `sayHello` that takes another function as an input parameter, and then invokes that function when it’s called. +If you’ve never done this before, congratulations. You just defined a method named `sayHello` that takes a function as an input parameter, and then invokes that function in its method body. ### sayHello can take many functions It’s important to know that the beauty of this approach is not that `sayHello` can take *one* function as an input parameter; the beauty is that it can take *any* function that matches `f`’s signature. For instance, because this next function takes no input parameters and returns nothing, it also works with `sayHello`: -```scala +```tut def bonjourJulien(): Unit = println("Bonjour, Julien") ``` Here it is in the REPL: -```scala +```` scala> sayHello(bonjourJulien) Bonjour, Julien -``` +```` This is a good start. The only thing to do now is see a few more examples of how to define different type signatures for function parameters. @@ -186,10 +186,10 @@ def sayHello(f: () => Unit) The type signature for `f` is: ```scala -f: () => Unit +() => Unit ``` -We know that’s a function that takes no input parameters and returns nothing (given by `Unit`). +We know that this means, “a function that takes no input parameters and returns nothing (given by `Unit`).” To demonstrate more type signature examples, here’s a function that takes a `String` parameter and returns an `Int`: @@ -197,7 +197,7 @@ To demonstrate more type signature examples, here’s a function that takes a `S f: (String) => Int ``` -That could be something like a string length or checksum function. +What kinds of functions take a string and return an integer? Functions like “string length” and checksum are two examples. Similarly, this function takes two `Int` parameters and return an `Int`: @@ -214,36 +214,36 @@ variableName: (parameterTypes ...) => returnType Going back to this type signature: ```scala -f: (Int, Int) => Int +(Int, Int) => Int ``` Can you imagine what sort of functions match that signature? -The answer is that any function that takes two `Int` input parameters and returns an `Int` matches that signature, so all of these functions match that signature: +The answer is that any function that takes two `Int` input parameters and returns an `Int` matches that signature, so all of these functions are a match: -```scala +```tut def add(a: Int, b: Int): Int = a + b def subtract(a: Int, b: Int): Int = a - b def multiply(a: Int, b: Int): Int = a * b ``` ->Because functional programming is like combining a series of algebraic equations, it’s common to think about types a *lot*. You might say that you “think in types.” +>Because functional programming is like creating and combining a series of algebraic equations, it’s common to think about types a *lot* when designing functions and applications. You might say that you “think in types.” ### Taking a function parameter along with other parameters -So far the methods we’ve shown have only taken a function input parameter. But for a method like this to be really interesting, it must also have some data to work on. For a class like `List`, its `map` method already has data to work on: the data in the `List`. But for a standalone method that doesn’t have its own data, it should accept data as another input parameter. +For higher-order functions to be really useful, they also need some data to work on. For a class like `List`, its `map` method already has data to work on: the data in the `List`. But for a standalone higher-order function that doesn’t have its own data, it should also accept data as other input parameters. For instance, here’s a method named `executeNTimes` that has two input parameters: a function, and an `Int`: -```scala +```tut def executeNTimes(f: () => Unit, n: Int): Unit = for i <- 1 to n do f() ``` -As the code shows, `executeNTimes` executes the `f` function `n` times. Because `f` returns `Unit`, `executeNTimes` also returns `Unit`. To test `executeNTimes`, define a method that matches `f`’s signature: +As the code shows, `executeNTimes` executes the `f` function `n` times. Because a simple `for` loop like this has no return value, `executeNTimes` returns `Unit`. To test `executeNTimes`, define a method that matches `f`’s signature: -```scala +```tut // a method of type `() => Unit` def helloWorld(): Unit = println("Hello, world") ``` @@ -261,12 +261,12 @@ Excellent. The `executeNTimes` method executes the `helloWorld` function three t Your methods can continue to get as complicated as necessary. For example, this method takes a function of type `(Int, Int) => Int`, along with two input parameters: -```scala +```tut def executeAndPrint(f: (Int, Int) => Int, i: Int, j: Int): Unit = println(f(i, j)) ``` -Again, because methods like these match that type signature, they can be passed into `executeAndPrint`: +Because these `sum` and `multiply` methods match that type signature, they can be passed into `executeAndPrint`: ```scala def sum(x: Int, y: Int) = x + y @@ -279,7 +279,7 @@ executeAndPrint(multiply, 3, 9) // prints 27 ### Consistency in the use of function type signatures -One of the great things about Scala is the consistency of the language. In this case, this means that the syntax you use to define function input parameters is the same syntax you use to write anonymous functions and function variables. +Scala’s syntax is very consistent. In this case, this means that the syntax you use to define function input parameters is the same syntax you use to write anonymous functions and function variables. For instance, if you were to write an anonymous function that calculates the sum of two integers, you’d write it like this: @@ -308,7 +308,7 @@ and the body of the function: ----- ```` -The consistency in Scala is shown here, where this anonymous function type signature: +Scala’s consistency is shown here, where this anonymous function type signature: ```` (Int, Int) => Int = (a, b) => a + b @@ -327,31 +327,33 @@ Once you’re comfortable with this syntax, you’ll use it to define function p ### How to write your own `map` method -At this point you can now write your own methods that take function parameters. For instance, if the `List` class didn’t have its own `map` method, you could write your own. +Now that you’ve seen how to write your own higher-order functions, let’s take a quick look at a more real-world example. + +Imagine for a moment that the `List` class doesn’t have its own `map` method, and you want to write your own. -A good first step for this is to accurately state the problem. Focusing only on a `List[Int]`, you state: +A good first step when creating functions is to accurately state the problem. Focusing only on a `List[Int]`, you state: ->I want to write a `map` method that can be used to apply other functions to each element in a `List[Int]` that it’s given, returning the transformed elements as a new list. +>I want to write a `map` method that can be used to a function to each element in a `List[Int]` that it’s given, returning the transformed elements as a new list. -Given that statement, you start to write the method signature. First, you know that you want to accept a function as a parameter, and that function should transform an `Int` into some generic type `A`, so you start to write: +Given that statement, you start to write the method signature. First, you know that you want to accept a function as a parameter, and that function should transform an `Int` into some generic type `A`, so you write: ```scala def map(f: (Int) => A ``` -The syntax for using a generic type requires declaring that type symbol before the parameter list: +The syntax for using a generic type requires declaring that type symbol before the parameter list, so you add that: ```scala def map[A](f: (Int) => A ``` -Next, you know that you also want to accept a `List[Int]`: +Next, you know that `map` should also accept a `List[Int]`: ```scala -def map[A](f: (Int) => A, xs: List[Int] +def map[A](f: (Int) => A, xs: List[Int]) ``` -You also know that `map` returns a transformed list of the generic type `A`: +Finally, you also know that `map` returns a transformed `List` that contains elements of the generic type `A`: ```scala def map[A](f: (Int) => A, xs: List[Int]): List[A] = ??? @@ -363,16 +365,18 @@ That takes care of the method signature. Now all you have to do is write the met for x <- xs yield f(x) ``` -Putting this together with the method signature, you now have a standalone `map` method that works with a `List[Int]`: +As with this example, `for` expressions often make code surprisingly simple, and that ends up being the entire method body. -```scala +Putting it together with the method signature, you now have a standalone `map` method that works with a `List[Int]`: + +```tut def map[A](f: (Int) => A, xs: List[Int]): List[A] = for x <- xs yield f(x) ``` -As a bonus, because the method body doesn’t care about the type inside the `List`, you can replace `Int` in the type signature with a generic type parameter: +As a bonus, notice that the `for` expression doesn’t do anything that depends on the type inside the `List` being `Int`. Therefore, you can replace `Int` in the type signature with a generic type parameter: -```scala +```tut def map[A,B](f: (B) => A, xs: List[B]): List[A] = for x <- xs yield f(x) ``` @@ -383,50 +387,49 @@ These examples demonstrate that `map` works as desired: ```scala def double(i : Int) = i * 2 -map(double, List(1,2,3)) // List(2,4,6) +map(double, List(1,2,3)) // List(2,4,6) def strlen(s: String) = s.length map(strlen, List("a", "bb", "ccc")) // List(1, 2, 3) ``` -Now that you’ve seen how to write methods that accept functions as parameters, let’s look at methods that return functions. +Now that you’ve seen how to write methods that accept functions as input parameters, let’s look at methods that return functions. ## Writing a method that returns a function -Thanks to Scala’s consistency, writing a method that returns a function is similar to everything you just saw. For instance, to define a “greeting” method that returns a function, start by defining an anonymous function: +Thanks to Scala’s consistency, writing a method that returns a function is similar to everything you just saw. For example, imagine that you want to write a `greet` method that returns a function. The statement of what we want to build goes like this: -```scala -(name: String) => println(s"Hello, $name") -``` +>I want to create a `greet` method that returns a function. That function will take a string parameter and print it using `println`. To simplify this first example, `greet` won’t take any input parameters; it will just build a function and return it. -This anonymous function takes a `String` input parameter and returns nothing, so it has this type: +Given that statement, you can start building `greet`. You know it’s going to be a method: ```scala -String => Unit +def greet() ``` -Therefore, if you want to write a method that returns this function, first define the method signature: +You also know this method will return a function that (a) takes a `String` parameter and (b) prints that string using `println`. Therefore that function has the type, `String => Unit`: ```scala def greet(): String => Unit = ??? + ---------------- ``` -Now you just need to add in the method body. In this case the method returns that anonymous function, so the complete method looks like this: +Now you just need a method body. You know that the method needs to return a function, and that function takes a `String` and prints it. Therefore, this anonymous function should do: ```scala -// a method that returns a function -def greet(): String => Unit = - (name: String) => println(s"Hello, $name") +(name: String) => println(s"Hello, $name") ``` -Because that method returns a function, you first create your new function: +Now you just return that function from the method: -```scala -val greetFunction = greet() +```tut +// a method that returns a function +def greet(): String => Unit = + (name: String) => println(s"Hello, $name") ``` -When you put that line of code in the REPL, you see that it has the type `String => Unit`, as expected: +Because this method returns a function, you get the function by calling `greet()`. This is a good step to do in the REPL because it verifies the type of the new function: ```` scala> val greetFunction = greet() @@ -434,7 +437,7 @@ val greetFunction: String => Unit = Lambda.... ----------------------------- ```` -Now you can call your new `greetFunction`: +Now you can call `greetFunction`: ```scala greetFunction("Joe") // prints "Hello, Joe" @@ -445,14 +448,14 @@ Congratulations, you just created a method that returns a function, and then exe ### Improving the method -That function would be more useful if you could pass in a greeting, so let’s do that. All you have to do is pass the greeting in as a parameter to the `greet` method, and use it in the string inside `println`: +Our method would be more useful if you could pass in a greeting, so let’s do that. All you have to do is pass the greeting in as a parameter to the `greet` method, and use it in the string inside `println`: -```scala +```tut def greet(theGreeting: String): String => Unit = (name: String) => println(s"$theGreeting, $name") ``` -Now when you call your method, the process is more flexible because you can change the greeting. Again, the first step of creating a function from the method is good to show in the REPL because it shows the resulting type: +Now when you call your method, the process is more flexible because you can change the greeting. This is what it looks like when you create a function from this method: ```` scala> val sayHello = greet("Hello") @@ -460,7 +463,7 @@ val sayHello: String => Unit = Lambda..... ------------------------ ```` -This shows that `sayHello` is a function that takes a `String` input parameter and returns `Unit` (nothing). So now when you give `sayHello` a `String`, it prints the greeting: +The REPL type signature output shows that `sayHello` is a function that takes a `String` input parameter and returns `Unit` (nothing). So now when you give `sayHello` a `String`, it prints the greeting: ```scala sayHello("Joe") // prints "Hello, Joe" @@ -477,24 +480,24 @@ sayHey("Joe") // prints "Hey, Joe" ### A more real-world example -In a more real-world example, a method like this is more useful when it can return one of many possible functions, like a factory that returns custom-built functions. +This technique can be even more useful when your method returns one of many possible functions, like a factory that returns custom-built functions. For instance, imagine that you want to write a method that returns functions that greet people in different languages. We’ll limit this to functions that greet in English or French, depending on a parameter that’s passed into the method. -A first thing you know is that you want to create a method that (a) takes a “desired language” as an input, and (b) returns a function as its result. Furthermore, because that function will print a string that it’s given, you know it has the type `String => Unit`. With that information you can start writing the method signature like this: +A first thing you know is that you want to create a method that (a) takes a “desired language” as an input, and (b) returns a function as its result. Furthermore, because that function prints a string that it’s given, you know it has the type `String => Unit`. With that information you write the method signature: ```scala def createGreetingFunction(desiredLanguage: String): String => Unit = ??? ``` -That’s a good start. Because you know that the possible functions you’ll return take a string and print it, you can write two anonymous functions like this for the English and French languages: +Next, because you know that the possible functions you’ll return take a string and print it, you can write two anonymous functions for the English and French languages: ```scala (name: String) => println(s"Hello, $name") (name: String) => println(s"Bonjour, $name") ``` -Inside a method it might be a little more readable if you give those anonymous functions some names, so let’s write them like this instead: +Inside a method it might be a little more readable if you give those anonymous functions some names, so let’s assign them to two variables: ```scala val englishGreeting = (name: String) => println(s"Hello, $name") @@ -503,7 +506,7 @@ val frenchGreeting = (name: String) => println(s"Bonjour, $name") Now all you need to do is (a) return `englishGreeting` if the `desiredLanguage` is English, and (b) return `frenchGreeting` if the `desiredLanguage` is French. One way to do that is with a `match` expression: -```scala +```tut def createGreetingFunction(desiredLanguage: String): String => Unit = val englishGreeting = (name: String) => println(s"Hello, $name") val frenchGreeting = (name: String) => println(s"Bonjour, $name") @@ -518,7 +521,7 @@ This is how `createGreetingFunction` builds a French-greeting function: ```scala val greetInFrench = createGreetingFunction("french") -greetInFrench("Raphael") // prints "Bonjour, Raphael" +greetInFrench("Jonathan") // prints "Bonjour, Jonathan" ``` And this is how it builds an English-greeting function: @@ -528,20 +531,21 @@ val greetInEnglish = createGreetingFunction("english") greetInEnglish("Joe") // prints "Hello, Joe" ``` -If this all makes sense — congratulations — you’ve just seen how to write methods that return functions. +If you’re comfortable with that code — congratulations — you now know how to write methods that return functions. -## Summary +## Key points -A higher-order function is often defined as a function that takes other functions as input parameters or returns a function as a result. In Scala this is possible because functions are first-class values. +That was a lengthy chapter, so let’s review it. + +A higher-order function is often defined as a function that takes other functions as input parameters or returns a function as its value. In Scala this is possible because functions are first-class values. In previous chapters you saw how to be a *consumer* of higher-order functions, and this chapter showed you how to be a *creator* of higher-order functions. Specifically, you saw: - How to write methods that take functions as input parameters - How to return a function from a method -A beneficial side effect of this chapter is that you saw many examples of how to declare type signatures for functions. The benefits of that are that you’ll use that same syntax to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions like `map`, `filter`, and others. - +A beneficial side effect of this chapter is that you saw many examples of how to declare type signatures for functions. The benefits of that are that you use that same syntax to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions like `map`, `filter`, and others. From 1b816443c60e56c7d0e4e77104c92706e7753cd5 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 5 Nov 2020 10:11:41 -0800 Subject: [PATCH 0201/2265] language tour: correct a claim in the named arguments section --- _tour/named-arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/named-arguments.md b/_tour/named-arguments.md index 3b8159bb99..db54d951e3 100644 --- a/_tour/named-arguments.md +++ b/_tour/named-arguments.md @@ -29,4 +29,4 @@ Notice how the order of named arguments can be rearranged. However, if some argu printName(last = "Smith", "john") // error: positional after named argument ``` -Note that named arguments do not work with calls to Java methods. +Named arguments work with calls to Java methods, but only if the Java library in question was compiled with `-parameters`. From 54d7fc7ca2f0621a402c1655b6dd23d2c5a5ff39 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 6 Nov 2020 18:43:02 +0100 Subject: [PATCH 0202/2265] fixed some typo --- _it/tutorials/scala-for-java-programmers.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/_it/tutorials/scala-for-java-programmers.md b/_it/tutorials/scala-for-java-programmers.md index fa4327bbeb..927f21b72b 100644 --- a/_it/tutorials/scala-for-java-programmers.md +++ b/_it/tutorials/scala-for-java-programmers.md @@ -73,7 +73,7 @@ avrà il nome `HelloWorld.class` e conterrà una classe che può essere direttamente eseguita con il comando `scala`, come mostra la seguente sezione. -### Eseguimo l'esempio +### Eseguiamo l'esempio Una volta compilato il programma può esser facilmente eseguito con il comando scala. L'uso è molto simile al comando java ed accetta le stesse @@ -91,13 +91,13 @@ codice Java. Tutte le classi del package `java.lang` sono importate di default mentre le altre richiedono l’esplicito import. Osserviamo un esempio che lo dimostra. Vogliamo ottenere la data -corrente e formattarla in accordo con la convezione usata in uno +corrente e formattarla in accordo con la convenzione usata in uno specifico paese del mondo, diciamo la Francia. (Altre regioni, come la parte di lingua francese della Svizzera, utilizzano le stesse convenzioni.) Le librerie delle classi Java definiscono potenti classi di utilità come `Date` e `DateFormat`. Poiché Scala interagisce direttamente con Java, non -esistono le classi equivalenti nella libreria delle classi di Scala--possiamo +esistono le classi equivalenti nella libreria delle classi di Scala; possiamo semplicemente importare le classi dei corrispondenti package Java: import java.util.{Date, Locale} @@ -112,7 +112,7 @@ semplicemente importare le classi dei corrispondenti package Java: } } -L’istruzione import di Scala è molto simile all’equivalente in Java +L’istruzione `import` di Scala è molto simile all’equivalente in Java tuttavia, risulta essere più potente. Più classi possono essere importate dallo stesso package includendole in parentesi graffe come nella prima riga di codice precedentemente riportato. Un’altra differenza è evidente @@ -130,7 +130,7 @@ Java che di default contiene la data corrente. Successivamente, definiamo il formato della data usando il metodo statico `getDateInstance` importato precedentemente. Infine, stampiamo la data corrente, formattata secondo la localizzazione scelta, con l’istanza `DateFormat`; quest’ultima linea mostra -un’importante proprietà di Scala.I metodi che prendono un argomento possono +un’importante proprietà di Scala. I metodi che prendono un argomento (ed uno soltanto) possono essere usati con una sintassi non fissa. Questa forma dell’espressione df format now @@ -582,7 +582,7 @@ definendo la classe `Date` come segue: La parte importante qui è la dichiarazione `extends Ord` che segue il nome della classe e dei parametri. Dichiara che la classe `Date` eredita il -codice dal trait `extends Ord`. +codice dal trait `Ord`. Successivamente ridefiniamo il metodo `equals`, ereditato da `Object`, in modo tale che possa confrontare in modo corretto le date confrontando @@ -694,6 +694,6 @@ poiché è stata dichiarata per memorizzare un intero. Questo documento ha fornito una veloce introduzione del linguaggio Scala e presentato alcuni esempi di base. Il lettore interessato può continuare, per -esempio, leggendo il documento *Scala By Example* che contiene esempi molti più +esempio, leggendo il documento [*Scala By Example*](https://docs.scala-lang.org/tour/tour-of-scala.html) che contiene esempi molti più avanzati e consultare al bisogno la documentazione *Scala Language Specification*. From a33a1cbb659e76bb291cdbf0536a3c5bdbfd3176 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 6 Nov 2020 18:46:59 +0100 Subject: [PATCH 0203/2265] fixed some typo --- _it/tutorials/scala-for-java-programmers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_it/tutorials/scala-for-java-programmers.md b/_it/tutorials/scala-for-java-programmers.md index 927f21b72b..5cf8cb4b1c 100644 --- a/_it/tutorials/scala-for-java-programmers.md +++ b/_it/tutorials/scala-for-java-programmers.md @@ -694,6 +694,6 @@ poiché è stata dichiarata per memorizzare un intero. Questo documento ha fornito una veloce introduzione del linguaggio Scala e presentato alcuni esempi di base. Il lettore interessato può continuare, per -esempio, leggendo il documento [*Scala By Example*](https://docs.scala-lang.org/tour/tour-of-scala.html) che contiene esempi molti più +esempio, leggendo il documento [*Tour of Scala*](https://docs.scala-lang.org/tour/tour-of-scala.html) che contiene esempi molti più avanzati e consultare al bisogno la documentazione *Scala Language Specification*. From d989b5d7710391886b0911280864239e50ce3b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Sat, 7 Nov 2020 15:33:13 +0300 Subject: [PATCH 0204/2265] Fix errors in seq.md Mistake in `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "bar")`. Right: List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "quux") --- _ru/overviews/collections-2.13/seqs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ru/overviews/collections-2.13/seqs.md b/_ru/overviews/collections-2.13/seqs.md index e85e6f1eb3..c5557bdd40 100644 --- a/_ru/overviews/collections-2.13/seqs.md +++ b/_ru/overviews/collections-2.13/seqs.md @@ -76,7 +76,7 @@ language: ru | `xs intersect ys` |Операция пересечения на множестве между последовательностей `xs` и `ys`, сохраняющее порядок элементов в `xs`.| | `xs diff ys` |Операция расхождения на множестве между последовательностей `xs` и `ys`, сохраняющее порядок элементов в `xs`.| | `xs.distinct` |Подпоследовательность `xs`, которая не содержит дублирующих друг друга элементов.| -| `xs distinctBy f` |Подпоследовательность `xs`, которая не содержит дублирующего элемента после применения функции преобразования `f`. Например, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "bar")`| +| `xs distinctBy f` |Подпоследовательность `xs`, которая не содержит дублирующего элемента после применения функции преобразования `f`. Например, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "quux")`| У трейта [Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html) есть два дочерних трейта [LinearSeq](https://www.scala-lang.org/api/current/scala/collection/LinearSeq.html), и [IndexedSeq](https://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html). Они не добавляют никаких новых операций, но у каждого из них разные характеристики производительности: у LinearSeq эффективные операции `head` и `tail`, в то время как у IndexedSeq эффективные операции `apply`, `length` и (если мутабельная) `update`. Часто используемые варианты LinearSeq - это `scala.collection.immutable.List` и `scala.collection.immutable.LazyList`. А наиболее часто используемые IndexedSeq - это `scala.Array` и `scala.collection.mutable.ArrayBuffer`. Класс `Vector` представляет собой компромисс между IndexedSeq и LinearSeq. У него эффективные, как обращение по индексу, так и последовательный обход элементов. Поэтому вектора хорошая основа для смешанных моделей доступа, где используются как индексированный, так и последовательный доступ. Позже мы расскажем больше о [векторах](concrete-immutable-collection-classes.html). From f75875d1ea071b4139ed20e65a0f8e5c6fca8108 Mon Sep 17 00:00:00 2001 From: Alvin Alexander Date: Sun, 8 Nov 2020 19:01:47 -0700 Subject: [PATCH 0205/2265] =?UTF-8?q?Initial=20version=20of=20the=20?= =?UTF-8?q?=E2=80=98Functional=20Programming=E2=80=99=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _overviews/overview/functional-programming.md | 563 ++++++++++++++++++ 1 file changed, 563 insertions(+) diff --git a/_overviews/overview/functional-programming.md b/_overviews/overview/functional-programming.md index e69de29bb2..745d35fe1d 100644 --- a/_overviews/overview/functional-programming.md +++ b/_overviews/overview/functional-programming.md @@ -0,0 +1,563 @@ +--- +title: Functional Programming with Scala 3 +description: This section provides an introduction to functional programming in Scala 3. +--- + + +Scala lets you write code in an object-oriented programming (OOP) style, a functional programming (FP) style, and also in a hybrid style — using both approaches in combination. [As Martin Odersky has stated](https://twitter.com/alexelcu/status/996408359514525696), the essence of Scala is a fusion of functional and object-oriented programming in a typed setting: + +- Functions for the logic +- Objects for the modularity + +This chapter assumes that you’re comfortable with OOP and less comfortable with FP, so it provides a gentle introduction to several main functional programming concepts: + +- What is functional programming? +- Immutable values +- Pure functions +- Functions are values +- Functional error handling + + + +## What is functional programming? + +[Wikipedia defines *functional programming*](https://en.wikipedia.org/wiki/Functional_programming) like this: + +>Functional programming is a programming paradigm where programs are constructed by applying and composing functions. It is a declarative programming paradigm in which function definitions are trees of expressions that each return a value, rather than a sequence of imperative statements which change the state of the program. +>In functional programming, functions are treated as first-class citizens, meaning that they can be bound to names (including local identifiers), passed as arguments, and returned from other functions, just as any other data type can. This allows programs to be written in a declarative and composable style, where small functions are combined in a modular manner. + +It can also be helpful to know that experienced functional programmers have a strong desire to see their code as math, that combining pure functions together is like combining a series of algebraic equations. When you write functional code you feel like a mathematician, and once you understand the paradigm, you want to write pure functions that always return *values* — not exceptions or null values — so you can combine (compose) them together to create solutions. The feeling that you’re writing math-like equations (expressions) is the driving desire that leads you to use *only* pure functions and immutable values, because that’s what you use in algebra and other forms of math. + +Functional programming is a large topic, and there’s no simple way to condense the entire topic into one chapter, but hopefully the following section will provide an overview of the main topics, and show some of the tools Scala provides for writing functional code. + + + +## Immutable values + +In pure functional programming, only immutable values are used. In Scala this means: + +- All variables are created as `val` fields +- Only immutable collections classes are used, such as `List`, `Vector`, and the immutable `Map` and `Set` classes + +Using only immutable variables raises an interesting question: If everything is immutable, how does anything ever change? + +When it comes to using collections, one answer is that you don’t mutate an existing collection; instead, you apply a function to an existing collection to create a new collection. This is where higher-order functions like `map` and `filter` come in. + + +For example, imagine that you have a list of names — a `List[String]` — that are all in lowercase, and you want to find all the names that begin with the letter `"j"`, and then you want to capitalize those names. In FP you write this code: + +```tut +val a = List("jane", "jon", "mary", "joe") +val b = a.filter(_.startsWith("j")) + .map(_.capitalize) +``` + +As shown, you don’t mutate the original list `a`. Instead, you apply filtering and transformation functions to `a` to create a new collection, and assign that result to the new immutable variable `b`. + +Similarly, in FP you don’t create classes with mutable `var` constructor parameters. That is, you don’t write this: + +```scala +// don’t do this in FP +class Person(var firstName: String, var lastName: String) + --- --- +``` + +Instead, you typically create `case` classes, whose constructor parameters are `val` by default: + +```scala +case class Person(firstName: String, lastName: String) +``` + +Now you create a `Person` instance as a `val` field: + +```scala +val reginald = Person("Reginald", "Dwight") +``` + +Then, when you need to make a change to the data, you use the `copy` method that comes with a `case` class to “update the data as you make a copy,” like this: + +```scala +val elton = p.copy( + firstName = "Elton", // update the first name + lastName = "John" // update the last name +) +``` + +There are other techniques for working with immutable collections and variables, but hopefully these examples give you a taste of the techniques. + + +>Depending on your needs, you may create enums, traits, or classes instead of `case` classes. See the Data Modeling chapter for more details. + + + + +## Pure functions + + +Another feature that Scala offers to help you write functional code is the ability to write pure functions. In his book, *Functional Programming, Simplified*, Alvin Alexander defines a *pure function* like this: + +- A function’s output depends *only* on its input variables and its internal algorithm +- It doesn’t mutate any hidden state +- It doesn’t have any “back doors”: It doesn’t read data from the outside world (including the console, web services, databases, files, etc.), or write data to the outside world + +As a result of this definition, any time you call a pure function with the same input value(s), you’ll always get the same result. For example, you can call a `double` function an infinite number of times with the input value `2`, and you’ll always get the result `4`. + + +### Examples of pure functions + +Given that definition, as you can imagine, methods like these in the *scala.math._* package are pure functions: + +- `abs` +- `ceil` +- `max` + +These `String` methods are also pure functions: + +- `isEmpty` +- `length` +- `substring` + +Most methods on the Scala collections classes also work as pure functions, including `drop`, `filter`, `map`, and many more. + + +>In Scala, *functions* and *methods* are almost completely interchangeable, so even though we use the common industry term “pure function,” this term can be used to describe both functions and methods. + + +### Examples of impure functions + +Conversely, the following functions are *impure* because they violate the definition. + +The `foreach` method on collections classes is impure because it’s only used for its side effects, such as printing to STDOUT. + +>A great hint that `foreach` is impure is that it’s method signature declares that it returns the type `Unit`. Because it doesn’t return anything, logically the only reason you ever call it is to achieve some side effect. Similarly, *any* method that returns `Unit` is going to be an impure function. + +Date and time related methods like `getDayOfWeek`, `getHour`, and `getMinute` are all impure because their output depends on something other than their input parameters. Their results rely on some form of hidden I/O; *hidden inputs,* in these examples. + +Additionally, methods that interact with the console, files, databases, web services, sensors, etc., are all impure. + +In general, impure functions do one or more of these things: + +- Read hidden inputs, i.e., they access variables and data not explicitly passed into the function as input parameters +- Write hidden outputs +- Mutate the parameters they’re given, or mutate hidden variables, such as fields in their containing class +- Perform some sort of I/O with the outside world + + +### But impure functions are needed ... + +Of course an application isn’t very useful if it can’t read or write to the outside world, so people make this recommendation: + +>Write the core of your application using pure functions, and then write an impure “wrapper” around that core to interact with the outside world. As someone once said, this is like putting a layer of impure icing on top of a pure cake. + +It’s important to note that there are ways to make impure interactions with the outside world feel more pure. For instance, you’ll hear about using an `IO` Monad to deal with input and output. These topics are beyond the scope of this document, so to keep things simple it can help to think that FP applications have a core of pure functions that are wrapped with other functions to interact with the outside world. + + +### Writing pure functions + +**Note**: In this section the common industry term “pure function” is often used to refer to Scala methods. + +To write pure functions in Scala, just write them using Scala’s method syntax (though you can also use Scala’s function syntax, as well). For instance, here’s a pure function that doubles the input value it’s given: + +```scala +def double(i: Int): Int = i * 2 +``` + +If you’re comfortable with recursion, here’s a pure function that calculates the sum of a list of integers: + +```scala +def sum(xs: List[Int]): Int = xs match + case Nil => 0 + case head :: tail => head + sum(tail) +``` + +If you understand that code, you’ll see that it meets the pure function definition. + + +### Key points + +The first key point of this section is the definition of a pure function: + +>A *pure function* is a function that depends only on its declared inputs and its internal algorithm to produce its output. It does not read any other values from “the outside world” — the world outside of the function’s scope — and it doesn’t modify any values in the outside world. + +A second key point is that every real-world application interacts with the outside world. Therefore, a simplified way to think about functional programs is that they consist of a core of pure functions that are wrapped with other functions that interact with the outside world. + + + + +## Functions are values + +While every programming language ever created probably lets you write pure functions, a second important Scala FP feature is that *you can create functions as values*, just like you create `String` and `Int` values. + +This feature has many benefits, the most common of which are (a) you can define methods to accept function parameters, and (b) you can pass functions as parameters into methods. You’ve seen this in multiple places in this Overview, whenever methods like `map` and `filter` are demonstrated: + +```tut +val nums = (1 to 10).toList + +val doubles = nums.map(_ * 2) // double each value +val lessThanFive = nums.filter(_ < 5) // List(1,2,3,4) +``` + +In those examples, anonymous functions are passed into `map` and `filter`. + +>Anonymous functions are also known as *lambdas*. + +In addition to passing anonymous functions into `filter` and `map`, you can also supply them with *methods*: + +```scala +// two methods +def double(i: Int): Int = i * 2 +def underFive(i: Int): Boolean = i < 5 + +// pass those methods into filter and map +val doubles = nums.filter(underFive).map(double) +``` + +This ability to treat methods and functions as values is a powerful feature that functional programming languages provide. + +>Technically, a a function that takes another function as an input parameter is known as a *Higher-Order Function*. (If you like humor, as someone once wrote, that’s like saying that a class that takes an instance of another class as a constructor parameter is a Higher-Order Class.) + + +### Functions, anonymous functions, and methods + +As you saw in those examples, this is an anonymous function: + +```scala +_ * 2 +``` + + +As shown in the higher-order functions discussion, that’s a shorthand version of this syntax: + +```scala +(i: Int) => i * 2 +``` + +Functions like these are called “anonymous” because they don’t have names. If you want to give one a name, just assign it to a variable: + +```scala +val double = (i: Int) => i * 2 +``` + +Now you have a named function, one that’s assigned to a variable. You can use this function just like you use a method: + +```scala +double(2) // 4 +``` + +In most scenarios it doesn’t matter if `double` is a function or a method; Scala lets you treat them the same way. Behind the scenes, the Scala technology that lets you treat methods just like functions is known as [Eta Expansion](TODO:LINK). + +This ability to seamlessly pass functions around as variables is a distinguishing feature of functional programming languages like Scala. And as you’ve seen in the `map` and `filter` examples throughout this Overview, the ability to pass functions into other functions helps you create code that is concise and still readable — *expressive*. + +If you’re not comfortable with the process of passing functions as parameters into other functions, here are a few more examples you can experiment with: + +```tut +List("foo", "bar").map(_.toUpperCase) +List("foo", "bar").map(_.capitalize) +List("adam", "scott").map(_.length) +List(1,2,3,4,5).map(_ * 10) +List(1,2,3,4,5).filter(_ > 2) +List(5,1,3,11,7).takeWhile(_ < 6) +``` + + + + +## Functional error handling + +Functional programming is like writing a series of algebraic equations, and because algebra doesn’t have null values or throw exceptions, you don’t use these features in FP. This brings up an interesting question: In the situations where you might normally use a null value or exception in OOP code, what do you do? + +Scala’s solution is to use constructs like the `Option`/`Some`/`None` classes. This lesson provides an introduction to using these techniques. + +Two notes before we jump in: + +- The `Some` and `None` classes are subclasses of `Option`. +- Instead of repeatedly saying “`Option`/`Some`/`None`,” the following text generally just refers to “`Option`” or “the `Option` classes.” + + +### A first example + +While this first example doesn’t deal with null values, it’s a good way to introduce the `Option` classes, so we’ll start with it. + +Imagine that you want to write a method that makes it easy to convert strings to integer values, and you want an elegant way to handle the exception that’s thrown when your method gets a string like `"Hello"` instead of `"1"`. A first guess at such a method might look like this: + +```tut +def makeInt(s: String): Int = + try + Integer.parseInt(s.trim) + catch + case e: Exception => 0 +``` + +If the conversion works, this method returns the correct `Int` value, but if it fails, the method returns `0`. This might be okay for some purposes, but it’s not really accurate. For instance, the method might have received `"0"`, but it may have also received `"foo"`, `"bar"`, or an infinite number of other strings that will throw an exception. This is a real problem: How do you know when the method really received a `"0"`, or when it received something else? The answer is that with this approach, there’s no way to know. + + +### Using Option/Some/None + +A common solution to this problem in Scala is to use a trio of classes known as `Option`, `Some`, and `None`. The `Some` and `None` classes are subclasses of `Option`, so the solution works like this: + +- You declare that `makeInt` returns an `Option` type +- If `makeInt` receives a string it *can* convert to an `Int`, the answer is wrapped inside a `Some` +- If `makeInt` receives a string it *can’t* convert, it returns a `None` + +Here’s the revised version of `makeInt`: + +```tut +def makeInt(s: String): Option[Int] = + try + Some(Integer.parseInt(s.trim)) + catch + case e: Exception => None +``` + +This code can be read as, “When the given string converts to an integer, return the `Int` wrapped inside a `Some`, such as `Some(1)`. When the string can’t be converted to an integer, an exception is thrown and caught, and the method returns a `None` value.” + +These examples show how `makeInt` works: + +```scala +val a = makeInt("1") // Some(1) +val b = makeInt("one") // None +``` + +As shown, the string `"1"` results in a `Some(1)`, and the string `"one"` results in a `None`. This is the essence of the `Option` approach to error handling. As shown, this technique is used so methods can return *values* instead of *exceptions*. In other situations, `Option` values are also used to replace `null` values. + +Two notes: + +- You’ll find this approach used throughout Scala library classes, and in third-party Scala libraries. +- A key point of this example is that functional methods don’t throw exceptions; instead they return values like `Option`. + + +### Being a consumer of makeInt + +Now imagine that you’re a consumer of the `makeInt` method. You know that it returns a subclass of `Option[Int]`, so the question becomes, how do you work with these return types? + +There are two common answers, depending on your needs: + +- Use a `match` expression +- Use a `for` expression + + +>There are other approaches that can be used. See the Reference documentation for details on those approaches. + + +### Using a `match` expression + +One possible solution is to use a `match` expression: + +```scala +makeInt(x) match + case Some(i) => println(i) + case None => println("That didn’t work.") +``` + +In this example, if `x` can be converted to an `Int`, the first `case` statement is executed; if `x` can’t be converted to an `Int`, the second `case` statement is executed. + + +### Using a `for` expression + +Another common solution is to use a `for` expression — i.e., the `for`/`yield` combination that was shown earlier in this Overview. For instance, imagine that you want to convert three strings to integer values, and then add them together. This is how you do that with a `for` expression and `makeInt`: + +```scala +val y = for + a <- makeInt(stringA) + b <- makeInt(stringB) + c <- makeInt(stringC) +yield + a + b + c +``` + +After that expression runs, `y` will be one of two things: + +- If *all* three strings convert to `Int` values, `y` will be a `Some[Int]`, i.e., an integer wrapped inside a `Some` +- If *any* of the three strings can’t be converted to an `Int`, `y` will be a `None` + +You can test this for yourself: + +```scala +val stringA = "1" +val stringB = "2" +val stringC = "3" + +val y = for { + a <- makeInt(stringA) + b <- makeInt(stringB) + c <- makeInt(stringC) +yield + a + b + c +``` + +With that sample data, the variable `y` will have the value `Some(6)`. + +To see the failure case, change any of those strings to something that won’t convert to an integer. When you do that, you’ll see that `y` is a `None`: + +```scala +y: Option[Int] = None +``` + +### Thinking of Option as a container + +Mental models can often help us understand new situations, so if you’re not familiar with the `Option` classes, one way to think about them is as a *container*: + +- `Some` is a container with one item in it +- `None` is a container, but it has nothing in it + +If you prefer to think of the `Option` classes as being like a box, `None` is like an empty box. It could have had something in it, but it doesn’t. + + + + + +### Using `Option` to replace `null` values + +Getting back to `null` values, a place where a `null` value can silently creep into your code is with a class like this: + +```scala +class Address: + var street1: String, + var street2: String, + var city: String, + var state: String, + var zip: String +``` + +While every address on Earth has a `street1` value, the `street2` value is optional. As a result, the `street2` field can be assigned a `null` value: + +```scala +val santa = new Address( + "1 Main Street", + null, // <-- D’oh! A null value! + "North Pole", + "Alaska", + "99705" +) +``` + +Historically, developers have used blank strings and null values in this situation, both of which are hacks to work around the root problem: `street2` is an *optional* field. In Scala — and other modern languages — the correct solution is to declare up front that `street2` is optional: + +```scala +class Address: + var street1: String, + var street2: Option[String], // an optional value + var city: String, + var state: String, + var zip: String +``` + +Now developers can write more accurate code like this: + +```scala +val santa = new Address( + "1 Main Street", + None, // 'street2' has no value + "North Pole", + "Alaska", + "99705" +) +``` + +or this: + +```scala +val santa = new Address( + "123 Main Street", + Some("Apt. 2B"), + "Talkeetna", + "Alaska", + "99676" +) +``` + + +### `Option` isn’t the only solution + +While this section focuses on the `Option` classes, Scala has a few other alternatives. + +For example, a trio of classes known as `Try`/`Success`/`Failure` work in the same manner, but (a) you primarily use these classes when your code can throw exceptions, and (b) you want to use the `Failure` class because it gives you access to the exception message. For example, these `Try` classes are commonly used when writing methods that interact with files, databases, and internet services, as those functions can easily throw exceptions. + +You can learn more about the `Try` classes and the similar `Either`/`Right`/`Left` classes in the Reference documentation. + + +### A quick review + +This section was long, so let’s give it a quick review: + +- Functional programmers don’t use `null` values +- A main replacement for `null` values is to use the `Option` classes +- Functional methods don’t throw exceptions; instead they return values like `Option`, `Try`, or `Either` +- Common ways to work with `Option` values are `match` and `for` expressions +- Options can be thought of as containers of one item (`Some`) and no items (`None`) +- Options can also be used for optional constructor or method parameters + + + +## Summary + +This chapter provides a high-level introduction to functional programming in Scala. The topics covered are: + +- What is functional programming? +- Immutable values +- Pure functions +- Functions are values +- Functional error handling + +As mentioned, functional programming is a big topic, so all we can do in this Overview is to touch on these introductory concepts. See the Reference documentation for more details. + + + + From 5a3bad7a1fcbabbd9f89766eb21bd4abac973994 Mon Sep 17 00:00:00 2001 From: Juan Miguel Cejuela Date: Wed, 11 Nov 2020 17:57:12 +0100 Subject: [PATCH 0206/2265] minor: fix indentation to be consistent --- _tour/self-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/self-types.md b/_tour/self-types.md index 2f659637f0..e1a80388fb 100644 --- a/_tour/self-types.md +++ b/_tour/self-types.md @@ -27,7 +27,7 @@ trait Tweeter { } class VerifiedTweeter(val username_ : String) extends Tweeter with User { // We mixin User because Tweeter required it - def username = s"real $username_" + def username = s"real $username_" } val realBeyoncé = new VerifiedTweeter("Beyoncé") From 7ea94c24c5f558a269c6d3e353e1eb3cd061e53c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 9 Nov 2020 20:38:03 -0800 Subject: [PATCH 0207/2265] remove postfix ops from style guide Scala 2.13 errors by default, so I don't think the style guide needs to cover this any more --- _style/index.md | 1 - _style/method-invocation.md | 24 ------------------------ 2 files changed, 25 deletions(-) diff --git a/_style/index.md b/_style/index.md index 619c864e5e..279779349f 100644 --- a/_style/index.md +++ b/_style/index.md @@ -55,7 +55,6 @@ This document is intended to outline some basic Scala stylistic guidelines which - [Trivial Conditionals](control-structures.html#trivial-conditionals) - [Method Invocation](method-invocation.html) - [Arity-0](method-invocation.html#arity-0) - - [Postfix Notation](method-invocation.html#postfix-notation) - [Arity-1 (Infix Notation)](method-invocation.html#arity-1-infix-notation) - [Symbolic Methods/Operators](method-invocation.html#symbolic-methodsoperators) - [Higher-Order Functions](method-invocation.html#higher-order-functions) diff --git a/_style/method-invocation.md b/_style/method-invocation.md index 694552afba..861d07dba6 100644 --- a/_style/method-invocation.md +++ b/_style/method-invocation.md @@ -56,30 +56,6 @@ readability and will make it much easier to understand at a glance the most basic operation of any given method. Resist the urge to omit parentheses simply to save two characters! -### Postfix Notation - -Scala allows methods that take no arguments to be invoked using postfix notation: - - // recommended - names.toList - - // discourage - names toList - -This style is unsafe, and should not be used. Since semicolons are -optional, the compiler will attempt to treat it as an infix method -if it can, potentially taking a term from the next line. - - names toList - val answer = 42 // will not compile! - -This may result in unexpected compile errors at best, and happily -compiled faulty code at worst. Although the syntax is used by some -DSLs, it should be considered deprecated, and avoided. - -Since Scala 2.10, using postfix operator notation will result in a -compiler warning. - ## Arity-1 (Infix Notation) Scala has a special punctuation-free syntax for invoking methods of arity-1 From cb6f12d72cd250ddf7898e8658ca0f2c7e41d70c Mon Sep 17 00:00:00 2001 From: Nexus01 <32005836+Nexus01@users.noreply.github.com> Date: Mon, 16 Nov 2020 21:33:12 +0800 Subject: [PATCH 0208/2265] Update generic-classes.md replace `{ elements = x :: elements }` with `: Unit = \n elements = x :: elements` to remove `warning: procedure syntax is deprecated: instead, add `: Unit =` to explicitly declare `push`'s return type` --- _tour/generic-classes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_tour/generic-classes.md b/_tour/generic-classes.md index cf654cc4aa..035a6c0ee5 100644 --- a/_tour/generic-classes.md +++ b/_tour/generic-classes.md @@ -17,7 +17,8 @@ Generic classes take a type as a parameter within square brackets `[]`. One conv ```tut class Stack[A] { private var elements: List[A] = Nil - def push(x: A) { elements = x :: elements } + def push(x: A): Unit = + elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek From e632b050819acf6ec24194b8d903905f3360cad0 Mon Sep 17 00:00:00 2001 From: Vladyslav Pekker Date: Tue, 17 Nov 2020 06:10:25 +0100 Subject: [PATCH 0209/2265] Makes the DevInsideYou YouTube channel description more neutral/objective --- learn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn.md b/learn.md index ddf12bd370..342a4f772a 100644 --- a/learn.md +++ b/learn.md @@ -48,7 +48,7 @@ There are a handful of websites where you can interactively run Scala code in yo [Independent Courseware](https://getscala.com), online self-study or instructor-led Scala and Play courses for a fee. ## DevInsideYou -[DevInsideYou](https://youtube.com/devinsideyou) is a YouTube channel with hundreds of hours of free, high quality Scala content. +[DevInsideYou](https://youtube.com/devinsideyou) is a YouTube channel with hundreds of hours of free Scala content. ## Visual Scala Reference [Visual Scala Reference](https://superruzafa.github.com/visual-scala-reference/), a guide to visually learn about Scala concepts and functions. From a170485778f4566eee1509584f28609d01d3580c Mon Sep 17 00:00:00 2001 From: Wentao Li Date: Tue, 17 Nov 2020 19:37:45 +0800 Subject: [PATCH 0210/2265] Update mixin-class-composition.md typo --- _zh-cn/tour/mixin-class-composition.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/tour/mixin-class-composition.md b/_zh-cn/tour/mixin-class-composition.md index f51354554c..1875e0ec58 100644 --- a/_zh-cn/tour/mixin-class-composition.md +++ b/_zh-cn/tour/mixin-class-composition.md @@ -30,7 +30,7 @@ println(d.message) // I'm an instance of class B println(d.loudMessage) // I'M AN INSTANCE OF CLASS B ``` -类`D`有一个父类`B`和一个混入`C`。一个类只能有一个父类但是可以有多个混入(分别使用关键字`extend`和`with`)。混入和某个父类可能有相同的父类。 +类`D`有一个父类`B`和一个混入`C`。一个类只能有一个父类但是可以有多个混入(分别使用关键字`extends`和`with`)。混入和某个父类可能有相同的父类。 现在,让我们看一个更有趣的例子,其中使用了抽象类: @@ -81,4 +81,4 @@ object StringIteratorTest extends App { } ``` -新的类`RichStringIter`有一个父类`StringIterator`和一个混入`RichIterator`。如果是单一继承,我们将不会达到这样的灵活性。 \ No newline at end of file +新的类`RichStringIter`有一个父类`StringIterator`和一个混入`RichIterator`。如果是单一继承,我们将不会达到这样的灵活性。 From 293eb3639318ef71be10233af7dd96926f386176 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 17 Nov 2020 16:24:43 -0800 Subject: [PATCH 0211/2265] many small improvements to the compiler plugins guide as suggested by Alice Ravier at https://users.scala-lang.org/t/bintray-with-sbt-addcompilerplugin/6784/5 --- _overviews/plugins/index.md | 71 +++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md index 13f1666a2d..91978ab80b 100644 --- a/_overviews/plugins/index.md +++ b/_overviews/plugins/index.md @@ -17,6 +17,13 @@ compiler. It does not go into depth on how to make your plugin actually do something useful, but just shows the basics needed to write a plugin and hook it into the Scala compiler. +## You can read, but you can also watch TV + +The contents of this guide overlaps substantially with Seth Tisue's +talk "Scala Compiler Plugins 101" ([32 minute video](https://www.youtube.com/watch?v=h5NZjuxS5Qo)). +Although the talk is from April 2018, nearly all of the information +in it still applies (as of November 2020). + ## When to write a plugin Plugins let you modify the behavior of the Scala compiler without @@ -68,6 +75,7 @@ All of this is then packaged in a JAR file. To use the plugin, a user adds the JAR file to their compile-time classpath and enables it by invoking `scalac` with `-Xplugin:...`. +(Some build tools provide shortcuts for this; see below.) All of this will be described in more detail below. @@ -147,6 +155,12 @@ aspects of note. desire on the given compilation unit. Usually this involves examining the trees within the unit and doing some transformation on the tree. +- The pattern match inside the body of `apply` shows one way of + detecting certain tree shapes in user code. + (Quasiquotes are another way.) `Apply` denotes a method call, + and `Select` denotes the "selection" of a member, such as `a.b`. + The details of tree processing are out of scope for this document, + but see "Going further", below, for links to further documentation. The `runsAfter` method gives the plugin author control over when the phase is executed. As seen above, it is expected to return a list of @@ -187,6 +201,11 @@ with that file plus your compiled code: cp scalac-plugin.xml classes (cd classes; jar cf ../divbyzero.jar .) +That's how it works with no build tool. If you are using sbt to build +your plugin, then the XML file goes in `src/main/resources`. + +## Using a plugin with scalac + Now you can use your plugin with `scalac` by adding the `-Xplugin:` option: @@ -196,23 +215,44 @@ option: ^ one error found +## Publishing your plugin + When you are happy with how the plugin behaves, you may wish to publish the JAR to a Maven or Ivy repository where it can be resolved -by a build tool. +by a build tool. (For testing purposes, you can also publish it to +your local machine only. In sbt, this is accomplished with +`publishLocal`.) + +In most respects, compiler plugins are ordinary Scala libraries, +so publishing a plugin is like publishing any library. +See the [Library Author Guide]({{site.baseurl}}/overviews/contributors/index.html) +and/or your build tool's documentation on publishing. -sbt, for example, provides an `addCompilerPlugin` method you can +## Using a plugin from sbt + +To make it convenient for end users to use your plugin once it has +been published, sbt provides an `addCompilerPlugin` method you can call in your build definition, e.g.: - addCompilerPlugin("org.divbyzero" % "divbyzero" % "1.0") + addCompilerPlugin("org.divbyzero" %% "divbyzero" % "1.0") + +`addCompilerPlugin` performs multiple actions. It adds the JAR to the +classpath (the compilation classpath only, not the runtime classpath) +via `libraryDependencies`, and it also customizes `scalacOptions` to +enable the plugin using `-Xplugin`. + +For more details, see [Compiler Plugin +Support](https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html) in +the sbt manual. -Note however that `addCompilerPlugin` only adds the JAR to the -compilation classpath; it doesn't actually enable the plugin. To -do that, you must customize `scalacOptions` to include the appropriate -`-Xplugin` call. To shield users from having to know this, it's -relatively common for compiler plugin authors to also write an -accompanying sbt plugin that takes of customizing the classpath and -compiler options appropriately. Then using your plugin only requires -adding an `addSbtPlugin(...)` call to `project/plugins.sbt`. +## Developing compiler plugins with an IDE + +Internally, the use of path-dependent types in the Scala compiler +may confuse some IDEs such as IntelliJ. Correct plugin code may +sometimes be highlighted as erroneous. The IDE is usually still +useful under these circumstances, but remember to take its feedback +with a grain of salt. If the error highlighting is distracting, +the IDE may have a setting where you can disable it. ## Useful compiler options @@ -317,9 +357,12 @@ behavior other than to print out its option. ## Going further For the details on how to make your plugin accomplish some task, you -must consult other documentation on compiler internals (such as the -documentation on [Symbols, Trees, and Types]({{site.baseurl -}}/overviews/reflection/symbols-trees-types.html). +must consult other documentation on compiler internals. Relevant +documents include: + +* [Symbols, Trees, and Types]({{site.baseurl}}/overviews/reflection/symbols-trees-types.html) is the single most important reference about the data structures used inside the compiler. +* [Quasiquotes]({{site.baseurl}}/overviews/quasiquotes/intro.html) are useful for pattern matching on ASTs. + * The [syntax summary]({{site.baseurl}}/overviews/quasiquotes/syntax-summary.html) in the quasiquotes guide is a useful concordance between user-level syntax and AST node types. It's also useful to look at other plugins and to study existing phases within the compiler source code. From 53c67062a6a08da4ea81a4a146439b098874c18c Mon Sep 17 00:00:00 2001 From: Nexus01 Date: Thu, 19 Nov 2020 08:20:47 +0800 Subject: [PATCH 0212/2265] Update generic-classes.md replace `{ elements = x :: elements }` with `: Unit = elements = x :: elements` to remove `warning: procedure syntax is deprecated: instead, add `: Unit =` to explicitly declare `push`'s return type` for various languages --- _ba/tour/generic-classes.md | 3 ++- _es/tour/generic-classes.md | 3 ++- _ja/tour/generic-classes.md | 3 ++- _ko/tour/generic-classes.md | 3 ++- _pl/tour/generic-classes.md | 3 ++- _pt-br/tour/generic-classes.md | 3 ++- _ru/tour/generic-classes.md | 3 ++- _zh-cn/tour/generic-classes.md | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/_ba/tour/generic-classes.md b/_ba/tour/generic-classes.md index c86d8f3f8f..9d85eee471 100644 --- a/_ba/tour/generic-classes.md +++ b/_ba/tour/generic-classes.md @@ -22,7 +22,8 @@ Konvencija je da se koristi slovo `A` kao identifikator tipa, mada se može kori ```tut class Stack[A] { private var elements: List[A] = Nil - def push(x: A) { elements = x :: elements } + def push(x: A): Unit = + elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek diff --git a/_es/tour/generic-classes.md b/_es/tour/generic-classes.md index 60d7626cab..2a1ed5a2ba 100644 --- a/_es/tour/generic-classes.md +++ b/_es/tour/generic-classes.md @@ -16,7 +16,8 @@ A continuación se muestra un ejemplo: class Stack[T] { var elems: List[T] = Nil - def push(x: T) { elems = x :: elems } + def push(x: T): Unit = + elems = x :: elems def top: T = elems.head def pop() { elems = elems.tail } } diff --git a/_ja/tour/generic-classes.md b/_ja/tour/generic-classes.md index 8e04bacd92..338a71b68c 100644 --- a/_ja/tour/generic-classes.md +++ b/_ja/tour/generic-classes.md @@ -21,7 +21,8 @@ assumed-knowledge: classes unified-types ```tut class Stack[A] { private var elements: List[A] = Nil - def push(x: A) { elements = x :: elements } + def push(x: A): Unit = + elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek diff --git a/_ko/tour/generic-classes.md b/_ko/tour/generic-classes.md index e9f0d66e57..724514f338 100644 --- a/_ko/tour/generic-classes.md +++ b/_ko/tour/generic-classes.md @@ -14,7 +14,8 @@ previous-page: extractor-objects class Stack[T] { var elems: List[T] = Nil - def push(x: T) { elems = x :: elems } + def push(x: T): Unit = + elems = x :: elems def top: T = elems.head def pop() { elems = elems.tail } } diff --git a/_pl/tour/generic-classes.md b/_pl/tour/generic-classes.md index 5552d9931f..0db4768aff 100644 --- a/_pl/tour/generic-classes.md +++ b/_pl/tour/generic-classes.md @@ -16,7 +16,8 @@ Poniższy przykład demonstruje zastosowanie parametrów generycznych: ```tut class Stack[T] { var elems: List[T] = Nil - def push(x: T) { elems = x :: elems } + def push(x: T): Unit = + elems = x :: elems def top: T = elems.head def pop() { elems = elems.tail } } diff --git a/_pt-br/tour/generic-classes.md b/_pt-br/tour/generic-classes.md index 82234c4636..253bbf84f2 100644 --- a/_pt-br/tour/generic-classes.md +++ b/_pt-br/tour/generic-classes.md @@ -15,7 +15,8 @@ Aqui temos um exemplo que demonstra isso: ```tut class Stack[T] { var elems: List[T] = Nil - def push(x: T) { elems = x :: elems } + def push(x: T): Unit = + elems = x :: elems def top: T = elems.head def pop() { elems = elems.tail } } diff --git a/_ru/tour/generic-classes.md b/_ru/tour/generic-classes.md index 30587567ca..082fa2bf67 100644 --- a/_ru/tour/generic-classes.md +++ b/_ru/tour/generic-classes.md @@ -20,7 +20,8 @@ assumed-knowledge: classes unified-types ```tut class Stack[A] { private var elements: List[A] = Nil - def push(x: A) { elements = x :: elements } + def push(x: A): Unit = + elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek diff --git a/_zh-cn/tour/generic-classes.md b/_zh-cn/tour/generic-classes.md index 944105906c..93fba67d39 100644 --- a/_zh-cn/tour/generic-classes.md +++ b/_zh-cn/tour/generic-classes.md @@ -17,7 +17,8 @@ previous-page: extractor-objects ```tut class Stack[A] { private var elements: List[A] = Nil - def push(x: A) { elements = x :: elements } + def push(x: A): Unit = + elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek From 80ed395589314f1058911ed4d71a3d9298e9b6dd Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 19 Nov 2020 13:15:11 +0000 Subject: [PATCH 0213/2265] Release Scala 2.13.4 --- _config.yml | 2 +- _overviews/jdk-compatibility/overview.md | 8 ++++---- api/all.md | 12 ++++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/_config.yml b/_config.yml index 6ab7b65d5c..c5df7d0779 100644 --- a/_config.yml +++ b/_config.yml @@ -15,7 +15,7 @@ keywords: - Document - Guide -scala-version: 2.13.3 +scala-version: 2.13.4 scala-212-version: 2.12.12 collections: diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 604bbb18bf..fd20db5a37 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -12,10 +12,10 @@ Sometimes new JVM and JDK (Java Development Kit) versions require us to update S | JDK version | Minimum Scala versions | Recommended Scala versions | |:-----------:|:---------------------------------|:-----------------------------------------------------------| -| 13, 14, 15 | 2.13.2, 2.12.11 | 2.13.3, 2.12.12 | -| 12 | 2.13.1, 2.12.9 | 2.13.3, 2.12.12 | -| 11 | 2.13.0, 2.12.4, 2.11.12 | 2.13.3, 2.12.12, 2.11.12 | -| 8 | 2.13.0, 2.12.0, 2.11.0, 2.10.2 | 2.13.3, 2.12.12, 2.11.12, 2.10.7 | +| 13, 14, 15 | 2.13.2, 2.12.11 | 2.13.4, 2.12.12 | +| 12 | 2.13.1, 2.12.9 | 2.13.4, 2.12.12 | +| 11 | 2.13.0, 2.12.4, 2.11.12 | 2.13.4, 2.12.12, 2.11.12 | +| 8 | 2.13.0, 2.12.0, 2.11.0, 2.10.2 | 2.13.4, 2.12.12, 2.11.12, 2.10.7 | | 6, 7 | 2.11.0, 2.10.0 | 2.11.12, 2.10.7 | Even when a version combination isn't listed as supported, most features may still work. (But Scala 2.12+ definitely doesn't work at all on JDK 6 or 7.) diff --git a/api/all.md b/api/all.md index 0ca4d83e28..0519ad1068 100644 --- a/api/all.md +++ b/api/all.md @@ -6,10 +6,10 @@ includeTOC: true ## Latest releases -* Scala 2.13.3 - * [Library API](https://www.scala-lang.org/api/2.13.3/) - * [Compiler API](https://www.scala-lang.org/api/2.13.3/scala-compiler/scala/) - * [Reflection API](https://www.scala-lang.org/api/2.13.3/scala-reflect/scala/reflect/) +* Scala 2.13.4 + * [Library API](https://www.scala-lang.org/api/2.13.4/) + * [Compiler API](https://www.scala-lang.org/api/2.13.4/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.4/scala-reflect/scala/reflect/) * Scala 2.12.12 * [Library API](https://www.scala-lang.org/api/2.12.12/) * [Compiler API](https://www.scala-lang.org/api/2.12.12/scala-compiler/scala/) @@ -53,6 +53,10 @@ includeTOC: true ## Previous releases +* Scala 2.13.3 + * [Library API](https://www.scala-lang.org/api/2.13.3/) + * [Compiler API](https://www.scala-lang.org/api/2.13.3/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.3/scala-reflect/scala/reflect/) * Scala 2.13.2 * [Library API](https://www.scala-lang.org/api/2.13.2/) * [Compiler API](https://www.scala-lang.org/api/2.13.2/scala-compiler/scala/) From 607dfd4ba61b8ff40999178140acac9cf5981194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Brachth=C3=A4user?= Date: Tue, 24 Nov 2020 18:17:47 +0100 Subject: [PATCH 0214/2265] Add option to present page as Scala 3 docs --- _data/scala3-doc-nav-header.yml | 9 +++++++++ _includes/navbar-inner.html | 20 ++++++++++++++++---- _layouts/inner-page-parent-dropdown.html | 9 +++++++-- _overviews/overview/introduction.md | 14 ++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 _data/scala3-doc-nav-header.yml diff --git a/_data/scala3-doc-nav-header.yml b/_data/scala3-doc-nav-header.yml new file mode 100644 index 0000000000..3eda2e1486 --- /dev/null +++ b/_data/scala3-doc-nav-header.yml @@ -0,0 +1,9 @@ +- title: API + url: "#" + submenu: + - title: Current + url: https://www.scala-lang.org/api/current/ + - title: Nightly + url: https://www.scala-lang.org/files/archive/nightly/2.13.x/api/2.13.x/ + - title: All Versions + url: "/api/all.html" diff --git a/_includes/navbar-inner.html b/_includes/navbar-inner.html index e565a2fd73..b8ca1c77ce 100644 --- a/_includes/navbar-inner.html +++ b/_includes/navbar-inner.html @@ -1,3 +1,9 @@ +{% if page.scala3 %} + {% assign navdata = site.data.scala3-doc-nav-header %} +{% else %} + {% assign navdata = site.data.doc-nav-header %} +{% endif %} + + +{% if page.scala3 %} +
      +{% else %}
      +{% endif %}
diff --git a/_includes/navbar-inner.html b/_includes/navbar-inner.html index b8ca1c77ce..171d00924e 100644 --- a/_includes/navbar-inner.html +++ b/_includes/navbar-inner.html @@ -4,25 +4,7 @@ {% assign navdata = site.data.doc-nav-header %} {% endif %} - +{% include site-header.html %} {% if page.scala3 %}
@@ -32,10 +14,14 @@

- +
diff --git a/_includes/sidebar-toc-singlepage-overview.html b/_includes/sidebar-toc-singlepage-overview.html index bcea6a8911..7b2e68e995 100644 --- a/_includes/sidebar-toc-singlepage-overview.html +++ b/_includes/sidebar-toc-singlepage-overview.html @@ -26,6 +26,6 @@
Contents
{% endif %}

- + diff --git a/_includes/sidebar-toc-style.html b/_includes/sidebar-toc-style.html index eec6ffb078..b82f7974e9 100644 --- a/_includes/sidebar-toc-style.html +++ b/_includes/sidebar-toc-style.html @@ -52,7 +52,7 @@
Contents
{% endif %}
- + {% endif %} diff --git a/_includes/sidebar-toc-tour-overview.html b/_includes/sidebar-toc-tour-overview.html index ed5f756cb2..4150ede379 100644 --- a/_includes/sidebar-toc-tour-overview.html +++ b/_includes/sidebar-toc-tour-overview.html @@ -43,6 +43,6 @@
Contents
{% endif %}
- + diff --git a/_includes/sidebar-toc.html b/_includes/sidebar-toc.html index eec6ffb078..b82f7974e9 100644 --- a/_includes/sidebar-toc.html +++ b/_includes/sidebar-toc.html @@ -52,7 +52,7 @@
Contents
{% endif %}
- + {% endif %} diff --git a/_includes/tutorial-toc.html b/_includes/tutorial-toc.html index 6d34a77d95..8f54cd0a74 100644 --- a/_includes/tutorial-toc.html +++ b/_includes/tutorial-toc.html @@ -24,6 +24,6 @@
Contents
{% include tutorial-tour-list.txt %}
- + diff --git a/_includes/upcoming-training.html b/_includes/upcoming-training.html index 7b205eb794..1609682751 100644 --- a/_includes/upcoming-training.html +++ b/_includes/upcoming-training.html @@ -33,6 +33,6 @@

{{training.title}}

{% endfor %} - \ No newline at end of file + diff --git a/_ja/scala3/contribute-to-docs.md b/_ja/scala3/contribute-to-docs.md index dda4e2433e..69a9a0478b 100644 --- a/_ja/scala3/contribute-to-docs.md +++ b/_ja/scala3/contribute-to-docs.md @@ -30,19 +30,19 @@ Scala 3 の高品質なドキュメンテーションを作るためのいくつ ## Scala 3 Book [Scala 3 Book][scala3-book] は Alvin Alexander 氏 が書いている。 この本は Scala 3 のすべての重要な機能の概説書である。これから Scala を使いはじめる読者を対象にしている。 -- [Sources](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-book) +- [Sources](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-book) - [Issues](https://github.com/scala/docs.scala-lang/issues) ## Macros Tutorial [Macros Tutorial](/scala3/guides/macros)は Nicolas Stucki 氏 が書いている。この本では Scala 3 のマクロとそのベストプラクティスについて詳しく説明している。 -- [Sources](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-macros) +- [Sources](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-macros) - [Issues](https://github.com/scala/docs.scala-lang/issues) ## Migration Guide [Scala 3 Migration Guide](/scala3/guides/migration/compatibility-intro.html) は Scala 2 と Scala 3 の互換性、移行に役立つツールの紹介、そして詳しい移行のガイドを含んだ包括的なドキュメントである。 -- [Source](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-migration) +- [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-migration) - [Issues](https://github.com/scalacenter/docs.scala-lang/issues) diff --git a/_layouts/frontpage.html b/_layouts/frontpage.html index 86a7694ae1..743e27bd83 100644 --- a/_layouts/frontpage.html +++ b/_layouts/frontpage.html @@ -216,7 +216,7 @@

{{event.title}}

{% endfor %} @@ -383,4 +383,4 @@

{{site.data.common.texts.scalaSupportersTitle}}

-{% include footer.html %} \ No newline at end of file +{% include footer.html %} diff --git a/_layouts/sip.html b/_layouts/sip.html index 9537c472fe..3d778db55e 100644 --- a/_layouts/sip.html +++ b/_layouts/sip.html @@ -26,7 +26,7 @@
SIP Contents

- + diff --git a/_layouts/sips.html b/_layouts/sips.html index 2bb7843cf0..de3535a24e 100644 --- a/_layouts/sips.html +++ b/_layouts/sips.html @@ -40,7 +40,7 @@
Writing a SIP
  • Submitting a SIP
  • Tutorial: Writing a SIP
  • - + diff --git a/_overviews/contributors/index.md b/_overviews/contributors/index.md index 0d31996273..c20879ffbd 100644 --- a/_overviews/contributors/index.md +++ b/_overviews/contributors/index.md @@ -742,7 +742,7 @@ Last, add the following job to the “test” stage, in the `.travis.yml` file: This will check that pull requests don’t make changes that are binary incompatible with the previous stable version. -We suggest working with the following Git workflow: the `master` branch always receives pull requests +We suggest working with the following Git workflow: the `main` branch always receives pull requests for the next major version (so, binary compatibility checks are disabled, by setting the `mimaPreviousArtifacts` value to `Set.empty`), and each major version `N` has a corresponding `N.x` branch (e.g., `1.x`, `2.x`, etc.) branch where the binary compatibility checks are enabled. diff --git a/_sips/sip-submission.md b/_sips/sip-submission.md index 1d7d1d0609..e2efb5ec2a 100644 --- a/_sips/sip-submission.md +++ b/_sips/sip-submission.md @@ -76,7 +76,7 @@ a SIP or needs more work. After receiving the green light from the Process Lead, you can write up your idea and submit it as a SIP. -A SIP is a Markdown document written in conformance with the [process template](https://github.com/scala/docs.scala-lang/blob/master/_sips/sip-template.md). +A SIP is a Markdown document written in conformance with the [process template](https://github.com/scala/docs.scala-lang/blob/main/_sips/sip-template.md). It ought to contain a clear specification of the proposed changes. When such changes significantly alter the compiler internals, the author is invited to provide a proof of concept. Delivering a basic implementation can speed up the @@ -323,7 +323,7 @@ Scala compiler. The process to submit is simple: * Fork the Scala documentation repository, [https://github.com/scala/docs.scala-lang](https://github.com/scala/docs.scala-lang). -* Create a new SIP file in the `_sips/sips/`. Use the [S(L)IP template](https://github.com/scala/docs.scala-lang/blob/master/_sips/sip-template.md) +* Create a new SIP file in the `_sips/sips/`. Use the [S(L)IP template](https://github.com/scala/docs.scala-lang/blob/main/_sips/sip-template.md) * Make sure the new file follows the format: `YYYY-MM-dd-{title}.md`. Use the proposal date for `YYYY-MM-dd`. * Use the [Markdown Syntax](https://daringfireball.net/projects/markdown/syntax) to write your SIP. * Follow the instructions in the [README](https://github.com/scala/docs.scala-lang/) to build your SIP locally so you can ensure that it looks correct on the website. diff --git a/_sips/sip-tutorial.md b/_sips/sip-tutorial.md index 2696fd12af..6103c16d94 100644 --- a/_sips/sip-tutorial.md +++ b/_sips/sip-tutorial.md @@ -10,10 +10,10 @@ This tutorial details of how to write a new SIP and adding it to the website. The process to submit is simple: * Fork the [Scala documentation repository](https://github.com/scala/docs.scala-lang) and clone it. -* Create a new SIP file in the `_sips/sips`. Use the [SIP template](https://github.com/scala/docs.scala-lang/blob/master/_sips/sip-template.md) +* Create a new SIP file in the `_sips/sips`. Use the [SIP template](https://github.com/scala/docs.scala-lang/blob/main/_sips/sip-template.md) * Make sure the new file follows the format: `YYYY-MM-dd-{title}.md`. Use the proposal date for `YYYY-MM-dd`. * Use the [Markdown Syntax](https://daringfireball.net/projects/markdown/syntax) to write your SIP. - * Follow the instructions in the [README](https://github.com/scala/docs.scala-lang/blob/master/README.md) to build your SIP locally so you can ensure that it looks correct on the website. + * Follow the instructions in the [README](https://github.com/scala/docs.scala-lang/blob/main/README.md) to build your SIP locally so you can ensure that it looks correct on the website. * Create a link to your SIP in the "pending sips" section of `index.md`. * Commit your changes and push them to your forked repository. * Create a new pull request. This will notify the Scala SIP team. @@ -34,7 +34,7 @@ Use the [Markdown Syntax](https://daringfireball.net/projects/markdown/syntax) t If you would like a starting point, clone the [SIP Template](./sip-template.html) in `_sips/sip-template.md` and use that. -See the [source](https://github.com/scala/docs.scala-lang/blob/master/_sips/sip-template.md) for this document (`sip-tutorial.md`) for how to do syntax highlighting. +See the [source](https://github.com/scala/docs.scala-lang/blob/main/_sips/sip-template.md) for this document (`sip-tutorial.md`) for how to do syntax highlighting. ```scala class Foo @@ -46,6 +46,6 @@ class Foo Testing changes requires installing [Jekyll](https://jekyllrb.com/docs/installation/). Since this site is hosted on github pages, make sure you have [whatever version of Jekyll that github is running](https://help.github.com/articles/using-jekyll-with-pages#troubleshooting). As of the writing of this README, that is version >= 1.0.x. After the installation, you need to start up the local server. The -[README](https://github.com/scala/docs.scala-lang/blob/master/README.md) gives +[README](https://github.com/scala/docs.scala-lang/blob/main/README.md) gives a concise explanation on how to do it. When the server is running, view your changes at [https://localhost:4000/sips](https://localhost:4000/sips). diff --git a/scala3/contribute-to-docs.md b/scala3/contribute-to-docs.md index 25d719a764..91b467766f 100644 --- a/scala3/contribute-to-docs.md +++ b/scala3/contribute-to-docs.md @@ -28,13 +28,13 @@ Typically, each of the different documentation projects contain links (and so do ## Scala 3 Book The [Scala 3 Book][scala3-book] is being written by Alvin Alexander and provides an overview over all the important features of Scala 3. It targets readers, which are new to Scala. -- [Sources](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-book) +- [Sources](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-book) - [Issues](https://github.com/scala/docs.scala-lang/issues) ## Macros Tutorial The [Macros Tutorial](/scala3/guides/macros) is being written by Nicolas Stucki and contains detailed information about macros in Scala 3 and best-practices. -- [Sources](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-macros) +- [Sources](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-macros) - [Issues](https://github.com/scala/docs.scala-lang/issues) ## Migration Guide @@ -42,7 +42,7 @@ The [Scala 3 Migration Guide](/scala3/guides/migration/compatibility-intro.html) contains an comprehensive overview over compatibility between Scala 2 and Scala 3, a tour presenting the migration tools, and detailed migration guides. -- [Source](https://github.com/scala/docs.scala-lang/tree/master/_overviews/scala3-migration) +- [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-migration) - [Issues](https://github.com/scalacenter/docs.scala-lang/issues) ## Scala 3 Language Reference From 3d94c2fb4c6df2b8db2bfda9209c5bd65aab64c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Koz=C5=82owski?= Date: Wed, 2 Jun 2021 19:17:24 +0200 Subject: [PATCH 0681/2265] Update index.md --- _overviews/plugins/index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md index 9e1b2015b7..20b3508cf9 100644 --- a/_overviews/plugins/index.md +++ b/_overviews/plugins/index.md @@ -46,11 +46,10 @@ include: - Plugins that alter Scala's behavior around errors and warnings, such as [silencer](https://github.com/ghik/silencer), [splain](https://github.com/tek/splain) and [clippy](https://scala-clippy.org/). - Plugins that analyze the structure of source code, such as - [Sculpt](https://github.com/lightbend/scala-sculpt) and [acyclic](https://github.com/lihaoyi/acyclic). + [Sculpt](https://github.com/lightbend/scala-sculpt), [acyclic](https://github.com/lihaoyi/acyclic) and [graph-buddy](https://github.com/VirtusLab/graphbuddy). - Plugins that instrument user code to collect information, such as the code coverage tool [scoverage](https://github.com/scoverage/scalac-scoverage-plugin). -- Plugins that add metaprogramming facilities to Scala, - such as [Macro Paradise](https://github.com/scalamacros/paradise), [semanticdb](https://scalameta.org/docs/semanticdb/guide.html). +- Plugins that enable tooling. One such plugin is [semanticdb](https://scalameta.org/docs/semanticdb/guide.html), which enables [scalafix](https://scalacenter.github.io/scalafix/) (a well-known refactoring and linting tool) to do its work. Another one is [Macro Paradise](https://github.com/scalamacros/paradise) (only needed for Scala 2.12). - Plugins that modify existing Scala constructs in user code, such as [better-monadic-for](https://github.com/oleg-py/better-monadic-for) and [better-tostring](https://github.com/polyvariant/better-tostring). - Plugins that add entirely new constructs to Scala by From 619652ef2d82107bdc03acfbb55877abd2fec84d Mon Sep 17 00:00:00 2001 From: nscarcella Date: Thu, 3 Jun 2021 03:37:26 -0300 Subject: [PATCH 0682/2265] Fixed typos (#2049) * Fixed missing `then` keyword * Replaced Any type for Matchable * Adding missing parenthesis * Added short Matchable description --- _overviews/scala3-book/fun-write-map-function.md | 4 ++-- _overviews/scala3-book/methods-most.md | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/_overviews/scala3-book/fun-write-map-function.md b/_overviews/scala3-book/fun-write-map-function.md index 37a0748074..633d9b8fb8 100644 --- a/_overviews/scala3-book/fun-write-map-function.md +++ b/_overviews/scala3-book/fun-write-map-function.md @@ -20,13 +20,13 @@ Given that statement, you start to write the method signature. First, you know that you want to accept a function as a parameter, and that function should transform an `Int` into some generic type `A`, so you write: ```scala -def map(f: (Int) => A +def map(f: (Int) => A) ``` The syntax for using a generic type requires declaring that type symbol before the parameter list, so you add that: ```scala -def map[A](f: (Int) => A +def map[A](f: (Int) => A) ``` Next, you know that `map` should also accept a `List[Int]`: diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index b501b1687b..ac2140a41b 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -233,7 +233,7 @@ Here’s a method named `isTruthy` that implements the Perl definitions of `true ```scala def isTruthy(a: Any) = - if a == 0 || a == "" + if a == 0 || a == "" then false else true @@ -256,13 +256,14 @@ A `match` expression can also be used as the entire method body, and often is. Here’s another version of `isTruthy`, written with a `match` expression : ```scala -def isTruthy(a: Any) = a match +def isTruthy(a: Matchable) = a match case 0 | "" => false case _ => true ``` -This method works just like the previous method that used an `if`/`else` expression. +This method works just like the previous method that used an `if`/`else` expression. We use `Matchable` instead of `Any` as the parameter's type to accept any value that supports pattern matching. +For more details on the `Matchable` trait, see the [Reference documentation][reference_matchable]. ## Controlling visibility in classes @@ -401,3 +402,4 @@ See the [Reference documentation][reference] for more details on these features. [extension]: {% link _overviews/scala3-book/ca-extension-methods.md %} [reference_extension_methods]: {{ site.scala3ref }}/contextual/extension-methods.html [reference]: {{ site.scala3ref }}/overview.html +[reference_matchable]: {{ site.scala3ref }}/other-new-features/matchable.html From 6b2ae553fc0b34e1b6f78b30a81e6892e59b3553 Mon Sep 17 00:00:00 2001 From: SourceCodeBot Date: Thu, 3 Jun 2021 16:54:34 +0200 Subject: [PATCH 0683/2265] docs: add import notice for extension methods (#2042) * docs: add import notice for extension methods * fix: solved review discussions --- .../scala3-book/ca-extension-methods.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/_overviews/scala3-book/ca-extension-methods.md b/_overviews/scala3-book/ca-extension-methods.md index 7c8639e020..b860b4f928 100644 --- a/_overviews/scala3-book/ca-extension-methods.md +++ b/_overviews/scala3-book/ca-extension-methods.md @@ -50,6 +50,25 @@ Then in your code you use `circumference` just as though it was originally defin aCircle.circumference ``` +### Import extension method + +Imagine, that `circumference` is defined in package `lib`, you can import it by + +```scala +import lib.circumference + +aCircle.circumference +``` + +The compiler also support you if the import is missing by showing a detailed compilation error message such as the following: + +```text +value circumference is not a member of Circle, but could be made available as an extension method. + +The following import might fix the problem: + + import lib.circumference +``` ## Discussion From 38c8ef07dd499326b3a5a8660817d2bf02ee7d52 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 12:17:43 +0200 Subject: [PATCH 0684/2265] Fix redirects --- _sips/all.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_sips/all.md b/_sips/all.md index ed26042765..8133c137af 100644 --- a/_sips/all.md +++ b/_sips/all.md @@ -2,8 +2,9 @@ layout: sips title: List of All SIPs -redirect_from: "/sips/sip-list.html" -redirect_from: "/sips/pending/index.html" +redirect_from: + - "/sips/sip-list.html" + - "/sips/pending/index.html" --- From 6b8bc3882609961746ea005ad9fb2fd94f03d027 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 12:23:48 +0200 Subject: [PATCH 0685/2265] Fix redirects --- _tour/named-arguments.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_tour/named-arguments.md b/_tour/named-arguments.md index 3dc7a4a503..af82d72844 100644 --- a/_tour/named-arguments.md +++ b/_tour/named-arguments.md @@ -8,8 +8,9 @@ next-page: traits previous-page: default-parameter-values prerequisite-knowledge: function-syntax -redirect_from: "/tutorials/tour/named-arguments.html" -redirect_from: "/tutorials/tour/named-parameters.html" +redirect_from: + - "/tutorials/tour/named-arguments.html" + - "/tutorials/tour/named-parameters.html" --- When calling methods, you can label the arguments with their parameter names like so: From a480f7581acab3e49b5fa2d4169c76bafa41efc0 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 12:24:22 +0200 Subject: [PATCH 0686/2265] Fix redirects --- _tour/tour-of-scala.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/_tour/tour-of-scala.md b/_tour/tour-of-scala.md index 2f23fdd254..59e4072e3a 100644 --- a/_tour/tour-of-scala.md +++ b/_tour/tour-of-scala.md @@ -7,9 +7,10 @@ num: 1 next-page: basics -redirect_from: "/tutorials/tour/tour-of-scala.html" -redirect_from: "/tutorials/tour/anonymous-function-syntax.html" -redirect_from: "/tutorials/tour/explicitly-typed-self-references.html" +redirect_from: + - "/tutorials/tour/tour-of-scala.html" + - "/tutorials/tour/anonymous-function-syntax.html" + - "/tutorials/tour/explicitly-typed-self-references.html" --- ## Welcome to the tour From 980dc6d1f9e9f53c63413a1c11c82b2bde24f496 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 12:24:49 +0200 Subject: [PATCH 0687/2265] Fix redirects --- _tour/for-comprehensions.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_tour/for-comprehensions.md b/_tour/for-comprehensions.md index 54ed69f0bf..ce9a8849c5 100644 --- a/_tour/for-comprehensions.md +++ b/_tour/for-comprehensions.md @@ -7,8 +7,9 @@ num: 19 next-page: generic-classes previous-page: extractor-objects -redirect_from: "/tutorials/tour/for-comprehensions.html" -redirect_from: "/tutorials/tour/sequence-comprehensions.html" +redirect_from: + - "/tutorials/tour/for-comprehensions.html" + - "/tutorials/tour/sequence-comprehensions.html" --- Scala offers a lightweight notation for expressing *sequence comprehensions*. Comprehensions have the form `for (enumerators) yield e`, where `enumerators` refers to a semicolon-separated list of enumerators. An *enumerator* is either a generator which introduces new variables, or it is a filter. A comprehension evaluates the body `e` for each binding generated by the enumerators and returns a sequence of these values. From f51e92ee1dd4b976b036f83cf73b232df533604e Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 12:25:14 +0200 Subject: [PATCH 0688/2265] Fix redirects --- _tour/abstract-type-members.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_tour/abstract-type-members.md b/_tour/abstract-type-members.md index 8cad19b617..77dedcc386 100644 --- a/_tour/abstract-type-members.md +++ b/_tour/abstract-type-members.md @@ -8,8 +8,9 @@ previous-page: inner-classes topics: abstract type members prerequisite-knowledge: variance, upper-type-bound -redirect_from: "/tutorials/tour/abstract-types.html" -redirect_from: "/tour/abstract-types.html" +redirect_from: + - "/tutorials/tour/abstract-types.html" + - "/tour/abstract-types.html" --- Abstract types, such as traits and abstract classes, can in turn have abstract type members. From 2eee485ffb573391f00861027d85d61b53afc1a5 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 4 Jun 2021 14:39:30 +0200 Subject: [PATCH 0689/2265] Fix redirects --- _overviews/FAQ/index.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index b9eca9a551..0e4b7200ad 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -2,14 +2,15 @@ layout: singlepage-overview title: Scala FAQ permalink: /tutorials/FAQ/index.html -redirect_from: "/tutorials/FAQ/breakout.html" -redirect_from: "/tutorials/FAQ/chaining-implicits.html" -redirect_from: "/tutorials/FAQ/collections.html" -redirect_from: "/tutorials/FAQ/context-bounds.html" -redirect_from: "/tutorials/FAQ/finding-implicits.html" -redirect_from: "/tutorials/FAQ/finding-symbols.html" -redirect_from: "/tutorials/FAQ/stream-view.html" -redirect_from: "/tutorials/FAQ/yield.html" +redirect_from: + - "/tutorials/FAQ/breakout.html" + - "/tutorials/FAQ/chaining-implicits.html" + - "/tutorials/FAQ/collections.html" + - "/tutorials/FAQ/context-bounds.html" + - "/tutorials/FAQ/finding-implicits.html" + - "/tutorials/FAQ/finding-symbols.html" + - "/tutorials/FAQ/stream-view.html" + - "/tutorials/FAQ/yield.html" --- Frequently asked questions, with _brief_ answers and/or links to From c3fd91cc9b2c2148410373ebab177cc85597b30e Mon Sep 17 00:00:00 2001 From: Alessandro Buggin <830963+abuggin@users.noreply.github.com> Date: Thu, 10 Jun 2021 14:21:41 +0100 Subject: [PATCH 0690/2265] Minor typo --- _overviews/scala3-migration/tooling-migration-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/tooling-migration-mode.md b/_overviews/scala3-migration/tooling-migration-mode.md index 045ede947b..b8c2cb0904 100644 --- a/_overviews/scala3-migration/tooling-migration-mode.md +++ b/_overviews/scala3-migration/tooling-migration-mode.md @@ -37,7 +37,7 @@ where possible standard options include: The `-source:3.0-migration` option makes the compiler forgiving on most of the dropped features, printing warnings in place of errors. Each warning is a strong indication that the compiler is even capable of safely rewriting the deprecated pieces of code into their cross-compiling counterparts. -We call this the **Scala 3 migration compialtion**. +We call this the **Scala 3 migration compilation**. ## Automatic rewrites From 262f04216954d5ee7651300c3f8fac0b17199883 Mon Sep 17 00:00:00 2001 From: vincenzobaz Date: Fri, 28 May 2021 10:49:25 +0200 Subject: [PATCH 0691/2265] Use GitHub actions instead of Travis CI --- _overviews/contributors/index.md | 354 ++++++++++++------------------- 1 file changed, 135 insertions(+), 219 deletions(-) diff --git a/_overviews/contributors/index.md b/_overviews/contributors/index.md index 0d31996273..4421211e15 100644 --- a/_overviews/contributors/index.md +++ b/_overviews/contributors/index.md @@ -46,62 +46,47 @@ use the correct sbt version. ## Setup Continuous Integration The first reason for setting up a continuous integration (CI) server is to systematically run tests on pull requests. -Examples of CI servers that are free for open source projects are [Travis CI](https://travis-ci.org), -[Drone](https://drone.io) or [AppVeyor](https://appveyor.com). +Examples of CI servers that are free for open source projects are [GitHub Actions](https://github.com/features/actions), +[Travis CI](https://travis-ci.com), [Drone](https://drone.io) or [AppVeyor](https://appveyor.com). -Our example uses Travis CI. To enable Travis CI on your project, go to [travis-ci.org](https://travis-ci.org/), -sign up using your GitHub account, and enable your project repository. Then, add a `.travis.yml` file to your -repository with the following content: +Our example uses Github Actions. This feature is enabled by default on GitHub repositories. You can verify if that is +the case and enable them in the *Actions* section of the *Settings* tab of the repository. -~~~ yaml -language: scala -~~~ - -Push your changes and check that Travis CI triggers a build for your repository. - -Travis CI tries to guess which build tool your project uses and executes a default command to run the project tests. -For instance, if your repository contains a `build.sbt` file in the root directory, Travis CI executes the -`sbt ++$TRAVIS_SCALA_VERSION test` command, where the `TRAVIS_SCALA_VERSION` variable is, by default, set to an -arbitrary Scala version (`2.12.8`, at the time these lines are written), which could be inconsistent with the -`scalaVersion` defined in your `build.sbt` file. - -To avoid this potential inconsistency, you want to use one Scala version definition as a single source of truth. -For instance, the [sbt-travisci](https://github.com/dwijnand/sbt-travisci) plugin lets you define the Scala version -in the `.travis.yml` file, and then forwards this version to your sbt build definition. Alternatively, you can -override the default command run by Travis CI to use the Scala version defined by the `scalaVersion` settings of -your build. +With Actions enabled, you can create a *workflow definition file*. A **workflow** is an automated procedure, +composed of one or more jobs. A **job** is a set of sequential steps that are executed on the same runner. +A **step** is an individual task that can run commands; a step can be either an *action* or a shell command. +An **action** is the smallest building block of a workflow, it is possible to reuse community actions or to +define new ones. -The latter approach is the one used in this guide. Override the command run by Travis CI by adding the folliwng -lines to your `.travis.yml` file: +To create a workflow, create a *yaml* file in the directory `.github/workflows/` in the repository, for example +`.github/workflows/ci.yml` with the following content: ~~~ yaml +name: Continuous integration +on: push + jobs: - include: - - stage: test - script: sbt test + Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 # Retrieve the content of the repository + - uses: olafurpg/setup-scala@v11 # Set up a jdk and sbt + - name: unit tests # Custom action consisting of a shell command + run: sbt +test ~~~ -Travis CI will now execute the `sbt test` command, which uses the Scala version from the build definition. +This workflow is called *Continuous integration* and it will run every time one or more commits are pushed to +the repository. It contains only one job called *Tests*, which will run on an Ubuntu runner and that is composed +of three actions. `setup-scala` uses the sbt version specified in `project/build.properties` and the Scala +version defined in your `build.sbt`. -Last, an important thing to setup is caching, to avoid the CI server to re-download your project dependencies each -time it runs. For instance, in case you use sbt, you can instruct Travis CI to save the content of the `~/.ivy2/` -and `~/.sbt/` directories across builds by adding the following lines to your `.travis.yml` file: - -~~~ yaml -# These directories are cached at the end of the build -cache: - directories: - - $HOME/.ivy2/cache - - $HOME/.sbt -before_cache: - # Cleanup the cached directories to avoid unnecessary cache updates - - rm -fv $HOME/.ivy2/.sbt.ivy.lock - - find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete - - find $HOME/.sbt -name "*.lock" -print -delete -~~~ +The worfklow above will run at any push to any branch of the repository. You can +specify the branch or add more triggers such as pull requests, releases, tags or +schedules. More information about workflow triggers is available [here](https://docs.github.com/en/actions/reference/events-that-trigger-workflows). +while the `setup-scala` action is hosted [in this repository](https://github.com/olafurpg/setup-scala). For reference, here is our complete -[.travis.yml example file](https://github.com/scalacenter/library-example/blob/master/.travis.yml). +[workflow example file](https://github.com/scalacenter/library-example/blob/master/.github/.workflows/ci.yml). ## Publish a Release @@ -125,7 +110,7 @@ sign the binaries. ### Create a Sonatype Account and Project Follow the instructions given on the [OSSRH Guide](https://central.sonatype.org/pages/ossrh-guide.html#initial-setup) -to create a new Sonatype account (unless you already have one) and to +to create a new Sonatype account (unless you already have one) and to [create a new project ticket](https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134). This latter step is where you define the `groupId` that you will release to. You can use a domain name that you already own, otherwise a common practice is to use `io.github.(username)` (where `(username)` is replaced with your GitHub @@ -143,7 +128,7 @@ This step has to be performed only once per person. ### Setup Your Project -In case you use sbt, we recommend using the [sbt-sonatype](https://github.com/xerial/sbt-sonatype) +In case you use sbt, we recommend using the [sbt-sonatype](https://github.com/xerial/sbt-sonatype) and [sbt-pgp](https://www.scala-sbt.org/sbt-pgp/) plugins to publish your artifacts. Add the following dependencies to your `project/plugins.sbt` file: @@ -201,7 +186,7 @@ And make sure your build does **not** define the `version` setting. With this setup, the process for cutting a release is the following. Create a Git tag whose name begins with a lowercase `v` followed by the version number: - + ~~~ bash $ git tag v0.1.0 ~~~ @@ -236,9 +221,8 @@ Continuous publication addresses these issues by delegating the publication proc follows: any contributor with write access to the repository can cut a release by pushing a Git tag, the CI server first checks that the tests pass and then runs the publication commands. -The remaining sections show how to setup Travis CI for continuous publication on Sonatype. You can find instructions -for other CI servers and repositories in the [sbt-release-early](https://github.com/scalacenter/sbt-release-early) -plugin documentation. +The remaining sections show how to setup GitHub Actions for continuous publication on Sonatype. You can find instructions +for Travis CI in the [sbt-ci-release](https://github.com/olafurpg/sbt-ci-release) plugin documentation. ### Setup the CI Server @@ -247,28 +231,14 @@ it is possible to securely give this information by using the secret management #### Export Your Sonatype Account Credentials -The `SONATYPE_USERNAME` and `SONATYPE_PASSWORD` environment variables are recognized by the `sbt-sonatype` -plugin, as documented [here](https://github.com/xerial/sbt-sonatype#homesbtsbt-version-013-or-10sonatypesbt-1). +Create two [GitHub Encrypted secrets](https://docs.github.com/en/actions/reference/encrypted-secrets) +for your Sonatype account credentials: `SONATYPE_USERNAME` and `SONATYPE_PASSWORD`. +To do so, go to the *Settings* tab of the repository and select *Secrets* on the left panel. +You can then use the button *New repository secret* to open the secret creation menu where you will enter +the name of the secret and its content. -With Travis CI, you will have to install the [Travis CLI](https://github.com/travis-ci/travis.rb#installation). - -Then, run the following commands from your project root directory to add your Sonatype credentials as -environment variables to your `.travis.yml` file in an encrypted form: - -~~~ bash -$ travis encrypt SONATYPE_USERNAME="(Sonatype user name)" --add -$ travis encrypt SONATYPE_PASSWORD="(Sonatype password)" --add -~~~ - -(Put your actual user name and password in place of `(Sonatype user name)` and `(Sonatype password)`) - -The `--add` option updates your `.travis.yml` file with entries like the following: - -~~~ yaml -env: - global: - - secure: "dllL1w+pZT6yTBYwy5hX07t8r0JL5Cqer6YgYnXJ+q3OhSGUs7ul2fDUiqVxGIgUpTij1cGwBmoJOTbRk2V/be4+3Ua4ZNrAxjNF2ehqUcV5KdC3ufTTTXX0ZoL9MqEIb+GKzKtPqbzR4uly/5q5NbV7J1GeZRhummnx87POl6yH4kmXTpahig7vvnwN5dLanMshRb2Z8tO8kF4SnC31QuNBDQLnS89PEajHQu+LRAJloYvcikm+NeUj79m64CYg9JZdrHvZpIYKOMY1twT+lYoerqzG+asiNE1WrDs/We1RFVgcrKLpEThcvuIxuuPKhu24+0KteAX+7z/ulT0lndyBRfuuDjHV844LrNbjhnTB64V1uF7aEdaEZRLTsFQnFZqzpoqYqxzgfow9LN/kU5CMJX1R4wwf3YgR1VC9ZfjZnu0Pbt24g48I+72ZDNk3oRZoPsN9AtovwdZcg7TgU/iPcHNKSNhEZRP6ryhv/9aX3URLkfhnDaJmTXAnC3YCYt5cGo0FBUHARA+AHcas14Dx95bFSbH7EBivb2LiDmi44goRCWR4p+vNSBJ6Ak1NZz/+paai0pXDG6S/VdqwGSmmfjn7m9H3L5c8X5xNich9qtZbWz0fj2baZGq/doA8KE91JCzX11p/9fKNzbVivQZdsw3C3ZWDjkMZM+hl++0=" -~~~ +Repository Secrets allow us to safely store confidential information and to expose +it to Actions workflows without the risk of committing them to git history. #### Export Your PGP Key Pair @@ -285,72 +255,65 @@ uid Julien Richard-Foy In my case, I have one key pair, whose ID is `BE614499`. -Export your public and private keys into files, in a `ci` directory: - -~~~ bash -$ mkdir ci -$ gpg -a --export (key ID) > ci/pubring.asc -$ gpg -a --export-secret-keys (key ID) > ci/secring.asc -~~~ +Then: + + 1. Create a new Secret containing the passphrase of your PGP key named `PGP_PASSPHRASE`. + 2. Create a new Secret containing the base64 encoded secret of your private key, which you can obtain + by running: +``` +# macOS +gpg --armor --export-secret-keys $LONG_ID | base64 +# Ubuntu (assuming GNU base64) +gpg --armor --export-secret-keys $LONG_ID | base64 -w0 +# Arch +gpg --armor --export-secret-keys $LONG_ID | base64 | sed -z 's;\n;;g' +# FreeBSD (assuming BSD base64) +gpg --armor --export-secret-keys $LONG_ID | base64 +# Windows +gpg --armor --export-secret-keys %LONG_ID% | openssl base64 +``` + 3. Publish your public key signature to a public server, for example [http://keyserver.ubuntu.com:11371](http://keyserver.ubuntu.com:11371/). + You can obtain the signature by running: +``` +# macOS and linux +gpg --armor --export $LONG_ID +# Windows +gpg --armor --export %LONG_ID% +``` (Replace `(key ID)` with **your** key ID) -Add the `ci/pubring.asc` file (which contains your public key) to your repository. The `secring.asc` file -(which contains your private key) should **not** be added as it is to the repository, so make sure it will -be ignored by Git by adding it to the `.gitignore` file: - -~~~ -ci/secring.asc -~~~ - -Encrypt it with the `travis` tool: - -~~~ bash -$ travis encrypt-file ci/secring.asc ci/secring.asc.enc --add -~~~ - -As advised in the command output, make sure to add the `secring.asc.enc` to the git repository. - -The `--add` option above adds a line like the following to your `.travis.yml` file: - -~~~ diff -before_install: - - openssl aes-256-cbc -K $encrypted_602f530300eb_key -iv $encrypted_602f530300eb_iv -in ci/secring.asc.enc -out ci/secring.asc -d -~~~ - -Finally, add export your PGP passphrase to the `.travis.yml` file: - -~~~ -$ travis encrypt PGP_PASSPHRASE="(your passphrase)" --add -~~~ - -(Replace `(your passphrase)` with your actual passphrase) #### Publish From the CI Server -On Travis CI, you can define a -[conditional stage](https://docs.travis-ci.com/user/build-stages/#specifying-stage-order-and-conditions) -publishing the library when a tag is pushed: +On GitHub Actions, you can define a workflow to publish the library when a tag is pushed: ~~~ yaml -jobs: - include: - - stage: test - script: sbt test - - stage: deploy - if: tag =~ ^v - script: sbt publishSigned sonatypeRelease -~~~ +# .github/workflows/release.yml +name: Continuous publication +on: + push: + branches: ['**'] + tags: [v*] -The last step is to tell your build definition how to retrieve the PGP passphrase from the `PGP_PASSPHRASE` -environment variable and to use the `pubring.asc` and `secring.asc` files as the PGP key pair. -Include the following settings in your `build.sbt` file: - -~~~ scala -pgpPublicRing := file("ci/pubring.asc") -pgpSecretRing := file("ci/secring.asc") -pgpPassphrase := sys.env.get("PGP_PASSPHRASE").map(_.toArray) -~~~ +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # fetch all tags, required for sbt-dynver + - uses: olafurpg/setup-scala@v11 + - run: sbt ci-release + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} +~~~ + +The `env` statement exposes the secrets you defined earlier to the publication process through +environment variables. ### Cut a Release @@ -374,19 +337,7 @@ scalaVersion := crossScalaVersions.value.head ~~~ The second line makes sbt use by default the first Scala version of the `crossScalaVersions`. - -Modify the CI jobs to use all the Scala versions of your build definition by using the `+` prefix, -when appropriate: - -~~~ yaml -jobs: - include: - - stage: test - script: sbt +test - - stage: deploy - if: tag =~ ^v - script: sbt +publishSigned sonatypeRelease -~~~ +The CI job will use all the Scala versions of your build definition. ## Publish Online Documentation @@ -589,78 +540,28 @@ can browse it at [https://scalacenter.github.io/library-example/](https://scalac ### Continuous Publication -You need to grant the CI job write access to the Git repository hosting the documentation. This can be achieved -by creating an SSH key that the CI job can use to push the website to GitHub. - -Create an SSH key: +You can extend `.github/workflows/release.yml` to automatically publish documentation to GitHub pages. +To do so, add another job: -~~~ bash -$ ssh-keygen -t rsa -b 4096 -C "sbt-site@travis" -f ci/travis-key -~~~ - -Make sure to **not** define a passphrase (just leave it empty and press enter), and to add the private -key (the `ci/travis-key` file) to your `.gitignore`: - -~~~ -ci/secring.asc -ci/travis-key -~~~ +```yml +# .github/workflows/release.yml +name: Continuous publication -Add the public key, `ci/travis-key.pub`, in the Deploy Keys section of your GitHub project’s settings page: - -![](/resources/images/travis-publishing-key.png) - -Make sure you “allow write access” by checking the box. - -The private key has to be added to the repository, like we did with the PGP private key. Unfortunately, due -to a limitation of Travis CI, you can not add several encrypted files. The -[workaround](https://docs.travis-ci.com/user/encrypting-files/#encrypting-multiple-files) consists in -creating an archive containing all the files to encrypt. In your case, you want to encrypt the PGP -key and the SSH key into a single `ci/secrets.tar` file: - -~~~ bash -$ tar cvf ci/secrets.tar ci/secring.asc ci/travis-key -$ travis encrypt-file ci/secrets.tar ci/secrets.tar.enc --add -~~~ - -Make sure to add the `ci/secrets.tar` file to your `.gitignore`: - -~~~ -ci/secring.asc -ci/travis-key -ci/secrets.tar -~~~ - -Finally, update the `.travis.yml` file to unpack the archive and push the documentation website -on releases: - -~~~ yaml jobs: - include: - - stage: test - # Run tests for all Scala versions - script: sbt +test - name: "Tests" - # Check that the documentation can be built - - script: sbt makeSite - name: "Documentation" - - - stage: deploy - if: tag =~ ^v - script: - # decrypt PGP secret key and GitHub SSH key - - openssl aes-256-cbc -K $encrypted_602f530300eb_key -iv $encrypted_602f530300eb_iv -in ci/secrets.tar.enc -out ci/secrets.tar -d - - tar xvf ci/secrets.tar - # load the key in the ssh-agent - - chmod 600 ci/travis-key - - eval "$(ssh-agent -s)" - - ssh-add ci/travis-key - # perform deployment - - sbt makeSite +publishSigned sonatypeRelease ghpagesPushSite -~~~ - -(Replace the `$encrypted_602f530300eb_key` and `$encrypted_602f530300eb_iv` variables with the ones produced by the -`travis encrypt-file` command) + release: # The release job is not changed, you can find it above + publishSite: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: olafurpg/setup-scala@v11 + - name: Generate site + run: sbt makeSite + - uses: JamesIves/github-pages-deploy-action@4.1.3 + with: + branch: gh-pages + folder: target/site + +``` As usual, cut a release by pushing a Git tag. The CI server will run the tests, publish the binaries and update the online documentation. @@ -699,14 +600,19 @@ addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1") In the `CONTRIBUTING.md` file, mention that you use that code formatter and encourage users to use the “format on save” feature of their editor. -In your `.travis.yml` file, add a first stage checking that the code has been properly formatted: +In your `.github/workflows/ci.yml` file, add a step checking that the code has been properly formatted: ~~~ yaml +# .github/workflows/ci.yml +# The three periods `...` indicate the parts of file that do not change +# from the snippets above and they are omitted for brevity jobs: - include: - - - stage: style - script: sbt scalafmtCheck + ci: + # ... + steps: + # ... + - name: Code style + run: sbt scalafmtCheck ~~~ ## Evolve @@ -732,11 +638,21 @@ Configure it as follow, in `build.sbt`: mimaPreviousArtifacts := previousStableVersion.value.map(organization.value %% name.value % _).toSet ~~~ -Last, add the following job to the “test” stage, in the `.travis.yml` file: +Last, add the following step to the job `ci` of the `Continuous integration` workflow, in the `.github/workflows/ci.yml` file: ~~~ yaml - - script: sbt mimaReportBinaryIssues - name: "Binary compatibility" +# .github/workflows/ci.yml +# The three periods `...` indicate the parts of file that do not change +# from the snippets above and they are omitted for brevity + +# ... +jobs: + ci: + # ... + steps: + # ... + - name: Binary compatibility + run: sbt mimaReportBinaryIssues ~~~ This will check that pull requests don’t make changes that are binary incompatible with the From 797f0f77b1f1b3276c6d281718c1aefaa40ffcc3 Mon Sep 17 00:00:00 2001 From: vincenzobaz Date: Wed, 9 Jun 2021 16:22:36 +0200 Subject: [PATCH 0692/2265] t# This is a combination of 3 commits. Drop Scala 2.11 --- _overviews/contributors/index.md | 41 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/_overviews/contributors/index.md b/_overviews/contributors/index.md index 4421211e15..1c94648972 100644 --- a/_overviews/contributors/index.md +++ b/_overviews/contributors/index.md @@ -50,7 +50,9 @@ Examples of CI servers that are free for open source projects are [GitHub Action [Travis CI](https://travis-ci.com), [Drone](https://drone.io) or [AppVeyor](https://appveyor.com). Our example uses Github Actions. This feature is enabled by default on GitHub repositories. You can verify if that is -the case and enable them in the *Actions* section of the *Settings* tab of the repository. +the case in the *Actions* section of the *Settings* tab of the repository. +If *Disable all actions* is checked, then Actions are not enabled and you can activate them +by selecting *Allow all actions*, *Allow local actions only* or *Allow select actions*. With Actions enabled, you can create a *workflow definition file*. A **workflow** is an automated procedure, composed of one or more jobs. A **job** is a set of sequential steps that are executed on the same runner. @@ -66,7 +68,7 @@ name: Continuous integration on: push jobs: - Tests: + ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Retrieve the content of the repository @@ -75,18 +77,23 @@ jobs: run: sbt +test ~~~ -This workflow is called *Continuous integration* and it will run every time one or more commits are pushed to -the repository. It contains only one job called *Tests*, which will run on an Ubuntu runner and that is composed -of three actions. `setup-scala` uses the sbt version specified in `project/build.properties` and the Scala -version defined in your `build.sbt`. +This workflow is called *Continuous integration* and it will run every time one +or more commits are pushed to the repository. It contains only one job called +*ci*, which will run on an Ubuntu runner and that is composed of three +actions. The action `setup-scala` installs the sbt launcher in the runner. Then +the job runs `sbt +test`, which loads the sbt version specified in +`project/build.properties`, and runs the project tests using the Scala version +defined in the file `build.sbt`. -The worfklow above will run at any push to any branch of the repository. You can -specify the branch or add more triggers such as pull requests, releases, tags or -schedules. More information about workflow triggers is available [here](https://docs.github.com/en/actions/reference/events-that-trigger-workflows). -while the `setup-scala` action is hosted [in this repository](https://github.com/olafurpg/setup-scala). +The workflow above will run at any push to any branch of the repository. You +can specify the branch or add more triggers such as pull requests, releases, +tags or schedules. More information about workflow triggers is available +[here](https://docs.github.com/en/actions/reference/events-that-trigger-workflows). +while the `setup-scala` action is hosted [in this +repository](https://github.com/olafurpg/setup-scala). -For reference, here is our complete -[workflow example file](https://github.com/scalacenter/library-example/blob/master/.github/.workflows/ci.yml). +For reference, here is our complete [workflow example +file](https://github.com/scalacenter/library-example/blob/master/.github/.workflows/ci.yml). ## Publish a Release @@ -156,7 +163,7 @@ import xerial.sbt.Sonatype._ sonatypeProjectHosting := Some(GitHubHosting("scalacenter", "library-example", "julien.richard-foy@epfl.ch")) // publish to the sonatype repository -publishTo := sonatypePublishTo.value +publishTo := sonatypePublishToBundle.value ~~~ Put your Sonatype credentials in a `$HOME/.sbt/1.0/sonatype.sbt` file: @@ -289,7 +296,7 @@ gpg --armor --export %LONG_ID% On GitHub Actions, you can define a workflow to publish the library when a tag is pushed: ~~~ yaml -# .github/workflows/release.yml +# .github/workflows/publish.yml name: Continuous publication on: push: @@ -332,7 +339,7 @@ If you have written a library, you probably want it to be usable from several Sc Define the versions you want to support in the `crossScalaVersions` setting, in your `build.sbt` file: ~~~ scala -crossScalaVersions := Seq("2.12.8", "2.11.12") +crossScalaVersions := Seq("2.13.6", "2.12.8") scalaVersion := crossScalaVersions.value.head ~~~ @@ -540,11 +547,11 @@ can browse it at [https://scalacenter.github.io/library-example/](https://scalac ### Continuous Publication -You can extend `.github/workflows/release.yml` to automatically publish documentation to GitHub pages. +You can extend `.github/workflows/publish.yml` to automatically publish documentation to GitHub pages. To do so, add another job: ```yml -# .github/workflows/release.yml +# .github/workflows/publish.yml name: Continuous publication jobs: From 5c24940560a5107139bf93364e562b428a7257a4 Mon Sep 17 00:00:00 2001 From: vincenzobaz Date: Fri, 11 Jun 2021 11:36:15 +0200 Subject: [PATCH 0693/2265] Update dependencies --- _overviews/contributors/index.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/_overviews/contributors/index.md b/_overviews/contributors/index.md index 1c94648972..76eb540b80 100644 --- a/_overviews/contributors/index.md +++ b/_overviews/contributors/index.md @@ -72,7 +72,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Retrieve the content of the repository - - uses: olafurpg/setup-scala@v11 # Set up a jdk and sbt + - uses: olafurpg/setup-scala@v12 # Set up a jdk and sbt - name: unit tests # Custom action consisting of a shell command run: sbt +test ~~~ @@ -140,8 +140,8 @@ and [sbt-pgp](https://www.scala-sbt.org/sbt-pgp/) plugins to publish your artifa dependencies to your `project/plugins.sbt` file: ~~~ scala -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.4") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.1.1") ~~~ And make sure your build fulfills the [Sonatype requirements](https://central.sonatype.org/publish/requirements) @@ -183,7 +183,7 @@ Last, we recommend using the [sbt-dynver](https://github.com/dwijnand/sbt-dynver of your releases. Add the following dependency to your `project/plugins.sbt` file: ~~~ scala -addSbtPlugin("com.dwijnand" % "sbt-dynver" % "3.1.0") +addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") ~~~ And make sure your build does **not** define the `version` setting. @@ -310,7 +310,7 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 # fetch all tags, required for sbt-dynver - - uses: olafurpg/setup-scala@v11 + - uses: olafurpg/setup-scala@v12 - run: sbt ci-release env: PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} @@ -339,7 +339,7 @@ If you have written a library, you probably want it to be usable from several Sc Define the versions you want to support in the `crossScalaVersions` setting, in your `build.sbt` file: ~~~ scala -crossScalaVersions := Seq("2.13.6", "2.12.8") +crossScalaVersions := Seq("2.13.6", "2.12.14") scalaVersion := crossScalaVersions.value.head ~~~ @@ -372,8 +372,8 @@ most other documentation generators, which are based on Ruby, Node.js or Python) To install Paradox and sbt-site, add the following lines to your `project/plugins.sbt` file: ~~~ scala -addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.2") -addSbtPlugin("com.lightbend.paradox" % "sbt-paradox" % "0.4.4") +addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1") +addSbtPlugin("com.lightbend.paradox" % "sbt-paradox" % "0.9.2") ~~~ And then add the following configuration to your `build.sbt` file: @@ -560,7 +560,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v11 + - uses: olafurpg/setup-scala@v12 - name: Generate site run: sbt makeSite - uses: JamesIves/github-pages-deploy-action@4.1.3 @@ -601,7 +601,7 @@ For instance, to use [scalafmt](https://scalameta.org/scalafmt/), add the follow file: ~~~ scala -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") ~~~ In the `CONTRIBUTING.md` file, mention that you use that code formatter and encourage users to use the “format @@ -636,7 +636,7 @@ break this versioning policy. Add the `sbt-mima-plugin` to your build with the f `project/plugins.sbt` file: ~~~ scala -addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.3.0") +addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.9.2") ~~~ Configure it as follow, in `build.sbt`: From f0ee521a5c99065fc84ddb3cd7ed84af9706d12f Mon Sep 17 00:00:00 2001 From: "Lan, Jian" <45252210+ShapelessCat@users.noreply.github.com> Date: Sat, 12 Jun 2021 01:22:07 -0700 Subject: [PATCH 0694/2265] Fix why-scala-3.md The second `LinearSeq` of the clause "traits like `LinearSeq` and `LinearSeq`" should be another trait. --- _overviews/scala3-book/why-scala-3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/why-scala-3.md b/_overviews/scala3-book/why-scala-3.md index 1c23d1e7f0..e5f317f9f3 100644 --- a/_overviews/scala3-book/why-scala-3.md +++ b/_overviews/scala3-book/why-scala-3.md @@ -45,7 +45,7 @@ For instance, a `List` is defined as a class---technically it’s an abstract cl val x = List(1, 2, 3) ``` -However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including an abstract class named `AbstractSeq`, traits like `LinearSeq` and `LinearSeq`, and more. +However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including an abstract class named `AbstractSeq`, traits like `LinearSeq` and `LinearSeqOps`, and more. Those types are similarly composed of other small, modular units of code. In addition to building a type like `List` from a series of modular traits, the `List` API also consists of dozens of other methods, many of which are higher-order functions: From 273a57fd4fa472fc3248a1a26703daeaa593ced4 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 9 Jun 2021 18:15:48 +0200 Subject: [PATCH 0695/2265] Suggestions in the Scala book MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’ve reviewed the chapters Methods, Functions, and Packaging and Imports. --- .../scala3-book/fun-anonymous-functions.md | 4 +- _overviews/scala3-book/fun-hofs.md | 32 ++++++------ .../scala3-book/fun-write-map-function.md | 4 +- _overviews/scala3-book/methods-intro.md | 2 +- .../scala3-book/methods-main-methods.md | 4 +- _overviews/scala3-book/methods-most.md | 25 ++++----- _overviews/scala3-book/packaging-imports.md | 51 +++++++++++-------- 7 files changed, 65 insertions(+), 57 deletions(-) diff --git a/_overviews/scala3-book/fun-anonymous-functions.md b/_overviews/scala3-book/fun-anonymous-functions.md index c771c1458c..39d87da216 100644 --- a/_overviews/scala3-book/fun-anonymous-functions.md +++ b/_overviews/scala3-book/fun-anonymous-functions.md @@ -116,7 +116,7 @@ In other examples, you can simplify your anonymous functions further. For instance, beginning with the most explicit form, you can print each element in `ints` using this anonymous function with the `List` class `foreach` method: ```scala -ints.foreach((i:Int) => println(i)) +ints.foreach((i: Int) => println(i)) ``` As before, the `Int` declaration isn’t required, and because there’s only one argument, the parentheses around `i` aren’t needed: @@ -131,7 +131,7 @@ Because `i` is used only once in the body of the function, the expression can be ints.foreach(println(_)) ``` -Finally, if an anonymous function consists of one statement that takes a single argument, you don’t need to explicitly name and specify the argument, so the statement can finally be reduced to this: +Finally, if an anonymous function consists of one method call that takes a single argument, you don’t need to explicitly name and specify the argument, so you can finally write only the name of the method (here, `println`): ```scala ints.foreach(println) diff --git a/_overviews/scala3-book/fun-hofs.md b/_overviews/scala3-book/fun-hofs.md index c8d93c46ef..0985c38ea2 100644 --- a/_overviews/scala3-book/fun-hofs.md +++ b/_overviews/scala3-book/fun-hofs.md @@ -37,7 +37,7 @@ As a beneficial side effect of this discussion, once you’re comfortable with t To understand how higher-order functions work, it helps to dig into an example. For instance, you can understand the type of functions `filter` accepts by looking at its Scaladoc. -Here’s the `filter` definition in the `List` class: +Here’s the `filter` definition in the `List[A]` class: ```scala def filter(p: (A) => Boolean): List[A] @@ -102,7 +102,7 @@ Here’s how this works: It’s just like naming a `String` parameter `s` or an `Int` parameter `i`. - The type signature of `f` specifies the *type* of the functions this method will accept. - The `()` portion of `f`’s signature (on the left side of the `=>` symbol) states that `f` takes no input parameters. -- The `Unit` portion of the signature (on the right side of the `=>` symbol) indicates that `f` should return nothing. +- The `Unit` portion of the signature (on the right side of the `=>` symbol) indicates that `f` should not return a meaningful result. - Looking back at the body of the `sayHello` method (on the right side of the `=` symbol), the `f()` statement there invokes the function that’s passed in. Now that we’ve defined `sayHello`, let’s create a function to match `f`’s signature so we can test it. @@ -148,7 +148,7 @@ The only thing to do now is see a few more examples of how to define different t In this method: ```scala -def sayHello(f: () => Unit) +def sayHello(f: () => Unit): Unit ``` We noted that the type signature for `f` is: @@ -157,7 +157,7 @@ We noted that the type signature for `f` is: () => Unit ``` -We know that this means, “a function that takes no input parameters and returns nothing (given by `Unit`).” +We know that this means, “a function that takes no input parameters and returns nothing meaningful (given by `Unit`).” To demonstrate more type signature examples, here’s a function that takes a `String` parameter and returns an `Int`: @@ -255,40 +255,40 @@ executeAndPrint(multiply, 3, 9) // prints 27 ## Function type signature consistency -A great thing about learning about Scala’s function type signatures is that the syntax you use to define function input parameters is the same syntax you use to write anonymous functions and function variables. +A great thing about learning about Scala’s function type signatures is that the syntax you use to define function input parameters is the same syntax you use to write function literals. -For instance, if you were to write an anonymous function that calculates the sum of two integers, you’d write it like this: +For instance, if you were to write a function that calculates the sum of two integers, you’d write it like this: ```scala -(Int, Int) => Int = (a, b) => a + b +val f: (Int, Int) => Int = (a, b) => a + b ``` That code consists of the type signature: ```` -(Int, Int) => Int = (a, b) => a + b ------------------ +val f: (Int, Int) => Int = (a, b) => a + b + ----------------- ```` The input parameters: ```` -(Int, Int) => Int = (a, b) => a + b - ------ +val f: (Int, Int) => Int = (a, b) => a + b + ------ ```` and the body of the function: ```` -(Int, Int) => Int = (a, b) => a + b - ----- +val f: (Int, Int) => Int = (a, b) => a + b + ----- ```` -Scala’s consistency is shown here, where this anonymous function type signature: +Scala’s consistency is shown here, where this function type: ```` -(Int, Int) => Int = (a, b) => a + b ------------------ +val f: (Int, Int) => Int = (a, b) => a + b + ----------------- ```` is the same as the type signature you use to define a function input parameter: diff --git a/_overviews/scala3-book/fun-write-map-function.md b/_overviews/scala3-book/fun-write-map-function.md index 633d9b8fb8..74cab95213 100644 --- a/_overviews/scala3-book/fun-write-map-function.md +++ b/_overviews/scala3-book/fun-write-map-function.md @@ -66,7 +66,7 @@ As a bonus, notice that the `for` expression doesn’t do anything that depends Therefore, you can replace `Int` in the type signature with the generic type parameter `B`: ```scala -def map[A,B](f: (B) => A, xs: List[B]): List[A] = +def map[A, B](f: (B) => A, xs: List[B]): List[A] = for x <- xs yield f(x) ``` @@ -76,7 +76,7 @@ These examples demonstrate that `map` works as desired: ```scala def double(i : Int) = i * 2 -map(double, List(1, 2, 3)) // List(2,4,6) +map(double, List(1, 2, 3)) // List(2, 4, 6) def strlen(s: String) = s.length map(strlen, List("a", "bb", "ccc")) // List(1, 2, 3) diff --git a/_overviews/scala3-book/methods-intro.md b/_overviews/scala3-book/methods-intro.md index a6bf3e2fff..1c1414746c 100644 --- a/_overviews/scala3-book/methods-intro.md +++ b/_overviews/scala3-book/methods-intro.md @@ -9,7 +9,7 @@ next-page: methods-most In Scala 2, _methods_ can be defined inside classes, traits, objects, case classes, and case objects. -But it gets better: In Scala 3 they can also be defined _outside_ any of those constructs with a new feature named Toplevel definitions. +But it gets better: In Scala 3 they can also be defined _outside_ any of those constructs; we say that they are "top-level" definitions, since they are not nested in another definition. In short, methods can now be defined anywhere. Many features of methods are demonstrated in the next section. diff --git a/_overviews/scala3-book/methods-main-methods.md b/_overviews/scala3-book/methods-main-methods.md index 1077e238a2..bee342a45f 100644 --- a/_overviews/scala3-book/methods-main-methods.md +++ b/_overviews/scala3-book/methods-main-methods.md @@ -11,7 +11,7 @@ next-page: methods-summary Scala 3 offers a new way to define programs that can be invoked from the command line: Adding a `@main` annotation to a method turns it into entry point of an executable program: ```scala -@main def hello = println("Hello, world") +@main def hello() = println("Hello, world") ``` Just save that line of code in a file named something like *Hello.scala*---the filename doesn’t have to match the method name---and compile it with `scalac`: @@ -81,7 +81,7 @@ Illegal command line: java.lang.NumberFormatException: For input string: "sixty" The Scala compiler generates a program from an `@main` method `f` as follows: - It creates a class named `f` in the package where the `@main` method was found. -- The class has a static method `main` with the usual signature: It takes an `Array[String]` as argument and returns `Unit`. +- The class has a static method `main` with the usual signature of a Java `main` method: it takes an `Array[String]` as argument and returns `Unit`. - The generated `main` method calls method `f` with arguments converted using methods in the `scala.util.CommandLineParser` object. For instance, the `happyBirthday` method above generates additional code equivalent to the following class: diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index ac2140a41b..233c51b847 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -7,16 +7,16 @@ previous-page: methods-intro next-page: methods-main-methods --- -This section introduces the various aspects of how to define and call methods in Scala 2. +This section introduces the various aspects of how to define and call methods in Scala 3. ## Defining Methods Scala methods have many features, including these: - Generic (type) parameters -- Automatically provided `using` parameters - Default parameter values - Multiple parameter groups +- Context-provided parameters - By-name parameters - ... @@ -63,7 +63,7 @@ The Scala collections classes have dozens of built-in methods. These examples show how to call them: ```scala -val x = List(1,2,3) +val x = List(1, 2, 3) x.size // 3 x.contains(1) // true @@ -102,7 +102,7 @@ res0: Int = 4 ``` Notice that there’s no need for a `return` statement at the end of the method. -Because almost everything in Scala is an _expression_---meaning that each line of code returns (or _evaluates to) a value---there’s no need to use `return`. +Because almost everything in Scala is an _expression_---meaning that each line of code returns (or _evaluates to_) a value---there’s no need to use `return`. This becomes more clear when you condense that method and write it on one line: @@ -118,6 +118,7 @@ The body of a method can use all the different features of the language: - `for` loops and `for` expressions - Variable assignments - Calls to other methods +- Definitions of other methods As an example of a real-world multiline method, this `getStackTraceAsString` method converts its `Throwable` input parameter into a well-formatted `String`: @@ -202,10 +203,10 @@ When a method takes no parameters, it’s said to have an _arity_ level of _arit Similarly, when a method takes one parameter it’s an _arity-1_ method. When you create arity-0 methods: -- If the method has side effects, such as calling `println`, declare the method with empty parentheses -- If the method does not have side effects---such as getting the size of a collection, which is similar to accessing a field on the collection---leave the parentheses off +- If the method performs side effects, such as calling `println`, declare the method with empty parentheses +- If the method does not perform side effects---such as getting the size of a collection, which is similar to accessing a field on the collection---leave the parentheses off -For example, this method has a side effect, so it’s declared with empty parentheses: +For example, this method performs a side effect, so it’s declared with empty parentheses: ```scala def speak() = println("hi") @@ -218,7 +219,7 @@ speak // error: "method speak must be called with () argument" speak() // prints "hi" ``` -While this is just a convention, following it dramatically improves code readability: It makes it easier to understand at a glance that an arity-0 method has side effects. +While this is just a convention, following it dramatically improves code readability: It makes it easier to understand at a glance that an arity-0 method performs side effects. {% comment %} Some of that wording comes from this page: https://docs.scala-lang.org/style/method-invocation.html @@ -233,7 +234,7 @@ Here’s a method named `isTruthy` that implements the Perl definitions of `true ```scala def isTruthy(a: Any) = - if a == 0 || a == "" then + if a == 0 || a == "" || a == false then false else true @@ -257,7 +258,7 @@ Here’s another version of `isTruthy`, written with a `match` expression : ```scala def isTruthy(a: Matchable) = a match - case 0 | "" => false + case 0 | "" | false => false case _ => true ``` @@ -279,7 +280,7 @@ d.speak() // prints "Woof" ``` Methods can also be marked as `private`. -This makes them private to the current class, and they can’t be overridden in subclasses: +This makes them private to the current class, so they can’t be called nor overridden in subclasses: ```scala class Animal: @@ -290,7 +291,7 @@ class Cat extends Animal: override def breathe() = println("Yo, I’m totally breathing") ``` -If you want to make a method private to the current class and also allow subclasses to override it, mark the method as `protected`, as shown with the `speak` method in this example: +If you want to make a method private to the current class and also allow subclasses to call it or override it, mark the method as `protected`, as shown with the `speak` method in this example: ```scala class Animal: diff --git a/_overviews/scala3-book/packaging-imports.md b/_overviews/scala3-book/packaging-imports.md index b34071123d..ef3b9a16c1 100644 --- a/_overviews/scala3-book/packaging-imports.md +++ b/_overviews/scala3-book/packaging-imports.md @@ -33,26 +33,33 @@ package com.acme.myapp.model class Person ... ``` -By convention, package names should be all lower case, and the formal naming convention is *...*. +By convention, package names should be all lower case, and the formal naming convention is *\.\.\.\*. Although it’s not required, package names typically follow directory structure names, so if you follow this convention, a `Person` class in this project will be found in a *MyApp/src/main/scala/com/acme/myapp/model/Person.scala* file. -### Curly brace packaging style +### Using multiple packages in the same file -The other way to declare packages in Scala is by using the curly brace namespace notation used in languages like C, C++, and C#: +The syntax shown above applies to the entire source file: all the definitions in the file +`Person.scala` belong to package `com.acme.myapp.model`, according to the package clause +at the beginning of the file. + +Alternatively, it is possible to write package clauses that apply only to the definitions +they contain: ```scala -package users { - package administrators { - class AdminUser - } - package normalusers { - class NormalUser - } -} +package users: + + package administrators: // the full name of this package is users.administrators + class AdminUser // the full name of this class is users.administrators.AdminUser + + package normalusers: // the full name of this package is users.normalusers + class NormalUser // the full name of this class is users.normalusers.NormalUser ``` +Note that the package names are followed by a colon, and that the defininitions within +a package are indented. + The advantages of this approach are that it allows for package nesting, and provides more obvious control of scope and encapsulation, especially within the same file. @@ -92,27 +99,27 @@ A note before moving on: In Scala you can import one member from a package like this: ```scala -import java.io.File +import scala.concurrent.Future ``` and multiple members like this: ```scala -import java.io.File -import java.io.IOException -import java.io.FileNotFoundException +import scala.concurrent.Future +import scala.concurrent.Promise +import scala.concurrent.blocking ``` When importing multiple members, you can import them more concisely like this: ```scala -import java.io.{File, IOException, FileNotFoundException} +import scala.concurrent.{Future, Promise, blocking} ``` -When you want to import everything from the *java.io* package, use this syntax: +When you want to import everything from the *scala.concurrent* package, use this syntax: ```scala -import java.io.* +import scala.concurrent.* ``` @@ -170,13 +177,13 @@ val res0: java.util.ArrayList[String] = [] Because those Java classes are hidden, you can also use the Scala `List`, `Set`, and `Map` classes without having a naming collision: ```scala -scala> val a = List(1,2,3) +scala> val a = List(1, 2, 3) val a: List[Int] = List(1, 2, 3) -scala> val b = Set(1,2,3) +scala> val b = Set(1, 2, 3) val b: Set[Int] = Set(1, 2, 3) -scala> val c = Map(1->1, 2->2) +scala> val c = Map(1 -> 1, 2 -> 2) val c: Map[Int, Int] = Map(1 -> 1, 2 -> 2) ``` @@ -241,7 +248,7 @@ Two packages are implicitly imported into the scope of all of your source code f - java.lang.* - scala.* -The Scala `Predef` object is also imported by default. +The members of the Scala object `Predef` are also imported by default. > If you ever wondered why you can use classes like `List`, `Vector`, `Map`, etc., without importing them, they’re available because of definitions in the `Predef` object. From 08ede3bd71d7e400206b247beaf213065bf2535d Mon Sep 17 00:00:00 2001 From: Todd O'Bryan Date: Mon, 14 Jun 2021 01:06:14 -0700 Subject: [PATCH 0696/2265] Update quotes.md (#2047) I think the first two things are just typos. The third seems much easier for me, as a native English speaker, to understand. --- _overviews/scala3-macros/tutorial/quotes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_overviews/scala3-macros/tutorial/quotes.md b/_overviews/scala3-macros/tutorial/quotes.md index fe99cb4260..a772b23f8f 100644 --- a/_overviews/scala3-macros/tutorial/quotes.md +++ b/_overviews/scala3-macros/tutorial/quotes.md @@ -14,7 +14,7 @@ Intuitively, the code directly within the quote is not executed now, while the c ```scala val msg = Expr("Hello") -val printHello = '{ print($hello) } +val printHello = '{ print($msg) } println(printHello.show) // print("Hello") ``` @@ -46,7 +46,8 @@ def myBadCounter2(using Quotes): Expr[Int] = '{ } ``` Clearly, this should not work as the variable does not exist yet. -To make sure you can only write programs that do not contain these kinds of problems we restrict the set of references to variable and other definitions. + +To make sure you cannot write programs that contain these kinds of problems, we restrict the kinds of references allowed in quote environments. We introduce _levels_ as a count of the number of quotes minus the number of splices surrounding an expression or definition. From e70abc8308d1d262ade788c96a11d27745815c02 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 2 Jun 2021 15:59:37 +0200 Subject: [PATCH 0697/2265] Some suggestions in the Scala 3 book --- _overviews/scala3-book/introduction.md | 4 +- _overviews/scala3-book/scala-features.md | 38 ++++----- _overviews/scala3-book/taste-collections.md | 12 ++- .../scala3-book/taste-control-structures.md | 17 ++-- _overviews/scala3-book/taste-functions.md | 4 +- _overviews/scala3-book/taste-methods.md | 2 +- _overviews/scala3-book/taste-modeling.md | 14 +-- _overviews/scala3-book/taste-objects.md | 4 +- _overviews/scala3-book/why-scala-3.md | 85 ++++++++++--------- scala3/contribute-to-docs.md | 2 +- 10 files changed, 90 insertions(+), 92 deletions(-) diff --git a/_overviews/scala3-book/introduction.md b/_overviews/scala3-book/introduction.md index c2e131e26c..3d3558203d 100644 --- a/_overviews/scala3-book/introduction.md +++ b/_overviews/scala3-book/introduction.md @@ -12,8 +12,8 @@ The goal of this book is to provide an informal introduction to the Scala langua It touches on all Scala topics, in a relatively light manner. If at any time while you’re reading this book and want more information on a specific feature, you’ll find links to our [_Reference_ documentation][reference], which covers many new features of the Scala language in more detail. -Over the course of this book, we hope to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax, and supports functional programming (FP), object-oriented programming (OOP), and a fusion of FP and OOP in a typed setting. -Scala’s syntax, grammar, and features have been re-thought, debated in an open process, and updated in 2020 to be more clear and easier to understand than ever before. +Over the course of this book, we hope to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax, which supports functional programming (FP) and object-oriented programming (OOP), and that provides a safe static type system. +Scala’s syntax, grammar, and features have been re-thought, debated in an open process, and updated in 2020 to be clearer and easier to understand than ever before. The book begins with a whirlwind tour of many of Scala’s features in the [“A Taste of Scala” section][taste]. After that tour, the sections that follow it provide more details on those language features. diff --git a/_overviews/scala3-book/scala-features.md b/_overviews/scala3-book/scala-features.md index 048d7e4519..f0c8efb129 100644 --- a/_overviews/scala3-book/scala-features.md +++ b/_overviews/scala3-book/scala-features.md @@ -30,8 +30,8 @@ Looking at Scala from the proverbial “30,000 foot view,” you can make the fo - It has a concise, readable syntax - It’s statically-typed (but feels dynamic) - It has an expressive type system -- It’s a pure functional programming (FP) language -- It’s a pure object-oriented programming (OOP) language +- It’s a functional programming (FP) language +- It’s an object-oriented programming (OOP) language - It supports the fusion of FP and OOP - Contextual abstractions provide a clear way to implement _term inference_ - It runs on the JVM (and in the browser) @@ -63,7 +63,7 @@ val newNumbers = double(oldNumbers) ``` That code instructs the compiler what to do on a step-by-step basis. -Instead, we write high-level, functional code using higher-order functions and lambdas like this to achieve the same effect: +Instead, we write high-level, functional code using higher-order functions and lambdas like this to compute the same result: ```scala val newNumbers = oldNumbers.map(_ * 2) @@ -92,7 +92,7 @@ nums.filter(i => i > 1) nums.filter(_ > 1) ``` -And traits, classes, and methods are defined with a clean, light syntax: +Traits, classes, and methods are defined with a clean, light syntax: ```scala trait Animal: @@ -128,15 +128,13 @@ As Heather Miller states, Scala is considered to be a [strong, statically-typed - Correctness: you catch most errors at compile-time - Great IDE support - - Code completion + - Reliable code completion - Catching errors at compile-time means catching mistakes as you type - Easy and reliable refactoring - - Reliable code completion - You can refactor your code with confidence - Method type declarations tell readers what the method does, and help serve as documentation -- Types make your code easier to maintain -- Scalability: types help ensure correctness across arbitrarily large applications and development teams -- Strong typing in combination with excellent inference enables mechanisms like [contextual abstraction]({{ site.scala3ref }}/contextual/motivation.html) that allows you to omit boilerplate code. Often, this boilerplate code can be inferred by the compiler, based on type definitions and a given context (e.g. method arguments for implicit parameters). +- Scalability and maintainability: types help ensure correctness across arbitrarily large applications and development teams +- Strong typing in combination with excellent inference enables mechanisms like [contextual abstraction]({{ site.scala3ref }}/contextual/motivation.html) that allows you to omit boilerplate code. Often, this boilerplate code can be inferred by the compiler, based on type definitions and a given context. {% comment %} In that list: @@ -156,11 +154,11 @@ In that list: - i removed these items until we can replace them: * [Compound types](/tour/compound-types.html) -* [Implicit parameters](/tour/implicit-parameters.html) and [conversions](/tour/implicit-conversions.html) +* [conversions](/tour/implicit-conversions.html) * [Explicitly typed self references](/tour/self-types.html) {% endcomment %} -Scala’s expressive type system enforces, at compile-time, that abstractions are used in a safe and coherent manner. +Scala’s type system enforces, at compile-time, that abstractions are used in a safe and coherent manner. In particular, the type system supports: - [Type inference](/tour/type-inference.html) @@ -187,11 +185,11 @@ In particular, the type system supports: In combination, these features provide a powerful basis for the safe reuse of programming abstractions and for the type-safe extension of software. -### A pure FP language +### A functional programming language Scala is a functional programming (FP) language, meaning: -- Functions are variables, and can be passed around like any other variable +- Functions are values, and can be passed around like any other value - Higher-order functions are directly supported - Lambdas are built in - Everything in Scala is an expression that returns a value @@ -200,10 +198,10 @@ Scala is a functional programming (FP) language, meaning: - Those collection classes come with dozens of functional methods: they don’t mutate the collection, but instead return an updated copy of the data -### A pure OOP language +### An object-oriented language -Scala is a _pure_ object-oriented programming (OOP) language. -Every variable is an object and every “operator” is a method. +Scala is an object-oriented programming (OOP) language. +Every value is an instance of a class and every “operator” is a method. In Scala, all types inherit from a top-level class `Any`, whose immediate children are `AnyVal` (_value types_, such as `Int` and `Boolean`) and `AnyRef` (_reference types_, as in Java). This means that the Java distinction between primitive types and boxed types (e.g. `int` vs. `Integer`) isn’t present in Scala. @@ -236,9 +234,9 @@ Following Haskell, Scala was the second popular language to have some form of _i In Scala 3 these concepts have been completely re-thought and more clearly implemented. The core idea is _term inference_: Given a type, the compiler synthesizes a “canonical” term that has that type. -In Scala, an implicit parameter directly leads to an inferred argument term that could also be written down explicitly. +In Scala, a context parameter directly leads to an inferred argument term that could also be written down explicitly. -Use cases for this concept include implementing type classes, establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them. +Use cases for this concept include implementing [type classes]({% link _overviews/scala3-book/ca-type-classes.md %}), establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them. Scala 3 makes this process more clear than ever before. Read about contextual abstractions in the [Reference documentation]({{ site.scala3ref }}/contextual/motivation.html). @@ -442,7 +440,7 @@ Serialization: - [ScalaPB](https://github.com/scalapb/ScalaPB) -Science and data analysis: +### Science and data analysis: - [Algebird](https://github.com/twitter/algebird) - [Spire](https://github.com/typelevel/spire) @@ -461,7 +459,7 @@ Science and data analysis: - [TensorFlow Scala](https://github.com/eaplatanios/tensorflow_scala) -### FP & FRP +### Functional Programming & Functional Reactive Programming FP: diff --git a/_overviews/scala3-book/taste-collections.md b/_overviews/scala3-book/taste-collections.md index e40b85887b..67fdbc1d61 100644 --- a/_overviews/scala3-book/taste-collections.md +++ b/_overviews/scala3-book/taste-collections.md @@ -60,15 +60,13 @@ nums.map(_.toUpperCase) // List("ONE", "TWO") nums.flatMap(_.toUpperCase) // List('O', 'N', 'E', 'T', 'W', 'O') ``` -These examples show how the “fold” and “reduce” methods are used to sum the values in a sequence of integers: +These examples show how the “foldLeft” and “reduceLeft” methods are used to sum the values in a sequence of integers: ```scala val firstTen = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -firstTen.reduce(_ + _) // 55 firstTen.reduceLeft(_ + _) // 55 -firstTen.fold(100)(_ + _) // 155 (100 is a “seed” value) -firstTen.foldLeft(100)(_ + _) // 155 +firstTen.foldLeft(100)(_ + _) // 155 (100 is a “seed” value) ``` There are many more methods available to Scala collections classes, and they’re demonstrated in the [Collections chapter][collections], and in the [API Documentation][api]. @@ -93,9 +91,9 @@ val t = (11, "eleven", Person("Eleven")) Once you have a tuple, you can access its values by binding them to variables, or access them by number: ```scala -t._1 // 11 -t._2 // "eleven" -t._3 // Person("Eleven") +t(0) // 11 +t(1) // "eleven" +t(2) // Person("Eleven") ``` You can also use this _extractor_ approach to assign the tuple fields to variable names: diff --git a/_overviews/scala3-book/taste-control-structures.md b/_overviews/scala3-book/taste-control-structures.md index a527f603d2..5c30f73da4 100644 --- a/_overviews/scala3-book/taste-control-structures.md +++ b/_overviews/scala3-book/taste-control-structures.md @@ -186,7 +186,7 @@ This example shows (a) how to use a `match` expression as the body of a method, ```scala // getClassAsString is a method that takes a single argument of any type. -def getClassAsString(x: Any): String = x match +def getClassAsString(x: Matchable): String = x match case s: String => s"'$s' is a String" case i: Int => "Int" case d: Double => "Double" @@ -199,6 +199,10 @@ getClassAsString("hello") // 'hello' is a String getClassAsString(List(1, 2, 3)) // List ``` +The method `getClassAsString` takes as a parameter a value of type [Matchable]({{ site.scala3ref }}/other-new-features/matchable.html), which can be +any type supporting pattern matching (some types don’t support pattern matching because this could +break encapsulation). + There’s _much_ more to pattern matching in Scala. Patterns can be nested, results of patterns can be bound, and pattern matching can even be user-defined. See the pattern matching examples in the [Control Structures chapter][control] for more details. @@ -231,29 +235,26 @@ It’s one-line syntax looks like this: while x >= 0 do x = f(x) ``` -Again, Scala’s control structure syntax is flexible, and you can write this code in different ways depending on your preferences: +In Scala 2, the syntax was a bit different. The condition was surrounded by parentheses, and +there was no `do` keyword: ```scala while (x >= 0) do x = f(x) while (x >= 0) { x = f(x) } ``` +Scala 3 still supports the Scala 2 syntax for the sake of compatibility. + The `while` loop multiline syntax looks like this: ```scala var x = 1 -// without parentheses while x < 3 do println(x) x += 1 - -// with parentheses -while (x < 3) - println(x) - x += 1 ``` diff --git a/_overviews/scala3-book/taste-functions.md b/_overviews/scala3-book/taste-functions.md index 7977f6d600..b103dba666 100644 --- a/_overviews/scala3-book/taste-functions.md +++ b/_overviews/scala3-book/taste-functions.md @@ -11,13 +11,13 @@ next-page: taste-objects Scala has most features you’d expect in a functional programming language, including: -- Lambdas +- Lambdas (anonymous functions) - Higher-order functions (HOFs) - Immutable collections in the standard library Lambdas, also known as _anonymous functions_, are a big part of keeping your code concise but readable. -The `map` method of the `List` class is a typical example of a higher-order function---a function that takes a lambda as parameter. +The `map` method of the `List` class is a typical example of a higher-order function---a function that takes a function as parameter. These two examples are equivalent, and show how to multiply each number in a list by `2` by passing a lambda into the `map` method: diff --git a/_overviews/scala3-book/taste-methods.md b/_overviews/scala3-book/taste-methods.md index 011ba23bd7..2718059bb1 100644 --- a/_overviews/scala3-book/taste-methods.md +++ b/_overviews/scala3-book/taste-methods.md @@ -128,7 +128,7 @@ extension (s: String) ## See also Scala Methods can be much more powerful: they can take type parameters and context parameters. -They are covered in detail in the [Data Modeling][data-1] section. +They are covered in detail in the [Domain Modeling][data-1] section. diff --git a/_overviews/scala3-book/taste-modeling.md b/_overviews/scala3-book/taste-modeling.md index aaee4fa19a..20c605c6f9 100644 --- a/_overviews/scala3-book/taste-modeling.md +++ b/_overviews/scala3-book/taste-modeling.md @@ -81,7 +81,7 @@ c.stopRunning() // "No need to stop" ``` If that code makes sense---great, you’re comfortable with traits as interfaces. -If not, don’t worry, they’re explained in more detail in the [Data Modeling][data-1] chapter. +If not, don’t worry, they’re explained in more detail in the [Domain Modeling][data-1] chapter. ### Classes @@ -106,7 +106,7 @@ Notice that the class declaration creates a constructor: val p = Person("John", "Stephens") ``` -Constructors and other class-related topics are covered in the [Data Modeling][data-1] chapter. +Constructors and other class-related topics are covered in the [Domain Modeling][data-1] chapter. ## FP Domain Modeling @@ -170,7 +170,7 @@ enum Nat: case Succ(pred: Nat) ``` -Enums are covered in detail in the [Data Modeling][data-1] section of this book, and in the [Reference documentation]({{ site.scala3ref }}/enums/enums.html). +Enums are covered in detail in the [Domain Modeling][data-1] section of this book, and in the [Reference documentation]({{ site.scala3ref }}/enums/enums.html). ### Case classes @@ -183,7 +183,7 @@ When the compiler sees the `case` keyword in front of a `class` it has these eff - An `unapply` method is generated, which lets you use case classes in more ways in `match` expressions. - A `copy` method is generated in the class. This provides a way to create updated copies of the object without changing the original object. -- `equals` and `hashCode` methods are generated. +- `equals` and `hashCode` methods are generated to implement structural equality. - A default `toString` method is generated, which is helpful for debugging. @@ -206,7 +206,7 @@ case class Person( val p = Person("Reginald Kenneth Dwight", "Singer") // a good default toString method -p // Person = Person(Reginald Kenneth Dwight,Singer) +p // : Person = Person(Reginald Kenneth Dwight,Singer) // can access its fields, which are immutable p.name // "Reginald Kenneth Dwight" @@ -215,10 +215,10 @@ p.name = "Joe" // error: can’t reassign a val field // when you need to make a change, use the `copy` method // to “update as you copy” val p2 = p.copy(name = "Elton John") -p2 // Person = Person(Elton John,Singer) +p2 // : Person = Person(Elton John,Singer) ``` -See the [Data Modeling][data-1] sections for many more details on `case` classes. +See the [Domain Modeling][data-1] sections for many more details on `case` classes. diff --git a/_overviews/scala3-book/taste-objects.md b/_overviews/scala3-book/taste-objects.md index 1ba49e30d6..ae522627f1 100644 --- a/_overviews/scala3-book/taste-objects.md +++ b/_overviews/scala3-book/taste-objects.md @@ -1,7 +1,7 @@ --- -title: Objects +title: Singleton Objects type: section -description: This section provides an introduction to the use of objects in Scala 3. +description: This section provides an introduction to the use of singleton objects in Scala 3. num: 12 previous-page: taste-functions next-page: taste-collections diff --git a/_overviews/scala3-book/why-scala-3.md b/_overviews/scala3-book/why-scala-3.md index e5f317f9f3..e6c5b2bd96 100644 --- a/_overviews/scala3-book/why-scala-3.md +++ b/_overviews/scala3-book/why-scala-3.md @@ -45,7 +45,7 @@ For instance, a `List` is defined as a class---technically it’s an abstract cl val x = List(1, 2, 3) ``` -However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including an abstract class named `AbstractSeq`, traits like `LinearSeq` and `LinearSeqOps`, and more. +However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including abstract classes named `Iterable`, `Seq`, and `LinearSeq`. Those types are similarly composed of other small, modular units of code. In addition to building a type like `List` from a series of modular traits, the `List` API also consists of dozens of other methods, many of which are higher-order functions: @@ -67,7 +67,7 @@ The `List` class is immutable, so all of those methods return new values, as sho ## 2) A dynamic feel Scala’s _type inference_ often makes the language feel dynamically typed, even though it’s statically typed. -This is true with variable assignment: +This is true with variable declaration: ```scala val a = 1 @@ -108,7 +108,7 @@ val b: Password | Username = if (true) name else password ## 3) Concise syntax -Scala is a low ceremony, “concise but still readable” language. For instance, variable type assignment is concise: +Scala is a low ceremony, “concise but still readable” language. For instance, variable declaration is concise: ```scala val a = 1 @@ -120,8 +120,8 @@ Creating types like traits, classes, and enumerations are concise: ```scala trait Tail: - def wagTail: Unit - def stopTail: Unit + def wagTail(): Unit + def stopTail(): Unit enum Topping: case Cheese, Pepperoni, Sausage, Mushrooms, Onions @@ -151,7 +151,7 @@ All of these expressions and many more are concise, and still very readable: wha Implicits in Scala 2 were a major distinguishing design feature. They represented _the_ fundamental way to abstract over context, with a unified paradigm that served a great variety of use cases, among them: -- Implementing type classes +- Implementing [type classes]({% link _overviews/scala3-book/ca-type-classes.md %}) - Establishing context - Dependency injection - Expressing capabilities @@ -208,7 +208,7 @@ See that chapter for more details on these features. Scala can be used on the server side with terrific frameworks: - The [Play Framework](https://www.playframework.com) lets you build highly scalable server-side applications and microservices -- [Akka Actors](https://akka.io) let you use the actor model to greatly simplify parallel and concurrent software applications +- [Akka Actors](https://akka.io) let you use the actor model to greatly simplify distributed and concurrent software applications Scala can also be used in the browser with the [Scala.js project](https://www.scala-js.org), which is a type-safe replacement for JavaScript. The Scala.js ecosystem [has dozens of libraries](https://www.scala-js.org/libraries) to let you use React, Angular, jQuery, and many other JavaScript and Scala libraries in the browser. @@ -227,50 +227,50 @@ While these all use the `List` class, the same methods work with other collectio Here are some examples: ```scala -List.range(1, 3) // List(1, 2) -List.range(1, 6, 2) // List(1, 3, 5) -List.fill(3)("foo") // List(foo, foo, foo) -List.tabulate(3)(n => n * n) // List(0, 1, 4) -List.tabulate(4)(n => n * n) // List(0, 1, 4, 9) - -val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) -a.distinct // List(10, 20, 30, 40) -a.drop(2) // List(30, 40, 10) -a.dropRight(2) // List(10, 20, 30) -a.dropWhile(_ < 25) // List(30, 40, 10) -a.filter(_ < 25) // List(10, 20, 10) -a.filter(_ > 100) // List() -a.find(_ > 20) // Some(30) -a.head // 10 -a.headOption // Some(10) -a.init // List(10, 20, 30, 40) -a.intersect(List(19,20,21)) // List(20) -a.last // 10 -a.lastOption // Some(10) -a.map(_ * 2) // List(20, 40, 60, 80, 20) -a.slice(2,4) // List(30, 40) -a.tail // List(20, 30, 40, 10) -a.take(3) // List(10, 20, 30) -a.takeRight(2) // List(40, 10) -a.takeWhile(_ < 30) // List(10, 20) -a.filter(_ < 30).map(_ * 10) // List(100, 200) +List.range(1, 3) // List(1, 2) +List.range(start = 1, end = 6, step = 2) // List(1, 3, 5) +List.fill(3)("foo") // List(foo, foo, foo) +List.tabulate(3)(n => n * n) // List(0, 1, 4) +List.tabulate(4)(n => n * n) // List(0, 1, 4, 9) + +val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) +a.distinct // List(10, 20, 30, 40) +a.drop(2) // List(30, 40, 10) +a.dropRight(2) // List(10, 20, 30) +a.dropWhile(_ < 25) // List(30, 40, 10) +a.filter(_ < 25) // List(10, 20, 10) +a.filter(_ > 100) // List() +a.find(_ > 20) // Some(30) +a.head // 10 +a.headOption // Some(10) +a.init // List(10, 20, 30, 40) +a.intersect(List(19,20,21)) // List(20) +a.last // 10 +a.lastOption // Some(10) +a.map(_ * 2) // List(20, 40, 60, 80, 20) +a.slice(2, 4) // List(30, 40) +a.tail // List(20, 30, 40, 10) +a.take(3) // List(10, 20, 30) +a.takeRight(2) // List(40, 10) +a.takeWhile(_ < 30) // List(10, 20) +a.filter(_ < 30).map(_ * 10) // List(100, 200) val fruits = List("apple", "pear") -fruits.map(_.toUpperCase) // List(APPLE, PEAR) -fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R) +fruits.map(_.toUpperCase) // List(APPLE, PEAR) +fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R) val nums = List(10, 5, 8, 1, 7) -nums.sorted // List(1, 5, 7, 8, 10) -nums.sortWith(_ < _) // List(1, 5, 7, 8, 10) -nums.sortWith(_ > _) // List(10, 8, 7, 5, 1) +nums.sorted // List(1, 5, 7, 8, 10) +nums.sortWith(_ < _) // List(1, 5, 7, 8, 10) +nums.sortWith(_ > _) // List(10, 8, 7, 5, 1) ``` -## 8) Built-in practices +## 8) Built-in best practices Scala idioms encourage best practices in many ways. -For immutability, you’re encouraged to create immutable `val` fields: +For immutability, you’re encouraged to create immutable `val` declarations: ```scala val a = 1 // immutable variable @@ -283,7 +283,7 @@ val b = List(1,2,3) // List is immutable val c = Map(1 -> "one") // Map is immutable ``` -Case classes are primarily intended for use in functional programming, and their parameters are immutable: +Case classes are primarily intended for use in [domain modeling]({% link _overviews/scala3-book/domain-modeling-intro.md %}), and their parameters are immutable: ```scala case class Person(name: String) @@ -386,6 +386,7 @@ _Safety_ is related to several new and changed features: - Multiversal equality - Restricting implicit conversions - Null safety +- Safe initialization Good examples of _ergonomics_ are enumerations and extension methods, which have been added to Scala 3 in a very readable manner: diff --git a/scala3/contribute-to-docs.md b/scala3/contribute-to-docs.md index 91b467766f..642a12f2c0 100644 --- a/scala3/contribute-to-docs.md +++ b/scala3/contribute-to-docs.md @@ -16,7 +16,7 @@ We welcome contributions from the community to every aspect of the documentation ### How can I contribute? -In general, there is many different ways you could help us: +In general, there are many ways you can help us: - **Confused about something in any of the docs?** Open an issue. - **Found something not up-to-date?** Open an issue or create a PR. From 5bc689d64915c1e7f90a6d821e2adc7aa3c36a47 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 7 Jun 2021 18:35:57 +0200 Subject: [PATCH 0698/2265] Some suggestions in the Scala 3 book (2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’ve reviewed the following chapters: - a first look at types - control structures - domain modeling Here are some simple suggestions, or typos fixes. --- _overviews/scala3-book/control-structures.md | 34 ++++++------------- _overviews/scala3-book/domain-modeling-fp.md | 2 +- _overviews/scala3-book/domain-modeling-oop.md | 21 ++++++------ .../scala3-book/domain-modeling-tools.md | 20 +---------- _overviews/scala3-book/first-look-at-types.md | 7 ++-- 5 files changed, 27 insertions(+), 57 deletions(-) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index a1fd727a3d..50f81a2b1b 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -144,26 +144,14 @@ scala> for i <- ints do println(i) 3 ```` -When you need a multiline block of code following the `for` generator, use either of these approaches: +When you need a multiline block of code following the `for` generator, use the following syntax: ```scala -// option 1 for i <- ints do val x = i * 2 println(s"i = $i, x = $x") - -// option 2 -for (i <- ints) - val x = i * 2 - println(s"i = $i, x = $x") - -// option 3 -for (i <- ints) { - val x = i * 2 - println(s"i = $i, x = $x") -} ``` ### Multiple generators @@ -276,7 +264,7 @@ val list = yield i * 2 -// result: list == Vector(20, 22, 24) +// list: IndexedSeq[Int] = Vector(20, 22, 24) ``` After that `for` expression runs, the variable `list` is a `Vector` that contains the values shown. @@ -288,7 +276,7 @@ This is how the expression works: It multiples it by `2`, then yields the value `22`. You can think of these yielded values as accumulating in a temporary holding place. 3. Finally the loop gets the number `12` from the range, multiplies it by `2`, yielding the number `24`. - The loop completes at this point and yields the final result, the `Vector(20,22,24)`. + The loop completes at this point and yields the final result, the `Vector(20, 22, 24)`. {% comment %} NOTE: This is a place where it would be great to have a TIP or NOTE block: @@ -297,7 +285,7 @@ NOTE: This is a place where it would be great to have a TIP or NOTE block: While the intent of this section is to demonstrate `for` expressions, it can help to know that the `for` expression shown is equivalent to this `map` method call: ```scala -val list = (10 to 12).map { i => i * 2} +val list = (10 to 12).map(i => i * 2) ``` `for` expressions can be used any time you need to traverse all of the elements in a collection and apply an algorithm to those elements to create a new list. @@ -312,7 +300,7 @@ val capNames = for name <- names yield val capName = nameWithoutUnderscore.capitalize capName -// result: List[String] = List(Olivia, Walter, Peter) +// capNames: List[String] = List(Olivia, Walter, Peter) ``` @@ -329,7 +317,7 @@ def between3and10(xs: List[Int]): List[Int] = if x <= 10 yield x -between3and10(List(1, 3, 7, 11)) // result: List(3, 7) +between3and10(List(1, 3, 7, 11)) // : List[Int] = List(3, 7) ``` @@ -386,7 +374,7 @@ If it’s between `0` and `6`, `day` is bound to a string that represents one of Otherwise, the catch-all case is represented by the `_` character, and `day` is bound to the string, `"invalid day"`. > When writing simple `match` expressions like this, it’s recommended to use the `@switch` annotation on the variable `i`. -> This annotation provides a compile time warning if the switch can’t be compiled to a `tableswitch` or `lookupswitch`, which are better for performance. +> This annotation provides a compile-time warning if the switch can’t be compiled to a `tableswitch` or `lookupswitch`, which are better for performance. ### Using the default value @@ -417,7 +405,7 @@ val evenOrOdd = i match ``` -### Using `if` expressions in `case` statements +### Using `if` guards in `case` clauses You can also use guards in the `case`s of a match expression. In this example the second and third `case` both use guards to match multiple integer values: @@ -528,8 +516,8 @@ def pattern(x: Matchable): String = x match case a: Array[Int] => s"array of int: ${a.mkString(",")}" case as: Array[String] => s"string array: ${as.mkString(",")}" case d: Dog => s"dog: ${d.name}" - case list: List[_] => s"got a List: $list" - case m: Map[_, _] => m.toString + case list: List[?] => s"got a List: $list" + case m: Map[?, ?] => m.toString // the default wildcard pattern case _ => "Unknown" @@ -561,7 +549,7 @@ finally println("Came to the 'finally' clause.") ``` -Assuming that the `openAndReadAFile` method uses the Java `java.io._` classes to read a file and doesn’t catch its exceptions, attempting to open and read a file can result in both a `FileNotFoundException` and an `IOException`, and those two exceptions are caught in the `catch` block of this example. +Assuming that the `openAndReadAFile` method uses the Java `java.io.*` classes to read a file and doesn’t catch its exceptions, attempting to open and read a file can result in both a `FileNotFoundException` and an `IOException`, and those two exceptions are caught in the `catch` block of this example. [matchable]: {{ site.scala3ref }}/other-new-features/matchable.html diff --git a/_overviews/scala3-book/domain-modeling-fp.md b/_overviews/scala3-book/domain-modeling-fp.md index 4d42dc6abb..dec7dda6d2 100644 --- a/_overviews/scala3-book/domain-modeling-fp.md +++ b/_overviews/scala3-book/domain-modeling-fp.md @@ -43,7 +43,7 @@ An FP design is implemented in a similar way: > As we will see, reasoning about programs in this style is quite different from the object-oriented programming. > Data in FP simply **is**: -> Separating functionality from your data let's you inspect your data without having to worry about behavior. +> Separating functionality from your data lets you inspect your data without having to worry about behavior. In this chapter we’ll model the data and operations for a “pizza” in a pizza store. You’ll see how to implement the “data” portion of the Scala/FP model, and then you’ll see several different ways you can organize the operations on that data. diff --git a/_overviews/scala3-book/domain-modeling-oop.md b/_overviews/scala3-book/domain-modeling-oop.md index 10821996d9..c06260d84d 100644 --- a/_overviews/scala3-book/domain-modeling-oop.md +++ b/_overviews/scala3-book/domain-modeling-oop.md @@ -89,12 +89,11 @@ When designing software in Scala, it’s often helpful to only consider using cl NOTE: I think “leaves” may technically be the correct word to use, but I prefer “leafs.” {% endcomment %} -```text -traits T1 T2 ... T3 -composed traits S extends T1, T2 ... S extends T2, T3 -classes C extends S, T3 -instances new C -``` +| Traits | `T1`, `T2`, `T3` +| Composed traits | `S extends T1, T2`, `S extends T2, T3` +| Classes | `C extends S, T3` +| Instances | `C()` + This is even more the case in Scala 3, where traits now can also take parameters, further eliminating the need for classes. #### Defining Classes @@ -147,7 +146,7 @@ class Counter: // can only be observed by the method `count` private var currentCount = 0 - def tick() = currentCount += 1 + def tick(): Unit = currentCount += 1 def count: Int = currentCount ``` Every instance of the class `Counter` has its own private state that can only be observed through the method `count`, as the following interaction illustrates: @@ -198,7 +197,7 @@ There are a few things that need explanation. #### Abstract Type Members The declaration `type S <: Subject` says that within the trait `SubjectObserver` we can refer to some _unknown_ (that is, abstract) type that we call `S`. However, the type is not completely unknown: we know at least that it is _some subtype_ of the trait `Subject`. -All traits and classes extending `SubjectObserer` are free to chose any type for `S` as long as the chosen type is a subtype of `Subject`. +All traits and classes extending `SubjectObserer` are free to choose any type for `S` as long as the chosen type is a subtype of `Subject`. The `<: Subject` part of the declaration is also referred to as an _upper bound on `S`_. #### Nested Traits @@ -210,12 +209,12 @@ The second trait, `Subject`, defines one private field `observers` to store all Subscribing to a subject simply stores the object into this list. Again, the type of parameter `obs` is `O`, not `Observer`. -#### Selftype Annotations +#### Self-type Annotations Finally, you might have wondered what the `self: S =>` on trait `Subject` is supposed to mean. -This is called a _selftype annotation_. +This is called a _self-type annotation_. It requires subtypes of `Subject` to also be subtypes of `S`. This is necessary to be able to call `obs.notify` with `this` as an argument, since it requires a value of type `S`. -If `S` was a _concrete_ type, the selftype annotation could be replaced by `trait Subject extends S`. +If `S` was a _concrete_ type, the self-type annotation could be replaced by `trait Subject extends S`. ### Implementing the Component We can now implement the above component and define the abstract type members to be concrete types: diff --git a/_overviews/scala3-book/domain-modeling-tools.md b/_overviews/scala3-book/domain-modeling-tools.md index bd9e955ba5..b8fd76f2fc 100644 --- a/_overviews/scala3-book/domain-modeling-tools.md +++ b/_overviews/scala3-book/domain-modeling-tools.md @@ -33,27 +33,9 @@ class Movie(var name: String, var director: String, var year: Int) ``` These examples show that Scala has a very lightweight way to declare classes. -The definition of the class `Person` roughly corresponds to the following, more explicit, version: - -```scala -class Person: - // fields - var name: String = null - var vocation: String = null - - // constructor - def this(_name: String, _vocation: String) = - // call to the super constructor - this() - // assigning the fields - name = _name - vocation = _vocation -``` - -This version defines the two fields `name` and `vocation`, together with a constructor that accepts values for those two fields and assigns them. All of the parameters of our example classes are defined as `var` fields, which means they are mutable: you can read them, and also modify them. -If you want them to be immutable---read only---create them as `val` fields instead. +If you want them to be immutable---read only---create them as `val` fields instead, or use a case class. Prior to Scala 3, you used the `new` keyword to create a new instance of a class: diff --git a/_overviews/scala3-book/first-look-at-types.md b/_overviews/scala3-book/first-look-at-types.md index 0a14e41a8c..106f564258 100644 --- a/_overviews/scala3-book/first-look-at-types.md +++ b/_overviews/scala3-book/first-look-at-types.md @@ -267,13 +267,14 @@ A common use is to signal non-termination, such as a thrown exception, program e `Null` is a subtype of all reference types (i.e. any subtype of `AnyRef`). It has a single value identified by the keyword literal `null`. -`Null` is provided mostly for interoperability with other JVM languages and should almost never be used in Scala code. -Alternatives to `null` are discussed in the [Functional Programming chapter][fp] of this book, and the [API documentation][option-api]. - +Currently, the usage of `null` is considered bad practice. It should be used mostly for interoperability with other JVM languages. An opt-in compiler option changes the status of `Null` to fix the caveats related to its usage. This option might become the default in a future version of Scala. You can learn more about it [here][safe-null]. +In the meantime, `null` should almost never be used in Scala code. +Alternatives to `null` are discussed in the [Functional Programming chapter][fp] of this book, and the [API documentation][option-api]. [reference]: {{ site.scala3ref }}/overview.html [matchable]: {{ site.scala3ref }}/other-new-features/matchable.html [interpolation]: {% link _overviews/core/string-interpolation.md %} [fp]: {% link _overviews/scala3-book/fp-intro.md %} [option-api]: https://dotty.epfl.ch/api/scala/Option.html +[safe-null]: {{ site.scala3ref }}/other-new-features/explicit-nulls.html From 84ef96cf45c0c27a59fda3162b529e01d210f6c8 Mon Sep 17 00:00:00 2001 From: SourceCodeBot Date: Mon, 14 Jun 2021 21:14:46 +0200 Subject: [PATCH 0699/2265] fix: fix syntax issue with arguments --- _overviews/scala3-book/ca-given-using-clauses.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/ca-given-using-clauses.md b/_overviews/scala3-book/ca-given-using-clauses.md index dd1b4ccc1b..5ba38fd64b 100644 --- a/_overviews/scala3-book/ca-given-using-clauses.md +++ b/_overviews/scala3-book/ca-given-using-clauses.md @@ -26,7 +26,7 @@ def renderWebsite(path: String, c: Config): String = def renderWidget(items: List[String], c: Config): String = ??? val config = Config(8080, "docs.scala-lang.org") -renderWebsite("/home")(config) +renderWebsite("/home", config) ``` Let us assume that the configuration does not change throughout most of our code base. Passing `c` to each and every method call (like `renderWidget`) becomes very tedious and makes our program more difficult to read, since we need to ignore the `c` argument. From 83206c35bbfeaafe52ae49bd92d709894e76d1f3 Mon Sep 17 00:00:00 2001 From: Stephan Schneider Date: Mon, 14 Jun 2021 21:32:28 +0200 Subject: [PATCH 0700/2265] Update index.md typo --- _overviews/FAQ/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index 0e4b7200ad..e7d25dbcf5 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -188,7 +188,7 @@ differ from a function value such as: Note that in **Scala 3** most of the differences will go; for example, they will be able to [accept implicit parameters](https://dotty.epfl.ch/docs/reference/contextual/context-functions.html) -as well as [type parameterts](https://dotty.epfl.ch/docs/reference/new-types/polymorphic-function-types.html). +as well as [type parameters](https://dotty.epfl.ch/docs/reference/new-types/polymorphic-function-types.html). Nevertheless, it is still recommended to use methods most of the time, unless you absolutely need a function. And, thanks to From f6943140ff557f826c81e2d46ea96d72f6a83011 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 14 Jun 2021 17:04:36 +0200 Subject: [PATCH 0701/2265] Suggestions in the Scala 3 book (part 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’ve reviewed the following chapters: - Scala Collections - Functional Programming - Types and the Type System - Contextual Abstractions --- _overviews/scala3-book/ca-context-bounds.md | 2 +- .../scala3-book/ca-given-using-clauses.md | 2 +- .../scala3-book/ca-implicit-conversions.md | 11 +++--- _overviews/scala3-book/collections-classes.md | 36 ++++++++++--------- _overviews/scala3-book/collections-methods.md | 16 ++++----- .../fp-functional-error-handling.md | 18 +++++----- _overviews/scala3-book/types-inferred.md | 2 +- _overviews/scala3-book/types-type-classes.md | 4 +-- _overviews/scala3-book/types-variance.md | 16 ++++----- 9 files changed, 57 insertions(+), 50 deletions(-) diff --git a/_overviews/scala3-book/ca-context-bounds.md b/_overviews/scala3-book/ca-context-bounds.md index fd435eb68f..462774a2d4 100644 --- a/_overviews/scala3-book/ca-context-bounds.md +++ b/_overviews/scala3-book/ca-context-bounds.md @@ -13,7 +13,7 @@ next-page: ca-given-imports - TODO: define "synthesized" and "synthesized arguments" {% endcomment %} -In many situations the name of a _context parameter_ doesn’t have to be mentioned explicitly, since it’s only used in synthesized arguments for other context parameters. +In many situations the name of a _context parameter_ doesn’t have to be mentioned explicitly, since it’s only used by the compiler in synthesized arguments for other context parameters. In that case you don’t have to define a parameter name, and can just provide the parameter type. diff --git a/_overviews/scala3-book/ca-given-using-clauses.md b/_overviews/scala3-book/ca-given-using-clauses.md index dd1b4ccc1b..39af385316 100644 --- a/_overviews/scala3-book/ca-given-using-clauses.md +++ b/_overviews/scala3-book/ca-given-using-clauses.md @@ -47,7 +47,7 @@ The Scala compiler thus performs **term inference**. In our call to `renderWidget(List("cart"))` the Scala compiler will see that there is a term of type `Config` in scope (the `c`) and automatically provide it to `renderWidget`. So the program is equivalent to the one above. -In fact, since we do not need to refer to `c` in our implementation of `renderWebsite` anymore, we can even omit it in the signature: +In fact, since we do not need to refer to `c` in our implementation of `renderWebsite` anymore, we can even omit its name in the signature: ```scala // no need to come up with a parameter name diff --git a/_overviews/scala3-book/ca-implicit-conversions.md b/_overviews/scala3-book/ca-implicit-conversions.md index 4a421da97b..d04cefa104 100644 --- a/_overviews/scala3-book/ca-implicit-conversions.md +++ b/_overviews/scala3-book/ca-implicit-conversions.md @@ -8,8 +8,8 @@ next-page: ca-summary --- -Implicit conversions are defined by `given` instances of the _scala.Conversion_ class. -For example, not accounting for possible conversion errors, this code defines an an implicit conversion from `String` to `Int`: +Implicit conversions are defined by `given` instances of the `scala.Conversion` class. +For example, not accounting for possible conversion errors, this code defines an implicit conversion from `String` to `Int`: ```scala given Conversion[String, Int] with @@ -34,10 +34,13 @@ def plus1(i: Int) = i + 1 plus1("1") ``` +> Note the clause `import scala.language.implicitConversions` at the beginning, +> to enable implicit conversions in the file. + ## Discussion -The Predef package contains “auto-boxing” conversions that map primitive number types to subclasses of _java.lang.Number_. -For instance, the conversion from `Int` to _java.lang.Integer_ can be defined as follows: +The Predef package contains “auto-boxing” conversions that map primitive number types to subclasses of `java.lang.Number`. +For instance, the conversion from `Int` to `java.lang.Integer` can be defined as follows: ```scala given int2Integer: Conversion[Int, java.lang.Integer] = diff --git a/_overviews/scala3-book/collections-classes.md b/_overviews/scala3-book/collections-classes.md index 7226398406..e9b7adec45 100644 --- a/_overviews/scala3-book/collections-classes.md +++ b/_overviews/scala3-book/collections-classes.md @@ -28,9 +28,9 @@ When you need more flexibility, see these pages at the end of this section for m Looking at Scala collections from a high level, there are three main categories to choose from: -- **Sequences** are a linear collection of elements and may be _indexed_ (like an array) or _linear_ (like a linked list) +- **Sequences** are a sequential collection of elements and may be _indexed_ (like an array) or _linear_ (like a linked list) - **Maps** contain a collection of key/value pairs, like a Java `Map`, Python dictionary, or Ruby `Hash` -- **Sets** are an unordered sequence of unique elements +- **Sets** are an unordered collection of unique elements All of those are basic types, and have subtypes for specific purposes, such as concurrency, caching, and streaming. In addition to those three main categories, there are other useful collection types, including ranges, stacks, and queues. @@ -74,7 +74,7 @@ The main collections you’ll use on a regular basis are: | `LazyList` | ✓ | | A lazy immutable linked list, its elements are computed only when they’re needed; Good for large or infinite sequences. | | `ArrayBuffer` | | ✓ | The go-to type for a mutable, indexed sequence | | `ListBuffer` | | ✓ | Used when you want a mutable `List`; typically converted to a `List` | -| `Map` | ✓ | ✓ | An iterable sequence that consists of pairs of keys and values. | +| `Map` | ✓ | ✓ | An iterable collection that consists of pairs of keys and values. | | `Set` | ✓ | ✓ | An iterable collection with no duplicate elements | As shown, `Map` and `Set` come in both immutable and mutable versions. @@ -109,7 +109,7 @@ For example, if you need an immutable, indexed collection, in general you should Conversely, if you need a mutable, indexed collection, use an `ArrayBuffer`. > `List` and `Vector` are often used when writing code in a functional style. -> `ArrayBuffer` is commonly used when writing code in a mutable style. +> `ArrayBuffer` is commonly used when writing code in an imperative style. > `ListBuffer` is used when you’re mixing styles, such as building a list. The next several sections briefly demonstrate the `List`, `Vector`, and `ArrayBuffer` types. @@ -291,7 +291,7 @@ val nums = Vector(1, 2, 3, 4, 5) val strings = Vector("one", "two") -case class Person(val name: String) +case class Person(name: String) val people = Vector( Person("Bert"), Person("Ernie"), @@ -383,10 +383,9 @@ Or if you prefer methods with textual names you can also use `append`, `appendAl Here are some examples of `+=` and `++=`: ```scala -var nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) +val nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) nums += 4 // ArrayBuffer(1, 2, 3, 4) -nums += (5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) -nums ++= List(7, 8) // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8) +nums ++= List(5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) ``` ### Removing elements from an ArrayBuffer @@ -415,7 +414,7 @@ a.update(0, 10) // ArrayBuffer(10, 2, 50, 4) ## Maps -A `Map` is an iterable sequence that consists of pairs of keys and values. +A `Map` is an iterable collection that consists of pairs of keys and values. Scala has both mutable and immutable `Map` types, and this section demonstrates how to use the _immutable_ `Map`. ### Creating an immutable Map @@ -433,13 +432,13 @@ val states = Map( Once you have a `Map` you can traverse its elements in a `for` loop like this: ```scala -for ((k,v) <- states) println(s"key: $k, value: $v") +for (k, v) <- states do println(s"key: $k, value: $v") ``` The REPL shows how this works: ```` -scala> for ((k,v) <- states) println(s"key: $k, value: $v") +scala> for (k, v) <- states do println(s"key: $k, value: $v") key: AK, value: Alaska key: AL, value: Alabama key: AZ, value: Arizona @@ -463,7 +462,7 @@ Add elements to an immutable map using `+` and `++`, remembering to assign the r ```scala val a = Map(1 -> "one") // a: Map(1 -> one) val b = a + (2 -> "two") // b: Map(1 -> one, 2 -> two) -val c = b + ( +val c = b ++ Seq( 3 -> "three", 4 -> "four" ) @@ -482,13 +481,13 @@ val a = Map( 4 -> "four" ) -a - 4 // Map(1 -> one, 2 -> two, 3 -> three) -a - 4 - 3 // Map(1 -> one, 2 -> two) +val b = a - 4 // b: Map(1 -> one, 2 -> two, 3 -> three) +val c = a - 4 - 3 // c: Map(1 -> one, 2 -> two) ``` ### Updating Map elements -To update elements in an immutable map, use the `updated` method while assigning the result to a new variable: +To update elements in an immutable map, use the `updated` method (or the `+` operator) while assigning the result to a new variable: ```scala val a = Map( @@ -497,7 +496,8 @@ val a = Map( 3 -> "three" ) -val b = a.updated(3, "THREE!") // Map(1 -> one, 2 -> two, 3 -> THREE!) +val b = a.updated(3, "THREE!") // b: Map(1 -> one, 2 -> two, 3 -> THREE!) +val c = a + (2 -> "TWO...") // c: Map(1 -> one, 2 -> TWO..., 3 -> three) ``` ### Traversing a Map @@ -511,7 +511,7 @@ val states = Map( "AZ" -> "Arizona" ) -for ((k,v) <- states) println(s"key: $k, value: $v") +for (k, v) <- states do println(s"key: $k, value: $v") ``` That being said, there are _many_ ways to work with the keys and values in a map. @@ -558,6 +558,8 @@ val c = b ++ Seq(4, 1, 5, 5) // HashSet(5, 1, 2, 3, 4) Notice that when you attempt to add duplicate elements, they’re quietly dropped. +Also notice that the order of iteration of the elements is arbitrary. + ### Deleting elements from a Set diff --git a/_overviews/scala3-book/collections-methods.md b/_overviews/scala3-book/collections-methods.md index 3e6c208a21..4316dea761 100644 --- a/_overviews/scala3-book/collections-methods.md +++ b/_overviews/scala3-book/collections-methods.md @@ -34,7 +34,7 @@ The following methods work on all of the sequence types, including `List`, `Vect ## Examples of common methods To give you an overview of what you’ll see in the following sections, these examples show some of the most commonly used collections methods. -First, here are some methods don’t use lambdas: +First, here are some methods that don’t use lambdas: ```scala val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10) @@ -103,7 +103,7 @@ a.map(double(_)) a.map(double) ``` -In the last example, when an anonymous function consists of one statement that takes a single argument, you don’t have to name the argument, so even `-` isn’t required. +In the last example, when an anonymous function consists of one function call that takes a single argument, you don’t have to name the argument, so even `_` isn’t required. Finally, you can combine HOFs as desired to solve problems: @@ -217,10 +217,10 @@ david ## `head` The `head` method comes from Lisp and other earlier functional programming languages. -It’s used to print the first element (the head element) of a list: +It’s used to access the first element (the head element) of a list: ```scala -oneToTen.head // Int = 1 +oneToTen.head // 1 names.head // adam ``` @@ -228,8 +228,8 @@ Because a `String` can be seen as a sequence of characters, you can also treat i This is how `head` works on these strings: ```scala -"foo".head // Char = 'f' -"bar".head // Char = 'b' +"foo".head // 'f' +"bar".head // 'b' ``` `head` is a great method to work with, but as a word of caution it can also throw an exception when called on an empty collection: @@ -242,7 +242,7 @@ emptyList.head // java.util.NoSuchElementException: head of empty Because of this you may want to use `headOption` instead of `head`, especially when programming in a functional style: ```scala -emptyList.headOption // Option[Int] = None +emptyList.headOption // None ``` As shown, it doesn’t throw an exception, it simply returns the type `Option` that has the value `None`. @@ -256,7 +256,7 @@ The `tail` method also comes from Lisp, and it’s used to print every element i A few examples demonstrate this: ```scala -oneToTen.head // Int = 1 +oneToTen.head // 1 oneToTen.tail // List(2, 3, 4, 5, 6, 7, 8, 9, 10) names.head // adam diff --git a/_overviews/scala3-book/fp-functional-error-handling.md b/_overviews/scala3-book/fp-functional-error-handling.md index ee33cffe11..d56dfff3a6 100644 --- a/_overviews/scala3-book/fp-functional-error-handling.md +++ b/_overviews/scala3-book/fp-functional-error-handling.md @@ -106,7 +106,7 @@ makeInt(x) match case None => println("That didn’t work.") ``` -In this example, if `x` can be converted to an `Int`, the first `case` statement is executed; if `x` can’t be converted to an `Int`, the second `case` statement is executed. +In this example, if `x` can be converted to an `Int`, the expression on the right-hand side of the first `case` clause is evaluated; if `x` can’t be converted to an `Int`, the expression on the right-hand side of the second `case` clause is evaluated. @@ -240,19 +240,20 @@ makeInt(x) match Getting back to `null` values, a place where a `null` value can silently creep into your code is with a class like this: ```scala -class Address: +class Address( var street1: String, var street2: String, - var city: String, - var state: String, + var city: String, + var state: String, var zip: String +) ``` While every address on Earth has a `street1` value, the `street2` value is optional. As a result, the `street2` field can be assigned a `null` value: ```scala -val santa = new Address( +val santa = Address( "1 Main Street", null, // <-- D’oh! A null value! "North Pole", @@ -265,18 +266,19 @@ Historically, developers have used blank strings and null values in this situati In Scala---and other modern languages---the correct solution is to declare up front that `street2` is optional: ```scala -class Address: +class Address( var street1: String, var street2: Option[String], // an optional value var city: String, var state: String, var zip: String +) ``` Now developers can write more accurate code like this: ```scala -val santa = new Address( +val santa = Address( "1 Main Street", None, // 'street2' has no value "North Pole", @@ -288,7 +290,7 @@ val santa = new Address( or this: ```scala -val santa = new Address( +val santa = Address( "123 Main Street", Some("Apt. 2B"), "Talkeetna", diff --git a/_overviews/scala3-book/types-inferred.md b/_overviews/scala3-book/types-inferred.md index fab485fecc..d56bafb629 100644 --- a/_overviews/scala3-book/types-inferred.md +++ b/_overviews/scala3-book/types-inferred.md @@ -12,7 +12,7 @@ As with other statically typed programming languages, in Scala you can _declare_ ```scala val x: Int = 1 -val x: Double = 1 +val y: Double = 1 ``` In those examples the types are _explicitly_ declared to be `Int` and `Double`, respectively. diff --git a/_overviews/scala3-book/types-type-classes.md b/_overviews/scala3-book/types-type-classes.md index 239866ecb7..24619309d1 100644 --- a/_overviews/scala3-book/types-type-classes.md +++ b/_overviews/scala3-book/types-type-classes.md @@ -23,7 +23,7 @@ In Scala 3, _type classes_ are just _traits_ with one or more type parameters, l trait Show[A]: def show(a: A): String ``` -Instances of `Show` for a particular type `A` witness that `A` we can show an instance of type `A`. +Instances of `Show` for a particular type `A` witness that we can show (i.e., produce a text representation of) an instance of type `A`. For example, let’s look at the following `Show` instance for `Int` values: ```scala @@ -43,7 +43,7 @@ toHtml(42)(ShowInt()) // results in "

    The number is 42!

    " ``` -#### Automatically passing Type Class Instances +#### Automatically passing type class instances Since type classes are a very important way to structure software, Scala 3 offers additional features that make working with them very convenient. We discuss these additional features (which fall into the category of *Contextual Abstractions*) in a [later chapter][typeclasses-chapter] of this book. diff --git a/_overviews/scala3-book/types-variance.md b/_overviews/scala3-book/types-variance.md index 5eec37b647..90ee0d04ba 100644 --- a/_overviews/scala3-book/types-variance.md +++ b/_overviews/scala3-book/types-variance.md @@ -22,11 +22,11 @@ Let us also assume the following parameterized types: trait Pipeline[T]: def process(t: T): T -// an example of an covariant type +// an example of a covariant type trait Producer[+T]: def make: T -// an example of an contravariant type +// an example of a contravariant type trait Consumer[-T]: def take(t: T): Unit ``` @@ -73,7 +73,7 @@ In contrast to `Pipeline`, which is invariant, the type `Producer` is marked as This is valid, since the type parameter is only used in a _return position_. Marking it as covariant means that we can pass (or return) a `Producer[Book]` where a `Producer[Buyable]` is expected. -And in fact, this is sound: The type of `Producer[Buyable].make` only promises to _return_ a `Buyable`. +And in fact, this is sound. The type of `Producer[Buyable].make` only promises to _return_ a `Buyable`. As a caller of `make`, we will be happy to also accept a `Book`, which is a subtype of `Buyable`---that is, it is _at least_ a `Buyable`. This is illustrated by the following example, where the function `makeTwo` expects a `Producer[Buyable]`: @@ -108,12 +108,12 @@ They have an additional ISBN method in our example, but you are free to ignore t In contrast to the type `Producer`, which is marked as covariant, the type `Consumer` is marked as **contravariant** by prefixing the type parameter with a `-`. This is valid, since the type parameter is only used in an _argument position_. -Marking it as contravariant means that we can pass (or return) a `Producer[Item]` where a `Producer[Buyable]` is expected. -That is, we have the subtyping relationship `Producer[Item] <: Producer[Buyable]`. -Remember, for type `Consumer`, it was the other way around, and we had `Consumer[Buyable] <: Consumer[Item]`. +Marking it as contravariant means that we can pass (or return) a `Consumer[Item]` where a `Consumer[Buyable]` is expected. +That is, we have the subtyping relationship `Consumer[Item] <: Consumer[Buyable]`. +Remember, for type `Producer`, it was the other way around, and we had `Producer[Buyable] <: Producer[Item]`. -And in fact, this is sound: The type of `Producer[Buyable].make` only promises us to _return_ a `Buyable`. -As a caller of `make`, we will be happy to also accept a `Book`, which is a subtype of `Buyable`---that is, it is _at least_ a `Buyable`. +And in fact, this is sound. The method `Consumer[Item].take` accepts an `Item`. +As a caller of `take`, we can also supply a `Buyable`, which will be happily accepted by the `Consumer[Item]` since `Buyable` is a subtype of `Item`---that is, it is _at least_ an `Item`. #### Contravariant Types for Consumers From 592063af448278ba521e82dac23ebc6b4fb1122a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 15 Jun 2021 12:57:20 -0700 Subject: [PATCH 0702/2265] update FAQ for Scala 3 release (#2074) --- _overviews/FAQ/index.md | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index e7d25dbcf5..ba0cce896d 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -2,14 +2,14 @@ layout: singlepage-overview title: Scala FAQ permalink: /tutorials/FAQ/index.html -redirect_from: +redirect_from: - "/tutorials/FAQ/breakout.html" - "/tutorials/FAQ/chaining-implicits.html" - "/tutorials/FAQ/collections.html" - "/tutorials/FAQ/context-bounds.html" - "/tutorials/FAQ/finding-implicits.html" - "/tutorials/FAQ/finding-symbols.html" - - "/tutorials/FAQ/stream-view.html" + - "/tutorials/FAQ/stream-view.html" - "/tutorials/FAQ/yield.html" --- @@ -35,25 +35,21 @@ 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 +ask for book recommendations. You'll get more helpful answers if you provide some information about your background and your reasons for wanting to learn Scala. ### 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 was released in May 2021. Because Scala 3 is still so new, +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.0 is planned for release in 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. +Thus, Scala 2 remains a common and reasonable choice. -### When is Scala 3 coming out? - -In 2021. Watch the [Scala blog](https://www.scala-lang.org/blog/) -for announcements. For a more detailed view of how work is progressing, -see the [Dotty milestones](https://github.com/lampepfl/dotty/milestones). +Some books that cover Scala 3 are already available; more are on the +way. In time, there will be more and more Scala 3 jobs as well. ### Where are Scala jobs advertised? @@ -181,11 +177,10 @@ differ from a function value such as: val square: Int => Int = x => x * x -[Complete answer on Stack Overflow](https://stackoverflow.com/a/2530007/4111404). - -[Summary with practical differences](https://tpolecat.github.io/2014/06/09/methods-functions.html). +For Scala 2, there is a [complete answer on Stack Overflow](https://stackoverflow.com/a/2530007/4111404) +and a [summary with practical differences](https://tpolecat.github.io/2014/06/09/methods-functions.html). -Note that in **Scala 3** most of the differences will go; +Note that in **Scala 3** the differences are fewer; for example, they will be able to [accept implicit parameters](https://dotty.epfl.ch/docs/reference/contextual/context-functions.html) as well as [type parameters](https://dotty.epfl.ch/docs/reference/new-types/polymorphic-function-types.html). @@ -193,7 +188,7 @@ as well as [type parameters](https://dotty.epfl.ch/docs/reference/new-types/poly Nevertheless, it is still recommended to use methods most of the time, unless you absolutely need a function. And, thanks to [eta-expansion](https://stackoverflow.com/questions/39445018/what-is-the-eta-expansion-in-scala) -you rarely would need to define a function over a method. +you rarely would need to define a function rather than a method. ### What's the difference between types and classes? From d9a05be0d454d9433db78187a13f9b6dee2ebfd4 Mon Sep 17 00:00:00 2001 From: "Lan, Jian" Date: Tue, 15 Jun 2021 14:06:23 -0700 Subject: [PATCH 0703/2265] Fix why-scala-3.md --- _overviews/scala3-book/why-scala-3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_overviews/scala3-book/why-scala-3.md b/_overviews/scala3-book/why-scala-3.md index e6c5b2bd96..ac74de1606 100644 --- a/_overviews/scala3-book/why-scala-3.md +++ b/_overviews/scala3-book/why-scala-3.md @@ -29,7 +29,6 @@ It’s hard to list every benefit of Scala, but a “Top Ten” list might look - ## 1) FP/OOP fusion More than any other language, Scala supports a fusion of the FP and OOP paradigms. @@ -45,7 +44,7 @@ For instance, a `List` is defined as a class---technically it’s an abstract cl val x = List(1, 2, 3) ``` -However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including abstract classes named `Iterable`, `Seq`, and `LinearSeq`. +However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including traits named `Iterable`, `Seq`, and `LinearSeq`. Those types are similarly composed of other small, modular units of code. In addition to building a type like `List` from a series of modular traits, the `List` API also consists of dozens of other methods, many of which are higher-order functions: @@ -106,6 +105,7 @@ val b: Password | Username = if (true) name else password ``` + ## 3) Concise syntax Scala is a low ceremony, “concise but still readable” language. For instance, variable declaration is concise: @@ -176,7 +176,6 @@ These capabilities are described in detail in other sections, so see the [Contex - ## 5) Seamless Java integration Scala/Java interaction is seamless in many ways. @@ -357,6 +356,7 @@ Some of the most important features in this category are: {% comment %} A list of types from the Dotty documentation: + - Inferred types - Generics - Intersection types From fcb797833e2b08cd0e549037109dc1b3450ba86b Mon Sep 17 00:00:00 2001 From: Elias Baldwin Date: Tue, 15 Jun 2021 14:15:45 -0700 Subject: [PATCH 0704/2265] Fix typo on line 131 of domain-modeling-oop.md --- _overviews/scala3-book/domain-modeling-oop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/domain-modeling-oop.md b/_overviews/scala3-book/domain-modeling-oop.md index c06260d84d..56d0972198 100644 --- a/_overviews/scala3-book/domain-modeling-oop.md +++ b/_overviews/scala3-book/domain-modeling-oop.md @@ -128,7 +128,7 @@ In order to allow this, the base class needs to be marked as `open`: ```scala open class Person(name: String) ``` -Marking classes with [`open`][open] is a new feature of Sala 3. Having to explicitly mark classes as open avoids many common pitfalls in OO design. +Marking classes with [`open`][open] is a new feature of Scala 3. Having to explicitly mark classes as open avoids many common pitfalls in OO design. In particular, it requires library designers to explicitly plan for extension and for instance document the classes that are marked as open with additional extension contracts. {% comment %} From 6ca2c3dbcb959eee3424e90a6dea5afdcfa26f6f Mon Sep 17 00:00:00 2001 From: Andrea Peruffo Date: Mon, 24 May 2021 14:40:20 +0100 Subject: [PATCH 0705/2265] Add graalvm AOT notes --- _overviews/jdk-compatibility/overview.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 880c4a4614..6c6a0e9201 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -89,6 +89,16 @@ JDK 17 prereleases are already available. The final release is [targeted](https: The Scala community build doesn't run on JDK 17 yet. We will add it once 17 is closer to release. +## GraalVM Native Image compatibility notes + +There are several records of successfully using Scala with [GraalVM](https://www.graalvm.org) Native Image(i.e.: ahead of time compiler) to produce directly executable binaries. +Beware that, even using solely the Scala standard library, Native Image compilation have some heavy requirements in terms of [reflective access](https://www.graalvm.org/reference-manual/native-image/Reflection/), and it very likely require additional configuration steps to be performed. + +A few sbt plugins are offering support for GraalVM Native Image compilation: + +- [sbt-native-packager](https://www.scala-sbt.org/sbt-native-packager/formats/graalvm-native-image.html) +- [sbt-native-image](https://github.com/scalameta/sbt-native-image) + ## Scala 3 The Scala 3.0.x series supports JDK 8, as well as 11 and beyond. From 57f573092edbb37d038da4d8f479a115757aa89e Mon Sep 17 00:00:00 2001 From: Theofanis Despoudis <328805+theodesp@users.noreply.github.com> Date: Wed, 9 Jun 2021 16:36:21 +0100 Subject: [PATCH 0706/2265] Update learn.md Removed ScalaCourses expired link for consistency and less confusion --- learn.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/learn.md b/learn.md index 2204c55f1d..19af2b78c9 100644 --- a/learn.md +++ b/learn.md @@ -101,9 +101,6 @@ You can visit his [YouTube channel](https://www.youtube.com/user/DrMarkCLewis/fe ## allaboutscala [allaboutscala](https://allaboutscala.com/) provides detailed tutorials for beginners. -## ScalaCourses -[Independent Courseware](https://getscala.com), online self-study or instructor-led Scala and Play courses for a fee. - ## DevInsideYou [DevInsideYou](https://youtube.com/devinsideyou) is a YouTube channel with hundreds of hours of free Scala content. From e2aa390b9d5ba0410181c84a64f9ed2990455ca0 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Sat, 19 Jun 2021 04:53:48 +0900 Subject: [PATCH 0707/2265] Create CODEOWNERS https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..ce1bb0f48b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +/_ja @scala/docs-ja From af81dade1616289e5bc5e01404322713ba433582 Mon Sep 17 00:00:00 2001 From: Myyk Seok Date: Sat, 19 Jun 2021 16:34:05 +0800 Subject: [PATCH 0708/2265] Fix typo: eather -> either --- _overviews/scala3-migration/incompat-dropped-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/incompat-dropped-features.md b/_overviews/scala3-migration/incompat-dropped-features.md index 2ba51e4a86..a8fe9b7789 100644 --- a/_overviews/scala3-migration/incompat-dropped-features.md +++ b/_overviews/scala3-migration/incompat-dropped-features.md @@ -204,7 +204,7 @@ Existential type is a [dropped feature](https://dotty.epfl.ch/docs/reference/dro def foo: List[Class[T]] forSome { type T } // Error: Existential types are no longer supported ``` -> Existential type is an experimental feature in Scala 2.13 that must be enabled explicitly eather by importing `import scala.language.existentials` or by setting the `-language:existentials` compiler flag. +> Existential type is an experimental feature in Scala 2.13 that must be enabled explicitly either by importing `import scala.language.existentials` or by setting the `-language:existentials` compiler flag. The proposed solution is to introduce an enclosing type that carries the dependent type: From 9ce11019bb8bfb0796a39af4503fa3d277113943 Mon Sep 17 00:00:00 2001 From: Abhishek Vyas <44902551+abhi887@users.noreply.github.com> Date: Mon, 21 Jun 2021 00:22:10 +0530 Subject: [PATCH 0709/2265] scala-for-python-devs.md creating multiline string variables Added an example for creating multiline string variables --- _overviews/scala3-book/scala-for-python-devs.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/_overviews/scala3-book/scala-for-python-devs.md b/_overviews/scala3-book/scala-for-python-devs.md index b045e67ac6..4a39f4ee27 100644 --- a/_overviews/scala3-book/scala-for-python-devs.md +++ b/_overviews/scala3-book/scala-for-python-devs.md @@ -136,13 +136,19 @@ These examples demonstrate how to create variables in Python and Scala. x = 1 -
    x = "Hi"
    +
    x = "Hi" +
    x = """foo +
           bar +
           baz"""
    val x = 1 -
    val x = "Hi"
    +
    val x = "Hi" +
    val x = """foo +
               bar +
               baz"""
    From 652241943ce762bbd488461a257e61cd640321c6 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 21 Jun 2021 14:23:35 +0100 Subject: [PATCH 0710/2265] compatibility example has wrong scala version --- _overviews/scala3-migration/compatibility-classpath.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/scala3-migration/compatibility-classpath.md b/_overviews/scala3-migration/compatibility-classpath.md index e9d71d65ab..521b2e448b 100644 --- a/_overviews/scala3-migration/compatibility-classpath.md +++ b/_overviews/scala3-migration/compatibility-classpath.md @@ -113,13 +113,13 @@ Or, in case `bar` is a published Scala 3 library: ```scala lazy val foo = project.in.file("foo") .settings( - scalaVersion := "3.0.0", + scalaVersion := "2.13.6", scalacOptions += "-Ytasty-reader", libraryDependencies += ("org.bar" %% "bar" % "1.0.0").cross(CrossVersion.for2_13Use3) ) ``` -Similarly to `CrossVersion.for2_13Use3`, we use `CrossVersion.for3Use2_13` in sbt to resolve `bar_2.13` instead of `bar_3`. +Similarly to `CrossVersion.for2_13Use3`, we use `CrossVersion.for3Use2_13` in sbt to resolve `bar_3` instead of `bar_2.13`. ## Interoperability Overview From ce031b5be7d04107c96c22e9afdbc850e6634a2e Mon Sep 17 00:00:00 2001 From: Abhishek Vyas <44902551+abhi887@users.noreply.github.com> Date: Mon, 21 Jun 2021 19:34:38 +0530 Subject: [PATCH 0711/2265] updated identifiers for multiline string and dictionary variables updated identifiers for multiline string variables and dictionary/map variable in scala-for-python-devs.md --- _overviews/scala3-book/scala-for-python-devs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_overviews/scala3-book/scala-for-python-devs.md b/_overviews/scala3-book/scala-for-python-devs.md index 4a39f4ee27..0934989d4e 100644 --- a/_overviews/scala3-book/scala-for-python-devs.md +++ b/_overviews/scala3-book/scala-for-python-devs.md @@ -137,7 +137,7 @@ These examples demonstrate how to create variables in Python and Scala. x = 1
    x = "Hi" -
    x = """foo +
    y = """foo
           bar
           baz"""
    @@ -146,7 +146,7 @@ These examples demonstrate how to create variables in Python and Scala. val x = 1
    val x = "Hi" -
    val x = """foo +
    val y = """foo
               bar
               baz"""
    @@ -186,7 +186,7 @@ These examples demonstrate how to create variables in Python and Scala. - val movies = Map( + val x = Map(
      "Toy Story" -> 8.3,
      "Forrest Gump" -> 8.8,
      "Cloud Atlas" -> 7.4 From 5f734205a00ae937f335c59e5fed26d4d6b69cf9 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 21 Jun 2021 13:39:55 -0700 Subject: [PATCH 0712/2265] fix Error Formatting page --- _data/overviews.yml | 2 +- _overviews/compiler-options/errors.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index 1764f6bc5e..54bb90a02b 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -257,7 +257,7 @@ - title: Error Formatting by: Torsten Schmits icon: cog - url: "compiler-options/index.html" + url: "compiler-options/errors.html" description: "A new engine for more user-friendly error messages, printing chains of dependent implicits and colored found/required type diffs." diff --git a/_overviews/compiler-options/errors.md b/_overviews/compiler-options/errors.md index f6e7823689..8128ef96ae 100644 --- a/_overviews/compiler-options/errors.md +++ b/_overviews/compiler-options/errors.md @@ -1,3 +1,8 @@ +--- +layout: singlepage-overview +title: Error Formatting +--- + # Introduction An advanced mechanism for formatting type errors and inspecting missing From 7c7eb8499a26b7ea7a1b07074dc3a25f4f431e4a Mon Sep 17 00:00:00 2001 From: Dean Wampler Date: Tue, 22 Jun 2021 16:08:18 -0500 Subject: [PATCH 0713/2265] Updated Programming Scala book images --- .../books/ProgrammingScala-final-border.gif | Bin 5574 -> 5619 bytes resources/img/books/ProgrammingScala.jpg | Bin 42408 -> 60005 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/img/books/ProgrammingScala-final-border.gif b/resources/img/books/ProgrammingScala-final-border.gif index 69f7cb8cad766bf0185700a2712858f73f7d9c8a..a8646acbdd87d5a7b1ee0fd9fd9c85b2f2048c81 100644 GIT binary patch literal 5619 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 YT)^)+s+S#2M=?0SZl|3b1c6Qe2dyeKE&u=k literal 5574 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 diff --git a/resources/img/books/ProgrammingScala.jpg b/resources/img/books/ProgrammingScala.jpg index 07db7ec46afc58b6c3f551498481de25399610a8..232d0abff801c3f66ec604c7a3432d4d71635341 100644 GIT binary patch literal 60005 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μ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 Date: Tue, 22 Jun 2021 16:35:27 -0500 Subject: [PATCH 0714/2265] Updated content for Programming Scala by Dean Wampler --- _books/2-programming-scala.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_books/2-programming-scala.md b/_books/2-programming-scala.md index 27a1e9ce61..8fc729169f 100644 --- a/_books/2-programming-scala.md +++ b/_books/2-programming-scala.md @@ -1,11 +1,11 @@ --- title: "Programming Scala" -link: https://shop.oreilly.com/product/0636920033073.do +link: http://programming-scala.com image: /resources/img/books/ProgrammingScala-final-border.gif -status: Updated for Scala 2.12 -authors: ["Alex Payne", "Dean Wampler"] +status: Updated for Scala 3 +authors: ["Dean Wampler"] publisher: O’Reilly publisherLink: https://www.oreilly.com/ --- -Both are industry experts, Alex Payne being the lead API programmer at Twitter, a social networking service based on Scala. O’Reilly, the publisher, writes: "Learn how to be more productive with Scala, a new multi-paradigm language for the Java Virtual Machine (JVM) that integrates features of both object-oriented and functional programming. With this book, you'll discover why Scala is ideal for highly scalable, component-based applications that support concurrency and distribution. You'll also learn how to leverage the wealth of Java class libraries to meet the practical needs of enterprise and Internet projects more easily." +Dean is a well-known member of the Scala community, using Scala recently for streaming data systems at Lightbend and now at Domino Data Lab. This edition covers the new features of Scala 3, with comparisons to Scala 2, both to explain why the changes were made and how they improve Scala, and also to enable developers using mixed Scala 2 and 3 code bases to work effectively. The book is aimed at professional programmers who want a comprehensive, in-depth, yet pragmatic tour of Scala and best practices for using it. From bcad9c105fc521b4bff0661017dede35c17042c0 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 23 Jun 2021 13:49:51 -0700 Subject: [PATCH 0715/2265] update JDK 17 info on JDK compatiblity page --- _overviews/jdk-compatibility/overview.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 6c6a0e9201..85e65f3448 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -12,8 +12,8 @@ Sometimes new JVM and JDK (Java Development Kit) versions require us to update S | JDK version | Minimum Scala versions | Recommended Scala versions | |:-----------:|:---------------------------------|:-----------------------------------------------------------| -| 17 | 2.13.6, 2.12.14 (see below) | 2.13.6, 2.12.14 (see below) -| 16 | 2.13.5, 2.12.14 | 2.13.6, 2.12.14 +| 17 | 2.13.6, 2.12.15 (forthcoming) | 2.13.6, 2.12.15 (forthcoming) | +| 16 | 2.13.5, 2.12.14 | 2.13.6, 2.12.14 | | 13, 14, 15 | 2.13.2, 2.12.11 | 2.13.6, 2.12.14 | | 12 | 2.13.1, 2.12.9 | 2.13.6, 2.12.14 | | 11 | 2.13.0, 2.12.4, 2.11.12 | 2.13.6, 2.12.14, 2.11.12 | @@ -81,13 +81,15 @@ As far as we know, 12, 13, 14, and 15 are similar to 11 with respect to Scala co JDK 16 was released in March 2021. It is not an LTS release, so the remarks above about non-LTS releases apply. The next LTS release will be JDK 17. -The Scala community build and the Scala build and test suite run on JDK 16. We shipped improved JDK 16 support in [Scala 2.13.5](https://github.com/scala/scala/releases/tag/v2.13.5) and intend to ship the same improvements soon in Scala 2.12.14 ([release timing thread](https://contributors.scala-lang.org/t/scala-2-12-14-planning/4852/2)). +The Scala build and test suite pass on JDK 16, and so does most of the Scala community build. We shipped improved JDK 16 support in [Scala 2.13.5](https://github.com/scala/scala/releases/tag/v2.13.5) and [2.12.14](https://github.com/scala/scala/releases/tag/v2.12.14). ## JDK 17 compatibility notes -JDK 17 prereleases are already available. The final release is [targeted](https://openjdk.java.net/projects/jdk/17/) for September 2021. JDK 17 will be an LTS release. +JDK 17 prereleases are already available. As of June 2021, the feature set is frozen. The final release is [targeted](https://openjdk.java.net/projects/jdk/17/) for September 2021. JDK 17 will be an LTS release. -The Scala community build doesn't run on JDK 17 yet. We will add it once 17 is closer to release. +The Scala community build is mostly green on JDK 17, as of June 2021. We are in the process of making Scala's own build and test suite pass. + +Scala 2.13.6 already supports JDK 17. Scala 2.12.14 mostly works as well, but there is a known issue with lambda deserialiation; a fix will ship in Scala 2.12.15 (see [release timing thread](https://contributors.scala-lang.org/t/scala-2-12-15-planning/5152)). ## GraalVM Native Image compatibility notes @@ -101,6 +103,6 @@ A few sbt plugins are offering support for GraalVM Native Image compilation: ## Scala 3 -The Scala 3.0.x series supports JDK 8, as well as 11 and beyond. +The Scala 3.x series supports JDK 8, as well as 11 and beyond. -As Scala and the JVM continue to evolve, some eventual Scala 3.x version may drop support for JDK 8, in order to better take advantage of new JVM features. It isn't clear yet what the new minimum supported version might become. +As Scala and the JVM continue to evolve, some eventual Scala version may drop support for JDK 8, in order to better take advantage of new JVM features. It isn't clear yet what the new minimum supported version might become. From 0e4bce98931a9a0e4d3ab5c75b5a28905207f444 Mon Sep 17 00:00:00 2001 From: Liam Bohl Date: Thu, 24 Jun 2021 11:37:33 -0400 Subject: [PATCH 0716/2265] Replaced functions deprecated as of 2.13 += (varargs) -> ++= -= (varargs) -> --= retain -> filterInPlace --- _overviews/scala-book/collections-maps.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_overviews/scala-book/collections-maps.md b/_overviews/scala-book/collections-maps.md index 1556a66ef8..95e890bbc3 100644 --- a/_overviews/scala-book/collections-maps.md +++ b/_overviews/scala-book/collections-maps.md @@ -83,18 +83,18 @@ Here are some things you can do with a mutable `Map`: ```scala // add elements with += states += ("AZ" -> "Arizona") -states += ("CO" -> "Colorado", "KY" -> "Kentucky") +states ++= Map("CO" -> "Colorado", "KY" -> "Kentucky") // remove elements with -= states -= "KY" -states -= ("AZ", "CO") +states --= List("AZ", "CO") // update elements by reassigning them states("AK") = "Alaska, The Big State" -// retain elements by supplying a function that operates on +// filter elements by supplying a function that operates on // the keys and/or values -states.retain((k,v) => k == "AK") +states.filterInPlace((k,v) => k == "AK") ``` From 8c0d3389302ac608fc436dc61a149dce5b723812 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 24 Jun 2021 08:40:05 -0700 Subject: [PATCH 0717/2265] tweak wording around community build as per Lukas's feedback --- _overviews/jdk-compatibility/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 85e65f3448..dd151bf707 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -81,13 +81,13 @@ As far as we know, 12, 13, 14, and 15 are similar to 11 with respect to Scala co JDK 16 was released in March 2021. It is not an LTS release, so the remarks above about non-LTS releases apply. The next LTS release will be JDK 17. -The Scala build and test suite pass on JDK 16, and so does most of the Scala community build. We shipped improved JDK 16 support in [Scala 2.13.5](https://github.com/scala/scala/releases/tag/v2.13.5) and [2.12.14](https://github.com/scala/scala/releases/tag/v2.12.14). +The Scala build and test suite pass on JDK 16, and so does the Scala community build. We shipped improved JDK 16 support in [Scala 2.13.5](https://github.com/scala/scala/releases/tag/v2.13.5) and [2.12.14](https://github.com/scala/scala/releases/tag/v2.12.14). ## JDK 17 compatibility notes JDK 17 prereleases are already available. As of June 2021, the feature set is frozen. The final release is [targeted](https://openjdk.java.net/projects/jdk/17/) for September 2021. JDK 17 will be an LTS release. -The Scala community build is mostly green on JDK 17, as of June 2021. We are in the process of making Scala's own build and test suite pass. +The Scala community build passes on JDK 17. We are in the process of making Scala's own build and test suite pass. Scala 2.13.6 already supports JDK 17. Scala 2.12.14 mostly works as well, but there is a known issue with lambda deserialiation; a fix will ship in Scala 2.12.15 (see [release timing thread](https://contributors.scala-lang.org/t/scala-2-12-15-planning/5152)). From bcd05f58cb46217358858002a9e17be6a57f2699 Mon Sep 17 00:00:00 2001 From: Dmitrii Naumenko Date: Thu, 24 Jun 2021 19:01:58 +0300 Subject: [PATCH 0718/2265] Update ca-given-imports.md --- _overviews/scala3-book/ca-given-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/ca-given-imports.md b/_overviews/scala3-book/ca-given-imports.md index 2b5c0a6429..6cfb436a29 100644 --- a/_overviews/scala3-book/ca-given-imports.md +++ b/_overviews/scala3-book/ca-given-imports.md @@ -14,7 +14,7 @@ The basic form is shown in this example: ```scala object A: class TC - given tc as TC + given tc: TC = ??? def f(using TC) = ??? object B: From c3a58d34c576e4798bc141ac7967117a81331920 Mon Sep 17 00:00:00 2001 From: Altair-Bueno <67512202+Altair-Bueno@users.noreply.github.com> Date: Thu, 24 Jun 2021 19:30:21 +0200 Subject: [PATCH 0719/2265] Using Scala 2 If-else expression instead if () else syntax is from Scala 2. Use if then else instead or simplify it by removing the if-else expression. If-else is unnecessary --- _overviews/scala3-book/taste-objects.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_overviews/scala3-book/taste-objects.md b/_overviews/scala3-book/taste-objects.md index ae522627f1..5c27e3b8a9 100644 --- a/_overviews/scala3-book/taste-objects.md +++ b/_overviews/scala3-book/taste-objects.md @@ -27,8 +27,7 @@ For example, this `StringUtils` object contains a small collection of string-rel ```scala object StringUtils: - def isNullOrEmpty(s: String): Boolean = - if (s==null || s.trim.equals("")) true else false + def isNullOrEmpty(s: String): Boolean = s==null || s.trim.equals("") def leftTrim(s: String): String = s.replaceAll("^\\s+", "") def rightTrim(s: String): String = s.replaceAll("\\s+$", "") ``` From 662cf053d5c84f5e11650e4e6787b41ed34c4d08 Mon Sep 17 00:00:00 2001 From: Altair-Bueno <67512202+Altair-Bueno@users.noreply.github.com> Date: Fri, 25 Jun 2021 11:28:03 +0200 Subject: [PATCH 0720/2265] Added @SethTisue suggestion --- _overviews/scala3-book/taste-objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/taste-objects.md b/_overviews/scala3-book/taste-objects.md index 5c27e3b8a9..6e33d8fd55 100644 --- a/_overviews/scala3-book/taste-objects.md +++ b/_overviews/scala3-book/taste-objects.md @@ -27,7 +27,7 @@ For example, this `StringUtils` object contains a small collection of string-rel ```scala object StringUtils: - def isNullOrEmpty(s: String): Boolean = s==null || s.trim.equals("") + def isNullOrEmpty(s: String): Boolean = s==null || s.trim == "" def leftTrim(s: String): String = s.replaceAll("^\\s+", "") def rightTrim(s: String): String = s.replaceAll("\\s+$", "") ``` From 430252a1766eb0062784ad992d78eec516965b27 Mon Sep 17 00:00:00 2001 From: Altair-Bueno <67512202+Altair-Bueno@users.noreply.github.com> Date: Fri, 25 Jun 2021 11:29:44 +0200 Subject: [PATCH 0721/2265] Update taste-objects.md --- _overviews/scala3-book/taste-objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/taste-objects.md b/_overviews/scala3-book/taste-objects.md index 6e33d8fd55..2e6d1428ca 100644 --- a/_overviews/scala3-book/taste-objects.md +++ b/_overviews/scala3-book/taste-objects.md @@ -27,7 +27,7 @@ For example, this `StringUtils` object contains a small collection of string-rel ```scala object StringUtils: - def isNullOrEmpty(s: String): Boolean = s==null || s.trim == "" + def isNullOrEmpty(s: String): Boolean = s==null || s.trim.isEmpty def leftTrim(s: String): String = s.replaceAll("^\\s+", "") def rightTrim(s: String): String = s.replaceAll("\\s+$", "") ``` From f8b8af443956c64769a7577ed0882b182ec8d87e Mon Sep 17 00:00:00 2001 From: Altair-Bueno <67512202+Altair-Bueno@users.noreply.github.com> Date: Fri, 25 Jun 2021 13:06:17 +0200 Subject: [PATCH 0722/2265] Found another Scala 2 `isNullOrEmpty` --- _overviews/scala3-book/domain-modeling-tools.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_overviews/scala3-book/domain-modeling-tools.md b/_overviews/scala3-book/domain-modeling-tools.md index b8fd76f2fc..f59c39c8af 100644 --- a/_overviews/scala3-book/domain-modeling-tools.md +++ b/_overviews/scala3-book/domain-modeling-tools.md @@ -219,8 +219,7 @@ Here’s an example of a “string utilities” object that contains a set of me object StringUtils: def truncate(s: String, length: Int): String = s.take(length) def containsWhitespace(s: String): Boolean = s.matches(".*\\s.*") - def isNullOrEmpty(s: String): Boolean = - if s == null || s.trim.equals("") then true else false + def isNullOrEmpty(s: String): Boolean = s==null || s.trim.isEmpty ``` We can use the object as follows: From cb136c0b509d438348c6e9737eb0fb55a7d119fe Mon Sep 17 00:00:00 2001 From: Jentsch Date: Sat, 26 Jun 2021 11:52:38 +0200 Subject: [PATCH 0723/2265] Fix docker port in Readme.md docker-compose.yml:7 exposes the port on 4000 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eef762ce16..8b3d557025 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ To build and view site with docker: docker-compose up -It will incrementally build and serve site at `http://localhost:8080` +It will incrementally build and serve site at `http://localhost:4000` ## Contributing ## From 904fdf7d95ce146f37c1ab1ee37c0ecf41917916 Mon Sep 17 00:00:00 2001 From: Genghis Yang Date: Sat, 26 Jun 2021 19:56:02 +0800 Subject: [PATCH 0724/2265] Fix a typo in Domain Modeling / Tools I believe `have also have` is not grammatical. Should be `also have` --- _overviews/scala3-book/domain-modeling-tools.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/domain-modeling-tools.md b/_overviews/scala3-book/domain-modeling-tools.md index b8fd76f2fc..e994551aff 100644 --- a/_overviews/scala3-book/domain-modeling-tools.md +++ b/_overviews/scala3-book/domain-modeling-tools.md @@ -66,7 +66,7 @@ p.vocation = "Musician" ### Fields and methods -Classes can have also have methods and additional fields that are not part of constructors. +Classes can also have methods and additional fields that are not part of constructors. They are defined in the body of the class. The body is initialized as part of the default constructor: From 4d0e5d3baae763f96046c2d7ad5b8a6d4658c165 Mon Sep 17 00:00:00 2001 From: Genghis Yang Date: Sat, 26 Jun 2021 21:18:08 +0800 Subject: [PATCH 0725/2265] Fix a typo in scala 3 book domain modeling fp Just a typo --- _overviews/scala3-book/domain-modeling-fp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/domain-modeling-fp.md b/_overviews/scala3-book/domain-modeling-fp.md index dec7dda6d2..9d1c163864 100644 --- a/_overviews/scala3-book/domain-modeling-fp.md +++ b/_overviews/scala3-book/domain-modeling-fp.md @@ -259,7 +259,7 @@ Pizza.price(pizza1) Grouping functionality this way has a few advantages: - It associates functionality with data and makes it easier to find for programmers (and the compiler). -- It creates a namespace and for instance let's us use `price` as a method name without having to rely on overloading. +- It creates a namespace and for instance let's use `price` as a method name without having to rely on overloading. - The implementation of `Topping.price` can access enumeration values like `Cheese` without having to import them. However, there are also a few tradeoffs that should be considered: From 8bd14057ecc07ae2b9c82ba0acc228812e9b7dc3 Mon Sep 17 00:00:00 2001 From: Mario Galic Date: Sat, 10 Apr 2021 19:07:47 +0100 Subject: [PATCH 0726/2265] Conversion Between Option and the Collections - Clarify if Option is considered a collection by summarising discussion at Make Option extend IterableOnce #8038 - Document implicit conversion option2iterable --- ...sion-between-option-and-the-collections.md | 53 +++++++++++++++++++ ...ions-between-java-and-scala-collections.md | 1 + 2 files changed, 54 insertions(+) create mode 100644 _overviews/collections-2.13/conversion-between-option-and-the-collections.md diff --git a/_overviews/collections-2.13/conversion-between-option-and-the-collections.md b/_overviews/collections-2.13/conversion-between-option-and-the-collections.md new file mode 100644 index 0000000000..7fff2ea548 --- /dev/null +++ b/_overviews/collections-2.13/conversion-between-option-and-the-collections.md @@ -0,0 +1,53 @@ +--- +layout: multipage-overview +title: Conversion Between Option and the Collections +partof: collections-213 +overview-name: Collections + +num: 18 +previous-page: conversions-between-java-and-scala-collections + +permalink: /overviews/collections-2.13/:title.html +--- +`Option` can be seen as a collection that has zero or exactly one element, and it provides a degree of interoperability with the collection types found in the package `scala.collection`. In particular, it implements the interface `IterableOnce`, which models the simplest form of collections: something that can be iterated over, at least once. However, `Option` does not implement the more comprehensive interface of `Iterable`. Indeed, we cannot provide a sensible implementation for the operation [`fromSpecific`](https://github.com/scala/scala/blob/6c68c2825e893bb71d6dc78465ac8c6f415cbd93/src/library/scala/collection/Iterable.scala#L173), which is supposed to create an `Option` from a collection of possibly more than one element. Starting from [Scala 2.13](https://github.com/scala/scala/pull/8038), `Option` was made an `IterableOnce` but not an `Iterable`. + +Hence `Option` can be used everywhere an `IterableOnce` is expected, for example, when calling `flatMap` on a collection (or inside a for-comprehension) + +```scala mdoc +for { + a <- Set(1) + b <- Option(41) +} yield (a + b) +// : Set[Int] = Set(42) +``` + +since the operation `flatMap` on the type `Set[Int]` takes a function returning an `IterableOnce`: + +``` +def flatMap[B](f: Int => IterableOnce[B]): Set[B] +``` + +Although `Option` does not extend `Iterable`, there exists an [implicit conversion](https://github.com/scala/scala/blob/6c68c2825e893bb71d6dc78465ac8c6f415cbd93/src/library/scala/Option.scala#L19) between `Option` and `Iterable` + + +``` +implicit def option2Iterable[A](xo: Option[A]): Iterable[A] +``` + +so although `Option[A]` is not a full collection it can be _viewed_ as one. For example, + +```scala mdoc +Some(42).drop(1) +// : Iterable[Int] = List() +``` + +expands to + +```scala mdoc +Option.option2Iterable(Some(42)).drop(1) +// : Iterable[Int] = List() +``` + +because `drop` is not defined on `Option`. A downside of the above implicit conversion is that instead of getting back an `Option[A]` we are left with an `Iterable[A]`. For this reason, `Option`’s documentation carries the following note: + +> Many of the methods in `Option` are duplicative with those in the `Iterable` hierarchy, but they are duplicated for a reason: the implicit conversion tends to leave one with an `Iterable` in situations where one could have retained an `Option`. diff --git a/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md b/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md index 86070db314..b4090053ba 100644 --- a/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md +++ b/_overviews/collections-2.13/conversions-between-java-and-scala-collections.md @@ -6,6 +6,7 @@ overview-name: Collections num: 17 previous-page: creating-collections-from-scratch +next-page: conversion-between-option-and-the-collections languages: [ru] permalink: /overviews/collections-2.13/:title.html From 824a0ab96c40c373fa2b4372098cfe079c696e0b Mon Sep 17 00:00:00 2001 From: Genghis Yang Date: Mon, 28 Jun 2021 16:13:54 +0800 Subject: [PATCH 0727/2265] Fix typo --- _overviews/scala3-book/domain-modeling-fp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/domain-modeling-fp.md b/_overviews/scala3-book/domain-modeling-fp.md index 9d1c163864..31e5d19008 100644 --- a/_overviews/scala3-book/domain-modeling-fp.md +++ b/_overviews/scala3-book/domain-modeling-fp.md @@ -259,7 +259,7 @@ Pizza.price(pizza1) Grouping functionality this way has a few advantages: - It associates functionality with data and makes it easier to find for programmers (and the compiler). -- It creates a namespace and for instance let's use `price` as a method name without having to rely on overloading. +- It creates a namespace and for instance lets us use `price` as a method name without having to rely on overloading. - The implementation of `Topping.price` can access enumeration values like `Cheese` without having to import them. However, there are also a few tradeoffs that should be considered: From 923bb72a713bef577cde546368a30c4a1e2d59d9 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 21 Jun 2021 15:01:12 +0200 Subject: [PATCH 0728/2265] Suggestions on the Scala 3 book (part 5) --- _overviews/scala3-book/concurrency.md | 63 ++++++++----- .../scala3-book/interacting-with-java.md | 11 ++- _overviews/scala3-book/scala-for-java-devs.md | 23 +++-- .../scala3-book/scala-for-javascript-devs.md | 7 +- .../scala3-book/scala-for-python-devs.md | 34 ++++--- _overviews/scala3-book/scala-tools.md | 89 +++++++++++++------ 6 files changed, 139 insertions(+), 88 deletions(-) diff --git a/_overviews/scala3-book/concurrency.md b/_overviews/scala3-book/concurrency.md index 59b86b0815..bda65f21a9 100644 --- a/_overviews/scala3-book/concurrency.md +++ b/_overviews/scala3-book/concurrency.md @@ -55,7 +55,8 @@ You’ll also see examples of methods that are used to handle the value in a fut > When you think about futures, it’s important to know that they’re intended as a one-shot, “Handle this relatively slow computation on some other thread, and call me back with a result when you’re done” construct. > As a point of contrast, [Akka](https://akka.io) actors are intended to run for a long time and respond to many requests during their lifetime. -> While an actor may live forever, a future is intended to be run only once. +> While an actor may live forever, a future eventually contains the result +> of a computation that ran only once. @@ -77,7 +78,7 @@ Now you’re ready to create a future. For this example, first define a long-running, single-threaded algorithm: ```scala -def longRunningAlgorithm = +def longRunningAlgorithm() = Thread.sleep(10_000) 42 ``` @@ -86,29 +87,29 @@ That fancy algorithm returns the integer value `42` after a ten second delay. Now call that algorithm by wrapping it into the `Future` constructor, and assigning the result to a variable: ```scala -scala> val f = Future(longRunningAlgorithm) -f: scala.concurrent.Future[Int] = Future() +scala> val eventualInt = Future(longRunningAlgorithm()) +eventualInt: scala.concurrent.Future[Int] = Future() ``` -Right away your future begins running. -If you immediately check the value of the variable `f`, you see that the future hasn’t completed yet: +Right away, your computation---the call to `longRunningAlgorithm()`---begins running. +If you immediately check the value of the variable `eventualInt`, you see that the future hasn’t been completed yet: ```scala -scala> f +scala> eventualInt val res1: scala.concurrent.Future[Int] = Future() ``` -But if you check again after ten seconds, you’ll see that it completes successfully: +But if you check again after ten seconds, you’ll see that it is completed successfully: ```scala -scala> f +scala> eventualInt val res2: scala.concurrent.Future[Int] = Future(Success(42)) ``` While that’s a relatively simple example, it shows the basic approach: Just construct a new `Future` with your long-running algorithm. One thing to notice is that the `42` you expected is wrapped in a `Success`, which is further wrapped in a `Future`. -This is a key concept to understand: the value in a `Future` is always an instance of one of the *scala.util.Try* types: `Success` or `Failure`. +This is a key concept to understand: the value in a `Future` is always an instance of one of the `scala.util.Try` types: `Success` or `Failure`. Therefore, when you work with the result of a future, you use the usual `Try`-handling techniques. @@ -118,7 +119,7 @@ Therefore, when you work with the result of a future, you use the usual `Try`-ha This is what the result looks like when you call `map` right after creating the variable `f`: ```scala -scala> val a = f.map(_ * 2) +scala> val a = eventualInt.map(_ * 2) a: scala.concurrent.Future[Int] = Future() ``` @@ -139,13 +140,13 @@ In addition to higher-order functions like `map`, you can also use callback meth One commonly used callback method is `onComplete`, which takes a *partial function* in which you handle the `Success` and `Failure` cases: ```scala -f.onComplete { +eventualInt.onComplete { case Success(value) => println(s"Got the callback, value = $value") case Failure(e) => e.printStackTrace } ``` -When you paste that code in the REPL you’ll see the result: +When you paste that code in the REPL you’ll eventually see the result: ```scala Got the callback, value = 42 @@ -180,10 +181,11 @@ See the [Futures and Promises][futures] page for a discussion of additional meth ## Running multiple futures and joining their results -To run multiple futures in parallel and join their results when all of the futures complete, use a `for` expression. +To run multiple computations in parallel and join their results when all of the futures have been completed, use a `for` expression. + The correct approach is: -1. Create the futures +1. Start the computations that return `Future` results 2. Merge their results in a `for` expression 3. Extract the merged result using `onComplete` or a similar technique @@ -191,27 +193,27 @@ The correct approach is: ### An example The three steps of the correct approach are shown in the following example. -A key is that you first create the futures and then join them in the `for` expression: +A key is that you first start the computations that return futures, and then join them in the `for` expression: ```scala import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import scala.util.{Failure, Success} -val startTime = System.currentTimeMillis -def delta() = System.currentTimeMillis - startTime +val startTime = System.currentTimeMillis() +def delta() = System.currentTimeMillis() - startTime def sleep(millis: Long) = Thread.sleep(millis) @main def multipleFutures1 = println(s"creating the futures: ${delta()}") - // (1) create the futures + // (1) start the computations that return futures val f1 = Future { sleep(800); 1 } // eventually returns 1 val f2 = Future { sleep(200); 2 } // eventually returns 2 val f3 = Future { sleep(400); 3 } // eventually returns 3 - // (2) run them simultaneously in a `for` expression + // (2) join the futures in a `for` expression val result = for r1 <- f1 @@ -251,10 +253,23 @@ All of that code is run on the JVM’s main thread. Then, at 806 ms, the three futures complete and the code in the `yield` block is run. Then the code immediately goes to the `Success` case in the `onComplete` method. -The 806 ms output is a key to seeing that the three futures are run in parallel. -If they were run sequentially, the total time would be about 1,400 ms---the sum of the sleep times of the three futures. -But because they’re run in parallel, the total time is just slightly longer than the longest-running future: `f1`, which is 800 ms. - +The 806 ms output is a key to seeing that the three computations are run in parallel. +If they were run sequentially, the total time would be about 1,400 ms---the sum of the sleep times of the three computations. +But because they’re run in parallel, the total time is just slightly longer than the longest-running computation: `f1`, which is 800 ms. + +> Notice that if the computations were run within the `for` expression, they +> would be executed sequentially, not in parallel: +> ~~~ +> // Sequential execution (no parallelism!) +> for +> r1 <- Future { sleep(800); 1 } +> r2 <- Future { sleep(200); 2 } +> r3 <- Future { sleep(400); 3 } +> yield +> r1 + r2 + r3 +> ~~~ +> So, if you want the computations to be possibly run in parallel, remember +> to run them outside of the `for` expression. ### A method that returns a future diff --git a/_overviews/scala3-book/interacting-with-java.md b/_overviews/scala3-book/interacting-with-java.md index 36ceb7fe58..8ccb38e156 100644 --- a/_overviews/scala3-book/interacting-with-java.md +++ b/_overviews/scala3-book/interacting-with-java.md @@ -58,9 +58,8 @@ You can convert that Java list to a Scala `Seq`, using the conversion utilities ```scala // scala import scala.jdk.CollectionConverters.* -import java.util.List -def testList = +def testList() = println("Using a Java List in Scala") val javaList: java.util.List[String] = JavaClass.getStrings() val scalaSeq: Seq[String] = javaList.asScala.toSeq @@ -156,7 +155,7 @@ class Dog extends Animal, Wagging, Running: ## How to use Scala collections in Java -When you need to use a Scala collection class in your Java code, use the methods of Scala’s _scala.jdk.javaapi.CollectionConverters_ object in your Java code to make the conversions work. +When you need to use a Scala collection class in your Java code, use the methods of Scala’s `scala.jdk.javaapi.CollectionConverters` object in your Java code to make the conversions work. For example, if you have a `List[String]` like this in a Scala class: ```scala @@ -192,7 +191,7 @@ Here are a few things to notice in that code: ## How to use Scala `Option` in Java -When you need to use a Scala `Option` in your Java code, you can convert the `Option` to a Java `Optional` value using the `toJava` method of the Scala _scala.jdk.javaapi.OptionConverters_ object. +When you need to use a Scala `Option` in your Java code, you can convert the `Option` to a Java `Optional` value using the `toJava` method of the Scala `scala.jdk.javaapi.OptionConverters` object. To demonstrate this, create a Scala class with two `Option[String]` values, one containing a string and the other one empty: @@ -203,7 +202,7 @@ object ScalaObject: val noneString: Option[String] = None ``` -Then in your Java code, convert those `Option[String]` values into `java.util.Optional[String]` using the `toJava` method from the _scala.jdk.javaapi.OptionConverters_ object: +Then in your Java code, convert those `Option[String]` values into `java.util.Optional[String]` using the `toJava` method from the `scala.jdk.javaapi.OptionConverters` object: ```java // java @@ -258,7 +257,7 @@ System.out.println(jm.multiply(3,4)); // 12 ## How to handle Scala methods that throw exceptions in Java code When you’re writing Scala code using Scala programming idioms, you’ll never write a method that throws an exception. -But if for some reason you have a Scala method that does throw an exception, and you want Java developers to be able to use that method, add the `@throws` annotation to your Scala method so Java consumers will know the exceptions they can throw. +But if for some reason you have a Scala method that does throw an exception, and you want Java developers to be able to use that method, add the `@throws` annotation to your Scala method so Java consumers will know the exceptions it can throw. For example, this Scala `exceptionThrower` method is annotated to declare that it throws an `Exception`: diff --git a/_overviews/scala3-book/scala-for-java-devs.md b/_overviews/scala3-book/scala-for-java-devs.md index 50d1777677..be54f5fd25 100644 --- a/_overviews/scala3-book/scala-for-java-devs.md +++ b/_overviews/scala3-book/scala-for-java-devs.md @@ -49,6 +49,7 @@ Also at a high level, the differences between Java and Scala are: - Scala has a full suite of immutable collections, including `List`, `Vector`, and immutable `Map` and `Set` implementations - Everything in Scala is an _expression_: constructs like `if` statements, `for` loops, `match` expressions, and even `try`/`catch` expressions all have return values - Scala idioms favor immutability by default: you’re encouraged to use immutable (`final`) variables and immutable collections +- Idiomatic Scala code does not use `null`, and thus does not suffer from `NullPointerException` - The Scala ecosystem has other [build tools][tools] in sbt, Mill, and others - In addition to running on the JVM, the [Scala.js](https://www.scala-js.org) project lets you use Scala as a JavaScript replacement - The [Scala Native](http://www.scala-native.org) project adds low-level constructs to let you write “systems” level code, and also compiles to native executables @@ -117,14 +118,18 @@ This section provides comparisons of features related to OOP-style classes and m ### OOP style class, primary constructor: +Scala doesn’t follow the JavaBeans standard, so instead of showing Java +code written in the JavaBeans style, here we show Java code that is +equivalent to the Scala code that follows it. + @@ -976,7 +981,7 @@ val a = Array("a", "b") as being backed by this Java `String[]`: ```scala -String[] a = ["a", "b"] +String[] a = ["a", "b"]; ``` However, a Scala `Array` also has all of the functional methods you expect in a Scala collection, including `map` and `filter`: @@ -1275,7 +1280,7 @@ For more information on dealing with errors and exceptions in Scala, see the [Fu That concludes are comparison of the Java and Scala languages. -Currently there are other concepts in Scala which currently have no equal in Java 11. +There are other concepts in Scala which currently have no equal in Java 11. This includes: - Everything related to Scala’s [contextual abstractions][contextual] diff --git a/_overviews/scala3-book/scala-for-javascript-devs.md b/_overviews/scala3-book/scala-for-javascript-devs.md index 0237e0d63c..a577837e56 100644 --- a/_overviews/scala3-book/scala-for-javascript-devs.md +++ b/_overviews/scala3-book/scala-for-javascript-devs.md @@ -36,7 +36,7 @@ At a high level, Scala shares these similarities with JavaScript: - Both languages have similar `if` statements, `while` loops, and `for` loops - Starting [at this Scala.js page](https://www.scala-js.org/libraries/index.html), you’ll find dozens of libraries to support React, Angular, jQuery, and many other JavaScript and Scala libraries - JavaScript objects are mutable; Scala objects _can_ be mutable when writing in an imperative style -- Both JavaScript and Scala support _promises_ as a way of running asynchronous computations ([Scala concurrency][concurrency] uses futures and promises) +- Both JavaScript and Scala support _promises_ as a way of handling the result of asynchronous computations ([Scala concurrency][concurrency] uses futures and promises) ### High-level differences @@ -441,7 +441,7 @@ In both JavaScript and Scala, functions are objects, so their functionality is s @@ -474,7 +474,7 @@ In both JavaScript and Scala, functions are objects, so their functionality is s
    class Person { -
      private String firstName; -
      private String lastName; -
      private int age; +
      public String firstName; +
      public String lastName; +
      public int age;
      public Person(
        String firstName,
        String lastName, int age @@ -160,9 +165,9 @@ This section provides comparisons of features related to OOP-style classes and m
    public class Person { -
      private String firstName; -
      private String lastName; -
      private int age; +
      public String firstName; +
      public String lastName; +
      public int age;

      // primary constructor
      public Person( @@ -424,7 +429,7 @@ This section compares Java interfaces to Scala traits, including how classes ext
    - class Dog extends Animal, HasLegs, HasTail + class Dog extends Animal implements HasLegs, HasTail
    - // technically this is a “method,” not a function + // technically this is a method, not a function
    def add(a: Int, b: Int) = a + b
    add(2, 2)   // 4
    In Scala, showing the `Int` return type is optional. -It’s _not_ shown in the `add` example and _is_ shown in the `addThenDouble` example, so you can see both approaches. +It’s _not_ shown in the `add` example and _is_ shown in the `addAndDouble` example, so you can see both approaches. @@ -1374,4 +1374,3 @@ There are other concepts in Scala which currently have no equivalent in JavaScri [union-types]: {% link _overviews/scala3-book/types-union.md %} - diff --git a/_overviews/scala3-book/scala-for-python-devs.md b/_overviews/scala3-book/scala-for-python-devs.md index 0934989d4e..395d7c450d 100644 --- a/_overviews/scala3-book/scala-for-python-devs.md +++ b/_overviews/scala3-book/scala-for-python-devs.md @@ -230,7 +230,7 @@ These examples demonstrate how to create variables in Python and Scala. -If a Scala field is going to be mutable, use `var` instead of `val` for variable assignment: +If a Scala field is going to be mutable, use `var` instead of `val` for variable definition: ```scala var x = 1 @@ -631,18 +631,14 @@ Scala also has `match` expressions. - x = [i*10 for i in range(1,4)] -
    # x: [10,20,30]
    + xs = [i * 10 for i in range(1, 4)] +
    # xs: [10,20,30]
    - val x = -
      for -
        i <- 1 to 3 -
      yield -
        i * 10 -
    // x: Vector(10, 20, 30)
    + val xs = for i <- 1 to 3 yield i * 10 +
    // xs: Vector(10, 20, 30)
    @@ -894,9 +890,7 @@ However, the default Scala map is _immutable_, and has a number of transformatio - for -
      (key,value) <- myMap -
    do + for (key,value) <- myMap do
      println(key)
      println(value)
    @@ -934,7 +928,7 @@ The Python set is similar to the _mutable_ Scala `Set` class. set = {1,2,1} -
    # set: {1,2}
    +
    # set: {1,2}
    @@ -1012,7 +1006,7 @@ Those lists are used in the following table, that shows how to apply mapping and - x = [i*10 for i in numbers] + x = [i * 10 for i in numbers] @@ -1034,7 +1028,9 @@ Those lists are used in the following table, that shows how to apply mapping and - val evens = numbers.filter(_ % 2 == 0) + val evens = numbers.filter(_ % 2 == 0) +
    // or +
    val evens = for i <- numbers if i % 2 == 0 yield i
    @@ -1051,8 +1047,9 @@ Those lists are used in the following table, that shows how to apply mapping and - val x = numbers.filter(_ % 2 == 0) -
              .map(_ * 10)
    + val x = numbers.filter(_ % 2 == 0).map(_ * 10) +
    // or +
    val x = for i <- numbers if i % 2 == 0 yield i * 10
    @@ -1064,8 +1061,7 @@ Those lists are used in the following table, that shows how to apply mapping and - def times_10(n): return n * 10 -
    x = map(lambda x: x * 10, numbers)
    + x = map(lambda x: x * 10, numbers) diff --git a/_overviews/scala3-book/scala-tools.md b/_overviews/scala3-book/scala-tools.md index 81f7177515..75bb1f2c0d 100644 --- a/_overviews/scala3-book/scala-tools.md +++ b/_overviews/scala3-book/scala-tools.md @@ -22,7 +22,7 @@ We’ll start by showing how to use sbt to build your Scala projects, and then w ## Building Scala projects with sbt You can use several different tools to build your Scala projects, including Ant, Maven, Gradle, Mill, and more. -But a tool named _sbt_ was the first build tool that was specifically created for Scala, and these days it’s supported by [Lightbend](https://www.lightbend.com), the company that also maintains [Akka](https://akka.io), the [Play framework](https://www.playframework.com), the [Lagom framework](https://www.lagomframework.com), and more. +But a tool named _sbt_ was the first build tool that was specifically created for Scala. > To install sbt, see [its download page](https://www.scala-sbt.org/download.html) or our [Getting Started][getting_started] page. @@ -38,7 +38,20 @@ $ mkdir hello $ cd hello ``` -Then create a file named _build.sbt_ that contains this line: +In the directory `hello`, create a subdirectory `project`: + +```bash +$ mkdir project +``` + +Create a file named _build.properties_ in the directory `project`, with +the following content: + +```text +sbt.version=1.5.4 +``` + +Then create a file named _build.sbt_ in the project root directory that contains this line: ```scala scalaVersion := "{{ site.scala-3-version }}" @@ -51,6 +64,18 @@ Now create a file named something like _Hello.scala_---the first part of the nam ``` That’s all you have to do. + +You should have a project structure like the following: + +~~~ bash +$ tree +. +├── build.sbt +├── Hello.scala +└── project + └── build.properties +~~~ + Now run the project with this `sbt` command: ```bash @@ -61,7 +86,7 @@ You should see output that looks like this, including the `"Hello, world"` from ```bash $ sbt run -[info] welcome to sbt 1.4.4 (AdoptOpenJDK Java 11.x) +[info] welcome to sbt 1.5.4 (AdoptOpenJDK Java 11.x) [info] loading project definition from project ... [info] loading settings for project from build.sbt ... [info] compiling 1 Scala source to target/scala-3.0.0/classes ... @@ -70,7 +95,9 @@ Hello, world [success] Total time: 2 s ``` -When you look at your directory, you’ll see that sbt has created two directories named _project_ and _target_. +The sbt launcher---the `sbt` command-line tool---loads the version of sbt set in the file _project/build.properties_, which loads the version of the Scala compiler set in the file _build.sbt_, compiles the code in the file _Hello.scala_, and runs the resulting bytecode. + +When you look at your directory, you’ll see that sbt has a directory named _target_. These are working directories that sbt uses. As you can see, creating and running a little Scala project with sbt takes just a few simple steps. @@ -92,31 +119,34 @@ A nice benefit of that is that once you’re comfortable with its structure, it The first thing to know is that underneath the root directory of your project, sbt expects a directory structure that looks like this: -```bash -build.sbt -project/ -src/ --- main/ - |-- java/ - |-- resources/ - |-- scala/ -|-- test/ - |-- java/ - |-- resources/ - |-- scala/ -target/ +```text +. +├── build.sbt +├── project/ +│ └── build.properties +├── src/ +│ ├── main/ +│ │ ├── java/ +│ │ ├── resources/ +│ │ └── scala/ +│ └── test/ +│ ├── java/ +│ ├── resources/ +│ └── scala/ +└── target/ ``` You can also add a _lib_ directory under the root directory if you want to add unmanaged dependencies---JAR files---to your project. If you’re going to create a project that has Scala source code files and tests, but won’t be using any Java source code files, and doesn’t need any “resources”---such as embedded images, configuration files, etc.---this is all you really need under the _src_ directory: -```bash -src/ --- main/ - |-- scala/ -|-- test/ - |-- scala/ +```text +. +└── src/ + ├── main/ + │ └── scala/ + └── test/ + └── scala/ ``` @@ -284,11 +314,18 @@ As with the previous lesson, create an sbt project directory structure for a pro $ mkdir HelloScalaTest $ cd HelloScalaTest $ mkdir -p src/{main,test}/scala -$ mkdir project target +$ mkdir project ``` -### Creating the build.sbt file +### Creating the build.properties and build.sbt files + +Next, create a _build.properties_ file in the _project/_ subdirectory of your project +with this line: + +```text +sbt.version=1.5.4 +``` Next, create a _build.sbt_ file in the root directory of your project with these contents: @@ -298,7 +335,7 @@ version := "0.1" scalaVersion := "{{site.scala-3-version}}" libraryDependencies ++= Seq( - "org.scalatest" %% "scalatest" % "3.3.0-SNAP3" % Test + "org.scalatest" %% "scalatest" % "3.2.9" % Test ) ``` From 512f89eb3fbdd80305d56e186f3775a7c49621ce Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 Jun 2021 17:30:19 +0200 Subject: [PATCH 0729/2265] Clarify the recommended learning path via the MOOCs --- learn.md | 16 ++++++++++++++++ resources/images/learning-path.png | Bin 0 -> 42763 bytes 2 files changed, 16 insertions(+) create mode 100644 resources/images/learning-path.png diff --git a/learn.md b/learn.md index 19af2b78c9..797f193e3e 100644 --- a/learn.md +++ b/learn.md @@ -36,6 +36,8 @@ this course in the following video: +This course is also a good way to upgrade your Scala 2 knowledge to Scala 3. + After taking this course, you might be interested in improving your skills in specific areas by taking the courses [Parallel Programming], [Big Data Analysis with Scala and Spark], or [Programming Reactive Systems]. @@ -61,6 +63,20 @@ and Spark. teaches how to write responsive, scalable, and resilient systems with the library Akka. +### Scala Learning Path + +The diagram below summarizes the possible learning paths with our courses: + +![](/resources/images/learning-path.png) + +The “foundational” courses target programmers with no prior experience in Scala, whereas the “deepening” +courses aim at strengthening Scala programmers skills in a specific domain (such as parallel programming). + +We recommend starting with either Effective Programming in Scala, or Functional Programming Principles in +Scala followed by Functional Program Design. Then, you can complement your Scala skills by taking any +of the courses Programming Reactive Systems, Parallel Programming, or Big Data Analysis with Scala and Spark. +In case you take the Scala Specialization, you will end with the Scala Capstone Project. + ### Scala 2 Courses The above courses use Scala 3 (except the Spark courses). If needed, you can find diff --git a/resources/images/learning-path.png b/resources/images/learning-path.png new file mode 100644 index 0000000000000000000000000000000000000000..43e9d09631651ea12fc71a3cd9707a9f97e05da8 GIT binary patch literal 42763 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 Date: Mon, 28 Jun 2021 10:07:30 -0700 Subject: [PATCH 0730/2265] FAQ: Who's behind Scala? --- _overviews/FAQ/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index ba0cce896d..1bf9ea5b7a 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -58,6 +58,10 @@ This is addressed on our [Community page](https://scala-lang.org/community/#scal In short, the only officially sanctioned place is the [scala/job-board room on Gitter](https://gitter.im/scala/job-board). +### Who's behind Scala? + +This is answered [on the community page](https://www.scala-lang.org/community/#whos-behind-scala). + ### Can I use the Scala logo? See [scala/scala-lang#1040](https://github.com/scala/scala-lang/issues/1040). From 9ffe4b9aff6443d9e789a89bf2c84a62be7a55e7 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 30 Jun 2021 11:18:07 +0200 Subject: [PATCH 0731/2265] Merge https://github.com/lampepfl/dotty/blob/master/docs/docs/usage/getting-started.md here MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The part about scastie was already mentioned in our scala3/getting-started.md page - Copied the part about the giter8 templates into the Scala 3 book, - IDE support was covered in our getting-started page - Skipped “Standalone installation”, since the recommended way to install Scala 3 is to use `cs` - “Scala 3 for scripting” was already covered by scala3/book/taste-hello-world.md --- _overviews/scala3-book/scala-tools.md | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/_overviews/scala3-book/scala-tools.md b/_overviews/scala3-book/scala-tools.md index 75bb1f2c0d..bffe1791dd 100644 --- a/_overviews/scala3-book/scala-tools.md +++ b/_overviews/scala3-book/scala-tools.md @@ -269,6 +269,42 @@ There, that’s much faster. If you type `help` at the sbt command prompt you’ll see a list of other commands you can run. But for now, just type `exit` (or press `CTRL-D`) to leave the sbt shell. +### Using project templates + +Manually creating the project structure can be tedious. Thankfully, sbt can create it for you, +based on a template. + +To create a Scala 3 project from a template, run the following command in a shell: + +~~~ +$ sbt new scala/scala3.g8 +~~~ + +Sbt will load the template, ask some questions, and create the project files in a subdirectory: + +~~~ +$ tree scala-3-project-template +scala-3-project-template +├── build.sbt +├── project +│ └── build.properties +├── README.md +└── src + ├── main + │ └── scala + │ └── Main.scala + └── test + └── scala + └── Test1.scala +~~~ + +> If you want to create a Scala 3 project that cross-compiles with Scala 2, use the template `scala/scala3-cross.g8`: +> +> ~~~ +> $ sbt new scala/scala3-cross.g8 +> ~~~ + +Learn more about `sbt new` and project templates in the [documentation of sbt](https://www.scala-sbt.org/1.x/docs/sbt-new-and-Templates.html#sbt+new+and+Templates). ### Other build tools for Scala From 446a51fb7d8b4f907f2325d1a5cc3affcdc1790f Mon Sep 17 00:00:00 2001 From: Nate Black Date: Wed, 30 Jun 2021 08:31:25 -0400 Subject: [PATCH 0732/2265] Removed 'do' line from the Scala 2 while section --- _overviews/scala3-book/taste-control-structures.md | 1 - 1 file changed, 1 deletion(-) diff --git a/_overviews/scala3-book/taste-control-structures.md b/_overviews/scala3-book/taste-control-structures.md index 5c30f73da4..520453481f 100644 --- a/_overviews/scala3-book/taste-control-structures.md +++ b/_overviews/scala3-book/taste-control-structures.md @@ -239,7 +239,6 @@ In Scala 2, the syntax was a bit different. The condition was surrounded by pare there was no `do` keyword: ```scala -while (x >= 0) do x = f(x) while (x >= 0) { x = f(x) } ``` From 9b8c42b8498c3f55d0d2ffcec9c8c02b0c3d4866 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 30 Jun 2021 15:06:16 +0200 Subject: [PATCH 0733/2265] Merge https://github.com/lampepfl/dotty/blob/master/docs/docs/usage/ide-support.md here MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Only added a mention of BSP - Skipped instructions in “importing the project using BSP using IntelliJ” because they are not working --- scala3/getting-started.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scala3/getting-started.md b/scala3/getting-started.md index b24836f764..c888285fb3 100644 --- a/scala3/getting-started.md +++ b/scala3/getting-started.md @@ -117,8 +117,9 @@ They both offer rich IDE features, but you can still use [many other editors.](h When prompted to do so, select _Import build_. >[Metals](https://scalameta.org/metals) is a “Scala language server” that provides support for writing Scala code in VS Code and other editors like [Atom, Sublime Text, and more](https://scalameta.org/metals/docs/editors/overview.html), using the Language Server Protocol. -(For details on how Metals works, see, [“Write Scala in VS Code, Vim, Emacs, Atom and Sublime Text with Metals”](https://www.scala-lang.org/2019/04/16/metals.html).) - +> +> Under the hood, Metals communicates with the build tool by using +> the [Build Server Protocol (BSP)](https://build-server-protocol.github.io/). For details on how Metals works, see, [“Write Scala in VS Code, Vim, Emacs, Atom and Sublime Text with Metals”](https://www.scala-lang.org/2019/04/16/metals.html). ### View the source code From 3d941d96c703c12d4c8732ae5306530b5c7239d5 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Jun 2021 15:17:52 +0200 Subject: [PATCH 0734/2265] Fix page number --- _overviews/scala3-migration/external-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/external-resources.md b/_overviews/scala3-migration/external-resources.md index 77a65829b2..4915537176 100644 --- a/_overviews/scala3-migration/external-resources.md +++ b/_overviews/scala3-migration/external-resources.md @@ -2,7 +2,7 @@ title: External Resources type: section description: This section lists external resources about the migration to Scala 3. -num: 26 +num: 27 previous-page: plugin-kind-projector next-page: --- From 01b5a7cfff1ae96a9c2b9d1918df4f9e66fc2b5c Mon Sep 17 00:00:00 2001 From: Adrian Theodorescu Date: Sat, 3 Jul 2021 13:49:48 -0500 Subject: [PATCH 0735/2265] Fix typo in overviews/scala-book/scala-build-tool-sbt --- _overviews/scala-book/scala-build-tool-sbt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala-book/scala-build-tool-sbt.md b/_overviews/scala-book/scala-build-tool-sbt.md index e798bc05d2..8986433976 100644 --- a/_overviews/scala-book/scala-build-tool-sbt.md +++ b/_overviews/scala-book/scala-build-tool-sbt.md @@ -156,7 +156,7 @@ If you type `help` at the sbt command prompt you’ll see a bunch of other comma ## See also -Here’s a list of other build tools you can use to build Scala projects are: +Here’s a list of other build tools you can use to build Scala projects: - [Ant](http://ant.apache.org/) - [Gradle](https://gradle.org/) From 1b0bd33313fa592a65bec9731a85d9425ebf4c56 Mon Sep 17 00:00:00 2001 From: Genghis Yang Date: Sun, 4 Jul 2021 17:26:13 +0800 Subject: [PATCH 0736/2265] Remove duplicated `a` --- _overviews/scala3-book/fp-functions-are-values.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/fp-functions-are-values.md b/_overviews/scala3-book/fp-functions-are-values.md index 0c8a1df792..d2766c65fe 100644 --- a/_overviews/scala3-book/fp-functions-are-values.md +++ b/_overviews/scala3-book/fp-functions-are-values.md @@ -37,7 +37,7 @@ val doubles = nums.filter(underFive).map(double) This ability to treat methods and functions as values is a powerful feature that functional programming languages provide. -> Technically, a a function that takes another function as an input parameter is known as a *Higher-Order Function*. +> Technically, a function that takes another function as an input parameter is known as a *Higher-Order Function*. > (If you like humor, as someone once wrote, that’s like saying that a class that takes an instance of another class as a constructor parameter is a Higher-Order Class.) From bf9f32e844c577d1d4ba55a5f7fe31ffd11a4300 Mon Sep 17 00:00:00 2001 From: Haythem Chagwey Date: Sun, 4 Jul 2021 10:48:27 +0100 Subject: [PATCH 0737/2265] Update the Type inference section's link --- _overviews/scala3-book/scala-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/scala-features.md b/_overviews/scala3-book/scala-features.md index f0c8efb129..606365a130 100644 --- a/_overviews/scala3-book/scala-features.md +++ b/_overviews/scala3-book/scala-features.md @@ -161,7 +161,7 @@ In that list: Scala’s type system enforces, at compile-time, that abstractions are used in a safe and coherent manner. In particular, the type system supports: -- [Type inference](/tour/type-inference.html) +- [Inferred types]({% link _overviews/scala3-book/types-inferred.md %}) - [Generic classes]({% link _overviews/scala3-book/types-generics.md %}) - [Variance annotations]({% link _overviews/scala3-book/types-variance.md %}) - [Upper](/tour/upper-type-bounds.html) and [lower](/tour/lower-type-bounds.html) type bounds From 45678020ba4566d9d8cf8562a39827c7d1dbe34a Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 5 Jul 2021 14:36:41 +0200 Subject: [PATCH 0738/2265] Introduce a page about worksheets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the page “Scala Tools” was mainly about sbt. We now have a chapter “Scala Tools”, which contains two sections: “Building and Testing Scala Projects with sbt”, and “Worksheets”. --- .../scala3-book/interacting-with-java.md | 4 +- _overviews/scala3-book/scala-for-java-devs.md | 2 +- .../scala3-book/scala-for-javascript-devs.md | 2 +- .../scala3-book/scala-for-python-devs.md | 2 +- _overviews/scala3-book/scala-tools.md | 508 +---------------- _overviews/scala3-book/taste-repl.md | 2 + _overviews/scala3-book/tools-sbt.md | 512 ++++++++++++++++++ _overviews/scala3-book/tools-worksheets.md | 56 ++ .../images/scala3-book/intellij-worksheet.png | Bin 0 -> 12899 bytes .../images/scala3-book/metals-worksheet.png | Bin 0 -> 16233 bytes 10 files changed, 579 insertions(+), 509 deletions(-) create mode 100644 _overviews/scala3-book/tools-sbt.md create mode 100644 _overviews/scala3-book/tools-worksheets.md create mode 100644 resources/images/scala3-book/intellij-worksheet.png create mode 100644 resources/images/scala3-book/metals-worksheet.png diff --git a/_overviews/scala3-book/interacting-with-java.md b/_overviews/scala3-book/interacting-with-java.md index 8ccb38e156..5b0b99286b 100644 --- a/_overviews/scala3-book/interacting-with-java.md +++ b/_overviews/scala3-book/interacting-with-java.md @@ -2,8 +2,8 @@ title: Interacting with Java type: chapter description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. -num: 70 -previous-page: scala-tools +num: 72 +previous-page: tools-worksheets next-page: scala-for-java-devs --- diff --git a/_overviews/scala3-book/scala-for-java-devs.md b/_overviews/scala3-book/scala-for-java-devs.md index be54f5fd25..125f77c06e 100644 --- a/_overviews/scala3-book/scala-for-java-devs.md +++ b/_overviews/scala3-book/scala-for-java-devs.md @@ -2,7 +2,7 @@ title: Scala for Java Developers type: chapter description: This page is for Java developers who are interested in learning about Scala 3. -num: 71 +num: 73 previous-page: interacting-with-java next-page: scala-for-javascript-devs --- diff --git a/_overviews/scala3-book/scala-for-javascript-devs.md b/_overviews/scala3-book/scala-for-javascript-devs.md index a577837e56..462a1017ce 100644 --- a/_overviews/scala3-book/scala-for-javascript-devs.md +++ b/_overviews/scala3-book/scala-for-javascript-devs.md @@ -2,7 +2,7 @@ title: Scala for JavaScript Developers type: chapter description: This chapter provides an introduction to Scala 3 for JavaScript developers -num: 72 +num: 74 previous-page: scala-for-java-devs next-page: scala-for-python-devs --- diff --git a/_overviews/scala3-book/scala-for-python-devs.md b/_overviews/scala3-book/scala-for-python-devs.md index 395d7c450d..77fb3c5881 100644 --- a/_overviews/scala3-book/scala-for-python-devs.md +++ b/_overviews/scala3-book/scala-for-python-devs.md @@ -2,7 +2,7 @@ title: Scala for Python Developers type: chapter description: This page is for Python developers who are interested in learning about Scala 3. -num: 73 +num: 75 previous-page: scala-for-javascript-devs next-page: --- diff --git a/_overviews/scala3-book/scala-tools.md b/_overviews/scala3-book/scala-tools.md index bffe1791dd..52e4bc67b7 100644 --- a/_overviews/scala3-book/scala-tools.md +++ b/_overviews/scala3-book/scala-tools.md @@ -4,510 +4,10 @@ type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. num: 69 previous-page: concurrency -next-page: interacting-with-java +next-page: tools-sbt --- +This chapter introduces two ways to write and run Scala programs: -In this chapter you’ll see two tools that are commonly used in Scala projects: - -- The [sbt](https://www.scala-sbt.org) build tool -- [ScalaTest](https://www.scalatest.org), a source code testing framework - -We’ll start by showing how to use sbt to build your Scala projects, and then we’ll show how to use sbt and ScalaTest together to test your Scala projects. - -> If you want to learn about tools to help you migrate your Scala 2 code to Scala 3, see our [Scala 3 Migration Guide](/scala3/guides/migration/compatibility-intro.html). - - - -## Building Scala projects with sbt - -You can use several different tools to build your Scala projects, including Ant, Maven, Gradle, Mill, and more. -But a tool named _sbt_ was the first build tool that was specifically created for Scala. - -> To install sbt, see [its download page](https://www.scala-sbt.org/download.html) or our [Getting Started][getting_started] page. - - - -### Creating a “Hello, world” project - -You can create an sbt “Hello, world” project in just a few steps. -First, create a directory to work in, and move into that directory: - -```bash -$ mkdir hello -$ cd hello -``` - -In the directory `hello`, create a subdirectory `project`: - -```bash -$ mkdir project -``` - -Create a file named _build.properties_ in the directory `project`, with -the following content: - -```text -sbt.version=1.5.4 -``` - -Then create a file named _build.sbt_ in the project root directory that contains this line: - -```scala -scalaVersion := "{{ site.scala-3-version }}" -``` - -Now create a file named something like _Hello.scala_---the first part of the name doesn’t matter---with this line: - -```scala -@main def helloWorld = println("Hello, world") -``` - -That’s all you have to do. - -You should have a project structure like the following: - -~~~ bash -$ tree -. -├── build.sbt -├── Hello.scala -└── project - └── build.properties -~~~ - -Now run the project with this `sbt` command: - -```bash -$ sbt run -``` - -You should see output that looks like this, including the `"Hello, world"` from your program: - -```bash -$ sbt run -[info] welcome to sbt 1.5.4 (AdoptOpenJDK Java 11.x) -[info] loading project definition from project ... -[info] loading settings for project from build.sbt ... -[info] compiling 1 Scala source to target/scala-3.0.0/classes ... -[info] running helloWorld -Hello, world -[success] Total time: 2 s -``` - -The sbt launcher---the `sbt` command-line tool---loads the version of sbt set in the file _project/build.properties_, which loads the version of the Scala compiler set in the file _build.sbt_, compiles the code in the file _Hello.scala_, and runs the resulting bytecode. - -When you look at your directory, you’ll see that sbt has a directory named _target_. -These are working directories that sbt uses. - -As you can see, creating and running a little Scala project with sbt takes just a few simple steps. - -> For sbt version < 1.5.0, it is required to have the following line in a *project/plugins.sbt* file: `addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "{{ site.scala-3-plugin-version }}")` - - -### Using sbt with larger projects - -For a little project, that’s all that sbt requires to run. -For larger projects that require many source code files, dependencies, or sbt plugins, you’ll want to create an organized directory structure. -The rest of this section demonstrates the structure that sbt uses. - - -### The sbt directory structure - -Like Maven, sbt uses a standard project directory structure. -A nice benefit of that is that once you’re comfortable with its structure, it makes it easy to work on other Scala/sbt projects. - -The first thing to know is that underneath the root directory of your project, sbt expects a directory structure that looks like this: - -```text -. -├── build.sbt -├── project/ -│ └── build.properties -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ ├── resources/ -│ │ └── scala/ -│ └── test/ -│ ├── java/ -│ ├── resources/ -│ └── scala/ -└── target/ -``` - -You can also add a _lib_ directory under the root directory if you want to add unmanaged dependencies---JAR files---to your project. - -If you’re going to create a project that has Scala source code files and tests, but won’t be using any Java source code files, and doesn’t need any “resources”---such as embedded images, configuration files, etc.---this is all you really need under the _src_ directory: - -```text -. -└── src/ - ├── main/ - │ └── scala/ - └── test/ - └── scala/ -``` - - -### “Hello, world” with an sbt directory structure - -{% comment %} -LATER: using something like `sbt new scala/scala3.g8` may eventually - be preferable, but that seems to have a few bugs atm (creates - a 'target' directory above the root; renames the root dir; - uses 'dottyVersion'; 'name' doesn’t match the supplied name; - config syntax is a little hard for beginners.) -{% endcomment %} - -Creating this directory structure is simple. -There are tools to do this for you, but assuming that you’re using a Unix/Linux system, you can use these commands to create your first sbt project directory structure: - -```bash -$ mkdir HelloWorld -$ cd HelloWorld -$ mkdir -p src/{main,test}/scala -$ mkdir project target -``` - -When you run a `find .` command after running those commands, you should see this result: - -```bash -$ find . -. -./project -./src -./src/main -./src/main/scala -./src/test -./src/test/scala -./target -``` - -If you see that, you’re in great shape for the next step. - -> There are other ways to create the files and directories for an sbt project. -> One way is to use the `sbt new` command, [which is documented here on scala-sbt.org](https://www.scala-sbt.org/1.x/docs/Hello.html). -> That approach isn’t shown here because some of the files it creates are more complicated than necessary for an introduction like this. - - -### Creating a first build.sbt file - -At this point you only need two more things to run a “Hello, world” project: - -- A _build.sbt_ file -- A _Hello.scala_ file - -For a little project like this, the _build.sbt_ file only needs a `scalaVersion` entry, but we’ll add three lines that you commonly see: - -```scala -name := "HelloWorld" -version := "0.1" -scalaVersion := "{{ site.scala-3-version }}" -``` - -Because sbt projects use a standard directory structure, sbt can find everything else it needs. - -Now you just need to add a little “Hello, world” program. - - -### A “Hello, world” program - -In large projects, all of your Scala source code files will go under the _src/main/scala_ and _src/test/scala_ directories, but for a little sample project like this, you can put your source code file in the root directory of your project. -Therefore, create a file named _HelloWorld.scala_ in the root directory with these contents: - -```scala -@main def helloWorld = println("Hello, world") -``` - -That code defines a Scala 3 “main” method that prints the `"Hello, world"` when it’s run. - -Now, use the `sbt run` command to compile and run your project: - -```bash -$ sbt run - -[info] welcome to sbt -[info] loading settings for project ... -[info] loading project definition -[info] loading settings for project root from build.sbt ... -[info] Compiling 1 Scala source ... -[info] running helloWorld -Hello, world -[success] Total time: 4 s -``` - -The first time you run `sbt` it downloads everything it needs, and that can take a few moments to run, but after that it gets much faster. - -Also, once you get this first step working, you’ll find that it’s much faster to run sbt interactively. -To do that, first run the `sbt` command by itself: - -```bash -$ sbt - -[info] welcome to sbt -[info] loading settings for project ... -[info] loading project definition ... -[info] loading settings for project root from build.sbt ... -[info] sbt server started at - local:///${HOME}/.sbt/1.0/server/7d26bae822c36a31071c/sock -sbt:hello-world> _ -``` - -Then inside this sbt shell, execute its `run` command: - -```` -sbt:hello-world> run - -[info] running helloWorld -Hello, world -[success] Total time: 0 s -```` - -There, that’s much faster. - -If you type `help` at the sbt command prompt you’ll see a list of other commands you can run. -But for now, just type `exit` (or press `CTRL-D`) to leave the sbt shell. - -### Using project templates - -Manually creating the project structure can be tedious. Thankfully, sbt can create it for you, -based on a template. - -To create a Scala 3 project from a template, run the following command in a shell: - -~~~ -$ sbt new scala/scala3.g8 -~~~ - -Sbt will load the template, ask some questions, and create the project files in a subdirectory: - -~~~ -$ tree scala-3-project-template -scala-3-project-template -├── build.sbt -├── project -│ └── build.properties -├── README.md -└── src - ├── main - │ └── scala - │ └── Main.scala - └── test - └── scala - └── Test1.scala -~~~ - -> If you want to create a Scala 3 project that cross-compiles with Scala 2, use the template `scala/scala3-cross.g8`: -> -> ~~~ -> $ sbt new scala/scala3-cross.g8 -> ~~~ - -Learn more about `sbt new` and project templates in the [documentation of sbt](https://www.scala-sbt.org/1.x/docs/sbt-new-and-Templates.html#sbt+new+and+Templates). - -### Other build tools for Scala - -While sbt is widely used, there are other tools you can use to build Scala projects: - -- [Ant](https://ant.apache.org/) -- [Gradle](https://gradle.org/) -- [Maven](https://maven.apache.org/) -- [Mill](https://com-lihaoyi.github.io/mill/) - -#### Coursier - -In a related note, [Coursier](https://get-coursier.io/docs/overview) is a “dependency resolver,” similar to Maven and Ivy in function. -It’s written from scratch in Scala, “embraces functional programming principles,” and downloads artifacts in parallel for rapid downloads. -sbt uses it to handle most dependency resolutions, and as a command-line tool, it can be used to easily install tools like sbt, Java, and Scala on your system, as shown in our [Getting Started][getting_started] page. - -This example from the `launch` web page shows that the `cs launch` command can be used to launch applications from dependencies: - -```scala -$ cs launch org.scalameta::scalafmt-cli:2.4.2 -- --help -scalafmt 2.4.2 -Usage: scalafmt [options] [...] - - -h, --help prints this usage text - -v, --version print version - more ... -``` - -See Coursier’s [launch page](https://get-coursier.io/docs/cli-launch) for more details. - - - -## Using sbt with ScalaTest - -[ScalaTest](https://www.scalatest.org) is one of the main testing libraries for Scala projects, and in this section you’ll see how to create a Scala/sbt project that uses ScalaTest. - - -### Creating the project directory structure - -As with the previous lesson, create an sbt project directory structure for a project named _HelloScalaTest_ with the following commands: - -```bash -$ mkdir HelloScalaTest -$ cd HelloScalaTest -$ mkdir -p src/{main,test}/scala -$ mkdir project -``` - - -### Creating the build.properties and build.sbt files - -Next, create a _build.properties_ file in the _project/_ subdirectory of your project -with this line: - -```text -sbt.version=1.5.4 -``` - -Next, create a _build.sbt_ file in the root directory of your project with these contents: - -```scala -name := "HelloScalaTest" -version := "0.1" -scalaVersion := "{{site.scala-3-version}}" - -libraryDependencies ++= Seq( - "org.scalatest" %% "scalatest" % "3.2.9" % Test -) -``` - -The first three lines of this file are essentially the same as the first example. -The `libraryDependencies` lines tell sbt to include the dependencies (JAR files) that are needed to include ScalaTest. - -> The ScalaTest documentation has always been good, and you can always find the up to date information on what those lines should look like on the [Installing ScalaTest](https://www.scalatest.org/install) page. - - -### Create a Scala source code file - -Next, create a Scala program that you can use to demonstrate ScalaTest. -First, create a directory under _src/main/scala_ named _math_: - -```bash -$ mkdir src/main/scala/math - ---- -``` - -Then, inside that directory, create a file named _MathUtils.scala_ with these contents: - -```scala -package math - -object MathUtils: - def double(i: Int) = i * 2 -``` - -That method provides a simple way to demonstrate ScalaTest. - - -{% comment %} -Because this project doesn’t have a `main` method, we don’t try to run it with `sbt run`; we just compile it with `sbt compile`: - -```` -$ sbt compile - -[info] welcome to sbt -[info] loading settings for project ... -[info] loading project definition ... -[info] loading settings for project ... -[info] Executing in batch mode. For better performance use sbt's shell -[success] Total time: 1 s -```` - -With that compiled, let’s create a ScalaTest file to test the `double` method. -{% endcomment %} - - -### Your first ScalaTest tests - -ScalaTest is very flexible, and offers several different ways to write tests. -A simple way to get started is to write tests using the ScalaTest `AnyFunSuite`. -To get started, create a directory named _math_ under the _src/test/scala_ directory: - -```bash -$ mkdir src/test/scala/math - ---- -``` - -Next, create a file named _MathUtilsTests.scala_ in that directory with the following contents: - -```scala -package math - -import org.scalatest.funsuite.AnyFunSuite - -class MathUtilsTests extends AnyFunSuite: - - // test 1 - test("'double' should handle 0") { - val result = MathUtils.double(0) - assert(result == 0) - } - - // test 2 - test("'double' should handle 1") { - val result = MathUtils.double(1) - assert(result == 2) - } - - test("test with Int.MaxValue") (pending) - -end MathUtilsTests -``` - -This code demonstrates the ScalaTest `AnyFunSuite` approach. -A few important points: - -- Your test class should extend `AnyFunSuite` -- You create tests as shown, by giving each `test` a unique name -- At the end of each test you should call `assert` to test that a condition has been satisfied -- When you know you want to write a test, but you don’t want to write it right now, create the test as “pending,” with the syntax shown - -Using ScalaTest like this is similar to JUnit, so if you’re coming to Scala from Java, hopefully this looks similar. - -Now you can run these tests with the `sbt test` command. -Skipping the first few lines of output, the result looks like this: - -```` -sbt:HelloScalaTest> test - -[info] Compiling 1 Scala source ... -[info] MathUtilsTests: -[info] - 'double' should handle 0 -[info] - 'double' should handle 1 -[info] - test with Int.MaxValue (pending) -[info] Total number of tests run: 2 -[info] Suites: completed 1, aborted 0 -[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 1 -[info] All tests passed. -[success] Total time: 1 s -```` - -If everything works well, you’ll see output that looks like that. -Welcome to the world of testing Scala applications with sbt and ScalaTest. - - -### Support for many types of tests - -This example demonstrates a style of testing that’s similar to xUnit _Test-Driven Development_ (TDD) style testing, with a few benefits of the _Behavior-Driven Development_ (BDD) style. - -As mentioned, ScalaTest is flexible and you can also write tests using other styles, such as a style similar to Ruby’s RSpec. -You can also use mock objects, property-based testing, and use ScalaTest to test Scala.js code. - -See the User Guide on the [ScalaTest website](https://www.scalatest.org) for more details on the different testing styles that are available. - - - -## Where to go from here - -For more information about sbt and ScalaTest, see the following resources: - -- [The sbt documentation](https://www.scala-sbt.org/1.x/docs/) -- [The ScalaTest website](https://www.scalatest.org/) - - - -[getting_started]: {{ site.baseurl }}/scala3/getting-started.html +- by creating Scala projects, possibly containing multiple files, and defining a program entry point, +- by interacting with a worksheet, which is a program defined in a single file, executed line by line. diff --git a/_overviews/scala3-book/taste-repl.md b/_overviews/scala3-book/taste-repl.md index 130168c5cb..dba5420401 100644 --- a/_overviews/scala3-book/taste-repl.md +++ b/_overviews/scala3-book/taste-repl.md @@ -54,4 +54,6 @@ val res2: Int = 4 If you prefer a browser-based playground environment, you can also use [scastie.scala-lang.org](https://scastie.scala-lang.org). +If you prefer writing your code in a text editor instead of in console prompt, you can use a [worksheet]. +[worksheet]: {% link _overviews/scala3-book/tools-worksheets.md %} diff --git a/_overviews/scala3-book/tools-sbt.md b/_overviews/scala3-book/tools-sbt.md new file mode 100644 index 0000000000..e5dd291293 --- /dev/null +++ b/_overviews/scala3-book/tools-sbt.md @@ -0,0 +1,512 @@ +--- +title: Building and Testing Scala Projects with sbt +type: section +description: This section looks at a commonly-used build tool, sbt, and a testing library, ScalaTest. +num: 70 +previous-page: scala-tools +next-page: tools-worksheets +--- + +In this section you’ll see two tools that are commonly used in Scala projects: + +- The [sbt](https://www.scala-sbt.org) build tool +- [ScalaTest](https://www.scalatest.org), a source code testing framework + +We’ll start by showing how to use sbt to build your Scala projects, and then we’ll show how to use sbt and ScalaTest together to test your Scala projects. + +> If you want to learn about tools to help you migrate your Scala 2 code to Scala 3, see our [Scala 3 Migration Guide](/scala3/guides/migration/compatibility-intro.html). + + + +## Building Scala projects with sbt + +You can use several different tools to build your Scala projects, including Ant, Maven, Gradle, Mill, and more. +But a tool named _sbt_ was the first build tool that was specifically created for Scala. + +> To install sbt, see [its download page](https://www.scala-sbt.org/download.html) or our [Getting Started][getting_started] page. + + + +### Creating a “Hello, world” project + +You can create an sbt “Hello, world” project in just a few steps. +First, create a directory to work in, and move into that directory: + +```bash +$ mkdir hello +$ cd hello +``` + +In the directory `hello`, create a subdirectory `project`: + +```bash +$ mkdir project +``` + +Create a file named _build.properties_ in the directory `project`, with +the following content: + +```text +sbt.version=1.5.4 +``` + +Then create a file named _build.sbt_ in the project root directory that contains this line: + +```scala +scalaVersion := "{{ site.scala-3-version }}" +``` + +Now create a file named something like _Hello.scala_---the first part of the name doesn’t matter---with this line: + +```scala +@main def helloWorld = println("Hello, world") +``` + +That’s all you have to do. + +You should have a project structure like the following: + +~~~ bash +$ tree +. +├── build.sbt +├── Hello.scala +└── project + └── build.properties +~~~ + +Now run the project with this `sbt` command: + +```bash +$ sbt run +``` + +You should see output that looks like this, including the `"Hello, world"` from your program: + +```bash +$ sbt run +[info] welcome to sbt 1.5.4 (AdoptOpenJDK Java 11.x) +[info] loading project definition from project ... +[info] loading settings for project from build.sbt ... +[info] compiling 1 Scala source to target/scala-3.0.0/classes ... +[info] running helloWorld +Hello, world +[success] Total time: 2 s +``` + +The sbt launcher---the `sbt` command-line tool---loads the version of sbt set in the file _project/build.properties_, which loads the version of the Scala compiler set in the file _build.sbt_, compiles the code in the file _Hello.scala_, and runs the resulting bytecode. + +When you look at your directory, you’ll see that sbt has a directory named _target_. +These are working directories that sbt uses. + +As you can see, creating and running a little Scala project with sbt takes just a few simple steps. + +> For sbt version < 1.5.0, it is required to have the following line in a *project/plugins.sbt* file: `addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "{{ site.scala-3-plugin-version }}")` + + +### Using sbt with larger projects + +For a little project, that’s all that sbt requires to run. +For larger projects that require many source code files, dependencies, or sbt plugins, you’ll want to create an organized directory structure. +The rest of this section demonstrates the structure that sbt uses. + + +### The sbt directory structure + +Like Maven, sbt uses a standard project directory structure. +A nice benefit of that is that once you’re comfortable with its structure, it makes it easy to work on other Scala/sbt projects. + +The first thing to know is that underneath the root directory of your project, sbt expects a directory structure that looks like this: + +```text +. +├── build.sbt +├── project/ +│ └── build.properties +├── src/ +│ ├── main/ +│ │ ├── java/ +│ │ ├── resources/ +│ │ └── scala/ +│ └── test/ +│ ├── java/ +│ ├── resources/ +│ └── scala/ +└── target/ +``` + +You can also add a _lib_ directory under the root directory if you want to add unmanaged dependencies---JAR files---to your project. + +If you’re going to create a project that has Scala source code files and tests, but won’t be using any Java source code files, and doesn’t need any “resources”---such as embedded images, configuration files, etc.---this is all you really need under the _src_ directory: + +```text +. +└── src/ + ├── main/ + │ └── scala/ + └── test/ + └── scala/ +``` + + +### “Hello, world” with an sbt directory structure + +{% comment %} +LATER: using something like `sbt new scala/scala3.g8` may eventually + be preferable, but that seems to have a few bugs atm (creates + a 'target' directory above the root; renames the root dir; + uses 'dottyVersion'; 'name' doesn’t match the supplied name; + config syntax is a little hard for beginners.) +{% endcomment %} + +Creating this directory structure is simple. +There are tools to do this for you, but assuming that you’re using a Unix/Linux system, you can use these commands to create your first sbt project directory structure: + +```bash +$ mkdir HelloWorld +$ cd HelloWorld +$ mkdir -p src/{main,test}/scala +$ mkdir project target +``` + +When you run a `find .` command after running those commands, you should see this result: + +```bash +$ find . +. +./project +./src +./src/main +./src/main/scala +./src/test +./src/test/scala +./target +``` + +If you see that, you’re in great shape for the next step. + +> There are other ways to create the files and directories for an sbt project. +> One way is to use the `sbt new` command, [which is documented here on scala-sbt.org](https://www.scala-sbt.org/1.x/docs/Hello.html). +> That approach isn’t shown here because some of the files it creates are more complicated than necessary for an introduction like this. + + +### Creating a first build.sbt file + +At this point you only need two more things to run a “Hello, world” project: + +- A _build.sbt_ file +- A _Hello.scala_ file + +For a little project like this, the _build.sbt_ file only needs a `scalaVersion` entry, but we’ll add three lines that you commonly see: + +```scala +name := "HelloWorld" +version := "0.1" +scalaVersion := "{{ site.scala-3-version }}" +``` + +Because sbt projects use a standard directory structure, sbt can find everything else it needs. + +Now you just need to add a little “Hello, world” program. + + +### A “Hello, world” program + +In large projects, all of your Scala source code files will go under the _src/main/scala_ and _src/test/scala_ directories, but for a little sample project like this, you can put your source code file in the root directory of your project. +Therefore, create a file named _HelloWorld.scala_ in the root directory with these contents: + +```scala +@main def helloWorld = println("Hello, world") +``` + +That code defines a Scala 3 “main” method that prints the `"Hello, world"` when it’s run. + +Now, use the `sbt run` command to compile and run your project: + +```bash +$ sbt run + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition +[info] loading settings for project root from build.sbt ... +[info] Compiling 1 Scala source ... +[info] running helloWorld +Hello, world +[success] Total time: 4 s +``` + +The first time you run `sbt` it downloads everything it needs, and that can take a few moments to run, but after that it gets much faster. + +Also, once you get this first step working, you’ll find that it’s much faster to run sbt interactively. +To do that, first run the `sbt` command by itself: + +```bash +$ sbt + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition ... +[info] loading settings for project root from build.sbt ... +[info] sbt server started at + local:///${HOME}/.sbt/1.0/server/7d26bae822c36a31071c/sock +sbt:hello-world> _ +``` + +Then inside this sbt shell, execute its `run` command: + +```` +sbt:hello-world> run + +[info] running helloWorld +Hello, world +[success] Total time: 0 s +```` + +There, that’s much faster. + +If you type `help` at the sbt command prompt you’ll see a list of other commands you can run. +But for now, just type `exit` (or press `CTRL-D`) to leave the sbt shell. + +### Using project templates + +Manually creating the project structure can be tedious. Thankfully, sbt can create it for you, +based on a template. + +To create a Scala 3 project from a template, run the following command in a shell: + +~~~ +$ sbt new scala/scala3.g8 +~~~ + +Sbt will load the template, ask some questions, and create the project files in a subdirectory: + +~~~ +$ tree scala-3-project-template +scala-3-project-template +├── build.sbt +├── project +│ └── build.properties +├── README.md +└── src + ├── main + │ └── scala + │ └── Main.scala + └── test + └── scala + └── Test1.scala +~~~ + +> If you want to create a Scala 3 project that cross-compiles with Scala 2, use the template `scala/scala3-cross.g8`: +> +> ~~~ +> $ sbt new scala/scala3-cross.g8 +> ~~~ + +Learn more about `sbt new` and project templates in the [documentation of sbt](https://www.scala-sbt.org/1.x/docs/sbt-new-and-Templates.html#sbt+new+and+Templates). + +### Other build tools for Scala + +While sbt is widely used, there are other tools you can use to build Scala projects: + +- [Ant](https://ant.apache.org/) +- [Gradle](https://gradle.org/) +- [Maven](https://maven.apache.org/) +- [Mill](https://com-lihaoyi.github.io/mill/) + +#### Coursier + +In a related note, [Coursier](https://get-coursier.io/docs/overview) is a “dependency resolver,” similar to Maven and Ivy in function. +It’s written from scratch in Scala, “embraces functional programming principles,” and downloads artifacts in parallel for rapid downloads. +sbt uses it to handle most dependency resolutions, and as a command-line tool, it can be used to easily install tools like sbt, Java, and Scala on your system, as shown in our [Getting Started][getting_started] page. + +This example from the `launch` web page shows that the `cs launch` command can be used to launch applications from dependencies: + +```scala +$ cs launch org.scalameta::scalafmt-cli:2.4.2 -- --help +scalafmt 2.4.2 +Usage: scalafmt [options] [...] + + -h, --help prints this usage text + -v, --version print version + more ... +``` + +See Coursier’s [launch page](https://get-coursier.io/docs/cli-launch) for more details. + + + +## Using sbt with ScalaTest + +[ScalaTest](https://www.scalatest.org) is one of the main testing libraries for Scala projects, and in this section you’ll see how to create a Scala/sbt project that uses ScalaTest. + + +### Creating the project directory structure + +As with the previous lesson, create an sbt project directory structure for a project named _HelloScalaTest_ with the following commands: + +```bash +$ mkdir HelloScalaTest +$ cd HelloScalaTest +$ mkdir -p src/{main,test}/scala +$ mkdir project +``` + + +### Creating the build.properties and build.sbt files + +Next, create a _build.properties_ file in the _project/_ subdirectory of your project +with this line: + +```text +sbt.version=1.5.4 +``` + +Next, create a _build.sbt_ file in the root directory of your project with these contents: + +```scala +name := "HelloScalaTest" +version := "0.1" +scalaVersion := "{{site.scala-3-version}}" + +libraryDependencies ++= Seq( + "org.scalatest" %% "scalatest" % "3.2.9" % Test +) +``` + +The first three lines of this file are essentially the same as the first example. +The `libraryDependencies` lines tell sbt to include the dependencies (JAR files) that are needed to include ScalaTest. + +> The ScalaTest documentation has always been good, and you can always find the up to date information on what those lines should look like on the [Installing ScalaTest](https://www.scalatest.org/install) page. + + +### Create a Scala source code file + +Next, create a Scala program that you can use to demonstrate ScalaTest. +First, create a directory under _src/main/scala_ named _math_: + +```bash +$ mkdir src/main/scala/math + ---- +``` + +Then, inside that directory, create a file named _MathUtils.scala_ with these contents: + +```scala +package math + +object MathUtils: + def double(i: Int) = i * 2 +``` + +That method provides a simple way to demonstrate ScalaTest. + + +{% comment %} +Because this project doesn’t have a `main` method, we don’t try to run it with `sbt run`; we just compile it with `sbt compile`: + +```` +$ sbt compile + +[info] welcome to sbt +[info] loading settings for project ... +[info] loading project definition ... +[info] loading settings for project ... +[info] Executing in batch mode. For better performance use sbt's shell +[success] Total time: 1 s +```` + +With that compiled, let’s create a ScalaTest file to test the `double` method. +{% endcomment %} + + +### Your first ScalaTest tests + +ScalaTest is very flexible, and offers several different ways to write tests. +A simple way to get started is to write tests using the ScalaTest `AnyFunSuite`. +To get started, create a directory named _math_ under the _src/test/scala_ directory: + +```bash +$ mkdir src/test/scala/math + ---- +``` + +Next, create a file named _MathUtilsTests.scala_ in that directory with the following contents: + +```scala +package math + +import org.scalatest.funsuite.AnyFunSuite + +class MathUtilsTests extends AnyFunSuite: + + // test 1 + test("'double' should handle 0") { + val result = MathUtils.double(0) + assert(result == 0) + } + + // test 2 + test("'double' should handle 1") { + val result = MathUtils.double(1) + assert(result == 2) + } + + test("test with Int.MaxValue") (pending) + +end MathUtilsTests +``` + +This code demonstrates the ScalaTest `AnyFunSuite` approach. +A few important points: + +- Your test class should extend `AnyFunSuite` +- You create tests as shown, by giving each `test` a unique name +- At the end of each test you should call `assert` to test that a condition has been satisfied +- When you know you want to write a test, but you don’t want to write it right now, create the test as “pending,” with the syntax shown + +Using ScalaTest like this is similar to JUnit, so if you’re coming to Scala from Java, hopefully this looks similar. + +Now you can run these tests with the `sbt test` command. +Skipping the first few lines of output, the result looks like this: + +```` +sbt:HelloScalaTest> test + +[info] Compiling 1 Scala source ... +[info] MathUtilsTests: +[info] - 'double' should handle 0 +[info] - 'double' should handle 1 +[info] - test with Int.MaxValue (pending) +[info] Total number of tests run: 2 +[info] Suites: completed 1, aborted 0 +[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 1 +[info] All tests passed. +[success] Total time: 1 s +```` + +If everything works well, you’ll see output that looks like that. +Welcome to the world of testing Scala applications with sbt and ScalaTest. + + +### Support for many types of tests + +This example demonstrates a style of testing that’s similar to xUnit _Test-Driven Development_ (TDD) style testing, with a few benefits of the _Behavior-Driven Development_ (BDD) style. + +As mentioned, ScalaTest is flexible and you can also write tests using other styles, such as a style similar to Ruby’s RSpec. +You can also use mock objects, property-based testing, and use ScalaTest to test Scala.js code. + +See the User Guide on the [ScalaTest website](https://www.scalatest.org) for more details on the different testing styles that are available. + + + +## Where to go from here + +For more information about sbt and ScalaTest, see the following resources: + +- [The sbt documentation](https://www.scala-sbt.org/1.x/docs/) +- [The ScalaTest website](https://www.scalatest.org/) + + + +[getting_started]: {{ site.baseurl }}/scala3/getting-started.html diff --git a/_overviews/scala3-book/tools-worksheets.md b/_overviews/scala3-book/tools-worksheets.md new file mode 100644 index 0000000000..3231d4e654 --- /dev/null +++ b/_overviews/scala3-book/tools-worksheets.md @@ -0,0 +1,56 @@ +--- +title: Worksheets +type: section +description: This section looks at worksheets, an alternative to Scala projects. +num: 71 +previous-page: tools-sbt +next-page: interacting-with-java +--- + +A worksheet is a Scala file that is evaluated on save, and the result of each expression is shown +in a column to the right of your program. Worksheets are like a [REPL session] on steroids, and +enjoy 1st class editor support: completion, hyperlinking, interactive errors-as-you-type, etc. +Worksheets use the extension `.worksheet.sc`. + +In the following, we show how to use worksheets in IntelliJ, and in VS Code (with the Metals extension). + +1. Open a Scala project, or create one. + - To create a project in IntelliJ, select “File” -> “New” -> “Project…”, select “Scala” + in the left column, and click “Next” to set the project name and location. + - To create a project in VS Code, run the command “Metals: New Scala project”, select the + seed `scala/scala3.g8`, set the project location, open it in a new VS Code window, and + import its build. +1. Create a file named `hello.worksheet.sc` in the directory `src/main/scala/`. + - In IntelliJ, right-click on the directory `src/main/scala/`, and select “New”, and + then “File”. + - In VS Code, right-click on the directory `src/main/scala/`, and select “New File”. +1. Paste the following content in the editor: + ~~~ + println("Hello, world!") + + val x = 1 + x + x + ~~~ +1. Evaluate the worksheet. + - In IntelliJ, click on the green arrow at the top of the editor to evaluate the worksheet. + - In VS Code, save the file. + + You should see the result of the evaluation of every line on the right panel (IntelliJ), or + as comments (VS Code). + +![]({{ site.baseurl }}/resources/images/scala3-book/intellij-worksheet.png) + +A worksheet evaluated in IntelliJ. + +![]({{ site.baseurl }}/resources/images/scala3-book/metals-worksheet.png) + +A worksheet evaluated in VS Code (with the Metals extension). + +Note that the worksheet will use the Scala version defined by your project (set by the key `scalaVersion`, +in your file `build.sbt`, typically). + +Also note that worksheets don’t have a [program entry point]. Instead, top-level statements and expressions +are evaluated from top to bottom. + +[REPL session]: {% link _overviews/scala3-book/taste-repl.md %} +[program entry point]: {% link _overviews/scala3-book/methods-main-methods.md %} diff --git a/resources/images/scala3-book/intellij-worksheet.png b/resources/images/scala3-book/intellij-worksheet.png new file mode 100644 index 0000000000000000000000000000000000000000..e33fd3566e8c43b3e32aeb06a951f69f57bdd03b GIT binary patch literal 12899 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 literal 0 HcmV?d00001 From 8c1ff35b174b2446b9be5e9739c1d79164b07779 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 5 Jul 2021 16:27:14 +0200 Subject: [PATCH 0739/2265] Create docs.scala-lang.org/scala3/guides/reference and move language-versions here Content was taken from commit 270bd8b0f5af338be73790082d774516a83a73b5 --- _config.yml | 11 +++++- .../scala3-reference/language-versions.md | 36 +++++++++++++++++++ _overviews/scala3-reference/overview.md | 7 ++++ scala3/guides.md | 4 +++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 _overviews/scala3-reference/language-versions.md create mode 100644 _overviews/scala3-reference/overview.md diff --git a/_config.yml b/_config.yml index ea13ad3eae..395bed4a34 100644 --- a/_config.yml +++ b/_config.yml @@ -123,6 +123,15 @@ defaults: overview-name: "Macros in Scala 3" layout: multipage-overview permalink: "/scala3/guides/macros/:title.html" + - + scope: + path: "_overviews/scala3-reference" + values: + scala3: true + partof: scala3-reference + overview-name: "Scala 3 Language Reference" + layout: multipage-overview + permalink: "/scala3/guides/reference/:title.html" - scope: path: "scala3" @@ -133,7 +142,7 @@ defaults: highlighter: rouge permalink: /:categories/:title.html:output_ext baseurl: -scala3ref: "https://dotty.epfl.ch/docs/reference" +scala3ref: "/scala3/guides/reference" exclude: ["vendor"] plugins: - jekyll-redirect-from diff --git a/_overviews/scala3-reference/language-versions.md b/_overviews/scala3-reference/language-versions.md new file mode 100644 index 0000000000..01a8ab1c32 --- /dev/null +++ b/_overviews/scala3-reference/language-versions.md @@ -0,0 +1,36 @@ +--- +title: Language Versions +type: chapter +description: This page lists the different flavours of language supported by the Scala 3 compiler. +num: 2 +previous-page: overview +--- + +The default Scala language version currently supported by the Dotty compiler is `3.0`. There are also other language versions that can be specified instead: + +- `3.0-migration`: Same as `3.0` but with a Scala 2 compatibility mode that helps moving Scala 2.13 sources over to Scala 3. In particular, it + + - flags some Scala 2 constructs that are disallowed in Scala 3 as migration warnings instead of hard errors, + - changes some rules to be more lenient and backwards compatible with Scala 2.13 + - gives some additional warnings where the semantics has changed between Scala 2.13 and 3.0 + - in conjunction with `-rewrite`, offer code rewrites from Scala 2.13 to 3.0. + +- `future`: A preview of changes introduced in the next versions after 3.0. In the doc pages here we refer to the language version with these changes as `3.1`, but it might be that some of these changes will be rolled out in later `3.x` versions. + +Some Scala-2 specific idioms will be dropped in this version. The feature set supported by this version will be refined over time as we approach its release. + +- `future-migration`: Same as `future` but with additional helpers to migrate from `3.0`. Similarly to the helpers available under `3.0-migration`, these include migration warnings and optional rewrites. + +There are two ways to specify a language version. + +- With a `-source` command line setting, e.g. `-source 3.0-migration`. +- With a `scala.language` import at the top of a source file, e.g: + +```scala +package p +import scala.language.`future-migration` + +class C { ... } +``` + +Language imports supersede command-line settings in the source files where they are specified. Only one language import specifying a source version is allowed in a source file, and it must come before any definitions in that file. diff --git a/_overviews/scala3-reference/overview.md b/_overviews/scala3-reference/overview.md new file mode 100644 index 0000000000..aa34ec188f --- /dev/null +++ b/_overviews/scala3-reference/overview.md @@ -0,0 +1,7 @@ +--- +title: Overview +type: chapter +description: This page begins the reference documentation. +num: 1 +next-page: language-versions +--- diff --git a/scala3/guides.md b/scala3/guides.md index 45587d280f..e6ddb733db 100644 --- a/scala3/guides.md +++ b/scala3/guides.md @@ -18,6 +18,10 @@ guides: icon: birthday-cake url: "/scala3/guides/tasty-overview.html" description: "An overview over the TASTy format aimed at end-users of the Scala language." + - title: Scala 3 Language Reference + icon: book + url: "/scala3/guides/reference/overview.html" + description: "The reference for Scala 3" --- \ No newline at end of file + diff --git a/_layouts/frontpage.html b/_layouts/frontpage.html index 743e27bd83..29fa5825fe 100644 --- a/_layouts/frontpage.html +++ b/_layouts/frontpage.html @@ -299,24 +299,24 @@

    {{forum.title}}

    {% endfor %} -
    -

    Real-time (topic-specialized) chat

    - {% assign modLimit = site.data.chats-forums.gitterChannels.size | modulo: 2 %} +
    +

    Real-time chat

    + {% assign modLimit = site.data.chats-forums.discordServers.size | modulo: 2 %} {% capture channelLimit %} {% if modLimit != 0 %} - {{site.data.chats-forums.gitterChannels.size | minus: 1}} + {{site.data.chats-forums.discordServers.size | minus: 1}} {% else %} - {{site.data.chats-forums.gitterChannels.size}} + {{site.data.chats-forums.discordServers.size}} {% endif %} {% endcapture %} - {% for channel in site.data.chats-forums.gitterChannels limit: channelLimit %} + {% for server in site.data.chats-forums.discordServers limit: channelLimit %} {% if forloop.first %}
    From 2dd2d506445008554d88614618b9faf28b16a355 Mon Sep 17 00:00:00 2001 From: Horimoto Yasuhiro Date: Wed, 9 Feb 2022 23:19:53 +0900 Subject: [PATCH 0968/2265] Add a missing translation in getting-started.md (Japanese) --- _includes/_ja/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/_ja/getting-started.md b/_includes/_ja/getting-started.md index 97ebcbd692..f70eba4848 100644 --- a/_includes/_ja/getting-started.md +++ b/_includes/_ja/getting-started.md @@ -150,7 +150,7 @@ Scala について日本語で質問したい場合、Twitterでつぶやくと
    From 1dd5138701fd92d82ebe284f49e566c39e1e68db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 10 Feb 2022 16:57:43 +0100 Subject: [PATCH 0969/2265] Update the Getting Started page(s) for the latest `cs` behavior. The default installation of coursier now installs Scala 3 by default under `scala` and `scalac`. However, it also allows to override that with `cs launch scala:2.13.8` or `cs install scala:2.13.8`, as Scala 2 and Scala 3 have been unified. --- _includes/getting-started.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/_includes/getting-started.md b/_includes/getting-started.md index dcbf448b0f..628f2a41c5 100644 --- a/_includes/getting-started.md +++ b/_includes/getting-started.md @@ -34,20 +34,24 @@ Along with managing JVMs, `cs setup` also installs useful command-line tools: - The [sbt](https://www.scala-sbt.org/) build tool - [Ammonite](https://ammonite.io/), an enhanced REPL - [scalafmt](https://scalameta.org/scalafmt/), the Scala code formatter -- `scalac` (the Scala 2 compiler) -- `scala` (the Scala 2 REPL and script runner). +- `scalac` (the Scala compiler) +- `scala` (the Scala REPL and script runner). For more information about `cs`, read [coursier-cli documentation](https://get-coursier.io/docs/cli-overview). -> Currently, `cs setup` installs the Scala 2 compiler and runner (the `scalac` and -> `scala` commands, respectively). This is usually not an issue because most projects -> use a build tool that works with both Scala 2 and Scala 3. -> Nevertheless, you can install the Scala 3 compiler and runner as command-line tools -> by running the following additional commands: +> `cs setup` installs the Scala 3 compiler and runner by default (the `scalac` and +> `scala` commands, respectively). Whether you intend to use Scala 2 or 3, +> this is usually not an issue because most projects use a build tool that will +> use the correct version of Scala irrespective of the one installed "globally". +> Nevertheless, you can always launch a specific version of Scala using > ``` -> $ cs install scala3-compiler -> $ cs install scala3 +> $ cs launch scala:{{ site.scala-version }} +> $ cs launch scalac:{{ site.scala-version }} +> ``` +> If you prefer Scala 2 to be run by default, you can force that version to be installed with: +> ``` +> $ cs install scala:{{ site.scala-version }} scalac:{{ site.scala-version }} > ``` ### ...or manually @@ -164,7 +168,7 @@ There are a multitude of mailing lists and real-time chat rooms in case you want + --> From 30f11ac17dbe37d7edc46bd64450dd030207b07d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 10 Feb 2022 20:02:07 -0800 Subject: [PATCH 0970/2265] Mention library version quirk --- _overviews/FAQ/index.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/_overviews/FAQ/index.md b/_overviews/FAQ/index.md index d20c5d7a4b..fe4b457451 100644 --- a/_overviews/FAQ/index.md +++ b/_overviews/FAQ/index.md @@ -105,9 +105,22 @@ get poor results, try surrounding the symbol with double quotes. sbt 1.x always uses Scala 2.12 to compile build definitions. Your sbt 1.x build definition is always a Scala 2.12 program. -Regardless, in your `build.sbt` you can set `scalaVersion` to anything -you want and your actual program code will be compiled with that -version. +Regardless, in your `build.sbt`, you can set `scalaVersion` to whichever +available distribution you want and your program code will be compiled with that version. + +### I want Scala 3.1.1 (etc); why does std lib say it's using Scala 2.13? + +Scala 3 currently uses the Scala 2.13 library by leveraging its seamless +interoperability. Note that it does not necessarily ingest the latest +version of the Scala 2.13 library. + +``` +Welcome to Scala 3.1.1 (17.0.2, Java OpenJDK 64-Bit Server VM). +Type in expressions for evaluation. Or try :help. + +scala> util.Properties.versionString +val res0: String = version 2.13.6 +``` ### Why is my (abstract or overridden) `val` null? From dcc51592443ca85e535c71068137865daf1ef17e Mon Sep 17 00:00:00 2001 From: czasoprzestrzenny <46657059+czasoprzestrzenny@users.noreply.github.com> Date: Fri, 11 Feb 2022 15:41:48 +0100 Subject: [PATCH 0971/2265] Update generic-classes.md changed a stack pop to stack.pop() --- _tour/generic-classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_tour/generic-classes.md b/_tour/generic-classes.md index 0b479d30df..d883e88115 100644 --- a/_tour/generic-classes.md +++ b/_tour/generic-classes.md @@ -38,8 +38,8 @@ To use a generic class, put the type in the square brackets in place of `A`. val stack = new Stack[Int] stack.push(1) stack.push(2) -println(stack.pop) // prints 2 -println(stack.pop) // prints 1 +println(stack.pop()) // prints 2 +println(stack.pop()) // prints 1 ``` The instance `stack` can only take Ints. However, if the type argument had subtypes, those could be passed in: ``` From 15ba133475ab1f48392e0b82f1356d93899f2178 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 15 Feb 2022 10:37:40 +0100 Subject: [PATCH 0972/2265] update install instructions for coursier Use the same instructions as listed on the official Coursier website, as git.io short url service is no longer maintained. --- _includes/_ja/getting-started.md | 8 ++++---- _includes/getting-started.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/_includes/_ja/getting-started.md b/_includes/_ja/getting-started.md index 0fe5652204..40bcf9ff29 100644 --- a/_includes/_ja/getting-started.md +++ b/_includes/_ja/getting-started.md @@ -14,7 +14,7 @@ Scala をインストールすると、コンパイラやビルドツールな ### Scala インストーラーを使う(推奨) -Scala のインストーラーは[Coursier](https://get-coursier.io/docs/cli-overview)というツールで、コマンドは`cs`です。このツールを使うと、JVM と標準 Scala ツールがシステムにインストールされます。 +Scala のインストーラーは[Coursier](https://get-coursier.io/docs/cli-overview)というツールで、コマンドは`cs`です。このツールを使うと、JVM と標準 Scala ツールがシステムにインストールされます。 以下の手順でお使いのシステムにインストールしてください。
    @@ -146,7 +146,7 @@ Scala について日本語で質問したい場合、Twitterでつぶやくと -- This is handled in `resources/js/functions.js`. -->

    または、Homebrewを使用しない場合は

    - $ curl -fLo cs https://git.io/coursier-cli-macos && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs setup
    + $ curl -fL https://github.com/coursier/launchers/raw/master/cs-x86_64-apple-darwin.gz | gzip -d > cs && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs setup
    diff --git a/_includes/getting-started.md b/_includes/getting-started.md index 628f2a41c5..83c1de45fe 100644 --- a/_includes/getting-started.md +++ b/_includes/getting-started.md @@ -170,7 +170,7 @@ There are a multitude of mailing lists and real-time chat rooms in case you want -- This is handled in `resources/js/functions.js`. -->

    Alternatively, if you don't use Homebrew

    - $ curl -fLo cs https://git.io/coursier-cli-macos && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs setup
    + $ curl -fL https://github.com/coursier/launchers/raw/master/cs-x86_64-apple-darwin.gz | gzip -d > cs && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs setup
    From b3e7f156841a4b3b7ec3f36d739f01d3c65874b1 Mon Sep 17 00:00:00 2001 From: Bersier Date: Wed, 16 Feb 2022 16:06:11 -0500 Subject: [PATCH 0973/2265] Update staging.md Added a link for "PCP". --- _scala3-reference/metaprogramming/staging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_scala3-reference/metaprogramming/staging.md b/_scala3-reference/metaprogramming/staging.md index 0e90966c85..bb35f51055 100644 --- a/_scala3-reference/metaprogramming/staging.md +++ b/_scala3-reference/metaprogramming/staging.md @@ -62,7 +62,7 @@ impose the following restrictions on the use of splices. The framework as discussed so far allows code to be staged, i.e. be prepared to be executed at a later stage. To run that code, there is another method in class `Expr` called `run`. Note that `$` and `run` both map from `Expr[T]` -to `T` but only `$` is subject to the PCP, whereas `run` is just a normal method. +to `T` but only `$` is subject to the [PCP](./macros.html#the-phase-consistency-principle), whereas `run` is just a normal method. `scala.quoted.staging.run` provides a `Quotes` that can be used to show the expression in its scope. On the other hand `scala.quoted.staging.withQuotes` provides a `Quotes` without evaluating the expression. From 99b84bc5a89a1e76535abbea3199d1bb8ee31020 Mon Sep 17 00:00:00 2001 From: Ye Shu Date: Sun, 20 Feb 2022 18:58:55 -0500 Subject: [PATCH 0974/2265] Fix deprecated warning in scala for java programer ``` warning: method + in class Int is deprecated (since 2.13.0): Adding a number and a String is deprecated. Use the string interpolation `s"$num$str"` override def toString(): String = year + "-" + month + "-" + day ``` --- _it/tutorials/scala-for-java-programmers.md | 2 +- _ja/tutorials/scala-for-java-programmers.md | 2 +- _ko/tutorials/scala-for-java-programmers.md | 2 +- _overviews/tutorials/scala-for-java-programmers.md | 2 +- _zh-cn/tutorials/scala-for-java-programmers.md | 2 +- _zh-tw/tutorials/scala-for-java-programmers.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_it/tutorials/scala-for-java-programmers.md b/_it/tutorials/scala-for-java-programmers.md index 5cf8cb4b1c..7a60a2d6c6 100644 --- a/_it/tutorials/scala-for-java-programmers.md +++ b/_it/tutorials/scala-for-java-programmers.md @@ -578,7 +578,7 @@ definendo la classe `Date` come segue: def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" La parte importante qui è la dichiarazione `extends Ord` che segue il nome della classe e dei parametri. Dichiara che la classe `Date` eredita il diff --git a/_ja/tutorials/scala-for-java-programmers.md b/_ja/tutorials/scala-for-java-programmers.md index 8d6fb7aef3..b49113ff72 100644 --- a/_ja/tutorials/scala-for-java-programmers.md +++ b/_ja/tutorials/scala-for-java-programmers.md @@ -461,7 +461,7 @@ Java の `Object` 型のより一般的なものとしてとらえられます def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" ここで重要なのは、クラス名とパラメータのあとに続く `extends Ord` という宣言です。 `Date` クラスが `Ord` トレイトを継承していることを宣言しています。 diff --git a/_ko/tutorials/scala-for-java-programmers.md b/_ko/tutorials/scala-for-java-programmers.md index 4f26dee244..b3f3d1b6d3 100644 --- a/_ko/tutorials/scala-for-java-programmers.md +++ b/_ko/tutorials/scala-for-java-programmers.md @@ -547,7 +547,7 @@ Java 프로그래머들이 트레잇을 이해하는 가장 쉬운 길은 코드 def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" 여기서 중요한 부분은 클래스 이름과 파라미터 뒤에 따라오는 `extends Ord` 선언이다. 이 선언은 `Date` 클래스가 `Ord` diff --git a/_overviews/tutorials/scala-for-java-programmers.md b/_overviews/tutorials/scala-for-java-programmers.md index 52c988066e..ebac87fce3 100644 --- a/_overviews/tutorials/scala-for-java-programmers.md +++ b/_overviews/tutorials/scala-for-java-programmers.md @@ -595,7 +595,7 @@ represent as integers. We therefore start the definition of the def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" The important part here is the `extends Ord` declaration which follows the class name and parameters. It declares that the diff --git a/_zh-cn/tutorials/scala-for-java-programmers.md b/_zh-cn/tutorials/scala-for-java-programmers.md index 9ee8838b4d..00559b596d 100644 --- a/_zh-cn/tutorials/scala-for-java-programmers.md +++ b/_zh-cn/tutorials/scala-for-java-programmers.md @@ -308,7 +308,7 @@ Java 中我们会将这个树用一个抽象父类表示,然后每种节点跟 def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" 这边要注意的是声明在类名称跟参数之后的 `extends Ord`。这个语法声明了 `Date` 继承 `Ord` 特质。 diff --git a/_zh-tw/tutorials/scala-for-java-programmers.md b/_zh-tw/tutorials/scala-for-java-programmers.md index 290ee22ac3..d9b4bcd4d0 100755 --- a/_zh-tw/tutorials/scala-for-java-programmers.md +++ b/_zh-tw/tutorials/scala-for-java-programmers.md @@ -308,7 +308,7 @@ Java 中我們會將這個樹用一個抽象母類別表示,然後每種節點 def year = y def month = m def day = d - override def toString(): String = year + "-" + month + "-" + day + override def toString(): String = s"$year-$month-$day" 這邊要注意的是宣告在類別名稱跟參數之後的 `extends Ord`。這個語法宣告了 `Date` 繼承 `Ord` 特質。 From cf096aebaaceb121695d1aea973c5216c97d8437 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 23 Feb 2022 20:24:54 -0800 Subject: [PATCH 0975/2265] Add lightbend blog post --- _overviews/compiler-options/optimizer.md | 221 +++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 _overviews/compiler-options/optimizer.md diff --git a/_overviews/compiler-options/optimizer.md b/_overviews/compiler-options/optimizer.md new file mode 100644 index 0000000000..a5cf6fbb29 --- /dev/null +++ b/_overviews/compiler-options/optimizer.md @@ -0,0 +1,221 @@ +# The Scala 2.12 / 2.13 Inliner and Optimizer + +_by [Lukas Rytz](https://github.com/lrytz), November 7, 2018_ + +tl;dr: + +- Don't enable the optimizer during development: it breaks incremental compilation, and it makes the compiler slower. Only enable it for testing, on CI, and to build releases. +- Enable method-local optimizations with `-opt:l:method`. This option is safe for binary compatibility, but typically doesn't improve performance on its own. +- Enable inlining in addition to method-local optimizations with `-opt:l:inline` and `-opt-inline-from:[PATTERN]` + - Don't inline from your dependencies when publishing a library, it breaks binary compatibility. Use `-opt-inline-from:my.package.**` to only inline from packages within your library. + - When compiling an application with global inlining (`-opt-inline-from:**`), ensure that the run-time classpath is exactly the same as the compile-time classpath. +- The `@inline` annotation only has an effect if the inliner is enabled. It tells the inliner to always try to inline the annotated method or callsite. +- Without the `@inline` annotation, the inliner generally inlines higher-order methods and forwarder methods. The main goal is to eliminate megamorphic callsites due to functions passed as argument, and to eliminate value boxing. Other optimizations are delegated to the JVM. + +To learn more, read on. + +## Intro + +The Scala compiler has included an inliner since version 2.0. Closure elimination and dead code elimination were added in 2.1. That was the first Scala optimizer, written and maintained by [Iulian Dragos](https://github.com/dragos). He continued to improve these features over time and consolidated them under the `-optimise` flag (later Americanized to `-optimize`), which remained available through Scala 2.11. + +The optimizer was re-written for Scala 2.12 to become more reliable and powerful – and to side-step the spelling issue by calling the new flag `-opt`. This post describes how to use the optimizer in Scala 2.12 and 2.13: what it does, how it works, and what are its limitations. + +## Motivation + +Why does the Scala compiler even have a JVM bytecode optimizer? The JVM is a highly optimized runtime with a just-in-time (JIT) compiler with 19 years of tuning. It's because there are certain well-known code patterns that the JVM fails to optimize properly. These patterns are common in functional languages such as Scala. (Increasingly, Java code with lambdas is catching up and showing the same performance issues at run-time.) + +The two most important such patterns are "megamorphic dispatch" (also called "the inlining problem") and value boxing. If you'd like to learn more about these problems in the context of Scala, you could watch the part of [my Scala Days 2015 talk (starting at 26:13)](https://youtu.be/Ic4vQJcYwsU?t=1573). + +The goal of the Scala optimizer is to produce bytecode that the JVM can execute fast. It is also a goal to avoid performing any optimizations that the JVM can already do well. + +This means that the Scala optimizer may become obsolete in the future, if the JIT compiler is improved to handle these patterns better. In fact, with the arrival of GraalVM, that future might be nearer than you think! We take a closer look at Graal in a follow-up post. But for now, we dive into some details about the Scala optimizer. + +## Constraints and assumptions + +The Scala optimizer has to make its improvements within fairly narrow constraints: + +- The optimizer only changes method bodies, but never signatures of classes or methods. The generated bytecode has the same (binary) interface, whether or not the optimizer is enabled. +- We don't assume the whole program (all user code plus all of its dependencies, that together make up an application) is known when running the optimizer. There may be classes on the run-time classpath that we don't see at compile-time: we may be compiling a library, or only a component of an application. This means that: + - Every non-final method can potentially be overridden, even if at compile-time there are no classes that define such an override + - Consequently, we can only inline methods that can be resolved at compile-time: final methods, methods in `object`s, and methods where the receiver's type is precisely known (for example, in `(new A).f`, the receiver is known to be exactly `A`, not a subtype of `A`). +- The optimizer does not break applications that use reflection. This follows from the two points above: changes to classes could be observed by reflection, and additional classes could be loaded and instantiated dynamically. + +However, even when staying within these constraints, some changes performed by the optimizer can be observed at run-time: + +- Inlined methods disappear from call stacks. + + - This can lead to unexpected behaviors when using a debugger. + - Related: line numbers (stored in bytecode) are discarded when a method is inlined into a different classfile, which also impacts debugging experience. (This [could be improved](https://github.com/scala/scala-dev/issues/3).) + +- Inlining a method can delay class loading of the class where the method is defined. + +- The optimizer assumes that modules (singletons like `object O`) are never `null`. + - This assumption can be false if the module is loaded in its superclass. The following example throws a `NullPointerException` when compiled normally, but prints `0` when compiled with the optimizer enabled: + + ```scala + class A { + println(Test.f) + } + object Test extends A { + @inline def f = 0 + def main(args: Array[String]): Unit = () + } + ``` + + - This assumption can be disabled with `-opt:-assume-modules-non-null`, which results in additional null checks in optimized code. + +- The optimizer removes unnecessary loads of certain built-in modules, for example `scala.Predef` and `scala.runtime.ScalaRunTime`. This means that initialization (construction) of these modules can be skipped or delayed. + + - For example, in `def f = 1 -> ""`, the method `Predef.->` is inlined and the access to `Predef` is eliminated. The resulting code is `def f = new Tuple2(1, "")`. + - This assumption can be disabled with `-opt:-allow-skip-core-module-init` + +- The optimizer eliminates unused `C.getClass` calls, which may delay class loading. This can be disabled with `-opt:-allow-skip-class-loading`. + +## Binary compatibility + +Scala minor releases are binary compatible with each other, for example 2.12.6 and 2.12.7. The same is true for many libraries in the Scala ecosystem. These binary compatibility promises are the main reason for the Scala optimizer not to be enabled everywhere. + +The reason is that inlining a method from one class into another changes the (binary) interface that is accessed: + +```scala +class C { + private[this] var x = 0 + @inline final def inc(): Int = { x += 1; x } +} +``` + +When inlining a callsite `c.inc()`, the resulting code no longer calls `inc`, but instead accesses the field `x` directly. Since that field is private (also in bytecode), inlining `inc` is only allowed within the class `C` itself. Trying to access `x` from any other class would cause an `IllegalAccessError` at run-time. + +However, there are many cases where implementation details in Scala source code become public in bytecode: + +```scala +class C { + private def x = 0 + @inline final def m: Int = x +} +object C { + def t(c: C) = c.x +} +``` + +Scala allows accessing the private method `x` in the companion object `C`. In bytecode, however, the classfile for the companion `C$` is not allowed to access a private method of `C`. For that reason, the Scala compiler "mangles" the name of `x` to `C$$x` and makes the method public. + +This means that `m` can be inlined into classes other than `C`, since the resulting code invokes `C.C$$x` instead of `C.m`. Unfortunately this breaks Scala's binary compatibility promise: the fact that the public method `m` calls a private method `x` is considered to be an implementation detail that can change in a minor release of the library defining `C`. + +Even more trivially, assume that method `m` was buggy and is changed to `def m = if (fullMoon) 1 else x` in a minor release. Normally, it would be enough for a user to put the new version on the classpath. However, if the old version of `c.m` was inlined at compile-time, having the new version of C on the run-time classpath would not fix the bug. + +In order to safely use the Scala optimizer, users need to make sure that the compile-time and run-time classpaths are identical. This has a far-reaching consequence for library developers: **libraries that are published to be consumed by other projects should not inline code from the classpath**. The inliner can be configured to inline code from the library itself using `-opt-inline-from:my.package.**`. + +The reason for this restriction is that dependency management tools like sbt will often pick newer versions of transitive dependencies. For example, if library `A` depends on `core-1.1.1`, `B` depends on `core-1.1.2` and the application depends on both `A` and `B`, the build tool will put `core-1.1.2` on the classpath. If code from `core-1.1.1` was inlined into `A` at compile-time, it might break at run-time due to a binary incompatibility. + +## Using and interacting with the optimizer + +The compiler flag for enabling the optimizer is `-opt`. Running `scalac -opt:help` shows how to use the flag. + +By default (without any compiler flags, or with `-opt:l:default`), the Scala compiler eliminates unreachable code, but does not run any other optimizations. + +`-opt:l:method` enables all method-local optimizations, for example: + +- Elimination of code that loads unused values +- Rewriting of null and `isInstanceOf` checks whose result is known at compile-time +- Elimination of value boxes like `java.lang.Integer` or `scala.runtime.DoubleRef` that are created within a method and don't escape it + +Individual optimizations can be disabled. For example, `-opt:l:method,-nullness-tracking` disables nullness optimizations. + +Method-local optimizations alone typically don't have any positive effect on performance, because source code usually doesn't have unnecessary boxing or null checks. However, local optimizations can often be applied after inlining, so it's really the combination of inlining and local optimizations that can improve program performance. + +`-opt:l:inline` enables inlining in addition to method-local optimizations. However, to avoid unexpected binary compatibility issues, we also need to tell the compiler which code it is allowed to inline. This is done with the `-opt-inline-from` compiler flag. Examples: + +- `-opt-inline-from:my.library.**` enables inlining from any class defined in package `my.library`, or in any of its sub-packages. Inlining within a library is safe for binary compatibility, so the resulting binary can be published. It will still work correctly even if one of its dependencies is updated to a newer minor version in the run-time classpath. +- `-opt-inline-from:` enables inlining from the set of source files being compiled in the current compiler invocation. This option can also be used for compiling libraries. If the source files of a library are split up across multiple sbt projects, inlining is only done within each project. Note that in an incremental compilation, inlining would only happen within the sources being re-compiled – but in any case, it is recommended to only enable the optimizer in CI and release builds (and to run `clean` before building). +- `-opt-inline-from:**` allows inlining from every class, including the JDK. This option enables full optimization when compiling an application. To avoid binary incompatibilities, it is mandatory to ensure that the run-time classpath is identical to the compile-time classpath, including the Java standard library. + +Running `scalac -opt-inline-from:help` explains how to use the compiler flag. + +### Inliner heuristics and `@inline` + +When the inliner is enabled, it automatically selects callsites for inlining according to a heuristic. + +As mentioned in the introduction, the main goal of the Scala optimizer is to eliminate megamorphic dispatch and value boxing. In order to keep this post from growing too long, a followup post will include the analysis of concrete examples that motivate which callsites are selected by the inliner heuristic. + +Nevertheless, it is useful to have an intuition of how the heuristic works, so here is an overview: + +- Methods or callsites annotated [`@noinline`](https://www.scala-lang.org/api/current/scala/noinline.html) are not inlined. +- The inliner doesn't inline *into* forwarder methods. +- Methods or callsites annotated [`@inline`](https://www.scala-lang.org/api/current/scala/inline.html) are inlined. +- Higher-order methods with a function literal as argument are inlined. +- Higher-order methods where a parameter function of the callsite method is forwarded to the callee are inlined. +- Methods with an `IntRef` / `DoubleRef` / ... parameter are inlined. When nested methods update variables of the outer method, those variables are boxed into `XRef` objects. These boxes can often be eliminated after inlining the nested method. +- Forwarders, factory methods and trivial methods are inlined. Examples include simple closure bodies like `_ + 1` and synthetic methods (potentially with boxing / unboxing adaptations) such as bridges. + +To prevent methods from exceeding the JVM's method size limit, the inliner has size limits. Inlining into a method stops when the number of instructions exceeds a certain threshold. + +As you can see in the list above, the `@inline` and `@noinline` annotations are the only way for programmers to influence inlining decisions. In general, our recommendation is to avoid using these annotations. If you observe issues with the inliner heuristic that can be fixed by annotating methods, we are very keen to hear about them, for example in the form of a [bug report](https://github.com/scala/bug/issues). + +A related anecdote: in the Scala compiler and standard library (which are built with the optimizer enabled), there are roughly 330 `@inline`-annotated methods. Removing all of these annotations and re-building the project has no effect on the compiler's performance. So the annotations are well-intended and benign, but in reality unnecessary. + +For expert users, `@inline` annotations can be used to hand-tune performance critical code without reducing abstraction. If you have a project that falls into this category, please [let us know](https://contributors.scala-lang.org), we're interested to learn more! + +Finally, note that the `@inline` annotation only has an effect when the inliner is enabled, which is not the case by default. The reason is to avoid introducing accidental binary incompatibilities, as [explained above](#binary-compatibility). + +### Inliner warnings + +The inliner can issue warnings when callsites cannot be inlined. By default, these warnings are not issued individually, but only as a summary at the end of compilation (similar to deprecation warnings). + +``` +$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' +warning: there was one inliner warning; re-run enabling -opt-warnings for details, or try -help +one warning found + +$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' -opt-warnings +Test.scala:3: warning: C::f()I is annotated @inline but could not be inlined: +The method is not final and may be overridden. + def t = f + ^ +one warning found +``` + +By default, the inliner issues warnings for invocations of methods annotated `@inline` that cannot be inlined. Here is the source code that was compiled in the commands above: + +```scala +class C { + @inline def f = 1 + def t = f // cannot inline: C.f is not final +} +object T extends C { + override def t = f // can inline: T.f is final +} +``` + +The `-opt-warnings` flag has more configurations. With `-opt-warnings:_`, a warning is issued for every callsite that is selected by the heuristic but cannot be inlined. See also `-opt-warnings:help`. + +### Inliner log + +If you're curious (or maybe even skeptical) about what the inliner is doing to your code, you can use the `-Yopt-log-inline` flag to produce a trace of the inliner's work: + +```scala +package my.project +class C { + def f(a: Array[Int]) = a.map(_ + 1) +} +``` + +``` +$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' -Yopt-log-inline my/project/C.f +Inlining into my/project/C.f + inlined scala/Predef$.intArrayOps (the callee is annotated `@inline`). Before: 15 ins, after: 30 ins. + inlined scala/collection/ArrayOps$.map$extension (the callee is a higher-order method, the argument for parameter (evidence$6: Function1) is a function literal). Before: 30 ins, after: 94 ins. + inlined scala/runtime/ScalaRunTime$.array_length (the callee is annotated `@inline`). Before: 94 ins, after: 110 ins. + [...] + rewrote invocations of closure allocated in my/project/C.f with body $anonfun$f$1: INVOKEINTERFACE scala/Function1.apply (Ljava/lang/Object;)Ljava/lang/Object; (itf) + inlined my/project/C.$anonfun$f$1 (the callee is a synthetic forwarder method). Before: 654 ins, after: 666 ins. + inlined scala/runtime/BoxesRunTime.boxToInteger (the callee is a forwarder method with boxing adaptation). Before: 666 ins, after: 674 ins. +``` + +Explaining the details here is out of scope for this post. We defer this discussion to a follow-up post that will explain the internals of the Scala optimizer in more detail. + +## Summary + +The goal of this article was to explain why the Scala optimizer exists and give a rough explanation what it can and cannot do. It also showed how to configure and use the optimizer in your project. + +In the next post, we will go into detail about how the optimizer works, what transformations are applied, and how they work together. We will also measure performance improvements that the optimizer can bring. Finally, we will look at related projects, dive a little more into the history of the optimizer, and discuss ideas for the future. From 13f8c85396d73527fdeab4372455424e1ed3a615 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 23 Feb 2022 21:39:23 -0800 Subject: [PATCH 0976/2265] Update optimizer overview --- _data/overviews.yml | 5 ++ _overviews/compiler-options/optimizer.md | 68 ++++++++++++------------ 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index cf89f286a7..ae56e9b5e9 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -259,6 +259,11 @@ icon: cog url: "compiler-options/errors.html" description: "A new engine for more user-friendly error messages, printing chains of dependent implicits and colored found/required type diffs." + - title: Optimizer + by: Lukas Rytz and Andrew Marki + icon: cog + url: "compiler-options/optimizer.html" + description: "The compiler can perform various optimizations as specified by compiler options." - category: Legacy diff --git a/_overviews/compiler-options/optimizer.md b/_overviews/compiler-options/optimizer.md index a5cf6fbb29..936967e8a0 100644 --- a/_overviews/compiler-options/optimizer.md +++ b/_overviews/compiler-options/optimizer.md @@ -1,18 +1,26 @@ -# The Scala 2.12 / 2.13 Inliner and Optimizer +--- +layout: singlepage-overview +title: Optimizer +--- + +**[Lukas Rytz](https://github.com/lrytz) (November 7, 2018)** -_by [Lukas Rytz](https://github.com/lrytz), November 7, 2018_ +**[Andrew Marki](https://github.com/som-snytt) (February 29, 2022)** -tl;dr: +# The Scala 2.12 / 2.13 Inliner and Optimizer +## In Brief + +- The Scala compiler has a compile-time optimizer that is available in versions 2.12 and 2.13, but not yet in Scala 3. - Don't enable the optimizer during development: it breaks incremental compilation, and it makes the compiler slower. Only enable it for testing, on CI, and to build releases. -- Enable method-local optimizations with `-opt:l:method`. This option is safe for binary compatibility, but typically doesn't improve performance on its own. -- Enable inlining in addition to method-local optimizations with `-opt:l:inline` and `-opt-inline-from:[PATTERN]` - - Don't inline from your dependencies when publishing a library, it breaks binary compatibility. Use `-opt-inline-from:my.package.**` to only inline from packages within your library. - - When compiling an application with global inlining (`-opt-inline-from:**`), ensure that the run-time classpath is exactly the same as the compile-time classpath. +- Enable method-local optimizations with `-opt:local`. This option is safe for binary compatibility, but typically doesn't improve performance on its own. +- Enable inlining in addition to method-local optimizations with `-opt:inline:[PATTERN]`. + - Don't inline from your dependencies when publishing a library, it breaks binary compatibility. Use `-opt:inline:my.package.**` to only inline from packages within your library. + - When compiling an application with global inlining (`-opt:inline:**`), ensure that the run-time classpath is **exactly the same** as the compile-time classpath. - The `@inline` annotation only has an effect if the inliner is enabled. It tells the inliner to always try to inline the annotated method or callsite. - Without the `@inline` annotation, the inliner generally inlines higher-order methods and forwarder methods. The main goal is to eliminate megamorphic callsites due to functions passed as argument, and to eliminate value boxing. Other optimizations are delegated to the JVM. -To learn more, read on. +Read more to learn more. ## Intro @@ -20,15 +28,17 @@ The Scala compiler has included an inliner since version 2.0. Closure eliminatio The optimizer was re-written for Scala 2.12 to become more reliable and powerful – and to side-step the spelling issue by calling the new flag `-opt`. This post describes how to use the optimizer in Scala 2.12 and 2.13: what it does, how it works, and what are its limitations. +The options were simplified for 2.13.9, as described here. The [earlier version](https://www.lightbend.com/blog/scala-inliner-optimizer) of this article uses the traditional forms, which are still supported. + ## Motivation -Why does the Scala compiler even have a JVM bytecode optimizer? The JVM is a highly optimized runtime with a just-in-time (JIT) compiler with 19 years of tuning. It's because there are certain well-known code patterns that the JVM fails to optimize properly. These patterns are common in functional languages such as Scala. (Increasingly, Java code with lambdas is catching up and showing the same performance issues at run-time.) +Why does the Scala compiler even have a JVM bytecode optimizer? The JVM is a highly optimized runtime with a just-in-time (JIT) compiler that benefits from over two decades of tuning. It's because there are certain well-known code patterns that the JVM fails to optimize properly. These patterns are common in functional languages such as Scala. (Increasingly, Java code with lambdas is catching up and showing the same performance issues at run-time.) The two most important such patterns are "megamorphic dispatch" (also called "the inlining problem") and value boxing. If you'd like to learn more about these problems in the context of Scala, you could watch the part of [my Scala Days 2015 talk (starting at 26:13)](https://youtu.be/Ic4vQJcYwsU?t=1573). The goal of the Scala optimizer is to produce bytecode that the JVM can execute fast. It is also a goal to avoid performing any optimizations that the JVM can already do well. -This means that the Scala optimizer may become obsolete in the future, if the JIT compiler is improved to handle these patterns better. In fact, with the arrival of GraalVM, that future might be nearer than you think! We take a closer look at Graal in a follow-up post. But for now, we dive into some details about the Scala optimizer. +This means that the Scala optimizer may become obsolete in the future, if the JIT compiler is improved to handle these patterns better. In fact, with the arrival of GraalVM, that future might be nearer than you think! But for now, we dive into some details about the Scala optimizer. ## Constraints and assumptions @@ -45,7 +55,7 @@ However, even when staying within these constraints, some changes performed by t - Inlined methods disappear from call stacks. - This can lead to unexpected behaviors when using a debugger. - - Related: line numbers (stored in bytecode) are discarded when a method is inlined into a different classfile, which also impacts debugging experience. (This [could be improved](https://github.com/scala/scala-dev/issues/3).) + - Related: line numbers (stored in bytecode) are discarded when a method is inlined into a different classfile, which also impacts debugging experience. (This [could be improved](https://github.com/scala/scala-dev/issues/3) and is expected to [progress](https://github.com/lampepfl/dotty/pull/11492).) - Inlining a method can delay class loading of the class where the method is defined. @@ -73,7 +83,7 @@ However, even when staying within these constraints, some changes performed by t ## Binary compatibility -Scala minor releases are binary compatible with each other, for example 2.12.6 and 2.12.7. The same is true for many libraries in the Scala ecosystem. These binary compatibility promises are the main reason for the Scala optimizer not to be enabled everywhere. +Scala minor releases are binary compatible with each other, for example, 2.12.6 and 2.12.7. The same is true for many libraries in the Scala ecosystem. These binary compatibility promises are the main reason for the Scala optimizer not to be enabled everywhere. The reason is that inlining a method from one class into another changes the (binary) interface that is accessed: @@ -112,25 +122,25 @@ The reason for this restriction is that dependency management tools like sbt wil The compiler flag for enabling the optimizer is `-opt`. Running `scalac -opt:help` shows how to use the flag. -By default (without any compiler flags, or with `-opt:l:default`), the Scala compiler eliminates unreachable code, but does not run any other optimizations. +By default (without any compiler flags, or with `-opt:default`), the Scala compiler eliminates unreachable code, but does not run any other optimizations. -`-opt:l:method` enables all method-local optimizations, for example: +`-opt:local` enables all method-local optimizations, for example: - Elimination of code that loads unused values - Rewriting of null and `isInstanceOf` checks whose result is known at compile-time - Elimination of value boxes like `java.lang.Integer` or `scala.runtime.DoubleRef` that are created within a method and don't escape it -Individual optimizations can be disabled. For example, `-opt:l:method,-nullness-tracking` disables nullness optimizations. +Individual optimizations can be disabled. For example, `-opt:local,-nullness-tracking` disables nullness optimizations. Method-local optimizations alone typically don't have any positive effect on performance, because source code usually doesn't have unnecessary boxing or null checks. However, local optimizations can often be applied after inlining, so it's really the combination of inlining and local optimizations that can improve program performance. -`-opt:l:inline` enables inlining in addition to method-local optimizations. However, to avoid unexpected binary compatibility issues, we also need to tell the compiler which code it is allowed to inline. This is done with the `-opt-inline-from` compiler flag. Examples: +`-opt:inline` enables inlining in addition to method-local optimizations. However, to avoid unexpected binary compatibility issues, we also need to tell the compiler which code it is allowed to inline. This is done by specifying a pattern after the option to select packages, classes, and methods for inlining. Examples: -- `-opt-inline-from:my.library.**` enables inlining from any class defined in package `my.library`, or in any of its sub-packages. Inlining within a library is safe for binary compatibility, so the resulting binary can be published. It will still work correctly even if one of its dependencies is updated to a newer minor version in the run-time classpath. -- `-opt-inline-from:` enables inlining from the set of source files being compiled in the current compiler invocation. This option can also be used for compiling libraries. If the source files of a library are split up across multiple sbt projects, inlining is only done within each project. Note that in an incremental compilation, inlining would only happen within the sources being re-compiled – but in any case, it is recommended to only enable the optimizer in CI and release builds (and to run `clean` before building). -- `-opt-inline-from:**` allows inlining from every class, including the JDK. This option enables full optimization when compiling an application. To avoid binary incompatibilities, it is mandatory to ensure that the run-time classpath is identical to the compile-time classpath, including the Java standard library. +- `-opt:inline:my.library.**` enables inlining from any class defined in package `my.library`, or in any of its sub-packages. Inlining within a library is safe for binary compatibility, so the resulting binary can be published. It will still work correctly even if one of its dependencies is updated to a newer minor version in the run-time classpath. +- `-opt-inline:`, where the pattern is the literal string ``, enables inlining from the set of source files being compiled in the current compiler invocation. This option can also be used for compiling libraries. If the source files of a library are split up across multiple sbt projects, inlining is only done within each project. Note that in an incremental compilation, inlining would only happen within the sources being re-compiled – but in any case, it is recommended to only enable the optimizer in CI and release builds (and to run `clean` before building). +- `-opt:inline:**` allows inlining from every class, including the JDK. This option enables full optimization when compiling an application. To avoid binary incompatibilities, it is mandatory to ensure that the run-time classpath is identical to the compile-time classpath, including the Java standard library. -Running `scalac -opt-inline-from:help` explains how to use the compiler flag. +Running `scalac -opt:help` explains how to use the compiler flag. ### Inliner heuristics and `@inline` @@ -163,11 +173,11 @@ Finally, note that the `@inline` annotation only has an effect when the inliner The inliner can issue warnings when callsites cannot be inlined. By default, these warnings are not issued individually, but only as a summary at the end of compilation (similar to deprecation warnings). ``` -$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' +$> scalac Test.scala '-opt:inline:**' warning: there was one inliner warning; re-run enabling -opt-warnings for details, or try -help one warning found -$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' -opt-warnings +$> scalac Test.scala '-opt:inline:**' -Wopt Test.scala:3: warning: C::f()I is annotated @inline but could not be inlined: The method is not final and may be overridden. def t = f @@ -187,11 +197,11 @@ object T extends C { } ``` -The `-opt-warnings` flag has more configurations. With `-opt-warnings:_`, a warning is issued for every callsite that is selected by the heuristic but cannot be inlined. See also `-opt-warnings:help`. +The `-Wopt` flag has more configurations. With `-Wopt:_`, a warning is issued for every callsite that is selected by the heuristic but cannot be inlined. See also `-Wopt:help`. ### Inliner log -If you're curious (or maybe even skeptical) about what the inliner is doing to your code, you can use the `-Yopt-log-inline` flag to produce a trace of the inliner's work: +If you're curious (or maybe even skeptical) about what the inliner is doing to your code, you can use the `-Vinline` verbose flag to produce a trace of the inliner's work: ```scala package my.project @@ -201,7 +211,7 @@ class C { ``` ``` -$> scalac Test.scala -opt:l:inline '-opt-inline-from:**' -Yopt-log-inline my/project/C.f +$> scalac Test.scala '-opt:inline:**' -Vinline my/project/C.f Inlining into my/project/C.f inlined scala/Predef$.intArrayOps (the callee is annotated `@inline`). Before: 15 ins, after: 30 ins. inlined scala/collection/ArrayOps$.map$extension (the callee is a higher-order method, the argument for parameter (evidence$6: Function1) is a function literal). Before: 30 ins, after: 94 ins. @@ -211,11 +221,3 @@ Inlining into my/project/C.f inlined my/project/C.$anonfun$f$1 (the callee is a synthetic forwarder method). Before: 654 ins, after: 666 ins. inlined scala/runtime/BoxesRunTime.boxToInteger (the callee is a forwarder method with boxing adaptation). Before: 666 ins, after: 674 ins. ``` - -Explaining the details here is out of scope for this post. We defer this discussion to a follow-up post that will explain the internals of the Scala optimizer in more detail. - -## Summary - -The goal of this article was to explain why the Scala optimizer exists and give a rough explanation what it can and cannot do. It also showed how to configure and use the optimizer in your project. - -In the next post, we will go into detail about how the optimizer works, what transformations are applied, and how they work together. We will also measure performance improvements that the optimizer can bring. Finally, we will look at related projects, dive a little more into the history of the optimizer, and discuss ideas for the future. From 3925a6475dfe3ff6ef0d25c319663d1117df31a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Feb 2022 02:56:40 +0000 Subject: [PATCH 0977/2265] Bump nokogiri from 1.12.5 to 1.13.3 Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.12.5 to 1.13.3. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.12.5...v1.13.3) --- updated-dependencies: - dependency-name: nokogiri dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0bbe4414f9..5b52d7697a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,9 +54,9 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - mini_portile2 (2.6.1) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + mini_portile2 (2.8.0) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) racc (~> 1.4) nokogumbo (2.0.2) nokogiri (~> 1.8, >= 1.8.4) @@ -64,7 +64,7 @@ GEM pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (4.0.6) - racc (1.5.2) + racc (1.6.0) rainbow (3.0.0) rb-fsevent (0.11.0) rb-inotify (0.10.1) From 582e6c017de371609f54545b0e340fe4287cc22f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 2 Mar 2022 07:06:41 -0800 Subject: [PATCH 0978/2265] Ruby 2.6 (was 2.5) --- .github/workflows/build.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9cca5b785..808f492a7d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.5.8 + ruby-version: 2.6.9 bundler-cache: true - name: Set up coursier uses: coursier/setup-action@v1.2.0-M2 diff --git a/Dockerfile b/Dockerfile index b972fe1c24..2fe3d70737 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.5 +FROM ruby:2.6 RUN gem install bundler jekyll From b33f3a7d286db7aa3d3eb481b1997b5d1ce7388b Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 3 Mar 2022 02:46:11 -0800 Subject: [PATCH 0979/2265] Review and corrections --- _data/overviews.yml | 2 +- _overviews/compiler-options/optimizer.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index ae56e9b5e9..a8bc055f7c 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -263,7 +263,7 @@ by: Lukas Rytz and Andrew Marki icon: cog url: "compiler-options/optimizer.html" - description: "The compiler can perform various optimizations as specified by compiler options." + description: "The compiler can perform various optimizations." - category: Legacy diff --git a/_overviews/compiler-options/optimizer.md b/_overviews/compiler-options/optimizer.md index 936967e8a0..cad7255280 100644 --- a/_overviews/compiler-options/optimizer.md +++ b/_overviews/compiler-options/optimizer.md @@ -3,9 +3,9 @@ layout: singlepage-overview title: Optimizer --- -**[Lukas Rytz](https://github.com/lrytz) (November 7, 2018)** +**[Lukas Rytz](https://github.com/lrytz) (2018)** -**[Andrew Marki](https://github.com/som-snytt) (February 29, 2022)** +**[Andrew Marki](https://github.com/som-snytt) (2022)** # The Scala 2.12 / 2.13 Inliner and Optimizer @@ -114,7 +114,7 @@ This means that `m` can be inlined into classes other than `C`, since the result Even more trivially, assume that method `m` was buggy and is changed to `def m = if (fullMoon) 1 else x` in a minor release. Normally, it would be enough for a user to put the new version on the classpath. However, if the old version of `c.m` was inlined at compile-time, having the new version of C on the run-time classpath would not fix the bug. -In order to safely use the Scala optimizer, users need to make sure that the compile-time and run-time classpaths are identical. This has a far-reaching consequence for library developers: **libraries that are published to be consumed by other projects should not inline code from the classpath**. The inliner can be configured to inline code from the library itself using `-opt-inline-from:my.package.**`. +In order to safely use the Scala optimizer, users need to make sure that the compile-time and run-time classpaths are identical. This has a far-reaching consequence for library developers: **libraries that are published to be consumed by other projects should not inline code from the classpath**. The inliner can be configured to inline code from the library itself using `-opt:inline:my.package.**`. The reason for this restriction is that dependency management tools like sbt will often pick newer versions of transitive dependencies. For example, if library `A` depends on `core-1.1.1`, `B` depends on `core-1.1.2` and the application depends on both `A` and `B`, the build tool will put `core-1.1.2` on the classpath. If code from `core-1.1.1` was inlined into `A` at compile-time, it might break at run-time due to a binary incompatibility. @@ -137,7 +137,7 @@ Method-local optimizations alone typically don't have any positive effect on per `-opt:inline` enables inlining in addition to method-local optimizations. However, to avoid unexpected binary compatibility issues, we also need to tell the compiler which code it is allowed to inline. This is done by specifying a pattern after the option to select packages, classes, and methods for inlining. Examples: - `-opt:inline:my.library.**` enables inlining from any class defined in package `my.library`, or in any of its sub-packages. Inlining within a library is safe for binary compatibility, so the resulting binary can be published. It will still work correctly even if one of its dependencies is updated to a newer minor version in the run-time classpath. -- `-opt-inline:`, where the pattern is the literal string ``, enables inlining from the set of source files being compiled in the current compiler invocation. This option can also be used for compiling libraries. If the source files of a library are split up across multiple sbt projects, inlining is only done within each project. Note that in an incremental compilation, inlining would only happen within the sources being re-compiled – but in any case, it is recommended to only enable the optimizer in CI and release builds (and to run `clean` before building). +- `-opt:inline:`, where the pattern is the literal string ``, enables inlining from the set of source files being compiled in the current compiler invocation. This option can also be used for compiling libraries. If the source files of a library are split up across multiple sbt projects, inlining is only done within each project. Note that in an incremental compilation, inlining would only happen within the sources being re-compiled – but in any case, it is recommended to only enable the optimizer in CI and release builds (and to run `clean` before building). - `-opt:inline:**` allows inlining from every class, including the JDK. This option enables full optimization when compiling an application. To avoid binary incompatibilities, it is mandatory to ensure that the run-time classpath is identical to the compile-time classpath, including the Java standard library. Running `scalac -opt:help` explains how to use the compiler flag. @@ -174,7 +174,7 @@ The inliner can issue warnings when callsites cannot be inlined. By default, the ``` $> scalac Test.scala '-opt:inline:**' -warning: there was one inliner warning; re-run enabling -opt-warnings for details, or try -help +warning: there was one inliner warning; re-run enabling -Wopt for details, or try -help one warning found $> scalac Test.scala '-opt:inline:**' -Wopt From 5ab2ddda467ac4b3228338002648c0315da28269 Mon Sep 17 00:00:00 2001 From: Brian Yue Date: Sat, 5 Mar 2022 12:19:04 +0800 Subject: [PATCH 0980/2265] Fix invalid links --- _overviews/scaladoc/contribute.md | 2 +- _scala3-reference/other-new-features/explicit-nulls.md | 2 +- scala3/scaladoc.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_overviews/scaladoc/contribute.md b/_overviews/scaladoc/contribute.md index c902e99f97..dc0af2ce57 100644 --- a/_overviews/scaladoc/contribute.md +++ b/_overviews/scaladoc/contribute.md @@ -25,4 +25,4 @@ which covers the steps and workflow necessary work on the Scaladoc tool. As of Scala 2.13, the Scaladoc tool is maintained but not actively developed. Major development of Scaladoc will progress as a part of Dotty for Scala 3 in the -[Dottydoc](https://dotty.epfl.ch/docs/usage/dottydoc.html) tool. +[Scaladoc]({% link _overviews/scala3-scaladoc/index.md %}) tool. diff --git a/_scala3-reference/other-new-features/explicit-nulls.md b/_scala3-reference/other-new-features/explicit-nulls.md index a0dac187ae..d33d86c931 100644 --- a/_scala3-reference/other-new-features/explicit-nulls.md +++ b/_scala3-reference/other-new-features/explicit-nulls.md @@ -537,4 +537,4 @@ Our strategy for binary compatibility with Scala binaries that predate explicit and new libraries compiled without `-Yexplicit-nulls` is to leave the types unchanged and be compatible but unsound. -[More details](https://dotty.epfl.ch/docs/internals/explicit-nulls.html) +[More details](https://dotty.epfl.ch/3.0.0/docs/internals/explicit-nulls.html) diff --git a/scala3/scaladoc.md b/scala3/scaladoc.md index 69c307654e..3b8e90b7d8 100644 --- a/scala3/scaladoc.md +++ b/scala3/scaladoc.md @@ -79,7 +79,7 @@ For more information see [Guides](/scala3/guides/scaladoc/search-engine.html) Note that this feature is still in development, so it can be subject to considerable change. If you encounter a bug or have an idea for improvement, don't hesitate to create an issue on [Inkuire](https://github.com/VirtusLab/Inkuire/issues/new) or [dotty](https://github.com/lampepfl/dotty/issues/new). -[scaladoc-docstrings]: https://dotty.epfl.ch/docs/usage/scaladoc/docstrings.html -[static-documentation]: https://dotty.epfl.ch/docs/usage/scaladoc/static-site.html -[built-in-blog]: https://dotty.epfl.ch/docs/usage/scaladoc/blog.html +[scaladoc-docstrings]: {% link _overviews/scala3-scaladoc/docstrings.md %} +[static-documentation]: {% link _overviews/scala3-scaladoc/static-site.md %} +[built-in-blog]: {% link _overviews/scala3-scaladoc/blog.md %} [social-links]: https://dotty.epfl.ch/docs/usage/scaladoc/settings.html#-social-links From 821446e2eb2ed77a39e0839698f821b5e5051562 Mon Sep 17 00:00:00 2001 From: Brian Yue Date: Fri, 4 Mar 2022 22:47:25 +0800 Subject: [PATCH 0981/2265] [zh-cn] Scala 3 Features --- _zh-cn/overviews/scala3-book/introduction.md | 12 +- .../overviews/scala3-book/scala-features.md | 891 ++++++++++++++++++ 2 files changed, 897 insertions(+), 6 deletions(-) create mode 100644 _zh-cn/overviews/scala3-book/scala-features.md diff --git a/_zh-cn/overviews/scala3-book/introduction.md b/_zh-cn/overviews/scala3-book/introduction.md index 158c93df11..21d8562dc2 100644 --- a/_zh-cn/overviews/scala3-book/introduction.md +++ b/_zh-cn/overviews/scala3-book/introduction.md @@ -4,7 +4,7 @@ type: chapter description: This page begins the overview documentation of the Scala 3 language. num: 1 previous-page: -next-page: +next-page: scala-features scala3: true partof: scala3-book @@ -14,13 +14,13 @@ permalink: "/zh-cn/scala3/book/:title.html" --- 欢迎阅读《Scala 3》一书。 -本书的目标是提供对Scala语言的非正式介绍,并以相对轻松的方式涉及所有的Scala主题。 -若您在阅读本书时想了解有关特定功能的更多信息,可以随时参阅[_参考文档_][reference],其中更详细地涵盖了Scala语言的许多新特性。 +本书的目标是提供对 Scala 语言的非正式介绍,并以相对轻松的方式涉及所有的 Scala 主题。 +若您在阅读本书时想了解有关特定功能的更多信息,可以随时参阅[_参考文档_][reference],其中更详细地涵盖了 Scala 语言的许多新特性。 -在本书中,我们希望证明Scala是一种优美的、富有表现力的编程语言。它具有简洁、现代的语法,支持函数式编程(FP)和面向对象编程(OOP),并提供安全的静态类型系统。 -Scala的语法和特性都经过了重新思考与公开辩论,并在2020年更新,比以往任何时候都更清晰、更容易理解。 +在本书中,我们希望证明 Scala 是一种优美的、富有表现力的编程语言。它具有简洁、现代的语法,支持函数式编程(FP)和面向对象编程(OOP),并提供安全的静态类型系统。 +Scala 的语法和特性都经过了重新思考与公开辩论,并在2020年更新,比以往任何时候都更清晰、更容易理解。 -本书首先在[“品味Scala”部分][taste]对Scala的许多特性进行了一次“旋风之旅”。随后的章节会提供有关这些语言特性的更多详细信息。 +本书首先在[“品味 Scala”部分][taste]对 Scala 的许多特性进行了一次“旋风之旅”。随后的章节会提供有关这些语言特性的更多详细信息。 > 我们仍在撰写本书的过程中。 > 您可以[帮助我们改进][contributing] diff --git a/_zh-cn/overviews/scala3-book/scala-features.md b/_zh-cn/overviews/scala3-book/scala-features.md new file mode 100644 index 0000000000..394681e1cf --- /dev/null +++ b/_zh-cn/overviews/scala3-book/scala-features.md @@ -0,0 +1,891 @@ +--- +title: Scala 3 特性 +type: chapter +description: This page discusses the main features of the Scala 3 programming language. +num: 2 +previous-page: introduction +next-page: + +scala3: true +partof: scala3-book +overview-name: "Scala 3 — Book" +layout: multipage-overview +permalink: "/zh-cn/scala3/book/:title.html" +--- + +{% comment %} +The name _Scala_ comes from the word _scalable_, and true to that name, the Scala language is used to power busy websites and analyze huge data sets. +This section introduces the features that make Scala a scalable language. +These features are split into three sections: +{% endcomment %} + +_Scala_ 这个名字来源于 _scalable_ 一词。正如其名,Scala 语言被用于支撑高流量网站以及分析庞大的数据集。 +本节介绍了使 Scala 成为一门可扩展语言的特性。 +这些特性分为三个部分: + +{% comment %} + +- High-level language features +- Lower-level language features +- Scala ecosystem features + +{% endcomment %} + +- 高级语言特性 +- 底层语言特性 +- Scala 生态系统特性 + +{% comment %} +I think of this section as being like an “elevator pitch.” +{% endcomment %} + +{% comment %} + +## High-level features + +{% endcomment %} + +## 高级特性 + +{% comment %} +Looking at Scala from the proverbial “30,000 foot view,” you can make the following statements about it: +{% endcomment %} + +从宏观视角来看 Scala,您可以对它做出以下陈述: + +{% comment %} + +- It’s a high-level programming language +- It has a concise, readable syntax +- It’s statically-typed (but feels dynamic) +- It has an expressive type system +- It’s a functional programming (FP) language +- It’s an object-oriented programming (OOP) language +- It supports the fusion of FP and OOP +- Contextual abstractions provide a clear way to implement _term inference_ +- It runs on the JVM (and in the browser) +- It interacts seamlessly with Java code +- It’s used for server-side applications (including microservices), big data applications, and can also be used in the browser with Scala.js + +{% endcomment %} + +- 它是一种高级编程语言 +- 它具有简明易读的语法 +- 它是静态类型的(但使人感觉是动态的) +- 它有一个表达力强大的类型系统 +- 它是一种函数式编程(FP)语言 +- 它是一种面向对象的编程(OOP)语言 +- 它支持 FP 与 OOP 的融合 +- 上下文抽象提供了一种清晰的方式来实现 _表达式推断_ +- 它在 JVM(和浏览器)上运行 +- 它与 Java 代码无缝交互 +- 它可被用于服务器端应用(包括微服务)、大数据应用,也可以在浏览器中与 Scala.js 共同使用 + +{% comment %} +The following sections take a quick look at these features. +{% endcomment %} + +以下部分将对这些特性进行简要介绍。 + +{% comment %} + +### A high-level language + +{% endcomment %} + +### 一门高级语言 + +{% comment %} +Scala is considered a high-level language in at least two ways. +First, like Java and many other modern languages, you don’t deal with low-level concepts like pointers and memory management. +{% endcomment %} + +Scala 至少在两个方面被认为是一门高级语言。 +首先,像 Java 和许多其他现代语言一样,您不需要与指针和内存管理等底层概念打交道。 + +{% comment %} +Second, with the use of lambdas and higher-order functions, you write your code at a very high level. +As the functional programming saying goes, in Scala you write _what_ you want, not _how_ to achieve it. +That is, we don’t write imperative code like this: +{% endcomment %} + +其次,通过使用 lambda 与高阶函数,您可以在非常高的层次上编写代码。 +正如函数式编程的说法,在 Scala 中,您编写您想要 _“什么”_,而不是 _“如何”_ 去实现它。 +也就是说,我们不会像这样编写命令式代码: + +```scala +def double(ints: List[Int]): List[Int] = { + val buffer = new ListBuffer[Int]() + for (i <- ints) { + buffer += i * 2 + } + buffer.toList +} + +val newNumbers = double(oldNumbers) +``` + +{% comment %} +That code instructs the compiler what to do on a step-by-step basis. +Instead, we write high-level, functional code using higher-order functions and lambdas like this to compute the same result: +{% endcomment %} + +这段代码指示编译器逐步执行特定操作。 +相反,我们使用像这样的高阶函数与 lambda 来编写高层次的函数式代码以计算出相同的结果: + +```scala +val newNumbers = oldNumbers.map(_ * 2) +``` + +{% comment %} +As you can see, that code is much more concise, easier to read, and easier to maintain. +{% endcomment %} + +如您所见,该代码更简洁、更容易阅读且更易于维护。 + +{% comment %} + +### Concise syntax + +{% endcomment %} + +### 简明的语法 + +{% comment %} +Scala has a concise, readable syntax. +For instance, variables are created concisely, and their types are clear: +{% endcomment %} + +Scala 具有简明易读的语法。例如,变量的创建十分简洁,其类型也很明确。 + +```scala +val nums = List(1,2,3) +val p = Person("Martin", "Odersky") +``` + +{% comment %} +Higher-order functions and lambdas make for concise code that’s readable: +{% endcomment %} + +高阶函数与 lambda 使代码简明易读: + +```scala +nums.map(i => i * 2) // long form +nums.map(_ * 2) // short form + +nums.filter(i => i > 1) +nums.filter(_ > 1) +``` + +{% comment %} +Traits, classes, and methods are defined with a clean, light syntax: +{% endcomment %} + +特质(Traits)、类(Class)和方法(Method)都是用简洁、轻巧的语法定义的。 + +```scala +trait Animal: + def speak(): Unit + +trait HasTail: + def wagTail(): Unit + +class Dog extends Animal, HasTail: + def speak() = println("Woof") + def wagTail() = println("⎞⎜⎛ ⎞⎜⎛") +``` + +{% comment %} +Studies have shown that the time a developer spends _reading_ code to _writing_ code is at least a 10:1 ratio, so writing code that is concise _and_ readable is important. +{% endcomment %} + +研究表明,开发人员花在 _阅读_ 代码和 _编写_ 代码上的时间比例至少为 10:1。因此,编写简洁 _并_ 易读的代码非常重要。 + +{% comment %} + +### A dynamic feel + +{% endcomment %} + +### 动态感受 + +{% comment %} +Scala is a statically-typed language, but thanks to its type inference capabilities it feels dynamic. +All of these expressions look like a dynamically-typed language like Python or Ruby, but they’re all Scala: +{% endcomment %} + +Scala 是一种静态类型的语言,但由于其类型推断能力,它使人感觉是动态的。所有这些表达式看起来都像 Python 或 Ruby 这样的动态类型语言代码,但其实它们都是 Scala 代码: + +```scala +val s = "Hello" +val p = Person("Al", "Pacino") +val sum = ints.reduceLeft(_ + _) +val y = for i <- nums yield i * 2 +val z = nums.filter(_ > 100) + .filter(_ < 10_000) + .map(_ * 2) +``` + +{% comment %} +As Heather Miller states, Scala is considered to be a [strong, statically-typed language](https://heather.miller.am/blog/types-in-scala.html), and you get all the benefits of static types: +{% endcomment %} + +正如 Heather Miller 所说,Scala 被认为是一种[强静态类型语言](https://heather.miller.am/blog/types-in-scala.html)。您可以获得静态类型的全部益处: + +{% comment %} + +- Correctness: you catch most errors at compile-time +- Great IDE support + - Reliable code completion + - Catching errors at compile-time means catching mistakes as you type + - Easy and reliable refactoring +- You can refactor your code with confidence +- Method type declarations tell readers what the method does, and help serve as documentation +- Scalability and maintainability: types help ensure correctness across arbitrarily large applications and development teams +- Strong typing in combination with excellent inference enables mechanisms like [contextual abstraction]({{ site.scala3ref }}/contextual.html) that allows you to omit boilerplate code. Often, this boilerplate code can be inferred by the compiler, based on type definitions and a given context. + +{% endcomment %} + +- 正确性:您可以在编译时捕获大多数错误 +- 强大的 IDE 支持 + - 可靠的代码补全 + - 在编译时捕获错误意味着在您打字时捕获错误 + - 简单而可靠的重构 +- 您可以自信地重构您的代码 +- 方法类型声明告诉读者该方法的作用,并作为文档提供帮助 +- 可扩展性与可维护性:类型有助于在任意大小的应用程序与开发团队中确保正确性 +- 强类型结合优秀的推断能力可实现[上下文抽象]({{ site.scala3ref }}/contextual.html)等机制,这允许您省略样板代码。通常,这些样板代码可由编译器根据类型定义及给定的上下文推断出来。 + +{% comment %} +In that list: +- 'Correctness' and 'Scalability' come from Heather Miller’s page +- the IDE-related quotes in this section come from the Scala.js website: + - catch most errors in the IDE + - Easy and reliable refactoring + - Reliable code completion +{% endcomment %} + +{% comment %} + +### Expressive type system + +{% endcomment %} + +### 富有表现力的类型系统 + +{% comment %} +- this text comes from the current [ScalaTour](https://docs.scala-lang.org/tour/tour-of-scala.html). +- TODO: all of the URLs will have to be updated + +- i removed these items until we can replace them: +* [Compound types](/tour/compound-types.html) +* [conversions](/tour/implicit-conversions.html) +* [Explicitly typed self references](/tour/self-types.html) +{% endcomment %} + +{% comment %} +Scala’s type system enforces, at compile-time, that abstractions are used in a safe and coherent manner. +In particular, the type system supports: +{% endcomment %} + +Scala 的类型系统在编译时强制要求以安全与连贯的方式使用抽象概念。特别是,该类型系统支持: + +{% comment %} +- [Inferred types]({% link _overviews/scala3-book/types-inferred.md %}) +- [Generic classes]({% link _overviews/scala3-book/types-generics.md %}) +- [Variance annotations]({% link _overviews/scala3-book/types-variance.md %}) +- [Upper](/tour/upper-type-bounds.html) and [lower](/tour/lower-type-bounds.html) type bounds +- [Polymorphic methods](/tour/polymorphic-methods.html) +- [Intersection types]({% link _overviews/scala3-book/types-intersection.md %}) +- [Union types]({% link _overviews/scala3-book/types-union.md %}) +- [Type lambdas]({{ site.scala3ref }}/new-types/type-lambdas.html) +- [`given` instances and `using` clauses]({% link _overviews/scala3-book/ca-given-using-clauses.md %}) +- [Extension methods]({% link _overviews/scala3-book/ca-extension-methods.md %}) +- [Type classes]({% link _overviews/scala3-book/ca-type-classes.md %}) +- [Multiversal equality]({% link _overviews/scala3-book/ca-multiversal-equality.md %}) +- [Opaque type aliases]({% link _overviews/scala3-book/types-opaque-types.md %}) +- [Open classes]({{ site.scala3ref }}/other-new-features/open-classes.html) +- [Match types]({{ site.scala3ref }}/new-types/match-types.html) +- [Dependent function types]({{ site.scala3ref }}/new-types/dependent-function-types.html) +- [Polymorphic function types]({{ site.scala3ref }}/new-types/polymorphic-function-types.html) +- [Context bounds]({{ site.scala3ref }}/contextual/context-bounds.html) +- [Context functions]({{ site.scala3ref }}/contextual/context-functions.html) +- [Inner classes](/tour/inner-classes.html) and [abstract type members](/tour/abstract-type-members.html) as object members +{% endcomment %} + +- [推断类型]({% link _overviews/scala3-book/types-inferred.md %}) +- [泛型类]({% link _overviews/scala3-book/types-generics.md %}) +- [型变]({% link _overviews/scala3-book/types-variance.md %}) +- [类型上界](/tour/upper-type-bounds.html) 与 [类型下界](/tour/lower-type-bounds.html) +- [多态方法](/tour/polymorphic-methods.html) +- [交叉类型]({% link _overviews/scala3-book/types-intersection.md %}) +- [联合类型]({% link _overviews/scala3-book/types-union.md %}) +- [类型 Lambda]({{ site.scala3ref }}/new-types/type-lambdas.html) +- [`given` 实例与 `using` 子句]({% link _overviews/scala3-book/ca-given-using-clauses.md %}) +- [扩展方法]({% link _overviews/scala3-book/ca-extension-methods.md %}) +- [类型类]({% link _overviews/scala3-book/ca-type-classes.md %}) +- [多元相等]({% link _overviews/scala3-book/ca-multiversal-equality.md %}) +- [不透明类型别名]({% link _overviews/scala3-book/types-opaque-types.md %}) +- [开放类]({{ site.scala3ref }}/other-new-features/open-classes.html) +- [匹配类型]({{ site.scala3ref }}/new-types/match-types.html) +- [依赖函数类型]({{ site.scala3ref }}/new-types/dependent-function-types.html) +- [多态函数类型]({{ site.scala3ref }}/new-types/polymorphic-function-types.html) +- [上下文边界]({{ site.scala3ref }}/contextual/context-bounds.html) +- [上下文函数]({{ site.scala3ref }}/contextual/context-functions.html) +- 作为对象成员的[内部类](/tour/inner-classes.html) 与 [抽象类型](/tour/abstract-type-members.html) + +{% comment %} +In combination, these features provide a powerful basis for the safe reuse of programming abstractions and for the type-safe extension of software. +{% endcomment %} + +通过结合使用,这些特性为编程抽象的安全重用及软件的类型安全扩展提供了强大的基础。 + +{% comment %} + +### A functional programming language + +{% endcomment %} + +### 一门函数式编程语言 + +{% comment %} +Scala is a functional programming (FP) language, meaning: +{% endcomment %} + +Scala 是一门函数式编程(FP)语言,也就是说: + +{% comment %} + +- Functions are values, and can be passed around like any other value +- Higher-order functions are directly supported +- Lambdas are built in +- Everything in Scala is an expression that returns a value +- Syntactically it’s easy to use immutable variables, and their use is encouraged +- It has a wealth of immutable collection classes in the standard library +- Those collection classes come with dozens of functional methods: they don’t mutate the collection, but instead return an updated copy of the data + +{% endcomment %} + +- 函数是值,可以像任何其他值一样被传递 +- 直接支持高阶函数 +- 原生地支持 Lambda +- Scala 中的一切都是会返回值的表达式 +- 从语法上来说,使用不可变变量很容易并且此行为被鼓励 +- 在标准库中有大量的不可变集合类 +- 这些集合类带有许多函数式方法:它们不改变集合本身,而是返回数据的更新副本 + +{% comment %} + +### An object-oriented language + +{% endcomment %} + +### 一门面向对象语言 + +{% comment %} +Scala is an object-oriented programming (OOP) language. +Every value is an instance of a class and every “operator” is a method. +{% endcomment %} + +Scala 是一门面向对象编程(OOP)语言。 +每个值都是一个类的实例,每个“运算符”都是一个方法。 + +{% comment %} +In Scala, all types inherit from a top-level class `Any`, whose immediate children are `AnyVal` (_value types_, such as `Int` and `Boolean`) and `AnyRef` (_reference types_, as in Java). +This means that the Java distinction between primitive types and boxed types (e.g. `int` vs. `Integer`) isn’t present in Scala. +Boxing and unboxing is completely transparent to the user. +{% endcomment %} + +在 Scala 中,所有类型都继承自顶层类 `Any`,其直接子类是 `AnyVal`(_值类型_,例如 `Int` 与 `Boolean`)和 `AnyRef`(_引用类型_,与 Java 中相同)。 +这意味着 Scala 中不存在 Java 中原始类型和包装类型的区别(例如 `int` 与 `Integer`)。 +装箱与拆箱对用户来说是完全透明的。 + +{% comment %} +- AnyRef above is wrong in case of strict null checking, no? On the other hand, maybe too much information to state this here +- probably not worth to mention (too advanced at this point) there is AnyKind +- Add the “types hierarchy” image here? +{% endcomment %} + +{% comment %} + +### Supports FP/OOP fusion + +{% endcomment %} + +### 支持 FP 与 OOP 融合 + +{% comment %} +NOTE: This text in the first line comes from this slide: https://twitter.com/alexelcu/status/996408359514525696 +{% endcomment %} + +{% comment %} +The essence of Scala is the fusion of functional programming and object-oriented programming in a typed setting: + +- Functions for the logic +- Objects for the modularity + +As [Martin Odersky has stated](https://jaxenter.com/current-state-scala-odersky-interview-129495.html), “Scala was designed to show that a fusion of functional and object-oriented programming is possible and practical.” +{% endcomment %} + +Scala 的本质是函数式编程和面向对象编程的融合: + +- 函数用于代表逻辑 +- 对象用于模块化 + +正如 [Martin Odersky 所说](https://jaxenter.com/current-state-scala-odersky-interview-129495.html),“Scala 旨在表明函数式编程与面向对象编程的融合是切实可行的。” + +{% comment %} + +### Term inference, made clearer + +{% endcomment %} + +### 表达式推断,更加清晰 + +{% comment %} +Following Haskell, Scala was the second popular language to have some form of _implicits_. +In Scala 3 these concepts have been completely re-thought and more clearly implemented. + +The core idea is _term inference_: Given a type, the compiler synthesizes a “canonical” term that has that type. +In Scala, a context parameter directly leads to an inferred argument term that could also be written down explicitly. + +Use cases for this concept include implementing [type classes]({% link _overviews/scala3-book/ca-type-classes.md %}), establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them. + +Scala 3 makes this process more clear than ever before. +Read about contextual abstractions in the [Reference documentation]({{ site.scala3ref }}/contextual.html). +{% endcomment %} + +继 Haskell 之后,Scala 是第二种具有某种形式的 _隐式_ 的流行语言。 +在 Scala 3 中,这些概念经过了重新考虑并更清晰地实现。 + +其核心思想是 _表达式推断_:给定一个类型,编译器会合成一个具有该类型的“规范”表达式。 +在 Scala 中,一个上下文参数直接导致一个被推断出的参数项的出现。该参数项也可以被显式地写出来。 + +此概念的用例包括实现[类型类]({% link _overviews/scala3-book/ca-type-classes.md %})、建立上下文、依赖注入、表达能力、计算新类型以及证明它们之间的关系。 + +Scala 3 使此过程比以往任何时候都更加清晰。 +请在[参考文档]({{ site.scala3ref }}/contextual.html)中阅读关于上下文抽象的内容。 + +{% comment %} + +### Client & server + +{% endcomment %} + +### 客户端与服务器 + +{% comment %} +Scala code runs on the Java Virtual Machine (JVM), so you get all of its benefits: + +- Security +- Performance +- Memory management +- Portability and platform independence +- The ability to use the wealth of existing Java and JVM libraries + +In addition to running on the JVM, Scala also runs in the browser with Scala.js (and open source third-party tools to integrate popular JavaScript libraries), and native executables can be built with Scala Native and GraalVM. +{% endcomment %} + +Scala 代码在 Java 虚拟机(JVM)上运行,因此您可以获得它的全部益处: + +- 安全性 +- 性能 +- 内存管理 +- 可移植性与平台独立性 +- 能够使用大量的现有 Java 和 JVM 库 + +除了在 JVM 上运行外,Scala 还可以通过 Scala.js (以及开源的第三方工具以集成流行的 JavaScript 库)在浏览器中运行,并且可以使用Scala Native 与 GraalVM 构建原生可执行文件。 + +{% comment %} + +### Seamless Java interaction + +{% endcomment %} + +### 与 Java 无缝交互 + +{% comment %} +You can use Java classes and libraries in your Scala applications, and you can use Scala code in your Java applications. +In regards to the second point, large libraries like [Akka](https://akka.io) and the [Play Framework](https://www.playframework.com) are written in Scala, and can be used in Java applications. +{% endcomment %} + +您可以在 Scala 应用程序中使用 Java 类和库,也可以在 Java 应用程序中使用 Scala 代码。 +对于第二点来说,诸如 [Akka](https://akka.io) 和 [Play Framework](https://www.playframework.com) 之类的大型库是用 Scala 编写的,并且它们可以在 Java 应用程序中使用。 + +{% comment %} +In regards to the first point, Java classes and libraries are used in Scala applications every day. +For instance, in Scala you can read files with a Java `BufferedReader` and `FileReader`: +{% endcomment %} + +对于第一点来说,Scala 应用程序中每天都会用到 Java 类和库。 +例如,在 Scala 中,您可以使用 Java 的 `BufferedReader` 和 `FileReader` 来读取文件: + +```scala +import java.io.* +val br = BufferedReader(FileReader(filename)) +// read the file with `br` ... +``` + +{% comment %} +Using Java code in Scala is generally seamless. + +Java collections can also be used in Scala, and if you want to use Scala’s rich collection class methods with them, you can convert them with just a few lines of code: +{% endcomment %} + +在 Scala 中使用 Java 代码通常是无缝衔接的。 + +Java 集合也可以在 Scala 中使用, 如果您想将 Scala 丰富的集合类方法与其一起使用,只需几行代码即可转换它们: + + +```scala +import scala.jdk.CollectionConverters.* +val scalaList: Seq[Integer] = JavaClass.getJavaList().asScala.toSeq +``` + +{% comment %} + +### Wealth of libraries + +{% endcomment %} + +### 丰富的库 + +{% comment %} +As you’ll see in the third section of this page, Scala libraries and frameworks like these have been written to power busy websites and work with huge datasets: + +1. The [Play Framework](https://www.playframework.com) is a lightweight, stateless, developer-friendly, web-friendly architecture for creating highly-scalable applications +2. [Lagom](https://www.lagomframework.com) is a microservices framework that helps you decompose your legacy monolith and build, test, and deploy entire systems of reactive microservices +3. [Apache Spark](https://spark.apache.org) is a unified analytics engine for big data processing, with built-in modules for streaming, SQL, machine learning and graph processing + +The [Awesome Scala list](https://github.com/lauris/awesome-scala) shows dozens of additional open source tools that developers have created to build Scala applications. + +In addition to server-side programming, [Scala.js](https://www.scala-js.org) is a strongly-typed replacement for writing JavaScript, with open source third-party libraries that include tools to integrate with Facebook’s React library, jQuery, and more. +{% endcomment %} + +正如您将在本页的第三部分中所看到的那样,已经有诸如此类的 Scala 库和框架被编写出来用于支撑高流量网站以及分析庞大的数据集: + +1. [Play Framework](https://www.playframework.com) 是一种用于创建高度可扩展应用程序的轻量级、无状态、对开发者及Web友好的架构 +2. [Lagom](https://www.lagomframework.com) 是一种微服务框架,可帮助您分解遗留的单体应用并构建、测试和部署整个响应式微服务系统 +3. [Apache Spark](https://spark.apache.org) 是一种面向大规模数据处理的统一分析引擎,内置流、SQL、机器学习和图形处理等模块 + +[Awesome Scala 列表](https://github.com/lauris/awesome-scala)展示了开发人员为构建 Scala 应用程序而创建的许多其他开源工具。 + +除了服务器端编程之外,[Scala.js](https://www.scala-js.org) 是一款用于编写 JavaScript 应用的强类型替代方案。其开源的第三方库包含支持与 Facebook 的 React、jQuery 及其他库等集成的工具。 + +{% comment %} +The Lower-Level Features section is like the second part of an elevator pitch. +Assuming you told someone about the previous high-level features and then they say, “Tell me more,” this is what you might tell them. +{% endcomment %} + +{% comment %} + +## Lower-level language features + +{% endcomment %} + +## 底层语言特性 + +{% comment %} +Where the previous section covered high-level features of Scala 3, it’s interesting to note that at a high level you can make the same statements about both Scala 2 and Scala 3. +A decade ago Scala started with a strong foundation of desirable features, and as you’ll see in this section, those benefits have been improved with Scala 3. +{% endcomment %} + +上一节介绍了 Scala 3 的高级特性,有趣的是,您可以从高层次上对 Scala 2 和 Scala 3 作出相同的表述。 +十年前,Scala 就为各种理想特性打下了坚实基础,正如您在本节中即将看到的那样,这些效益在 Scala 3 中得到了提高。 + +{% comment %} +At a “sea level” view of the details---i.e., the language features programmers use everyday---Scala 3 has significant advantages over Scala 2: + +- The ability to create algebraic data types (ADTs) more concisely with enums +- An even more concise and readable syntax: + - The “quiet” control structure syntax is easier to read + - Optional braces + - Fewer symbols in the code creates less visual noise, making it easier to read + - The `new` keyword is generally no longer needed when creating class instances + - The formality of package objects have been dropped in favor of simpler “top level” definitions +- A grammar that’s more clear: + - Multiple different uses of the `implicit` keyword have been removed; those uses are replaced by more obvious keywords like `given`, `using`, and `extension`, focusing on intent over mechanism (see the [Givens][givens] section for details) + - [Extension methods][extension] replace implicit classes with a clearer and simpler mechanism + - The addition of the `open` modifier for classes makes the developer intentionally declare that a class is open for modification, thereby limiting ad-hoc extensions to a code base + - [Multiversal equality][multiversal] rules out nonsensical comparisons with `==` and `!=` (i.e., attempting to compare a `Person` to a `Planet`) + - Macros are implemented much more easily + - Union and intersection offer a flexible way to model types + - Trait parameters replace and simplify early initializers + - [Opaque type aliases][opaque_types] replace most uses of value classes, while guaranteeing the absence of boxing + - Export clauses provide a simple and general way to express aggregation, which can replace the previous facade pattern of package objects inheriting from classes + - The procedure syntax has been dropped, and the varargs syntax has been changed, both to make the language more consistent + - The `@infix` annotation makes it obvious how you want a method to be applied + - The [`@targetName`]({{ site.scala3ref }}/other-new-features/targetName.html) method annotation defines an alternate name for the method, improving Java interoperability, and letting you provide aliases for symbolic operators + +It would take too much space to demonstrate all of those features here, but follow the links in the items above to see those features in action. +All of these features are discussed in detail in the *New*, *Changed*, and *Dropped* features pages in the [Overview documentation][reference]. +{% endcomment %} + +以小见大,从程序员日常使用的语言特性来看,Scala 3 比 Scala 2 具有显著优势: + +- 可以用枚举更简洁地创建代数数据类型(ADT) +- 更简明易读的语法: + - “干净”的控制结构语法更容易阅读 + - 可选的大括号 + - 代码中包含更少的符号,因此会产生更少的视觉噪音,使其更容易阅读 + - 创建类实例时一般不再需要 `new` 关键字 + - 弃用了包对象,转而使用更简单的“顶层”定义 +- 更清晰的语法: + - 移除了 `implicit` 关键字的多种不同用法,这些用法被更显而易见的关键字所取代,如 `given`、 `using`、和 `extension`,以此将关注重点放在意图而不是机制上(详见 [Givens][givens] 部分) + - [扩展方法][extension]通过更加清晰简单的机制取代了隐式类 + - 为类添加了 `open` 修饰符,使开发者能够有意识地声明一个类是可以被修改的,从而限制对代码库的临时扩展 + - [多元相等][multiversal]排除了用 `==` 和 `!=` 进行无意义的比较(即试图将 `Person` 与 `Planet` 进行比较) + - 宏的实现变得更加容易 + - 联合与交叉提供了一种灵活的方式以建模类型 + - 特质参数取代并简化了早期初始化器 + - [不透明类型别名][opaque_types]取代了值类的大多数用途,并确保不进行装箱 + - 导出子句提供了一种简单而通用的方式来表现聚合,它可以取代之前继承自类的包对象的外观模式 + - 删除了过程语法并更改了可变参数语法,这增加了语言一致性 + - `@infix` 注解使得您想让一个方法被如何应用更加显而易见 + - [`@targetName`]({{ site.scala3ref }}/other-new-features/targetName.html) 方法注解为方法定义了一个候补名称。这提高了与 Java 的互操作性,并允许您为符号运算符提供别名 + +在这里演示所有这些特性会占用太多空间,请通过上述内容中的链接来查看这些特性的实际效果。 +所有这些特性都在[概述文档][reference]的*新特性*、*变更的特性*、与*删除的特性*等页面中进行了详细讨论。 + +{% comment %} +CHECKLIST OF ALL ADDED, UPDATED, AND REMOVED FEATURES +===================================================== + +New Features +------------ +- trait parameters +- super traits +- creator applications +- export clauses +- opaque type aliases +- open classes +- parameter untupling +- kind polymorphism +- tupled function +- threadUnsafe annotation +- new control syntax +- optional braces (experimental) +- explicit nulls +- safe initialization + +CHANGED FEATURES +---------------- +- numeric literals +- structural types +- operators +- wildcard types +- type checking +- type inference +- implicit resolution +- implicit conversions +- overload resolution +- match expressions +- vararg patterns +- pattern bindings +- pattern matching +- eta expansion +- compiler plugins +- lazy vals initialization +- main functions + +DROPPED FEATURES +---------------- +- DelayedInit +- macros +- existential types +- type projection +- do/while syntax +- procedure syntax +- package objects +- early initializers +- class shadowing +- limit 22 +- XML literals +- symbol literals +- auto-application +- weak conformance +- nonlocal returns +- [this] qualifier + - private[this] and protected[this] access modifiers are deprecated + and will be phased out +{% endcomment %} + + +{% comment %} + +## Scala ecosystem + +{% endcomment %} + +## Scala 生态系统 + +{% comment %} +TODO: I didn’t put much work into this section because I don’t know if you want + to add many tools because (a) that can be seen as an endorsement and + (b) it creates a section that can need more maintenance than average + since tool popularity can wax and wane. One way to avoid the first + point is to base the lists on Github stars and activity. +{% endcomment %} + +{% comment %} +Scala has a vibrant ecosystem, with libraries and frameworks for every need. +The [“Awesome Scala” list](https://github.com/lauris/awesome-scala) provides a list of hundreds of open source projects that are available to Scala developers, and the [Scaladex](https://index.scala-lang.org) provides a searchable index of Scala libraries. +Some of the more notable libraries are listed below. +{% endcomment %} + +Scala 拥有一个充满活力的生态系统,有满足各种需求的库和框架。 +[Awesome Scala 列表](https://github.com/lauris/awesome-scala)提供了数百个可供 Scala 开发者使用的开源项目,[Scaladex](https://index.scala-lang.org) 则提供了 Scala 库的可搜索索引。 +以下列出了一些比较著名的库: + +{% comment %} + +### Web development + +{% endcomment %} + +### Web 开发 + +{% comment %} + +- The [Play Framework](https://www.playframework.com) followed the Ruby on Rails model to become a lightweight, stateless, developer-friendly, web-friendly architecture for highly-scalable applications +- [Scalatra](https://scalatra.org) is a tiny, high-performance, async web framework, inspired by Sinatra +- [Finatra](https://twitter.github.io/finatra) is Scala services built on TwitterServer and Finagle +- [Scala.js](https://www.scala-js.org) is a strongly-typed replacement for JavaScript that provides a safer way to build robust front-end web applications +- [ScalaJs-React](https://github.com/japgolly/scalajs-react) lifts Facebook’s React library into Scala.js, and endeavours to make it as type-safe and Scala-friendly as possible +- [Lagom](https://www.lagomframework.com) is a microservices framework that helps you decompose your legacy monolith and build, test, and deploy entire systems of Reactive microservices +- +{% endcomment %} + +- [Play Framework](https://www.playframework.com) 遵循 Ruby on Rails 模型,是一种用于高度可扩展应用程序的轻量级、无状态、对开发者及Web友好的架构 +- [Scalatra](https://scalatra.org) 是一个小型的、高性能的、异步的网络框架,其灵感来自于 Sinatra +- [Finatra](https://twitter.github.io/finatra) 是基于 TwitterServer 和 Finagle 构建的 Scala 服务 +- [Scala.js](https://www.scala-js.org) 是 JavaScript 的强类型替代品,它提供了一种更安全的方式以构建稳健的前端 Web 应用程序 +- [ScalaJs-React](https://github.com/japgolly/scalajs-react) 将 Facebook 的 React 库整合至 Scala.js,并努力使其尽可能类型安全和 Scala 友好 +- [Lagom](https://www.lagomframework.com) 是一种微服务框架,可帮助您分解遗留的单体应用并构建、测试和部署整个响应式微服务系统 + +{% comment %} +HTTP(S) libraries: +{% endcomment %} + +HTTP(S) 库: + +- [Akka-http](https://akka.io) +- [Finch](https://github.com/finagle/finch) +- [Http4s](https://github.com/http4s/http4s) +- [Sttp](https://github.com/softwaremill/sttp) + +{% comment %} +JSON libraries: +{% endcomment %} + +JSON 库: + +- [Argonaut](https://github.com/argonaut-io/argonaut) +- [Circe](https://github.com/circe/circe) +- [Json4s](https://github.com/json4s/json4s) +- [Play-JSON](https://github.com/playframework/play-json) + +{% comment %} +Serialization: +{% endcomment %} + +序列化: + +- [ScalaPB](https://github.com/scalapb/ScalaPB) + +{% comment %} + +### Science and data analysis: + +{% endcomment %} + +### 科学和数据分析 + +- [Algebird](https://github.com/twitter/algebird) +- [Spire](https://github.com/typelevel/spire) +- [Squants](https://github.com/typelevel/squants) + +{% comment %} + +### Big data + +{% endcomment %} + +### 大数据 + +- [Apache Spark](https://github.com/apache/spark) +- [Apache Flink](https://github.com/apache/flink) + +{% comment %} + +### AI, machine learning + +- [BigDL](https://github.com/intel-analytics/BigDL) (Distributed Deep Learning Framework for Apache Spark) for Apache Spark +- [TensorFlow Scala](https://github.com/eaplatanios/tensorflow_scala) + +{% endcomment %} + +### 人工智能,机器学习 + +- [BigDL](https://github.com/intel-analytics/BigDL) (用于 Apache Spark 的分布式深度学习框架) +- [TensorFlow Scala](https://github.com/eaplatanios/tensorflow_scala) + +{% comment %} + +### Functional Programming & Functional Reactive Programming + +{% endcomment %} + +### 函数式编程 & 函数式响应式编程 + +{% comment %} +FP: +{% endcomment %} + +函数式编程: + +- [Cats](https://github.com/typelevel/cats) +- [Zio](https://github.com/zio/zio) + +{% comment %} +Functional reactive programming (FRP): +{% endcomment %} + +函数式响应式编程(FRP) + +- [fs2](https://github.com/typelevel/fs2) +- [monix](https://github.com/monix/monix) + +{% comment %} + +### Build tools + +{% endcomment %} + +### 构建工具 + +- [sbt](https://www.scala-sbt.org) +- [Gradle](https://gradle.org) +- [Mill](https://github.com/lihaoyi/mill) + +{% comment %} + +## Summary + +As this page shows, Scala has many terrific programming language features at a high level, at an everyday programming level, and through its developer ecosystem. + +{% endcomment %} + +## 总结 + +如此页所示,Scala 在高层、日常编程层面以及贯穿开发者生态系统都具有许多出色的编程语言特性。 + + +[reference]: {{ site.scala3ref }}/overview.html +[multiversal]: {% link _overviews/scala3-book/ca-multiversal-equality.md %} +[extension]: {% link _overviews/scala3-book/ca-extension-methods.md %} +[givens]: {% link _overviews/scala3-book/ca-given-using-clauses.md %} +[opaque_types]: {% link _overviews/scala3-book/types-opaque-types.md %} + + + From 0eae0a35185c354be03ab5b707b993c06c555be0 Mon Sep 17 00:00:00 2001 From: Thanh Le Date: Tue, 8 Mar 2022 20:37:57 +0100 Subject: [PATCH 0982/2265] Fix link to for type lambdas url --- _overviews/scala3-migration/plugin-kind-projector.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/plugin-kind-projector.md b/_overviews/scala3-migration/plugin-kind-projector.md index 6d49be8d28..8557cdb559 100644 --- a/_overviews/scala3-migration/plugin-kind-projector.md +++ b/_overviews/scala3-migration/plugin-kind-projector.md @@ -100,7 +100,7 @@ type MyLambda[F[_], A] = EitherT[F, Int, A] MyLambda ``` -Alternatively you may use Scala 3's [Native Type Lambdas](https://dotty.epfl.ch/docs/reference/new-types/type-lambdas.html) if you do not need to cross-compile: +Alternatively you may use Scala 3's [Native Type Lambdas](https://docs.scala-lang.org/scala3/reference/new-types/type-lambdas.html) if you do not need to cross-compile: ```scala [F[_], A] =>> EitherT[F, Int, A] From 9097144e071d4290dc165aee2e2855c48aae64dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Tue, 8 Feb 2022 15:13:34 +0100 Subject: [PATCH 0983/2265] Update static site docs --- _overviews/scala3-scaladoc/blog.md | 13 +- _overviews/scala3-scaladoc/static-site.md | 170 ++++++++++++---------- 2 files changed, 96 insertions(+), 87 deletions(-) diff --git a/_overviews/scala3-scaladoc/blog.md b/_overviews/scala3-scaladoc/blog.md index 1e3c371c8e..612ee5c25e 100644 --- a/_overviews/scala3-scaladoc/blog.md +++ b/_overviews/scala3-scaladoc/blog.md @@ -15,24 +15,17 @@ Blog is treated a little differently than regular static sites. This article wil ## Proper directory setup -All your blogposts must be put under `blog/_posts` directory. +All your blogposts must be put under `_blog/_posts` directory. ``` -├── blog +├── _blog │ ├── _posts │ │ └── 2016-12-05-implicit-function-types.md │ └── index.html ``` -If you are using yaml [sidebar]({% link _overviews/scala3-scaladoc/static-site.md %}#sidebar) don't forget to place - -``` -sidebar: - - title: Blog -``` - -somewhere inside the `yaml` tree representing the sidebar sections. Scaladoc will attach under that section all of your blogposts. +Scaladoc loads blog if the `_blog` directory exists. ## Naming convention diff --git a/_overviews/scala3-scaladoc/static-site.md b/_overviews/scala3-scaladoc/static-site.md index e7516ea09c..d9d11f6bf6 100644 --- a/_overviews/scala3-scaladoc/static-site.md +++ b/_overviews/scala3-scaladoc/static-site.md @@ -20,16 +20,18 @@ and will from here on be referred to as "template files" or "templates". A simple "hello world" site could look something like this: ``` -├── docs -│ └── getting-started.md -└── index.html +. +└── / + └── _docs/ + ├── index.html + └── getting-started.html ``` This will give you a site with the following files in generated documentation: ``` index.html -docs/getting-started.html +getting-started.html ``` Scaladoc can transform both files and directories (to organize your documentation into a tree-like structure). By default, directories have a title based on the file name and have empty content. It is possible to provide index pages for each section by creating `index.html` or `index.md` (not both) in the dedicated directory. @@ -98,63 +100,64 @@ Layouts must be placed in a `_layouts` directory in the site root: ``` ├── _layouts │ └── main.html -├── docs -│ └── getting-started.md -└── index.html +└── _docs + └── getting-started.md +``` + +## Assets + +In order to render assets along with static site, they need to be placed in the `_assets` directory in the site root: +``` +├── _assets +│ └── images +│ └── myimage.png +└── _docs + └── getting-started.md +``` +To reference the asset in a page, one need to create link relative to the `_assets` directory + +``` +Take a look at the following image: [My image](images/myimage.png) ``` ## Sidebar -Scaladoc by default uses layout of files in `docs` directory to create table of content. There is also ability to override it by providing a `sidebar.yml` file in the site root: +Scaladoc by default uses directory structure in `_docs` directory to organize static sites. There is also possibility to override it by providing a `sidebar.yml` file in the site root. The YAML configuration file describes the structure of rendered static site and the table of content: ```yaml -sidebar: - - title: Blog - - title: My title - page: my-page1.md - - page: my-page2.md - - page: my-page3/subsection - - title: Reference - subsection: - - page: my-page3.md - - index: my-page4/index.md - subsection: - - page: my-page4/my-page4.md - - title: My subsection - index: my-page5/index.md - subsection: - - page: my-page5/my-page5.md - - index: my-page6/index.md - subsection: - - index: my-page6/my-page6/index.md - subsection: - - page: my-page6/my-page6/my-page6.md -``` - -The `sidebar` key is mandatory. -On each level, you can have three different types of entries: `page`, `blog` or `subsection`. - -`page` is a leaf of the structure and accepts the following attributes: -- `title` (optional) - title of the page -- `page` (mandatory) - path to the file that will represent the page, it can be either html or markdown file to be rendered, there is also the possibility to pass the `directory` path. If so, the scaladoc will render the directory and all its content as if there were no `sidebar.yml` basing on its tree structure and index files. - -The `page` property `subsection` accepts nested nodes, these can be either pages or subsections, which allow you to create tree-like navigation. The attributes are: -- `title` (optional) - title of the page -- `index` (optional) - path to the file that will represent the index file of the subsection, it can be either html or markdown file to be rendered -- `subsection` (mandatory) - nested nodes, can be either pages or subsections - -In `subsection`s, you can omit `title` or `index`, however not specifying any of these properties prevents you from specifying the title of the section. - -`blog` is a special node represented by simple entry `- title: Blog` with no other attributes. All your blog posts will be automatically linked under this section. You can read more about the blog [here]({% link _overviews/scala3-scaladoc/blog.md %}). - -``` -├── blog -│ ├── _posts -│ │ └── 2016-12-05-implicit-function-types.md -│ └── index.html -├── index.html -└── sidebar.yml -``` +index: index.html +subsection: + - title: Usage + index: usage/index.html + directory: usage + subsection: + - title: Dottydoc + page: usage/dottydoc.html + hidden: false + - title: sbt-projects + page: usage/sbt-projects.html + hidden: false +``` +The root element needs to be a `subsection`. +Nesting subsections will result in a tree-like structure of navigation. + +`subsection` properties are: + - `title` - Optional string - A default title of the subsection. + Front-matter titles have higher priorities. + - `index` - Optional string - A path to index page of a subsection. + - `directory` - Optional string - A name of the directory that will contain the subsection. + By default, the directory name is the subsection name converted to kebab case. + - `subsection` - Array of `subsection` or `page`. + + Either `index` or `subsection` must be defined. The subsection defined with `index` and without `subsection` will contain pages and directories loaded recursively from directory of the index page. + +`page` properties are: + - `title` - Optional string - A default title of the page. + Front-matter titles have higher priorities. + - `page` - String - A path to the page + - `hidden` - Optional boolean - A flag that indicates whether the page should be visible in navigation. By default, it is set to `false`. + +**Note**: All paths in YAML configuration file are relative to `/_docs`. ## Hierarchy of title @@ -174,30 +177,43 @@ If the title is specified multiple times, the priority is as follows (from highe Note that if you skip the `index` file in your tree structure or you don't specify the `title` in the frontmatter, there will be given a generic name `index`. The same applies when using `sidebar.yml` but not specifying `title` nor `index`, just a subsection. Again, a generic `index` name will appear. +## Blog +Blog feature is described in [a separate document]({% link _overviews/scala3-scaladoc/blog.md %}) -## Static resources - -You can attach static resources (pdf, images) to your documentation by using two dedicated directories: -`resources` and `images`. After placing your assets under any of these directories, you can reference them in markdown -as if they were relatively at the same level. - -For example, consider the following situation: - +## Advanced configuration +### Full structure of site root ``` -├── blog -│ ├── _posts -│ │ └── 2016-12-05-implicit-function-types.md -│ └── index.html -├── index.html -├── resources -│ └── my_file.pdf -├── images -│ └── my_image.png -└── sidebar.yml - +. +└── / + ├── _layouts_/ + │ └── ... + ├── _docs/ + │ └── ... + ├── _blog/ + │ ├── index.md + │ └── _posts/ + │ └── ... + └── _assets/ + ├── js/ + │ └── ... + ├── img/ + │ └── ... + └── ... ``` +It results in static site containing documents as well as blog. It also contains custom layouts and assets. The structure of rendered documentation can be based on file system but it can also be overriden by YAML configuration. -You can refer to the assets from within any of the files using markdown links: +### Mapping directory structure -``` -This is my blog post. Here is the image ![](my_image.png) and here is my [pdf](my_file.pdf)``` +Using YAML configuration file, we can define how the source directory structure should be transformed in target directory structure. + +Take a look at following subsection definition: +```yaml +- title: Some other subsection + index: abc/index.html + directory: custom-directory + subsection: + - page: abc2/page1.md + - page: foo/page2.md +``` +This subsection shows the ability of YAML configuration to map the directory structure. +Even though the index page and all defined children are in different directories, they will be rendered in `custom-directory`. From 6e2cf92d84dc4ee4290dc65cd83f2a4a4b250796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Thu, 10 Mar 2022 09:05:31 +0100 Subject: [PATCH 0984/2265] Apply suggestions from review --- _overviews/scala3-scaladoc/static-site.md | 27 +++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/_overviews/scala3-scaladoc/static-site.md b/_overviews/scala3-scaladoc/static-site.md index d9d11f6bf6..127f6c59e7 100644 --- a/_overviews/scala3-scaladoc/static-site.md +++ b/_overviews/scala3-scaladoc/static-site.md @@ -101,7 +101,8 @@ Layouts must be placed in a `_layouts` directory in the site root: ├── _layouts │ └── main.html └── _docs - └── getting-started.md + ├── getting-started.md + └── index.html ``` ## Assets @@ -114,7 +115,7 @@ In order to render assets along with static site, they need to be placed in the └── _docs └── getting-started.md ``` -To reference the asset in a page, one need to create link relative to the `_assets` directory +To reference the asset on a page, one needs to create a link relative to the `_assets` directory ``` Take a look at the following image: [My image](images/myimage.png) @@ -122,7 +123,7 @@ Take a look at the following image: [My image](images/myimage.png) ## Sidebar -Scaladoc by default uses directory structure in `_docs` directory to organize static sites. There is also possibility to override it by providing a `sidebar.yml` file in the site root. The YAML configuration file describes the structure of rendered static site and the table of content: +By default, Scaladoc reflects the directory structure from `_docs` directory in the rendered site. There is also the ability to override it by providing a `sidebar.yml` file in the site root directory. The YAML configuration file describes the structure of the rendered static site and the table of content: ```yaml index: index.html @@ -144,20 +145,20 @@ Nesting subsections will result in a tree-like structure of navigation. `subsection` properties are: - `title` - Optional string - A default title of the subsection. Front-matter titles have higher priorities. - - `index` - Optional string - A path to index page of a subsection. - - `directory` - Optional string - A name of the directory that will contain the subsection. + - `index` - Optional string - A path to index page of a subsection. The path is relative to the `_docs` directory. + - `directory` - Optional string - A name of the directory that will contain the subsection in the generated site. By default, the directory name is the subsection name converted to kebab case. - `subsection` - Array of `subsection` or `page`. - Either `index` or `subsection` must be defined. The subsection defined with `index` and without `subsection` will contain pages and directories loaded recursively from directory of the index page. + Either `index` or `subsection` must be defined. The subsection defined with `index` and without `subsection` will contain pages and directories loaded recursively from the directory of the index page. `page` properties are: - `title` - Optional string - A default title of the page. Front-matter titles have higher priorities. - - `page` - String - A path to the page - - `hidden` - Optional boolean - A flag that indicates whether the page should be visible in navigation. By default, it is set to `false`. + - `page` - String - A path to the page, relative to the `_docs` directory. + - `hidden` - Optional boolean - A flag that indicates whether the page should be visible in the navigation sidebar. By default, it is set to `false`. -**Note**: All paths in YAML configuration file are relative to `/_docs`. +**Note**: All the paths in the YAML configuration file are relative to `/_docs`. ## Hierarchy of title @@ -200,13 +201,13 @@ Blog feature is described in [a separate document]({% link _overviews/scala3-sca │ └── ... └── ... ``` -It results in static site containing documents as well as blog. It also contains custom layouts and assets. The structure of rendered documentation can be based on file system but it can also be overriden by YAML configuration. +It results in a static site containing documents as well as a blog. It also contains custom layouts and assets. The structure of the rendered documentation can be based on the file system but it can also be overridden by YAML configuration. ### Mapping directory structure -Using YAML configuration file, we can define how the source directory structure should be transformed in target directory structure. +Using the YAML configuration file, we can define how the source directory structure should be transformed into an outputs directory structure. -Take a look at following subsection definition: +Take a look at the following subsection definition: ```yaml - title: Some other subsection index: abc/index.html @@ -217,3 +218,5 @@ Take a look at following subsection definition: ``` This subsection shows the ability of YAML configuration to map the directory structure. Even though the index page and all defined children are in different directories, they will be rendered in `custom-directory`. +The source page `abc/index.html` will generate a page `custom-directory/index.html`, the source page `abc2/page1.md` will generate a page `custom-directory/page1.html`, +and the source page `foo/page2.md` will generate a page `custom-directory/page2.html`. From 388973da5dfc75990bb00be1d15ea2bd217b8780 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 14 Mar 2022 14:12:50 +0100 Subject: [PATCH 0985/2265] list scala 3 releases in api/all --- api/all.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/all.md b/api/all.md index ddf77295f7..ea55e544d9 100644 --- a/api/all.md +++ b/api/all.md @@ -6,6 +6,8 @@ includeTOC: true ## Latest releases +* Scala 3.1.1 + * [Library API](https://www.scala-lang.org/api/3.1.1/) * Scala 2.13.8 * [Library API](https://www.scala-lang.org/api/2.13.8/) * [Compiler API](https://www.scala-lang.org/api/2.13.8/scala-compiler/scala/) @@ -58,6 +60,14 @@ https://scala-ci.typesafe.com/artifactory/scala-integration/org/scala-lang/ ## Previous releases +* Scala 3.1.0 + * [Library API](https://www.scala-lang.org/api/3.1.0/) +* Scala 3.0.2 + * [Library API](https://www.scala-lang.org/api/3.0.2/) +* Scala 3.0.1 + * [Library API](https://www.scala-lang.org/api/3.0.1/) +* Scala 3.0.0 + * [Library API](https://www.scala-lang.org/api/3.0.0/) * Scala 2.13.7 * [Library API](https://www.scala-lang.org/api/2.13.7/) * [Compiler API](https://www.scala-lang.org/api/2.13.7/scala-compiler/scala/) From 5152494a70fb70694d0381474115e404d7e89317 Mon Sep 17 00:00:00 2001 From: TSLsun Date: Sat, 19 Mar 2022 11:10:20 +0800 Subject: [PATCH 0986/2265] fix compiling warnings in code example --- _tour/classes.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_tour/classes.md b/_tour/classes.md index 47b5079bc5..ee3dc33703 100644 --- a/_tour/classes.md +++ b/_tour/classes.md @@ -76,17 +76,17 @@ class Point { private var _y = 0 private val bound = 100 - def x = _x + def x: Int = _x def x_= (newValue: Int): Unit = { - if (newValue < bound) _x = newValue else printWarning + if (newValue < bound) _x = newValue else printWarning() } - def y = _y + def y: Int = _y def y_= (newValue: Int): Unit = { - if (newValue < bound) _y = newValue else printWarning + if (newValue < bound) _y = newValue else printWarning() } - private def printWarning = println("WARNING: Out of bounds") + private def printWarning(): Unit = println("WARNING: Out of bounds") } val point1 = new Point From 532dbc3f09686cedda3ac3cf8fd90986f5ffbe85 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 11:51:25 +0100 Subject: [PATCH 0987/2265] enable collection contribute_resources change icons in contribute_resources --- _config.yml | 1 + _contribute_resources/1-documentation.md | 2 +- _contribute_resources/2-bug-fixes.md | 2 +- _contribute_resources/6-compiler-language.md | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/_config.yml b/_config.yml index ecd8829749..0d58e58a8f 100644 --- a/_config.yml +++ b/_config.yml @@ -20,6 +20,7 @@ scala-212-version: 2.12.15 scala-3-version: 3.1.1 collections: + contribute_resources: style: output: true overviews: diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index b39290a394..431c4e0ab1 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -1,6 +1,6 @@ --- title: Documentation link: /contribute/documentation.html -icon: fa fa-file-text +icon: fa fa-book --- [Scaladoc (API)](/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](https://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index cca6269e06..54e6d2cf9d 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -1,6 +1,6 @@ --- title: Bug fixes link: /contribute/guide.html -icon: fa fa-pencil +icon: fa fa-bug --- Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). diff --git a/_contribute_resources/6-compiler-language.md b/_contribute_resources/6-compiler-language.md index fcfea35d5a..d54e34fac9 100644 --- a/_contribute_resources/6-compiler-language.md +++ b/_contribute_resources/6-compiler-language.md @@ -1,6 +1,6 @@ --- title: Compiler/Language link: /contribute/guide.html#larger-changes-new-features -icon: fa fa-gears +icon: fa fa-cogs --- Larger language features and compiler enhancements including language specification and SIPs. From d9c44ebf1f469c7d8ed2b46c2a38f0940569b6e2 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 13:13:26 +0100 Subject: [PATCH 0988/2265] prepare for move files --- contribute/bug-reporting-guide.md | 4 ++-- contribute/codereviews.md | 2 +- contribute/corelibs.md | 2 +- contribute/documentation.md | 2 +- contribute/guide.md | 2 +- contribute/hacker-guide.md | 2 +- contribute/index.md | 2 +- contribute/partest-guide.md | 4 ++-- contribute/scala-internals.md | 2 +- contribute/scala-standard-library-api-documentation.md | 2 +- contribute/tools.md | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 88317da0ce..d4588de422 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -1,8 +1,8 @@ --- -title: Bug Reporting +title: Bug Reporting Guide layout: inner-page-no-masthead -# permalink: /contribute/bug-reporting-guide/ includeTOC: true +permalink: /contribute/bug-reporting-guide.html --- The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. diff --git a/contribute/codereviews.md b/contribute/codereviews.md index 6e0a2592b6..860ba65884 100644 --- a/contribute/codereviews.md +++ b/contribute/codereviews.md @@ -1,8 +1,8 @@ --- title: Code Review Contributions layout: inner-page-no-masthead -# permalink: /contribute/codereviews/ includeTOC: true +permalink: /contribute/codereviews.html --- ## Code Review Contributions diff --git a/contribute/corelibs.md b/contribute/corelibs.md index 6b2cc5d95f..4f10208334 100644 --- a/contribute/corelibs.md +++ b/contribute/corelibs.md @@ -1,8 +1,8 @@ --- title: Core Library Contributions layout: inner-page-no-masthead -# permalink: /contribute/corelibs/ includeTOC: true +permalink: /contribute/corelibs.html --- ## Core Library Contributions diff --git a/contribute/documentation.md b/contribute/documentation.md index 967806de42..b8ea229f93 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -1,8 +1,8 @@ --- title: Documentation Contributions layout: inner-page-no-masthead -# permalink: /contribute/documentation/ includeTOC: true +permalink: /contribute/documentation.html --- ## Contributing Documentation to the Scala project diff --git a/contribute/guide.md b/contribute/guide.md index 7e4f375005..c10a5c20c1 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -1,8 +1,8 @@ --- title: Contributing guide layout: inner-page-no-masthead -# permalink: /contribute/guide/ includeTOC: true +permalink: /contribute/guide.html ---
    diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 302635fae1..990754e3df 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -2,8 +2,8 @@ title: Scala hacker guide by: Eugene Burmako layout: inner-page-no-masthead -# permalink: /contribute/hacker-guide/ includeTOC: true +permalink: /contribute/hacker-guide.html ---
    This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. diff --git a/contribute/index.md b/contribute/index.md index d78a72e159..d4bc7069a2 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,8 +1,8 @@ --- title: Contribute layout: inner-page-no-masthead -# permalink: /contribute/ includeTOC: true +permalink: /contribute/ --- The Scala programming language is an open source project with a very diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md index e7e10621e1..d55c02e884 100644 --- a/contribute/partest-guide.md +++ b/contribute/partest-guide.md @@ -1,8 +1,8 @@ --- title: Running the Test Suite layout: inner-page-no-masthead -# permalink: /contribute/partest-guide/ includeTOC: true +permalink: /contribute/partest-guide.html --- Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go to the scala project folder from your local checkout and run it via `sbt`, `ant` or standalone as follows. @@ -35,7 +35,7 @@ The test suite can be run by using ant from the command line: Please note the standalone scripts mentioned below were removed in 2.12.2. sbt is the preferred way to run the test suite. -There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use +There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use ./test/partest --show-diff --show-log --failed diff --git a/contribute/scala-internals.md b/contribute/scala-internals.md index e6fde53a81..b380525088 100644 --- a/contribute/scala-internals.md +++ b/contribute/scala-internals.md @@ -1,8 +1,8 @@ --- title: Scala Internals Mailing List layout: inner-page-no-masthead -permalink: /contribute/scala-internals/ includeTOC: true +permalink: /contribute/scala-internals/ --- ## scala-internals diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index 6f3af62b30..2700d2fd11 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -1,8 +1,8 @@ --- title: Contribute to API Documentation layout: inner-page-no-masthead -# permalink: /contribute/scala-standard-library-api-documentation.html includeTOC: true +permalink: /contribute/scala-standard-library-api-documentation.html --- This page is specific to API documentation contributions – that is, API diff --git a/contribute/tools.md b/contribute/tools.md index 0afd3982d8..a76d0b90bd 100644 --- a/contribute/tools.md +++ b/contribute/tools.md @@ -1,8 +1,8 @@ --- title: IDE and Build Tool Contributions layout: inner-page-no-masthead -# permalink: /contribute/tools/ includeTOC: true +permalink: /contribute/tools.html # Projects list: projects: From 30735654a67e967f41a9c7162b64846f2050f5ae Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 13:14:45 +0100 Subject: [PATCH 0989/2265] move contribute files --- {contribute => _overviews/contribute}/bug-reporting-guide.md | 0 {contribute => _overviews/contribute}/codereviews.md | 0 {contribute => _overviews/contribute}/corelibs.md | 0 {contribute => _overviews/contribute}/documentation.md | 0 {contribute => _overviews/contribute}/guide.md | 0 {contribute => _overviews/contribute}/hacker-guide.md | 0 {contribute => _overviews/contribute}/inclusive-language-guide.md | 0 {contribute => _overviews/contribute}/index.md | 0 {contribute => _overviews/contribute}/partest-guide.md | 0 {contribute => _overviews/contribute}/scala-internals.md | 0 .../contribute}/scala-standard-library-api-documentation.md | 0 {contribute => _overviews/contribute}/tools.md | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename {contribute => _overviews/contribute}/bug-reporting-guide.md (100%) rename {contribute => _overviews/contribute}/codereviews.md (100%) rename {contribute => _overviews/contribute}/corelibs.md (100%) rename {contribute => _overviews/contribute}/documentation.md (100%) rename {contribute => _overviews/contribute}/guide.md (100%) rename {contribute => _overviews/contribute}/hacker-guide.md (100%) rename {contribute => _overviews/contribute}/inclusive-language-guide.md (100%) rename {contribute => _overviews/contribute}/index.md (100%) rename {contribute => _overviews/contribute}/partest-guide.md (100%) rename {contribute => _overviews/contribute}/scala-internals.md (100%) rename {contribute => _overviews/contribute}/scala-standard-library-api-documentation.md (100%) rename {contribute => _overviews/contribute}/tools.md (100%) diff --git a/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md similarity index 100% rename from contribute/bug-reporting-guide.md rename to _overviews/contribute/bug-reporting-guide.md diff --git a/contribute/codereviews.md b/_overviews/contribute/codereviews.md similarity index 100% rename from contribute/codereviews.md rename to _overviews/contribute/codereviews.md diff --git a/contribute/corelibs.md b/_overviews/contribute/corelibs.md similarity index 100% rename from contribute/corelibs.md rename to _overviews/contribute/corelibs.md diff --git a/contribute/documentation.md b/_overviews/contribute/documentation.md similarity index 100% rename from contribute/documentation.md rename to _overviews/contribute/documentation.md diff --git a/contribute/guide.md b/_overviews/contribute/guide.md similarity index 100% rename from contribute/guide.md rename to _overviews/contribute/guide.md diff --git a/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md similarity index 100% rename from contribute/hacker-guide.md rename to _overviews/contribute/hacker-guide.md diff --git a/contribute/inclusive-language-guide.md b/_overviews/contribute/inclusive-language-guide.md similarity index 100% rename from contribute/inclusive-language-guide.md rename to _overviews/contribute/inclusive-language-guide.md diff --git a/contribute/index.md b/_overviews/contribute/index.md similarity index 100% rename from contribute/index.md rename to _overviews/contribute/index.md diff --git a/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md similarity index 100% rename from contribute/partest-guide.md rename to _overviews/contribute/partest-guide.md diff --git a/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md similarity index 100% rename from contribute/scala-internals.md rename to _overviews/contribute/scala-internals.md diff --git a/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md similarity index 100% rename from contribute/scala-standard-library-api-documentation.md rename to _overviews/contribute/scala-standard-library-api-documentation.md diff --git a/contribute/tools.md b/_overviews/contribute/tools.md similarity index 100% rename from contribute/tools.md rename to _overviews/contribute/tools.md From db3d07ea0ff961fd5000fe4adf99491b6a01645e Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 13:27:32 +0100 Subject: [PATCH 0990/2265] convert to multipage overview --- _overviews/contribute/bug-reporting-guide.md | 6 ++++-- _overviews/contribute/codereviews.md | 6 ++++-- _overviews/contribute/corelibs.md | 6 ++++-- _overviews/contribute/documentation.md | 6 ++++-- _overviews/contribute/guide.md | 6 ++++-- _overviews/contribute/hacker-guide.md | 6 ++++-- _overviews/contribute/inclusive-language-guide.md | 6 ++++-- _overviews/contribute/index.md | 6 ++++-- _overviews/contribute/partest-guide.md | 6 ++++-- _overviews/contribute/scala-internals.md | 6 ++++-- .../contribute/scala-standard-library-api-documentation.md | 6 ++++-- _overviews/contribute/tools.md | 6 ++++-- 12 files changed, 48 insertions(+), 24 deletions(-) diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index d4588de422..3e358a30f0 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -1,7 +1,9 @@ --- title: Bug Reporting Guide -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 7 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/bug-reporting-guide.html --- diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index 860ba65884..5b5a4a4697 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -1,7 +1,9 @@ --- title: Code Review Contributions -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 3 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/codereviews.html --- ## Code Review Contributions diff --git a/_overviews/contribute/corelibs.md b/_overviews/contribute/corelibs.md index 4f10208334..984f8c4f7c 100644 --- a/_overviews/contribute/corelibs.md +++ b/_overviews/contribute/corelibs.md @@ -1,7 +1,9 @@ --- title: Core Library Contributions -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 4 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/corelibs.html --- ## Core Library Contributions diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index b8ea229f93..01cd8a5c15 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -1,7 +1,9 @@ --- title: Documentation Contributions -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 5 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/documentation.html --- ## Contributing Documentation to the Scala project diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index c10a5c20c1..7cafd3d8a3 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -1,7 +1,9 @@ --- title: Contributing guide -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 9 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/guide.html --- diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index 990754e3df..df659678cb 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -1,8 +1,10 @@ --- title: Scala hacker guide by: Eugene Burmako -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 11 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/hacker-guide.html ---
    diff --git a/_overviews/contribute/inclusive-language-guide.md b/_overviews/contribute/inclusive-language-guide.md index 6703532594..d673d57ad8 100644 --- a/_overviews/contribute/inclusive-language-guide.md +++ b/_overviews/contribute/inclusive-language-guide.md @@ -1,7 +1,9 @@ --- title: Inclusive Language Guide -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 2 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/inclusive-language/ --- diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index d4bc7069a2..ac513b0009 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -1,7 +1,9 @@ --- title: Contribute -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 1 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/ --- diff --git a/_overviews/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md index d55c02e884..8f4dff394b 100644 --- a/_overviews/contribute/partest-guide.md +++ b/_overviews/contribute/partest-guide.md @@ -1,7 +1,9 @@ --- title: Running the Test Suite -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 12 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/partest-guide.html --- diff --git a/_overviews/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md index b380525088..f52faa5c18 100644 --- a/_overviews/contribute/scala-internals.md +++ b/_overviews/contribute/scala-internals.md @@ -1,7 +1,9 @@ --- title: Scala Internals Mailing List -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 8 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/scala-internals/ --- diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index 2700d2fd11..97e3d708f9 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -1,7 +1,9 @@ --- title: Contribute to API Documentation -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 6 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/scala-standard-library-api-documentation.html --- diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index a76d0b90bd..6df7c454a9 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -1,7 +1,9 @@ --- title: IDE and Build Tool Contributions -layout: inner-page-no-masthead -includeTOC: true +layout: multipage-overview +num: 10 +partof: scala-contribution +overview-name: Contributing to Scala permalink: /contribute/tools.html # Projects list: From c692ad3ab96c94ea22c9f5e99e0cabcccd76489b Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 13:59:30 +0100 Subject: [PATCH 0991/2265] migrate urls to /overviews/contribute fix broken links --- _contribute_resources/1-documentation.md | 4 +-- _contribute_resources/2-bug-fixes.md | 4 +-- _contribute_resources/3-code-reviews.md | 6 ++-- _contribute_resources/4-core-libraries.md | 2 +- .../5-ide-and-build-tools.md | 2 +- _contribute_resources/6-compiler-language.md | 2 +- _overviews/contribute/bug-reporting-guide.md | 1 - _overviews/contribute/codereviews.md | 7 ++-- _overviews/contribute/corelibs.md | 7 ++-- _overviews/contribute/documentation.md | 11 +++---- _overviews/contribute/guide.md | 33 +++++++++---------- _overviews/contribute/hacker-guide.md | 11 +++---- .../contribute/inclusive-language-guide.md | 3 +- _overviews/contribute/index.md | 9 +++-- _overviews/contribute/partest-guide.md | 1 - _overviews/contribute/scala-internals.md | 1 - ...cala-standard-library-api-documentation.md | 7 ++-- _overviews/contribute/tools.md | 7 ++-- 18 files changed, 53 insertions(+), 65 deletions(-) diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 431c4e0ab1..3e1b81a7b9 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -1,6 +1,6 @@ --- title: Documentation -link: /contribute/documentation.html +link: /overviews/contribute/documentation.html icon: fa fa-book --- -[Scaladoc (API)](/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](https://docs.scala-lang.org/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). +[Scaladoc (API)](/overviews/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index 54e6d2cf9d..2baf672e5a 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -1,6 +1,6 @@ --- title: Bug fixes -link: /contribute/guide.html +link: /overviews/contribute/guide.html icon: fa fa-bug --- -Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). +Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/overviews/contribute/bug-reporting-guide.html). diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index 2fc057eb0d..41f6821414 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -1,8 +1,8 @@ --- title: Code Reviews -link: /contribute/codereviews.html +link: /overviews/contribute/codereviews.html icon: fa fa-eye --- -Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), -[scala/scala-lang](https://github.com/scala/scala-lang/pulls), +Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), +[scala/scala-lang](https://github.com/scala/scala-lang/pulls), [scala/docs.scala-lang](https://github.com/scala/docs.scala-lang/pulls) and others. diff --git a/_contribute_resources/4-core-libraries.md b/_contribute_resources/4-core-libraries.md index 06f1018479..fb66a906b8 100644 --- a/_contribute_resources/4-core-libraries.md +++ b/_contribute_resources/4-core-libraries.md @@ -1,6 +1,6 @@ --- title: Core Libraries -link: /contribute/corelibs.html +link: /overviews/contribute/corelibs.html icon: fa fa-clipboard --- Update and expand the capabilities of the core (and associated) Scala libraries. diff --git a/_contribute_resources/5-ide-and-build-tools.md b/_contribute_resources/5-ide-and-build-tools.md index 7202f0d953..2bf2c7d729 100644 --- a/_contribute_resources/5-ide-and-build-tools.md +++ b/_contribute_resources/5-ide-and-build-tools.md @@ -1,6 +1,6 @@ --- title: IDE and Build Tools -link: /contribute/tools.html +link: /overviews/contribute/tools.html icon: fa fa-terminal --- Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects. diff --git a/_contribute_resources/6-compiler-language.md b/_contribute_resources/6-compiler-language.md index d54e34fac9..a7dc618322 100644 --- a/_contribute_resources/6-compiler-language.md +++ b/_contribute_resources/6-compiler-language.md @@ -1,6 +1,6 @@ --- title: Compiler/Language -link: /contribute/guide.html#larger-changes-new-features +link: /overviews/contribute/guide.html#larger-changes-new-features icon: fa fa-cogs --- Larger language features and compiler enhancements including language specification and SIPs. diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index 3e358a30f0..5cbf0a3f46 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 7 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/bug-reporting-guide.html --- The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index 5b5a4a4697..368bf96793 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -4,11 +4,10 @@ layout: multipage-overview num: 3 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/codereviews.html --- ## Code Review Contributions -In addition to [bug fixing](/contribute/guide.html), you can help us review +In addition to [bug fixing](/overviews/contribute/guide.html), you can help us review [waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your @@ -17,7 +16,7 @@ own pull requests. ### Review Guidelines -[Code of Conduct reminder]({{ site.baseurl }}/conduct.html) +[Code of Conduct reminder](https://scala-lang.org/conduct.html) * Keep comments on-topic, concise and precise. * Attach comments to particular lines or regions they pertain to whenever possible. @@ -53,4 +52,4 @@ own pull requests.
    -Also note that the [Tools contributions](/contribute/tools.html) page has more projects that will generate pull requests. +Also note that the [Tools contributions](/overviews/contribute/tools.html) page has more projects that will generate pull requests. diff --git a/_overviews/contribute/corelibs.md b/_overviews/contribute/corelibs.md index 984f8c4f7c..6c64a887d7 100644 --- a/_overviews/contribute/corelibs.md +++ b/_overviews/contribute/corelibs.md @@ -4,15 +4,14 @@ layout: multipage-overview num: 4 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/corelibs.html --- ## Core Library Contributions There are several options for contributing to Scala's core libraries. You can: -* Help with [Documentation](/contribute/documentation.html). -* [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. -* [Fix Bugs or Issues](/contribute/guide.html) against the +* Help with [Documentation](/overviews/contribute/documentation.html). +* [Report Bugs or Issues](/overviews/contribute/bug-reporting-guide.html) against the core libraries. +* [Fix Bugs or Issues](/overviews/contribute/guide.html) against the [reported library bugs/issues](https://github.com/scala/bug). ### Significant changes diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index 01cd8a5c15..7fca82ff53 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 5 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/documentation.html --- ## Contributing Documentation to the Scala project @@ -24,11 +23,11 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](/overviews/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. -* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* [Claim Scaladoc Issues and Provide Documentation](/overviews/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just -[submit new Scaladoc](/contribute/scala-standard-library-api-documentation.html) +[submit new Scaladoc](/overviews/contribute/scala-standard-library-api-documentation.html) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on [Scala Contributors](https://contributors.scala-lang.org/) so that people know what you are doing. ### The Main Scala Documentation Site @@ -45,7 +44,7 @@ without creating an issue, but please look to see if there is an issue already s * SIP (Scala Improvement Process) Proposals and more -Please read [contributing to the docs.scala-lang.org site](https://docs.scala-lang.org/contribute.html) through before embarking on changes. The site uses +Please read [contributing to the docs.scala-lang.org site](/contribute.html) through before embarking on changes. The site uses the [Jekyll](https://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. ### Updating scala-lang.org @@ -56,4 +55,4 @@ to Scala and related projects) is provided on the main [scala-lang GitHub project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[docs.scala-lang.org contribution](https://docs.scala-lang.org/contribute.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[docs.scala-lang.org contribution](/contribute.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 7cafd3d8a3..0b5b146ffc 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 9 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/guide.html ---
    @@ -14,18 +13,18 @@ permalink: /contribute/guide.html

    Get a peek into the inners of the Scala compiler.

    -

    Report an issue

    +

    Report an issue

    File a bug report or a feature request.

    -

    Community issues

    +

    Community issues

    Get cracking on some easy to approach issues.

    -

    Hacker guide

    +

    Hacker guide

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    @@ -56,22 +55,22 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [GitHub branch](https://github.com/scala/scala) -1. [Select a bug to fix from GitHub](/contribute/#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/contribute/bug-reporting-guide.html) (but please -[make sure it's not a duplicate](/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). -2. Optional ([but recommended](/contribute/scala-internals/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with -[these friendly people](/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. -3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. -5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide.html) until [all the tests pass](/contribute/hacker-guide.html#verify). -7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. +1. [Select a bug to fix from GitHub](/overviews/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/overviews/contribute/bug-reporting-guide.html) (but please +[make sure it's not a duplicate](/overviews/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). +2. Optional ([but recommended](/overviews/contribute/scala-internals.html/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with +[these friendly people](/overviews/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. +3. [Fork the Scala repository](/overviews/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). +4. [Create a feature branch](/overviews/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. +5. [Fix the bug, or implement the new small feature](/overviews/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). +6. [Test, rinse](/overviews/contribute/hacker-guide.html#test) and [test some more](/overviews/contribute/partest-guide.html) until [all the tests pass](/overviews/contribute/hacker-guide.html#verify). +7. [Commit your changes](/overviews/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](https://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) -9. [Submit a pull request](./hacker-guide.html#submit). -10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide.html#review). +9. [Submit a pull request](/overviews/contribute/hacker-guide.html#submit). +10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/overviews/contribute/hacker-guide.html#review). 11. Celebrate! -Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](./hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). +Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](/overviews/contribute/hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). ### Larger Changes, New Features @@ -80,4 +79,4 @@ and on the implementation plan. Announce the change on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](https://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](/contribute/hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. +the Scala project source tree. The [hacker guide](/overviews/contribute/hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index df659678cb..cb83b6218a 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -5,7 +5,6 @@ layout: multipage-overview num: 11 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/hacker-guide.html ---
    This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. @@ -32,7 +31,7 @@ Sometimes it's appealing to hack alone and not to have to interact with others o this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#forums) to find out how people feel +Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists](https://scala-lang.org/community/index.html#forums) to find out how people feel about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. @@ -200,7 +199,7 @@ Contributing to the Scala standard library is about the same as working on one o If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. -If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](https://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](https://docs.scala-lang.org/overviews/collections/introduction.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](https://docs.scala-lang.org/overviews/parallel-collections/overview.html). +If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](/overviews/collections/introduction.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](/overviews/parallel-collections/overview.html). ##### The Scala Compiler @@ -208,7 +207,7 @@ Documentation about the internal workings of the Scala compiler is scarce, and m * [Compiler internals videos by Martin Odersky](https://www.scala-lang.org/old/node/598.html) are quite dated, but still very useful. In this three-video series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. -* [Reflection documentation](https://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that +* [Reflection documentation](/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. * [Reflection and Compilers by Martin Odersky](https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. @@ -266,7 +265,7 @@ Adding tests to the test suite is as easy as moving them to the appropriate dire * Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/2.12.x/test/files/pos). * Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/2.12.x/test/files/neg). -* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/2.12.x/test/files/run) and have a corresponding `.check` file with the expected output. You will get test failures if the content of a `.check` file is different from what the test produces while running. If the change in the output is an expected product of your work, you might not want to change the `.check` file by hand. To make partest change the `.check` file, run it with a `--update-check` flag, like so `./test/partest --update-check path/to/test.scala`. For more information on partest, please refer to its [documentation](https://docs.scala-lang.org/tutorials/partest-guide.html). +* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/2.12.x/test/files/run) and have a corresponding `.check` file with the expected output. You will get test failures if the content of a `.check` file is different from what the test produces while running. If the change in the output is an expected product of your work, you might not want to change the `.check` file by hand. To make partest change the `.check` file, run it with a `--update-check` flag, like so `./test/partest --update-check path/to/test.scala`. For more information on partest, please refer to its [documentation](https://github.com/scala/scala-partest). * Everything that can be unit-tested should go to ["junit" directory](https://github.com/scala/scala/tree/2.12.x/test/junit) * Property-based tests go to the ["scalacheck" directory](https://github.com/scala/scala/tree/2.12.x/test/scalacheck) @@ -311,7 +310,7 @@ This means your change is backward or forward binary incompatible with the speci ### Verify -Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest](partest-guide.html), a tool we wrote for testing Scala. +Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest](/overviews/contribute/partest-guide.html), a tool we wrote for testing Scala. Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, respectively. `partest` (not `sbt partest`) also allows you to run a subset of the tests using wildcards: diff --git a/_overviews/contribute/inclusive-language-guide.md b/_overviews/contribute/inclusive-language-guide.md index d673d57ad8..7f7c428f42 100644 --- a/_overviews/contribute/inclusive-language-guide.md +++ b/_overviews/contribute/inclusive-language-guide.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 2 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/inclusive-language/ --- We are committed to providing a friendly, safe and welcoming environment for @@ -131,4 +130,4 @@ In those cases, we recommend to keep the old names, but document (e.g., in Scala ## See also -* Our [code of conduct](../../conduct/). +* Our [code of conduct](https://scala-lang.org/conduct/). diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index ac513b0009..8b7dad1e83 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 1 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/ --- The Scala programming language is an open source project with a very @@ -19,7 +18,7 @@ That depends on what you want to contribute. Below are some getting started reso ### Reporting bugs -See our [bug reporting guide](/contribute/bug-reporting-guide.html) to learn +See our [bug reporting guide](/overviews/contribute/bug-reporting-guide.html) to learn how to efficiently report a bug. ### Contribute @@ -33,8 +32,8 @@ Coordination of contribution efforts takes place on When contributing, please follow: -* The [Scala Code of Conduct](../conduct/) -* The [Inclusive Language Guide](./inclusive-language/) +* The [Scala Code of Conduct](https://scala-lang.org/conduct/) +* The [Inclusive Language Guide](/overviews/contribute/inclusive-language-guide.html) ### Community Tickets @@ -48,7 +47,7 @@ with their own maintainers and community of contributors. Helping out one of these projects is another way to help Scala. Consider lending on a hand on a project you're already using. Or, to find out about other projects, see the -[Libraries and Tools section](/community/#community-libraries-and-tools) +[Libraries and Tools section](https://scala-lang.org/community/#community-libraries-and-tools) on our Community page. ### Scala Community Build diff --git a/_overviews/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md index 8f4dff394b..6fb5a2644b 100644 --- a/_overviews/contribute/partest-guide.md +++ b/_overviews/contribute/partest-guide.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 12 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/partest-guide.html --- Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go to the scala project folder from your local checkout and run it via `sbt`, `ant` or standalone as follows. diff --git a/_overviews/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md index f52faa5c18..82346bcb15 100644 --- a/_overviews/contribute/scala-internals.md +++ b/_overviews/contribute/scala-internals.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 8 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/scala-internals/ --- ## scala-internals diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index 97e3d708f9..977e733528 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 6 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/scala-standard-library-api-documentation.html --- This page is specific to API documentation contributions – that is, API @@ -13,8 +12,8 @@ documentation for sometimes referred to as Scaladoc contributions. For contributions to tutorial and guide-style documentation on -[docs.scala-lang.org](https://docs.scala-lang.org), -see the ["doc-site"'s contribution guide](https://docs.scala-lang.org/contribute.html). +[docs.scala-lang.org](/), +see the ["doc-site"'s contribution guide](/contribute.html). *Please note, these instructions cover documentation contributions Scala core libraries only. For other Scala projects please check those projects for the @@ -79,7 +78,7 @@ component so that they show up in the correct issue filters. Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](./hacker-guide.html#2-set-up) - follow the setup steps through +* [Forking the Repo](/overviews/contribute/hacker-guide.html#2-set-up) - follow the setup steps through the Branch section. If providing new documentation related to an existing GitHub issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated GitHub issue, use `scaladoc/xxxx` instead. diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index 6df7c454a9..b7ae46b9ed 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -4,7 +4,6 @@ layout: multipage-overview num: 10 partof: scala-contribution overview-name: Contributing to Scala -permalink: /contribute/tools.html # Projects list: projects: @@ -23,7 +22,7 @@ projects: homeLink: https://www.scala-lang.org/api issuesLink: https://github.com/scala/bug/labels/scaladoc readmeLink: https://github.com/scala/scala#welcome - contributingLink: https://scala-lang.org/contribute/guide.html + contributingLink: /overviews/contribute/guide.html - title: Scala IDE description: Interactive build tool. icon: https://avatars2.githubusercontent.com/u/1026788?v=3&s=200 @@ -70,7 +69,7 @@ projectsInNeed: The links below are to a number of Scala build and IDE related projects that are important in the larger Scala space, and which welcome contributions. -Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/contribute/hacker-guide.html) and [Bug-fixing](/contribute/guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. +Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/overviews/contribute/hacker-guide.html) and [Bug-fixing](/overviews/contribute/guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. Typically, issues for these projects will be reported and kept in the GitHub project issue tracker for that project rather than in the Scala bug tracker. @@ -82,7 +81,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation.html#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/overviews/contribute/documentation.html#updating-scala-langorg) to fix it. ### Projects From 9d9f0968e4635dc5eaf74cc0053b091e22eb2811 Mon Sep 17 00:00:00 2001 From: Antoine Pointeau Date: Mon, 21 Mar 2022 14:04:32 +0100 Subject: [PATCH 0992/2265] Translation for fr/extractor-objects (#2268) --- _fr/tour/extractor-objects.md | 58 +++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/_fr/tour/extractor-objects.md b/_fr/tour/extractor-objects.md index ac5c1dc013..9ffc529a58 100644 --- a/_fr/tour/extractor-objects.md +++ b/_fr/tour/extractor-objects.md @@ -3,10 +3,64 @@ layout: tour title: Extractor Objects partof: scala-tour -num: 14 +num: 18 language: fr -next-page: generic-classes +next-page: for-comprehensions previous-page: regular-expression-patterns --- + +Un objet extracteur est un objet avec une méthode `unapply`. Tandis que la méthode `apply` ressemble à un constructeur qui prend des arguments et crée un objet, `unapply` prend un object et essaye de retourner ses arguments. Il est utilisé le plus souvent en filtrage par motif (*pattern matching*) ou avec les fonctions partielles. + +```scala mdoc +import scala.util.Random + +object CustomerID { + + def apply(name: String) = s"$name--${Random.nextLong}" + + def unapply(customerID: String): Option[String] = { + val stringArray: Array[String] = customerID.split("--") + if (stringArray.tail.nonEmpty) Some(stringArray.head) else None + } +} + +val customer1ID = CustomerID("Sukyoung") // Sukyoung--23098234908 +customer1ID match { + case CustomerID(name) => println(name) // prints Sukyoung + case _ => println("Could not extract a CustomerID") +} +``` + +La méthode `apply` crée une chaîne de caractères `CustomerID` depuis `name`. La méthode `unapply` fait l'inverse pour retrouver le `name`. Lorsqu'on appelle `CustomerID("Sukyoung")`, c'est un raccourci pour `CustomerID.apply("Sukyoung")`. Lorsqu'on appelle `case CustomerID(name) => println(name)`, on appelle la méthode `unapply` avec `CustomerID.unapply(customer1ID)`. + +Sachant qu'une définition de valeur peut utiliser une décomposition pour introduire une nouvelle variable, un extracteur peut être utilisé pour initialiser la variable, avec la méthode `unapply` pour fournir la valeur. + +```scala mdoc +val customer2ID = CustomerID("Nico") +val CustomerID(name) = customer2ID +println(name) // prints Nico +``` + +C'est équivalent à `val name = CustomerID.unapply(customer2ID).get`. + +```scala mdoc +val CustomerID(name2) = "--asdfasdfasdf" +``` + +S'il n'y a pas de correspondance, une `scala.MatchError` est levée : + +```scala +val CustomerID(name3) = "-asdfasdfasdf" +``` + +Le type de retour de `unapply` doit être choisi comme suit : + +* Si c'est juste un test, retourner un `Boolean`. Par exemple, `case even()`. +* Si cela retourne une seule sous-valeur de type T, retourner un `Option[T]`. +* Si vous souhaitez retourner plusieurs sous-valeurs `T1,...,Tn`, groupez-les dans un tuple optionnel `Option[(T1,...,Tn)]`. + +Parfois, le nombre de valeurs à extraire n'est pas fixe et on souhaiterait retourner un nombre arbitraire de valeurs, en fonction des données d'entrée. Pour ce cas, vous pouvez définir des extracteurs avec la méthode `unapplySeq` qui retourne un `Option[Seq[T]]`. Un exemple commun d'utilisation est la déconstruction d'une liste en utilisant `case List(x, y, z) =>`. Un autre est la décomposition d'une `String` en utilisant une expression régulière `Regex`, comme `case r(name, remainingFields @ _*) =>`. + +Traduit par Antoine Pointeau. \ No newline at end of file From ef8f171b14742544916c206bada7517d7cb99d53 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 14:32:32 +0100 Subject: [PATCH 0993/2265] modernise the content somewhat --- _contribute_resources/3-code-reviews.md | 1 + _overviews/contribute/bug-reporting-guide.md | 29 +++---- _overviews/contribute/codereviews.md | 47 ++++++----- _overviews/contribute/guide.md | 44 ++++------ _overviews/contribute/index.md | 2 +- _overviews/contribute/scala-internals.md | 84 +++++++++++-------- ...cala-standard-library-api-documentation.md | 9 +- _overviews/contribute/tools.md | 61 +++++--------- 8 files changed, 137 insertions(+), 140 deletions(-) diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index 41f6821414..e6f15e271c 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -4,5 +4,6 @@ link: /overviews/contribute/codereviews.html icon: fa fa-eye --- Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), +[lampepfl/dotty](https://github.com/lampepfl/dotty/pulls), [scala/scala-lang](https://github.com/scala/scala-lang/pulls), [scala/docs.scala-lang](https://github.com/scala/docs.scala-lang/pulls) and others. diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index 5cbf0a3f46..9545ecdc53 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -6,7 +6,7 @@ partof: scala-contribution overview-name: Contributing to Scala --- -The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. +The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug), and for Scala 3, it is located at [github.com/lampepfl/dotty](https://github.com/lampepfl/dotty/issues). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. ## Is it a Bug? @@ -22,7 +22,6 @@ If your issue is related to any of the following external projects, make sure to - [Akka](https://doc.akka.io/docs/akka/current/project/issue-tracking.html) - [Play!](https://github.com/playframework/Play20/issues) - [Slick](https://github.com/slick/slick/issues) - - [Scala IDE](https://scala-ide-portfolio.assembla.com/spaces/scala-ide/support/tickets) - [sbt](https://github.com/sbt/sbt/issues) The following are generally considered to be bugs: @@ -53,10 +52,10 @@ In general, if you find yourself stuck on any of these steps, asking on [Scala C - For compiler bugs use the [Compiler Category](https://contributors.scala-lang.org/c/compiler). * Examples of exceptions reported by the compiler which usually are not bugs: - 1. `StackOverflowError` is typically not a bug unless the stacktrace involves the internal packages of the compiler (like `scala.tools.nsc...`). Try to increase the Java stack size (`-Xss`), in most of the cases it helps. + 1. `StackOverflowError` is typically not a bug unless the stacktrace involves the internal packages of the compiler (like `scala.tools.nsc...`, or `dotty.tools.dotc...`). Try to increase the Java stack size (`-Xss`), in most of the cases it helps. 2. `AbstractMethodError` can occur when you did not recompile all the necessary Scala files (build tools, like `sbt`, can prevent that from happening) or you are mixing external libraries compiled for different Scala versions (for example one uses `2.10.x` and the other `2.11.x`). -## Reporting Confirmed Bugs is a Sin +## Please Check Before Reporting a Bug Before reporting your bug, make sure to check the issue tracker for other similar bugs. The exception name or a compiler phase are the best keywords to search for. If you are experiencing unexpected behavior search for method/class names where it happens. Your issue might already be reported, and a workaround might already be available for you take advantage of. If your issue *is* reported, be sure to add your test case as a comment if it is different from any of the existing ones. @@ -68,7 +67,7 @@ If you cannot find your issue in the issue tracker, create a new bug. The detail Please make sure to fill in as many fields as possible. Make sure you've indicated the following: - 1. **Exact Scala version** that you are using. For example, `2.10.1` or `2.11.0-RC`. If the bug happens in multiple versions indicate all of them. + 1. **Exact Scala version** that you are using. For example, `2.13.8` or `3.1.2-RC1`. If the bug happens in multiple versions indicate all of them. 2. **The component** that is affected by the bug. For example, the Standard Library, Scaladoc, etc. 3. **Labels** related to your issue. For example, if you think your issue is related to the typechecker, and if you have successfully minimized your issue, label your bug as "typechecker" and "minimized". Issue tracker will suggest names for existing labels as you type them so try not to create duplicates. 4. **Running environment**. Are you running on Linux? Windows? What JVM version are you using? @@ -78,12 +77,14 @@ In order for us to quickly triage the bug that you've found, it's important that ### Description In the description of your issue, be as detailed as you can. Bug reports which have the following information included are typically understood, triaged, and fixed very quickly: - - 1. Include a test case (minimized if possible) enabling us to reproduce the problematic behavior. Include your test case (and output) in proper formatting `{code}` blocks: - - {code}Here you put your classes{code} - - 2. The expected output. - 3. The actual output, including the stacktrace. - 4. Related discussion on the mailing lists, if applicable. - 5. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. +1. Include a test case (minimized if possible) enabling us to reproduce the problematic behavior. Include your test +case (and output) in properly formatted code blocks: +~~~ +```scala +List(1, 2, 3).map(x => x + 1) +``` +~~~ +2. The expected output. +3. The actual output, including the stacktrace. +4. Related discussion on the mailing lists, if applicable. +5. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index 368bf96793..e7dea2acea 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -29,27 +29,32 @@ own pull requests. ## Pull Requests Awaiting Comment
    -
    -
    -

    scala/scala

    -

    Scala bug fixes and changes in the language, core libs and included tools.

    -
    -
    -

    scala/scala.github.com

    -

    Scala documentation site.

    -
    -
    - -
    -
    -

    scala/scala-lang

    -

    The Scala language web site.

    -
    -
    -

    All Scala GitHub Projects

    -

    For other PRs, follow the scala project from here.

    -
    -
    +
    +
    +

    lampepfl/dotty

    +

    Scala 3 bug fixes and changes in the language, core libs and included tools.

    +
    +
    +

    scala/scala

    +

    Scala 2 bug fixes and changes in the language, core libs and included tools.

    +
    +
    +
    +
    +

    scala/scala-lang

    +

    The Scala language web site.

    +
    +
    +

    scala/docs.scala-lang.org

    +

    Scala documentation site.

    +
    +
    +
    +
    +

    All Scala GitHub Projects

    +

    For other PRs, follow the scala project from here.

    +
    +
    Also note that the [Tools contributions](/overviews/contribute/tools.html) page has more projects that will generate pull requests. diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 0b5b146ffc..5acc188a27 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -6,29 +6,13 @@ partof: scala-contribution overview-name: Contributing to Scala --- -
    -
    -
    -

    Scala Contributors

    -

    Get a peek into the inners of the Scala compiler.

    -
    -
    -

    Report an issue

    -

    File a bug report or a feature request.

    -
    -
    - -
    -
    -

    Community issues

    -

    Get cracking on some easy to approach issues.

    -
    -
    -

    Hacker guide

    -

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    -
    -
    -
    +| **Shortcut** | **Description** | +|----------------------------------------|-----------------| +| [Scala Contributors][contrib-forum] | Get a peek into the inners of the Scala compiler. | +| [Report an Issue][bug-reporting-guide] | File a bug report or a feature request. | +| [Community Issues][community-tickets] | Get cracking on some easy to approach issues. | +| [Scala 2 Hacker's Guide][hackers] | Learn to write good code and improve your chances of contributing to the Scala galaxy. | +| [Scala 3 Contributing Guide][scala3-hackers] | Walkthrough contributing to the Scala 3 compiler, along with a guide to compiler internals. | @@ -52,11 +36,13 @@ which allows us to ensure that all code submitted to the project is unencumbered by copyrights or patents. ### Bug-fix Check List +> Originally these steps cover the [Scala 2 compiler](https://github.com/scala/scala), but they also are relevant to +> the [Scala 3 compiler](https://github.com/lampepfl/dotty). This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [GitHub branch](https://github.com/scala/scala) 1. [Select a bug to fix from GitHub](/overviews/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/overviews/contribute/bug-reporting-guide.html) (but please -[make sure it's not a duplicate](/overviews/contribute/bug-reporting-guide.html#reporting-confirmed-bugs-is-a-sin)). +[make sure it's not a duplicate](/overviews/contribute/bug-reporting-guide.html#please-check-before-reporting-a-bug)). 2. Optional ([but recommended](/overviews/contribute/scala-internals.html/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with [these friendly people](/overviews/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. 3. [Fork the Scala repository](/overviews/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). @@ -70,7 +56,7 @@ https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is r 10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/overviews/contribute/hacker-guide.html#review). 11. Celebrate! -Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide](/overviews/contribute/hacker-guide.html) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). +Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide][hackers] (or the [equivalent Scala 3 Contributing Guide][scala3-hackers]) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). ### Larger Changes, New Features @@ -79,4 +65,10 @@ and on the implementation plan. Announce the change on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](https://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](/overviews/contribute/hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. +the Scala project source tree. The hacker's guides ([Scala 2][hackers], or [Scala 3][scala3-hackers]) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. + +[hackers]: /overviews/contribute/hacker-guide.html +[community-tickets]: /overviews/contribute/index.html#community-tickets +[bug-reporting-guide]: /overviews/contribute/bug-reporting-guide.html +[scala3-hackers]: {% link _overviews/scala3-contribution/procedures-intro.md %} +[contrib-forum]: https://contributors.scala-lang.org/ diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index 8b7dad1e83..b89f04803a 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -37,7 +37,7 @@ When contributing, please follow: ### Community Tickets -All issues can be found in the [Scala bug tracker](https://github.com/scala/bug). Most issues are labeled +All issues can be found in the [Scala bug tracker](https://github.com/scala/bug), or the [Scala 3 issue tracker](https://github.com/lampepfl/dotty/issues). Most issues are labeled to make it easier to find issues you are interested in. ### Tools and Libraries diff --git a/_overviews/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md index 82346bcb15..ac5be2fd85 100644 --- a/_overviews/contribute/scala-internals.md +++ b/_overviews/contribute/scala-internals.md @@ -1,47 +1,63 @@ --- -title: Scala Internals Mailing List +title: Scala Contributors Forum layout: multipage-overview num: 8 partof: scala-contribution overview-name: Contributing to Scala --- -## scala-internals - -The [scala-internals mailing list](https://groups.google.com/d/forum/scala-internals) is where technical and logistical discussions concerning bugs, bug fixes, documentation, improvements, new features and other contributor related topics occur. - -### Coordinating on scala-internals - -Prior to commencing on contribution work on larger changes to the Scala project, it is recommended (but not required) that you make a post on scala-internals announcing your intention. It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, one of whom will probably be reviewing your contribution at some point. For smaller bug fixes or documentation changes where the risk of effort duplication is minimal, you can skip this post. - -To help subscribers on the scala-internals list to sort through the postings, we request that the following topic labels are applied when you start a new post please: - -| Label | Topics | -|-----------|-------------------------------------------------------| -| [docs] | Documentation, e.g. docs.scala-lang.org, API (scaladoc), etc. | -| [issues] | Bug reporting/fixing | -| [tools] | Tools including sbt, IDE plugins, testing, scaladoc generator, etc. | -| [libs] | Core libraries, extension libraries | -| [compiler] | Scala compiler discussions/features/issues | -| [admin] | Administrative/coordination topics | - -So, to talk about this list (an admin activity primarily) one might use: - -`[admin] more suggested labels for topic differentiation.` - -as a title, which then shows up on the mailing lists as - -`[scala-internals] [admin] more suggested labels for topic differentiation.` +The [Scala Contributors Forum][scala-contributors] is where discussions about the Scala ecosystem +occur, from the perspectives of core compiler, documentation and library contributors. It features updates from the +Scala Center, along with technical and logistical discussions concerning bugs, bug fixes, documentation, improvements, +new features and other contributor related topics. + +> The now legacy [scala-internals mailing list](https://groups.google.com/d/forum/scala-internals) used to fulfil this +> purpose, but has since expanded to encompass more topics in the new [forum][scala-contributors]. + +## Coordinating on Scala Contributors + +Prior to commencing on contribution work on larger changes to the Scala project, it is recommended (but not required) +that you make a post on [Scala Contributors][scala-contributors] announcing your intention. +It's a great time to invite any help, advice or ask any questions you might have. It's also a great place to meet peers, +one of whom will probably be reviewing your contribution at some point. +For smaller bug fixes or documentation changes where the risk of effort duplication is minimal, you can skip this post. + +To help users to sort through the posts, we request that the following categories are applied when you start a +new post please: + +| Category | Topics | +|-----------------------------|---------------------------------------------------------------------| +| `Documentation` | Documentation, e.g. docs.scala-lang.org, API (scaladoc), etc. | +| `Compiler` | Bug reporting/fixing, Scala compiler discussions/issues | +| `Tooling` | Tools including sbt, IDE plugins, testing, scaladoc generator, etc. | +| `Scala Standard Library` | Core libraries | +| `Scala Platform` | Extension libraries | +| `Language Design` | Scala language feature discussions / informal proposals | +| `Scala Improvement Process` | Scala language feature formal proposals | +| `Meta Discourse` | Administrative/coordination topics | +| `Community` | Discussions about events, community organising | ### Why It's a Good Idea -While it is optional to announce your intentions/work items on scala-internals before starting, it is recommended and a smart thing to do for a number of reasons: +While it is optional to announce your intentions/work items on [Scala Contributors][scala-contributors] before starting, it is recommended thing to do for a number of reasons: * To attempt to cut down on duplicate effort (i.e. to avoid two people working on the same bug at the same time without coordinating effort). * Related to the above: to allow the compiler team and core committers to warn of or smooth over potential merge conflicts between separate bugs that might affect the same code. -* Potentially someone has already thought about or even worked on that issue or a related one, and has valuable insight that might save you time (including warnings about what you might find and may want to avoid - dead ends that have already been explored). -* You might find a group of impassioned individuals want to volunteer to help you, since you got there first with your post it's up to you to decide if you want help or not. -* Posting could start a dialog with a potential reviewer, smoothing the latter, merge stages of the issue. -* There are a lot of nice people waiting to talk to you on scala-internals, you might be surprised how valuable and pleasant you find the experience of talking to them. - -If all of this has not convinced you then, please, go ahead and work on contributions anyway. It *is* less important to post to scala-internals first for small, self contained bugs than it is for larger issues or features, and not having posted first will not be a reason for your PR to be rejected, it just might be a rougher review/merge process than if you had posted first. It's your choice. +* Potentially someone has already thought about or even worked on that issue or a related one, and has valuable insight +that might save you time (including warnings about what you might find and may want to avoid - perhaps one option +already tried lead to no benefit). +* You might find a group of impassioned individuals who want to volunteer and help you. You will have the momentum since +you posted first, so then it's up to you to decide if you want their help or not. +* Posting could start a dialog with a potential reviewer, smoothing the later stages of your contribution before +merging your changes. +* There are a lot of nice people waiting to talk to you on [Scala Contributors][scala-contributors], you might be +surprised how valuable and pleasant you find the experience of talking to them. + +Even if you do not wish to post on [Scala Contributors][scala-contributors], please feel welcome to make contributions +anyway, as posting to the forum is *not* criteria for it to be accepted. For smaller, self-contained bugs it is +especially less important to make a post, however larger issues or features take more time to consider accepting them. +For large contributions we strongly recommend that you do to notify of your intention, which will help you determine if +there is large community support for your change, making it more likely that your large contribution will accepted, +before you spend a long time implementing it. + +[scala-contributors]: https://contributors.scala-lang.org diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index 977e733528..ba59855392 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -43,7 +43,8 @@ and identify missing, incorrect or inadequate documentation. A good place to sta package objects for important packages (these often get overlooked for documentation and are a good place for API overviews). -If you find an issue, please log it in the [Scala bug tracker](https://github.com/scala/bug) +If you find an issue, please log it in the [Scala bug tracker](https://github.com/scala/bug), +(or else the [Scala 3 issue tracker](https://github.com/lampepfl/dotty/issues) for Scala 3 library additions) **after making sure it is not already logged as an issue**. To help with disambiguation, please use the following format for issue title: @@ -112,10 +113,10 @@ PR is merged in smoothly: Scala code is likely to flag as mis-spelled sometimes, but any written language should be checked. If you can also use a grammar checker, even better. We *will* ask for spelling and grammar to be corrected before acceptance. -* You **must** also run `ant docs`, fix any problems and check the formatting and +* You **must** also run `sbt doc`, fix any problems and check the formatting and layout of your changes. Again, corrections will be required if formatting or - layout are inadequate. After running `ant docs` the generated documents can be - found under the `build/scaladoc/` folders (probably in the `library` folder + layout are inadequate. After running `sbt doc` the generated documents can be + found under the `build/scaladoc/` folders (probably in the `library` subdirectory but maybe under the others depending on what section of the Scala source you are working on). * All of these steps are required to save time for both the reviewers and diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index b7ae46b9ed..4ce5a3be0a 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -8,8 +8,8 @@ overview-name: Contributing to Scala # Projects list: projects: - title: sbt - description: Interactive build tool. - icon: https://www.scala-sbt.org/assets/typesafe_sbt_svg.svg + description: The interactive build tool. + icon: https://www.scala-sbt.org/assets/sbt-logo.svg link: https://github.com/sbt/sbt homeLink: https://www.scala-sbt.org/ issuesLink: https://github.com/sbt/sbt#issues-and-pull-requests @@ -23,57 +23,26 @@ projects: issuesLink: https://github.com/scala/bug/labels/scaladoc readmeLink: https://github.com/scala/scala#welcome contributingLink: /overviews/contribute/guide.html - - title: Scala IDE - description: Interactive build tool. - icon: https://avatars2.githubusercontent.com/u/1026788?v=3&s=200 - link: https://github.com/scala-ide/scala-ide - homeLink: http://scala-ide.org/ - issuesLink: https://scala-ide-portfolio.assembla.com/spaces/scala-ide/support/tickets - readmeLink: https://github.com/scala-ide/scala-ide/blob/master/README.md - contributingLink: https://github.com/scala-ide/scala-ide/blob/master/CONTRIBUTING.md - - title: DBuild - description: Multi-project build tool. - icon: https://avatars3.githubusercontent.com/u/784923?v=3&s=200 - link: https://github.com/lightbend/dbuild - homeLink: https://lightbend.github.io/dbuild - issuesLink: https://github.com/lightbend/dbuild/issues - readmeLink: https://github.com/lightbend/dbuild/blob/master/README.md - contributingLink: https://github.com/lightbend/dbuild/blob/master/README.md#get-involved - title: Partest - description: Scala Compiler/Library Testing + description: Scala Compiler/Library Testing (Contribute through scala/scala) icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 - link: https://github.com/scala/scala-partest - homeLink: https://docs.scala-lang.org/tutorials/partest-guide.html - issuesLink: https://github.com/scala/scala-partest/issues - readmeLink: https://github.com/scala/scala-partest/blob/1.1.x/README.md + link: https://github.com/scala/scala + homeLink: https://github.com/scala/scala + issuesLink: https://github.com/scala/scala/issues + readmeLink: https://github.com/scala/scala/blob/2.13.x/CONTRIBUTING.md#partest contributingLink: - - title: Scoverage - description: Scala code coverage tool - icon: https://avatars1.githubusercontent.com/u/5998302?v=3&s=200 - link: https://github.com/scoverage/scalac-scoverage-plugin - homeLink: http://scoverage.org/ - issuesLink: https://github.com/scoverage/scalac-scoverage-plugin/issues - readmeLink: https://github.com/scoverage/scalac-scoverage-plugin/blob/master/README.md - contributingLink: https://groups.google.com/forum/#!forum/scala-code-coverage-tool projectsInNeed: - - title: Scalariform - description: Scala source code formatter - icon: /resources/img/white-line.png - link: https://github.com/mdr/scalariform - homeLink: https://github.com/mdr/scalariform/wiki/Command-line-tool - issuesLink: https://github.com/mdr/scalariform/issues - readmeLink: https://github.com/mdr/scalariform/blob/master/README.rst --- ## Contributing to IDE and Build Tools The links below are to a number of Scala build and IDE related projects that are important in the larger Scala space, and which welcome contributions. -Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. The [Hacker Guide](/overviews/contribute/hacker-guide.html) and [Bug-fixing](/overviews/contribute/guide.html) pages will likely have much in the way of related information on how to contribute to these projects, and are recommended reading. You should also check the README.md and (if it's present) CONTRIBUTING.md files from the actual projects before contributing to them. +Since these tools are in separate projects, they may (and likely will) have their own rules and guidelines for contributing. You should also check the `README.md` and (if it's present) `CONTRIBUTING.md` files from the actual projects before contributing to them. Typically, issues for these projects will be reported and kept in the GitHub project issue tracker for that project rather than in the Scala bug tracker. -Many of these projects have a chat room on Discord or Gitter (usually linked from their README or CONTRIBUTING files) which is a great place to discuss proposed work before starting. +Many of these projects have a chat room on Discord or Gitter (usually linked from their `README.md` or `CONTRIBUTING.md` files) which is a great place to discuss proposed work before starting. There are some projects in this section that are in [particular need](#projects-in-particular-need) so please check those out @@ -85,10 +54,22 @@ Stuff changes. Found a broken link or something that needs updating on this page ### Projects +{% if page.projects.size > 0 %} {% include contributions-projects-list.html collection=page.projects %} +{% else %} +There are no projects. +{% endif %} ### Projects in Particular Need +{% if page.projectsInNeed.size > 0 %} + The following projects are important to the Scala community but are particularly in need of contributors to continue their development. {% include contributions-projects-list.html collection=page.projectsInNeed %} + +{% else %} + +There are no projects in particular need. + +{% endif %} From b32fe5627023d8c45d20a1fcf20c20ae3e70e7b0 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 14:47:11 +0100 Subject: [PATCH 0994/2265] add new page - Add New Guides/Tutorials --- README.md | 2 +- _contribute_resources/1-documentation.md | 2 +- _overviews/contribute/add-guides.md | 221 ++++++++++++++++++ _overviews/contribute/bug-reporting-guide.md | 2 +- _overviews/contribute/documentation.md | 4 +- _overviews/contribute/guide.md | 2 +- _overviews/contribute/hacker-guide.md | 2 +- _overviews/contribute/partest-guide.md | 2 +- _overviews/contribute/scala-internals.md | 2 +- ...cala-standard-library-api-documentation.md | 2 +- _overviews/contribute/tools.md | 2 +- contribute.md | 179 +------------- 12 files changed, 237 insertions(+), 185 deletions(-) create mode 100644 _overviews/contribute/add-guides.md diff --git a/README.md b/README.md index a6283b2386..ee37fe58d4 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ For more details on the Docker option, see [this issue](https://github.com/scala ## Contributing ## -Please have a look at [https://docs.scala-lang.org/contribute.html](https://docs.scala-lang.org/contribute.html) before making a contribution. +Please have a look at [Add New Guides/Tutorials](https://docs.scala-lang.org/overviews/contribute/add-guides.html) before making a contribution. This document gives an overview of the type of documentation contained within the Scala Documentation repository and the repository's structure. Small changes, or corrected typos will generally be pulled in right away. Large changes, like the addition of new documents, or the rewriting of diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 3e1b81a7b9..7515ff7519 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -3,4 +3,4 @@ title: Documentation link: /overviews/contribute/documentation.html icon: fa fa-book --- -[Scaladoc (API)](/overviews/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/contribute.html) and [scala-lang.org](https://github.com/scala/scala-lang). +[Scaladoc (API)](/overviews/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/overviews/contribute/add-guides.html) and [scala-lang.org](https://github.com/scala/scala-lang). diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md new file mode 100644 index 0000000000..c8f5e42f0c --- /dev/null +++ b/_overviews/contribute/add-guides.md @@ -0,0 +1,221 @@ +--- +title: Add New Guides/Tutorials +layout: multipage-overview +num: 7 +partof: scala-contribution +overview-name: Contributing to Scala +--- + +## Why Contribute New Learning Material? + +As [Heather Miller writes](/contribute.html), contributing to [docs.scala-lang.org](https://docs.scala-lang.org) is +critical to making Scala accessible to newcomers, experience programmers, and anyone who is curious. +It is also a fantastic way to contribute for anyone who is comfortable using Scala, but maybe does not want to get +involved with complex tools like the compiler. + +## Architecture + +This documentation website is backed by an open-source [github repository](https://github.com/scala/docs.scala-lang), +and is always contribution-ready. + +### Content + +Currently, the _types_ of documentation supported in this repository are: + +- **Guides/Overviews**: Definitive guides/overviews of specific language features. Often long, detailed documents, + often produced by members of the Scala team. An example is the excellent [Collections][collections-overview] overview. +- **Tutorials**: Bite-size, example-rich, and concise articles meant to get a developer up to speed quickly. +- **Cheatsheets**: Quick reference of Scala syntax and behaviors. + +### Implementation + +The website is statically generated from [Markdown](https://en.wikipedia.org/wiki/Markdown) source using +[Jekyll](https://github.com/mojombo/jekyll), and hosted on [GitHub Pages](https://pages.github.com/). +This workflow was chosen so as to make it as easy as possible for core committers and the community alike +to produce HTML documentation, and as easy as possible to publish it in a central location. + +The markdown syntax being used supports [Maruku](https://github.com/bhollis/maruku) extensions, and has automatic +syntax highlighting, without the need for any tags. + +Additionally [mdoc](https://github.com/scalameta/mdoc) is used during pull requests to validate Scala code blocks. +To use this feature you must use the backtick notation as documented by mdoc. Note that only validation is done. +The output files from mdoc are not used in the building of the tutorial. Use `mdoc` or `mdoc:fail` for your code blocks. + +## Submitting Docs + +For one to contribute a document, one must simply +[fork](https://help.github.com/articles/fork-a-repo/) the +[repo](https://github.com/scala/docs.scala-lang), write their article in +[Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and submit a pull request. That's it. +Likely after some edits and discussion, your document will be made live +on [docs.scala-lang.org](https://docs.scala-lang.org). + + --- + layout: overview + title: My Awesome Title + --- + + ## An h2 Header in Markdown + + And a paragraph, with a [link](https://www.scala-lang.org). + +One can contribute code in a markdown document by either + - indenting it by 4 spaces + - surrounding by triple backticks, as shown below + - in-line by putting backticks around it, e.g. `def foo`. + + ```scala + println("hello") + ``` + +Everything else is automatically generated for you; tables of contents, and most index pages. And of course, the +styling is already taken care of for you. + +### Criteria for Docs to be Accepted + +The goal of this documentation repository is to be tighter and more organized than other community-driven documentation platforms, like wikis. As such, any document pulled in for inclusion on +[docs.scala-lang.org](https://docs.scala-lang.org) must: + +- **"fit in"** to the repository ( _i.e.,_ it should not be a complete duplicate of another article), +- **be polished** it must be thorough, complete, correct, organized, and "article-like" (personal programming notes +don't quite fit.) +- **be maintained** if the document might require revisions from time to time, be prepared to keep it up to date, or +nominate someone to take ownership. + +If you have something you're thinking about contributing, or that you're thinking about writing in order to contribute +-- we'd love to consider it! Please don't hesitate to use GitHub issues and pull requests and the +\#scala-contributors room [on Discord](https://discord.com/invite/scala) for any questions, concerns, +clarifications, etc. + +## Document Templates + +> **Note:** These templates will soon change slightly as a result of necessary refactoring. + +### Guides/Overviews + +A guide or an overview that can be logically placed on **one** page must be placed in the directory +`_overviews/RELEVANT-CATEGORY/_posts` with the file name in the format `YYYY-MM-dd-title-separated-by-dashes.md`, +and header: + + --- + layout: overview + title: YOUR TITLE + --- + +The rest of the document should, of course, be written in [Markdown](https://en.wikipedia.org/wiki/Markdown). + +At the moment, `RELEVANT-CATEGORY` corresponds to only a single category, "core," because we are currently focusing on +building up documentation of core libraries. However, expect more categories here in the future. + +If your document consists of **multiple** pages, like the [Collections][collections-overview] overview, an ordering +must be specified, by numbering documents in their logical order with `num`, and a name must be assigned to the +collection of pages using `partof`. For example, the following header might be used for a document in the collections +overview: + + --- + layout: overview + title: YOUR TITLE + + partof: collections + num: 10 + --- + +A **single** document in the collection must contain a tag in the header, `outof`, that indicates the total number of +documents in the large overview. Putting it on the last page in the overview is often best: + + --- + layout: overview + title: YOUR TITLE + + partof: collections + num: 15 + outof: 15 + --- + +Index pages, such as [docs.scala-lang.org/overviews/index.html](https://docs.scala-lang.org/overviews/index.html) are +generated, by reading data from a configuration file, such as `_data/overviews.yml`, so your overview should be +placed into a category there. + +### Tutorials + +At the moment, tutorials are written the same as Guides/Overviews, except that their link must be added to +the metadata of `/tutorials.md`. e.g. for the [Scala With Maven][scala-with-maven] tutorial, the +metadata of `/tutorials.md` looks like + + --- + layout: inner-page-parent + title: Tutorials + + tutorials: + ... + - title: "Scala with Maven" + url: "/tutorials/scala-with-maven.html" + description: "Create a Scala project with Maven." + icon: code + --- + +For a single-page tutorial, the typical directory to place them in is `_overviews/tutorials`. + +### Cheatsheets + +For now, cheatsheets are assumed to be in the form of tables. To contribute a cheatsheet, one must simply produce their +cheatsheet as a Markdown table, with the following header: + + --- + layout: cheatsheet + title: YOUR TITLE + by: YOUR NAME + about: SOME TEXT ABOUT THE CHEAT SHEET. + --- + +### Code blocks + +The site build process uses [mdoc](https://scalameta.org/mdoc/) to typecheck +code snippets in markdown. This is a great way to ensure the code snippets that +you're including typecheck and are valid. Here are a few quick types to get +started. + +To get started, add `mdoc` after `scala` when you are creating a +code block. The `mdoc` modifier here will make sure that `mdoc` runs the code +snippet and ensures that it's valid. + + ```scala mdoc + val a = 1 + ``` +If you have a snippet that you expect to fail, you can also account for this by +using `mdoc:fail` for a compile error `mdoc:crash` for a runtime-error. + + ```scala mdoc:fail + val b: String = 3 // won't compile + ``` +Keep in mind that a single file is all compiled as a single unit, so you can't +redefine a variable that was defined above in another code snippet. _However_ +there are a couple ways to get around this. Firstly, you can use the `mdoc:nest` +modifier with will wrap the snippet in a `scala.Predef.locally{...}`. This will +essentially "hide" the snippet from the others. Another way around this is to +use the `mdoc:reset` modifier, which _resets_ and forgets about everything up +above. Here is an example using the various modifiers. + + ```scala mdoc + import java.time.Instant + + def now() = Instant.now() + object Foo {} + ``` + + ```scala mdoc:nest + case class Foo(a: Int) // conflicts with Foo above, but it's nested so it's fine + ``` + + ```scala mdoc + val a = s"The time is ${now()}" // still have access to the now method from above + ``` + ```scala mdoc:reset + case class Foo(a: String) // forget the previous Foo's and start fresh + ``` + ```scala mdoc + val myFoo = Foo("hi") // now we only have access to the last Foo + ``` + +[collections-overview]: {% link _overviews/collections-2.13/introduction.md %} +[scala-with-maven]: {% link _overviews/tutorials/scala-with-maven.md %} diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index 9545ecdc53..ac6df525a5 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -1,7 +1,7 @@ --- title: Bug Reporting Guide layout: multipage-overview -num: 7 +num: 8 partof: scala-contribution overview-name: Contributing to Scala --- diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index 7fca82ff53..417f9b234a 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -44,7 +44,7 @@ without creating an issue, but please look to see if there is an issue already s * SIP (Scala Improvement Process) Proposals and more -Please read [contributing to the docs.scala-lang.org site](/contribute.html) through before embarking on changes. The site uses +Please read [Add New Guides/Tutorials](/overviews/contribute/add-guides.html) through before embarking on changes. The site uses the [Jekyll](https://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. ### Updating scala-lang.org @@ -55,4 +55,4 @@ to Scala and related projects) is provided on the main [scala-lang GitHub project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[docs.scala-lang.org contribution](/contribute.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[Add New Guides/Tutorials](/overviews/contribute/add-guides.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 5acc188a27..802e3c387c 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -1,7 +1,7 @@ --- title: Contributing guide layout: multipage-overview -num: 9 +num: 10 partof: scala-contribution overview-name: Contributing to Scala --- diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index cb83b6218a..f342c98040 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -2,7 +2,7 @@ title: Scala hacker guide by: Eugene Burmako layout: multipage-overview -num: 11 +num: 12 partof: scala-contribution overview-name: Contributing to Scala --- diff --git a/_overviews/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md index 6fb5a2644b..548eb8d5e6 100644 --- a/_overviews/contribute/partest-guide.md +++ b/_overviews/contribute/partest-guide.md @@ -1,7 +1,7 @@ --- title: Running the Test Suite layout: multipage-overview -num: 12 +num: 13 partof: scala-contribution overview-name: Contributing to Scala --- diff --git a/_overviews/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md index ac5be2fd85..5f391947fa 100644 --- a/_overviews/contribute/scala-internals.md +++ b/_overviews/contribute/scala-internals.md @@ -1,7 +1,7 @@ --- title: Scala Contributors Forum layout: multipage-overview -num: 8 +num: 9 partof: scala-contribution overview-name: Contributing to Scala --- diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index ba59855392..99f1bb16e0 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -13,7 +13,7 @@ sometimes referred to as Scaladoc contributions. For contributions to tutorial and guide-style documentation on [docs.scala-lang.org](/), -see the ["doc-site"'s contribution guide](/contribute.html). +see [Add New Guides/Tutorials](/overviews/contribute/add-guides.html). *Please note, these instructions cover documentation contributions Scala core libraries only. For other Scala projects please check those projects for the diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index 4ce5a3be0a..875160ca96 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -1,7 +1,7 @@ --- title: IDE and Build Tool Contributions layout: multipage-overview -num: 10 +num: 11 partof: scala-contribution overview-name: Contributing to Scala diff --git a/contribute.md b/contribute.md index 1abb5e539c..4a7d38faec 100644 --- a/contribute.md +++ b/contribute.md @@ -1,9 +1,9 @@ --- -layout: contribute -title: Contribute +layout: singlepage-overview +title: Why Contribute to docs.scala-lang.org? --- -###### Heather Miller +###### A note from Heather Miller ## A Place to Build Documentation Together @@ -21,175 +21,6 @@ If we want Scala to be accessible to more programmers, clear, easy-to-find docum If you're interested in contributing to the Scala project in general, I argue that one of the most meaningful ways that you can, is to help us improve this transfer of information- let's make it easier and faster for people to _get_ core concepts, and to answer their own questions so they can progress to _Scala-proficient_ quickly. Each line that you contribute has the potential to affect the entire Scala community as a whole-- current, and future. -## About docs.scala-lang.org +## How Can I Contribute? -### Content - -Currently, the _types_ of documentation supported in this repository are: - -- **Guides/Overviews**: Definitive guides/overviews of specific language features. Often long, detailed documents, often produced by members of the Scala team. An example is the excellent [Collections]({{ site.baseurl }}/overviews/collections-2.13/introduction.html) overview. -- **Tutorials**: Bite-size, example-rich, and concise articles meant to get a developer up to speed quickly. -- **Cheatsheets**: Quick reference of Scala syntax and behaviors. - -### Implementation - -This documentation repository is open-source, it lives in [github repository](https://github.com/scala/docs.scala-lang), and is always contribution-ready. - -It's statically generated from [Markdown](https://en.wikipedia.org/wiki/Markdown) source using [Jekyll](https://github.com/mojombo/jekyll), and hosted on [GitHub Pages](https://pages.github.com/). This workflow was chosen so as to make it as easy as possible for core committers and the community alike to produce HTML documentation, and as easy as possible to publish it in a central location. - -The markdown syntax being used supports [Maruku](https://github.com/bhollis/maruku) extensions, and has automatic syntax highlighting, without the need for any tags. - -Additionally [mdoc](https://github.com/scalameta/mdoc) is used during pull requests to validate Scala code blocks. To use this feature you must use the backtick notation as documented by mdoc. Note that only validation is done. The output files from mdoc are not used in the building of the tutorial. Use `mdoc` or `mdoc:fail` for your code blocks. - -## Submitting Docs - -For one to contribute a document, one must simply -[fork](https://help.github.com/articles/fork-a-repo/) the -[repo](https://github.com/scala/docs.scala-lang), write their article in -[Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and submit a pull request. That's it. Likely after some edits and discussion, your document will be made live on [docs.scala-lang.org](https://docs.scala-lang.org). - - --- - layout: overview - title: My Awesome Title - --- - - ## An h2 Header in Markdown - - And a paragraph, with a [link](https://www.scala-lang.org). - - One can contribute code by indenting it 4 spaces, or in-line by putting backticks around it like so, `def foo` - -Everything else is automatically generated for you; tables of contents, and most index pages. And of course, the styling is already taken care of for you. - -### Criteria for Docs to be Accepted - -The goal of this documentation repository is to be tighter and more organized than other community-driven documentation platforms, like wikis. As such, any document pulled in for inclusion on [https://docs.scala-lang.org](https://docs.scala-lang.org) must: - -- **"fit in"** to the repository ( _i.e.,_ it should not be a complete duplicate of another article), -- **be polished** it must be thorough, complete, correct, organized, and "article-like" (personal programming notes don't quite fit.) -- **be maintained** if the document might require revisions from time to time, it should come with an owner - -If you have something you're thinking about contributing, or that you're thinking about writing in order to contribute-- we'd love to consider it! Please don't hesitate to use GitHub issues and pull requests and the \#scala-contributors room [on Discord](https://discord.com/invite/scala) for any questions, concerns, clarifications, etc. - -## Document Templates - -
    -

    Note: These templates will soon change slightly as a result of necessary refactoring.

    -
    - -### Guides/Overviews - -A guide or an overview that can be logically placed on **one** page must be placed in the directory `overviews/RELEVANT-CATEGORY/_posts` with the file name in the format `YYYY-MM-dd-title-separated-by-dashes.md`, and header: - - --- - layout: overview - title: YOUR TITLE - --- - -The rest of the document should, of course, be written in [Markdown](https://en.wikipedia.org/wiki/Markdown). - -At the moment, `RELEVANT-CATEGORY` corresponds to only a single category, "core," because we are currently focusing on building up documentation of core libraries. However, expect more categories here in the future. - -If your document consists of **multiple** pages, like the [Collections]({{ site.baseurl }}/overviews/collections-2.13/introduction.html) overview, an ordering must be specified, by numbering documents in their logical order with `num`, and a name must be assigned to the collection of pages using `partof`. For example, the following header might be used for a document in the collections overview: - - --- - layout: overview - title: YOUR TITLE - - partof: collections - num: 10 - --- - -A **single** document in the collection must contain a tag in the header, `outof`, that indicates the total number of documents in the large overview. Putting it on the last page in the overview is often best: - - --- - layout: overview - title: YOUR TITLE - - partof: collections - num: 15 - outof: 15 - --- - -Index pages, such as [https://docs.scala-lang.org/overviews/index.html](https://docs.scala-lang.org/overviews/index.html) are automatically generated, assuming documents are properly placed under the correct `RELEVANT-CATEGORY`. So, simply drop your document into the correct folder, and you're done. - -### Tutorials - -At the moment, a tutorial that can be logically placed on **one** page must be placed in the directory `tutorials/` with the file name in the format `title-separated-by-dashes.md`. For the moment, single-page tutorials use the same layout as single-page overviews: - - --- - layout: overview - title: YOUR TITLE - --- - -If you have a **multiple-page** tutorial, like in the case of multiple-page overviews, you must both specify an ordering for your document, and a name must be assigned to the collection of tutorial pages. For example, the following header is used for the [Tour of Scala]({{ site.baseurl }}/tour/tour-of-scala.html) series of tutorial articles: - - --- - layout: inner-page-no-masthead - title: YOUR TITLE - - tutorial: scala-tour - num: 4 - --- - -At the moment, only indexes for multiple-page tutorials are automatically generated. - -### Cheatsheets - -For now, cheatsheets are assumed to be in the form of tables. To contribute a cheatsheet, one must simply produce their cheatsheet as a Markdown table, with the following header: - - --- - layout: cheatsheet - title: YOUR TITLE - by: YOUR NAME - about: SOME TEXT ABOUT THE CHEAT SHEET. - --- - -### Code blocks - -The site build process uses [mdoc](https://scalameta.org/mdoc/) to typecheck -code snippets in markdown. This is a great way to ensure the code snippets that -you're including typecheck and are valid. Here are a few quick types to get -started. - -To get started, you can simply add `mdoc` behind `scala` when you are creating a -code block. The `mdoc` modifier here will make sure that `mdoc` runs the code -snippet and ensures that it's valid. - - ```scala mdoc - val a = 1 - ``` -If you have a snippet that you expect to fail, you can also account for this by -using `mdoc:fail` for a compile error `mdoc:crash` for a runtime-error. - - ```scala mdoc:fail - val b: String = 3 // won't compile - ``` -Keep in mind that a single file is all compiled as a single unit, so you can't -redefine a variable that was defined above in another code snippet. _However_ -there are a couple ways to get around this. Firstly, you can use the `mdoc:nest` -modifier with will wrap the snippet in a `scala.Predef.locally{...}`. This will -essentially "hide" the snippet from the others. Another way around this is to -use the `mdoc:reset` modifier, which _resets_ and forgets about everything up -above. Here is an example using the various modifiers. - - ```scala mdoc - import java.time.Instant - - def now() = Instant.now() - object Foo {} - ``` - - ```scala mdoc:nest - case class Foo(a: Int) // conflicts with Foo above, but it's nested so it's fine - ``` - - ```scala mdoc - val a = s"The time is ${now()}" // still have access to the now method from above - ``` - ```scala mdoc:reset - case class Foo(a: String) // forget the previous Foo's and start fresh - ``` - ```scala mdoc - val myFoo = Foo("hi") // now we only have access to the last Foo - ``` +Please read: [Add New Guides/Tutorials](/overviews/contribute/add-guides.html) From 4b34e7fa4a4a5a972026e91cc3daa76451f3489d Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 21 Mar 2022 15:19:19 +0100 Subject: [PATCH 0995/2265] integrate guide with the site --- _data/doc-nav-header.yml | 2 ++ _data/nav-header.yml | 7 ++++++- _includes/site-header.html | 2 +- _ja/scala3/contribute-to-docs.md | 4 ++-- _ja/scala3/new-in-scala3.md | 2 +- index.md | 6 +++++- scala3/contribute-to-docs.md | 4 ++-- scala3/guides.md | 2 +- scala3/index.md | 2 +- scala3/new-in-scala3.md | 2 +- 10 files changed, 22 insertions(+), 11 deletions(-) diff --git a/_data/doc-nav-header.yml b/_data/doc-nav-header.yml index a96fdb3d42..9f45227579 100644 --- a/_data/doc-nav-header.yml +++ b/_data/doc-nav-header.yml @@ -35,6 +35,8 @@ url: "/tutorials/FAQ/index.html" - title: Language Specification url: http://scala-lang.org/files/archive/spec/2.13/ + - title: Contribution Guide + url: "/overviews/contribute/" - title: Style Guide url: "/style/index.html" - title: Cheatsheet diff --git a/_data/nav-header.yml b/_data/nav-header.yml index 26bd280020..a9d2f9ab38 100644 --- a/_data/nav-header.yml +++ b/_data/nav-header.yml @@ -1,12 +1,17 @@ - title: Documentation url: "/" + can-highlight: true - title: Download url: https://www.scala-lang.org/download/ + can-highlight: true - title: Community url: https://www.scala-lang.org/community/ + can-highlight: true - title: Libraries url: https://index.scala-lang.org + can-highlight: true - title: Contribute - url: https://www.scala-lang.org/contribute/ + url: /overviews/contribute/ - title: Blog url: https://www.scala-lang.org/blog/ + can-highlight: true diff --git a/_includes/site-header.html b/_includes/site-header.html index 31f2bc2a38..70f1cb6840 100644 --- a/_includes/site-header.html +++ b/_includes/site-header.html @@ -10,7 +10,7 @@ diff --git a/_ja/scala3/contribute-to-docs.md b/_ja/scala3/contribute-to-docs.md index 2902ff1d2a..c13b4b0904 100644 --- a/_ja/scala3/contribute-to-docs.md +++ b/_ja/scala3/contribute-to-docs.md @@ -45,8 +45,8 @@ Scala 3 の高品質なドキュメンテーションを作るためのいくつ - [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-migration) - [Issues](https://github.com/scalacenter/docs.scala-lang/issues) -## Scala 3 Contribution Guide -[Scala 3 Contribution Guide](/scala3/guides/contribution/contribution-intro.html) +## Scala 3 Contributing Guide +[Scala 3 Contributing Guide](/scala3/guides/contribution/contribution-intro.html) Scala 3 コンパイラとライブラリへの貢献と内部に関する包括的な概要が含まれています - [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-contribution) diff --git a/_ja/scala3/new-in-scala3.md b/_ja/scala3/new-in-scala3.md index eea8ee14ca..8e69859268 100644 --- a/_ja/scala3/new-in-scala3.md +++ b/_ja/scala3/new-in-scala3.md @@ -13,7 +13,7 @@ Scala 3 は Scala 2 から大幅な改善が行われ、さまざまな新機能 - [Syntax Summary][syntax-summary] では Scala 3 で新しく追加されたシンタックスを解説している。 - [Language Reference][reference] を見ればScala 2 と Scala 3 の変更点を詳しく確認できる。 - Scala 2 から Scala 3 への移行を考えている方は[Migration Guide][migration] を参照。 -- [Contribution Guide][contribution] は、問題を修正するためのガイドを含め、コンパイラーをさらに深く掘り下げます。 +- [Scala 3 Contributing Guide][contribution] は、問題を修正するためのガイドを含め、コンパイラーをさらに深く掘り下げます。 ## What's new in Scala 3 Scala 3 は Scala 2 を徹底的に見直して再設計されている。核心部分で、型システムの多くの面が変更されより原理原則に基づいたものになった。この変更によって新機能(ユニオン型)が使えるようになったことにくわえて、なにより型システムがさらに使いやすくなった。 例えば、[型推論][type-inference] や overload resolution が改善された. diff --git a/index.md b/index.md index 7e778ec83c..aacc00e221 100644 --- a/index.md +++ b/index.md @@ -40,7 +40,7 @@ scala3-sections: description: "The Scala 3 language reference." icon: "fa fa-book" link: /scala3/reference/overview.html - - title: "Contribution Guide" + - title: "Scala 3 Contributing Guide" description: "Guide to the Scala 3 Compiler and fixing an issue" icon: "fa fa-cogs" link: /scala3/guides/contribution/contribution-intro.html @@ -118,4 +118,8 @@ scala2-sections: description: "The Scala Improvement Process. Language & compiler evolution." icon: "fa fa-cogs" link: /sips/index.html + - title: "Contributing to Scala" + description: "The Complete Guide to Contributing to the Scala Project" + icon: "fa fa-cogs" + link: /overviews/contribute/ --- diff --git a/scala3/contribute-to-docs.md b/scala3/contribute-to-docs.md index 5a2a336440..d39ba71ec4 100644 --- a/scala3/contribute-to-docs.md +++ b/scala3/contribute-to-docs.md @@ -45,8 +45,8 @@ a tour presenting the migration tools, and detailed migration guides. - [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-migration) - [Issues](https://github.com/scala/docs.scala-lang/issues) -## Scala 3 Contribution Guide -The [Scala 3 Contribution Guide](/scala3/guides/contribution/contribution-intro.html) +## Scala 3 Contributing Guide +The [Scala 3 Contributing Guide](/scala3/guides/contribution/contribution-intro.html) contains a comprehensive overview over contribution to and internals of the Scala 3 compiler and libraries - [Source](https://github.com/scala/docs.scala-lang/tree/main/_overviews/scala3-contribution) diff --git a/scala3/guides.md b/scala3/guides.md index 812cedb611..26110b10ba 100644 --- a/scala3/guides.md +++ b/scala3/guides.md @@ -18,7 +18,7 @@ guides: icon: birthday-cake url: "/scala3/guides/tasty-overview.html" description: "An overview over the TASTy format aimed at end-users of the Scala language." - - title: "Contribution Guide" + - title: "Scala 3 Contributing Guide" by: Jamie Thompson, Anatolii Kmetiuk icon: cogs url: "/scala3/guides/contribution/contribution-intro.html" diff --git a/scala3/index.md b/scala3/index.md index 7c741fd931..a34c19a1ca 100644 --- a/scala3/index.md +++ b/scala3/index.md @@ -40,7 +40,7 @@ sections: description: "The Scala 3 language reference." icon: "fa fa-book" link: /scala3/reference/overview.html - - title: "Contribution Guide" + - title: "Scala 3 Contributing Guide" description: "Guide to the Scala 3 Compiler and fixing an issue" icon: "fa fa-cogs" link: /scala3/guides/contribution/contribution-intro.html diff --git a/scala3/new-in-scala3.md b/scala3/new-in-scala3.md index 9a1e9da872..af6d6111c1 100644 --- a/scala3/new-in-scala3.md +++ b/scala3/new-in-scala3.md @@ -11,7 +11,7 @@ changes. If you want to dig deeper, there are a few references at your disposal: - The [Syntax Summary][syntax-summary] provides you with a formal description of the new syntax. - The [Language Reference][reference] gives a detailed description of the changes from Scala 2 to Scala 3. - The [Migration Guide][migration] provides you with all of the information necessary to move from Scala 2 to Scala 3. -- The [Contribution Guide][contribution] dives deeper into the compiler, including a guide to fix issues. +- The [Scala 3 Contributing Guide][contribution] dives deeper into the compiler, including a guide to fix issues. ## What's new in Scala 3 Scala 3 is a complete overhaul of the Scala language. At its core, many aspects From aa00e9cd6626ada8738267b9fb8a50f5378dfe0c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 21 Mar 2022 12:17:23 -0500 Subject: [PATCH 0996/2265] update status of JDK 8 also change AdoptOpenJDK->Temurin also move some GraalVM text to a more appropriate location --- _overviews/jdk-compatibility/overview.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 9eb850a77f..c00fd2f05f 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -26,13 +26,11 @@ Lightbend offers [commercial support](https://www.lightbend.com/lightbend-platfo ## Running versus compiling -JDK 8, 11, and 17 are all good choices both for *compiling* and *running* Scala code. +JDK 8, 11, and 17 are all reasonable choices both for *compiling* and *running* Scala code. Since the JVM is normally backwards compatible, it is usually safe to use a newer JVM for *running* your code than the one it was compiled on, especially if you are not using JVM features designated "experimental" or "unsafe". -If you compile on JDK 11+ but have users on an older JDK version, additional care is needed to avoid using APIs and features that don't exist in 8. Therefore, *compiling* on 8 may be the safest choice in this scenario. (Some Scala developers use JDK 11 or 17 for their daily work, but do release builds on JDK 8.) - -Additionally, you can also run your Scala application on GraalVM which is a JVM. GraalVM performs well on the Scala benchmarks, and it benefits from GraalVM runtime and runs faster too. +JDK 8 remains in use at many shops (as of early 2022), but usage is declining and some projects are dropping support. If you compile on JDK 11+ but want to allow your users to stay on 8, additional care is needed to avoid using APIs and features that don't exist in 8. (For this reason, some Scala developers use JDK 11 or 17 for their daily work but do release builds on JDK 8.) ## Long Term Support (LTS) versions @@ -50,9 +48,9 @@ In almost every case, you're free to use the JDK and JVM of your choice. JDK 8 users typically use the Oracle JDK or some flavor of OpenJDK. -Most JDK 11+ users are using either OpenJDK or GraalVM which runs in the context of OpenJDK. +Most JDK 11+ users are using OpenJDK, or GraalVM which runs in the context of OpenJDK. GraalVM performs well on the Scala benchmarks, and it benefits from GraalVM runtime and runs faster too. -OpenJDK comes in various flavors, offered by different providers. We build and test Scala using [AdoptOpenJDK](https://adoptopenjdk.net) in particular, but the differences are unlikely to matter to most users. +OpenJDK comes in various flavors, offered by different providers. We build and test Scala using [Temurin](https://adoptium.net) primarily, but the differences are unlikely to matter to most users. ## JDK 11 compatibility notes From 302bfbff1dc497bd07acaf9c5596ec94f8d50aa0 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 22 Mar 2022 16:00:44 +0100 Subject: [PATCH 0997/2265] revert to /contribute/ urls --- README.md | 2 +- _config.yml | 8 +++++ _contribute_resources/1-documentation.md | 4 +-- _contribute_resources/2-bug-fixes.md | 4 +-- _contribute_resources/3-code-reviews.md | 2 +- _contribute_resources/4-core-libraries.md | 2 +- .../5-ide-and-build-tools.md | 2 +- _contribute_resources/6-compiler-language.md | 2 +- _data/doc-nav-header.yml | 2 +- _data/nav-header.yml | 2 +- _overviews/contribute/add-guides.md | 3 -- _overviews/contribute/bug-reporting-guide.md | 3 -- _overviews/contribute/codereviews.md | 7 ++--- _overviews/contribute/corelibs.md | 9 ++---- _overviews/contribute/documentation.md | 13 +++----- _overviews/contribute/guide.md | 31 +++++++++---------- _overviews/contribute/hacker-guide.md | 5 +-- .../contribute/inclusive-language-guide.md | 3 -- _overviews/contribute/index.md | 7 ++--- _overviews/contribute/partest-guide.md | 3 -- _overviews/contribute/scala-internals.md | 3 -- ...cala-standard-library-api-documentation.md | 7 ++--- _overviews/contribute/tools.md | 7 ++--- contribute.md | 2 +- index.md | 2 +- 25 files changed, 52 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index ee37fe58d4..fe377e9f6b 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ For more details on the Docker option, see [this issue](https://github.com/scala ## Contributing ## -Please have a look at [Add New Guides/Tutorials](https://docs.scala-lang.org/overviews/contribute/add-guides.html) before making a contribution. +Please have a look at [Add New Guides/Tutorials](https://docs.scala-lang.org/contribute/add-guides.html) before making a contribution. This document gives an overview of the type of documentation contained within the Scala Documentation repository and the repository's structure. Small changes, or corrected typos will generally be pulled in right away. Large changes, like the addition of new documents, or the rewriting of diff --git a/_config.yml b/_config.yml index 0d58e58a8f..43f6dfd536 100644 --- a/_config.yml +++ b/_config.yml @@ -105,6 +105,14 @@ defaults: overview-name: "Scala 3 — Book" layout: multipage-overview permalink: "/scala3/book/:title.html" + - + scope: + path: "_overviews/contribute" + values: + partof: scala-contribution + overview-name: Contributing to Scala + layout: multipage-overview + permalink: "/contribute/:title.html" - scope: path: "_overviews/scala3-migration" diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 7515ff7519..474bea075f 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -1,6 +1,6 @@ --- title: Documentation -link: /overviews/contribute/documentation.html +link: /contribute/documentation.html icon: fa fa-book --- -[Scaladoc (API)](/overviews/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/overviews/contribute/add-guides.html) and [scala-lang.org](https://github.com/scala/scala-lang). +[Scaladoc (API)](/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/contribute/add-guides.html) and [scala-lang.org](https://github.com/scala/scala-lang). diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index 2baf672e5a..54e6d2cf9d 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -1,6 +1,6 @@ --- title: Bug fixes -link: /overviews/contribute/guide.html +link: /contribute/guide.html icon: fa fa-bug --- -Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/overviews/contribute/bug-reporting-guide.html). +Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). diff --git a/_contribute_resources/3-code-reviews.md b/_contribute_resources/3-code-reviews.md index e6f15e271c..e03305beb5 100644 --- a/_contribute_resources/3-code-reviews.md +++ b/_contribute_resources/3-code-reviews.md @@ -1,6 +1,6 @@ --- title: Code Reviews -link: /overviews/contribute/codereviews.html +link: /contribute/codereviews.html icon: fa fa-eye --- Review pull requests against [scala/scala](https://github.com/scala/scala/pulls), diff --git a/_contribute_resources/4-core-libraries.md b/_contribute_resources/4-core-libraries.md index fb66a906b8..06f1018479 100644 --- a/_contribute_resources/4-core-libraries.md +++ b/_contribute_resources/4-core-libraries.md @@ -1,6 +1,6 @@ --- title: Core Libraries -link: /overviews/contribute/corelibs.html +link: /contribute/corelibs.html icon: fa fa-clipboard --- Update and expand the capabilities of the core (and associated) Scala libraries. diff --git a/_contribute_resources/5-ide-and-build-tools.md b/_contribute_resources/5-ide-and-build-tools.md index 2bf2c7d729..7202f0d953 100644 --- a/_contribute_resources/5-ide-and-build-tools.md +++ b/_contribute_resources/5-ide-and-build-tools.md @@ -1,6 +1,6 @@ --- title: IDE and Build Tools -link: /overviews/contribute/tools.html +link: /contribute/tools.html icon: fa fa-terminal --- Enhance the Scala tools with features for build tools, IDE plug-ins and other related projects. diff --git a/_contribute_resources/6-compiler-language.md b/_contribute_resources/6-compiler-language.md index a7dc618322..d54e34fac9 100644 --- a/_contribute_resources/6-compiler-language.md +++ b/_contribute_resources/6-compiler-language.md @@ -1,6 +1,6 @@ --- title: Compiler/Language -link: /overviews/contribute/guide.html#larger-changes-new-features +link: /contribute/guide.html#larger-changes-new-features icon: fa fa-cogs --- Larger language features and compiler enhancements including language specification and SIPs. diff --git a/_data/doc-nav-header.yml b/_data/doc-nav-header.yml index 9f45227579..52b66be1da 100644 --- a/_data/doc-nav-header.yml +++ b/_data/doc-nav-header.yml @@ -36,7 +36,7 @@ - title: Language Specification url: http://scala-lang.org/files/archive/spec/2.13/ - title: Contribution Guide - url: "/overviews/contribute/" + url: "/contribute/" - title: Style Guide url: "/style/index.html" - title: Cheatsheet diff --git a/_data/nav-header.yml b/_data/nav-header.yml index a9d2f9ab38..03621e6d64 100644 --- a/_data/nav-header.yml +++ b/_data/nav-header.yml @@ -11,7 +11,7 @@ url: https://index.scala-lang.org can-highlight: true - title: Contribute - url: /overviews/contribute/ + url: /contribute/ - title: Blog url: https://www.scala-lang.org/blog/ can-highlight: true diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md index c8f5e42f0c..8e638021d2 100644 --- a/_overviews/contribute/add-guides.md +++ b/_overviews/contribute/add-guides.md @@ -1,9 +1,6 @@ --- title: Add New Guides/Tutorials -layout: multipage-overview num: 7 -partof: scala-contribution -overview-name: Contributing to Scala --- ## Why Contribute New Learning Material? diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index ac6df525a5..e2637ccd09 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -1,9 +1,6 @@ --- title: Bug Reporting Guide -layout: multipage-overview num: 8 -partof: scala-contribution -overview-name: Contributing to Scala --- The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug), and for Scala 3, it is located at [github.com/lampepfl/dotty](https://github.com/lampepfl/dotty/issues). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index e7dea2acea..6325fcde6c 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -1,13 +1,10 @@ --- title: Code Review Contributions -layout: multipage-overview num: 3 -partof: scala-contribution -overview-name: Contributing to Scala --- ## Code Review Contributions -In addition to [bug fixing](/overviews/contribute/guide.html), you can help us review +In addition to [bug fixing](/contribute/guide.html), you can help us review [waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your @@ -57,4 +54,4 @@ own pull requests. -Also note that the [Tools contributions](/overviews/contribute/tools.html) page has more projects that will generate pull requests. +Also note that the [Tools contributions](/contribute/tools.html) page has more projects that will generate pull requests. diff --git a/_overviews/contribute/corelibs.md b/_overviews/contribute/corelibs.md index 6c64a887d7..3ee05e6c13 100644 --- a/_overviews/contribute/corelibs.md +++ b/_overviews/contribute/corelibs.md @@ -1,17 +1,14 @@ --- title: Core Library Contributions -layout: multipage-overview num: 4 -partof: scala-contribution -overview-name: Contributing to Scala --- ## Core Library Contributions There are several options for contributing to Scala's core libraries. You can: -* Help with [Documentation](/overviews/contribute/documentation.html). -* [Report Bugs or Issues](/overviews/contribute/bug-reporting-guide.html) against the core libraries. -* [Fix Bugs or Issues](/overviews/contribute/guide.html) against the +* Help with [Documentation](/contribute/documentation.html). +* [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. +* [Fix Bugs or Issues](/contribute/guide.html) against the [reported library bugs/issues](https://github.com/scala/bug). ### Significant changes diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index 417f9b234a..3d3311dbce 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -1,9 +1,6 @@ --- title: Documentation Contributions -layout: multipage-overview num: 5 -partof: scala-contribution -overview-name: Contributing to Scala --- ## Contributing Documentation to the Scala project @@ -23,11 +20,11 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](/overviews/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - Please *follow the issue submission process closely* to help prevent duplicate issues being created. -* [Claim Scaladoc Issues and Provide Documentation](/overviews/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just -[submit new Scaladoc](/overviews/contribute/scala-standard-library-api-documentation.html) +[submit new Scaladoc](/contribute/scala-standard-library-api-documentation.html) without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on [Scala Contributors](https://contributors.scala-lang.org/) so that people know what you are doing. ### The Main Scala Documentation Site @@ -44,7 +41,7 @@ without creating an issue, but please look to see if there is an issue already s * SIP (Scala Improvement Process) Proposals and more -Please read [Add New Guides/Tutorials](/overviews/contribute/add-guides.html) through before embarking on changes. The site uses +Please read [Add New Guides/Tutorials](/contribute/add-guides.html) through before embarking on changes. The site uses the [Jekyll](https://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. ### Updating scala-lang.org @@ -55,4 +52,4 @@ to Scala and related projects) is provided on the main [scala-lang GitHub project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[Add New Guides/Tutorials](/overviews/contribute/add-guides.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[Add New Guides/Tutorials](/contribute/add-guides.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 802e3c387c..70d470d454 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -1,9 +1,6 @@ --- title: Contributing guide -layout: multipage-overview num: 10 -partof: scala-contribution -overview-name: Contributing to Scala --- | **Shortcut** | **Description** | @@ -41,19 +38,19 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [GitHub branch](https://github.com/scala/scala) -1. [Select a bug to fix from GitHub](/overviews/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/overviews/contribute/bug-reporting-guide.html) (but please -[make sure it's not a duplicate](/overviews/contribute/bug-reporting-guide.html#please-check-before-reporting-a-bug)). -2. Optional ([but recommended](/overviews/contribute/scala-internals.html/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with -[these friendly people](/overviews/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. -3. [Fork the Scala repository](/overviews/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](/overviews/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. -5. [Fix the bug, or implement the new small feature](/overviews/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](/overviews/contribute/hacker-guide.html#test) and [test some more](/overviews/contribute/partest-guide.html) until [all the tests pass](/overviews/contribute/hacker-guide.html#verify). -7. [Commit your changes](/overviews/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. +1. [Select a bug to fix from GitHub](/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/contribute/bug-reporting-guide.html) (but please +[make sure it's not a duplicate](/contribute/bug-reporting-guide.html#please-check-before-reporting-a-bug)). +2. Optional ([but recommended](/contribute/scala-internals.html/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with +[these friendly people](/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. +3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). +4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. +5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). +6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide.html) until [all the tests pass](/contribute/hacker-guide.html#verify). +7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](https://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) -9. [Submit a pull request](/overviews/contribute/hacker-guide.html#submit). -10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/overviews/contribute/hacker-guide.html#review). +9. [Submit a pull request](/contribute/hacker-guide.html#submit). +10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide.html#review). 11. Celebrate! Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide][hackers] (or the [equivalent Scala 3 Contributing Guide][scala3-hackers]) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). @@ -67,8 +64,8 @@ on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list a Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against the Scala project source tree. The hacker's guides ([Scala 2][hackers], or [Scala 3][scala3-hackers]) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. -[hackers]: /overviews/contribute/hacker-guide.html -[community-tickets]: /overviews/contribute/index.html#community-tickets -[bug-reporting-guide]: /overviews/contribute/bug-reporting-guide.html +[hackers]: /contribute/hacker-guide.html +[community-tickets]: /contribute/index.html#community-tickets +[bug-reporting-guide]: /contribute/bug-reporting-guide.html [scala3-hackers]: {% link _overviews/scala3-contribution/procedures-intro.md %} [contrib-forum]: https://contributors.scala-lang.org/ diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index f342c98040..f9db614056 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -1,10 +1,7 @@ --- title: Scala hacker guide by: Eugene Burmako -layout: multipage-overview num: 12 -partof: scala-contribution -overview-name: Contributing to Scala ---
    This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. @@ -310,7 +307,7 @@ This means your change is backward or forward binary incompatible with the speci ### Verify -Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest](/overviews/contribute/partest-guide.html), a tool we wrote for testing Scala. +Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest](/contribute/partest-guide.html), a tool we wrote for testing Scala. Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, respectively. `partest` (not `sbt partest`) also allows you to run a subset of the tests using wildcards: diff --git a/_overviews/contribute/inclusive-language-guide.md b/_overviews/contribute/inclusive-language-guide.md index 7f7c428f42..375d988158 100644 --- a/_overviews/contribute/inclusive-language-guide.md +++ b/_overviews/contribute/inclusive-language-guide.md @@ -1,9 +1,6 @@ --- title: Inclusive Language Guide -layout: multipage-overview num: 2 -partof: scala-contribution -overview-name: Contributing to Scala --- We are committed to providing a friendly, safe and welcoming environment for diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index b89f04803a..eb0596d802 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -1,9 +1,6 @@ --- title: Contribute -layout: multipage-overview num: 1 -partof: scala-contribution -overview-name: Contributing to Scala --- The Scala programming language is an open source project with a very @@ -18,7 +15,7 @@ That depends on what you want to contribute. Below are some getting started reso ### Reporting bugs -See our [bug reporting guide](/overviews/contribute/bug-reporting-guide.html) to learn +See our [bug reporting guide](/contribute/bug-reporting-guide.html) to learn how to efficiently report a bug. ### Contribute @@ -33,7 +30,7 @@ Coordination of contribution efforts takes place on When contributing, please follow: * The [Scala Code of Conduct](https://scala-lang.org/conduct/) -* The [Inclusive Language Guide](/overviews/contribute/inclusive-language-guide.html) +* The [Inclusive Language Guide](/contribute/inclusive-language-guide.html) ### Community Tickets diff --git a/_overviews/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md index 548eb8d5e6..c3e6980b06 100644 --- a/_overviews/contribute/partest-guide.md +++ b/_overviews/contribute/partest-guide.md @@ -1,9 +1,6 @@ --- title: Running the Test Suite -layout: multipage-overview num: 13 -partof: scala-contribution -overview-name: Contributing to Scala --- Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go to the scala project folder from your local checkout and run it via `sbt`, `ant` or standalone as follows. diff --git a/_overviews/contribute/scala-internals.md b/_overviews/contribute/scala-internals.md index 5f391947fa..f3b1de54de 100644 --- a/_overviews/contribute/scala-internals.md +++ b/_overviews/contribute/scala-internals.md @@ -1,9 +1,6 @@ --- title: Scala Contributors Forum -layout: multipage-overview num: 9 -partof: scala-contribution -overview-name: Contributing to Scala --- The [Scala Contributors Forum][scala-contributors] is where discussions about the Scala ecosystem diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index 99f1bb16e0..606407f886 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -1,9 +1,6 @@ --- title: Contribute to API Documentation -layout: multipage-overview num: 6 -partof: scala-contribution -overview-name: Contributing to Scala --- This page is specific to API documentation contributions – that is, API @@ -13,7 +10,7 @@ sometimes referred to as Scaladoc contributions. For contributions to tutorial and guide-style documentation on [docs.scala-lang.org](/), -see [Add New Guides/Tutorials](/overviews/contribute/add-guides.html). +see [Add New Guides/Tutorials](/contribute/add-guides.html). *Please note, these instructions cover documentation contributions Scala core libraries only. For other Scala projects please check those projects for the @@ -79,7 +76,7 @@ component so that they show up in the correct issue filters. Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](/overviews/contribute/hacker-guide.html#2-set-up) - follow the setup steps through +* [Forking the Repo](/contribute/hacker-guide.html#2-set-up) - follow the setup steps through the Branch section. If providing new documentation related to an existing GitHub issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated GitHub issue, use `scaladoc/xxxx` instead. diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index 875160ca96..68cee7796f 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -1,9 +1,6 @@ --- title: IDE and Build Tool Contributions -layout: multipage-overview num: 11 -partof: scala-contribution -overview-name: Contributing to Scala # Projects list: projects: @@ -22,7 +19,7 @@ projects: homeLink: https://www.scala-lang.org/api issuesLink: https://github.com/scala/bug/labels/scaladoc readmeLink: https://github.com/scala/scala#welcome - contributingLink: /overviews/contribute/guide.html + contributingLink: /contribute/guide.html - title: Partest description: Scala Compiler/Library Testing (Contribute through scala/scala) icon: https://avatars1.githubusercontent.com/u/57059?v=3&s=200 @@ -50,7 +47,7 @@ if you would like to help revive them. ### Broken Links? -Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/overviews/contribute/documentation.html#updating-scala-langorg) to fix it. +Stuff changes. Found a broken link or something that needs updating on this page? Please, consider [submitting a documentation pull request](/contribute/documentation.html#updating-scala-langorg) to fix it. ### Projects diff --git a/contribute.md b/contribute.md index 4a7d38faec..02a8e4b8d7 100644 --- a/contribute.md +++ b/contribute.md @@ -23,4 +23,4 @@ If you're interested in contributing to the Scala project in general, I argue th ## How Can I Contribute? -Please read: [Add New Guides/Tutorials](/overviews/contribute/add-guides.html) +Please read: [Add New Guides/Tutorials](/contribute/add-guides.html) diff --git a/index.md b/index.md index aacc00e221..5790ce8b7c 100644 --- a/index.md +++ b/index.md @@ -121,5 +121,5 @@ scala2-sections: - title: "Contributing to Scala" description: "The Complete Guide to Contributing to the Scala Project" icon: "fa fa-cogs" - link: /overviews/contribute/ + link: /contribute/ --- From 573e494856dd4138c155d7e6dbb7492b2e21ad28 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 22 Mar 2022 16:59:40 +0100 Subject: [PATCH 0998/2265] use jekyll link tag to render internal links --- _contribute_resources/1-documentation.md | 5 ++- _contribute_resources/2-bug-fixes.md | 4 +- _includes/column-list-of-items.html | 2 +- _overviews/contribute/add-guides.md | 11 +++-- _overviews/contribute/bug-reporting-guide.md | 4 +- _overviews/contribute/codereviews.md | 7 ++- _overviews/contribute/corelibs.md | 10 +++-- _overviews/contribute/documentation.md | 17 +++++--- _overviews/contribute/guide.md | 43 ++++++++++++------- _overviews/contribute/hacker-guide.md | 12 ++++-- _overviews/contribute/index.md | 7 ++- ...cala-standard-library-api-documentation.md | 16 ++++--- 12 files changed, 94 insertions(+), 44 deletions(-) diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 474bea075f..1f42a6e20b 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -3,4 +3,7 @@ title: Documentation link: /contribute/documentation.html icon: fa fa-book --- -[Scaladoc (API)](/contribute/scala-standard-library-api-documentation.html), [docs.scala-lang.org](/contribute/add-guides.html) and [scala-lang.org](https://github.com/scala/scala-lang). +[Scaladoc (API)][scala-standard-library-api-documentation], [docs.scala-lang.org][add-guides] and [scala-lang.org](https://github.com/scala/scala-lang). + +[add-guides]: {% link _overviews/contribute/add-guides.md %} +[scala-standard-library-api-documentation]: {% link _overviews/contribute/scala-standard-library-api-documentation.md %} diff --git a/_contribute_resources/2-bug-fixes.md b/_contribute_resources/2-bug-fixes.md index 54e6d2cf9d..7026e7e15b 100644 --- a/_contribute_resources/2-bug-fixes.md +++ b/_contribute_resources/2-bug-fixes.md @@ -3,4 +3,6 @@ title: Bug fixes link: /contribute/guide.html icon: fa fa-bug --- -Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs](/contribute/bug-reporting-guide.html). +Issues with the tools, core libraries and compiler. Also you can help us by [reporting bugs][bug-reporting-guide]. + +[bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} diff --git a/_includes/column-list-of-items.html b/_includes/column-list-of-items.html index eb9e1600be..2ce303e678 100644 --- a/_includes/column-list-of-items.html +++ b/_includes/column-list-of-items.html @@ -15,4 +15,4 @@

    {{item.title}}

    {% endfor %} - \ No newline at end of file + diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md index 8e638021d2..96091fb311 100644 --- a/_overviews/contribute/add-guides.md +++ b/_overviews/contribute/add-guides.md @@ -5,7 +5,7 @@ num: 7 ## Why Contribute New Learning Material? -As [Heather Miller writes](/contribute.html), contributing to [docs.scala-lang.org](https://docs.scala-lang.org) is +As [Heather Miller writes][why-contribute], contributing to [docs.scala-lang.org][home] is critical to making Scala accessible to newcomers, experience programmers, and anyone who is curious. It is also a fantastic way to contribute for anyone who is comfortable using Scala, but maybe does not want to get involved with complex tools like the compiler. @@ -45,7 +45,7 @@ For one to contribute a document, one must simply [repo](https://github.com/scala/docs.scala-lang), write their article in [Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and submit a pull request. That's it. Likely after some edits and discussion, your document will be made live -on [docs.scala-lang.org](https://docs.scala-lang.org). +on [docs.scala-lang.org][home]. --- layout: overview @@ -71,7 +71,7 @@ styling is already taken care of for you. ### Criteria for Docs to be Accepted The goal of this documentation repository is to be tighter and more organized than other community-driven documentation platforms, like wikis. As such, any document pulled in for inclusion on -[docs.scala-lang.org](https://docs.scala-lang.org) must: +[docs.scala-lang.org][home] must: - **"fit in"** to the repository ( _i.e.,_ it should not be a complete duplicate of another article), - **be polished** it must be thorough, complete, correct, organized, and "article-like" (personal programming notes @@ -129,7 +129,7 @@ documents in the large overview. Putting it on the last page in the overview is outof: 15 --- -Index pages, such as [docs.scala-lang.org/overviews/index.html](https://docs.scala-lang.org/overviews/index.html) are +Index pages, such as [docs.scala-lang.org/overviews/index.html][overviews-index] are generated, by reading data from a configuration file, such as `_data/overviews.yml`, so your overview should be placed into a category there. @@ -216,3 +216,6 @@ above. Here is an example using the various modifiers. [collections-overview]: {% link _overviews/collections-2.13/introduction.md %} [scala-with-maven]: {% link _overviews/tutorials/scala-with-maven.md %} +[why-contribute]: {% link contribute.md %} +[home]: {% link index.md %} +[overviews-index]: {% link _overviews/index.md %} diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index e2637ccd09..91858d589c 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -41,7 +41,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](https://docs.scala-lang.org/sips/) or in the [Scala Language Specification](https://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents][sips] or in the [Scala Language Specification](https://www.scala-lang.org/files/archive/spec/2.13/). If in doubt, you may always ask on the [Community Category](https://contributors.scala-lang.org/c/community) or [Stack Overflow](https://stackoverflow.com/questions/tagged/scala). In general, if you find yourself stuck on any of these steps, asking on [Scala Contributors](https://contributors.scala-lang.org/) can be helpful: @@ -85,3 +85,5 @@ List(1, 2, 3).map(x => x + 1) 3. The actual output, including the stacktrace. 4. Related discussion on the mailing lists, if applicable. 5. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. + +[sips]: {% link _sips/index.md %} diff --git a/_overviews/contribute/codereviews.md b/_overviews/contribute/codereviews.md index 6325fcde6c..be8e66ba46 100644 --- a/_overviews/contribute/codereviews.md +++ b/_overviews/contribute/codereviews.md @@ -4,7 +4,7 @@ num: 3 --- ## Code Review Contributions -In addition to [bug fixing](/contribute/guide.html), you can help us review +In addition to [bug fixing][bug-fixing], you can help us review [waiting pull requests](#pull-requests-awaiting-comment). This is also a good (and recommended) way to get to know the feel of the bug-fixing and submissions process before jumping in with your @@ -54,4 +54,7 @@ own pull requests. -Also note that the [Tools contributions](/contribute/tools.html) page has more projects that will generate pull requests. +Also note that the [Tools contributions][tools] page has more projects that will generate pull requests. + +[bug-fixing]: {% link _overviews/contribute/guide.md %} +[tools]: {% link _overviews/contribute/tools.md %} diff --git a/_overviews/contribute/corelibs.md b/_overviews/contribute/corelibs.md index 3ee05e6c13..1eb2f840b0 100644 --- a/_overviews/contribute/corelibs.md +++ b/_overviews/contribute/corelibs.md @@ -6,12 +6,16 @@ num: 4 There are several options for contributing to Scala's core libraries. You can: -* Help with [Documentation](/contribute/documentation.html). -* [Report Bugs or Issues](/contribute/bug-reporting-guide.html) against the core libraries. -* [Fix Bugs or Issues](/contribute/guide.html) against the +* Help with [Documentation][documentation]. +* [Report Bugs or Issues][bug-reporting-guide] against the core libraries. +* [Fix Bugs or Issues][guide] against the [reported library bugs/issues](https://github.com/scala/bug). ### Significant changes For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, please take into account [https://github.com/scala/scala-dev/issues/661] before doing so. + +[documentation]: {% link _overviews/contribute/documentation.md %} +[bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} +[guide]: {% link _overviews/contribute/guide.md %} diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index 3d3311dbce..9bd4597b36 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -20,16 +20,16 @@ Thanks The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: -* [Log issues for missing scaladoc documentation](/contribute/scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +* [Log issues for missing scaladoc documentation][report-api-doc-bugs] - Please *follow the issue submission process closely* to help prevent duplicate issues being created. -* [Claim Scaladoc Issues and Provide Documentation](/contribute/scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* [Claim Scaladoc Issues and Provide Documentation][scala-standard-library-api-documentation] - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. * You can also just -[submit new Scaladoc](/contribute/scala-standard-library-api-documentation.html) +[submit new Scaladoc][scala-standard-library-api-documentation] without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on [Scala Contributors](https://contributors.scala-lang.org/) so that people know what you are doing. ### The Main Scala Documentation Site -[docs.scala-lang.org](https://docs.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a GitHub project that you can fork and submit pull requests from. It includes: +[docs.scala-lang.org][home] houses the primary source of written, non-API documentation for Scala. It's a GitHub project that you can fork and submit pull requests from. It includes: * Overviews * Tutorials @@ -41,7 +41,7 @@ without creating an issue, but please look to see if there is an issue already s * SIP (Scala Improvement Process) Proposals and more -Please read [Add New Guides/Tutorials](/contribute/add-guides.html) through before embarking on changes. The site uses +Please read [Add New Guides/Tutorials][add-guides] through before embarking on changes. The site uses the [Jekyll](https://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. ### Updating scala-lang.org @@ -52,4 +52,9 @@ to Scala and related projects) is provided on the main [scala-lang GitHub project](https://github.com/scala/scala-lang) which may be forked to create pull requests. Please read both the -[Add New Guides/Tutorials](/contribute/add-guides.html) document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. +[Add New Guides/Tutorials][add-guides] document and the [scala-lang.org GitHub README](https://github.com/scala/scala-lang#scala-langorg) before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. + +[report-api-doc-bugs]: {% link _overviews/contribute/scala-standard-library-api-documentation.md %}#contribute-api-documentation-bug-reports +[scala-standard-library-api-documentation]: {% link _overviews/contribute/scala-standard-library-api-documentation.md %} +[home]: {% link index.md %} +[add-guides]: {% link _overviews/contribute/add-guides.md %} diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 70d470d454..472d2d41ab 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -38,19 +38,19 @@ unencumbered by copyrights or patents. This is the impatient developer's checklist for the steps to submit a bug-fix pull request to the Scala project. For more information, description and justification for the steps, follow the links in that step. Further specific instructions for the release of Scala you are targeting can be found in the `CONTRIBUTING.md` file for that [GitHub branch](https://github.com/scala/scala) -1. [Select a bug to fix from GitHub](/contribute/index.html#community-tickets), or if you found the bug yourself and want to fix it, [create a GitHub issue](/contribute/bug-reporting-guide.html) (but please -[make sure it's not a duplicate](/contribute/bug-reporting-guide.html#please-check-before-reporting-a-bug)). -2. Optional ([but recommended](/contribute/scala-internals.html/#why-its-a-good-idea)), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with -[these friendly people](/contribute/hacker-guide.html#1-connect) - it's one of the perks of contributing. -3. [Fork the Scala repository](/contribute/hacker-guide.html#fork) and clone your fork (if you haven't already). -4. [Create a feature branch](/contribute/hacker-guide.html#branch) to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. -5. [Fix the bug, or implement the new small feature](/contribute/hacker-guide.html#implement), include new tests (yes, for bug fixes too). -6. [Test, rinse](/contribute/hacker-guide.html#test) and [test some more](/contribute/partest-guide.html) until [all the tests pass](/contribute/hacker-guide.html#verify). -7. [Commit your changes](/contribute/hacker-guide.html#commit) to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. +1. [Select a bug to fix from GitHub][community-tickets], or if you found the bug yourself and want to fix it, [create a GitHub issue][bug-reporting-guide] (but please +[make sure it's not a duplicate][bug-report-check-dupes]). +2. Optional ([but recommended][why-its-a-good-idea]), announce your intention to work on the bug on [Scala Contributors](https://contributors.scala-lang.org/). After all, don't you want to work on a team with +[these friendly people][hackers-connect] - it's one of the perks of contributing. +3. [Fork the Scala repository][hackers-fork] and clone your fork (if you haven't already). +4. [Create a feature branch][hackers-branch] to work on: use the branch name `issue/NNNN` where NNNN is the GitHub issue number. +5. [Fix the bug, or implement the new small feature][hackers-implement], include new tests (yes, for bug fixes too). +6. [Test, rinse][hackers-test] and [test some more][partest-guide] until [all the tests pass][hackers-verify]. +7. [Commit your changes][hackers-commit] to your feature branch in your fork. Please choose your commit message based on the [Git Hygiene](https://github.com/scala/scala#user-content-git-hygiene) section of the Scala project README. 8. If necessary [re-write git history](https://git-scm.com/book/en/Git-Branching-Rebasing) so that [commits are organized by major steps to the fix/feature]( https://github.com/scala/scala#git-hygiene). For bug fixes, a single commit is requested, for features several commits may be desirable (but each separate commit must compile and pass all tests) -9. [Submit a pull request](/contribute/hacker-guide.html#submit). -10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in](/contribute/hacker-guide.html#review). +9. [Submit a pull request][hackers-submit]. +10. [Work with a reviewer](https://github.com/scala/scala#reviewing) to [get your pull request merged in][hackers-review]. 11. Celebrate! Need more information or a little more hand-holding for the first one? We got you covered: take a read through the entire [Hacker Guide][hackers] (or the [equivalent Scala 3 Contributing Guide][scala3-hackers]) for an example of implementing a new feature (some of the steps can be skipped for bug fixes, this will be obvious from reading it, but many of the steps here will help with bug fixes too). @@ -59,13 +59,26 @@ Need more information or a little more hand-holding for the first one? We got yo For larger, more ambitious changes (e.g. new language features), the first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea and on the implementation plan. Announce the change -on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](https://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. +on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)][sips] document might be required, but the first step is always to discuss it on the mailing list and if a SIP is required, that will be discussed on the mailing list. Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against the Scala project source tree. The hacker's guides ([Scala 2][hackers], or [Scala 3][scala3-hackers]) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. -[hackers]: /contribute/hacker-guide.html -[community-tickets]: /contribute/index.html#community-tickets -[bug-reporting-guide]: /contribute/bug-reporting-guide.html +[hackers]: {% link _overviews/contribute/hacker-guide.md %} +[community-tickets]: {% link _overviews/contribute/index.md %}#community-tickets +[bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} +[bug-report-check-dupes]: {% link _overviews/contribute/bug-reporting-guide.md %}#please-check-before-reporting-a-bug [scala3-hackers]: {% link _overviews/scala3-contribution/procedures-intro.md %} [contrib-forum]: https://contributors.scala-lang.org/ +[why-its-a-good-idea]: {% link _overviews/contribute/scala-internals.md %}#why-its-a-good-idea +[hackers-connect]: {% link _overviews/contribute/hacker-guide.md %}#1-connect +[hackers-fork]: {% link _overviews/contribute/hacker-guide.md %}#fork +[hackers-branch]: {% link _overviews/contribute/hacker-guide.md %}#branch +[hackers-implement]: {% link _overviews/contribute/hacker-guide.md %}#implement +[hackers-test]: {% link _overviews/contribute/hacker-guide.md %}#test +[hackers-verify]: {% link _overviews/contribute/hacker-guide.md %}#verify +[hackers-commit]: {% link _overviews/contribute/hacker-guide.md %}#commit +[hackers-submit]: {% link _overviews/contribute/hacker-guide.md %}#submit +[hackers-review]: {% link _overviews/contribute/hacker-guide.md %}#review +[partest-guide]: {% link _overviews/contribute/partest-guide.md %} +[sips]: {% link _sips/index.md %} diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index f9db614056..92181003fa 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -196,7 +196,7 @@ Contributing to the Scala standard library is about the same as working on one o If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. -If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](/overviews/collections/introduction.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](/overviews/parallel-collections/overview.html). +If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections][collections-arch], as well as a larger more general [Scala collections Guide][collections-intro] covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide][collections-par]. ##### The Scala Compiler @@ -204,7 +204,7 @@ Documentation about the internal workings of the Scala compiler is scarce, and m * [Compiler internals videos by Martin Odersky](https://www.scala-lang.org/old/node/598.html) are quite dated, but still very useful. In this three-video series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. -* [Reflection documentation](/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that +* [Reflection documentation][reflect-overview] describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. * [Reflection and Compilers by Martin Odersky](https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. @@ -307,7 +307,7 @@ This means your change is backward or forward binary incompatible with the speci ### Verify -Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest](/contribute/partest-guide.html), a tool we wrote for testing Scala. +Now to make sure that my fix doesn't break anything I need to run the test suite. The Scala test suite uses [JUnit](https://junit.org/junit4/) and [partest][partest-guide], a tool we wrote for testing Scala. Run `sbt test` and `sbt partest` to run all of the JUnit and partest tests, respectively. `partest` (not `sbt partest`) also allows you to run a subset of the tests using wildcards: @@ -378,3 +378,9 @@ workflow) and be ready to elaborate and adjust your patch if necessary. In this After your reviewer is happy with your code (usually signaled by a LGTM — “Looks good to me”), your job is done. Note that there can be a gap between a successful review and the merge, because not every reviewer has merge rights. In that case, someone else from the team will pick up your pull request and merge it. So don't be confused if your reviewer says “LGTM”, but your code doesn't get merged immediately. + +[collections-arch]: {% link _overviews/core/architecture-of-scala-collections.md %} +[collections-intro]: {% link _overviews/collections/introduction.md %} +[collections-par]: {% link _overviews/parallel-collections/overview.md %} +[reflect-overview]: {% link _overviews/reflection/overview.md %} +[partest-guide]: {% link _overviews/contribute/partest-guide.md %} diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index eb0596d802..4e94334061 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -15,7 +15,7 @@ That depends on what you want to contribute. Below are some getting started reso ### Reporting bugs -See our [bug reporting guide](/contribute/bug-reporting-guide.html) to learn +See our [bug reporting guide][bug-reporting-guide] to learn how to efficiently report a bug. ### Contribute @@ -30,7 +30,7 @@ Coordination of contribution efforts takes place on When contributing, please follow: * The [Scala Code of Conduct](https://scala-lang.org/conduct/) -* The [Inclusive Language Guide](/contribute/inclusive-language-guide.html) +* The [Inclusive Language Guide][inclusive-language-guide] ### Community Tickets @@ -63,3 +63,6 @@ open-source Scala library or tool, please visit the [community build documentation](https://github.com/scala/community-build/wiki) for guidelines on what projects are suitable for the community build and how projects can be added. + +[bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} +[inclusive-language-guide]: {% link _overviews/contribute/inclusive-language-guide.md %} diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index 606407f886..c1303e8b18 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -9,8 +9,8 @@ documentation for sometimes referred to as Scaladoc contributions. For contributions to tutorial and guide-style documentation on -[docs.scala-lang.org](/), -see [Add New Guides/Tutorials](/contribute/add-guides.html). +[docs.scala-lang.org][home], +see [Add New Guides/Tutorials][add-guides]. *Please note, these instructions cover documentation contributions Scala core libraries only. For other Scala projects please check those projects for the @@ -76,13 +76,13 @@ component so that they show up in the correct issue filters. Please familiarize yourself with the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](/contribute/hacker-guide.html#2-set-up) - follow the setup steps through +* [Forking the Repo][hackers-setup] - follow the setup steps through the Branch section. If providing new documentation related to an existing GitHub issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated GitHub issue, use `scaladoc/xxxx` instead. -* [Scaladoc for library authors](https://docs.scala-lang.org/overviews/scaladoc/for-library-authors.html) +* [Scaladoc for library authors][scaladoc-lib-authors] covers the use of scaladoc tags, markdown and other features. -* [Scaladoc's interface](https://docs.scala-lang.org/overviews/scaladoc/interface.html) +* [Scaladoc's interface][scaladoc-interface] covers all of the features of Scaladoc's interface, e.g. switching between companions, browsing package object documentation, searching, token searches and so on. @@ -121,3 +121,9 @@ PR is merged in smoothly: as smooth and streamlined as possible. Thanks for helping us improve the Scaladoc API documentation! + +[home]: {% link index.md %} +[add-guides]: {% link _overviews/contribute/add-guides.md %} +[hackers-setup]: {% link _overviews/contribute/hacker-guide.md %}#2-set-up +[scaladoc-lib-authors]: {% link _overviews/scaladoc/for-library-authors.md %} +[scaladoc-interface]: {% link _overviews/scaladoc/interface.md %} From 7de6290af5657b4a02373222452f25daca0fe0c8 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 23 Mar 2022 18:01:50 +0100 Subject: [PATCH 0999/2265] add back Scoverage as a project in need --- _overviews/contribute/tools.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/_overviews/contribute/tools.md b/_overviews/contribute/tools.md index 68cee7796f..77115d03ab 100644 --- a/_overviews/contribute/tools.md +++ b/_overviews/contribute/tools.md @@ -30,6 +30,14 @@ projects: contributingLink: projectsInNeed: + - title: Scoverage + description: Scala code coverage tool + icon: https://avatars1.githubusercontent.com/u/5998302?v=3&s=200 + link: https://github.com/scoverage/scalac-scoverage-plugin + homeLink: http://scoverage.org/ + issuesLink: https://github.com/scoverage/scalac-scoverage-plugin/issues + readmeLink: https://github.com/scoverage/scalac-scoverage-plugin/blob/master/README.md + contributingLink: https://groups.google.com/forum/#!forum/scala-code-coverage-tool --- ## Contributing to IDE and Build Tools From e2a41dc6ad52aad13d3e07acc1971c3cbc859344 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 23 Mar 2022 19:41:21 +0100 Subject: [PATCH 1000/2265] use more accessible language in Add New Guides/Tutorials - also switch some code blocks to explicit html so that mdoc code blocks are not escaped. --- _overviews/contribute/add-guides.md | 204 +++++++++++++++++----------- 1 file changed, 126 insertions(+), 78 deletions(-) diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md index 96091fb311..ed8b0d36c7 100644 --- a/_overviews/contribute/add-guides.md +++ b/_overviews/contribute/add-guides.md @@ -19,8 +19,11 @@ and is always contribution-ready. Currently, the _types_ of documentation supported in this repository are: -- **Guides/Overviews**: Definitive guides/overviews of specific language features. Often long, detailed documents, - often produced by members of the Scala team. An example is the excellent [Collections][collections-overview] overview. +- **Guides/Overviews/Books**: Definitive guides/overviews of specific language features. Often long, detailed documents, + often produced by members of the Scala team. An example is the [Collections][collections-overview] overview. +- **References**: The canonical reference for language features, written by members of the Scala team. + These provide the exact specification to understand more subtle aspects of the language. An example is the + [Scala 3 reference][scala-3-reference]. - **Tutorials**: Bite-size, example-rich, and concise articles meant to get a developer up to speed quickly. - **Cheatsheets**: Quick reference of Scala syntax and behaviors. @@ -28,27 +31,29 @@ Currently, the _types_ of documentation supported in this repository are: The website is statically generated from [Markdown](https://en.wikipedia.org/wiki/Markdown) source using [Jekyll](https://github.com/mojombo/jekyll), and hosted on [GitHub Pages](https://pages.github.com/). -This workflow was chosen so as to make it as easy as possible for core committers and the community alike -to produce HTML documentation, and as easy as possible to publish it in a central location. +This workflow was chosen to help contributors to focus on writing helpful content, rather than on configuration and +boilerplate. It also aids publishing a static site in a central location. The markdown syntax being used supports [Maruku](https://github.com/bhollis/maruku) extensions, and has automatic syntax highlighting, without the need for any tags. Additionally [mdoc](https://github.com/scalameta/mdoc) is used during pull requests to validate Scala code blocks. -To use this feature you must use the backtick notation as documented by mdoc. Note that only validation is done. -The output files from mdoc are not used in the building of the tutorial. Use `mdoc` or `mdoc:fail` for your code blocks. +To use this feature you must use the backtick notation as documented by mdoc, +[see here](#code-blocks) for an example. + +**Note:** only validation of code is done by mdoc, and no extra output is generated. ## Submitting Docs -For one to contribute a document, one must simply +For you to contribute a document, first [fork](https://help.github.com/articles/fork-a-repo/) the -[repo](https://github.com/scala/docs.scala-lang), write their article in -[Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and submit a pull request. That's it. +[repo](https://github.com/scala/docs.scala-lang), then write your article in +[Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and finally submit a pull request. Likely after some edits and discussion, your document will be made live on [docs.scala-lang.org][home]. --- - layout: overview + layout: singlepage-overview title: My Awesome Title --- @@ -56,32 +61,41 @@ on [docs.scala-lang.org][home]. And a paragraph, with a [link](https://www.scala-lang.org). -One can contribute code in a markdown document by either - - indenting it by 4 spaces - - surrounding by triple backticks, as shown below - - in-line by putting backticks around it, e.g. `def foo`. +You can contribute code in a markdown document by either +- in-line by putting backticks around it, +- surrounding by triple backticks, +- or indenting it by 4 spaces, e.g.: + +~~~ +inline example: `val x = 23` + +block example: +```scala +println("hello") +``` + +indented example: - ```scala - println("hello") - ``` + case class Foo(x: Int) +~~~ -Everything else is automatically generated for you; tables of contents, and most index pages. And of course, the -styling is already taken care of for you. +Tables of contents will be automatically generated in a sidebar for your document, and syntax highlighting +is provided. ### Criteria for Docs to be Accepted -The goal of this documentation repository is to be tighter and more organized than other community-driven documentation platforms, like wikis. As such, any document pulled in for inclusion on -[docs.scala-lang.org][home] must: +The goal of this documentation repository is to be highly curated, rather than the approach by other community-driven +documentation platforms, like wikis. Therefore, to be included on [docs.scala-lang.org][home], a document must: - **"fit in"** to the repository ( _i.e.,_ it should not be a complete duplicate of another article), -- **be polished** it must be thorough, complete, correct, organized, and "article-like" (personal programming notes -don't quite fit.) -- **be maintained** if the document might require revisions from time to time, be prepared to keep it up to date, or +- **be polished**, i.e. it must be thorough, complete, correct, and organized; written as an article to be understood + by many users. +- **be maintained**, if the document might require revisions from time to time, be prepared to keep it up to date, or nominate someone to take ownership. If you have something you're thinking about contributing, or that you're thinking about writing in order to contribute -- we'd love to consider it! Please don't hesitate to use GitHub issues and pull requests and the -\#scala-contributors room [on Discord](https://discord.com/invite/scala) for any questions, concerns, +`#scala-contributors` room [on Discord](https://discord.com/invite/scala) for any questions, concerns, clarifications, etc. ## Document Templates @@ -90,38 +104,36 @@ clarifications, etc. ### Guides/Overviews -A guide or an overview that can be logically placed on **one** page must be placed in the directory -`_overviews/RELEVANT-CATEGORY/_posts` with the file name in the format `YYYY-MM-dd-title-separated-by-dashes.md`, -and header: +A guide or an overview that can be logically placed on **one** markdown page should be placed in the directory +`_overviews/RELEVANT-CATEGORY/`. It should have the header: --- - layout: overview + layout: singlepage-overview title: YOUR TITLE --- -The rest of the document should, of course, be written in [Markdown](https://en.wikipedia.org/wiki/Markdown). +The rest of the document will be written in [Markdown](https://en.wikipedia.org/wiki/Markdown) syntax. -At the moment, `RELEVANT-CATEGORY` corresponds to only a single category, "core," because we are currently focusing on -building up documentation of core libraries. However, expect more categories here in the future. +You may substitute `RELEVANT-CATEGORY` for any directory that is related, or create a new one if one is not suitable. -If your document consists of **multiple** pages, like the [Collections][collections-overview] overview, an ordering -must be specified, by numbering documents in their logical order with `num`, and a name must be assigned to the -collection of pages using `partof`. For example, the following header might be used for a document in the collections -overview: +If your guide/overview consists of **multiple** pages, like the [Collections][collections-overview] overview, +an ordering must be specified, by numbering documents in their logical order with the `num` tag in the header, +and a name must be assigned to the collection of pages using the `partof` tag. +For example, the following header might be used for a document in the collections overview: --- - layout: overview + layout: multipage-overview title: YOUR TITLE partof: collections num: 10 --- -A **single** document in the collection must contain a tag in the header, `outof`, that indicates the total number of -documents in the large overview. Putting it on the last page in the overview is often best: +**At least one** document in the collection must contain a tag in the header, `outof`, that indicates the total number +of documents in the large overview. Putting it on the last page in the overview is often best: --- - layout: overview + layout: multipage-overview title: YOUR TITLE partof: collections @@ -130,14 +142,18 @@ documents in the large overview. Putting it on the last page in the overview is --- Index pages, such as [docs.scala-lang.org/overviews/index.html][overviews-index] are -generated, by reading data from a configuration file, such as `_data/overviews.yml`, so your overview should be +generated by reading data from a configuration file, such as `_data/overviews.yml`, so your overview should be placed into a category there. ### Tutorials -At the moment, tutorials are written the same as Guides/Overviews, except that their link must be added to -the metadata of `/tutorials.md`. e.g. for the [Scala With Maven][scala-with-maven] tutorial, the -metadata of `/tutorials.md` looks like +Tutorials are different to guides, they should be written in a much more concise, task-oriented style, +usually on a single page. + +Similar to guides, tutorials also use the same markdown header. + +Once the tutorial is written, to aid user navigation their link must be added to +the metadata of `/tutorials.md`. e.g. it could look like --- layout: inner-page-parent @@ -145,18 +161,33 @@ metadata of `/tutorials.md` looks like tutorials: ... - - title: "Scala with Maven" - url: "/tutorials/scala-with-maven.html" - description: "Create a Scala project with Maven." - icon: code + - title: My New Tutorial + url: "/tutorials/my-new-tutorial.html" + description: "Learn How To Do This Specific Task" + icon: code --- -For a single-page tutorial, the typical directory to place them in is `_overviews/tutorials`. +You must also add the tutorial to the drop down list in the navigation bar. To do this, add an extra entry to +`_data/doc-nav-header.yml`. i.e. + + --- + - title: Getting Started + url: "/getting-started/index.html" + - title: Learn + ... + - title: Tutorials + url: "#" + submenu: + ... + - title: My New Tutorial + url: "/tutorials/my-new-tutorial.html" + ... + --- ### Cheatsheets -For now, cheatsheets are assumed to be in the form of tables. To contribute a cheatsheet, one must simply produce their -cheatsheet as a Markdown table, with the following header: +Cheatsheets have a special layout, and the content is expected to be a markdown table. To contribute a cheatsheet, +you should use the following format: --- layout: cheatsheet @@ -164,27 +195,37 @@ cheatsheet as a Markdown table, with the following header: by: YOUR NAME about: SOME TEXT ABOUT THE CHEAT SHEET. --- + | Title A | Title B | + |---------|---------| + | content | more | ### Code blocks The site build process uses [mdoc](https://scalameta.org/mdoc/) to typecheck code snippets in markdown. This is a great way to ensure the code snippets that -you're including typecheck and are valid. Here are a few quick types to get -started. +you're including typecheck and are valid. Here are a few quick tips to get +started: -To get started, add `mdoc` after `scala` when you are creating a +First, add `mdoc` after `scala` when you are creating a code block. The `mdoc` modifier here will make sure that `mdoc` runs the code snippet and ensures that it's valid. - ```scala mdoc - val a = 1 - ``` +
    +
    +
    +            ```scala mdoc
    +val a = 1
    +```
    +
    + If you have a snippet that you expect to fail, you can also account for this by using `mdoc:fail` for a compile error `mdoc:crash` for a runtime-error. - ```scala mdoc:fail - val b: String = 3 // won't compile - ``` +
    ```scala mdoc:fail
    +val b: String = 3 // won't compile
    +```
    +
    + Keep in mind that a single file is all compiled as a single unit, so you can't redefine a variable that was defined above in another code snippet. _However_ there are a couple ways to get around this. Firstly, you can use the `mdoc:nest` @@ -193,29 +234,36 @@ essentially "hide" the snippet from the others. Another way around this is to use the `mdoc:reset` modifier, which _resets_ and forgets about everything up above. Here is an example using the various modifiers. - ```scala mdoc - import java.time.Instant +
    ```scala mdoc
    +import java.time.Instant
    +
    +def now() = Instant.now()
    +object Foo {}
    +```
    +
    + +
    ```scala mdoc:nest
    +case class Foo(a: Int) // conflicts with Foo above, but it's nested so it's fine
    +```
    +
    - def now() = Instant.now() - object Foo {} - ``` +
    ```scala mdoc
    +val a = s"The time is ${now()}" // still have access to the now method from above
    +```
    +
    - ```scala mdoc:nest - case class Foo(a: Int) // conflicts with Foo above, but it's nested so it's fine - ``` +
    ```scala mdoc:reset
    +case class Foo(a: String) // forget the previous Foo's and start fresh
    +```
    +
    - ```scala mdoc - val a = s"The time is ${now()}" // still have access to the now method from above - ``` - ```scala mdoc:reset - case class Foo(a: String) // forget the previous Foo's and start fresh - ``` - ```scala mdoc - val myFoo = Foo("hi") // now we only have access to the last Foo - ``` +
    ```scala mdoc
    +val myFoo = Foo("hi") // now we only have access to the last Foo
    +```
    +
    [collections-overview]: {% link _overviews/collections-2.13/introduction.md %} -[scala-with-maven]: {% link _overviews/tutorials/scala-with-maven.md %} [why-contribute]: {% link contribute.md %} [home]: {% link index.md %} [overviews-index]: {% link _overviews/index.md %} +[scala-3-reference]: https://docs.scala-lang.org/scala3/reference/overview.html From d8e9d2ebc889dc4b7e5a22530596bc9b6d7f24aa Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 23 Mar 2022 19:58:56 +0100 Subject: [PATCH 1001/2265] enhance contribute intro --- _contribute_resources/1-documentation.md | 4 +++- _overviews/contribute/index.md | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/_contribute_resources/1-documentation.md b/_contribute_resources/1-documentation.md index 1f42a6e20b..e11b539e16 100644 --- a/_contribute_resources/1-documentation.md +++ b/_contribute_resources/1-documentation.md @@ -3,7 +3,9 @@ title: Documentation link: /contribute/documentation.html icon: fa fa-book --- -[Scaladoc (API)][scala-standard-library-api-documentation], [docs.scala-lang.org][add-guides] and [scala-lang.org](https://github.com/scala/scala-lang). +[Library API docs][scala-standard-library-api-documentation], [new guides][add-guides] on [docs.scala-lang.org][home], and help +with [scala-lang.org](https://github.com/scala/scala-lang). [add-guides]: {% link _overviews/contribute/add-guides.md %} [scala-standard-library-api-documentation]: {% link _overviews/contribute/scala-standard-library-api-documentation.md %} +[home]: {% link index.md %} diff --git a/_overviews/contribute/index.md b/_overviews/contribute/index.md index 4e94334061..da197e233e 100644 --- a/_overviews/contribute/index.md +++ b/_overviews/contribute/index.md @@ -1,16 +1,16 @@ --- -title: Contribute +title: Introduction num: 1 --- +### Why You Should Contribute To Scala The Scala programming language is an open source project with a very diverse community, where people from all over the world contribute their work, with everyone benefiting from friendly help and advice, and kindly helping others in return. So why not join the Scala community and help everyone make things better? -## How to help? - +**What Can I Do?** That depends on what you want to contribute. Below are some getting started resources for different contribution domains. Please read all of the documentation and follow all the links from the topic pages below before attempting to contribute, as many of the questions you have will already be answered. ### Reporting bugs From 7282312e59bc4a38a1bf508e01ad7342cea386c9 Mon Sep 17 00:00:00 2001 From: Florian3k <24961583+Florian3k@users.noreply.github.com> Date: Sat, 26 Mar 2022 13:07:21 +0100 Subject: [PATCH 1002/2265] Remove dangling opening brace --- _overviews/scala3-book/fp-functional-error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/fp-functional-error-handling.md b/_overviews/scala3-book/fp-functional-error-handling.md index d56dfff3a6..41410e5cf1 100644 --- a/_overviews/scala3-book/fp-functional-error-handling.md +++ b/_overviews/scala3-book/fp-functional-error-handling.md @@ -137,7 +137,7 @@ val stringA = "1" val stringB = "2" val stringC = "3" -val y = for { +val y = for a <- makeInt(stringA) b <- makeInt(stringB) c <- makeInt(stringC) From 7a3468bec81c9382d37a10e6d2be5c928d4000db Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 26 Mar 2022 16:56:46 -0700 Subject: [PATCH 1003/2265] Give Nth advice --- _overviews/core/collections-migration-213.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 68c5247774..114da1f632 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -15,6 +15,8 @@ The most important changes in the Scala 2.13 collections library are: - Transformation methods no longer have an implicit `CanBuildFrom` parameter. This makes the library easier to understand (in source code, Scaladoc, and IDE code completion). It also makes compiling user code more efficient. - The type hierarchy is simplified. `Traversable` no longer exists, only `Iterable`. - The `to[Collection]` method was replaced by the `to(Collection)` method. + - The `toC` methods are strict by convention and yield the default collection type where applicable. For example, `Iterator.continually(42).take(10).toSeq` produces a `List[Int]` and without the limit would not. + - `toIterable` is deprecated wherever defined. For `Iterator`, in particular, prefer `to[LazyList]`. - Views have been vastly simplified and work reliably now. They no longer extend their corresponding collection type, for example, an `IndexedSeqView` no longer extends `IndexedSeq`. - `collection.breakOut` no longer exists, use `.view` and `.to(Collection)` instead. - Immutable hash sets and hash maps have a new implementation (`ChampHashSet` and `ChampHashMap`, based on the ["CHAMP" encoding](https://michael.steindorfer.name/publications/oopsla15.pdf)). From f874fe30c3d6c2b68483281ceadcc51b5620f301 Mon Sep 17 00:00:00 2001 From: som-snytt Date: Sat, 26 Mar 2022 18:35:24 -0700 Subject: [PATCH 1004/2265] Relax it's private --- _tour/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/classes.md b/_tour/classes.md index ee3dc33703..0bda77c78e 100644 --- a/_tour/classes.md +++ b/_tour/classes.md @@ -86,7 +86,7 @@ class Point { if (newValue < bound) _y = newValue else printWarning() } - private def printWarning(): Unit = println("WARNING: Out of bounds") + private def printWarning() = println("WARNING: Out of bounds") } val point1 = new Point From e6f52d94d532d7f6d8a07d8e5bac6a46ef11cf30 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 26 Mar 2022 22:14:41 -0700 Subject: [PATCH 1005/2265] Lower bound in tour includes dangers --- _tour/lower-type-bounds.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/_tour/lower-type-bounds.md b/_tour/lower-type-bounds.md index a1cdb9648f..548ffb733b 100644 --- a/_tour/lower-type-bounds.md +++ b/_tour/lower-type-bounds.md @@ -42,26 +42,40 @@ trait Node[+B] { def prepend[U >: B](elem: U): Node[U] } -case class ListNode[+B](h: B, t: Node[B]) extends Node[B] { +case class ListNode[+B](head: B, tail: Node[B]) extends Node[B] { def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this) - def head: B = h - def tail: Node[B] = t } -case class Nil[+B]() extends Node[B] { - def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this) +object Nil extends Node[Nothing] { + def prepend[U >: Nothing](elem: U): ListNode[U] = ListNode(elem, this) } ``` +We have also simplified `ListNode` to leverage its `case class` fields, and `Nil` to be a singleton object; it is a "node of nothing" because it does not hold an element. The type parameter for `Node` is `B` to suggest we want to store birds at each node. + Now we can do the following: ```scala mdoc trait Bird case class AfricanSwallow() extends Bird case class EuropeanSwallow() extends Bird +val africanSwallows: Node[AfricanSwallow] = ListNode[AfricanSwallow](AfricanSwallow(), Nil) +val swallowsFromAntarctica: Node[Bird] = Nil -val africanSwallowList = ListNode[AfricanSwallow](AfricanSwallow(), Nil()) -val birdList: Node[Bird] = africanSwallowList -birdList.prepend(EuropeanSwallow()) +// assign swallows to birds +val birds: Node[Bird] = africanSwallows + +// add a swallow to birds +val moreBirds = birds.prepend(EuropeanSwallow()) + +// add disparate swallows together to get birds +val allBirds = africanSwallows.prepend(EuropeanSwallow()) + +// but this is a mistake! adding a Node to birds widens the type arg too much. -Xlint will warn! +val error = moreBirds.prepend(swallowsFromAntarctica) ``` -The `Node[Bird]` can be assigned the `africanSwallowList` but then accept `EuropeanSwallow`s. +The covariant type parameter allows `birds` to get the value of `africanSwallows`. + +The type bound on the type parameter for `prepend` allows adding different varieties of swallows and getting a wider type: instead of `Node[AfricanSwallow]`, we get a `Node[Bird]`. + +The canary in the coal mine is `-Xlint`, which will warn if the type arg is widened too much. From e2f00f6c39981cdbeeaf5688b9f374904e403574 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 29 Mar 2022 18:10:06 +0200 Subject: [PATCH 1006/2265] Add parentheses to hello method definition Fixes #2357 --- _overviews/scala3-book/taste-hello-world.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-book/taste-hello-world.md b/_overviews/scala3-book/taste-hello-world.md index 7acf47e20e..110d55ba91 100644 --- a/_overviews/scala3-book/taste-hello-world.md +++ b/_overviews/scala3-book/taste-hello-world.md @@ -12,7 +12,7 @@ A Scala 3 “Hello, world!” example goes as follows. First, put this code in a file named _Hello.scala_: ```scala -@main def hello = println("Hello, world!") +@main def hello() = println("Hello, world!") ``` In this code, `hello` is a method. From 4895a4b7cc34c786937d1ef5c198bce66ab8777c Mon Sep 17 00:00:00 2001 From: som-snytt Date: Tue, 29 Mar 2022 09:49:23 -0700 Subject: [PATCH 1007/2265] Fix brackets Co-authored-by: Julien Richard-Foy --- _overviews/core/collections-migration-213.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 114da1f632..5eb05536ee 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -16,7 +16,7 @@ The most important changes in the Scala 2.13 collections library are: - The type hierarchy is simplified. `Traversable` no longer exists, only `Iterable`. - The `to[Collection]` method was replaced by the `to(Collection)` method. - The `toC` methods are strict by convention and yield the default collection type where applicable. For example, `Iterator.continually(42).take(10).toSeq` produces a `List[Int]` and without the limit would not. - - `toIterable` is deprecated wherever defined. For `Iterator`, in particular, prefer `to[LazyList]`. + - `toIterable` is deprecated wherever defined. For `Iterator`, in particular, prefer `to(LazyList)`. - Views have been vastly simplified and work reliably now. They no longer extend their corresponding collection type, for example, an `IndexedSeqView` no longer extends `IndexedSeq`. - `collection.breakOut` no longer exists, use `.view` and `.to(Collection)` instead. - Immutable hash sets and hash maps have a new implementation (`ChampHashSet` and `ChampHashMap`, based on the ["CHAMP" encoding](https://michael.steindorfer.name/publications/oopsla15.pdf)). From add60f3231771d2132441cacfc9ec8815f711211 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 30 Mar 2022 16:26:08 +0200 Subject: [PATCH 1008/2265] final proof read --- _overviews/contribute/add-guides.md | 29 +++---- _overviews/contribute/bug-reporting-guide.md | 13 +-- _overviews/contribute/corelibs.md | 2 +- _overviews/contribute/documentation.md | 6 +- _overviews/contribute/guide.md | 2 +- _overviews/contribute/hacker-guide.md | 81 ++++++++++--------- _overviews/contribute/partest-guide.md | 14 +++- ...cala-standard-library-api-documentation.md | 35 ++++---- 8 files changed, 89 insertions(+), 93 deletions(-) diff --git a/_overviews/contribute/add-guides.md b/_overviews/contribute/add-guides.md index ed8b0d36c7..bbb43a9686 100644 --- a/_overviews/contribute/add-guides.md +++ b/_overviews/contribute/add-guides.md @@ -6,7 +6,7 @@ num: 7 ## Why Contribute New Learning Material? As [Heather Miller writes][why-contribute], contributing to [docs.scala-lang.org][home] is -critical to making Scala accessible to newcomers, experience programmers, and anyone who is curious. +critical to making Scala accessible to newcomers, experienced programmers, and anyone who is curious. It is also a fantastic way to contribute for anyone who is comfortable using Scala, but maybe does not want to get involved with complex tools like the compiler. @@ -45,7 +45,7 @@ To use this feature you must use the backtick notation as documented by mdoc, ## Submitting Docs -For you to contribute a document, first +To contribute a new document, you should first [fork](https://help.github.com/articles/fork-a-repo/) the [repo](https://github.com/scala/docs.scala-lang), then write your article in [Markdown](https://daringfireball.net/projects/markdown/syntax) (example below), and finally submit a pull request. @@ -87,7 +87,7 @@ is provided. The goal of this documentation repository is to be highly curated, rather than the approach by other community-driven documentation platforms, like wikis. Therefore, to be included on [docs.scala-lang.org][home], a document must: -- **"fit in"** to the repository ( _i.e.,_ it should not be a complete duplicate of another article), +- **"fit in"** to the repository (_i.e.,_ it should not be a complete duplicate of another article), - **be polished**, i.e. it must be thorough, complete, correct, and organized; written as an article to be understood by many users. - **be maintained**, if the document might require revisions from time to time, be prepared to keep it up to date, or @@ -100,8 +100,6 @@ clarifications, etc. ## Document Templates -> **Note:** These templates will soon change slightly as a result of necessary refactoring. - ### Guides/Overviews A guide or an overview that can be logically placed on **one** markdown page should be placed in the directory @@ -215,16 +213,14 @@ snippet and ensures that it's valid.
                 ```scala mdoc
     val a = 1
    -```
    -
    +```
    If you have a snippet that you expect to fail, you can also account for this by using `mdoc:fail` for a compile error `mdoc:crash` for a runtime-error.
    ```scala mdoc:fail
     val b: String = 3 // won't compile
    -```
    -
    +``` Keep in mind that a single file is all compiled as a single unit, so you can't redefine a variable that was defined above in another code snippet. _However_ @@ -239,28 +235,23 @@ above. Here is an example using the various modifiers. def now() = Instant.now() object Foo {} -``` - +```
    ```scala mdoc:nest
     case class Foo(a: Int) // conflicts with Foo above, but it's nested so it's fine
    -```
    -
    +```
    ```scala mdoc
     val a = s"The time is ${now()}" // still have access to the now method from above
    -```
    -
    +```
    ```scala mdoc:reset
     case class Foo(a: String) // forget the previous Foo's and start fresh
    -```
    -
    +```
    ```scala mdoc
     val myFoo = Foo("hi") // now we only have access to the last Foo
    -```
    -
    +``` [collections-overview]: {% link _overviews/collections-2.13/introduction.md %} [why-contribute]: {% link contribute.md %} diff --git a/_overviews/contribute/bug-reporting-guide.md b/_overviews/contribute/bug-reporting-guide.md index 91858d589c..6830c18ab9 100644 --- a/_overviews/contribute/bug-reporting-guide.md +++ b/_overviews/contribute/bug-reporting-guide.md @@ -3,7 +3,8 @@ title: Bug Reporting Guide num: 8 --- -The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug), and for Scala 3, it is located at [github.com/lampepfl/dotty](https://github.com/lampepfl/dotty/issues). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. +The Scala compiler and standard library bug tracker is located at [https://github.com/scala/bug](https://github.com/scala/bug), and for Scala 3, it is located at [github.com/lampepfl/dotty](https://github.com/lampepfl/dotty/issues). Before you submit a bug make sure that it is certainly a bug by following instructions +in [Is it a Bug?](#is-it-a-bug). ## Is it a Bug? @@ -11,7 +12,7 @@ The first step in identifying a bug is to identify which component of the Scala - **Library** bugs typically manifest themselves as run-time exceptions, or as *unexpected*/*unintuitive* behavior of Scala Standard Library methods. - **Compiler** errors are manifested as compile time exceptions, unexpected behavior of your code at run time, or invalid behavior of the type system. - - **Reflection** are bugs that appear in the ‘scala.reflect’ package. For the *reflection* bugs , the same rules apply as for the *library* bugs. + - **Reflection** are bugs that appear in the `scala.reflect` package. For the *reflection* bugs, the same rules apply as for the *library* bugs. - **Scaladoc** bugs are manifested as a logical problems in the information it presents (that is, the displayed information is incorrect, such as an incorrect subclassing relationship), or incorrect behavior of the user interface. If you'd like to suggest a change in the content of the documentation, please submit a pull request (possible to do in the browser using GitHub, which is easier and faster than filing a bug). Please file a bug about the content of documentation only if you cannot provide a suggestion for its fix. If your issue is related to any of the following external projects, make sure to use its appropriate issue tracker: @@ -31,13 +32,13 @@ If you have a code snippet that is resulting in bytecode which you believe is be * Make sure you minimize your problem. To correctly minimize the problem follow the following instructions: - 1. Gradually take apart the offensive code snippet until you believe you have the simplest representation of your problem. + 1. Gradually remove parts from the original failing code snippet until you believe you have the simplest representation of your problem. - 2. Ensure that you have decoupled your code snippet from any library that could be introducing the offensive behavior. One way to achieve this is to try to recompile the offensive code snippet in isolation, outside of the context of any complex build environment. If your code depends on some strictly Java library and source code is available for it, make sure that the latter is also minimized. + 2. Ensure that you have decoupled your code snippet from any library that could be introducing the incorrect behavior. One way to achieve this is to try to recompile the offending code snippet in isolation, outside of the context of any complex build environment. If your code depends on some strictly Java library and source code is available for it, make sure that the latter is also minimized. 3. Make sure you are compiling your project from a clean slate. Your problem could be related to separate compilation, which is difficult to detect without a clean build with new `.class` files. - 4. If you have encountered a bug while building your code in the IDE, then please reproduce it on the command line. The same rule applies for build tools like `sbt` or `ant`. + 4. If you have encountered a bug while building your code in the IDE, then please reproduce it on the command line. The same rule applies for build tools like **sbt** or **Mill**. 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. @@ -69,7 +70,7 @@ Please make sure to fill in as many fields as possible. Make sure you've indicat 3. **Labels** related to your issue. For example, if you think your issue is related to the typechecker, and if you have successfully minimized your issue, label your bug as "typechecker" and "minimized". Issue tracker will suggest names for existing labels as you type them so try not to create duplicates. 4. **Running environment**. Are you running on Linux? Windows? What JVM version are you using? -In order for us to quickly triage the bug that you've found, it's important that the code snippet which produces the observed issue is as minimized as possible. For advice on minimizing your code snippet, please see the appropriate subsection of the above (Is it a Bug?). +In order for us to quickly triage the bug that you've found, it's important that the code snippet which produces the observed issue is as minimized as possible. For advice on minimizing your code snippet, please see the appropriate subsection of the above ([Is it a Bug?](#is-it-a-bug)). ### Description diff --git a/_overviews/contribute/corelibs.md b/_overviews/contribute/corelibs.md index 1eb2f840b0..4fcab907a2 100644 --- a/_overviews/contribute/corelibs.md +++ b/_overviews/contribute/corelibs.md @@ -14,7 +14,7 @@ There are several options for contributing to Scala's core libraries. You can: ### Significant changes For significant new functionality or a whole new API to be considered for inclusion in the core Scala distribution, -please take into account [https://github.com/scala/scala-dev/issues/661] before doing so. +please take into account [scala/scala-dev#661](https://github.com/scala/scala-dev/issues/661) before doing so. [documentation]: {% link _overviews/contribute/documentation.md %} [bug-reporting-guide]: {% link _overviews/contribute/bug-reporting-guide.md %} diff --git a/_overviews/contribute/documentation.md b/_overviews/contribute/documentation.md index 9bd4597b36..bd93b7fbd3 100644 --- a/_overviews/contribute/documentation.md +++ b/_overviews/contribute/documentation.md @@ -7,10 +7,10 @@ num: 5 There are several ways you can help out with the improvement of Scala documentation. These include: * API Documentation in Scaladoc -* Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site -* Updating scala-lang.org +* Guides, Overviews, Tutorials, Cheat Sheets and more on the [docs.scala-lang.org][home] site +* Updating [scala-lang.org](https://scala-lang.org) -Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [Scala Contributors](https://contributors.scala-lang.org/) mailing list and then, please, submit a pull request with updated documentation reflecting that answer. +Please read this page, and the pages linked from this one, fully before contributing documentation. Many frequently asked questions will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [Scala Contributors](https://contributors.scala-lang.org/) forum and then, please, submit a pull request with updated documentation reflecting that answer. **General requirements** for documentation submissions include spell-checking all written language, ensuring code samples compile and run correctly, correct grammar, and clean formatting/layout of the documentation. diff --git a/_overviews/contribute/guide.md b/_overviews/contribute/guide.md index 472d2d41ab..33330f511d 100644 --- a/_overviews/contribute/guide.md +++ b/_overviews/contribute/guide.md @@ -18,7 +18,7 @@ num: 10 Just to name a few common reasons: * contributing a patch is the best way to make sure your desired changes will be available in the next Scala version -* Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu +* Scala is written in Scala, so going through the source code and patching it will improve your knowledge of Scala. * last but not least, it only takes a few accepted commits to make it into the [Scala Contributor Hall of Fame](https://github.com/scala/scala/contributors). The main Scala project consists of the standard Scala library, the Scala reflection and macros library, diff --git a/_overviews/contribute/hacker-guide.md b/_overviews/contribute/hacker-guide.md index 92181003fa..2a70714f53 100644 --- a/_overviews/contribute/hacker-guide.md +++ b/_overviews/contribute/hacker-guide.md @@ -1,5 +1,5 @@ --- -title: Scala hacker guide +title: Scala 2 Hacker's Guide by: Eugene Burmako num: 12 --- @@ -18,26 +18,27 @@ Though, there's an annoying issue which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://github.com/scala/bug/issues/6725) new line tokens `%n`. -One approach would be to go the mailing list, request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala oneself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. +One approach would be to go the [Scala 2 bug tracker](https://github.com/scala/bug), request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala yourself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. **_Of note_**: There are several types of releases/builds. Nightly builds are produced every night at a fixed time. Minor releases happen once every few months. Major releases typically happen once per year. ## 1. Connect -Sometimes it's appealing to hack alone and not to have to interact with others out of fear, or out of comfort. However, in the context a big project such as Scala, -this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide +Sometimes it's appealing to hack alone and not to have to interact with others. However, in the context a big project such as Scala, there might be better ways. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists](https://scala-lang.org/community/index.html#forums) to find out how people feel -about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help -by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. +Typically bug fixes and new features start out as an idea or an experiment posted on one of [our forums](https://scala-lang.org/community/index.html#forums) to find out how people feel +about things you want to implement. People proficient in certain areas of Scala usually monitor forums and discussion rooms, so you'll often get some help by posting a message. +But the most efficient way to connect is to mention in your message one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. A list of language features/libraries along with their maintainer's full names and GitHub usernames is [in the Scala repo README](https://github.com/scala/scala#get-in-touch). In our running example, since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. -As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the [Scala Contributors](https://contributors.scala-lang.org/) mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, -in this example, we post to the [the scala-user mailing list](https://groups.google.com/group/scala-user) about our issue. +As alluded to earlier, one must also choose an appropriate avenue to discuss the issue. Typically, one would use the [Scala Contributor's Forum][contrib-forum], as there are post categories devoted to discussions about the core internal design and implementation of the Scala system. + +In this example, the issue was previously discussed on the (now unused) scala-user mailing list, at the time, +we would have posted to the [the (now unused) scala-user mailing list](https://groups.google.com/group/scala-user) about our issue: Posting to scala-user Response from Martin @@ -86,10 +87,11 @@ Before you start making changes, always create your own branch. Never work on th the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. -* For bug fixes, use `issue/NNNN` or `ticket/NNNN` for bug NNNN from the [Scala bug tracker](https://github.com/scala/bug). -* For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. +* For bug fixes, use `issue/NNNN` or `ticket/NNNN` for bug `NNNN` from the [Scala bug tracker](https://github.com/scala/bug). +* For new feature use `topic/XXX` for feature `XXX`. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. -Since in our example, we're going to fix an existing bug [6725](https://github.com/scala/bug/issues/6725), we'll create a branch named `ticket/6725`. +Since in our example, we're going to fix an existing bug +[scala/bug#6725](https://github.com/scala/bug/issues/6725), we'll create a branch named `ticket/6725`. 16:39 ~/Projects/scala (master)$ git checkout -b ticket/6725 Switched to a new branch 'ticket/6725' @@ -102,13 +104,13 @@ The next step after cloning your fork is setting up your machine to build Scala. You need the following tools: -* A Java SDK. The baseline version is 6 for 2.11.x and 8 for 2.12.x. It's possible to use a later SDK for local development, but the continuous integration builds will verify against the baseline version. +* A Java JDK. The baseline version is `8` for 2.13.x and higher. It's possible to use a higher JDK version for local development, but the continuous integration builds will verify against the baseline version. * `sbt`, an interactive build tool commonly used in Scala projects. Acquiring sbt manually is not necessary -- the recommended approach is to download the [sbt-extras runner script](https://github.com/paulp/sbt-extras/blob/master/sbt) and use it in place of `sbt`. The script will download and run the correct version of sbt when run from the Scala repository's root directory. * `curl` -- the build uses `curl` in the `pull-binary-libs.sh` script to download bootstrap libs. -OS X and Linux builds should work. Windows is supported, but it might have issues. Please report to the [Scala bug tracker](https://github.com/scala/bug) if you encounter any. +macOS and Linux builds should work. Windows is supported, but it might have issues. Please report to the [Scala 2 bug tracker](https://github.com/scala/bug) if you encounter any. -Building Scala is as easy as running `sbt dist/mkPack` in the root of your cloned repository. In general, it's much more efficient to enter the `sbt` shell once and run the various tasks from there, instead of running each task by launching `sbt some-task` on your command prompt. +Building Scala can be done with a single command `sbt dist/mkPack`, from the root of your cloned repository. In general, it's much more efficient to enter the `sbt` shell once and run the various tasks from there, instead of running each task by launching `sbt some-task` on your command prompt. Be prepared to wait for a while -- a full "clean" build takes 5+ minutes depending on your machine (longer on older machines with less memory). On a recent laptop, incremental builds usually complete within 10-30 seconds. @@ -116,16 +118,13 @@ Be prepared to wait for a while -- a full "clean" build takes 5+ minutes dependi There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. -Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. -Both of those Scala plugins provide navigation, refactoring, error reporting functionality, and integrated debugging. -See [the Scala README](https://github.com/scala/scala#ide-setup) for instructions on using Eclipse and IntelliJ IDEA with the Scala repository. +IntelliJ IDEA has a Scala plugin, which is known to work with our codebase. Alternatively you can use Visual Studio Code with the [Metals IDE extension](https://marketplace.visualstudio.com/items?itemName=scalameta.metals). +Both of these Scala IDE solutions provide navigation, refactoring, error reporting functionality, and integrated debugging. +See [the Scala README](https://github.com/scala/scala#ide-setup) for instructions on using either IntelliJ IDEA or Metals with the Scala repository. -There also exist lighter-weight editors such as Emacs, Sublime or jEdit which are faster and much less memory/compute-intensive to run, while -lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, -a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite -having significantly matured over the last year, support for our particular code base is still being improved, and is not as mature as for Eclipse and IntelliJ. +Other alternative editors exist, such as Atom, Emacs, Sublime Text or jEdit. These are faster and much less memory/compute-intensive to run, but lack semantic services and debugging. -Due to the immense variability in personal preference between IDE/editor experience, it's difficult to recommend a particular tool, and your choice should boil down to your personal preferences. +We recognise that there exist preferences towards specific IDE/editor experiences, so ultimately we recommend that your choice be your personal preference. ## 3. Hack @@ -156,7 +155,7 @@ Now, implement your bugfix or new feature! Here are also some tips & tricks that have proven useful in Scala development: * After building your working copy with the `compile` sbt task, there's no need to leave the comfort of your sbt shell to try it out: the REPL is available as the `scala` task, and you can also run the compiler using the `scalac` task. If you prefer to run the REPL outside sbt, you can generate the scripts in `build/quick/bin` using the `dist/mkQuick` task. -* The sbt workflow is also great for debugging, as you can simply create a remote debugging session in your favorite IDE, and then activate the JVM options for the next time you run the `scala` or `scalac` tasks using: +* The sbt workflow is also great for debugging, as you can create a remote debugging session in your favorite IDE, and then activate the JVM options for the next time you run the `scala` or `scalac` tasks using: ``` > set javaOptions in compiler := List("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8002") @@ -167,9 +166,8 @@ Listening for transport dt_socket at address: 8002 * Also see [the Scala README](https://github.com/scala/scala#incremental-compilation) for tips on speeding up compile times. * If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, try the `clean` task and building again. -* Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how - things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. +* Don't underestimate the power of using `println` to print debug information. When starting with Scala, I spent a lot of time in the debugger trying to figure out how + things work. However later I found out that print-based debugging is often more effective than jumping around. It's also useful to print stack traces to understand the flow of execution, for example what code executed before some action occurred. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. * You can publish your newly-built scala version locally using the `publishLocal` task in sbt. * It's convenient to enable the following local settings to speed up your workflow (put these in `local.sbt` in your working copy): @@ -184,33 +182,33 @@ testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("- // antStyle := true ``` -* Adding a macro to the `Predef` object is a pretty involved task. Due to bootstrapping, you cannot just throw a macro into it. For this reason, the process is more involved. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you have to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. [Here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. +* Adding a macro to the `Predef` object is a pretty involved task. Due to bootstrapping, it makes it more complex to add a macro. For this reason, the process is more involved. It could be useful to replicate the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (it will look like `def fn = macro ???`). Now you have to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. [Here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. -### Documentation +### Where to Find Documentation -There are several areas that one could contribute to -- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. +The separate projects under Scala have varying amounts of documentation: ##### The Scala Library -Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left the code cleaner than you found it). +Contributing to the Scala standard library is about the same as working on one of your own libraries. If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. -If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections][collections-arch], as well as a larger more general [Scala collections Guide][collections-intro] covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide][collections-par]. +The Scala collections framework, part of the Scala standard library, is more complex. You should become familiar +with its architecture, which is documented in [the Architecture of Scala Collections][collections-arch]. +The [Scala Collections Guide][collections-intro] is more general, covering the synchronous portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide][collections-par]. ##### The Scala Compiler -Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email ([Scala Contributors](https://contributors.scala-lang.org/) mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: +Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by forum ([Scala Contributors](https://contributors.scala-lang.org/) forum), chat-rooms (see `#scala-contributors` on [Discord][discord-contrib]), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: * [Compiler internals videos by Martin Odersky](https://www.scala-lang.org/old/node/598.html) are quite dated, but still very useful. In this three-video - series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. + series Martin explains the general architecture of the compiler, and the basics of the front-end, which later became the `scala-reflect` module's API. * [Reflection documentation][reflect-overview] describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that - are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. -* [Reflection and Compilers by Martin Odersky](https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk - at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. + are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the `scala-reflect` module, all of the fundamentals needed for reflection are the same for the compiler. * [Scala compiler corner](https://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/) contains extensive documentation about most of the post-typer phases (i.e. the backend) in the Scala compiler. -* [Scala Contributors](https://contributors.scala-lang.org/), a mailing list which hosts discussions about the core +* [Scala Contributors](https://contributors.scala-lang.org/), a forum which hosts discussions about the core internal design and implementation of the Scala system. ##### Other Projects @@ -303,7 +301,7 @@ Here are some more testing tips: ... Finished: FAILURE -This means your change is backward or forward binary incompatible with the specified version (the check is performed by the [migration manager](https://github.com/typesafehub/migration-manager)). The error message is actually saying what you need to add to `bincompat-backward.whitelist.conf` or `bincompat-forward.whitelist.conf` to make the error go away. If you are getting this on an internal/experimental api, it should be safe to add suggested sections to the config. Otherwise, you might want to target a newer version of scala for this change. +This means your change is backward or forward binary incompatible with the specified version (the check is performed by the [migration manager](https://github.com/typesafehub/migration-manager)). The error message is actually saying what you need to modify `project/MimaFilters.scala` to make the error go away. If you are getting this on an internal/experimental api, it should be safe to add suggested sections to the config. Otherwise, you might want to target a newer version of scala for this change. ### Verify @@ -380,7 +378,10 @@ Note that there can be a gap between a successful review and the merge, because So don't be confused if your reviewer says “LGTM”, but your code doesn't get merged immediately. [collections-arch]: {% link _overviews/core/architecture-of-scala-collections.md %} -[collections-intro]: {% link _overviews/collections/introduction.md %} +[collections-intro]: {% link _overviews/collections-2.13/introduction.md %} [collections-par]: {% link _overviews/parallel-collections/overview.md %} [reflect-overview]: {% link _overviews/reflection/overview.md %} [partest-guide]: {% link _overviews/contribute/partest-guide.md %} +[documentation]: {% link _overviews/contribute/documentation.md %} +[contrib-forum]: https://contributors.scala-lang.org/ +[discord-contrib]: https://discord.com/invite/scala diff --git a/_overviews/contribute/partest-guide.md b/_overviews/contribute/partest-guide.md index c3e6980b06..c8eb5cbf02 100644 --- a/_overviews/contribute/partest-guide.md +++ b/_overviews/contribute/partest-guide.md @@ -9,21 +9,27 @@ Partest is a custom parallel testing tool that we use to run the test suite for The test suite can be run from the sbt console with: - > partest +``` +sbt:root> partest +``` You can get a summary of the usage by running `partest --help`. If you would like to run particular tests pass the test paths as arguments - > partest test/files/pos/bounds.scala test/scaladoc/run/diagrams-base.scala +``` +sbt:root> partest test/files/pos/bounds.scala test/scaladoc/run/diagrams-base.scala +``` To run only the Scaladoc tests use `--srcpath` with the location of the tests - > partest --srcpath scaladoc +``` +sbt:root> partest --srcpath scaladoc +``` ## Using ant -Please note support for ant was removed on the 2.12 branch. +> Please note support for ant was removed on the 2.12 branch. The test suite can be run by using ant from the command line: diff --git a/_overviews/contribute/scala-standard-library-api-documentation.md b/_overviews/contribute/scala-standard-library-api-documentation.md index c1303e8b18..a6c812b7e4 100644 --- a/_overviews/contribute/scala-standard-library-api-documentation.md +++ b/_overviews/contribute/scala-standard-library-api-documentation.md @@ -21,16 +21,14 @@ contribution steps and guidelines. Thank you.* Since API documentation is located in Scala source code files, the process for contributing API documentation is similar to that of contributing bug-fixes to the Scala code base, but without the requirement that there be an issue filed on GitHub -first. When forking/branching, just use a `scaladoc/xxxx` branch name, where xxxx is a +first. When forking/branching, it would help to use a `scaladoc/xxxx` branch name, where `xxxx` is a descriptive, but short branch name (e.g. `scaladoc/future-object`). -However, if an issue *does* exist, please use `issue/NNNN`, where NNNN is the ticket number, +However, if an issue *does* exist, please use `issue/NNNN`, where `NNNN` is the ticket number, instead. -If you would like to assist us by helping us find missing documentation and -submitting bug reports for existing documentation, -[please read the following section](#contribute-api-documentation-bug-reports). -If you want to contribute new API documentation, -[jump down to the next section](#contribute-new-api-documentation). +If you would like to assist us, you can +[report missing/incorrect API documentation](#contribute-api-documentation-bug-reports), or +[contribute new API documentation](#contribute-new-api-documentation). ## Contribute API Documentation Bug Reports @@ -45,8 +43,8 @@ If you find an issue, please log it in the [Scala bug tracker](https://github.co **after making sure it is not already logged as an issue**. To help with disambiguation, please use the following format for issue title: -* Use an action describing the work required. E.g. Add, Document, Correct, Remove -* Use the full package, class/trait/object name (or state package object if +* Use an action describing the work required, e.g. **Add**, **Document**, **Correct**, **Remove**. +* Use the full package, class/trait/object/enum name (or state package object if that is the case). * Extremely short description of what to do. * More detail can (and should) go into the issue description, including a short @@ -60,10 +58,10 @@ Here is an example of the title and description for an example API documentation and the description: -`The methods on the Future companion object are critical` -`for using Futures effectively without blocking. Provide code` -`examples of how methods like sequence, transform, fold and` -`firstCompletedOf should be used.` +> The methods on the `Future` companion object are critical +> for using Futures effectively without blocking. Provide code +> examples of how methods like `sequence`, `transform`, `fold` and +> `firstCompletedOf` should be used. In addition to following these conventions, please add `documentation` and `community` labels to the issue, and put them in the `Documentation and API` @@ -93,9 +91,8 @@ new API documentation to save time, effort, mistakes and repetition. the whole document though, and pay close attention to the title and commit message formats, noting *present tense*, *length limits* and that it must merge cleanly. Remember that the title of the pull request will become the commit - message when merged. **Also**, be sure to assign one or more reviewers to the PR, list of - reviewers is at the bottom of this document, but the quick version is to add - `Review by @heathermiller` or `Review by @dickwall` **in the pull request comments**. + message when merged. **Also**, be sure to assign one or more reviewers to the PR, if this is + not possible for you, you could mention a user in **in the pull request comments**. ### Extra Requirements for Scaladoc Documentation Commits @@ -106,9 +103,9 @@ PR is merged in smoothly: * Any and all code examples provided should *be correct, compile and run* as expected (ensure this in the REPL or your IDE). * Spelling must be checked for all written language *and* code examples where - possible. Most editors have some spell checking feature available. Obviously - Scala code is likely to flag as mis-spelled sometimes, but any written language - should be checked. If you can also use a grammar checker, even better. We + possible. Most editors have some spell checking feature available. Scala code + itself is permitted to not pass a spell-checker, however any written language + should be checked. If you can also use a grammar checker, it will help. We *will* ask for spelling and grammar to be corrected before acceptance. * You **must** also run `sbt doc`, fix any problems and check the formatting and layout of your changes. Again, corrections will be required if formatting or From 8c3c443440ea72588a6bf8f35aeebfcad8ce464c Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 30 Mar 2022 17:00:52 +0200 Subject: [PATCH 1009/2265] remove contribute from nav bar --- _data/nav-header.yml | 7 ------- _includes/site-header.html | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/_data/nav-header.yml b/_data/nav-header.yml index 03621e6d64..b04b23ca78 100644 --- a/_data/nav-header.yml +++ b/_data/nav-header.yml @@ -1,17 +1,10 @@ - title: Documentation url: "/" - can-highlight: true - title: Download url: https://www.scala-lang.org/download/ - can-highlight: true - title: Community url: https://www.scala-lang.org/community/ - can-highlight: true - title: Libraries url: https://index.scala-lang.org - can-highlight: true -- title: Contribute - url: /contribute/ - title: Blog url: https://www.scala-lang.org/blog/ - can-highlight: true diff --git a/_includes/site-header.html b/_includes/site-header.html index 70f1cb6840..d2583b913f 100644 --- a/_includes/site-header.html +++ b/_includes/site-header.html @@ -10,7 +10,7 @@ From e99b6c664acc165fe48ee8307139c3cebb4a0173 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 30 Mar 2022 18:21:18 +0200 Subject: [PATCH 1010/2265] Recommend using the Scala Improvement Process category only instead of cross-posting on two categories. --- _sips/sip-submission.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/_sips/sip-submission.md b/_sips/sip-submission.md index e2efb5ec2a..4d9ae53a40 100644 --- a/_sips/sip-submission.md +++ b/_sips/sip-submission.md @@ -53,11 +53,10 @@ There are four major steps in the SIP process: Before submitting a SIP, it is required that you perform necessary preparations: -Discuss your idea on the [Scala Contributors Page](https://contributors.scala-lang.org/) (currently, we suggest -cross-posting on -[Scala Improvement Process](https://contributors.scala-lang.org/c/sip) and -[Language Design](https://contributors.scala-lang.org/c/language-design). This -may change in the future.) Create a topic that starts with “Pre-SIP” and briefly +Discuss your idea on the [Scala Contributors Page](https://contributors.scala-lang.org/) (we suggest +posting in the category +[Scala Improvement Process](https://contributors.scala-lang.org/c/sip)). +Create a topic that starts with “Pre-SIP” and briefly describe what you would like to change and why you think it’s a good idea. Proposing your ideas on the mailing list is not an optional step. For every From 640c86c471fcaed944350565e9094d90ef1b4a2e Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 31 Mar 2022 00:53:26 -0700 Subject: [PATCH 1011/2265] Simplify example and minimize diff --- _tour/lower-type-bounds.md | 40 ++++++++++++++------------------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/_tour/lower-type-bounds.md b/_tour/lower-type-bounds.md index 548ffb733b..9f5cd53b89 100644 --- a/_tour/lower-type-bounds.md +++ b/_tour/lower-type-bounds.md @@ -16,42 +16,32 @@ While [upper type bounds](upper-type-bounds.html) limit a type to a subtype of a Here is an example where this is useful: ```scala mdoc:fail -trait Node[+B] { - def prepend(elem: B): Node[B] +trait List[+B] { + def prepend(elem: B): NonEmptyList[B] = NonEmptyList(elem, this) } -case class ListNode[+B](h: B, t: Node[B]) extends Node[B] { - def prepend(elem: B): ListNode[B] = ListNode(elem, this) - def head: B = h - def tail: Node[B] = t -} +case class NonEmptyList[+B](head: B, tail: List[B]) extends List[B] -case class Nil[+B]() extends Node[B] { - def prepend(elem: B): ListNode[B] = ListNode(elem, this) -} +object Nil extends List[Nothing] ``` -This program implements a singly-linked list. `Nil` represents an empty element (i.e. an empty list). `class ListNode` is a node which contains an element of type `B` (`head`) and a reference to the rest of the list (`tail`). The `class Node` and its subtypes are covariant because we have `+B`. +This program implements a singly-linked list. `Nil` represents an empty list with no elements. `class NonEmptyList` is a node which contains an element of type `B` (`head`) and a reference to the rest of the list (`tail`). The `trait List` and its subtypes are covariant because we have `+B`. However, this program does _not_ compile because the parameter `elem` in `prepend` is of type `B`, which we declared *co*variant. This doesn't work because functions are *contra*variant in their parameter types and *co*variant in their result types. To fix this, we need to flip the variance of the type of the parameter `elem` in `prepend`. We do this by introducing a new type parameter `U` that has `B` as a lower type bound. ```scala mdoc -trait Node[+B] { - def prepend[U >: B](elem: U): Node[U] +trait List[+B] { + def prepend[U >: B](elem: U): NonEmptyList[U] = NonEmptyList(elem, this) } -case class ListNode[+B](head: B, tail: Node[B]) extends Node[B] { - def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this) -} +case class NonEmptyList[+B](head: B, tail: List[B]) extends List[B] -object Nil extends Node[Nothing] { - def prepend[U >: Nothing](elem: U): ListNode[U] = ListNode(elem, this) -} +object Nil extends List[Nothing] ``` -We have also simplified `ListNode` to leverage its `case class` fields, and `Nil` to be a singleton object; it is a "node of nothing" because it does not hold an element. The type parameter for `Node` is `B` to suggest we want to store birds at each node. +The type parameter for `List` is `B` to suggest we want to keep lists of birds. Now we can do the following: ```scala mdoc @@ -59,11 +49,11 @@ trait Bird case class AfricanSwallow() extends Bird case class EuropeanSwallow() extends Bird -val africanSwallows: Node[AfricanSwallow] = ListNode[AfricanSwallow](AfricanSwallow(), Nil) -val swallowsFromAntarctica: Node[Bird] = Nil +val africanSwallows: List[AfricanSwallow] = Nil.prepend(AfricanSwallow()) +val swallowsFromAntarctica: List[Bird] = Nil // assign swallows to birds -val birds: Node[Bird] = africanSwallows +val birds: List[Bird] = africanSwallows // add a swallow to birds val moreBirds = birds.prepend(EuropeanSwallow()) @@ -71,11 +61,11 @@ val moreBirds = birds.prepend(EuropeanSwallow()) // add disparate swallows together to get birds val allBirds = africanSwallows.prepend(EuropeanSwallow()) -// but this is a mistake! adding a Node to birds widens the type arg too much. -Xlint will warn! +// but this is a mistake! adding a list of birds widens the type arg too much. -Xlint will warn! val error = moreBirds.prepend(swallowsFromAntarctica) ``` The covariant type parameter allows `birds` to get the value of `africanSwallows`. -The type bound on the type parameter for `prepend` allows adding different varieties of swallows and getting a wider type: instead of `Node[AfricanSwallow]`, we get a `Node[Bird]`. +The type bound on the type parameter for `prepend` allows adding different varieties of swallows and getting a wider type: instead of `List[AfricanSwallow]`, we get a `List[Bird]`. The canary in the coal mine is `-Xlint`, which will warn if the type arg is widened too much. From 0bd08091e2cbccdd3d1f9fdeaa49911ba14fdcaa Mon Sep 17 00:00:00 2001 From: Andrea Mucciarelli Date: Thu, 31 Mar 2022 09:56:08 +0200 Subject: [PATCH 1012/2265] Getting started - sbt track - italian translations (#2239) Co-authored-by: Dale Wijnand --- ...-with-scala-and-sbt-on-the-command-line.md | 79 ++++++++++++++ ...ting-scala-with-sbt-on-the-command-line.md | 101 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 _it/getting-started/sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.md create mode 100644 _it/getting-started/sbt-track/testing-scala-with-sbt-on-the-command-line.md diff --git a/_it/getting-started/sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.md b/_it/getting-started/sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.md new file mode 100644 index 0000000000..0de0347ca5 --- /dev/null +++ b/_it/getting-started/sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.md @@ -0,0 +1,79 @@ +--- +title: Primi passi su scala e sbt con la linea di comando +layout: singlepage-overview +partof: getting-started-with-scala-and-sbt-on-the-command-line +language: it +disqus: true +next-page: /it/testing-scala-with-sbt-on-the-command-line +--- + +In questo tutorial si vedrà come creare un progetto Scala a partire da un template, che può essere usato come punto di partenza anche per progettti personali. +Lo strumento utilizzato per tale scopo è [sbt](https://www.scala-sbt.org/1.x/docs/index.html), che è lo standard di build per Scala. +sbt permette di compilare, eseguire e testare i tuoi progetti, ma permette di svolgere anche altri compiti. +Si presuppone una conoscenza dell'uso della linea di comando. + +## Installazione +1. Assicurarsi di avere la Java 8 JDK (conosciuta anche come 1.8) installata + * Per verificarlo, eseguire `javac -version` da linea di comando e controllare che nell'output sia riportato + `javac 1.8.___` + * Se non si possiede la versione 1.8 o superiore, installarla seguendo [queste indicazioni](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) +1. Installare sbt + * [Mac](https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Mac.html) + * [Windows](https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Windows.html) + * [Linux](https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Linux.html) + +## Creare il progetto +1. Eseguire il comando `cd` specificando una cartella vuota per spostarsi in essa. +1. Eseguire il comando `sbt new scala/hello-world.g8`. Questo effettuerà una pull del template 'hello-world' da GitHub. + Si occuperà inoltre di creare la cartella `target`, che per ora può essere ignorata. +1. Quando richiesto verrà richiesto il nome dell'applicazione, indicare `hello-world`. In questo modo verrà creato un progetto chiamato "hello-world". +1. Osserviamo cosa è stato generato una volta eseguiti i passaggi sopra riportati: + +``` +- hello-world + - project (sbt usa questa cartella per installare e gestire plugins e dipendenze) + - build.properties + - src + - main + - scala (Tutto il codice scala che viene scritto dovrà andare qui) + - Main.scala (Entry point dell'applicazione) <-- per ora è tutto ciò che ci servirà + - build.sbt (il file di definizione della build interpretato da sbt) +``` + +Una volta che verrà buildato il progetto, sbt creerà diverse cartelle `target` per i file generati. Possono essere ignorate per lo scopo di questo tutorial. + +## Eseguire il progetto +1. `cd` nella cartella `hello-world`. +1. Lanciare il comando `sbt`. Questo aprirà la console di sbt. +1. Eseguire `~run`. Il carattere `~` è opzionale. Indica ad sbt di eseguirsi ad ogni salvataggio di un file, permettendo un ciclo di modifica, esecuzione e debug più veloce. sbt genererà anche una cartella chiamata `target` che può essere ignorata. + +## Modificare il codice +1. Aprire il file `src/main/scala/Main.scala` in un qualsiasi editor di testo. +1. Modificare "Hello, World!" in "Hello, New York!" +1. Se non è stato interrotto il comando sbt, dovrebbe ora apparire "Hello, New York!" sulla console. +1. Si può continuare a modificare il file, e le modifiche dovrebbero apparire a schermo se non vengono riportati errori. + +## Aggiungere una dipendenza +Vediamo ora come utilizzare librerie pubblicate da terzi per aggiungere ulteriori funzionalità alle nostre applicazioni. + +1. Aprire il file `build.sbt` con un qualsiasi editor di testo e aggiungere la seguente riga: + +``` +libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" +``` +`libraryDependencies` è un set (un tipo di collection in scala), e utilizzando il simbolo `+=`, +si sta aggiungendo la dipendenza [scala-parser-combinators](https://github.com/scala/scala-parser-combinators) al set di dipendenze che sbt fetcherà quando verà inizializzato. +Una volta eseguito questo passaggio, sarà possibile importare classi, object ed altro da scala-parser-combinators tramite una semplice istruzione di import. + +Ulteriori librerie pubblicate possono essere trovate sul sito +[Scaladex](https://index.scala-lang.org/), dove è possibile copiare le informazioni delle dipendenze cercate nel file `build.sbt`. + +## Next steps + +Si consiglia di continuare al tutorial successivo della serie _getting started with sbt_ , ed imparare a [testare il codice Scala con sbt tramite linea di comando](testing-scala-with-sbt-on-the-command-line.html). + +**oppure** + +- Continuare ad imparare Scala online e in maniera interattiva su + [Scala Exercises](https://www.scala-exercises.org/scala_tutorial). +- Imparare le feature di Scala tramite articoli più concisi su [Tour of Scala]({{ site.baseurl }}/tour/tour-of-scala.html). \ No newline at end of file diff --git a/_it/getting-started/sbt-track/testing-scala-with-sbt-on-the-command-line.md b/_it/getting-started/sbt-track/testing-scala-with-sbt-on-the-command-line.md new file mode 100644 index 0000000000..cac6f0953a --- /dev/null +++ b/_it/getting-started/sbt-track/testing-scala-with-sbt-on-the-command-line.md @@ -0,0 +1,101 @@ +--- +title: Testare scala con sbt da linea di comando +layout: singlepage-overview +partof: testing-scala-with-sbt-on-the-command-line +language: it +disqus: true +previous-page: /it/getting-started-with-scala-and-sbt-on-the-command-line +--- + +Ci sono diverse librerie e modalità per testare il codice Scala, ma in questo tutorial verrà mostrato come eseguire il testing usando [AnyFunSuite](https://www.scalatest.org/scaladoc/3.2.2/org/scalatest/funsuite/AnyFunSuite.html) del framework ScalaTest. +Si assume che si sappia [creare un progetto Scala con sbt](getting-started-with-scala-and-sbt-on-the-command-line.html). + +## Setup +1. Da linea di comando, creare una nuova directory in una posizione a propria scelta. +1. `cd` nella cartella appena creata ed eseguire `sbt new scala/scalatest-example.g8` +1. Quando richiesto, rinominare il progetto come `ScalaTestTutorial`. +1. Il progetto avrà già in se la libreria ScalaTest come dipendenza indicata nel file `build.sbt`. +1. `cd` nel progetto ed eseguire `sbt test`. Questo eseguirà la test suite +`CubeCalculatorTest` con un unico test chiamato `CubeCalculator.cube`. + +``` +sbt test +[info] Loading global plugins from /Users/username/.sbt/0.13/plugins +[info] Loading project definition from /Users/username/workspace/sandbox/my-something-project/project +[info] Set current project to scalatest-example (in build file:/Users/username/workspace/sandbox/my-something-project/) +[info] CubeCalculatorTest: +[info] - CubeCalculator.cube +[info] Run completed in 267 milliseconds. +[info] Total number of tests run: 1 +[info] Suites: completed 1, aborted 0 +[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 +[info] All tests passed. +[success] Total time: 1 s, completed Feb 2, 2017 7:37:31 PM +``` + +## Comprendere i test +1. In qualsiasi editor di testo aprire i seguenti due file: + * `src/main/scala/CubeCalculator.scala` + * `src/test/scala/CubeCalculatorTest.scala` +1. Nel file `CubeCalculator.scala`, è riportata la definizione della funzione `cube`. +1. Nel file `CubeCalculatorTest.scala`, è presente una classe chiamata allo stesso modo dell'oggetto che stiamo testando. + +``` + import org.scalatest.funsuite.AnyFunSuite + + class CubeCalculatorTest extends AnyFunSuite { + test("CubeCalculator.cube") { + assert(CubeCalculator.cube(3) === 27) + } + } +``` + +Analizziamo ogni riga di codice. + +* `class CubeCalculatorTest` significa che stiamo testando l'oggetto `CubeCalculator` +* `extends AnyFunSuite` ci permette di utilizzare la funzionalità della classe AnyFunSuite, come ad esempio la funzione `test` +* `test` è una funzione proveniente da AnyFunSuite che raccoglie i risultati delle asserzioni all'interno del corpo della funzione. +* `"CubeCalculator.cube"` è il nome del test. Può essere chiamato in qualsiasi modo, ma la convenzione è "NomeClasse.nomeMetodo". +* `assert` prende una condizione booleana e stabilisce se il test è superato o no. +* `CubeCalculator.cube(3) === 27` controlla se l'output della funzione `cube` sia realmente 27. +Il simbolo `===` è parte di ScalaTest e restituisce messaggi di errore comprensibili. + +## Aggiungere un altro test case +1. Aggiungere un altro blocco di testo contenente il proprio enunciato `assert` che verificherà il cubo di `0`. + + ``` + import org.scalatest.funsuite.AnyFunSuite + + class CubeCalculatorTest extends AnyFunSuite { + test("CubeCalculator.cube 3 should be 27") { + assert(CubeCalculator.cube(3) === 27) + } + + test("CubeCalculator.cube 0 should be 0") { + assert(CubeCalculator.cube(0) === 0) + } + } + ``` + +1. Lanciare `sbt test` nuovamente e controllare i risultati. + + ``` + sbt test + [info] Loading project definition from C:\projects\scalaPlayground\scalatestpractice\project + [info] Loading settings for project root from build.sbt ... + [info] Set current project to scalatest-example (in build file:/C:/projects/scalaPlayground/scalatestpractice/) + [info] Compiling 1 Scala source to C:\projects\scalaPlayground\scalatestpractice\target\scala-2.13\test-classes ... + [info] CubeCalculatorTest: + [info] - CubeCalculator.cube 3 should be 27 + [info] - CubeCalculator.cube 0 should be 0 + [info] Run completed in 257 milliseconds. + [info] Total number of tests run: 2 + [info] Suites: completed 1, aborted 0 + [info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0 + [info] All tests passed. + [success] Total time: 3 s, completed Dec 4, 2019 10:34:04 PM + ``` + +## Conclusioni +In questo tutorial è stato mostrato una delle modalità per testare il codice Scala. Per saperne di più su FunSuite si può consultare [il sito ufficiale](https://www.scalatest.org/getting_started_with_fun_suite). +Si possono anche consultare altri framework di testing come [ScalaCheck](https://www.scalacheck.org/) e [Specs2](https://etorreborre.github.io/specs2/). From 100ba0eb73d497874afc0e7c3c3a07c2b9405e4e Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Thu, 31 Mar 2022 11:07:03 +0200 Subject: [PATCH 1013/2265] add instructions for viewing contents of .tasty files to Tasty Overview --- scala3/guides/tasty-overview.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scala3/guides/tasty-overview.md b/scala3/guides/tasty-overview.md index 11d0fa3608..1bf643bebd 100644 --- a/scala3/guides/tasty-overview.md +++ b/scala3/guides/tasty-overview.md @@ -52,6 +52,13 @@ $ scalac | Hello.scala | -> | Hello.tasty | -> | Hello.class | information) ``` +You can view the contents of a _.tasty_ file in a human-readable form by running the compiler on it with the `-print-tasty` flag. +You can also view the contents decompiled in a form similar to Scala source code using the `-decompile` flag. +```bash +$ scalac -print-tasty hello.tasty +$ scalac -decompile hello.tasty +``` + ### The issue with _.class_ files Because of issues such as [type erasure][erasure], _.class_ files are actually an incomplete representation of your code. From 6d41790cd92819c3f645342eb8bfd5d779294032 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 31 Mar 2022 11:30:57 +0200 Subject: [PATCH 1014/2265] Add scastie, rename top links --- _data/nav-header.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/_data/nav-header.yml b/_data/nav-header.yml index b04b23ca78..eeaa88291c 100644 --- a/_data/nav-header.yml +++ b/_data/nav-header.yml @@ -1,10 +1,12 @@ -- title: Documentation +- title: Learn url: "/" -- title: Download +- title: Install url: https://www.scala-lang.org/download/ +- title: Playground + url: https://scastie.scala-lang.org +- title: Find A Library + url: https://index.scala-lang.org - title: Community url: https://www.scala-lang.org/community/ -- title: Libraries - url: https://index.scala-lang.org - title: Blog url: https://www.scala-lang.org/blog/ From f69fb47e4ad56bc419efbcb6ca8739555728635a Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 31 Mar 2022 04:34:41 -0700 Subject: [PATCH 1015/2265] Normalize type param and add clarity per review --- _tour/lower-type-bounds.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/_tour/lower-type-bounds.md b/_tour/lower-type-bounds.md index 9f5cd53b89..f4191b425b 100644 --- a/_tour/lower-type-bounds.md +++ b/_tour/lower-type-bounds.md @@ -16,33 +16,30 @@ While [upper type bounds](upper-type-bounds.html) limit a type to a subtype of a Here is an example where this is useful: ```scala mdoc:fail -trait List[+B] { - def prepend(elem: B): NonEmptyList[B] = NonEmptyList(elem, this) +trait List[+A] { + def prepend(elem: A): NonEmptyList[A] = NonEmptyList(elem, this) } -case class NonEmptyList[+B](head: B, tail: List[B]) extends List[B] +case class NonEmptyList[+A](head: A, tail: List[A]) extends List[A] object Nil extends List[Nothing] ``` -This program implements a singly-linked list. `Nil` represents an empty list with no elements. `class NonEmptyList` is a node which contains an element of type `B` (`head`) and a reference to the rest of the list (`tail`). The `trait List` and its subtypes are covariant because we have `+B`. +This program implements a singly-linked list. `Nil` represents an empty list with no elements. `class NonEmptyList` is a node which contains an element of type `A` (`head`) and a reference to the rest of the list (`tail`). The `trait List` and its subtypes are covariant because we have `+A`. -However, this program does _not_ compile because the parameter `elem` in `prepend` is of type `B`, which we declared *co*variant. This doesn't work because functions are *contra*variant in their parameter types and *co*variant in their result types. +However, this program does _not_ compile because the parameter `elem` in `prepend` is of type `A`, which we declared *co*variant. This doesn't work because functions are *contra*variant in their parameter types and *co*variant in their result types. -To fix this, we need to flip the variance of the type of the parameter `elem` in `prepend`. We do this by introducing a new type parameter `U` that has `B` as a lower type bound. +To fix this, we need to flip the variance of the type of the parameter `elem` in `prepend`. We do this by introducing a new type parameter `B` that has `A` as a lower type bound. ```scala mdoc -trait List[+B] { - def prepend[U >: B](elem: U): NonEmptyList[U] = NonEmptyList(elem, this) +trait List[+A] { + def prepend[B >: A](elem: B): NonEmptyList[B] = NonEmptyList(elem, this) } -case class NonEmptyList[+B](head: B, tail: List[B]) extends List[B] +case class NonEmptyList[+A](head: A, tail: List[A]) extends List[A] object Nil extends List[Nothing] ``` - -The type parameter for `List` is `B` to suggest we want to keep lists of birds. - Now we can do the following: ```scala mdoc trait Bird @@ -51,21 +48,25 @@ case class EuropeanSwallow() extends Bird val africanSwallows: List[AfricanSwallow] = Nil.prepend(AfricanSwallow()) val swallowsFromAntarctica: List[Bird] = Nil +val someBird: Bird = EuropeanSwallow() // assign swallows to birds val birds: List[Bird] = africanSwallows +// add some bird to swallows, `B` is `Bird` +val someBirds = africanSwallows.prepend(someBird) + // add a swallow to birds val moreBirds = birds.prepend(EuropeanSwallow()) -// add disparate swallows together to get birds +// add disparate swallows together, `B` is `Bird` because that is the supertype common to both swallows val allBirds = africanSwallows.prepend(EuropeanSwallow()) // but this is a mistake! adding a list of birds widens the type arg too much. -Xlint will warn! -val error = moreBirds.prepend(swallowsFromAntarctica) +val error = moreBirds.prepend(swallowsFromAntarctica) // List[Object] ``` The covariant type parameter allows `birds` to get the value of `africanSwallows`. The type bound on the type parameter for `prepend` allows adding different varieties of swallows and getting a wider type: instead of `List[AfricanSwallow]`, we get a `List[Bird]`. -The canary in the coal mine is `-Xlint`, which will warn if the type arg is widened too much. +Use `-Xlint` to warn if the inferred type arg is widened too much. From 9821a64394baf44857099a69a95dca605b7e1ad3 Mon Sep 17 00:00:00 2001 From: Lixiang Ao Date: Fri, 1 Apr 2022 15:18:59 -0700 Subject: [PATCH 1016/2265] Remove deprecated methods As of 2.13.4, the following methods have been deprecated: - append(elems: A*): ArrayBuffer.this.type - prepend(elems: A*): ArrayBuffer.this.type - trimStart(n: Int): Unit - trimEnd(n: Int): Unit Affected examples are updated in this pr. --- _overviews/scala-book/arraybuffer-examples.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/_overviews/scala-book/arraybuffer-examples.md b/_overviews/scala-book/arraybuffer-examples.md index 8d4dd8ef53..381b593e49 100644 --- a/_overviews/scala-book/arraybuffer-examples.md +++ b/_overviews/scala-book/arraybuffer-examples.md @@ -114,24 +114,22 @@ As a brief overview, here are several methods you can use with an `ArrayBuffer`: ```scala val a = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) a.append(4) // ArrayBuffer(1, 2, 3, 4) -a.append(5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) -a.appendAll(Seq(7,8)) // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8) +a.appendAll(Seq(5, 6)) // ArrayBuffer(1, 2, 3, 4, 5, 6) a.clear // ArrayBuffer() val a = ArrayBuffer(9, 10) // ArrayBuffer(9, 10) a.insert(0, 8) // ArrayBuffer(8, 9, 10) a.insertAll(0, Vector(4, 5, 6, 7)) // ArrayBuffer(4, 5, 6, 7, 8, 9, 10) a.prepend(3) // ArrayBuffer(3, 4, 5, 6, 7, 8, 9, 10) -a.prepend(1, 2) // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -a.prependAll(Array(0)) // ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +a.prependAll(Array(0, 1, 2)) // ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g) a.remove(0) // ArrayBuffer(b, c, d, e, f, g) a.remove(2, 3) // ArrayBuffer(b, c, g) val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g) -a.trimStart(2) // ArrayBuffer(c, d, e, f, g) -a.trimEnd(2) // ArrayBuffer(c, d, e) +a.dropInPlace(2) // ArrayBuffer(c, d, e, f, g) +a.dropRightInPlace(2) // ArrayBuffer(c, d, e) ``` From f7afc59478816fbfaf4c1991d22fc4d1f900daa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Krenski?= Date: Sun, 3 Apr 2022 18:39:02 +0200 Subject: [PATCH 1017/2265] Fix 2.13 -Xsource:3 flag in incompatibility table --- _overviews/scala3-migration/incompatibility-table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/incompatibility-table.md b/_overviews/scala3-migration/incompatibility-table.md index 36e156a868..e699addbfe 100644 --- a/_overviews/scala3-migration/incompatibility-table.md +++ b/_overviews/scala3-migration/incompatibility-table.md @@ -19,7 +19,7 @@ Each incompatibility is described by: - The existence of a Scalafix rule that can fix it > #### Scala 2.13 deprecations and feature warnings -> Run the 2.13 compilation with `-source:3` to locate those incompatibilities in the code. +> Run the 2.13 compilation with `-Xsource:3` to locate those incompatibilities in the code. > #### Scala 3 migration versus Scalafix rewrites > The Scala 3 migration mode comes out-of-the-box. From a9de797f1d0cc5957221d13406038606a28cdd65 Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Mon, 4 Apr 2022 15:05:55 +0200 Subject: [PATCH 1018/2265] fixed typo --- _overviews/scala-book/pure-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala-book/pure-functions.md b/_overviews/scala-book/pure-functions.md index e753d67ce4..97c6ef6fb9 100644 --- a/_overviews/scala-book/pure-functions.md +++ b/_overviews/scala-book/pure-functions.md @@ -49,7 +49,7 @@ Conversely, the following functions are *impure* because they violate the defini The `foreach` method on collections classes is impure because it’s only used for its side effects, such as printing to STDOUT. ->A great hint that `foreach` is impure is that it’s method signature declares that it returns the type `Unit`. Because it returns nothing, logically the only reason you ever call it is to achieve some side effect. Similarly, *any* method that returns `Unit` is going to be an impure function. +>A great hint that `foreach` is impure is that its method signature declares that it returns the type `Unit`. Because it returns nothing, logically the only reason you ever call it is to achieve some side effect. Similarly, *any* method that returns `Unit` is going to be an impure function. Date and time related methods like `getDayOfWeek`, `getHour`, and `getMinute` are all impure because their output depends on something other than their input parameters. Their results rely on some form of hidden I/O, *hidden input* in these examples. From 180b9088915462d575813bc2644e598fb2f00348 Mon Sep 17 00:00:00 2001 From: Jason Pickens Date: Wed, 6 Apr 2022 08:02:06 +1200 Subject: [PATCH 1019/2265] Remove strikethrough from rewrite steps example (#2356) --- _overviews/scala3-migration/tooling-syntax-rewriting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/tooling-syntax-rewriting.md b/_overviews/scala3-migration/tooling-syntax-rewriting.md index 976e3c097e..bbe246aa1e 100644 --- a/_overviews/scala3-migration/tooling-syntax-rewriting.md +++ b/_overviews/scala3-migration/tooling-syntax-rewriting.md @@ -86,7 +86,7 @@ We will be able to move it to new syntax automatically in two steps: first by us > The `-indent` option does not work on the classic control structures. > So make sure to run the two steps in the correct order. -> Unfortunately, the compiler is not able to apply both steps at the same time: `-indent -new-syntax -rewrite`. +> Unfortunately, the compiler is not able to apply both steps at the same time: `-indent -new-syntax -rewrite`. ### New Control Structures From 3841483fd8a4c2e64fc021db1eca8d42a264f0ff Mon Sep 17 00:00:00 2001 From: Artem Korsakov Date: Sat, 9 Apr 2022 10:26:48 +0300 Subject: [PATCH 1020/2265] Fix error in `given` definition We can see in the [reference](https://docs.scala-lang.org/scala3/reference/contextual/givens.html) that the right `given` definition is: ``` given intMonthConverter: MonthConverter[Int] with ``` --- _overviews/scala3-book/packaging-imports.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/_overviews/scala3-book/packaging-imports.md b/_overviews/scala3-book/packaging-imports.md index 07450f72f8..3ae2e7c318 100644 --- a/_overviews/scala3-book/packaging-imports.md +++ b/_overviews/scala3-book/packaging-imports.md @@ -354,20 +354,19 @@ object MonthConversions: trait MonthConverter[A]: def convert(a: A): String - given intMonthConverter as MonthConverter[Int]: + given intMonthConverter: MonthConverter[Int] with def convert(i: Int): String = i match case 1 => "January" case 2 => "February" // more cases here ... - given stringMonthConverter as MonthConverter[String]: + given stringMonthConverter: MonthConverter[String] with def convert(s: String): String = s match case "jan" => "January" case "feb" => "February" // more cases here ... -} ``` To import those givens into the current scope, use these two `import` statements: From 519639583aa576680692632a85d94cf1b4118ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Mon, 11 Apr 2022 20:13:10 +0800 Subject: [PATCH 1021/2265] add zn-cn --- _zh-cn/scala3/new-in-scala3.md | 128 +++++++++++++++++++++++++++++++++ scala3/new-in-scala3.md | 2 +- 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 _zh-cn/scala3/new-in-scala3.md diff --git a/_zh-cn/scala3/new-in-scala3.md b/_zh-cn/scala3/new-in-scala3.md new file mode 100644 index 0000000000..28b458c8d5 --- /dev/null +++ b/_zh-cn/scala3/new-in-scala3.md @@ -0,0 +1,128 @@ +--- +layout: singlepage-overview +title: New in Scala 3 +scala3: true +--- + +令人振奋的新版 Scala 3 带来了许多改进和新功能。在这里,我们为你提供最重要的变更的快速概述。如果你想深入挖掘,还有一些参考资料供你使用。 + +- [Scala 3 Book]({% link _overviews/scala3-book/introduction.md %}) 面向刚接触 Scala 语言的开发人员。 +- [Syntax Summary][syntax-summary] 为您提供了新语法的正式描述。 +- [Language Reference][reference] 对 Scala 2 到 Scala 3 的变化做了详细说明。 +- [Migration Guide][migration] 为你提供了从 Scala 2 迁移到 Scala 3 的所有必要信息。 +- [Scala 3 Contributing Guide][contribution] Scala 3 贡献指南,更深入地探讨了编译器,包括修复问题的指南。 + +## What's new in Scala 3 +Scala 3 是对 Scala 语言的一次彻底改造。在其核心部分,类型系统的许多方面都被改变了,变得更有原则性。虽然这也带来了令人兴奋的新功能(比如联合类型),但首先意味着类型系统变得(甚至)不那么碍事了,例如[类型推断][type-inference]和 overload resolution 都得到了很大的改善。 + +### 新的和闪亮的:语法 + +除了许多(小的)清理,Scala 3 的语法还提供了以下改进: + +- 用于控制结构的新“quiet”语法,如 `if`、`while` 和 `for` 。 ([new control syntax][syntax-control]) +- `new` 关键字是可选的 (_aka_ [creator applications][creator]) +- [Optional braces][syntax-indentation]:可选的大括号,支持不受干扰、缩进敏感的编程风格 +- [类型级通配符][syntax-wildcard] 从 `_` 更改为 `?`。 +- implicit(和它们的语法)已被[大量修订][implicits]。 + +### Opinionated: Contextual Abstractions +Scala的一个基本核心概念是(在某种程度上仍然是)为用户提供一小部分强大的功能,这些功能可以被组合成巨大的(有时甚至是不可预见的)表达能力。例如,_implicit_ 的特性被用来模拟上下文抽象、表达类型级计算、模拟类型类、执行隐式强制、编码扩展方法等等。从这些用例中学习,Scala 3 采取了一种略微不同的方法,专注于 __意图__ 而非 __机制__。Scala 3 没有提供一个非常强大的功能,而是提供了多个定制的语言功能,让程序员直接表达他们的意图。 + +- **Abtracting over contextual information**. [Using clauses][contextual-using] 允许程序员对调用上下文中的信息进行抽象,这些信息应该以隐式方式传递。作为对 Scala 2 implicits 的改进,可以按类型指定`using`子句,从而将函数签名从从未显式引用的术语变量名中解放出来。 + +- **Providing Type-class instances**. [Given instances][contextual-givens] 允许程序员定义某个类型的 _规范值_ 。这使得使用类型类的编程更加简单,而不会泄露实现细节。 + +- **Retroactively extending classes**. 在 Scala 2 中,扩展方法必须使用隐式转换或隐式类进行编码。相比之下,在 Scala 3 中,[extension methods][contextual-extension]现在直接内置于语言中,从而产生更好的错误消息和改进的类型推断。 + +- **Viewing one type as another**. 隐式转换已经被重新[设计][contextual-conversions]为类型类转`Conversion`的实例。 + +- **Higher-order contextual abstractions**. [context functions][contextual-functions]的 _全新_ 功能使上下文抽象成为一流的公民。它们是库作者的一个重要工具,允许表达简洁的特定领域语言。 + +- **Actionable feedback from the compiler**. 如果一个隐式参数不能被编译器解决,它现在提供了可能解决这个问题的[import suggestions](https://www.scala-lang.org/blog/2020/05/05/scala-3-import-suggestions.html)。 + +### Say What You Mean: 类型系统改进 +除了极大地改进了类型推断,Scala 3 类型系统还提供了许多新的功能,还为你提供了强大的工具来静态地表达类型中的不变量。 + +- **Enumerations**. [枚举][enums]已经被重新设计,以便与样例类很好地融合,并形成表达[代数数据类型][enums-adts]的新标准。 + +- **Opaque Types**. 将实现细节隐藏在[opaque type aliases][types-opaque]的别名后面,而不需要在性能上付出代价! Opaque types 取代了值类,并允许你建立一个抽象的屏障,而不会造成额外的装箱开销。 + +- **Intersection and union types**. 将类型系统建立在新的基础上,导致了新的类型系统功能的引入:[intersection types][types-intersection]的实例,如`A & B`,既是`A`的实例,也是`B`的实例;[union types][types-union]的实例,如`A | B`,是`A`或`B`的实例。这两种结构都允许程序员在继承层次结构之外灵活地表达类型约束。 + +- **Dependent function types**. Scala 2 已经允许返回类型依赖于(值)参数。在 Scala 3 中,现在可以对这种模式进行抽象,表达[dependent function types][types-dependent]。在类型`F = (e: Entry) => e.Key`中,结果类型取决于参数。 + +- **Polymorphic function types**. 与 dependent function types 一样,Scala 2 支持拥有类型参数的方法,但不允许程序员对这些方法进行抽象。在 Scala 3 中,像`[A] => List[A] => List[A]`这样的[polymorphic function types][types-polymorphic]可以抽象出除值参数外还接受 _类型参数_ 的函数。 + +- **Type lambdas**. 在 Scala 2 中需要用[编译器插件](https://github.com/typelevel/kind-projector)来表达的东西,现在在 Scala 3 中是第一类的功能:类型lambdas是类型级别的函数,可以作为(高等类型的)类型参数传递,而不需要辅助类型定义。 + +- **Match types**. Scala 3 提供了对[matching on types][types-match]的直接支持,而不是使用隐式解析对类型级别的计算进行编码。将类型级计算整合到类型检查器中,可以改进错误信息,并消除对复杂编码的需求。 + +### 重新设想的:面向对象的编程 + +Scala 一直处于函数式编程和面向对象编程的前沿 -- 而 Scala 3 在这两个方向上都推动了边界的发展! 上述类型系统的变化和上下文抽象的重新设计使得 _函数式编程_ 比以前更容易。同时,以下的新特性使结构良好的 _面向对象设计_ 成为可能,并支持最佳实践。 + +- **Pass it on**. Trait 更接近于 class,现在也可以接受[参数][oo-trait-parameters],使其作为模块化软件分解的工具更加强大。 + +- **Plan for extension**. 在面向对象的设计中,扩展那些不打算扩展的类是一个长期存在的问题。为了解决这个问题,[open classes][oo-open]要求库设计者 _明确地_ 将类标记为 open(开放的)。 + +- **Hide implementation details**. 实施行为的实用性traits有时不应该是推断类型的一部分。在 Scala 3 中,这些traits可以被标记为[transparent][oo-transparent],(在推断类型中)向用户隐藏继承性。 + +- **Composition over inheritance**. 这句话经常被引用,但实现起来却很繁琐。Scala 3 的[export clauses][oo-export]则不然:与imports对应,export clauses 允许用户为对象的选定成员定义别名。 + +- **No more NPEs**. Scala 3 比以往任何时候都更安全:[explicit null][oo-explicit-null]将`null`移出了类型层次结构,帮助你静态地捕捉错误;[safe initialization][oo-safe-init]的额外检查可以检测对未初始化对象的访问。 + +### Batteries Included: 元编程 +Scala 2 中的宏只是一个实验性的功能,而 Scala 3 则为元编程提供了强大的工具库。[宏教程]({% link _overviews/scala3-macros/tutorial/index.md %})中包含了关于不同设施的详细信息。特别是,Scala 3 为元编程提供了以下功能: + +作为基本的起点,[inline feature][meta-inline]允许在编译时减少数值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 + +- **Inline**. [inline feature][meta-inline]允许在编译时减少数值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 +- **Compile-time operations**. 包[`scala.compiletime`][meta-compiletime]中包含了额外的功能,可以用来实现内联方法。 +- **Quoted code blocks**. Scala 3为代码增加了[quasi-quotation][meta-quotes]的新功能,这为构建和分析代码提供了方便的高级接口。构建加一加一的代码就像`'{ 1 + 1 }`一样简单。 +- **Reflection API**. 对于更高级的用例,[quotes.reflect][meta-reflection]提供了更详细的控制来检查和生成程序树。 + + +如果你想进一步了解 Scala 3 中的元编程,我们邀请你参加我们的[教程][meta-tutorial]。 + +[enums]: {{ site.scala3ref }}/enums/enums.html +[enums-adts]: {{ site.scala3ref }}/enums/adts.html + +[types-intersection]: {{ site.scala3ref }}/new-types/intersection-types.html +[types-union]: {{ site.scala3ref }}/new-types/union-types.html +[types-dependent]: {{ site.scala3ref }}/new-types/dependent-function-types.html +[types-lambdas]: {{ site.scala3ref }}/new-types/type-lambdas.html +[types-polymorphic]: {{ site.scala3ref }}/new-types/polymorphic-function-types.html +[types-match]: {{ site.scala3ref }}/new-types/match-types.html +[types-opaque]: {{ site.scala3ref }}/other-new-features/opaques.html + +[type-inference]: {{ site.scala3ref }}/changed-features/type-inference.html +[overload-resolution]: {{ site.scala3ref }}/changed-features/overload-resolution.html +[reference]: {{ site.scala3ref }}/overview.html +[creator]: {{ site.scala3ref }}/other-new-features/creator-applications.html +[migration]: {% link _overviews/scala3-migration/compatibility-intro.md %} +[contribution]: {% link _overviews/scala3-contribution/contribution-intro.md %} + +[implicits]: {{ site.scala3ref }}/contextual.html +[contextual-using]: {{ site.scala3ref }}/contextual/using-clauses.html +[contextual-givens]: {{ site.scala3ref }}/contextual/givens.html +[contextual-extension]: {{ site.scala3ref }}/contextual/extension-methods.html +[contextual-conversions]: {{ site.scala3ref }}/contextual/conversions.html +[contextual-functions]: {{ site.scala3ref }}/contextual/context-functions.html + +[syntax-summary]: {{ site.scala3ref }}/syntax.html +[syntax-control]: {{ site.scala3ref }}/other-new-features/control-syntax.html +[syntax-indentation]: {{ site.scala3ref }}/other-new-features/indentation.html +[syntax-wildcard]: {{ site.scala3ref }}/changed-features/wildcards.html + +[meta-tutorial]: {% link _overviews/scala3-macros/tutorial/index.md %} +[meta-inline]: {% link _overviews/scala3-macros/tutorial/inline.md %} +[meta-compiletime]: {% link _overviews/scala3-macros/tutorial/compiletime.md %} +[meta-quotes]: {% link _overviews/scala3-macros/tutorial/quotes.md %} +[meta-reflection]: {% link _overviews/scala3-macros/tutorial/reflection.md %} + +[oo-explicit-null]: {{ site.scala3ref }}/other-new-features/explicit-nulls.html +[oo-safe-init]: {{ site.scala3ref }}/other-new-features/safe-initialization.html +[oo-trait-parameters]: {{ site.scala3ref }}/other-new-features/trait-parameters.html +[oo-open]: {{ site.scala3ref }}/other-new-features/open-classes.html +[oo-transparent]: {{ site.scala3ref }}/other-new-features/transparent-traits.html +[oo-export]: {{ site.scala3ref }}/other-new-features/export.html diff --git a/scala3/new-in-scala3.md b/scala3/new-in-scala3.md index af6d6111c1..5b30d76158 100644 --- a/scala3/new-in-scala3.md +++ b/scala3/new-in-scala3.md @@ -1,7 +1,7 @@ --- layout: singlepage-overview title: New in Scala 3 -languages: ["ja"] +languages: ["ja","zh-cn"] --- The exciting new version of Scala 3 brings many improvements and new features. Here we provide you with a quick overview of the most important From afcaefc6d26c42d36da3bbad2d1ef81244b01a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Mon, 11 Apr 2022 20:25:45 +0800 Subject: [PATCH 1022/2265] fix --- _zh-cn/scala3/new-in-scala3.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/_zh-cn/scala3/new-in-scala3.md b/_zh-cn/scala3/new-in-scala3.md index 28b458c8d5..472f66331f 100644 --- a/_zh-cn/scala3/new-in-scala3.md +++ b/_zh-cn/scala3/new-in-scala3.md @@ -17,7 +17,7 @@ Scala 3 是对 Scala 语言的一次彻底改造。在其核心部分,类型 ### 新的和闪亮的:语法 -除了许多(小的)清理,Scala 3 的语法还提供了以下改进: +除了许多(小的)清理工作,Scala 3 的语法还提供了以下改进: - 用于控制结构的新“quiet”语法,如 `if`、`while` 和 `for` 。 ([new control syntax][syntax-control]) - `new` 关键字是可选的 (_aka_ [creator applications][creator]) @@ -34,9 +34,9 @@ Scala的一个基本核心概念是(在某种程度上仍然是)为用户提 - **Retroactively extending classes**. 在 Scala 2 中,扩展方法必须使用隐式转换或隐式类进行编码。相比之下,在 Scala 3 中,[extension methods][contextual-extension]现在直接内置于语言中,从而产生更好的错误消息和改进的类型推断。 -- **Viewing one type as another**. 隐式转换已经被重新[设计][contextual-conversions]为类型类转`Conversion`的实例。 +- **Viewing one type as another**. [隐式转换][contextual-conversions]已经被重新设计为类型类`Conversion`的实例。 -- **Higher-order contextual abstractions**. [context functions][contextual-functions]的 _全新_ 功能使上下文抽象成为一流的公民。它们是库作者的一个重要工具,允许表达简洁的特定领域语言。 +- **Higher-order contextual abstractions**. [context functions][contextual-functions]的 _全新_ 功能使上下文抽象成为一流的公民。它们是库开发人员的一个重要工具,允许表达简洁的特定领域语言。 - **Actionable feedback from the compiler**. 如果一个隐式参数不能被编译器解决,它现在提供了可能解决这个问题的[import suggestions](https://www.scala-lang.org/blog/2020/05/05/scala-3-import-suggestions.html)。 @@ -74,15 +74,13 @@ Scala 一直处于函数式编程和面向对象编程的前沿 -- 而 Scala 3 ### Batteries Included: 元编程 Scala 2 中的宏只是一个实验性的功能,而 Scala 3 则为元编程提供了强大的工具库。[宏教程]({% link _overviews/scala3-macros/tutorial/index.md %})中包含了关于不同设施的详细信息。特别是,Scala 3 为元编程提供了以下功能: -作为基本的起点,[inline feature][meta-inline]允许在编译时减少数值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 - - **Inline**. [inline feature][meta-inline]允许在编译时减少数值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 - **Compile-time operations**. 包[`scala.compiletime`][meta-compiletime]中包含了额外的功能,可以用来实现内联方法。 - **Quoted code blocks**. Scala 3为代码增加了[quasi-quotation][meta-quotes]的新功能,这为构建和分析代码提供了方便的高级接口。构建加一加一的代码就像`'{ 1 + 1 }`一样简单。 - **Reflection API**. 对于更高级的用例,[quotes.reflect][meta-reflection]提供了更详细的控制来检查和生成程序树。 -如果你想进一步了解 Scala 3 中的元编程,我们邀请你参加我们的[教程][meta-tutorial]。 +如果你想进一步了解 Scala 3 中的元编程,我们邀请你参加[教程][meta-tutorial]。 [enums]: {{ site.scala3ref }}/enums/enums.html [enums-adts]: {{ site.scala3ref }}/enums/adts.html From 9109395ffc43c7168daf02d0b328aca7c116ec39 Mon Sep 17 00:00:00 2001 From: Gord Currie <1119730+gordcurrie@users.noreply.github.com> Date: Mon, 11 Apr 2022 09:04:42 -0500 Subject: [PATCH 1023/2265] Update implicit casting example (#2370) --- _overviews/scala3-book/first-look-at-types.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/_overviews/scala3-book/first-look-at-types.md b/_overviews/scala3-book/first-look-at-types.md index c62e2cc9dd..85c3214ad9 100644 --- a/_overviews/scala3-book/first-look-at-types.md +++ b/_overviews/scala3-book/first-look-at-types.md @@ -238,20 +238,19 @@ Value types can be cast in the following way: For example: ```scala -val x: Long = 987654321 -val y: Float = x // 9.8765434E8 (note that some precision is lost in this case) +val b: Byte = 127 +val i: Int = b // 127 val face: Char = '☺' val number: Int = face // 9786 ``` -Casting is unidirectional. -This will not compile: +You can only cast to a type if there is no loss of information. Otherwise, you need to be explicit about the cast: -``` +```scala val x: Long = 987654321 -val y: Float = x // 9.8765434E8 -val z: Long = y // Does not conform +val y: Float = x.toFloat // 9.8765434E8 (note that `.toFloat` is required because the cast results in percision loss) +val z: Long = y // Error ``` You can also cast a reference type to a subtype. From 10c29916a9bfebaa979209d9421ff6d2a43d8e08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Apr 2022 10:15:06 +0000 Subject: [PATCH 1024/2265] Bump nokogiri from 1.13.3 to 1.13.4 Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.3 to 1.13.4. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.13.4/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.13.3...v1.13.4) --- updated-dependencies: - dependency-name: nokogiri dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5b52d7697a..3c6f6b8d12 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -55,7 +55,7 @@ GEM rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) mini_portile2 (2.8.0) - nokogiri (1.13.3) + nokogiri (1.13.4) mini_portile2 (~> 2.8.0) racc (~> 1.4) nokogumbo (2.0.2) From b9926e655a75be592d5fae52ca894e0490901692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Tue, 12 Apr 2022 15:46:45 +0200 Subject: [PATCH 1025/2265] Update Scala version to 3.1.2 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 43f6dfd536..accb4b5df1 100644 --- a/_config.yml +++ b/_config.yml @@ -17,7 +17,7 @@ keywords: scala-version: 2.13.8 scala-212-version: 2.12.15 -scala-3-version: 3.1.1 +scala-3-version: 3.1.2 collections: contribute_resources: From 10abafb233f9b2877585e4316cf30ab308bd7449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Tue, 12 Apr 2022 15:50:34 +0200 Subject: [PATCH 1026/2265] Add entry for the documentation --- api/all.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/all.md b/api/all.md index ea55e544d9..33566543b6 100644 --- a/api/all.md +++ b/api/all.md @@ -6,8 +6,8 @@ includeTOC: true ## Latest releases -* Scala 3.1.1 - * [Library API](https://www.scala-lang.org/api/3.1.1/) +* Scala 3.1.2 + * [Library API](https://www.scala-lang.org/api/3.1.2/) * Scala 2.13.8 * [Library API](https://www.scala-lang.org/api/2.13.8/) * [Compiler API](https://www.scala-lang.org/api/2.13.8/scala-compiler/scala/) @@ -60,6 +60,8 @@ https://scala-ci.typesafe.com/artifactory/scala-integration/org/scala-lang/ ## Previous releases +* Scala 3.1.1 + * [Library API](https://www.scala-lang.org/api/3.1.1/) * Scala 3.1.0 * [Library API](https://www.scala-lang.org/api/3.1.0/) * Scala 3.0.2 From 496e82cc9e0515c68f7359425728da91d8953a62 Mon Sep 17 00:00:00 2001 From: Jochen Schneider Date: Fri, 15 Apr 2022 18:37:06 +0200 Subject: [PATCH 1027/2265] Example variable typo --- _overviews/collections-2.13/maps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections-2.13/maps.md b/_overviews/collections-2.13/maps.md index 3a27586614..8dff664b27 100644 --- a/_overviews/collections-2.13/maps.md +++ b/_overviews/collections-2.13/maps.md @@ -62,7 +62,7 @@ Mutable maps support in addition the operations summarized in the following tabl | WHAT IT IS | WHAT IT DOES | | ------ | ------ | | **Additions and Updates:**| | -| `ms(k) = v` |(Or, written out, `ms.update(x, v)`). Adds mapping from key `k` to value `v` to map ms as a side effect, overwriting any previous mapping of `k`.| +| `ms(k) = v` |(Or, written out, `ms.update(k, v)`). Adds mapping from key `k` to value `v` to map ms as a side effect, overwriting any previous mapping of `k`.| | `ms.addOne(k -> v)`
    or `ms += (k -> v)` |Adds mapping from key `k` to value `v` to map `ms` as a side effect and returns `ms` itself.| | `ms addAll xvs`
    or `ms ++= kvs` |Adds all mappings in `kvs` to `ms` as a side effect and returns `ms` itself.| | `ms.put(k, v)` |Adds mapping from key `k` to value `v` to `ms` and returns any value previously associated with `k` as an option.| From 86724d38cd620fff0568b1b6399e047f81de24ec Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Apr 2022 10:56:08 +0200 Subject: [PATCH 1028/2265] Update scalatest to 3.2.11 in scala book --- _overviews/scala-book/sbt-scalatest-bdd.md | 4 ++-- _overviews/scala-book/sbt-scalatest-tdd.md | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/_overviews/scala-book/sbt-scalatest-bdd.md b/_overviews/scala-book/sbt-scalatest-bdd.md index ee20a8490e..5117bbc0fc 100644 --- a/_overviews/scala-book/sbt-scalatest-bdd.md +++ b/_overviews/scala-book/sbt-scalatest-bdd.md @@ -70,7 +70,7 @@ class MathUtilsSpec extends FunSpec { As you can see, this is a very different-looking style than the TDD tests in the previous lesson. If you’ve never used a BDD style of testing before, a main idea is that the tests should be relatively easy to read for one of the “domain experts” who work with the programmers to create the application. A few notes about this code: -- It uses the `FunSpec` class where the TDD tests used `FunSuite` +- It uses the `AnyFunSpec` class where the TDD tests used `AnyFunSuite` - A set of tests begins with `describe` - Each test begins with `it`. The idea is that the test should read like, “It should do XYZ...,” where “it” is the `double` function - This example also shows how to mark a test as “pending” @@ -96,7 +96,7 @@ With those files in place you can again run `sbt test`. The important part of th [info] Suites: completed 2, aborted 0 [info] Tests: succeeded 4, failed 0, canceled 0, ignored 0, pending 1 [info] All tests passed. -[success] Total time: 4 s, completed Jan 6, 2018 4:58:23 PM +[success] Total time: 4 s ```` A few notes about that output: diff --git a/_overviews/scala-book/sbt-scalatest-tdd.md b/_overviews/scala-book/sbt-scalatest-tdd.md index 7214566a09..a0c61da35c 100644 --- a/_overviews/scala-book/sbt-scalatest-tdd.md +++ b/_overviews/scala-book/sbt-scalatest-tdd.md @@ -39,7 +39,7 @@ version := "1.0" scalaVersion := "{{site.scala-version}}" libraryDependencies += - "org.scalatest" %% "scalatest" % "3.0.8" % Test + "org.scalatest" %% "scalatest" % "3.2.11" % Test ``` @@ -47,7 +47,7 @@ The first three lines of this file are essentially the same as the first example ```scala libraryDependencies += - "org.scalatest" %% "scalatest" % "3.0.8" % Test + "org.scalatest" %% "scalatest" % "3.2.11" % Test ``` >The ScalaTest documentation has always been good, and you can always find the up to date information on what those lines should look like on the [Installing ScalaTest](http://www.scalatest.org/install) page. @@ -85,8 +85,8 @@ There isn’t much that can go wrong with that source code, but it provides a si [warn] consider launching sbt without any commands, or explicitly passing 'shell' ... ... -[info] Compiling 1 Scala source to /Users/al/Projects/Scala/HelloScalaTest/target/scala-2.12/classes... -[info] Running simpletest.Hello +[info] compiling 1 Scala source to /Users/al/Projects/Scala/HelloScalaTest/target/scala-2.13/classes... +[info] running simpletest.Hello Hello Alvin Alexander [success] Total time: 4 s ```` @@ -108,9 +108,9 @@ Next, create a file named *HelloTests.scala* in that directory with the followin ```scala package simpletest -import org.scalatest.FunSuite +import org.scalatest.funsuite.AnyFunSuite -class HelloTests extends FunSuite { +class HelloTests extends AnyFunSuite { // test 1 test("the name is set correctly in constructor") { @@ -130,7 +130,7 @@ class HelloTests extends FunSuite { This file demonstrates the ScalaTest `FunSuite` approach. A few important points: -- Your class should extend `FunSuite` +- Your class should extend `AnyFunSuite` - You create tests as shown, by giving each `test` a unique name - At the end of each test you should call `assert` to test that a condition has been satisfied @@ -140,7 +140,7 @@ Now you can run these tests with the `sbt test` command. Skipping the first few ```` > sbt test -[info] Set current project to HelloScalaTest (in build file:/Users/al/Projects/Scala/HelloScalaTest/) +[info] set current project to HelloScalaTest (in build file:/Users/al/Projects/Scala/HelloScalaTest/) [info] HelloTests: [info] - the name is set correctly in constructor [info] - a Person's name can be changed From 9ac6061ceacad3e7a8906abe49e6a8f2504ac2f4 Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Apr 2022 10:56:35 +0200 Subject: [PATCH 1029/2265] Update scalatest to 3.2.11 in IntelliJ example --- .../testing-scala-in-intellij-with-scalatest.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md b/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md index 77d0b3341a..fb34580984 100644 --- a/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md +++ b/_getting-started/intellij-track/testing-scala-in-intellij-with-scalatest.md @@ -20,15 +20,15 @@ This assumes you know [how to build a project in IntelliJ](building-a-scala-proj 1. Add the ScalaTest dependency: 1. Add the ScalaTest dependency to your `build.sbt` file: ``` - libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test + libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.11" % Test ``` 1. If you get a notification "build.sbt was changed", select **auto-import**. 1. These two actions will cause `sbt` to download the ScalaTest library. - 1. Wait for the `sbt` sync to finish; otherwise, `FunSuite` and `test()` will be + 1. Wait for the `sbt` sync to finish; otherwise, `AnyFunSuite` and `test()` will be unrecognized. 1. On the project pane on the left, expand `src` => `main`. 1. Right-click on `scala` and select **New** => **Scala class**. -1. Call it `CubeCalculator`, change the **Kind** to `object`, and click **OK**. +1. Call it `CubeCalculator`, change the **Kind** to `object`, and hit enter or double click on `object`. 1. Replace the code with the following: ``` object CubeCalculator extends App { @@ -41,12 +41,12 @@ This assumes you know [how to build a project in IntelliJ](building-a-scala-proj ## Creating a test 1. On the project pane on the left, expand `src` => `test`. 1. Right-click on `scala` and select **New** => **Scala class**. -1. Name the class `CubeCalculatorTest` and click **OK**. +1. Name the class `CubeCalculatorTest` and hit enter or double click on `class`. 1. Replace the code with the following: ``` - import org.scalatest.FunSuite + import org.scalatest.funsuite.AnyFunSuite - class CubeCalculatorTest extends FunSuite { + class CubeCalculatorTest extends AnyFunSuite { test("CubeCalculator.cube") { assert(CubeCalculator.cube(3) === 27) } @@ -60,9 +60,9 @@ This assumes you know [how to build a project in IntelliJ](building-a-scala-proj Let's go over this line by line: * `class CubeCalculatorTest` means we are testing the object `CubeCalculator` -* `extends FunSuite` lets us use functionality of ScalaTest's FunSuite class +* `extends AnyFunSuite` lets us use functionality of ScalaTest's AnyFunSuite class such as the `test` function -* `test` is function that comes from the FunSuite library that collects +* `test` is a function that comes from the FunSuite library that collects results from assertions within the function body. * `"CubeCalculator.cube"` is a name for the test. You can call it anything but one convention is "ClassName.methodName". From 533d497ffc5c11e24f3efb5dbf67b387a4872083 Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Apr 2022 14:18:31 +0200 Subject: [PATCH 1030/2265] Drop references to Discourse comments --- _ja/tour/abstract-type-members.md | 4 ---- _ja/tour/annotations.md | 5 ----- _ja/tour/automatic-closures.md | 3 --- _ja/tour/basics.md | 5 ----- _ja/tour/by-name-parameters.md | 5 ----- _ja/tour/case-classes.md | 5 ----- _ja/tour/classes.md | 5 ----- _ja/tour/compound-types.md | 5 ----- _ja/tour/default-parameter-values.md | 5 ----- _ja/tour/extractor-objects.md | 5 ----- _ja/tour/for-comprehensions.md | 5 ----- _ja/tour/generic-classes.md | 5 ----- _ja/tour/higher-order-functions.md | 5 ----- _ja/tour/implicit-conversions.md | 5 ----- _ja/tour/implicit-parameters.md | 5 ----- _ja/tour/inner-classes.md | 5 ----- _ja/tour/lower-type-bounds.md | 5 ----- _ja/tour/mixin-class-composition.md | 5 ----- _ja/tour/multiple-parameter-lists.md | 5 ----- _ja/tour/named-arguments.md | 5 ----- _ja/tour/nested-functions.md | 5 ----- _ja/tour/operators.md | 5 ----- _ja/tour/package-objects.md | 4 ---- _ja/tour/packages-and-imports.md | 4 ---- _ja/tour/pattern-matching.md | 6 ------ _ja/tour/polymorphic-methods.md | 6 ------ _ja/tour/regular-expression-patterns.md | 6 ------ _ja/tour/self-types.md | 5 ----- _ja/tour/singleton-objects.md | 5 ----- _ja/tour/tour-of-scala.md | 6 ------ _ja/tour/traits.md | 5 ----- _ja/tour/tuples.md | 5 ----- _ja/tour/type-inference.md | 4 ---- _ja/tour/unified-types.md | 5 ----- _ja/tour/upper-type-bounds.md | 4 ---- _ja/tour/variances.md | 5 ----- _ja/tutorials/scala-for-java-programmers.md | 3 --- _overviews/scala-book/abstract-classes.md | 1 - _overviews/scala-book/anonymous-functions.md | 1 - _overviews/scala-book/arraybuffer-examples.md | 1 - _overviews/scala-book/built-in-types.md | 1 - _overviews/scala-book/case-classes.md | 1 - _overviews/scala-book/case-objects.md | 1 - _overviews/scala-book/classes-aux-constructors.md | 1 - _overviews/scala-book/classes.md | 1 - _overviews/scala-book/collections-101.md | 1 - _overviews/scala-book/collections-maps.md | 1 - _overviews/scala-book/collections-methods.md | 1 - _overviews/scala-book/command-line-io.md | 1 - _overviews/scala-book/companion-objects.md | 1 - _overviews/scala-book/concurrency-signpost.md | 1 - _overviews/scala-book/constructors-default-values.md | 1 - _overviews/scala-book/control-structures.md | 1 - _overviews/scala-book/enumerations-pizza-class.md | 1 - _overviews/scala-book/for-expressions.md | 1 - _overviews/scala-book/for-loops.md | 1 - _overviews/scala-book/functional-error-handling.md | 1 - _overviews/scala-book/functional-programming.md | 1 - _overviews/scala-book/futures.md | 1 - _overviews/scala-book/hello-world-1.md | 1 - _overviews/scala-book/hello-world-2.md | 1 - _overviews/scala-book/if-then-else-construct.md | 1 - _overviews/scala-book/list-class.md | 1 - _overviews/scala-book/map-class.md | 1 - _overviews/scala-book/match-expressions.md | 1 - _overviews/scala-book/methods-first-look.md | 1 - _overviews/scala-book/misc.md | 1 - _overviews/scala-book/no-null-values.md | 1 - _overviews/scala-book/oop-pizza-example.md | 1 - _overviews/scala-book/passing-functions-around.md | 1 - _overviews/scala-book/preliminaries.md | 1 - _overviews/scala-book/prelude-taste-of-scala.md | 1 - _overviews/scala-book/pure-functions.md | 1 - _overviews/scala-book/sbt-scalatest-bdd.md | 1 - _overviews/scala-book/sbt-scalatest-intro.md | 1 - _overviews/scala-book/sbt-scalatest-tdd.md | 1 - _overviews/scala-book/scala-build-tool-sbt.md | 1 - _overviews/scala-book/scala-features.md | 1 - _overviews/scala-book/scala-repl.md | 1 - _overviews/scala-book/set-class.md | 1 - _overviews/scala-book/traits-abstract-mixins.md | 1 - _overviews/scala-book/traits-interfaces.md | 1 - _overviews/scala-book/traits-intro.md | 1 - _overviews/scala-book/try-catch-finally.md | 1 - _overviews/scala-book/tuples.md | 1 - _overviews/scala-book/two-notes-about-strings.md | 1 - _overviews/scala-book/two-types-variables.md | 1 - _overviews/scala-book/type-is-optional.md | 1 - _overviews/scala-book/vector-class.md | 1 - _overviews/scala-book/where-next.md | 1 - _overviews/scaladoc/contribute.md | 5 ----- _overviews/scaladoc/generate.md | 5 ----- _ru/overviews/collections-2.13/arrays.md | 5 ----- .../concrete-immutable-collection-classes.md | 6 ------ .../collections-2.13/concrete-mutable-collection-classes.md | 6 ------ .../conversions-between-java-and-scala-collections.md | 6 ------ .../collections-2.13/creating-collections-from-scratch.md | 6 ------ _ru/overviews/collections-2.13/equality.md | 6 ------ _ru/overviews/collections-2.13/introduction.md | 6 ------ _ru/overviews/collections-2.13/iterators.md | 6 ------ _ru/overviews/collections-2.13/maps.md | 6 ------ _ru/overviews/collections-2.13/overview.md | 6 ------ .../collections-2.13/performance-characteristics.md | 6 ------ _ru/overviews/collections-2.13/seqs.md | 6 ------ _ru/overviews/collections-2.13/sets.md | 6 ------ _ru/overviews/collections-2.13/strings.md | 6 ------ _ru/overviews/collections-2.13/trait-iterable.md | 6 ------ _ru/overviews/collections-2.13/views.md | 6 ------ _ru/overviews/collections/introduction.md | 5 ----- _ru/overviews/parallel-collections/architecture.md | 3 --- .../parallel-collections/concrete-parallel-collections.md | 4 ---- _ru/overviews/parallel-collections/configuration.md | 4 ---- _ru/overviews/parallel-collections/conversions.md | 4 ---- _ru/overviews/parallel-collections/ctries.md | 4 ---- .../parallel-collections/custom-parallel-collections.md | 4 ---- _ru/overviews/parallel-collections/overview.md | 4 ---- _ru/overviews/parallel-collections/performance.md | 4 ---- _ru/tour/abstract-type-members.md | 4 ---- _ru/tour/annotations.md | 5 ----- _ru/tour/automatic-closures.md | 2 -- _ru/tour/basics.md | 5 ----- _ru/tour/by-name-parameters.md | 5 ----- _ru/tour/case-classes.md | 5 ----- _ru/tour/classes.md | 5 ----- _ru/tour/compound-types.md | 5 ----- _ru/tour/default-parameter-values.md | 5 ----- _ru/tour/extractor-objects.md | 5 ----- _ru/tour/for-comprehensions.md | 5 ----- _ru/tour/generic-classes.md | 5 ----- _ru/tour/higher-order-functions.md | 5 ----- _ru/tour/implicit-conversions.md | 5 ----- _ru/tour/implicit-parameters.md | 5 ----- _ru/tour/inner-classes.md | 5 ----- _ru/tour/lower-type-bounds.md | 5 ----- _ru/tour/mixin-class-composition.md | 5 ----- _ru/tour/multiple-parameter-lists.md | 5 ----- _ru/tour/named-arguments.md | 5 ----- _ru/tour/nested-functions.md | 5 ----- _ru/tour/operators.md | 5 ----- _ru/tour/package-objects.md | 4 ---- _ru/tour/packages-and-imports.md | 4 ---- _ru/tour/pattern-matching.md | 5 ----- _ru/tour/polymorphic-methods.md | 5 ----- _ru/tour/regular-expression-patterns.md | 5 ----- _ru/tour/self-types.md | 5 ----- _ru/tour/singleton-objects.md | 4 ---- _ru/tour/tour-of-scala.md | 4 ---- _ru/tour/traits.md | 5 ----- _ru/tour/tuples.md | 5 ----- _ru/tour/type-inference.md | 4 ---- _ru/tour/unified-types.md | 5 ----- _ru/tour/upper-type-bounds.md | 4 ---- _ru/tour/variances.md | 5 ----- 153 files changed, 544 deletions(-) diff --git a/_ja/tour/abstract-type-members.md b/_ja/tour/abstract-type-members.md index 2f480833bf..af08eb5c2b 100644 --- a/_ja/tour/abstract-type-members.md +++ b/_ja/tour/abstract-type-members.md @@ -2,16 +2,12 @@ layout: tour title: 抽象型メンバー language: ja - -discourse: true - partof: scala-tour num: 23 next-page: compound-types previous-page: inner-classes topics: abstract type members prerequisite-knowledge: variance, upper-type-bound - --- トレイトや抽象クラスのような抽象型は抽象型メンバーを持つことができます。 diff --git a/_ja/tour/annotations.md b/_ja/tour/annotations.md index d0fad2e82a..90545140fc 100644 --- a/_ja/tour/annotations.md +++ b/_ja/tour/annotations.md @@ -2,15 +2,10 @@ layout: tour title: アノテーション language: ja - -discourse: true - partof: scala-tour - num: 32 next-page: packages-and-imports previous-page: by-name-parameters - --- アノテーションはメタ情報と定義を関連づけます。例えば、メソッドの前のアノテーション`@deprecated`はメソッドが使われたらコンパイラに警告を出力させます。 diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 3b38e98178..0ba4911aa2 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -2,9 +2,6 @@ layout: tour title: 型依存クロージャの自動構築 language: ja - -discourse: true - partof: scala-tour --- diff --git a/_ja/tour/basics.md b/_ja/tour/basics.md index b2b06317bb..09c7033f3a 100644 --- a/_ja/tour/basics.md +++ b/_ja/tour/basics.md @@ -2,15 +2,10 @@ layout: tour title: 基本 language: ja - -discourse: true - partof: scala-tour - num: 2 next-page: unified-types previous-page: tour-of-scala - --- このページでは、Scalaの基本を取り扱います。 diff --git a/_ja/tour/by-name-parameters.md b/_ja/tour/by-name-parameters.md index c3494f5634..b88f6dd617 100644 --- a/_ja/tour/by-name-parameters.md +++ b/_ja/tour/by-name-parameters.md @@ -2,15 +2,10 @@ layout: tour title: 名前渡しパラメータ language: ja - -discourse: true - partof: scala-tour - num: 31 next-page: annotations previous-page: operators - --- *名前渡しのパラメータ*は使用された時に評価されます。それらは*値渡しパラメータ*とは対照的です。名前渡しのパラメータを作るには、単純に`=>`を型の前につけます。 diff --git a/_ja/tour/case-classes.md b/_ja/tour/case-classes.md index 65cce59c9b..2015b843c1 100644 --- a/_ja/tour/case-classes.md +++ b/_ja/tour/case-classes.md @@ -2,16 +2,11 @@ layout: tour title: ケースクラス language: ja - -discourse: true - partof: scala-tour - num: 11 next-page: pattern-matching previous-page: multiple-parameter-lists prerequisite-knowledge: classes, basics, mutability - --- ケースクラスはこれから論じるいくつかの差異はあるものの普通のクラスと似ています。 diff --git a/_ja/tour/classes.md b/_ja/tour/classes.md index e594b4ea37..74bd6c6997 100644 --- a/_ja/tour/classes.md +++ b/_ja/tour/classes.md @@ -2,17 +2,12 @@ layout: tour title: クラス language: ja - -discourse: true - partof: scala-tour - num: 4 next-page: traits previous-page: unified-types topics: classes prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-interpolation, procedures - --- Scalaにおけるクラスはオブジェクトを作るための設計図です。 diff --git a/_ja/tour/compound-types.md b/_ja/tour/compound-types.md index 60be4af3c3..2137ecc432 100644 --- a/_ja/tour/compound-types.md +++ b/_ja/tour/compound-types.md @@ -2,15 +2,10 @@ layout: tour title: 複合型 language: ja - -discourse: true - partof: scala-tour - num: 24 next-page: self-types previous-page: abstract-type-members - --- ときどき、あるオブジェクトの型が、複数の他の型のサブタイプであると表現する必要が生じます。 Scalaでは、これは*複合型*を用いて表現できます。複合型とはオブジェクトの型同士を重ねることです。 diff --git a/_ja/tour/default-parameter-values.md b/_ja/tour/default-parameter-values.md index 1e03cebe50..499f543566 100644 --- a/_ja/tour/default-parameter-values.md +++ b/_ja/tour/default-parameter-values.md @@ -2,16 +2,11 @@ layout: tour title: デフォルト引数 language: ja - -discourse: true - partof: scala-tour - num: 33 next-page: named-arguments previous-page: annotations prerequisite-knowledge: named-arguments, function syntax - --- Scalaはパラメータのデフォルト値を与えることができ、呼び出す側はこれらのパラメータを省略できます。 diff --git a/_ja/tour/extractor-objects.md b/_ja/tour/extractor-objects.md index ba4603a3fa..6dac1d2209 100644 --- a/_ja/tour/extractor-objects.md +++ b/_ja/tour/extractor-objects.md @@ -2,15 +2,10 @@ layout: tour title: 抽出子オブジェクト language: ja - -discourse: true - partof: scala-tour - num: 16 next-page: for-comprehensions previous-page: regular-expression-patterns - --- 抽出子オブジェクトは`unapply`メソッドを持つオブジェクトです。 diff --git a/_ja/tour/for-comprehensions.md b/_ja/tour/for-comprehensions.md index c673135b2b..1600904350 100644 --- a/_ja/tour/for-comprehensions.md +++ b/_ja/tour/for-comprehensions.md @@ -2,15 +2,10 @@ layout: tour title: for内包表記 language: ja - -discourse: true - partof: scala-tour - num: 17 next-page: generic-classes previous-page: extractor-objects - --- Scalaは*シーケンス内包表記*を表現するための軽量な記法を提供します。 diff --git a/_ja/tour/generic-classes.md b/_ja/tour/generic-classes.md index 2de82cc5ce..ad944b8b39 100644 --- a/_ja/tour/generic-classes.md +++ b/_ja/tour/generic-classes.md @@ -2,16 +2,11 @@ layout: tour title: ジェネリッククラス language: ja - -discourse: true - partof: scala-tour - num: 18 next-page: variances previous-page: for-comprehensions assumed-knowledge: classes unified-types - --- ジェネリッククラスはパラメータとして型を1つ受け取るクラスです。それらはコレクションクラスで特に役立ちます。 diff --git a/_ja/tour/higher-order-functions.md b/_ja/tour/higher-order-functions.md index 1740d1ba3d..773ca7170b 100644 --- a/_ja/tour/higher-order-functions.md +++ b/_ja/tour/higher-order-functions.md @@ -2,15 +2,10 @@ layout: tour title: 高階関数 language: ja - -discourse: true - partof: scala-tour - num: 8 next-page: nested-functions previous-page: mixin-class-composition - --- 高階関数は他の関数をパラメーターとして受け取る、もしくは結果として関数を返します。 diff --git a/_ja/tour/implicit-conversions.md b/_ja/tour/implicit-conversions.md index 8ee5a23069..d4de2375f3 100644 --- a/_ja/tour/implicit-conversions.md +++ b/_ja/tour/implicit-conversions.md @@ -2,15 +2,10 @@ layout: tour title: 暗黙の変換 language: ja - -discourse: true - partof: scala-tour - num: 27 next-page: polymorphic-methods previous-page: implicit-parameters - --- 型`S`から型`T`への暗黙の変換は`S => T`という型のimplicit値や、その型に一致するimplicitメソッドで定義されます。 diff --git a/_ja/tour/implicit-parameters.md b/_ja/tour/implicit-parameters.md index 30ff6028df..db43cd76fc 100644 --- a/_ja/tour/implicit-parameters.md +++ b/_ja/tour/implicit-parameters.md @@ -2,15 +2,10 @@ layout: tour title: 暗黙のパラメータ language: ja - -discourse: true - partof: scala-tour - num: 26 next-page: implicit-conversions previous-page: self-types - --- メソッドは _暗黙の_ パラメータのリストを持つことができ、パラメータリストの先頭には _implicit_ キーワードで印をつけます。 diff --git a/_ja/tour/inner-classes.md b/_ja/tour/inner-classes.md index 5d38b1f1f6..2bc8ecf450 100644 --- a/_ja/tour/inner-classes.md +++ b/_ja/tour/inner-classes.md @@ -2,15 +2,10 @@ layout: tour title: 内部クラス language: ja - -discourse: true - partof: scala-tour - num: 22 next-page: abstract-type-members previous-page: lower-type-bounds - --- Scalaではクラスが他のクラスをメンバーとして保持することが可能です。 diff --git a/_ja/tour/lower-type-bounds.md b/_ja/tour/lower-type-bounds.md index 62a15447d3..e72a3773f8 100644 --- a/_ja/tour/lower-type-bounds.md +++ b/_ja/tour/lower-type-bounds.md @@ -2,16 +2,11 @@ layout: tour title: 下限型境界 language: ja - -discourse: true - partof: scala-tour - num: 21 next-page: inner-classes previous-page: upper-type-bounds prerequisite-knowledge: upper-type-bounds, generics, variance - --- [上限型境界](upper-type-bounds.html) は型を別の型のサブタイプに制限しますが、*下限型境界*は型が別の型のスーパータイプであることを宣言します。表現`B >: A`はパラメータ`B`または抽象型`B`が型`A`のスーパータイプであることを表します。ほとんどのケースで`A`はそのクラスの型パラメータであり、`B`はメソッドの型パラメータになります。 diff --git a/_ja/tour/mixin-class-composition.md b/_ja/tour/mixin-class-composition.md index 8b4e26067e..f95ab54cb9 100644 --- a/_ja/tour/mixin-class-composition.md +++ b/_ja/tour/mixin-class-composition.md @@ -2,16 +2,11 @@ layout: tour title: ミックスインを用いたクラス合成 language: ja - -discourse: true - partof: scala-tour - num: 7 next-page: higher-order-functions previous-page: tuples prerequisite-knowledge: inheritance, traits, abstract-classes, unified-types - --- ミックスインはクラスを構成するのに使われるトレイトです。 diff --git a/_ja/tour/multiple-parameter-lists.md b/_ja/tour/multiple-parameter-lists.md index ff267531b8..c9b70ec998 100644 --- a/_ja/tour/multiple-parameter-lists.md +++ b/_ja/tour/multiple-parameter-lists.md @@ -2,15 +2,10 @@ layout: tour title: 複数パラメータリスト(カリー化) language: ja - -discourse: true - partof: scala-tour - num: 10 next-page: case-classes previous-page: nested-functions - --- メソッドは複数のパラメータリストを持てます。 diff --git a/_ja/tour/named-arguments.md b/_ja/tour/named-arguments.md index 8ce70335a9..88bc231fda 100644 --- a/_ja/tour/named-arguments.md +++ b/_ja/tour/named-arguments.md @@ -2,16 +2,11 @@ layout: tour title: 名前付き引数 language: ja - -discourse: true - partof: scala-tour - num: 34 next-page: packages-and-imports previous-page: default-parameter-values prerequisite-knowledge: function-syntax - --- メソッドを呼ぶ時、以下のように引数にパラメータ名でラベル付が可能です。 diff --git a/_ja/tour/nested-functions.md b/_ja/tour/nested-functions.md index 9701e421cc..9fa581bc3e 100644 --- a/_ja/tour/nested-functions.md +++ b/_ja/tour/nested-functions.md @@ -2,15 +2,10 @@ layout: tour title: ネストしたメソッド language: ja - -discourse: true - partof: scala-tour - num: 9 next-page: multiple-parameter-lists previous-page: higher-order-functions - --- Scalaではメソッドの定義をネストする(_訳注:入れ子にする_)ことができます。 diff --git a/_ja/tour/operators.md b/_ja/tour/operators.md index 7df5800aa1..398790b4e0 100644 --- a/_ja/tour/operators.md +++ b/_ja/tour/operators.md @@ -2,16 +2,11 @@ layout: tour title: 演算子 language: ja - -discourse: true - partof: scala-tour - num: 30 next-page: by-name-parameters previous-page: type-inference prerequisite-knowledge: case-classes - --- Scalaでは演算子はメソッドです。パラメータを1つだけ持つメソッドであれば*中置演算子*として使えます。例えば、`+`はドット記法で呼び出せます。 diff --git a/_ja/tour/package-objects.md b/_ja/tour/package-objects.md index 755935d3ef..f2ed9b1d89 100644 --- a/_ja/tour/package-objects.md +++ b/_ja/tour/package-objects.md @@ -2,11 +2,7 @@ layout: tour title: パッケージオブジェクト language: ja - -discourse: true - partof: scala-tour - num: 36 previous-page: packages-and-imports --- diff --git a/_ja/tour/packages-and-imports.md b/_ja/tour/packages-and-imports.md index 8e44239b05..4e94731644 100644 --- a/_ja/tour/packages-and-imports.md +++ b/_ja/tour/packages-and-imports.md @@ -2,11 +2,7 @@ layout: tour title: パッケージとインポート language: ja - -discourse: true - partof: scala-tour - num: 35 previous-page: named-arguments next-page: package-objects diff --git a/_ja/tour/pattern-matching.md b/_ja/tour/pattern-matching.md index 9e1f5d9692..23c997ca91 100644 --- a/_ja/tour/pattern-matching.md +++ b/_ja/tour/pattern-matching.md @@ -2,17 +2,11 @@ layout: tour title: パターンマッチング language: ja - -discourse: true - partof: scala-tour - num: 12 - next-page: singleton-objects previous-page: case-classes prerequisite-knowledge: case-classes, string-interpolation, subtyping - --- パターンマッチングは値をパターンに照合するための仕組みです。 diff --git a/_ja/tour/polymorphic-methods.md b/_ja/tour/polymorphic-methods.md index 6143ef2612..4bab5f63bd 100644 --- a/_ja/tour/polymorphic-methods.md +++ b/_ja/tour/polymorphic-methods.md @@ -2,17 +2,11 @@ layout: tour title: ポリモーフィックメソッド language: ja - -discourse: true - partof: scala-tour - num: 28 - next-page: type-inference previous-page: implicit-conversions prerequisite-knowledge: unified-types - --- Scalaのメソッドは値と同様に型によってパラメータ化することができます。構文はジェネリッククラスの構文と似ています。 diff --git a/_ja/tour/regular-expression-patterns.md b/_ja/tour/regular-expression-patterns.md index 05882529c0..79cf565c9f 100644 --- a/_ja/tour/regular-expression-patterns.md +++ b/_ja/tour/regular-expression-patterns.md @@ -2,16 +2,10 @@ layout: tour title: 正規表現パターン language: ja - -discourse: true - partof: scala-tour - num: 15 - next-page: extractor-objects previous-page: singleton-objects - --- 正規表現はデータの中からパターン(またはその欠如)を探すために使うことができる文字列です。 どんな文字列も`.r`メソッドを使うことで、正規表現に変換できます。 diff --git a/_ja/tour/self-types.md b/_ja/tour/self-types.md index cb585dc09e..7ffa6745ec 100644 --- a/_ja/tour/self-types.md +++ b/_ja/tour/self-types.md @@ -2,17 +2,12 @@ layout: tour title: 自分型 language: ja - -discourse: true - partof: scala-tour - num: 25 next-page: implicit-parameters previous-page: compound-types topics: self-types prerequisite-knowledge: nested-classes, mixin-class-composition - --- 自分型は、直接継承していなくてもトレイトが他のトレイトにミックスインされていることを宣言する方法です。 これにより依存先のメンバーをimportなしで利用できます。 diff --git a/_ja/tour/singleton-objects.md b/_ja/tour/singleton-objects.md index 69ce1aeede..0414291909 100644 --- a/_ja/tour/singleton-objects.md +++ b/_ja/tour/singleton-objects.md @@ -2,13 +2,8 @@ layout: tour title: シングルトンオブジェクト language: ja - -discourse: true - partof: scala-tour - num: 13 - next-page: regular-expression-patterns previous-page: pattern-matching prerequisite-knowledge: classes, methods, private-methods, packages, option diff --git a/_ja/tour/tour-of-scala.md b/_ja/tour/tour-of-scala.md index ff2d026686..9e5d2b9860 100644 --- a/_ja/tour/tour-of-scala.md +++ b/_ja/tour/tour-of-scala.md @@ -2,15 +2,9 @@ layout: tour title: 前書き language: ja - -discourse: true - partof: scala-tour - num: 1 - next-page: basics - --- ## ようこそツアーへ diff --git a/_ja/tour/traits.md b/_ja/tour/traits.md index 81b7dc7046..1738b0fc0d 100644 --- a/_ja/tour/traits.md +++ b/_ja/tour/traits.md @@ -2,17 +2,12 @@ layout: tour title: トレイト language: ja - -discourse: true - partof: scala-tour - num: 5 next-page: tuples previous-page: classes topics: traits prerequisite-knowledge: expressions, classes, generics, objects, companion-objects - --- トレイトはクラス間でインターフェースとフィールドを共有するために使います。それらはJava 8のインターフェースと似ています。 diff --git a/_ja/tour/tuples.md b/_ja/tour/tuples.md index 7729138914..e3c2f1e0f7 100644 --- a/_ja/tour/tuples.md +++ b/_ja/tour/tuples.md @@ -2,16 +2,11 @@ layout: tour title: タプル language: ja - -discourse: true - partof: scala-tour - num: 6 next-page: mixin-class-composition previous-page: traits topics: tuples - --- Scalaではタプルは決まった数の要素を含む値であり、各要素はそれぞれの型を持ちます。 diff --git a/_ja/tour/type-inference.md b/_ja/tour/type-inference.md index 2db0e440b9..5973da20a2 100644 --- a/_ja/tour/type-inference.md +++ b/_ja/tour/type-inference.md @@ -2,11 +2,7 @@ layout: tour title: 型推論 language: ja - -discourse: true - partof: scala-tour - num: 29 next-page: operators previous-page: polymorphic-methods diff --git a/_ja/tour/unified-types.md b/_ja/tour/unified-types.md index 8f9710b62a..a12895c677 100644 --- a/_ja/tour/unified-types.md +++ b/_ja/tour/unified-types.md @@ -2,16 +2,11 @@ layout: tour title: 統合された型 language: ja - -discourse: true - partof: scala-tour - num: 3 next-page: classes previous-page: basics prerequisite-knowledge: classes, basics - --- Scalaでは数値や関数を含め、全ての値は型を持ちます。 以下の図は型階層の一部を説明しています。 diff --git a/_ja/tour/upper-type-bounds.md b/_ja/tour/upper-type-bounds.md index 7d8ac4df9a..8dfe6ca8ac 100644 --- a/_ja/tour/upper-type-bounds.md +++ b/_ja/tour/upper-type-bounds.md @@ -2,15 +2,11 @@ layout: tour title: 上限型境界 language: ja - -discourse: true - partof: scala-tour categories: tour num: 20 next-page: lower-type-bounds previous-page: variances - --- Scalaでは [型パラメータ](generic-classes.html)と[抽象型メンバー](abstract-type-members.html) は型境界による制約をかけることができます。 diff --git a/_ja/tour/variances.md b/_ja/tour/variances.md index c7eb10304e..314f8c2e48 100644 --- a/_ja/tour/variances.md +++ b/_ja/tour/variances.md @@ -2,15 +2,10 @@ layout: tour title: 変位指定 language: ja - -discourse: true - partof: scala-tour - num: 19 next-page: upper-type-bounds previous-page: generic-classes - --- 変位指定は複合型の間の継承関係とそれらの型パラメータ間の継承関係の相関です。 diff --git a/_ja/tutorials/scala-for-java-programmers.md b/_ja/tutorials/scala-for-java-programmers.md index b49113ff72..a2076100b1 100644 --- a/_ja/tutorials/scala-for-java-programmers.md +++ b/_ja/tutorials/scala-for-java-programmers.md @@ -1,10 +1,7 @@ --- layout: singlepage-overview title: JavaプログラマーのためのScalaチュートリアル - partof: scala-for-java-programmers - -discourse: false language: ja --- diff --git a/_overviews/scala-book/abstract-classes.md b/_overviews/scala-book/abstract-classes.md index a5ec3b96fa..ed8dc3b147 100644 --- a/_overviews/scala-book/abstract-classes.md +++ b/_overviews/scala-book/abstract-classes.md @@ -5,7 +5,6 @@ title: Abstract Classes description: This page shows how to use abstract classes, including when and why you should use abstract classes. partof: scala_book overview-name: Scala Book -discourse: true num: 27 outof: 54 previous-page: traits-abstract-mixins diff --git a/_overviews/scala-book/anonymous-functions.md b/_overviews/scala-book/anonymous-functions.md index bbd7bc8d8d..de9c9ebd14 100644 --- a/_overviews/scala-book/anonymous-functions.md +++ b/_overviews/scala-book/anonymous-functions.md @@ -5,7 +5,6 @@ title: Anonymous Functions description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. partof: scala_book overview-name: Scala Book -discourse: true num: 34 outof: 54 previous-page: set-class diff --git a/_overviews/scala-book/arraybuffer-examples.md b/_overviews/scala-book/arraybuffer-examples.md index 8d4dd8ef53..1f0206e58f 100644 --- a/_overviews/scala-book/arraybuffer-examples.md +++ b/_overviews/scala-book/arraybuffer-examples.md @@ -5,7 +5,6 @@ title: The ArrayBuffer Class description: This page provides examples of how to use the Scala ArrayBuffer class, including adding and removing elements. partof: scala_book overview-name: Scala Book -discourse: true num: 29 outof: 54 previous-page: collections-101 diff --git a/_overviews/scala-book/built-in-types.md b/_overviews/scala-book/built-in-types.md index 209b1b8f0b..1567d13970 100644 --- a/_overviews/scala-book/built-in-types.md +++ b/_overviews/scala-book/built-in-types.md @@ -5,7 +5,6 @@ title: A Few Built-In Types description: A brief introduction to Scala's built-in types. partof: scala_book overview-name: Scala Book -discourse: true num: 10 outof: 54 previous-page: type-is-optional diff --git a/_overviews/scala-book/case-classes.md b/_overviews/scala-book/case-classes.md index 8722d4c5ae..33db4a9a7f 100644 --- a/_overviews/scala-book/case-classes.md +++ b/_overviews/scala-book/case-classes.md @@ -5,7 +5,6 @@ title: Case Classes description: This lesson provides an introduction to 'case classes' in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 49 outof: 54 previous-page: companion-objects diff --git a/_overviews/scala-book/case-objects.md b/_overviews/scala-book/case-objects.md index 1b7426f12a..ca6a5f155a 100644 --- a/_overviews/scala-book/case-objects.md +++ b/_overviews/scala-book/case-objects.md @@ -5,7 +5,6 @@ title: Case Objects description: This lesson introduces Scala 'case objects', which are used to create singletons with a few additional features. partof: scala_book overview-name: Scala Book -discourse: true num: 50 outof: 54 previous-page: case-classes diff --git a/_overviews/scala-book/classes-aux-constructors.md b/_overviews/scala-book/classes-aux-constructors.md index a66a4b4d80..d3af412a53 100644 --- a/_overviews/scala-book/classes-aux-constructors.md +++ b/_overviews/scala-book/classes-aux-constructors.md @@ -5,7 +5,6 @@ title: Auxiliary Class Constructors description: This page shows how to write auxiliary Scala class constructors, including several examples of the syntax. partof: scala_book overview-name: Scala Book -discourse: true num: 20 outof: 54 previous-page: classes diff --git a/_overviews/scala-book/classes.md b/_overviews/scala-book/classes.md index bc4fe65b66..c4861bc7c2 100644 --- a/_overviews/scala-book/classes.md +++ b/_overviews/scala-book/classes.md @@ -5,7 +5,6 @@ title: Scala Classes description: This page shows examples of how to create Scala classes, including the basic Scala class constructor. partof: scala_book overview-name: Scala Book -discourse: true num: 19 outof: 54 previous-page: try-catch-finally diff --git a/_overviews/scala-book/collections-101.md b/_overviews/scala-book/collections-101.md index 6df136b528..b98a72d116 100644 --- a/_overviews/scala-book/collections-101.md +++ b/_overviews/scala-book/collections-101.md @@ -5,7 +5,6 @@ title: Scala Collections description: This page provides an introduction to the Scala collections classes, including Vector, List, ArrayBuffer, Map, Set, and more. partof: scala_book overview-name: Scala Book -discourse: true num: 28 outof: 54 previous-page: abstract-classes diff --git a/_overviews/scala-book/collections-maps.md b/_overviews/scala-book/collections-maps.md index 95e890bbc3..84a9f065c4 100644 --- a/_overviews/scala-book/collections-maps.md +++ b/_overviews/scala-book/collections-maps.md @@ -5,7 +5,6 @@ title: Common Map Methods description: This page shows examples of the most common methods that are available on Scala Maps. partof: scala_book overview-name: Scala Book -discourse: true num: 36 outof: 54 previous-page: collections-methods diff --git a/_overviews/scala-book/collections-methods.md b/_overviews/scala-book/collections-methods.md index 7bd8d9a15a..e888179940 100644 --- a/_overviews/scala-book/collections-methods.md +++ b/_overviews/scala-book/collections-methods.md @@ -5,7 +5,6 @@ title: Common Sequence Methods description: This page shows examples of the most common methods that are available on the Scala sequences (collections classes). partof: scala_book overview-name: Scala Book -discourse: true num: 35 outof: 54 previous-page: anonymous-functions diff --git a/_overviews/scala-book/command-line-io.md b/_overviews/scala-book/command-line-io.md index ffb35f698e..14bf2901af 100644 --- a/_overviews/scala-book/command-line-io.md +++ b/_overviews/scala-book/command-line-io.md @@ -5,7 +5,6 @@ title: Command-Line I/O description: An introduction to command-line I/O in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 12 outof: 54 previous-page: two-notes-about-strings diff --git a/_overviews/scala-book/companion-objects.md b/_overviews/scala-book/companion-objects.md index 6babb21eb9..f024a8a2d5 100644 --- a/_overviews/scala-book/companion-objects.md +++ b/_overviews/scala-book/companion-objects.md @@ -5,7 +5,6 @@ title: Companion Objects description: This lesson provides an introduction to 'companion objects' in Scala, including writing 'apply' and 'unapply' methods. partof: scala_book overview-name: Scala Book -discourse: true num: 48 outof: 54 previous-page: no-null-values diff --git a/_overviews/scala-book/concurrency-signpost.md b/_overviews/scala-book/concurrency-signpost.md index 1629700299..d3435c4ede 100644 --- a/_overviews/scala-book/concurrency-signpost.md +++ b/_overviews/scala-book/concurrency-signpost.md @@ -5,7 +5,6 @@ title: Concurrency description: An introduction to concurrency in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 52 outof: 54 previous-page: functional-error-handling diff --git a/_overviews/scala-book/constructors-default-values.md b/_overviews/scala-book/constructors-default-values.md index aa4429305e..b54da93584 100644 --- a/_overviews/scala-book/constructors-default-values.md +++ b/_overviews/scala-book/constructors-default-values.md @@ -5,7 +5,6 @@ title: Supplying Default Values for Constructor Parameters description: This page shows how to provide default values for Scala constructor parameters, with several examples. partof: scala_book overview-name: Scala Book -discourse: true num: 21 outof: 54 previous-page: classes-aux-constructors diff --git a/_overviews/scala-book/control-structures.md b/_overviews/scala-book/control-structures.md index 813a05face..9d21b18eb3 100644 --- a/_overviews/scala-book/control-structures.md +++ b/_overviews/scala-book/control-structures.md @@ -5,7 +5,6 @@ title: Control Structures description: This page provides an introduction to Scala's control structures, including if/then/else, for loops, try/catch/finally, etc. partof: scala_book overview-name: Scala Book -discourse: true num: 13 outof: 54 previous-page: command-line-io diff --git a/_overviews/scala-book/enumerations-pizza-class.md b/_overviews/scala-book/enumerations-pizza-class.md index 31625129f0..d4052378bb 100644 --- a/_overviews/scala-book/enumerations-pizza-class.md +++ b/_overviews/scala-book/enumerations-pizza-class.md @@ -5,7 +5,6 @@ title: Enumerations (and a Complete Pizza Class) description: This page introduces Scala enumerations, and further shows how to create a complete OOP 'Pizza' class that uses those enumerations. partof: scala_book overview-name: Scala Book -discourse: true num: 23 outof: 54 previous-page: methods-first-look diff --git a/_overviews/scala-book/for-expressions.md b/_overviews/scala-book/for-expressions.md index 7977777872..4cd666ef42 100644 --- a/_overviews/scala-book/for-expressions.md +++ b/_overviews/scala-book/for-expressions.md @@ -5,7 +5,6 @@ title: for Expressions description: This page shows how to use Scala 'for' expressions (also known as 'for-expressions'), including examples of how to use it with the 'yield' keyword. partof: scala_book overview-name: Scala Book -discourse: true num: 16 outof: 54 previous-page: for-loops diff --git a/_overviews/scala-book/for-loops.md b/_overviews/scala-book/for-loops.md index 5eef6cc279..ef382270f2 100644 --- a/_overviews/scala-book/for-loops.md +++ b/_overviews/scala-book/for-loops.md @@ -5,7 +5,6 @@ title: for Loops description: This page provides an introduction to the Scala 'for' loop, including how to iterate over Scala collections. partof: scala_book overview-name: Scala Book -discourse: true num: 15 outof: 54 previous-page: if-then-else-construct diff --git a/_overviews/scala-book/functional-error-handling.md b/_overviews/scala-book/functional-error-handling.md index 00a448ccc0..8e779a2bc2 100644 --- a/_overviews/scala-book/functional-error-handling.md +++ b/_overviews/scala-book/functional-error-handling.md @@ -5,7 +5,6 @@ title: Functional Error Handling in Scala description: This lesson takes a look at error handling with functional programming in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 51 outof: 54 previous-page: case-objects diff --git a/_overviews/scala-book/functional-programming.md b/_overviews/scala-book/functional-programming.md index aa0581cf87..dee9cc4533 100644 --- a/_overviews/scala-book/functional-programming.md +++ b/_overviews/scala-book/functional-programming.md @@ -5,7 +5,6 @@ title: Functional Programming description: This lesson begins a second on 'An introduction to functional programming in Scala'. partof: scala_book overview-name: Scala Book -discourse: true num: 44 outof: 54 previous-page: sbt-scalatest-bdd diff --git a/_overviews/scala-book/futures.md b/_overviews/scala-book/futures.md index 9324b0ddf9..e585ff2819 100644 --- a/_overviews/scala-book/futures.md +++ b/_overviews/scala-book/futures.md @@ -5,7 +5,6 @@ title: Scala Futures description: This page provides an introduction to Futures in Scala, including Future callback methods. partof: scala_book overview-name: Scala Book -discourse: true num: 53 outof: 54 previous-page: concurrency-signpost diff --git a/_overviews/scala-book/hello-world-1.md b/_overviews/scala-book/hello-world-1.md index c9793a2376..28aa21f19b 100644 --- a/_overviews/scala-book/hello-world-1.md +++ b/_overviews/scala-book/hello-world-1.md @@ -5,7 +5,6 @@ title: Hello, World description: This page shares a Scala 'Hello, world' example. partof: scala_book overview-name: Scala Book -discourse: true num: 5 outof: 54 previous-page: scala-features diff --git a/_overviews/scala-book/hello-world-2.md b/_overviews/scala-book/hello-world-2.md index d07b7da00f..76d1bf053c 100644 --- a/_overviews/scala-book/hello-world-2.md +++ b/_overviews/scala-book/hello-world-2.md @@ -5,7 +5,6 @@ title: Hello, World - Version 2 description: This is a second Scala 'Hello, World' example. partof: scala_book overview-name: Scala Book -discourse: true num: 6 outof: 54 previous-page: hello-world-1 diff --git a/_overviews/scala-book/if-then-else-construct.md b/_overviews/scala-book/if-then-else-construct.md index 6fd09ef879..bd720f758a 100644 --- a/_overviews/scala-book/if-then-else-construct.md +++ b/_overviews/scala-book/if-then-else-construct.md @@ -5,7 +5,6 @@ title: The if/then/else Construct description: This page demonstrates Scala's if/then/else construct, including several examples you can try in the REPL. partof: scala_book overview-name: Scala Book -discourse: true num: 14 outof: 54 previous-page: control-structures diff --git a/_overviews/scala-book/list-class.md b/_overviews/scala-book/list-class.md index 1a606afc98..0e4e324e89 100644 --- a/_overviews/scala-book/list-class.md +++ b/_overviews/scala-book/list-class.md @@ -5,7 +5,6 @@ title: The List Class description: This page provides examples of the Scala List class, including how to add and remove elements from a List. partof: scala_book overview-name: Scala Book -discourse: true num: 30 outof: 54 previous-page: arraybuffer-examples diff --git a/_overviews/scala-book/map-class.md b/_overviews/scala-book/map-class.md index 4a7d48db98..34f0824fae 100644 --- a/_overviews/scala-book/map-class.md +++ b/_overviews/scala-book/map-class.md @@ -5,7 +5,6 @@ title: The Map Class description: This page provides examples of the Scala 'Map' class, including how to add and remove elements from a Map, and iterate over Map elements. partof: scala_book overview-name: Scala Book -discourse: true num: 32 outof: 54 previous-page: vector-class diff --git a/_overviews/scala-book/match-expressions.md b/_overviews/scala-book/match-expressions.md index 4b54dfb35c..60cc0d92ae 100644 --- a/_overviews/scala-book/match-expressions.md +++ b/_overviews/scala-book/match-expressions.md @@ -5,7 +5,6 @@ title: match Expressions description: This page shows examples of the Scala 'match' expression, including how to write match/case expressions. partof: scala_book overview-name: Scala Book -discourse: true num: 17 outof: 54 previous-page: for-expressions diff --git a/_overviews/scala-book/methods-first-look.md b/_overviews/scala-book/methods-first-look.md index 7e10bdfd77..348c66f56f 100644 --- a/_overviews/scala-book/methods-first-look.md +++ b/_overviews/scala-book/methods-first-look.md @@ -5,7 +5,6 @@ title: A First Look at Scala Methods description: This page provides a first look at how to write Scala methods, including how to test them in the REPL. partof: scala_book overview-name: Scala Book -discourse: true num: 22 outof: 54 previous-page: constructors-default-values diff --git a/_overviews/scala-book/misc.md b/_overviews/scala-book/misc.md index 61c19bd1b2..07f511305c 100644 --- a/_overviews/scala-book/misc.md +++ b/_overviews/scala-book/misc.md @@ -5,7 +5,6 @@ title: A Few Miscellaneous Items description: A few miscellaneous items about Scala partof: scala_book overview-name: Scala Book -discourse: true num: 37 outof: 54 previous-page: collections-maps diff --git a/_overviews/scala-book/no-null-values.md b/_overviews/scala-book/no-null-values.md index 757fc62670..194348c246 100644 --- a/_overviews/scala-book/no-null-values.md +++ b/_overviews/scala-book/no-null-values.md @@ -5,7 +5,6 @@ title: No Null Values description: This lesson demonstrates the Scala Option, Some, and None classes, including how to use them instead of null values. partof: scala_book overview-name: Scala Book -discourse: true num: 47 outof: 54 previous-page: passing-functions-around diff --git a/_overviews/scala-book/oop-pizza-example.md b/_overviews/scala-book/oop-pizza-example.md index 7d50686e71..c70df45e3f 100644 --- a/_overviews/scala-book/oop-pizza-example.md +++ b/_overviews/scala-book/oop-pizza-example.md @@ -5,7 +5,6 @@ title: An OOP Example description: This lesson shares an example of some OOP-style classes for a pizza restaurant order entry system, including Pizza, Topping, and Order classes. partof: scala_book overview-name: Scala Book -discourse: true num: 39 outof: 54 previous-page: tuples diff --git a/_overviews/scala-book/passing-functions-around.md b/_overviews/scala-book/passing-functions-around.md index 2700ea06c7..80c6cd2f2b 100644 --- a/_overviews/scala-book/passing-functions-around.md +++ b/_overviews/scala-book/passing-functions-around.md @@ -5,7 +5,6 @@ title: Passing Functions Around description: Like a good functional programming language, Scala lets you use functions just like other variables, including passing them into other functions. partof: scala_book overview-name: Scala Book -discourse: true num: 46 outof: 54 previous-page: pure-functions diff --git a/_overviews/scala-book/preliminaries.md b/_overviews/scala-book/preliminaries.md index e8057e37d9..ac3af5ea33 100644 --- a/_overviews/scala-book/preliminaries.md +++ b/_overviews/scala-book/preliminaries.md @@ -5,7 +5,6 @@ title: Preliminaries description: A few things to know about getting started with Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 3 outof: 54 previous-page: prelude-taste-of-scala diff --git a/_overviews/scala-book/prelude-taste-of-scala.md b/_overviews/scala-book/prelude-taste-of-scala.md index 1317561825..aba0111219 100644 --- a/_overviews/scala-book/prelude-taste-of-scala.md +++ b/_overviews/scala-book/prelude-taste-of-scala.md @@ -5,7 +5,6 @@ title: Prelude꞉ A Taste of Scala description: This page shares a Taste Of Scala example, quickly covering Scala's main features. partof: scala_book overview-name: Scala Book -discourse: true num: 2 outof: 54 previous-page: introduction diff --git a/_overviews/scala-book/pure-functions.md b/_overviews/scala-book/pure-functions.md index 97c6ef6fb9..5bbb4f50c2 100644 --- a/_overviews/scala-book/pure-functions.md +++ b/_overviews/scala-book/pure-functions.md @@ -5,7 +5,6 @@ title: Pure Functions description: This lesson provides an introduction to writing pure functions in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 45 outof: 54 previous-page: functional-programming diff --git a/_overviews/scala-book/sbt-scalatest-bdd.md b/_overviews/scala-book/sbt-scalatest-bdd.md index ee20a8490e..6bb134abdb 100644 --- a/_overviews/scala-book/sbt-scalatest-bdd.md +++ b/_overviews/scala-book/sbt-scalatest-bdd.md @@ -5,7 +5,6 @@ title: Writing BDD Style Tests with ScalaTest and sbt description: This lesson shows how to write ScalaTest unit tests with sbt in a behavior-driven development (TDD) style. partof: scala_book overview-name: Scala Book -discourse: true num: 43 outof: 54 previous-page: sbt-scalatest-tdd diff --git a/_overviews/scala-book/sbt-scalatest-intro.md b/_overviews/scala-book/sbt-scalatest-intro.md index bf40ba8c6c..e7f8d20bed 100644 --- a/_overviews/scala-book/sbt-scalatest-intro.md +++ b/_overviews/scala-book/sbt-scalatest-intro.md @@ -5,7 +5,6 @@ title: sbt and ScalaTest description: In this lesson we'll start to introduce sbt and ScalaTest, two tools commonly used on Scala projects. partof: scala_book overview-name: Scala Book -discourse: true num: 40 outof: 54 previous-page: oop-pizza-example diff --git a/_overviews/scala-book/sbt-scalatest-tdd.md b/_overviews/scala-book/sbt-scalatest-tdd.md index 7214566a09..724d9c1728 100644 --- a/_overviews/scala-book/sbt-scalatest-tdd.md +++ b/_overviews/scala-book/sbt-scalatest-tdd.md @@ -5,7 +5,6 @@ title: Using ScalaTest with sbt description: This lesson shows how to write ScalaTest unit tests with sbt in a test-driven development (TDD) style. partof: scala_book overview-name: Scala Book -discourse: true num: 42 outof: 54 previous-page: scala-build-tool-sbt diff --git a/_overviews/scala-book/scala-build-tool-sbt.md b/_overviews/scala-book/scala-build-tool-sbt.md index 8986433976..aefb28ecea 100644 --- a/_overviews/scala-book/scala-build-tool-sbt.md +++ b/_overviews/scala-book/scala-build-tool-sbt.md @@ -5,7 +5,6 @@ title: The most used scala build tool (sbt) description: This page provides an introduction to the Scala Build Tool, sbt, including a simple 'Hello, world' project. partof: scala_book overview-name: Scala Book -discourse: true num: 41 outof: 54 previous-page: sbt-scalatest-intro diff --git a/_overviews/scala-book/scala-features.md b/_overviews/scala-book/scala-features.md index eee55bd089..c7d7387d4a 100644 --- a/_overviews/scala-book/scala-features.md +++ b/_overviews/scala-book/scala-features.md @@ -5,7 +5,6 @@ title: Scala Features description: TODO partof: scala_book overview-name: Scala Book -discourse: true num: 4 outof: 54 previous-page: preliminaries diff --git a/_overviews/scala-book/scala-repl.md b/_overviews/scala-book/scala-repl.md index c1ced1f219..062ca12b7f 100644 --- a/_overviews/scala-book/scala-repl.md +++ b/_overviews/scala-book/scala-repl.md @@ -5,7 +5,6 @@ title: The Scala REPL description: This page shares an introduction to the Scala REPL. partof: scala_book overview-name: Scala Book -discourse: true num: 7 outof: 54 previous-page: hello-world-2 diff --git a/_overviews/scala-book/set-class.md b/_overviews/scala-book/set-class.md index 55fefb31d0..dc69cb2ae4 100644 --- a/_overviews/scala-book/set-class.md +++ b/_overviews/scala-book/set-class.md @@ -5,7 +5,6 @@ title: The Set Class description: This page provides examples of the Scala 'Set' class, including how to add and remove elements from a Set, and iterate over Set elements. partof: scala_book overview-name: Scala Book -discourse: true num: 33 outof: 54 previous-page: map-class diff --git a/_overviews/scala-book/traits-abstract-mixins.md b/_overviews/scala-book/traits-abstract-mixins.md index eeecb67aee..db3ab56d63 100644 --- a/_overviews/scala-book/traits-abstract-mixins.md +++ b/_overviews/scala-book/traits-abstract-mixins.md @@ -5,7 +5,6 @@ title: Using Scala Traits Like Abstract Classes description: This page shows how to use Scala traits just like abstract classes in Java, with examples of concrete and abstract methods. partof: scala_book overview-name: Scala Book -discourse: true num: 26 outof: 54 previous-page: traits-interfaces diff --git a/_overviews/scala-book/traits-interfaces.md b/_overviews/scala-book/traits-interfaces.md index a10ed18a61..f422f158bc 100644 --- a/_overviews/scala-book/traits-interfaces.md +++ b/_overviews/scala-book/traits-interfaces.md @@ -5,7 +5,6 @@ title: Using Scala Traits as Interfaces description: This page shows how to use Scala traits just like Java interfaces, including several examples. partof: scala_book overview-name: Scala Book -discourse: true num: 25 outof: 54 previous-page: traits-intro diff --git a/_overviews/scala-book/traits-intro.md b/_overviews/scala-book/traits-intro.md index a6d1db0f26..75656b4a64 100644 --- a/_overviews/scala-book/traits-intro.md +++ b/_overviews/scala-book/traits-intro.md @@ -5,7 +5,6 @@ title: Scala Traits and Abstract Classes description: An introduction to Scala traits and abstract classes. partof: scala_book overview-name: Scala Book -discourse: true num: 24 outof: 54 previous-page: enumerations-pizza-class diff --git a/_overviews/scala-book/try-catch-finally.md b/_overviews/scala-book/try-catch-finally.md index 5dee7890a4..607bf3fc0b 100644 --- a/_overviews/scala-book/try-catch-finally.md +++ b/_overviews/scala-book/try-catch-finally.md @@ -5,7 +5,6 @@ title: try/catch/finally Expressions description: This page shows how to use Scala's try/catch/finally construct, including several complete examples. partof: scala_book overview-name: Scala Book -discourse: true num: 18 outof: 54 previous-page: match-expressions diff --git a/_overviews/scala-book/tuples.md b/_overviews/scala-book/tuples.md index c2eb8e4225..568037274b 100644 --- a/_overviews/scala-book/tuples.md +++ b/_overviews/scala-book/tuples.md @@ -5,7 +5,6 @@ title: Tuples description: This page is an introduction to the Scala 'tuple' data type, showing examples of how to use tuples in your Scala code. partof: scala_book overview-name: Scala Book -discourse: true num: 38 outof: 54 previous-page: misc diff --git a/_overviews/scala-book/two-notes-about-strings.md b/_overviews/scala-book/two-notes-about-strings.md index fdcbd7a29a..dea6f3e643 100644 --- a/_overviews/scala-book/two-notes-about-strings.md +++ b/_overviews/scala-book/two-notes-about-strings.md @@ -5,7 +5,6 @@ title: Two Notes About Strings description: This page shares two important notes about strings in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 11 outof: 54 previous-page: built-in-types diff --git a/_overviews/scala-book/two-types-variables.md b/_overviews/scala-book/two-types-variables.md index 678c89dc3d..f369c66a87 100644 --- a/_overviews/scala-book/two-types-variables.md +++ b/_overviews/scala-book/two-types-variables.md @@ -5,7 +5,6 @@ title: Two Types of Variables description: Scala has two types of variables, val and var. partof: scala_book overview-name: Scala Book -discourse: true num: 8 outof: 54 previous-page: scala-repl diff --git a/_overviews/scala-book/type-is-optional.md b/_overviews/scala-book/type-is-optional.md index 3b21654433..0d8b0a1c93 100644 --- a/_overviews/scala-book/type-is-optional.md +++ b/_overviews/scala-book/type-is-optional.md @@ -5,7 +5,6 @@ title: The Type is Optional description: A note about explicit and implicit data type declarations in Scala. partof: scala_book overview-name: Scala Book -discourse: true num: 9 outof: 54 previous-page: two-types-variables diff --git a/_overviews/scala-book/vector-class.md b/_overviews/scala-book/vector-class.md index 15981e7904..1c17c9183c 100644 --- a/_overviews/scala-book/vector-class.md +++ b/_overviews/scala-book/vector-class.md @@ -5,7 +5,6 @@ title: The Vector Class description: This page provides examples of the Scala 'Vector' class, including how to add and remove elements from a Vector. partof: scala_book overview-name: Scala Book -discourse: true num: 31 outof: 54 previous-page: list-class diff --git a/_overviews/scala-book/where-next.md b/_overviews/scala-book/where-next.md index 4b045d7182..6bce221a97 100644 --- a/_overviews/scala-book/where-next.md +++ b/_overviews/scala-book/where-next.md @@ -5,7 +5,6 @@ title: Where To Go Next description: Where to go next after reading the Scala Book partof: scala_book overview-name: Scala Book -discourse: true num: 54 outof: 54 previous-page: futures diff --git a/_overviews/scaladoc/contribute.md b/_overviews/scaladoc/contribute.md index dc0af2ce57..0d8999574a 100644 --- a/_overviews/scaladoc/contribute.md +++ b/_overviews/scaladoc/contribute.md @@ -1,14 +1,9 @@ --- layout: multipage-overview title: Contributing to Scaladoc - -discourse: true - partof: scaladoc overview-name: Scaladoc - num: 5 - permalink: /overviews/scaladoc/:title.html --- diff --git a/_overviews/scaladoc/generate.md b/_overviews/scaladoc/generate.md index 98c0942ffe..0fbd38d533 100644 --- a/_overviews/scaladoc/generate.md +++ b/_overviews/scaladoc/generate.md @@ -1,14 +1,9 @@ --- layout: multipage-overview title: Generating Scaladoc - -discourse: true - partof: scaladoc overview-name: Scaladoc - num: 4 - permalink: /overviews/scaladoc/:title.html --- diff --git a/_ru/overviews/collections-2.13/arrays.md b/_ru/overviews/collections-2.13/arrays.md index 7e71da1027..dba3fb4e08 100644 --- a/_ru/overviews/collections-2.13/arrays.md +++ b/_ru/overviews/collections-2.13/arrays.md @@ -1,17 +1,12 @@ --- layout: multipage-overview title: Массивы - -discourse: true - partof: collections-213 overview-name: Collections - num: 10 previous-page: concrete-mutable-collection-classes next-page: strings language: ru - --- [Массивы](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/Array.html) особый вид коллекций в Scala. diff --git a/_ru/overviews/collections-2.13/concrete-immutable-collection-classes.md b/_ru/overviews/collections-2.13/concrete-immutable-collection-classes.md index 6da8bcc3e1..0c6a672ae0 100644 --- a/_ru/overviews/collections-2.13/concrete-immutable-collection-classes.md +++ b/_ru/overviews/collections-2.13/concrete-immutable-collection-classes.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Реализации Неизменяемых Коллекций - -discourse: true - partof: collections-213 overview-name: Collections - previous-page: maps next-page: concrete-mutable-collection-classes - num: 8 language: ru - --- Scala предлагает множество конечных реализаций неизменяемых коллекций. Они отличаются реализуемыми трейтами (мапы (map), множества(set), последовательности(seq)), они могут быть бесконечными, и различаются производительностью операций. Вот некоторые из наиболее распространенных неизменяемых типов коллекций, используемых в Scala. diff --git a/_ru/overviews/collections-2.13/concrete-mutable-collection-classes.md b/_ru/overviews/collections-2.13/concrete-mutable-collection-classes.md index 7152037ce9..a65910b05a 100644 --- a/_ru/overviews/collections-2.13/concrete-mutable-collection-classes.md +++ b/_ru/overviews/collections-2.13/concrete-mutable-collection-classes.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Реализации Изменяемых Коллекций - -discourse: true - partof: collections-213 overview-name: Collections - num: 9 previous-page: concrete-immutable-collection-classes next-page: arrays - language: ru - --- Вы уже успели увидеть наиболее часто используемые неизменяемые типы коллекции, которые есть в стандартной библиотеке Scala. Настало время посмотреть на изменяемые (mutable) типы коллекции. diff --git a/_ru/overviews/collections-2.13/conversions-between-java-and-scala-collections.md b/_ru/overviews/collections-2.13/conversions-between-java-and-scala-collections.md index 2471e0121f..0320c0c59d 100644 --- a/_ru/overviews/collections-2.13/conversions-between-java-and-scala-collections.md +++ b/_ru/overviews/collections-2.13/conversions-between-java-and-scala-collections.md @@ -1,17 +1,11 @@ --- layout: multipage-overview title: Преобразования между Java и Scala коллекциями - -discourse: true - partof: collections-213 overview-name: Collections - num: 17 previous-page: creating-collections-from-scratch - language: ru - --- Как и в Scala, в Java есть богатая библиотека коллекций. Между ними много общего. Например, обе библиотеки предоставляют итераторы, итерируемые сущности, множества, мапы и списки. Но есть и серьезные различия. В частности, библиотека Scala фокусируют больше внимания на неизменяемых коллекциях, предоставляя больше возможностей для преобразования исходной коллекции в новую. diff --git a/_ru/overviews/collections-2.13/creating-collections-from-scratch.md b/_ru/overviews/collections-2.13/creating-collections-from-scratch.md index 1eacea990f..25c9cb21cf 100644 --- a/_ru/overviews/collections-2.13/creating-collections-from-scratch.md +++ b/_ru/overviews/collections-2.13/creating-collections-from-scratch.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Создание коллекций с нуля - -discourse: true - partof: collections-213 overview-name: Collections - num: 16 previous-page: iterators next-page: conversions-between-java-and-scala-collections - language: ru - --- У вас есть синтаксис `List(1, 2, 3)` для создания списка из трех целых чисел и `Map('A' -> 1, 'C' -> 2)` для создания мапы с двумя элементами. На самом деле, это универсальная функциональность коллекций Scala. Можно получить любую коллекцию написав ее название и указав следом список элементов в круглых скобках. В результате получится новая коллекция с заданными элементами. Вот еще несколько примеров: diff --git a/_ru/overviews/collections-2.13/equality.md b/_ru/overviews/collections-2.13/equality.md index 5908d1ca2b..179ae0bd71 100644 --- a/_ru/overviews/collections-2.13/equality.md +++ b/_ru/overviews/collections-2.13/equality.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Равенство - -discourse: true - partof: collections-213 overview-name: Collections - num: 13 previous-page: performance-characteristics next-page: views - language: ru - --- Коллекций придерживаются единого подхода к определению равенства и получению хэшей. Идея состоит, во-первых, в том, чтобы разделить коллекции на группы: множества, мапы и последовательности. Коллекции в разных группах всегда различаются. Например, `Set(1,2,3)` неравнозначен списку `List(1,2,3)`, хотя они содержат одни и те же элементы. С другой стороны, в рамках одной и той же группы коллекции равны тогда и только тогда, когда они имеют одинаковые элементы (для последовательностей: одни и те же элементы в одном порядке). Например `List(1, 2, 3) == Vector(1, 2, 3)`, и `HashSet(1, 2) == TreeSet(2, 1)`. diff --git a/_ru/overviews/collections-2.13/introduction.md b/_ru/overviews/collections-2.13/introduction.md index c965ef979e..e97c142eb8 100644 --- a/_ru/overviews/collections-2.13/introduction.md +++ b/_ru/overviews/collections-2.13/introduction.md @@ -1,17 +1,11 @@ --- layout: multipage-overview title: Введение - -discourse: true - partof: collections-213 overview-name: Collections - num: 1 next-page: overview - language: ru - --- **Martin Odersky и Lex Spoon** diff --git a/_ru/overviews/collections-2.13/iterators.md b/_ru/overviews/collections-2.13/iterators.md index ee7c02c50d..a74e0bc860 100644 --- a/_ru/overviews/collections-2.13/iterators.md +++ b/_ru/overviews/collections-2.13/iterators.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Итераторы - -discourse: true - partof: collections-213 overview-name: Collections - num: 15 previous-page: views next-page: creating-collections-from-scratch - language: ru - --- Итератор (Iterator) - это не коллекция, а скорее способ поочередного доступа к элементам коллекции. Есть две основные операции у итератора - это `next` и `hasNext`. Вызов метода `it.next()` на итераторе `it` вернет следующий элемент и изменит его состояние. Повторный вызов `next` на том же итераторе выведит следующий элемент идущий после ранее возвращённого. Если больше нет элементов для возврата, вызов команды `next` кинет исключение `NoSuchElementException`. Вы можете узнать, есть ли еще элементы для возврата с помощью метода `hasNext` у [Итератора](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html). diff --git a/_ru/overviews/collections-2.13/maps.md b/_ru/overviews/collections-2.13/maps.md index 18cfc11245..a3d93834fd 100644 --- a/_ru/overviews/collections-2.13/maps.md +++ b/_ru/overviews/collections-2.13/maps.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Мапы - -discourse: true - partof: collections-213 overview-name: Collections - num: 7 previous-page: sets next-page: concrete-immutable-collection-classes - language: ru - --- [Map](https://www.scala-lang.org/api/current/scala/collection/Map.html) это [Iterable](https://www.scala-lang.org/api/current/scala/collection/Iterable.html) состоящее из пар ключ значение (также называемых _связкой_ или _ассоциативным массивом_). diff --git a/_ru/overviews/collections-2.13/overview.md b/_ru/overviews/collections-2.13/overview.md index b0fe21b1cd..361d8f5551 100644 --- a/_ru/overviews/collections-2.13/overview.md +++ b/_ru/overviews/collections-2.13/overview.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Изменяемые и Неизменяемые Коллекции - -discourse: true - partof: collections-213 overview-name: Collections - num: 2 previous-page: introduction next-page: trait-iterable - language: ru - --- В коллекциях Scala постоянно проводят различие между неизменяемыми и изменяемыми коллекциями. _Изменяемые_ (mutable) коллекции могут быть изменены или дополнены. Это означает, что вы можете изменять, добавлять или удалять её элементы. _Неизменяемые_ (Immutable) коллекции, напротив, никогда не меняются. У них есть операции, имитирующие добавления, удаления или обновления, но эти операции каждый раз будут возвращать новую коллекцию и оставлять старую коллекцию без изменений. diff --git a/_ru/overviews/collections-2.13/performance-characteristics.md b/_ru/overviews/collections-2.13/performance-characteristics.md index 526a74a2b2..eb63206c02 100644 --- a/_ru/overviews/collections-2.13/performance-characteristics.md +++ b/_ru/overviews/collections-2.13/performance-characteristics.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Показатели производительности - -discourse: true - partof: collections-213 overview-name: Collections - num: 12 previous-page: strings next-page: equality - language: ru - --- Из предыдущих объяснений стало ясно, что разные типы коллекций имеют разные показатели производительности. Что зачастую является основной причиной, выбора одной коллекции вместо другой. Показатели для наиболее распространенных операций собраны в таблицах ниже. diff --git a/_ru/overviews/collections-2.13/seqs.md b/_ru/overviews/collections-2.13/seqs.md index c5557bdd40..9bf9d180c3 100644 --- a/_ru/overviews/collections-2.13/seqs.md +++ b/_ru/overviews/collections-2.13/seqs.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Последовательности. Трейт Seq, IndexedSeq и LinearSeq - -discourse: true - partof: collections-213 overview-name: Collections - num: 5 previous-page: trait-iterable next-page: sets - language: ru - --- Трейт [Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html) представляет из себя последовательность. Последовательность - это своего рода итерируемая сущность, у которой есть длина (`length`) и элементы с фиксированным индексом, начинающийся от `0`. diff --git a/_ru/overviews/collections-2.13/sets.md b/_ru/overviews/collections-2.13/sets.md index 3a2bbbf98e..2a4d4a0550 100644 --- a/_ru/overviews/collections-2.13/sets.md +++ b/_ru/overviews/collections-2.13/sets.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Множества - -discourse: true - partof: collections-213 overview-name: Collections - num: 6 previous-page: seqs next-page: maps - language: ru - --- Множества (`Set`) - это итерируемые сущности, которые не содержат дублирующих друг друга элементов. Операции с множествами описаны в таблицах ниже. Описания включают операции для базовых, неизменяемых и изменяемых множеств. Все их операции поделены на следующие категории: diff --git a/_ru/overviews/collections-2.13/strings.md b/_ru/overviews/collections-2.13/strings.md index 1527860415..17e13d1a14 100644 --- a/_ru/overviews/collections-2.13/strings.md +++ b/_ru/overviews/collections-2.13/strings.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Строки - -discourse: true - partof: collections-213 overview-name: Collections - num: 11 previous-page: arrays next-page: performance-characteristics - language: ru - --- Как и массивы, строки не являются непосредственно последовательностями, но могут быть преобразованы в них, а также поддерживают все операции которые есть у последовательностей. Ниже приведены некоторые примеры операций, которые можно вызывать на строках. diff --git a/_ru/overviews/collections-2.13/trait-iterable.md b/_ru/overviews/collections-2.13/trait-iterable.md index 25cfd6ed37..447859daba 100644 --- a/_ru/overviews/collections-2.13/trait-iterable.md +++ b/_ru/overviews/collections-2.13/trait-iterable.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Трейт Iterable - -discourse: true - partof: collections-213 overview-name: Collections - num: 4 previous-page: overview next-page: seqs - language: ru - --- На самом верху иерархии коллекций находится трейт `Iterable`. Все методы в этого трейта описаны как абстрактные, `iterator` - это метод, который выдает элементы коллекции один за другим. diff --git a/_ru/overviews/collections-2.13/views.md b/_ru/overviews/collections-2.13/views.md index 8a095c96a1..3b8a5f5d76 100644 --- a/_ru/overviews/collections-2.13/views.md +++ b/_ru/overviews/collections-2.13/views.md @@ -1,18 +1,12 @@ --- layout: multipage-overview title: Отображения - -discourse: true - partof: collections-213 overview-name: Collections - num: 14 previous-page: equality next-page: iterators - language: ru - --- У коллекций довольно много вариантов создания новых коллекций. Ну например используя операции `map`, `filter` или `++`. Мы называем такие операции *трансформерами*, потому что они берут хотя бы одну коллекцию и трансформируют её в новую коллекцию. diff --git a/_ru/overviews/collections/introduction.md b/_ru/overviews/collections/introduction.md index 4f503f94d6..5b996a9254 100644 --- a/_ru/overviews/collections/introduction.md +++ b/_ru/overviews/collections/introduction.md @@ -1,14 +1,9 @@ --- layout: multipage-overview title: Введение - -discourse: false - partof: collections overview-name: Collections - num: 1 - language: ru --- diff --git a/_ru/overviews/parallel-collections/architecture.md b/_ru/overviews/parallel-collections/architecture.md index 5ee10d99b9..9677440e9c 100644 --- a/_ru/overviews/parallel-collections/architecture.md +++ b/_ru/overviews/parallel-collections/architecture.md @@ -1,9 +1,6 @@ --- layout: multipage-overview title: Архитектура библиотеки параллельных коллекций - -discourse: false - partof: parallel-collections overview-name: Parallel Collections diff --git a/_ru/overviews/parallel-collections/concrete-parallel-collections.md b/_ru/overviews/parallel-collections/concrete-parallel-collections.md index ab41a576c7..b6170ffe1d 100644 --- a/_ru/overviews/parallel-collections/concrete-parallel-collections.md +++ b/_ru/overviews/parallel-collections/concrete-parallel-collections.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Конкретные классы параллельных коллекций - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - language: ru num: 2 --- diff --git a/_ru/overviews/parallel-collections/configuration.md b/_ru/overviews/parallel-collections/configuration.md index 5dbd2b1e38..253c4c30d5 100644 --- a/_ru/overviews/parallel-collections/configuration.md +++ b/_ru/overviews/parallel-collections/configuration.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Конфигурирование параллельных коллекций - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - language: ru num: 7 --- diff --git a/_ru/overviews/parallel-collections/conversions.md b/_ru/overviews/parallel-collections/conversions.md index 114f2d8986..f001762841 100644 --- a/_ru/overviews/parallel-collections/conversions.md +++ b/_ru/overviews/parallel-collections/conversions.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Преобразования параллельных коллекций - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - language: ru num: 3 --- diff --git a/_ru/overviews/parallel-collections/ctries.md b/_ru/overviews/parallel-collections/ctries.md index 9e52d407bf..640ac7e8b9 100644 --- a/_ru/overviews/parallel-collections/ctries.md +++ b/_ru/overviews/parallel-collections/ctries.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Многопоточные префиксные деревья - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - language: ru num: 4 --- diff --git a/_ru/overviews/parallel-collections/custom-parallel-collections.md b/_ru/overviews/parallel-collections/custom-parallel-collections.md index 6fd6fa9f58..4dbcdf7e96 100644 --- a/_ru/overviews/parallel-collections/custom-parallel-collections.md +++ b/_ru/overviews/parallel-collections/custom-parallel-collections.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Создание пользовательской параллельной коллекции - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - language: ru num: 6 --- diff --git a/_ru/overviews/parallel-collections/overview.md b/_ru/overviews/parallel-collections/overview.md index 2d68d91d8d..e2b4bbcd7d 100644 --- a/_ru/overviews/parallel-collections/overview.md +++ b/_ru/overviews/parallel-collections/overview.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Обзор - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - num: 1 language: ru --- diff --git a/_ru/overviews/parallel-collections/performance.md b/_ru/overviews/parallel-collections/performance.md index b86e90bc2c..64e533e359 100644 --- a/_ru/overviews/parallel-collections/performance.md +++ b/_ru/overviews/parallel-collections/performance.md @@ -1,12 +1,8 @@ --- layout: multipage-overview title: Измерение производительности - -discourse: false - partof: parallel-collections overview-name: Parallel Collections - num: 8 language: ru --- diff --git a/_ru/tour/abstract-type-members.md b/_ru/tour/abstract-type-members.md index 849286419f..6da748d090 100644 --- a/_ru/tour/abstract-type-members.md +++ b/_ru/tour/abstract-type-members.md @@ -1,9 +1,6 @@ --- layout: tour title: Члены Абстрактного Типа - -discourse: true - partof: scala-tour num: 23 language: ru @@ -11,7 +8,6 @@ next-page: compound-types previous-page: inner-classes topics: abstract type members prerequisite-knowledge: variance, upper-type-bound - --- Абстрактные типы, такие как трейты и абстрактные классы, могут содержать членов абстрактного типа. diff --git a/_ru/tour/annotations.md b/_ru/tour/annotations.md index 99a668acb0..46718f2d77 100644 --- a/_ru/tour/annotations.md +++ b/_ru/tour/annotations.md @@ -1,16 +1,11 @@ --- layout: tour title: Аннотации - -discourse: true - partof: scala-tour - num: 32 language: ru next-page: packages-and-imports previous-page: by-name-parameters - --- Аннотации используются для передачи метаданных при объявлении. Например, аннотация `@deprecated` перед объявлением метода, заставит компилятор вывести предупреждение, если этот метод будет использован. diff --git a/_ru/tour/automatic-closures.md b/_ru/tour/automatic-closures.md index 7de83279d8..7465e6abef 100644 --- a/_ru/tour/automatic-closures.md +++ b/_ru/tour/automatic-closures.md @@ -1,8 +1,6 @@ --- layout: tour title: Конструкция Автоматического Замыкания Зависимого Типа - -discourse: true language: ru partof: scala-tour num: 14 diff --git a/_ru/tour/basics.md b/_ru/tour/basics.md index f6c3788f4c..518662c9f6 100644 --- a/_ru/tour/basics.md +++ b/_ru/tour/basics.md @@ -1,16 +1,11 @@ --- layout: tour title: Основы - -discourse: true - partof: scala-tour - num: 2 language: ru next-page: unified-types previous-page: tour-of-scala - --- На этой странице мы расскажем об основах Scala. diff --git a/_ru/tour/by-name-parameters.md b/_ru/tour/by-name-parameters.md index 4a1a4d4417..3be9478fe8 100644 --- a/_ru/tour/by-name-parameters.md +++ b/_ru/tour/by-name-parameters.md @@ -1,16 +1,11 @@ --- layout: tour title: Вызов по имени - -discourse: true - partof: scala-tour - num: 31 language: ru next-page: annotations previous-page: operators - --- _Вызов параметров по имени_ - это когда значение параметра вычисляется только в момент вызова параметра. Этот способ противоположен _вызову по значению_. Чтоб вызов параметра был по имени, необходимо просто указать `=>` перед его типом. diff --git a/_ru/tour/case-classes.md b/_ru/tour/case-classes.md index 9a49c560dd..64fab9024e 100644 --- a/_ru/tour/case-classes.md +++ b/_ru/tour/case-classes.md @@ -1,17 +1,12 @@ --- layout: tour title: Классы Образцы - -discourse: true - partof: scala-tour - num: 11 language: ru next-page: pattern-matching previous-page: multiple-parameter-lists prerequisite-knowledge: classes, basics, mutability - --- Классы образцы (Case classes) похожи на обычные классы с несколькими ключевыми отличиями, о которых мы поговорим ниже. Классы образцы хороши для моделирования неизменяемых данных. На следующей странице обзора вы увидите, насколько они полезны для участия в [сопоставлении с примером](pattern-matching.html). diff --git a/_ru/tour/classes.md b/_ru/tour/classes.md index db66150841..d7e66a84c0 100644 --- a/_ru/tour/classes.md +++ b/_ru/tour/classes.md @@ -1,18 +1,13 @@ --- layout: tour title: Классы - -discourse: true - partof: scala-tour - num: 4 language: ru next-page: traits previous-page: unified-types topics: classes prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-interpolation, procedures - --- Классы в Scala являются основами для создания объектов. Они могут содержать методы, константы, переменные, типы, объекты, трейты и классы, которые в совокупности называются _членами_. Типы, объекты и трейты будут рассмотрены позже в ходе нашего обзора. diff --git a/_ru/tour/compound-types.md b/_ru/tour/compound-types.md index eb861afbfd..5d0a49aa0e 100644 --- a/_ru/tour/compound-types.md +++ b/_ru/tour/compound-types.md @@ -1,16 +1,11 @@ --- layout: tour title: Составные Типы - -discourse: true - partof: scala-tour - num: 24 language: ru next-page: self-types previous-page: abstract-type-members - --- Иногда необходимо выразить, то что тип объекта является подтипом нескольких других типов. В Scala это можно выразить с помощью *составных типов*, которые являются объединением нескольких типов объектов. diff --git a/_ru/tour/default-parameter-values.md b/_ru/tour/default-parameter-values.md index 72ab55e786..ac8c04eda4 100644 --- a/_ru/tour/default-parameter-values.md +++ b/_ru/tour/default-parameter-values.md @@ -1,17 +1,12 @@ --- layout: tour title: Значения Параметров По умолчанию - -discourse: true - partof: scala-tour - num: 33 language: ru next-page: named-arguments previous-page: classes prerequisite-knowledge: named-arguments, function syntax - --- Scala предоставляет возможность задавать значения параметров по умолчанию, что позволяет лишний раз не указывать параметры. diff --git a/_ru/tour/extractor-objects.md b/_ru/tour/extractor-objects.md index 0c968f36cd..8d86b454ac 100644 --- a/_ru/tour/extractor-objects.md +++ b/_ru/tour/extractor-objects.md @@ -1,16 +1,11 @@ --- layout: tour title: Объект Экстрактор - -discourse: true - partof: scala-tour - num: 16 language: ru next-page: for-comprehensions previous-page: regular-expression-patterns - --- Объект Экстрактор (объект распаковщик или extractor object) - это объект с методом `unapply`. В то время как метод `apply` обычно действует как конструктор, который принимает аргументы и создает объект, метод `unapply` действует обратным образом, он принимает объект и пытается извлечь и вернуть аргументы из которых он (возможно) был создан. Чаще всего этот метод используется в функциях сопоставления с примером и в частично определенных функциях. diff --git a/_ru/tour/for-comprehensions.md b/_ru/tour/for-comprehensions.md index 29aad7105c..5a2c538769 100644 --- a/_ru/tour/for-comprehensions.md +++ b/_ru/tour/for-comprehensions.md @@ -1,16 +1,11 @@ --- layout: tour title: Сложные for-выражения - -discourse: true - partof: scala-tour - num: 17 language: ru next-page: generic-classes previous-page: extractor-objects - --- Scala предлагает простую запись для выражения *последовательных преобразований*. Эти преобразования можно упростить используя специальный синтаксис `for выражения` (for comprehension), который записывается как `for (enumerators) yield e`, где `enumerators` относятся к списку перечислителей, разделенных точкой с запятой. Где отдельный такой "перечислитель" (*enumerator*) является либо генератором, который вводит новые переменные, либо фильтром. For-выражение вычисляет тело `e` (которое связанно с тем что генерирует *enumerator*) и возвращает последовательность вычислений. diff --git a/_ru/tour/generic-classes.md b/_ru/tour/generic-classes.md index fafc2fd13e..48d68a9733 100644 --- a/_ru/tour/generic-classes.md +++ b/_ru/tour/generic-classes.md @@ -1,17 +1,12 @@ --- layout: tour title: Обобщенные Классы - -discourse: true - partof: scala-tour - num: 18 language: ru next-page: variances previous-page: for-comprehensions assumed-knowledge: classes unified-types - --- Обобщенные классы (Generic classes) - это классы, обладающие параметрическим полиморфизмом (т. е. классы, которые изменяют свое поведение в зависимости от приписываемого им типа. Этот тип указывается в квадратных скобках `[]` сразу после имени класса). Они особенно полезны для создания коллекций. diff --git a/_ru/tour/higher-order-functions.md b/_ru/tour/higher-order-functions.md index 36a8f0a2a7..2b029a6ca1 100644 --- a/_ru/tour/higher-order-functions.md +++ b/_ru/tour/higher-order-functions.md @@ -1,16 +1,11 @@ --- layout: tour title: Функции Высшего Порядка - -discourse: true - partof: scala-tour - num: 8 language: ru next-page: nested-functions previous-page: mixin-class-composition - --- Функции высшего порядка могут принимать другие функции в качестве параметров или возвращать функцию в качестве результата. diff --git a/_ru/tour/implicit-conversions.md b/_ru/tour/implicit-conversions.md index bd36a9e749..02c5319fae 100644 --- a/_ru/tour/implicit-conversions.md +++ b/_ru/tour/implicit-conversions.md @@ -1,16 +1,11 @@ --- layout: tour title: Неявные Преобразования - -discourse: true - partof: scala-tour - num: 27 language: ru next-page: polymorphic-methods previous-page: implicit-parameters - --- Неявные преобразование типа `S` к типу `T` задается неявным значением функционального типа `S =>T`, или неявным методом, который способен преобразовывать к значению требуемого типа. diff --git a/_ru/tour/implicit-parameters.md b/_ru/tour/implicit-parameters.md index cf58ded10e..f6ca9b6fda 100644 --- a/_ru/tour/implicit-parameters.md +++ b/_ru/tour/implicit-parameters.md @@ -1,16 +1,11 @@ --- layout: tour title: Неявные Параметры - -discourse: true - partof: scala-tour - num: 26 language: ru next-page: implicit-conversions previous-page: self-types - --- Метод может иметь список _неявных_ параметров, помеченный ключевым словом _implicit_ в начале списка параметров. Если параметры в этом списке не передаются как обычно, то Scala будет искать, где можно получить неявное значение требуемого типа, и если найдет, то передаст его автоматически. diff --git a/_ru/tour/inner-classes.md b/_ru/tour/inner-classes.md index 736677ceff..9d86b84000 100644 --- a/_ru/tour/inner-classes.md +++ b/_ru/tour/inner-classes.md @@ -1,16 +1,11 @@ --- layout: tour title: Внутренние классы - -discourse: true - partof: scala-tour - num: 22 language: ru next-page: abstract-type-members previous-page: lower-type-bounds - --- В Scala классам можно иметь в качестве членов другие классы. В отличие от Java-подобных языков, где такие внутренние классы являются членами окружающего класса, в Scala такие внутренние классы привязаны к содержащему его объекту. Предположим, мы хотим, чтобы компилятор не позволял нам на этапе компиляции смешивать узлы этого графа. Для решения этой задачи нам подойдут типы, зависящие от своего расположения. diff --git a/_ru/tour/lower-type-bounds.md b/_ru/tour/lower-type-bounds.md index 8351695a72..ac9e08bd59 100644 --- a/_ru/tour/lower-type-bounds.md +++ b/_ru/tour/lower-type-bounds.md @@ -1,17 +1,12 @@ --- layout: tour title: Нижнее Ограничение Типа - -discourse: true - partof: scala-tour - num: 21 language: ru next-page: inner-classes previous-page: upper-type-bounds prerequisite-knowledge: upper-type-bounds, generics, variance - --- В то время как [верхнее ограничение типа](upper-type-bounds.html) ограничивает тип до подтипа стороннего типа, *нижнее ограничение типа* объявляют тип супертипом стороннего типа. Термин `B >: A` выражает, то что параметр типа `B` или абстрактный тип `B` относится к супертипу типа `A`. В большинстве случаев `A` будет задавать тип класса, а `B` задавать тип метода. diff --git a/_ru/tour/mixin-class-composition.md b/_ru/tour/mixin-class-composition.md index ff7c1d60d9..c27a2edea1 100644 --- a/_ru/tour/mixin-class-composition.md +++ b/_ru/tour/mixin-class-composition.md @@ -1,17 +1,12 @@ --- layout: tour title: Композиция классов с примесями - -discourse: true - partof: scala-tour - num: 7 language: ru next-page: higher-order-functions previous-page: tuples prerequisite-knowledge: inheritance, traits, abstract-classes, unified-types - --- Примеси (Mixin) - это трейты, которые используются для создания класса. diff --git a/_ru/tour/multiple-parameter-lists.md b/_ru/tour/multiple-parameter-lists.md index c4656f5193..c93a6e31d1 100644 --- a/_ru/tour/multiple-parameter-lists.md +++ b/_ru/tour/multiple-parameter-lists.md @@ -1,16 +1,11 @@ --- layout: tour title: Множественные списки параметров (Каррирование) - -discourse: true - partof: scala-tour - num: 10 language: ru next-page: case-classes previous-page: nested-functions - --- Методы могут объявляться с несколькими списками параметров. При этом когда такой метод вызывается с меньшим количеством списков параметров, это приводит к созданию новой функции, которая ожидает на вход не достающий список параметров. Формально это называется [частичное применение](https://en.wikipedia.org/wiki/Partial_application). diff --git a/_ru/tour/named-arguments.md b/_ru/tour/named-arguments.md index 32b83664e4..463480e547 100644 --- a/_ru/tour/named-arguments.md +++ b/_ru/tour/named-arguments.md @@ -1,17 +1,12 @@ --- layout: tour title: Именованные Аргументы - -discourse: true - partof: scala-tour - num: 34 language: ru next-page: packages-and-imports previous-page: default-parameter-values prerequisite-knowledge: function-syntax - --- При вызове методов можно конкретно указывать название задаваемого аргумента следующим образом: diff --git a/_ru/tour/nested-functions.md b/_ru/tour/nested-functions.md index 663e0fdc36..6a59ca5a0e 100644 --- a/_ru/tour/nested-functions.md +++ b/_ru/tour/nested-functions.md @@ -1,16 +1,11 @@ --- layout: tour title: Вложенные Методы - -discourse: true - partof: scala-tour - num: 9 language: ru next-page: multiple-parameter-lists previous-page: higher-order-functions - --- В Scala возможно объявление метода вкладывать в тело другого метода. Это реализовано в следующем примере, в котором метод `factorial` используется для вычисления факториала заданного числа: diff --git a/_ru/tour/operators.md b/_ru/tour/operators.md index 09ea35ea76..dd80f7905d 100644 --- a/_ru/tour/operators.md +++ b/_ru/tour/operators.md @@ -1,17 +1,12 @@ --- layout: tour title: Операторы - -discourse: true - partof: scala-tour - num: 30 language: ru next-page: by-name-parameters previous-page: type-inference prerequisite-knowledge: case-classes - --- В Скале операторы - это обычные методы. В качестве _инфиксного оператора_ может быть использован любой метод с одним параметром. Например, `+` может вызываться с использованием точки: ``` diff --git a/_ru/tour/package-objects.md b/_ru/tour/package-objects.md index 1a0ba1b7f2..e7924e8de8 100644 --- a/_ru/tour/package-objects.md +++ b/_ru/tour/package-objects.md @@ -1,11 +1,7 @@ --- layout: tour title: Объекты Пакета - -discourse: true - partof: scala-tour - num: 36 language: ru previous-page: packages-and-imports diff --git a/_ru/tour/packages-and-imports.md b/_ru/tour/packages-and-imports.md index 2a3e6ba6ff..a4d6710454 100644 --- a/_ru/tour/packages-and-imports.md +++ b/_ru/tour/packages-and-imports.md @@ -1,11 +1,7 @@ --- layout: tour title: Пакеты и Импорт - -discourse: true - partof: scala-tour - num: 35 language: ru previous-page: annotations diff --git a/_ru/tour/pattern-matching.md b/_ru/tour/pattern-matching.md index 8d329636da..15e58ff983 100644 --- a/_ru/tour/pattern-matching.md +++ b/_ru/tour/pattern-matching.md @@ -1,17 +1,12 @@ --- layout: tour title: Сопоставление с примером - -discourse: true - partof: scala-tour - num: 12 language: ru next-page: singleton-objects previous-page: case-classes prerequisite-knowledge: case-classes, string-interpolation, subtyping - --- Сопоставление с примером (Pattern matching) - это механизм сравнения значений с определенным примером. При успешном совпадении значение может быть разложено на составные части. Мы рассматриваем сопоставление с примером, как более мощную версию `switch` оператора из Java. Eго также можно использовать вместо серии if/else выражений. diff --git a/_ru/tour/polymorphic-methods.md b/_ru/tour/polymorphic-methods.md index 3c017b89f6..9d54223100 100644 --- a/_ru/tour/polymorphic-methods.md +++ b/_ru/tour/polymorphic-methods.md @@ -1,17 +1,12 @@ --- layout: tour title: Полиморфные методы - -discourse: true - partof: scala-tour - num: 28 language: ru next-page: type-inference previous-page: implicit-conversions prerequisite-knowledge: unified-types - --- Также как и у обобщенных классов, у методов есть полиморфизм по типу, с таким же синтаксисом (параметр типа указывается в квадратных скобках сразу после названия метода). diff --git a/_ru/tour/regular-expression-patterns.md b/_ru/tour/regular-expression-patterns.md index e8c2ea8404..159921587c 100644 --- a/_ru/tour/regular-expression-patterns.md +++ b/_ru/tour/regular-expression-patterns.md @@ -1,16 +1,11 @@ --- layout: tour title: Регулярные Выражения - -discourse: true - partof: scala-tour - num: 15 language: ru next-page: extractor-objects previous-page: singleton-objects - --- Регулярные выражения (Regular expression) - это специальный шаблон для поиска данных, задаваемый в виде текстовой строки. Любая строка может быть преобразована в регулярное выражение методом `.r`. diff --git a/_ru/tour/self-types.md b/_ru/tour/self-types.md index 2ce9946450..5ca4c91b22 100644 --- a/_ru/tour/self-types.md +++ b/_ru/tour/self-types.md @@ -1,18 +1,13 @@ --- layout: tour title: Самоописываемые типы - -discourse: true - partof: scala-tour - num: 25 language: ru next-page: implicit-parameters previous-page: compound-types topics: self-types prerequisite-knowledge: nested-classes, mixin-class-composition - --- Самоописываемый тип(Self type) - это способ объявить, что трейт должен быть смешан с другим трейтом, даже если он не расширяет его напрямую. Что открывает доступ к членам зависимости без импортирования. diff --git a/_ru/tour/singleton-objects.md b/_ru/tour/singleton-objects.md index d39f5c170e..5b2f79dac8 100644 --- a/_ru/tour/singleton-objects.md +++ b/_ru/tour/singleton-objects.md @@ -1,11 +1,7 @@ --- layout: tour title: Объекты Одиночки - -discourse: true - partof: scala-tour - num: 13 language: ru next-page: regular-expression-patterns diff --git a/_ru/tour/tour-of-scala.md b/_ru/tour/tour-of-scala.md index ac523d9914..321685dbb3 100644 --- a/_ru/tour/tour-of-scala.md +++ b/_ru/tour/tour-of-scala.md @@ -1,11 +1,7 @@ --- layout: tour title: Введение - -discourse: true - partof: scala-tour - num: 1 language: ru next-page: basics diff --git a/_ru/tour/traits.md b/_ru/tour/traits.md index 3eec6fd35c..ab7f6a5ade 100644 --- a/_ru/tour/traits.md +++ b/_ru/tour/traits.md @@ -1,18 +1,13 @@ --- layout: tour title: Трейты - -discourse: true - partof: scala-tour - num: 5 language: ru next-page: tuples previous-page: named-arguments topics: traits prerequisite-knowledge: expressions, classes, generics, objects, companion-objects - --- Трейты (Traits) используются, чтобы обмениваться между классами информацией о структуре и полях. Они похожи на интерфейсы из Java 8. Классы и объекты могут расширять трейты, но трейты не могут быть созданы и поэтому не имеют параметров. diff --git a/_ru/tour/tuples.md b/_ru/tour/tuples.md index 8d30c607c5..8af61d5102 100644 --- a/_ru/tour/tuples.md +++ b/_ru/tour/tuples.md @@ -1,17 +1,12 @@ --- layout: tour title: Кортежи - -discourse: true - partof: scala-tour - num: 6 language: ru next-page: mixin-class-composition previous-page: traits topics: tuples - --- В Scala, кортеж (Тuple) это класс контейнер содержащий упорядоченный набор элементов различного типа. diff --git a/_ru/tour/type-inference.md b/_ru/tour/type-inference.md index 5e5e39cf17..6709acf411 100644 --- a/_ru/tour/type-inference.md +++ b/_ru/tour/type-inference.md @@ -1,11 +1,7 @@ --- layout: tour title: Выведение Типа - -discourse: true - partof: scala-tour - num: 29 language: ru next-page: operators diff --git a/_ru/tour/unified-types.md b/_ru/tour/unified-types.md index 1bd87556b7..7399f82409 100644 --- a/_ru/tour/unified-types.md +++ b/_ru/tour/unified-types.md @@ -1,17 +1,12 @@ --- layout: tour title: Единобразие типов - -discourse: true - partof: scala-tour - num: 3 language: ru next-page: classes previous-page: basics prerequisite-knowledge: classes, basics - --- В Scala все значения имеют тип, включая числовые значения и функции. Диаграмма ниже иллюстрирует подмножество иерархии типов. diff --git a/_ru/tour/upper-type-bounds.md b/_ru/tour/upper-type-bounds.md index 60ca550d59..2bfe19f96e 100644 --- a/_ru/tour/upper-type-bounds.md +++ b/_ru/tour/upper-type-bounds.md @@ -1,16 +1,12 @@ --- layout: tour title: Верхнее Ограничение Типа - -discourse: true - partof: scala-tour categories: tour num: 20 language: ru next-page: lower-type-bounds previous-page: variances - --- В Scala [параметры типа](generic-classes.html) и [члены абстрактного типа](abstract-type-members.html) могут быть ограничены определенными диапазонами. Такие диапазоны ограничивают конкретные значение типа и, возможно, предоставляют больше информации о членах таких типов. _Верхнее ограничение типа_ `T <: A` указывает на то что тип `T` относится к подтипу типа `A`. diff --git a/_ru/tour/variances.md b/_ru/tour/variances.md index c59549f340..17dd06b74c 100644 --- a/_ru/tour/variances.md +++ b/_ru/tour/variances.md @@ -1,16 +1,11 @@ --- layout: tour title: Вариантность - -discourse: true - partof: scala-tour - num: 19 language: ru next-page: upper-type-bounds previous-page: generic-classes - --- Вариантность (Variances) - это указание определенной специфики взаимосвязи между связанными типам. Scala поддерживает вариантную аннотацию типов у [обобщенных классов](generic-classes.html), что позволяет им быть ковариантными, контрвариантными или инвариантными (если нет никакого указание на вариантность). Использование вариантности в системе типов позволяет устанавливать понятные взаимосвязи между сложными типами, в то время как отсутствие вариантности может ограничить повторное использование абстракции класса. From 86b753a7c61b9ef04013902b6104eb92439b38fd Mon Sep 17 00:00:00 2001 From: Philippus Date: Tue, 19 Apr 2022 08:47:50 +0200 Subject: [PATCH 1031/2265] Display code blocks inside details/summary correctly --- _overviews/scala3-macros/tutorial/inline.md | 12 ++++++++++-- _sass/layout/details-summary.scss | 3 +++ resources/css/style.scss | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 _sass/layout/details-summary.scss diff --git a/_overviews/scala3-macros/tutorial/inline.md b/_overviews/scala3-macros/tutorial/inline.md index c081b8d61c..30c445cef0 100644 --- a/_overviews/scala3-macros/tutorial/inline.md +++ b/_overviews/scala3-macros/tutorial/inline.md @@ -254,8 +254,11 @@ Calling `power` with statically known constants results in the following code: val x = 2 power(x * x, 1) ``` + +{::options parse_block_html="true" /}
    - See rest of inlining steps + See rest of inlining steps + ```scala // then inlined as @@ -283,6 +286,8 @@ x2 * 1.0 ```
    +{::options parse_block_html="false" /} + In contrast, let us imagine we do not know the value of `n`: ```scala @@ -291,8 +296,10 @@ power(2, unknownNumber) Driven by the inline annotation on the parameter, the compiler will try to unroll the recursion. But without any success, since the parameter is not statically known. +{::options parse_block_html="true" /}
    - See inlining steps + See inlining steps + ```scala // first inlines as @@ -318,6 +325,7 @@ else { ... ```
    +{::options parse_block_html="false" /} To guarantee that the branching can indeed be performed at compile-time, we can use the `inline if` variant of `if`. Annotating a conditional with `inline` will guarantee that the conditional can be reduced at compile-time and emits an error if the condition is not a statically known constant. diff --git a/_sass/layout/details-summary.scss b/_sass/layout/details-summary.scss new file mode 100644 index 0000000000..1f18d4cd64 --- /dev/null +++ b/_sass/layout/details-summary.scss @@ -0,0 +1,3 @@ +details > summary > p { + display: inline; +} diff --git a/resources/css/style.scss b/resources/css/style.scss index 57b121deba..fb5c150296 100755 --- a/resources/css/style.scss +++ b/resources/css/style.scss @@ -56,6 +56,7 @@ @import 'layout/blog'; @import 'layout/download'; @import 'layout/content-contributors'; // COMPONENTS +@import 'layout/details-summary'; //------------------------------------------------ //------------------------------------------------ @import 'components/buttons'; From c4c0be187b9caf2c5243da2a2b521e91efba2ef2 Mon Sep 17 00:00:00 2001 From: Erik van Oosten Date: Thu, 21 Apr 2022 14:54:35 +0200 Subject: [PATCH 1032/2265] Avoid dysphemisms I was reading the inclusive language guide at https://docs.scala-lang.org/contribute/inclusive-language-guide.html. I have 2 points of feedback. I initially posted this on Discord but then I noticed I could do a pull request. So here it is. Re. blacklist/whitelist. Such lists are often used to regulate access. Therefore I propose we suggest the alternative 'allowlist/denylist' as it is probably appropriate in more circumstances. This is also the suggestion done from the linked page https://github.com/dialpad/inclusive-language. --- _overviews/contribute/inclusive-language-guide.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/_overviews/contribute/inclusive-language-guide.md b/_overviews/contribute/inclusive-language-guide.md index 375d988158..5689979302 100644 --- a/_overviews/contribute/inclusive-language-guide.md +++ b/_overviews/contribute/inclusive-language-guide.md @@ -90,7 +90,7 @@ This list is neither comprehensive nor definitive, and it can evolve over time. * **blacklist/whitelist** \ While the etymology of these words has no relation to racism, their use suggests an association between the color black and some form of badness or exclusion, and between the color white and some form of goodness or inclusion. Prefer alternatives when possible. - Several alternatives have been proposed but none sticks as "the one". We suggest using the pair *excludelist*/*includelist*, as it is generic enough to replace all uses of *blacklist*/*whitelist*. + Several alternatives have been proposed but none sticks as "the one". We suggest using the pair *allowlist*/*denylist*, as it is generic enough to replace most uses of *blacklist*/*whitelist*. * **master/slave** \ Never use *slave*. Never use *master* in conjunction with *slave*. @@ -116,6 +116,12 @@ We encourage you to research inclusive language guidelines applicable to your do You may want to use automated software like [In Solidarity](https://github.com/apps/in-solidarity) to steer contributors away from loaded words. +## Dysphemism + +Dysphemisms, the opposite of euphemisms, should be avoided. For example, the English expressions "pull the trigger" (enforce a decision) and "bite the bullet" (endure hardship) can be disturbingly violent if you are not used to them. + +Using the direct meaning is preferred. + ## Backward compatibility Sometimes, we have existing code, APIs or commands that do not follow the above recommendations. From 99d4d45e3c58c988849a1439a83e8f69a155a295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Chantepie?= Date: Thu, 21 Apr 2022 21:25:45 +0200 Subject: [PATCH 1033/2265] Fix StandardPlugin example --- _scala3-reference/changed-features/compiler-plugins.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_scala3-reference/changed-features/compiler-plugins.md b/_scala3-reference/changed-features/compiler-plugins.md index c77796d71d..39358b4e8c 100644 --- a/_scala3-reference/changed-features/compiler-plugins.md +++ b/_scala3-reference/changed-features/compiler-plugins.md @@ -57,6 +57,7 @@ package dividezero import dotty.tools.dotc.ast.Trees.* import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.report import dotty.tools.dotc.core.Constants.Constant import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Decorators.* @@ -84,7 +85,7 @@ class DivideZeroPhase extends PluginPhase: tree match case Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) if rcvr.tpe <:< defn.IntType => - report.error("dividing by zero", tree.pos) + report.error("dividing by zero", tree.srcPos) case _ => () tree From 885fac887ecff3a2964c095af6cd5b8e05782180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Fri, 22 Apr 2022 23:48:15 +0800 Subject: [PATCH 1034/2265] fix --- _zh-cn/scala3/new-in-scala3.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/_zh-cn/scala3/new-in-scala3.md b/_zh-cn/scala3/new-in-scala3.md index 472f66331f..ed649cb7da 100644 --- a/_zh-cn/scala3/new-in-scala3.md +++ b/_zh-cn/scala3/new-in-scala3.md @@ -36,7 +36,7 @@ Scala的一个基本核心概念是(在某种程度上仍然是)为用户提 - **Viewing one type as another**. [隐式转换][contextual-conversions]已经被重新设计为类型类`Conversion`的实例。 -- **Higher-order contextual abstractions**. [context functions][contextual-functions]的 _全新_ 功能使上下文抽象成为一流的公民。它们是库开发人员的一个重要工具,允许表达简洁的特定领域语言。 +- **Higher-order contextual abstractions**. [context functions][contextual-functions]的 _全新_ 功能使上下文抽象成为第一等公民。它们是库开发人员的一个重要工具,允许表达简洁的特定领域语言。 - **Actionable feedback from the compiler**. 如果一个隐式参数不能被编译器解决,它现在提供了可能解决这个问题的[import suggestions](https://www.scala-lang.org/blog/2020/05/05/scala-3-import-suggestions.html)。 @@ -47,17 +47,17 @@ Scala的一个基本核心概念是(在某种程度上仍然是)为用户提 - **Opaque Types**. 将实现细节隐藏在[opaque type aliases][types-opaque]的别名后面,而不需要在性能上付出代价! Opaque types 取代了值类,并允许你建立一个抽象的屏障,而不会造成额外的装箱开销。 -- **Intersection and union types**. 将类型系统建立在新的基础上,导致了新的类型系统功能的引入:[intersection types][types-intersection]的实例,如`A & B`,既是`A`的实例,也是`B`的实例;[union types][types-union]的实例,如`A | B`,是`A`或`B`的实例。这两种结构都允许程序员在继承层次结构之外灵活地表达类型约束。 +- **Intersection and union types**. 将类型系统建立在新的基础上,引入了新的类型系统特性:[intersection types][types-intersection]的实例,如`A & B`,既是`A`的实例,也是`B`的实例;[union types][types-union]的实例,如`A | B`,是`A`或`B`的实例。这两种结构都允许程序员在继承层次结构之外灵活地表达类型约束。 - **Dependent function types**. Scala 2 已经允许返回类型依赖于(值)参数。在 Scala 3 中,现在可以对这种模式进行抽象,表达[dependent function types][types-dependent]。在类型`F = (e: Entry) => e.Key`中,结果类型取决于参数。 - **Polymorphic function types**. 与 dependent function types 一样,Scala 2 支持拥有类型参数的方法,但不允许程序员对这些方法进行抽象。在 Scala 3 中,像`[A] => List[A] => List[A]`这样的[polymorphic function types][types-polymorphic]可以抽象出除值参数外还接受 _类型参数_ 的函数。 -- **Type lambdas**. 在 Scala 2 中需要用[编译器插件](https://github.com/typelevel/kind-projector)来表达的东西,现在在 Scala 3 中是第一类的功能:类型lambdas是类型级别的函数,可以作为(高等类型的)类型参数传递,而不需要辅助类型定义。 +- **Type lambdas**. 在 Scala 2 中需要用[编译器插件](https://github.com/typelevel/kind-projector)来表达的东西,现在在 Scala 3 中是原生支持的功能:类型lambdas是类型级别的函数,可以作为(高等类型的)类型参数传递,而不需要辅助类型定义。 - **Match types**. Scala 3 提供了对[matching on types][types-match]的直接支持,而不是使用隐式解析对类型级别的计算进行编码。将类型级计算整合到类型检查器中,可以改进错误信息,并消除对复杂编码的需求。 -### 重新设想的:面向对象的编程 +### Re-envisioned:面向对象的编程 Scala 一直处于函数式编程和面向对象编程的前沿 -- 而 Scala 3 在这两个方向上都推动了边界的发展! 上述类型系统的变化和上下文抽象的重新设计使得 _函数式编程_ 比以前更容易。同时,以下的新特性使结构良好的 _面向对象设计_ 成为可能,并支持最佳实践。 @@ -65,7 +65,7 @@ Scala 一直处于函数式编程和面向对象编程的前沿 -- 而 Scala 3 - **Plan for extension**. 在面向对象的设计中,扩展那些不打算扩展的类是一个长期存在的问题。为了解决这个问题,[open classes][oo-open]要求库设计者 _明确地_ 将类标记为 open(开放的)。 -- **Hide implementation details**. 实施行为的实用性traits有时不应该是推断类型的一部分。在 Scala 3 中,这些traits可以被标记为[transparent][oo-transparent],(在推断类型中)向用户隐藏继承性。 +- **Hide implementation details**. 实现功能的工具性的traits有时不应该是推断类型的一部分。在 Scala 3 中,这些traits可以被标记为[transparent][oo-transparent],(在推断类型中)向用户隐藏继承信息。 - **Composition over inheritance**. 这句话经常被引用,但实现起来却很繁琐。Scala 3 的[export clauses][oo-export]则不然:与imports对应,export clauses 允许用户为对象的选定成员定义别名。 @@ -74,13 +74,13 @@ Scala 一直处于函数式编程和面向对象编程的前沿 -- 而 Scala 3 ### Batteries Included: 元编程 Scala 2 中的宏只是一个实验性的功能,而 Scala 3 则为元编程提供了强大的工具库。[宏教程]({% link _overviews/scala3-macros/tutorial/index.md %})中包含了关于不同设施的详细信息。特别是,Scala 3 为元编程提供了以下功能: -- **Inline**. [inline feature][meta-inline]允许在编译时减少数值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 +- **Inline**. [inline feature][meta-inline]允许在编译时化简值和方法。这个简单的功能已经涵盖了许多使用情况,同时也为更高级的功能提供了入口。 - **Compile-time operations**. 包[`scala.compiletime`][meta-compiletime]中包含了额外的功能,可以用来实现内联方法。 - **Quoted code blocks**. Scala 3为代码增加了[quasi-quotation][meta-quotes]的新功能,这为构建和分析代码提供了方便的高级接口。构建加一加一的代码就像`'{ 1 + 1 }`一样简单。 - **Reflection API**. 对于更高级的用例,[quotes.reflect][meta-reflection]提供了更详细的控制来检查和生成程序树。 -如果你想进一步了解 Scala 3 中的元编程,我们邀请你参加[教程][meta-tutorial]。 +如果你想进一步了解 Scala 3 中的元编程,我们邀请你参阅我们的[教程][meta-tutorial]。 [enums]: {{ site.scala3ref }}/enums/enums.html [enums-adts]: {{ site.scala3ref }}/enums/adts.html From 6b6676f885d39e05e8be4eb4fc076d416366bb34 Mon Sep 17 00:00:00 2001 From: Maximilien Tirard Date: Sat, 23 Apr 2022 14:28:14 +0100 Subject: [PATCH 1035/2265] Typo --- _overviews/parallel-collections/performance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/parallel-collections/performance.md b/_overviews/parallel-collections/performance.md index 625f08304e..96be271b44 100644 --- a/_overviews/parallel-collections/performance.md +++ b/_overviews/parallel-collections/performance.md @@ -81,7 +81,7 @@ For proper benchmark examples, you can see the source code inside [Scala library This is a question commonly asked. The answer is somewhat involved. -The size of the collection at which the parallelization pays of really +The size of the collection at which the parallelization pays off really depends on many factors. Some of them, but not all, include: - Machine architecture. Different CPU types have different From c09f64ad58eaf42a3f5619c434c9f3919f846124 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Sun, 24 Apr 2022 09:50:15 +0900 Subject: [PATCH 1036/2265] fix Scala 3 reflection doc. `companionObject` => `companionClass` https://github.com/lampepfl/dotty/blob/3.1.3-RC2/library/src/scala/quoted/Quotes.scala#L3929-L3933 --- _overviews/scala3-macros/tutorial/reflection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-macros/tutorial/reflection.md b/_overviews/scala3-macros/tutorial/reflection.md index b9bca2e1c9..46618a1d4f 100644 --- a/_overviews/scala3-macros/tutorial/reflection.md +++ b/_overviews/scala3-macros/tutorial/reflection.md @@ -117,7 +117,7 @@ In addition, `Symbol` exposes and is used by many useful methods. For example: - `declaredFields` and `declaredMethods` allow you to iterate on the fields and members defined inside a symbol - `flags` allows you to check multiple properties of a symbol - - `companionObject` and `companionModule` provide a way to jump to and from the companion object/class + - `companionClass` and `companionModule` provide a way to jump to and from the companion object/class - `TypeRepr.baseClasses` returns the list of symbols of classes extended by a type - `Symbol.pos` gives you access to the position where the symbol is defined, the source code of the definition, and even the filename where the symbol is defined - many others that you can find in [`SymbolMethods`](https://scala-lang.org/api/3.x/scala/quoted/Quotes$reflectModule$SymbolMethods.html) From 0ac46fb75644b042c04bb9469f8951847331d1b0 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 29 Apr 2022 17:00:51 +0200 Subject: [PATCH 1037/2265] add tabs on get-started page (english) --- _config.yml | 3 + _data/setup-scala.yml | 4 + _includes/code-snippet.html | 6 ++ _includes/getting-started.md | 52 +++++----- _includes/tabsection.html | 20 ++++ _install_tabs/1-macos.md | 23 +++++ _install_tabs/2-linux.md | 14 +++ _install_tabs/3-windows.md | 14 +++ _install_tabs/4-other.md | 17 ++++ _sass/layout/alt-details.scss | 46 +++++++++ _sass/layout/scala-in-action.scss | 158 ++++++++++++++++++++++++++++++ _sass/layout/tabsection.scss | 60 ++++++++++++ resources/css/style.scss | 3 + resources/js/functions.js | 78 ++++++++++++--- 14 files changed, 456 insertions(+), 42 deletions(-) create mode 100644 _data/setup-scala.yml create mode 100644 _includes/code-snippet.html create mode 100644 _includes/tabsection.html create mode 100644 _install_tabs/1-macos.md create mode 100644 _install_tabs/2-linux.md create mode 100644 _install_tabs/3-windows.md create mode 100644 _install_tabs/4-other.md create mode 100644 _sass/layout/alt-details.scss create mode 100755 _sass/layout/scala-in-action.scss create mode 100755 _sass/layout/tabsection.scss diff --git a/_config.yml b/_config.yml index accb4b5df1..21f5c59539 100644 --- a/_config.yml +++ b/_config.yml @@ -21,6 +21,9 @@ scala-3-version: 3.1.2 collections: contribute_resources: + output: false + install_tabs: + output: false style: output: true overviews: diff --git a/_data/setup-scala.yml b/_data/setup-scala.yml new file mode 100644 index 0000000000..d1bb19a78d --- /dev/null +++ b/_data/setup-scala.yml @@ -0,0 +1,4 @@ +linux: curl -fL https://github.com/coursier/launchers/raw/master/cs-x86_64-pc-linux.gz | gzip -d > cs && chmod +x cs && ./cs setup +macOS-default: curl -fL https://github.com/coursier/launchers/raw/master/cs-x86_64-apple-darwin.gz | gzip -d > cs && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs setup +macOS-brew: brew install coursier/formulas/coursier && cs setup +windows-link: https://github.com/coursier/launchers/raw/master/cs-x86_64-pc-win32.zip diff --git a/_includes/code-snippet.html b/_includes/code-snippet.html new file mode 100644 index 0000000000..0286da8b4d --- /dev/null +++ b/_includes/code-snippet.html @@ -0,0 +1,6 @@ +
    +
    +
    +
    +
    {{include.codeSnippet}}
    +
    diff --git a/_includes/getting-started.md b/_includes/getting-started.md index 83c1de45fe..2df5661769 100644 --- a/_includes/getting-started.md +++ b/_includes/getting-started.md @@ -21,9 +21,29 @@ It ensures that a JVM and standard Scala tools are installed on your system. Install it on your system with the following instructions.
    -
    -

    Follow the instructions to install the cs launcher then run:

    -

    $ ./cs setup

    +
    @@ -165,29 +185,3 @@ Once you've finished the above tutorials, consider checking out: ## Getting Help There are a multitude of mailing lists and real-time chat rooms in case you want to quickly connect with other Scala users. Check out our [community](https://scala-lang.org/community/) page for a list of these resources, and for where to reach out for help. - - - - - - - - - diff --git a/_includes/tabsection.html b/_includes/tabsection.html new file mode 100644 index 0000000000..a5473b04e5 --- /dev/null +++ b/_includes/tabsection.html @@ -0,0 +1,20 @@ +
    +
    + {% for tabRoot in include.collection %} + + {% endfor %} +
    + {% for tabRoot in include.collection %} +
    {{tabRoot.content}}
    + {% endfor %} +
    diff --git a/_install_tabs/1-macos.md b/_install_tabs/1-macos.md new file mode 100644 index 0000000000..f91ab023fa --- /dev/null +++ b/_install_tabs/1-macos.md @@ -0,0 +1,23 @@ +--- +tabId: osx +tabLabel: macOS +--- +
    +
    +
    +
    +

    Run the following command in your terminal, following the on-screen instructions:

    + {% include code-snippet.html language='bash' codeSnippet=site.data.setup-scala.macOS-brew %} +
    + +
    +
    + {% include code-snippet.html language='bash' codeSnippet=site.data.setup-scala.macOS-default %} +
    +
    +
    +
    +
    +
    +
    diff --git a/_install_tabs/2-linux.md b/_install_tabs/2-linux.md new file mode 100644 index 0000000000..6924edf275 --- /dev/null +++ b/_install_tabs/2-linux.md @@ -0,0 +1,14 @@ +--- +tabId: linux +tabLabel: Linux +--- +
    +
    +
    +
    +

    Run the following command in your terminal, following the on-screen instructions:

    + {% include code-snippet.html language='bash' codeSnippet=site.data.setup-scala.linux %} +
    +
    +
    +
    diff --git a/_install_tabs/3-windows.md b/_install_tabs/3-windows.md new file mode 100644 index 0000000000..c3e31fb837 --- /dev/null +++ b/_install_tabs/3-windows.md @@ -0,0 +1,14 @@ +--- +tabId: windows +tabLabel: Windows +--- +
    +
    +
    +
    +

    Download and execute the Scala + installer for Windows based on Coursier, and follow the on-screen instructions.

    +
    +
    +
    +
    diff --git a/_install_tabs/4-other.md b/_install_tabs/4-other.md new file mode 100644 index 0000000000..d60085c17f --- /dev/null +++ b/_install_tabs/4-other.md @@ -0,0 +1,17 @@ +--- +tabId: other +tabLabel: Other +fallbackNoJS: true +--- +
    +
    +
    +
    + +

    Follow the documentation from Coursier on how to install and run cs setup.

    +
    +
    +
    +
    diff --git a/_sass/layout/alt-details.scss b/_sass/layout/alt-details.scss new file mode 100644 index 0000000000..aae4addefb --- /dev/null +++ b/_sass/layout/alt-details.scss @@ -0,0 +1,46 @@ +// ALT-DETAILS +//------------------------------------------------ +//------------------------------------------------ + +.alt-details { + margin: 10px 0px; + + button.alt-details-toggle { + width: 100%; + border: none; + background-color: #b635c4; + padding: 5px 10px; + border-radius: 15px; + font-size: $font-size-medium; + cursor: pointer; + font-weight: 500; + color: #fff; + + &:hover { + background-color: #941fa1; + } + + &:after { + content: "\f13a"; // + font-family: "Font Awesome 5 Free"; + font-weight: 900; + font-size: 15px; + color: #fff; + float: right; + margin-top: 2px; + } + + &.alt-details-closed:after { + content: "\f138"; // + } + } + + .alt-details-detail { + background-color: rgb(248, 226, 255); + border: 1px solid rgb(239, 207, 248); + padding-top: 25px; + padding-bottom: 10px; + margin-top: -15px; + margin-bottom: 10px; + } +} diff --git a/_sass/layout/scala-in-action.scss b/_sass/layout/scala-in-action.scss new file mode 100755 index 0000000000..404c9bbd7f --- /dev/null +++ b/_sass/layout/scala-in-action.scss @@ -0,0 +1,158 @@ +// SCALA-IN-ACTION +//------------------------------------------------ +//------------------------------------------------ + +.scala-in-action { + + .tabcontent { + .scala-text { + .alt-details { + button.alt-details-toggle { + border: 1px solid #a0dff0; + background-color: #d1e5eb; + color: $gray; + + &:hover { + background-color: #c9e3eb; + } + + &:after { + color: $gray; + } + } + + .alt-details-detail { + background-color: $gray-light; + border: 1px solid darken($gray-light, 3%); + } + } + } + } + + .scala-in-action-content { + transition: $base-transition; + + + .scala-in-action-code { + // display: none; + // background: $gray-dark; + padding: 20px 0; + + .wrap { + margin-bottom: 0px; + } + + .snippet { + position: relative; + margin: 10px 0px; + cursor: default; + width: 100%; + + &:hover { + .buttons { + opacity: 0.95; + + &:active { + opacity: 0.3; + } + } + } + + .buttons { + position: absolute; + right: 4px; + top: 5px; + transition: all .2s ease; + display: flex; + opacity: 0; + flex-direction: row-reverse; + justify-content: flex-start; + + button { + outline: none; + background: #fff; + border: none; + font-size: $font-size-medium; + color: rgba($gray, .6); + cursor: pointer; + + i { + font-weight: $font-bold; + } + } + } + + pre.snippet-code { + margin: 0px; + display: block; + overflow-x: auto; + + code { + overflow-x: auto; + display: block; + } + } + } + + .scala-code { + + @include span-columns(7); + + @include bp(large) { + @include span-columns(12); + } + } + + .scala-text { + + details { + summary { + + &:hover { + background-color: lighten($gray-lighter, 5%); + } + } + + summary>* { + display: inline; + } + } + + code { + padding: 3px 6px; + color: #859900; + background-color: #fff; + border-radius: 10px; + border: 1px solid $gray-light; + } + + .snippet { + pre.snippet-code { + code { + border: 1px solid darken($gray-light, 10%); + } + } + } + + @include span-columns(5); + + @include bp(large) { + @include span-columns(12); + } + + h3 { + font-size: 1.525rem; + margin-bottom: 20px; + } + + p { + color: $base-font-color; + } + + &.scala-text-large { + @include span-columns(12); + } + } + } + } +} diff --git a/_sass/layout/tabsection.scss b/_sass/layout/tabsection.scss new file mode 100755 index 0000000000..71c2777183 --- /dev/null +++ b/_sass/layout/tabsection.scss @@ -0,0 +1,60 @@ +// TABSECTION +//------------------------------------------------ +//------------------------------------------------ + +.recommended-install { + margin-top: -2em; + .tabsection { + background: $gray-lighter; + } +} + +.tabsection { + + &.inline-tabs { + margin: 20px 0px; + } + + /* Style the tab */ + .tab { + overflow: hidden; + margin-bottom: -12px; + } + + /* Style the buttons that are used to open the tab content */ + .tab button { + font-family: $heading-font-family; + font-size: $font-size-medium; + font-weight: $font-bold; + color: lighten($gray, 25%); + background-color: inherit; + float: left; + border: none; + border-radius: 30px; + outline: none; + cursor: pointer; + padding: 14px 16px; + } + + /* Change background color of buttons on hover */ + .tab button:hover { + color: #fff; + background-color: $gray; + border-bottom: $base-border-white; + } + + /* Create an active/current tablink class */ + .tab button.active { + background-color: $gray; + border-bottom: $base-border-white; + color: #fff; + } + + /* Style the tab content */ + .tabcontent { + display: none; + padding: 0px 2px; + border-top: none; + transition: all .5s linear; + } +} diff --git a/resources/css/style.scss b/resources/css/style.scss index fb5c150296..02ed07ce47 100755 --- a/resources/css/style.scss +++ b/resources/css/style.scss @@ -28,6 +28,9 @@ @import 'layout/twitter-feed'; @import 'layout/cheatsheet'; @import 'layout/ides'; +@import 'layout/alt-details'; +@import 'layout/tabsection'; +@import 'layout/scala-in-action'; @import 'layout/nutshell'; @import 'layout/overviews'; @import 'layout/sips'; diff --git a/resources/js/functions.js b/resources/js/functions.js index e52eddd5cf..cd5ac73eac 100644 --- a/resources/js/functions.js +++ b/resources/js/functions.js @@ -404,6 +404,58 @@ $(document).ready(function() { } }); +const toggleElement = (evt, elemId) => { + const btn = evt.target; + const elem = document.getElementById(elemId); + if (elem.style.display === "none") { + elem.style.display = "block"; + } else { + elem.style.display = "none"; + } + $(btn).toggleClass("alt-details-closed"); +} + +$(document).ready(() => { + $('.alt-details-toggle').click(); +}); + +function copySnippet(evt) { + const snippet = evt.target.closest('.snippet').querySelector('.snippet-code'); + const code = snippet.querySelector('code').innerText; + window.navigator.clipboard.writeText(code) +} + +function openTab(evt, category, tabName) { + // Get all elements with class="tabcontent" and hide them + $('.tabcontent-' + category + '.tabcontent').css('display', 'none'); + + const queried = evt.target; + + // Get all elements with class="tablinks" and remove the class "active" + $('.tablinks-' + category + '.tablinks').removeClass('active'); + + // Show the current tab, and add an "active" class to the button that opened the tab + document.getElementById(category + '-' + tabName).style.display = "block"; + queried.className += " active"; +} + +$(document).ready(() => { + const defaultTabs = document.getElementsByClassName('default-tab'); + for (i = 0; i < defaultTabs.length; i++) { + defaultTabs[i].click(); + } +}); + +$(document).ready(function () { + if ($(".main-download").length) { + let os = getOS(); + if (os === 'unix') { + os = 'linux'; + } + $("#get-started-tab-" + os).click(); + } +}); + var image = { width: 1680, height: 1100 @@ -467,18 +519,18 @@ $('#filter-glossary-terms').focus(); //Footer scroll to top button -$(document).ready(function(){ - $(window).scroll(function(){ - if ($(this).scrollTop() > 100) { - $('#scroll-to-top-btn').fadeIn(); - } else { - $('#scroll-to-top-btn').fadeOut(); - } - }); - $('#scroll-to-top-btn').click(function(){ - $("html, body").animate({ scrollTop: 0 }, 600); - return false; - }); +$(document).ready(function(){ + $(window).scroll(function(){ + if ($(this).scrollTop() > 100) { + $('#scroll-to-top-btn').fadeIn(); + } else { + $('#scroll-to-top-btn').fadeOut(); + } + }); + $('#scroll-to-top-btn').click(function(){ + $("html, body").animate({ scrollTop: 0 }, 600); + return false; + }); }); //Contributors widget @@ -490,7 +542,7 @@ $(document).ready(function () { * - some files aren't prefixed with underscore, see rootFiles * - some files are placed in _overviews but rendered to its folder, see overviewsFolders */ - + let rootFiles = ['getting-started', 'learn', 'glossary']; let overviewsFolders = ['FAQ', 'cheatsheets', 'collections', 'compiler-options', 'core', 'jdk-compatibility', 'macros', 'parallel-collections', From 71cf7e946fc3377ab35ae90e46cf3a9a9d8bc531 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 29 Apr 2022 18:03:35 +0200 Subject: [PATCH 1038/2265] add tabs to other translated pages --- _fr/getting-started/index.md | 41 +++--------- _includes/_ja/getting-started.md | 39 +++--------- _includes/alt-details.html | 6 ++ _includes/code-snippet.html | 2 + _includes/getting-started.md | 45 +++++++------- _includes/tabsection.html | 4 ++ _install_tabs/1-macos.md | 20 +++--- _install_tabs/2-linux.md | 1 + _install_tabs/3-windows.md | 1 + _install_tabs/4-other.md | 1 + _install_tabs/fr-1-macos.md | 26 ++++++++ _install_tabs/fr-2-linux.md | 14 +++++ _install_tabs/fr-3-windows.md | 14 +++++ _install_tabs/fr-4-other.md | 19 ++++++ _install_tabs/ja-1-macos.md | 26 ++++++++ _install_tabs/ja-2-linux.md | 14 +++++ _install_tabs/ja-3-windows.md | 14 +++++ _install_tabs/ja-4-other.md | 18 ++++++ _layouts/downloadpage.html | 100 ------------------------------ _sass/layout/scala-in-action.scss | 3 +- resources/js/functions.js | 30 +++------ 21 files changed, 225 insertions(+), 213 deletions(-) create mode 100644 _includes/alt-details.html create mode 100644 _install_tabs/fr-1-macos.md create mode 100644 _install_tabs/fr-2-linux.md create mode 100644 _install_tabs/fr-3-windows.md create mode 100644 _install_tabs/fr-4-other.md create mode 100644 _install_tabs/ja-1-macos.md create mode 100644 _install_tabs/ja-2-linux.md create mode 100644 _install_tabs/ja-3-windows.md create mode 100644 _install_tabs/ja-4-other.md delete mode 100644 _layouts/downloadpage.html diff --git a/_fr/getting-started/index.md b/_fr/getting-started/index.md index f9b05d7df9..397c18e59c 100644 --- a/_fr/getting-started/index.md +++ b/_fr/getting-started/index.md @@ -24,13 +24,19 @@ Nous recommandons l'utilisation de l'outil d'installation "Coursier" qui va auto ### Utilisation de l'installateur Scala (recommandé) L'installateur Scala est un outil nommé [Coursier](https://get-coursier.io/docs/cli-overview), la commande principale de l'outil est `cs`. -Il s'assure que la JVM est les outils standards de Scala sont installés sur votre système. +Il s'assure que la JVM est les outils standards de Scala sont installés sur votre système. Installez-le sur votre système avec les instructions suivantes.
    -
    -

    Suivez les instructions pour installer la commande cs puis exécutez :

    -

    $ ./cs setup

    +
    @@ -165,30 +171,3 @@ Une fois que vous avez terminé le tutoriel ce dessus, vous pouvez consulter : Il y a plusieurs listes de diffusion et canaux de discussions instantanés si vous souhaitez rencontrer rapidement d'autres utilisateurs de Scala. Allez faire un tour sur notre page [community](https://scala-lang.org/community/) pour consulter la liste des ces ressources et obtenir de l'aide. Traduction par Antoine Pointeau. - - - - - - - - - diff --git a/_includes/_ja/getting-started.md b/_includes/_ja/getting-started.md index 1df3b33933..f747ff92f7 100644 --- a/_includes/_ja/getting-started.md +++ b/_includes/_ja/getting-started.md @@ -18,13 +18,18 @@ Scala のインストーラーは[Coursier](https://get-coursier.io/docs/cli-ove 以下の手順でお使いのシステムにインストールしてください。
    -
    -

    Follow the instructions to install the cs launcher then run:

    -

    $ ./cs setup

    +
    - `cs setup` は JVM の管理だけでなく、便利なコマンドラインツールもインストールします: - JDK (インストール済みでなければ) @@ -141,29 +146,3 @@ IDE の使用に慣れている場合は、IDE から_Main.scala_のコードを ### (日本語のみ追記) Scala について日本語で質問したい場合、Twitterでつぶやくと気づいた人が教えてくれます。 - - - - - - - - - diff --git a/_includes/alt-details.html b/_includes/alt-details.html new file mode 100644 index 0000000000..52e8d9cf67 --- /dev/null +++ b/_includes/alt-details.html @@ -0,0 +1,6 @@ +
    + +
    + {{include.detail}} +
    +
    diff --git a/_includes/code-snippet.html b/_includes/code-snippet.html index 0286da8b4d..6267a08ad3 100644 --- a/_includes/code-snippet.html +++ b/_includes/code-snippet.html @@ -1,6 +1,8 @@
    + {% unless include.nocopy %}
    + {% endunless %}
    {{include.codeSnippet}}
    diff --git a/_includes/getting-started.md b/_includes/getting-started.md index 2df5661769..45c42b166f 100644 --- a/_includes/getting-started.md +++ b/_includes/getting-started.md @@ -20,31 +20,32 @@ The Scala installer is a tool named [Coursier](https://get-coursier.io/docs/cli- It ensures that a JVM and standard Scala tools are installed on your system. Install it on your system with the following instructions. +{% capture scalaDemo %}$ scala -version +Scala code runner version {{site.scala-3-version}} -- Copyright 2002-2022, LAMP/EPFL{% endcapture %} +
    -
    From 113f485c10c9143d9a5f081974a87061903b5a0d Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 6 Jul 2021 16:29:35 +0200 Subject: [PATCH 0740/2265] Copy https://dotty.epfl.ch/docs/reference into https://docs.scala-lang.org/scala3/reference Content was taken from commit 270bd8b0f5af338be73790082d774516a83a73b5 --- _config.yml | 9 +- _data/scala3-doc-nav-header.yml | 2 +- _includes/sidebar-toc-multipage-overview.html | 2 +- _ja/index.md | 2 +- _ja/scala3/contribute-to-docs.md | 2 +- _ja/scala3/index.md | 2 +- _ja/scala3/new-in-scala3.md | 2 +- _overviews/FAQ/index.md | 4 +- _overviews/scala3-book/ca-summary.md | 2 +- _overviews/scala3-book/scala-features.md | 4 +- _overviews/scala3-macros/other-resources.md | 2 +- _overviews/scala3-macros/tutorial/inline.md | 2 +- .../compatibility-classpath.md | 36 +- .../compatibility-metaprogramming.md | 2 +- .../incompat-contextual-abstractions.md | 2 +- .../incompat-dropped-features.md | 10 +- .../incompat-other-changes.md | 2 +- .../incompat-type-inference.md | 2 +- .../scala3-migration/incompatibility-table.md | 4 +- _overviews/scala3-reference/overview.md | 7 - _scala3-reference/changed-features.md | 9 + .../changed-features/compiler-plugins.md | 130 +++ .../changed-features/eta-expansion-spec.md | 77 ++ .../changed-features/eta-expansion.md | 44 + .../implicit-conversions-spec.md | 117 +++ .../changed-features/implicit-conversions.md | 66 ++ .../changed-features/implicit-resolution.md | 170 ++++ _scala3-reference/changed-features/imports.md | 61 ++ .../changed-features/interpolation-escapes.md | 14 + .../changed-features/lazy-vals-init.md | 82 ++ .../changed-features/main-functions.md | 91 ++ .../changed-features/match-syntax.md | 58 ++ .../changed-features/numeric-literals.md | 264 ++++++ .../changed-features/operators.md | 167 ++++ .../changed-features/overload-resolution.md | 94 ++ .../changed-features/pattern-bindings.md | 62 ++ .../changed-features/pattern-matching.md | 246 ++++++ .../changed-features/structural-types-spec.md | 153 ++++ .../changed-features/structural-types.md | 194 ++++ .../changed-features/type-checking.md | 9 + .../changed-features/type-inference.md | 12 + .../changed-features/vararg-splices.md | 42 + .../changed-features/wildcards.md | 52 ++ _scala3-reference/contextual.md | 85 ++ .../contextual/by-name-context-parameters.md | 67 ++ .../contextual/context-bounds.md | 48 + .../contextual/context-functions-spec.md | 79 ++ .../contextual/context-functions.md | 156 ++++ _scala3-reference/contextual/conversions.md | 78 ++ .../contextual/derivation-macro.md | 204 +++++ _scala3-reference/contextual/derivation.md | 405 +++++++++ .../contextual/extension-methods.md | 308 +++++++ _scala3-reference/contextual/given-imports.md | 119 +++ _scala3-reference/contextual/givens.md | 173 ++++ .../contextual/multiversal-equality.md | 229 +++++ .../contextual/relationship-implicits.md | 208 +++++ .../right-associative-extension-methods.md | 52 ++ _scala3-reference/contextual/type-classes.md | 284 ++++++ _scala3-reference/contextual/using-clauses.md | 155 ++++ _scala3-reference/dropped-features.md | 9 + .../dropped-features/auto-apply.md | 98 +++ .../dropped-features/class-shadowing-spec.md | 26 + .../dropped-features/class-shadowing.md | 35 + .../dropped-features/delayed-init.md | 32 + .../dropped-features/do-while.md | 43 + .../dropped-features/early-initializers.md | 18 + .../dropped-features/existential-types.md | 37 + _scala3-reference/dropped-features/limit22.md | 19 + _scala3-reference/dropped-features/macros.md | 18 + .../dropped-features/nonlocal-returns.md | 26 + .../dropped-features/package-objects.md | 49 ++ .../dropped-features/procedure-syntax.md | 21 + _scala3-reference/dropped-features/symlits.md | 12 + .../dropped-features/this-qualifier.md | 17 + .../dropped-features/type-projection.md | 20 + .../dropped-features/weak-conformance-spec.md | 54 ++ .../dropped-features/weak-conformance.md | 49 ++ .../dropped-features/wildcard-init.md | 25 + _scala3-reference/dropped-features/xml.md | 41 + _scala3-reference/enums.md | 9 + _scala3-reference/enums/adts.md | 175 ++++ _scala3-reference/enums/desugarEnums.md | 217 +++++ _scala3-reference/enums/enums.md | 196 +++++ _scala3-reference/experimental/canthrow.md | 242 +++++ .../experimental/erased-defs-spec.md | 65 ++ _scala3-reference/experimental/erased-defs.md | 229 +++++ _scala3-reference/features-classification.md | 201 +++++ .../language-versions.md | 2 +- _scala3-reference/metaprogramming.md | 49 ++ .../metaprogramming/compiletime-ops.md | 296 +++++++ _scala3-reference/metaprogramming/inline.md | 380 ++++++++ .../metaprogramming/macros-spec.md | 254 ++++++ _scala3-reference/metaprogramming/macros.md | 825 ++++++++++++++++++ .../metaprogramming/reflection.md | 133 +++ .../metaprogramming/simple-smp.md | 232 +++++ _scala3-reference/metaprogramming/staging.md | 123 +++ .../metaprogramming/tasty-inspect.md | 59 ++ _scala3-reference/new-types.md | 9 + .../dependent-function-types-spec.md | 125 +++ .../new-types/dependent-function-types.md | 51 ++ .../new-types/intersection-types-spec.md | 108 +++ .../new-types/intersection-types.md | 70 ++ _scala3-reference/new-types/match-types.md | 247 ++++++ .../new-types/polymorphic-function-types.md | 96 ++ .../new-types/type-lambdas-spec.md | 119 +++ _scala3-reference/new-types/type-lambdas.md | 19 + .../new-types/union-types-spec.md | 172 ++++ _scala3-reference/new-types/union-types.md | 48 + _scala3-reference/other-new-features.md | 9 + .../other-new-features/control-syntax.md | 49 ++ .../creator-applications.md | 59 ++ .../other-new-features/explicit-nulls.md | 540 ++++++++++++ .../other-new-features/export.md | 179 ++++ .../indentation-experimental.md | 83 ++ .../other-new-features/indentation.md | 455 ++++++++++ .../other-new-features/kind-polymorphism.md | 49 ++ .../other-new-features/matchable.md | 143 +++ .../other-new-features/named-typeargs-spec.md | 39 + .../other-new-features/named-typeargs.md | 33 + .../other-new-features/opaques-details.md | 123 +++ .../other-new-features/opaques.md | 169 ++++ .../other-new-features/open-classes.md | 82 ++ .../parameter-untupling-spec.md | 88 ++ .../other-new-features/parameter-untupling.md | 48 + .../other-new-features/safe-initialization.md | 246 ++++++ .../other-new-features/targetName.md | 122 +++ .../threadUnsafe-annotation.md | 20 + .../other-new-features/trait-parameters.md | 90 ++ .../other-new-features/transparent-traits.md | 72 ++ .../other-new-features/type-test.md | 183 ++++ _scala3-reference/overview.md | 155 ++++ _scala3-reference/soft-modifier.md | 27 + _scala3-reference/syntax.md | 445 ++++++++++ _zh-cn/index.md | 2 +- index.md | 2 +- .../explicit-nulls-type-hierarchy.png | Bin 0 -> 57752 bytes scala3/contribute-to-docs.md | 6 +- scala3/guides.md | 4 - scala3/index.md | 2 +- scala3/new-in-scala3.md | 2 +- 140 files changed, 13826 insertions(+), 64 deletions(-) delete mode 100644 _overviews/scala3-reference/overview.md create mode 100644 _scala3-reference/changed-features.md create mode 100644 _scala3-reference/changed-features/compiler-plugins.md create mode 100644 _scala3-reference/changed-features/eta-expansion-spec.md create mode 100644 _scala3-reference/changed-features/eta-expansion.md create mode 100644 _scala3-reference/changed-features/implicit-conversions-spec.md create mode 100644 _scala3-reference/changed-features/implicit-conversions.md create mode 100644 _scala3-reference/changed-features/implicit-resolution.md create mode 100644 _scala3-reference/changed-features/imports.md create mode 100644 _scala3-reference/changed-features/interpolation-escapes.md create mode 100644 _scala3-reference/changed-features/lazy-vals-init.md create mode 100644 _scala3-reference/changed-features/main-functions.md create mode 100644 _scala3-reference/changed-features/match-syntax.md create mode 100644 _scala3-reference/changed-features/numeric-literals.md create mode 100644 _scala3-reference/changed-features/operators.md create mode 100644 _scala3-reference/changed-features/overload-resolution.md create mode 100644 _scala3-reference/changed-features/pattern-bindings.md create mode 100644 _scala3-reference/changed-features/pattern-matching.md create mode 100644 _scala3-reference/changed-features/structural-types-spec.md create mode 100644 _scala3-reference/changed-features/structural-types.md create mode 100644 _scala3-reference/changed-features/type-checking.md create mode 100644 _scala3-reference/changed-features/type-inference.md create mode 100644 _scala3-reference/changed-features/vararg-splices.md create mode 100644 _scala3-reference/changed-features/wildcards.md create mode 100644 _scala3-reference/contextual.md create mode 100644 _scala3-reference/contextual/by-name-context-parameters.md create mode 100644 _scala3-reference/contextual/context-bounds.md create mode 100644 _scala3-reference/contextual/context-functions-spec.md create mode 100644 _scala3-reference/contextual/context-functions.md create mode 100644 _scala3-reference/contextual/conversions.md create mode 100644 _scala3-reference/contextual/derivation-macro.md create mode 100644 _scala3-reference/contextual/derivation.md create mode 100644 _scala3-reference/contextual/extension-methods.md create mode 100644 _scala3-reference/contextual/given-imports.md create mode 100644 _scala3-reference/contextual/givens.md create mode 100644 _scala3-reference/contextual/multiversal-equality.md create mode 100644 _scala3-reference/contextual/relationship-implicits.md create mode 100644 _scala3-reference/contextual/right-associative-extension-methods.md create mode 100644 _scala3-reference/contextual/type-classes.md create mode 100644 _scala3-reference/contextual/using-clauses.md create mode 100644 _scala3-reference/dropped-features.md create mode 100644 _scala3-reference/dropped-features/auto-apply.md create mode 100644 _scala3-reference/dropped-features/class-shadowing-spec.md create mode 100644 _scala3-reference/dropped-features/class-shadowing.md create mode 100644 _scala3-reference/dropped-features/delayed-init.md create mode 100644 _scala3-reference/dropped-features/do-while.md create mode 100644 _scala3-reference/dropped-features/early-initializers.md create mode 100644 _scala3-reference/dropped-features/existential-types.md create mode 100644 _scala3-reference/dropped-features/limit22.md create mode 100644 _scala3-reference/dropped-features/macros.md create mode 100644 _scala3-reference/dropped-features/nonlocal-returns.md create mode 100644 _scala3-reference/dropped-features/package-objects.md create mode 100644 _scala3-reference/dropped-features/procedure-syntax.md create mode 100644 _scala3-reference/dropped-features/symlits.md create mode 100644 _scala3-reference/dropped-features/this-qualifier.md create mode 100644 _scala3-reference/dropped-features/type-projection.md create mode 100644 _scala3-reference/dropped-features/weak-conformance-spec.md create mode 100644 _scala3-reference/dropped-features/weak-conformance.md create mode 100644 _scala3-reference/dropped-features/wildcard-init.md create mode 100644 _scala3-reference/dropped-features/xml.md create mode 100644 _scala3-reference/enums.md create mode 100644 _scala3-reference/enums/adts.md create mode 100644 _scala3-reference/enums/desugarEnums.md create mode 100644 _scala3-reference/enums/enums.md create mode 100644 _scala3-reference/experimental/canthrow.md create mode 100644 _scala3-reference/experimental/erased-defs-spec.md create mode 100644 _scala3-reference/experimental/erased-defs.md create mode 100644 _scala3-reference/features-classification.md rename {_overviews/scala3-reference => _scala3-reference}/language-versions.md (99%) create mode 100644 _scala3-reference/metaprogramming.md create mode 100644 _scala3-reference/metaprogramming/compiletime-ops.md create mode 100644 _scala3-reference/metaprogramming/inline.md create mode 100644 _scala3-reference/metaprogramming/macros-spec.md create mode 100644 _scala3-reference/metaprogramming/macros.md create mode 100644 _scala3-reference/metaprogramming/reflection.md create mode 100644 _scala3-reference/metaprogramming/simple-smp.md create mode 100644 _scala3-reference/metaprogramming/staging.md create mode 100644 _scala3-reference/metaprogramming/tasty-inspect.md create mode 100644 _scala3-reference/new-types.md create mode 100644 _scala3-reference/new-types/dependent-function-types-spec.md create mode 100644 _scala3-reference/new-types/dependent-function-types.md create mode 100644 _scala3-reference/new-types/intersection-types-spec.md create mode 100644 _scala3-reference/new-types/intersection-types.md create mode 100644 _scala3-reference/new-types/match-types.md create mode 100644 _scala3-reference/new-types/polymorphic-function-types.md create mode 100644 _scala3-reference/new-types/type-lambdas-spec.md create mode 100644 _scala3-reference/new-types/type-lambdas.md create mode 100644 _scala3-reference/new-types/union-types-spec.md create mode 100644 _scala3-reference/new-types/union-types.md create mode 100644 _scala3-reference/other-new-features.md create mode 100644 _scala3-reference/other-new-features/control-syntax.md create mode 100644 _scala3-reference/other-new-features/creator-applications.md create mode 100644 _scala3-reference/other-new-features/explicit-nulls.md create mode 100644 _scala3-reference/other-new-features/export.md create mode 100644 _scala3-reference/other-new-features/indentation-experimental.md create mode 100644 _scala3-reference/other-new-features/indentation.md create mode 100644 _scala3-reference/other-new-features/kind-polymorphism.md create mode 100644 _scala3-reference/other-new-features/matchable.md create mode 100644 _scala3-reference/other-new-features/named-typeargs-spec.md create mode 100644 _scala3-reference/other-new-features/named-typeargs.md create mode 100644 _scala3-reference/other-new-features/opaques-details.md create mode 100644 _scala3-reference/other-new-features/opaques.md create mode 100644 _scala3-reference/other-new-features/open-classes.md create mode 100644 _scala3-reference/other-new-features/parameter-untupling-spec.md create mode 100644 _scala3-reference/other-new-features/parameter-untupling.md create mode 100644 _scala3-reference/other-new-features/safe-initialization.md create mode 100644 _scala3-reference/other-new-features/targetName.md create mode 100644 _scala3-reference/other-new-features/threadUnsafe-annotation.md create mode 100644 _scala3-reference/other-new-features/trait-parameters.md create mode 100644 _scala3-reference/other-new-features/transparent-traits.md create mode 100644 _scala3-reference/other-new-features/type-test.md create mode 100644 _scala3-reference/overview.md create mode 100644 _scala3-reference/soft-modifier.md create mode 100644 _scala3-reference/syntax.md create mode 100644 resources/images/scala3/explicit-nulls/explicit-nulls-type-hierarchy.png diff --git a/_config.yml b/_config.yml index 395bed4a34..64f78bc718 100644 --- a/_config.yml +++ b/_config.yml @@ -45,6 +45,8 @@ collections: getting-started: output: true permalink: /:collection/:path.html + scala3-reference: # not really a collection, but this is the only way I found to be able to generate the navigation bar on the right + output: true ja: # Japanese translations output: true permalink: /:collection/:path.html @@ -125,13 +127,14 @@ defaults: permalink: "/scala3/guides/macros/:title.html" - scope: - path: "_overviews/scala3-reference" + path: "_scala3-reference" values: scala3: true partof: scala3-reference + type: section overview-name: "Scala 3 Language Reference" layout: multipage-overview - permalink: "/scala3/guides/reference/:title.html" + permalink: "/scala3/reference/:path.html" - scope: path: "scala3" @@ -142,7 +145,7 @@ defaults: highlighter: rouge permalink: /:categories/:title.html:output_ext baseurl: -scala3ref: "/scala3/guides/reference" +scala3ref: "/scala3/reference" exclude: ["vendor"] plugins: - jekyll-redirect-from diff --git a/_data/scala3-doc-nav-header.yml b/_data/scala3-doc-nav-header.yml index c390278c6d..94e3bfa5c5 100644 --- a/_data/scala3-doc-nav-header.yml +++ b/_data/scala3-doc-nav-header.yml @@ -12,6 +12,6 @@ - title: Migrate url: "/scala3/guides/migration/compatibility-intro.html" - title: Reference - url: "https://dotty.epfl.ch/docs/reference/overview.html" + url: "/scala3/reference/overview.html" - title: API url: "https://dotty.epfl.ch/api/index.html" diff --git a/_includes/sidebar-toc-multipage-overview.html b/_includes/sidebar-toc-multipage-overview.html index ceab98320f..168f4b5950 100644 --- a/_includes/sidebar-toc-multipage-overview.html +++ b/_includes/sidebar-toc-multipage-overview.html @@ -9,7 +9,7 @@
    Contents
    {% endif %}
    -
    -

    Gitter

    - Real-time (topic-specialized) chat +
    +

    Chat

    + Real-time chat on Discord
    -
    ! Jekyll/Marulu limitation {% endcomment %} +

    From f317bfc00ca5272eeaa6556cb395e3dae8e0f9cc Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Fri, 19 Apr 2013 18:07:58 +0200 Subject: [PATCH 0018/2265] Bug reporting guide. --- contribute/bug-reporting-guide.md | 120 +++++++++++++++++------------- 1 file changed, 70 insertions(+), 50 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 345dc03034..9b89f60ef4 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -3,53 +3,73 @@ layout: page title: Bug Reporting --- -# Reporting bugs to the Scala project - -The Scala project tracker is located at: - -> [http://issues.scala-lang.org](http://issues.scala-lang.org) - - -{% comment %} -WHAT THIS PAGE SHOULD TALK ABOUT: - - tracker - - what's a bug and what's not a bug? - - is it in the scala area? - - library - - compiler - - reflection - - scaladoc - - external libraries have their own trackers: - - akka - - play - - lift - - slick - - if it's a compiler crasher, it's a bug - - if the code generated throws a VerifyError, it's a bug - - if it's a regression, i.e. it worked in the previous version, it's a bug - - if the code generated is not doing what you expected, then it may or may not be a bug - - minimize the problem - - decouple from libraries - - decouple from complex build systems - - it could be a separate compilation issue - does it happen if you clean everything before? - - create small and self-contained files that, when compiled, will exhibit the behavior - - even if the behavior is not what you hoped for, it might still be correct - - if possible, look at the Scala Reference Specification and SIP documents - - or ask on the scala-internals mailing list - - okay, I'm sure it's a bug, now what? - - search for similar bugs - - the exception name and phase should be the best keywords to search for - - if the bug is there, add your test case as a comment. When someone picks up the bug, they will have to add your test case as a confirmation test - - if there's no similar bug - - try to fill in as many fields as possible: - - scala version - - component (if you know) - - labels - - assigneee may be left empty, as all new bugs are triaged - - environment - Machine architecture, Operating system, Java virtual machine version, any other environment necessary - - description - - - the test case - - the commands to trigger the bug - - the expected output - - the actual output -{% endcomment %} +# Reporting Bugs to the Scala Project + +The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. + +## Is it a Bug? + +The first step in identifying a bug is to identify which component of the Scala distribution is affected. First, ensure that your issue falls within any of the following categories: + + - **Library** bugs typically manifest themselves as run-time exceptions, or as *unexpected*/*unintuitive* behavior of Scala Standard Library methods. + - **Compiler** errors are manifested as compile time exceptions, unexpected behavior of your code at run time, or invalid behavior of the type system. + - **Reflection** are bugs that appear in the ‘scala.reflect’ package. For the *reflection* bugs , the same rules apply as for the *library* bugs. + - **Scaladoc** bugs are manifested as a logical problems in the information it presents (that is, the displayed information is incorrect, such as an incorrect subclassing relationship), or incorrect behavior of the user interface. If you'd like to suggest a change in the content of the documentation, please submit a pull request (possible to do in the browser using GitHub, which is easier and faster than filing a bug). Please file a bug about the content of documentation only if you cannot provide a suggestion for its fix. + +If your issue is related to any of the following external libraries, make sure to use the relevant project's issue tracker: + + - [Akka](http://doc.akka.io/docs/akka/current/project/issue-tracking.html) + - [Play!](http://github.com/playframework/Play20/issues) + - [Slick](http://github.com/slick/slick/issues) + - [Actors Migration Kit](http://github.com/scala/actors-migration/issues?state=open) + +The following are generally considered to be bugs: + +- **Scala Compiler Crash** If the Scala compiler is crashing with an internal error (compile time exception) you have certainly found a bug, and can move on to the next section of this document on reporting confirmed bugs. +- **Regressions** If some code snippet worked in a previous Scala release, but now no longer compiles or results in an exception, it is probably a regression. +- **Verify Errors** happen when the compiled Scala program is loaded to the Java Virtual Machine. If you're getting a *Verify Error*, you've usually found a bug. Make sure first that your project is not using stale `.class` files before reporting a new issue. + +If you have a code snippet that is resulting in bytecode which you believe is behaving incorrectly, you may or may not have found a bug. Before reporting your issue, please attempt the following: + +* Make sure you minimize your problem. To correctly minimize the problem follow the following instructions: + + 1. Gradually take apart the offensive code snippet until you believe you have the simplest representation of your problem. + + 2. Ensure that you have decoupled your code snippet from any library that could be introducing the offensive behavior. One way to achieve this is to try to recompile the offensive code snippet in isolation, outside of the context of any complex build environment. + + 3. Make sure you are compiling your project from a clean slate. Your problem could be related to separate compilation, which is difficult to detect without a clean build with new `.class` files. + +* Keep in mind that the behavior you are witnessing could be intended. Good resources for verifying whether or not behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) + +In general, if you find yourself stuck on any of these steps, asking on one of following Scala mailing lists can be helpful: + + - For compiler bugs use the [scala-internals](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) mailing list. + - For unexpected behavior use [scala-language](https://groups.google.com/forum/?fromgroups#!forum/scala-language), or [scala-user](https://groups.google.com/forum/?fromgroups#!forum/scala-user) mailing lists. + +## Reporting Confirmed Bugs is a Sin + +Before reporting your bug, make sure to check the issue tracker for other similar bugs. The exception name or a compiler phase are the best keywords to search for. If you are experiencing unexpected behavior search for method/class names where it happens. Your issue might already be reported, and a workaround might already be available for you take advantage of. If your issue *is* reported, be sure to add your test case as a comment. + +**Note:** reporting a bug that already exists creates an additional overhead for you, the Scala Team, and all people that search the issue database. To avoid this inconvenience make sure that you thoroughly search for an existing issue. + +If you cannot find your issue in the issue tracker, create a new bug. The details about creating a bug report are in the following section. + +## Creating a Bug Report + +Please make sure to fill in as many fields as possible. Make sure you've indicated the following: + + 1. **Exact Scala version** that you are using. For example, `2.10.1` or `0.11.0-RC`. If the bug happens in mulitple versions indicate all of them. + 2. **The component** that is affected by the bug. For example, the Standard Library, Scaladoc, etc. + 3. **Labels** related to your issue. For example, if you think your issue is related to the typechecker, and if you have successfully minimized your issue, label your bug as "typechecker" and "minimized" + 4. **Running environment**. Are you running on Linux? Windows? What JVM version are you using? + +In order for us to quickly triage the bug that you've found, it's important that the code snippet which produces the observed issue is as minimized as possible. For advice on minimizing your code snippet, please see the appropriate subsection of the above (Is it a Bug?). + +### Description + +In the description of your issue, be as detailed as you can. Bug reports which have the following information included are typically understood, triaged, and fixed very quickly: + + 1. Include a test case (minimized if possible) enabling us to reproduce the problematic behavior. + 2. The expected output. + 3. The actual output. + 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. \ No newline at end of file From fe39e1214a9b70ac76f223bde9670f66187b5810 Mon Sep 17 00:00:00 2001 From: Manojo Date: Tue, 23 Apr 2013 11:40:46 +0200 Subject: [PATCH 0019/2265] contribute -> get-involved --- contribute/bug-reporting-guide.md | 75 ------- contribute/documentation.md | 29 --- contribute/hacker-guide.md | 337 ------------------------------ contribute/index.md | 172 --------------- contribute/partest-guide.md | 66 ------ contribute/scala-fame.md | 9 - 6 files changed, 688 deletions(-) delete mode 100644 contribute/bug-reporting-guide.md delete mode 100644 contribute/documentation.md delete mode 100644 contribute/hacker-guide.md delete mode 100644 contribute/index.md delete mode 100644 contribute/partest-guide.md delete mode 100644 contribute/scala-fame.md diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md deleted file mode 100644 index 9b89f60ef4..0000000000 --- a/contribute/bug-reporting-guide.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -layout: page -title: Bug Reporting ---- - -# Reporting Bugs to the Scala Project - -The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. - -## Is it a Bug? - -The first step in identifying a bug is to identify which component of the Scala distribution is affected. First, ensure that your issue falls within any of the following categories: - - - **Library** bugs typically manifest themselves as run-time exceptions, or as *unexpected*/*unintuitive* behavior of Scala Standard Library methods. - - **Compiler** errors are manifested as compile time exceptions, unexpected behavior of your code at run time, or invalid behavior of the type system. - - **Reflection** are bugs that appear in the ‘scala.reflect’ package. For the *reflection* bugs , the same rules apply as for the *library* bugs. - - **Scaladoc** bugs are manifested as a logical problems in the information it presents (that is, the displayed information is incorrect, such as an incorrect subclassing relationship), or incorrect behavior of the user interface. If you'd like to suggest a change in the content of the documentation, please submit a pull request (possible to do in the browser using GitHub, which is easier and faster than filing a bug). Please file a bug about the content of documentation only if you cannot provide a suggestion for its fix. - -If your issue is related to any of the following external libraries, make sure to use the relevant project's issue tracker: - - - [Akka](http://doc.akka.io/docs/akka/current/project/issue-tracking.html) - - [Play!](http://github.com/playframework/Play20/issues) - - [Slick](http://github.com/slick/slick/issues) - - [Actors Migration Kit](http://github.com/scala/actors-migration/issues?state=open) - -The following are generally considered to be bugs: - -- **Scala Compiler Crash** If the Scala compiler is crashing with an internal error (compile time exception) you have certainly found a bug, and can move on to the next section of this document on reporting confirmed bugs. -- **Regressions** If some code snippet worked in a previous Scala release, but now no longer compiles or results in an exception, it is probably a regression. -- **Verify Errors** happen when the compiled Scala program is loaded to the Java Virtual Machine. If you're getting a *Verify Error*, you've usually found a bug. Make sure first that your project is not using stale `.class` files before reporting a new issue. - -If you have a code snippet that is resulting in bytecode which you believe is behaving incorrectly, you may or may not have found a bug. Before reporting your issue, please attempt the following: - -* Make sure you minimize your problem. To correctly minimize the problem follow the following instructions: - - 1. Gradually take apart the offensive code snippet until you believe you have the simplest representation of your problem. - - 2. Ensure that you have decoupled your code snippet from any library that could be introducing the offensive behavior. One way to achieve this is to try to recompile the offensive code snippet in isolation, outside of the context of any complex build environment. - - 3. Make sure you are compiling your project from a clean slate. Your problem could be related to separate compilation, which is difficult to detect without a clean build with new `.class` files. - -* Keep in mind that the behavior you are witnessing could be intended. Good resources for verifying whether or not behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) - -In general, if you find yourself stuck on any of these steps, asking on one of following Scala mailing lists can be helpful: - - - For compiler bugs use the [scala-internals](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) mailing list. - - For unexpected behavior use [scala-language](https://groups.google.com/forum/?fromgroups#!forum/scala-language), or [scala-user](https://groups.google.com/forum/?fromgroups#!forum/scala-user) mailing lists. - -## Reporting Confirmed Bugs is a Sin - -Before reporting your bug, make sure to check the issue tracker for other similar bugs. The exception name or a compiler phase are the best keywords to search for. If you are experiencing unexpected behavior search for method/class names where it happens. Your issue might already be reported, and a workaround might already be available for you take advantage of. If your issue *is* reported, be sure to add your test case as a comment. - -**Note:** reporting a bug that already exists creates an additional overhead for you, the Scala Team, and all people that search the issue database. To avoid this inconvenience make sure that you thoroughly search for an existing issue. - -If you cannot find your issue in the issue tracker, create a new bug. The details about creating a bug report are in the following section. - -## Creating a Bug Report - -Please make sure to fill in as many fields as possible. Make sure you've indicated the following: - - 1. **Exact Scala version** that you are using. For example, `2.10.1` or `0.11.0-RC`. If the bug happens in mulitple versions indicate all of them. - 2. **The component** that is affected by the bug. For example, the Standard Library, Scaladoc, etc. - 3. **Labels** related to your issue. For example, if you think your issue is related to the typechecker, and if you have successfully minimized your issue, label your bug as "typechecker" and "minimized" - 4. **Running environment**. Are you running on Linux? Windows? What JVM version are you using? - -In order for us to quickly triage the bug that you've found, it's important that the code snippet which produces the observed issue is as minimized as possible. For advice on minimizing your code snippet, please see the appropriate subsection of the above (Is it a Bug?). - -### Description - -In the description of your issue, be as detailed as you can. Bug reports which have the following information included are typically understood, triaged, and fixed very quickly: - - 1. Include a test case (minimized if possible) enabling us to reproduce the problematic behavior. - 2. The expected output. - 3. The actual output. - 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. \ No newline at end of file diff --git a/contribute/documentation.md b/contribute/documentation.md deleted file mode 100644 index 05b2455a5f..0000000000 --- a/contribute/documentation.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: page -title: Documentation Contributions ---- -# Contributing documentation to the Scala project - -TODO - - diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md deleted file mode 100644 index bd7ac60e71..0000000000 --- a/contribute/hacker-guide.md +++ /dev/null @@ -1,337 +0,0 @@ ---- -layout: page -title: Scala hacker guide ---- - -**Eugene Burmako** - -This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. - -This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. - -## The Running Example - -Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. - -Though, there's an annoying issue -which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) -new line tokens `%n`. - -One approach would be to go the mailing list, request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala oneself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. - -**_Of note_**: There are several types of releases/builds. Nightly builds are produced every night at a fixed time. Minor releases happen once every few months. Major releases typically happen once per year. - -## 1. Connect - -Sometimes it's appealing to hack alone and not to have to interact with others out of fear, or out of comfort. However, in the context a big project such as Scala, -this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide -unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. - -Typically bug fixes new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel -about things you want to implement. People proficient is certain areas of Scala usually monitor mailing lists, so you'll often get some help -by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. - -This is the list of language features/libraries along with their maintainers's full names and github usernames: - -{% include maintainers.html %} - -Since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. - -As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, -in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user)about our issue. - -
    Posting to scala-user
    -
    -
    Response from Martin
    - -Now that we have the approval of the feature's author, we can get to work! - -## 2. Set up - -Hacking Scala begins with creating a branch for your work item. To develop Scala we use [Git](http://git-scm.com/) -and [GitHub](http://github.com/). This section of the guide provides a short walkthrough, but if you are new to Git, -it probably makes sense to familiarize yourself with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) -online book. - -### Fork - -Log into [GitHub](http://github.com/), go to [https://github.com/scala/scala](https://github.com/scala/scala) and click the `Fork` -button in the top right corner of the page. This will create your own copy of our repository that will serve as a scratchpad for your work. - -If you're new to Git, don't be afraid of messing up-- there is no way you can corrupt our repository. - -
    Fork scala/scala
    - -### Clone - -If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` -is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), -which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from github to your local machine) by running the following on the command line: - - 16:35 ~/Projects$ git clone https://github.com/xeno-by/scala - Cloning into 'scala'... - remote: Counting objects: 258564, done. - remote: Compressing objects: 100% (58239/58239), done. - remote: Total 258564 (delta 182155), reused 254094 (delta 178356) - Receiving objects: 100% (258564/258564), 46.91 MiB | 700 KiB/s, done. - Resolving deltas: 100% (182155/182155), done. - -This will create a local directory called `scala`, which contains a clone of your own copy of our repository. The changes that you make -in this directory can be propagated back to your copy hosted on github and, ultimately, pushed into Scala when your patch is ready. - -### Branch - -Before you start making changes, always create your own branch. Never work on the `master` branch. Think of a name that describes -the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: -bug fixes and new features. - -* For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). -* For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. - -Since in our example, we're going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), we'll create a branch named `ticket/6725`. - - 16:39 ~/Projects/scala (master)$ git checkout -b ticket/6725 - Switched to a new branch 'ticket/6725' - -If you are new to Git and branching, read the [Branching Chapter](http://git-scm.com/book/en/Git-Branching) in the Git Pro book. - -### Build - -The next step after cloning your fork is setting up your machine to build Scala. The definitive guide on building Scala is located at -[https://github.com/scala/scala/blob/master/README.rst](https://github.com/scala/scala/blob/master/README.rst), but here's the summary: - -* It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). -* The build tool is `ant`. -* The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. -* The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. -* Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. - -Building Scala is as easy as running `ant` in the root of your cloned repository. Be prepared to wait for a while-- a full "clean" build -takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary -with your hardware). - - 16:50 ~/Projects/scala (ticket/6725)$ ant - Buildfile: /Users/xeno_by/Projects/scala/build.xml - - strap.clean: - - pack.clean: - - init.jars.check: - - init.jars: - [echo] Updating bootstrap libs. (To do this by hand, run ./pull-binary-libs.sh) - [exec] Resolving [943cd5c8802b2a3a64a010efb86ec19bac142e40/lib/ant/ant-contrib.jar] - - ... - - pack.bin: - [mkdir] Created dir: /Users/xeno_by/Projects/scala/build/pack/bin - - pack.done: - - build: - - BUILD SUCCESSFUL - Total time: 9 minutes 41 seconds - -### IDE - -There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. - -Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. Here are -[instructions for Eclipse](https://github.com/scala/scala/blob/master/src/eclipse/README.md) and -[instructions for Intellij](https://github.com/scala/scala/blob/master/src/intellij/README). Both of those Scala plugins provide -navigation, refactoring and error reporting functionality as well as integrated debugging. - -There also exist lighter-weight editors such as Emacs, Sublime or jEdit which provide unparalleled are faster and much less memory/compute-intensive to run, while -lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, -a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite -having significantly matured over the last year, support for our particular code base is still being improved, and is not as mature as for Eclipse and IntelliJ. - -Due to the immense variability in personal preference between IDE/editor experience, it's difficult to recommend a particular tool, and your choice should boil down to your personal preferences. - -## 3. Hack - -When hacking on your topic of choice, you'll be modifying Scala, compiling it and testing it on relevant input files. -Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break -by running a comprehensive test suite. - -We'll start by creating a `sandbox` directory (this particular name doesn't bear any special meaning), which will hold a single test file and its compilation results. First, let's make sure that -[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `ant`. The Scala compiler that we just built is located in `build/pack/bin`. - - 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox - 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox - 17:26 ~/Projects/scala/sandbox (ticket/6725)$ edit Test.scala - 17:26 ~/Projects/scala/sandbox (ticket/6725)$ cat Test.scala - object Test extends App { - val a = 1 - val s = f"$a%s%n$a%s" - println(s) - } - 17:27 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala - 17:28 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test - 1%n1 // %n should've been replaced by a newline here - -### Implement - -Now, implement your bugfix or new feature! - -Here are also some tips & tricks that have proven useful in Scala development: - -* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, - try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile - just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to - very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. -* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, - some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. -* Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how - things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. - -### Documentation - -There are several areas that one could contribute to-- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. - -##### The Scala Library - -Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it.) - -If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. - -If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](http://docs.scala-lang.org/overviews/core/collections.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](http://docs.scala-lang.org/overviews/core/parallel-collections.html). (TODO double check these links!) - -##### The Scala Compiler - -Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email (scala-internals mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: - -* [Compiler internals videos by Martin Odersky](TODO) are quite dated, but still very useful. In this three-video - series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. -* [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that - are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. -* [Reflection and Compilers by Martin Odersky](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk - at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. -* [Scala compiler corner](http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/) contains extensive documentation about - most of the post-typer phases (i.e. the backend) in the Scala compiler. -* [scala-internals](http://groups.google.com/group/scala-internals), a mailing list which hosts discussions about the core - internal design and implementation of the Scala system. - -##### Other Projects - -Tools like Scaladoc also welcome contributions. Unfortunately these smaller projects have less developer documentation. In these cases, the best thing to do is to directly explore the code base (which often contains documentation as inline comments) or to write to the appropriate maintainers for pointers. - -### Interlude - -To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725). Let's say we've tracked the `StringContext.f` interpolator -down to a macro implemented in `MacroImplementations.scala`, and there we notice that the interpolator only processes conversions, -but not tokens like `%n`. Looks like an easy fix. - - 18:44 ~/Projects/scala/sandbox (ticket/6725)$ git diff - diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/ - index 002a3fce82..4e8f02084d 100644 - --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala - +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala - @@ -117,7 +117,8 @@ abstract class MacroImplementations { - if (!strIsEmpty) { - val len = str.length - while (idx < len) { - - if (str(idx) == '%') { - + def notPercentN = str(idx) != '%' || (idx + 1 < len && str(idx + 1) != 'n') - + if (str(idx) == '%' && notPercentN) { - bldr append (str substring (start, idx)) append "%%" - start = idx + 1 - } - -After applying the fix and running `ant`, our simple test case in `sandbox/Test.scala` started working! - - 18:51 ~/Projects/scala/sandbox (ticket/6725)$ cd .. - 18:51 ~/Projects/scala (ticket/6725)$ ant - Buildfile: /Users/xeno_by/Projects/scala/build.xml - - ... - - quick.comp: - [scalacfork] Compiling 1 file to /Users/xeno_by/Projects/scala/build/quick/classes/compiler - [propertyfile] Updating property file: /Users/xeno_by/Projects/scala/build/quick/classes/compiler/compiler.properties - [stopwatch] [quick.comp.timer: 6.588 sec] - - ... - - BUILD SUCCESSFUL - Total time: 18 seconds - - 18:51 ~/Projects/scala (ticket/6725)$ cd sandbox - 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala - 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test - 1 - 1 // no longer getting the %n here - it got transformed into a newline - -### Verify - -Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. -Read up [the partest guide](/contribute/partest-guide.html) to learn the details about partest, but in a nutshell you can either -run `ant test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: - - 18:52 ~/Projects/scala/sandbox (ticket/6725)$ cd ../test - 18:56 ~/Projects/scala/test (ticket/6725)$ partest files/run/*interpol* - Testing individual files - testing: [...]/files/run/interpolationArgs.scala [ OK ] - testing: [...]/files/run/interpolationMultiline1.scala [ OK ] - testing: [...]/files/run/interpolationMultiline2.scala [ OK ] - testing: [...]/files/run/sm-interpolator.scala [ OK ] - testing: [...]/files/run/interpolation.scala [ OK ] - testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] - All of 6 tests were successful (elapsed time: 00:00:08) - -## 4. Publish - -After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. -In a nutshell, this involves: - - 1. making sure that your code and commit messages are of high quality, - 2. clicking a few buttons in the Github interface, - 3. assigning one or more reviewers which will look through your pull request. - - Let's go into each of these points in more detail. - -### Commit - -The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. -There are two things you should know here: - - 1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. - - 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. - -Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. - - 19:22 ~/Projects/scala/test (ticket/6725)$ git add ../src/compiler/scala/tools/reflect/MacroImplementations.scala - 19:22 ~/Projects/scala/test (ticket/6725)$ git commit - [ticket/6725 3c3098693b] SI-6725 `f` interpolator now supports %n tokens - 1 file changed, 2 insertions(+), 1 deletion(-) - 19:34 ~/Projects/scala/test (ticket/6725)$ git push origin ticket/6725 - Username for 'https://github.com': xeno-by - Password for 'https://xeno-by@github.com': - Counting objects: 15, done. - Delta compression using up to 8 threads. - Compressing objects: 100% (8/8), done. - Writing objects: 100% (8/8), 1.00 KiB, done. - Total 8 (delta 5), reused 0 (delta 0) - To https://github.com/xeno-by/scala - * [new branch] ticket/6725 -> ticket/6725 - -### Submit - -Now, we must simply submit our proposed patch. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) -and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will -need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. - -
    Submit a pull request
    - -### Discuss - -After the pull request has been submitted, you need to pick a reviewer (usually the person you've contacted in the beginning of your -workflow) and be ready to elaborate and adjust your patch if necessary. In this example, we picked Martin, because we had such a nice chat on the mailing list: - -
    SAssign the reviewer
    - diff --git a/contribute/index.md b/contribute/index.md deleted file mode 100644 index 05696f5165..0000000000 --- a/contribute/index.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -layout: page -title: Contribute ---- -# Contributing to the Scala project - -The Scala programming langauge is an open source project with a very -diverse community, where people from all over the world contribute their work, -with everyone benefitting from friendly help and advice, and -kindly helping others in return. So why not join the Scala community and help -everyone make things better? - -The following are typical questions you might ask when first contributing to Scala. -If you have other questions not addressed here, feel free to ask on the [scala-internals mailing list](http://groups.google.com/group/scala-internals). - -
    - -### I found something that doesn't work as expected. How to file a bug report? - -[The reporting bugs page](bug-reporting-guide.html) describes the steps to take when you find something that doesn't work -as expected. Filing in a good bug report increases the chances the ticket is fixed quickly. - -
    - -### Why contribute a patch to Scala? - -Just to name a few common reasons: - - contributing a patch is the best way to make sure your desired changes will be available in the next Scala version - - Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu - - last but not least, you will make it into the [Scala Contribuitor Hall of Fame](scala-fame.html). - -
    - -### I'd like to start hacking the Scala project, how to find something to work on? - -Depending on your skillset, you may want to contribute documentation and/or code. Documentation has always been very -appreciated work in the Scala community, as most code contributions tend to be quite scarce in explanations of how -things work and how everyone else is supposed to use them. To contribute documentation, have a look at the -[documentation page](documentation.html). - -The main Scala project consists of the standard Scala library, the Scala reflection and macros library, -the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. -Typically the scaladoc tool provides a low entry point for new committers, so it is a good first step into contributing. - -On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. - -{% comment %} Keep the space in the
    ! Jekyll/Marulu limitation {% endcomment %} -
    - -
    - -### I have this idea that I'd like to add to Scala, how do I start? - -The first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea -and on the implementation plan. Starting point ("community") bugs are usually uncontroversial, so you can jump right -ahead to hacking the scala source tree and filing a pull request. For larger changes it is best to announce the change -on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list. - -Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. - -
    - - \ No newline at end of file diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md deleted file mode 100644 index e681c569fe..0000000000 --- a/contribute/partest-guide.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -layout: page -title: Running the Test Suite ---- - -Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go the scala project folder from your local checkout and run it via `ant` or standalone as follows. - -## Using ant - -The test suite can be run by using ant from the command line: - - $ ant test.suite - -## Standalone - -There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use - - ./test/partest --show-diff --show-log --failed - -You can get a summary of the usage by running partest without arguments. - -* Most commonly you want to invoke partest with an option that tells it which part of the tests to run. For example `--all`, `--pos`, `--neg` or `--run`. -* You can test individual files by specifying individual test files (`.scala` files) as options. Several files can be tested if they are from the same category, e.g., `pos`. -* You can enable output of log and diff using the `-show-log` and `-show-diff` options. -* If you get into real trouble, and want to find out what partest does, you can run it with option `--verbose`. This info is useful as part of bug reports. -* Set custom path from where to load classes: `-classpath ` and `-buildpath `. -* You can use the `SCALAC_OPTS` environment variable to pass command line options to the compiler. -* You can use the `JAVA_OPTS` environment variable to pass command line options to the runner (e.g., for `run/jvm` tests). -* The launch scripts run partest as follows: - - scala -cp scala.tools.partest.nest.NestRunner - - Partest classes from a `quick` build, e.g., can be found in `./build/quick/classes/partest/`. - - Partest will tell you where it loads compiler/library classes from by adding the `partest.debug` property: - - scala -Dpartest.debug=true -cp scala.tools.partest.nest.NestRunner - - - -## ScalaCheck tests - -Tests that depend on [ScalaCheck](https://github.com/rickynils/scalacheck) can be added under folder `./test/files/scalacheck`. A sample test: - - import org.scalacheck._ - import Prop._ - - object Test { - val prop_ConcatLists = property{ (l1: ListInt, l2: ListInt) => - l1.size + l2.size == (l1 ::: l2).size - } - - val tests = List(("prop_ConcatLists", prop_ConcatLists)) - } - -## Troubleshooting - -### Windows - -Some tests might fail because line endings in the `.check` files and the produced results do not match. In that case, set either - - git config core.autocrlf false - -or - - git config core.autocrlf input \ No newline at end of file diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md deleted file mode 100644 index 75317be820..0000000000 --- a/contribute/scala-fame.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -layout: page -title: Scala Contribuitor Hall of Fame ---- -# Scala Hall of Fame - -A big thank you to everyone who contributed to: - - [the Scala library and compiler](https://github.com/scala/scala/contributors) - - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) \ No newline at end of file From ab597ab0b5dde3577da92ef3fd803f6e00675b94 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 30 May 2013 13:25:09 +0100 Subject: [PATCH 0020/2265] Going back to having a 'Contribute' section --- contribute/bug-reporting-guide.md | 89 +++++ contribute/documentation.md | 29 ++ contribute/hacker-guide.md | 337 ++++++++++++++++++ contribute/index.md | 201 +++++++++++ contribute/partest-guide.md | 66 ++++ .../_posts/2013-03-01-scala-fame-2013-02.md | 182 ++++++++++ .../_posts/2013-04-01-scala-fame-2013-03.md | 126 +++++++ .../_posts/2013-05-01-scala-fame-2013-04.md | 91 +++++ contribute/scala-fame.md | 14 + 9 files changed, 1135 insertions(+) create mode 100644 contribute/bug-reporting-guide.md create mode 100644 contribute/documentation.md create mode 100644 contribute/hacker-guide.md create mode 100644 contribute/index.md create mode 100644 contribute/partest-guide.md create mode 100644 contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md create mode 100644 contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md create mode 100644 contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md create mode 100644 contribute/scala-fame.md diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md new file mode 100644 index 0000000000..e286ce2002 --- /dev/null +++ b/contribute/bug-reporting-guide.md @@ -0,0 +1,89 @@ +--- +layout: page +title: Bug Reporting +--- + +# Reporting Bugs to the Scala Project + +The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. + +## Is it a Bug? + +The first step in identifying a bug is to identify which component of the Scala distribution is affected. First, ensure that your issue falls within any of the following categories: + + - **Library** bugs typically manifest themselves as run-time exceptions, or as *unexpected*/*unintuitive* behavior of Scala Standard Library methods. + - **Compiler** errors are manifested as compile time exceptions, unexpected behavior of your code at run time, or invalid behavior of the type system. + - **Reflection** are bugs that appear in the ‘scala.reflect’ package. For the *reflection* bugs , the same rules apply as for the *library* bugs. + - **Scaladoc** bugs are manifested as a logical problems in the information it presents (that is, the displayed information is incorrect, such as an incorrect subclassing relationship), or incorrect behavior of the user interface. If you'd like to suggest a change in the content of the documentation, please submit a pull request (possible to do in the browser using GitHub, which is easier and faster than filing a bug). Please file a bug about the content of documentation only if you cannot provide a suggestion for its fix. + +If your issue is related to any of the following external projects, make sure to use its appropriate issue tracker: + + - [Akka](http://doc.akka.io/docs/akka/current/project/issue-tracking.html) + - [Play!](http://github.com/playframework/Play20/issues) + - [Slick](http://github.com/slick/slick/issues) + - [Actors Migration Kit](http://github.com/scala/actors-migration/issues?state=open) + - [Scala IDE](https://scala-ide-portfolio.assembla.com/spaces/scala-ide/support/tickets) + - [sbt](https://github.com/sbt/sbt/issues) + +The following are generally considered to be bugs: + +- **Scala Compiler Crash** If the Scala compiler is crashing with an internal error (compile time exception) you have certainly found a bug, and can move on to the next section of this document on reporting confirmed bugs. +- **Regressions** If some code snippet worked in a previous Scala release, but now no longer compiles or results in an exception, it is probably a regression. +- **Verify Errors** happen when the compiled Scala program is loaded to the Java Virtual Machine. If you're getting a *Verify Error*, you've usually found a bug. Make sure first that your project is not using stale `.class` files before reporting a new issue. + +If you have a code snippet that is resulting in bytecode which you believe is behaving incorrectly, you may or may not have found a bug. Before reporting your issue, please attempt the following: + +* Make sure you minimize your problem. To correctly minimize the problem follow the following instructions: + + 1. Gradually take apart the offensive code snippet until you believe you have the simplest representation of your problem. + + 2. Ensure that you have decoupled your code snippet from any library that could be introducing the offensive behavior. One way to achieve this is to try to recompile the offensive code snippet in isolation, outside of the context of any complex build environment. If your code depends on some strictly Java library and source code is available for it, make sure that the latter is also minimized. + + 3. Make sure you are compiling your project from a clean slate. Your problem could be related to separate compilation, which is difficult to detect without a clean build with new `.class` files. + + 4. If you have encountered a bug while building your code in the IDE, then please reproduce it on the command line. The same rule applies for build tools like `sbt` or `ant`. + + 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. + +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) or [stackoveflow](http://stackoverflow.com/questions/tagged/scala). + +In general, if you find yourself stuck on any of these steps, asking on one of following Scala mailing lists can be helpful: + + - For unexpected behavior use [scala-language](https://groups.google.com/forum/?fromgroups#!forum/scala-language), or [scala-user](https://groups.google.com/forum/?fromgroups#!forum/scala-user) mailing lists. + - For compiler bugs use the [scala-internals](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) mailing list. + +* Examples of exceptions reported by the compiler which usually are not bugs: + 1. `StackOverflowError` is typically not a bug unless the stacktrace involves the internal packages of the compiler (like `scala.tools.nsc...`). Try to increase the Java stack size (`-Xss`), in most of the cases it helps. + 2. `AbstractMethodError` can occur when you did not recompile all the necessary Scala files (build tools, like `sbt`, can prevent that from happening) or you are mixing external libraries compiled for different Scala versions (for example one uses `2.10.x` and the other `2.11.x`). + +## Reporting Confirmed Bugs is a Sin + +Before reporting your bug, make sure to check the issue tracker for other similar bugs. The exception name or a compiler phase are the best keywords to search for. If you are experiencing unexpected behavior search for method/class names where it happens. Your issue might already be reported, and a workaround might already be available for you take advantage of. If your issue *is* reported, be sure to add your test case as a comment if it is different from any of the existing ones. + +**Note:** reporting a bug that already exists creates an additional overhead for you, the Scala Team, and all people that search the issue database. To avoid this inconvenience make sure that you thoroughly search for an existing issue. + +If you cannot find your issue in the issue tracker, create a new bug. The details about creating a bug report are in the following section. + +## Creating a Bug Report + +Please make sure to fill in as many fields as possible. Make sure you've indicated the following: + + 1. **Exact Scala version** that you are using. For example, `2.10.1` or `2.11.0-RC`. If the bug happens in multiple versions indicate all of them. + 2. **The component** that is affected by the bug. For example, the Standard Library, Scaladoc, etc. + 3. **Labels** related to your issue. For example, if you think your issue is related to the typechecker, and if you have successfully minimized your issue, label your bug as "typechecker" and "minimized". Issue tracker will suggest names for existing labels as you type them so try not to create duplicates. + 4. **Running environment**. Are you running on Linux? Windows? What JVM version are you using? + +In order for us to quickly triage the bug that you've found, it's important that the code snippet which produces the observed issue is as minimized as possible. For advice on minimizing your code snippet, please see the appropriate subsection of the above (Is it a Bug?). + +### Description + +In the description of your issue, be as detailed as you can. Bug reports which have the following information included are typically understood, triaged, and fixed very quickly: + + 1. Include a test case (minimized if possible) enabling us to reproduce the problematic behavior. Include your test case (and output) in proper formatting `{code}` blocks: + + {code}Here you put your classes{code} + + 2. The expected output. + 3. The actual output, including the stacktrace. + 4. Related discussion on the mailing lists, if applicable. + 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. \ No newline at end of file diff --git a/contribute/documentation.md b/contribute/documentation.md new file mode 100644 index 0000000000..05b2455a5f --- /dev/null +++ b/contribute/documentation.md @@ -0,0 +1,29 @@ +--- +layout: page +title: Documentation Contributions +--- +# Contributing documentation to the Scala project + +TODO + + diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md new file mode 100644 index 0000000000..758bb17115 --- /dev/null +++ b/contribute/hacker-guide.md @@ -0,0 +1,337 @@ +--- +layout: page +title: Scala hacker guide +--- + +**Eugene Burmako** + +This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. + +This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. + +## The Running Example + +Let's say that you particularly enjoy the new string interpolation language feature introduced in Scala 2.10.0, and you use it quite heavily. + +Though, there's an annoying issue +which you occasionally stumble upon: the formatting string interpolator `f` [does not support](https://issues.scala-lang.org/browse/SI-6725) +new line tokens `%n`. + +One approach would be to go the mailing list, request that the bug be fixed, and then to wait indefinitely for the fix arrive. Another approach would be to instead patch Scala oneself, and to submit the fix to the Scala repository in hopes that it might make it into a subsequent release. + +**_Of note_**: There are several types of releases/builds. Nightly builds are produced every night at a fixed time. Minor releases happen once every few months. Major releases typically happen once per year. + +## 1. Connect + +Sometimes it's appealing to hack alone and not to have to interact with others out of fear, or out of comfort. However, in the context a big project such as Scala, +this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide +unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. + +Typically bug fixes new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel +about things you want to implement. People proficient is certain areas of Scala usually monitor mailing lists, so you'll often get some help +by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. + +This is the list of language features/libraries along with their maintainers's full names and github usernames: + +{% include maintainers.html %} + +Since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. + +As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, +in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user)about our issue. + +
    Posting to scala-user
    +
    +
    Response from Martin
    + +Now that we have the approval of the feature's author, we can get to work! + +## 2. Set up + +Hacking Scala begins with creating a branch for your work item. To develop Scala we use [Git](http://git-scm.com/) +and [GitHub](http://github.com/). This section of the guide provides a short walkthrough, but if you are new to Git, +it probably makes sense to familiarize yourself with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) +online book. + +### Fork + +Log into [GitHub](http://github.com/), go to [https://github.com/scala/scala](https://github.com/scala/scala) and click the `Fork` +button in the top right corner of the page. This will create your own copy of our repository that will serve as a scratchpad for your work. + +If you're new to Git, don't be afraid of messing up-- there is no way you can corrupt our repository. + +
    Fork scala/scala
    + +### Clone + +If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` +is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), +which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from github to your local machine) by running the following on the command line: + + 16:35 ~/Projects$ git clone https://github.com/xeno-by/scala + Cloning into 'scala'... + remote: Counting objects: 258564, done. + remote: Compressing objects: 100% (58239/58239), done. + remote: Total 258564 (delta 182155), reused 254094 (delta 178356) + Receiving objects: 100% (258564/258564), 46.91 MiB | 700 KiB/s, done. + Resolving deltas: 100% (182155/182155), done. + +This will create a local directory called `scala`, which contains a clone of your own copy of our repository. The changes that you make +in this directory can be propagated back to your copy hosted on github and, ultimately, pushed into Scala when your patch is ready. + +### Branch + +Before you start making changes, always create your own branch. Never work on the `master` branch. Think of a name that describes +the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: +bug fixes and new features. + +* For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). +* For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. + +Since in our example, we're going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), we'll create a branch named `ticket/6725`. + + 16:39 ~/Projects/scala (master)$ git checkout -b ticket/6725 + Switched to a new branch 'ticket/6725' + +If you are new to Git and branching, read the [Branching Chapter](http://git-scm.com/book/en/Git-Branching) in the Git Pro book. + +### Build + +The next step after cloning your fork is setting up your machine to build Scala. The definitive guide on building Scala is located at +[https://github.com/scala/scala/blob/master/README.rst](https://github.com/scala/scala/blob/master/README.rst), but here's the summary: + +* It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). +* The build tool is `ant`. +* The build runs the `pull-binary-libs.sh` script to download bootstrap libs. This requires `bash` and `curl`. +* The majority of our team works on Linux and OS X, so these operating systems are guaranteed to work. +* Windows is supported, but it might have issues. Please report to [the issue tracker](https://issues.scala-lang.org/) if you encounter any. + +Building Scala is as easy as running `ant` in the root of your cloned repository. Be prepared to wait for a while-- a full "clean" build +takes 8+ minutes depending on your machine (and up to 30 minutes on older machines with less memory). Incremental builds are usually within 30-120 seconds range (again, your mileage might vary +with your hardware). + + 16:50 ~/Projects/scala (ticket/6725)$ ant + Buildfile: /Users/xeno_by/Projects/scala/build.xml + + strap.clean: + + pack.clean: + + init.jars.check: + + init.jars: + [echo] Updating bootstrap libs. (To do this by hand, run ./pull-binary-libs.sh) + [exec] Resolving [943cd5c8802b2a3a64a010efb86ec19bac142e40/lib/ant/ant-contrib.jar] + + ... + + pack.bin: + [mkdir] Created dir: /Users/xeno_by/Projects/scala/build/pack/bin + + pack.done: + + build: + + BUILD SUCCESSFUL + Total time: 9 minutes 41 seconds + +### IDE + +There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. + +Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. Here are +[instructions for Eclipse](https://github.com/scala/scala/blob/master/src/eclipse/README.md) and +[instructions for Intellij](https://github.com/scala/scala/blob/master/src/intellij/README). Both of those Scala plugins provide +navigation, refactoring and error reporting functionality as well as integrated debugging. + +There also exist lighter-weight editors such as Emacs, Sublime or jEdit which provide unparalleled are faster and much less memory/compute-intensive to run, while +lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, +a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite +having significantly matured over the last year, support for our particular code base is still being improved, and is not as mature as for Eclipse and IntelliJ. + +Due to the immense variability in personal preference between IDE/editor experience, it's difficult to recommend a particular tool, and your choice should boil down to your personal preferences. + +## 3. Hack + +When hacking on your topic of choice, you'll be modifying Scala, compiling it and testing it on relevant input files. +Typically you would want to first make sure that your changes work on a small example and afterwards verify that nothing break +by running a comprehensive test suite. + +We'll start by creating a `sandbox` directory (this particular name doesn't bear any special meaning), which will hold a single test file and its compilation results. First, let's make sure that +[the bug](https://issues.scala-lang.org/browse/SI-6725) is indeed reproducible by putting together a simple test and compiling and running it with the Scala compiler that we built using `ant`. The Scala compiler that we just built is located in `build/pack/bin`. + + 17:25 ~/Projects/scala (ticket/6725)$ mkdir sandbox + 17:26 ~/Projects/scala (ticket/6725)$ cd sandbox + 17:26 ~/Projects/scala/sandbox (ticket/6725)$ edit Test.scala + 17:26 ~/Projects/scala/sandbox (ticket/6725)$ cat Test.scala + object Test extends App { + val a = 1 + val s = f"$a%s%n$a%s" + println(s) + } + 17:27 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala + 17:28 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test + 1%n1 // %n should've been replaced by a newline here + +### Implement + +Now, implement your bugfix or new feature! + +Here are also some tips & tricks that have proven useful in Scala development: + +* If after introducing changes or updating your clone, you get `AbstractMethodError` or other linkage exceptions, + try doing `ant clean build`. Due to the way how Scala compiles traits, if a trait changes, then it's sometimes not enough to recompile + just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to + very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. +* Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, + some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. +* Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how + things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious + to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. + +### Documentation + +There are several areas that one could contribute to-- there is the Scala library, the Scala compiler, and other tools such as Scaladoc. Each area has varying amounts of documentation. + +##### The Scala Library + +Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it.) + +If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. + +If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](http://docs.scala-lang.org/overviews/core/collections.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](http://docs.scala-lang.org/overviews/core/parallel-collections.html). (TODO double check these links!) + +##### The Scala Compiler + +Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email (scala-internals mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: + +* [Compiler internals videos by Martin Odersky](TODO) are quite dated, but still very useful. In this three-video + series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. +* [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that + are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. +* [Reflection and Compilers by Martin Odersky](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Reflection-and-Compilers), a talk + at Lang.NEXT 2012 in which Martin elaborates on the design of scalac and the architecture of the reflection API. +* [Scala compiler corner](http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/) contains extensive documentation about + most of the post-typer phases (i.e. the backend) in the Scala compiler. +* [scala-internals](http://groups.google.com/group/scala-internals), a mailing list which hosts discussions about the core + internal design and implementation of the Scala system. + +##### Other Projects + +Tools like Scaladoc also welcome contributions. Unfortunately these smaller projects have less developer documentation. In these cases, the best thing to do is to directly explore the code base (which often contains documentation as inline comments) or to write to the appropriate maintainers for pointers. + +### Interlude + +To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725). Let's say we've tracked the `StringContext.f` interpolator +down to a macro implemented in `MacroImplementations.scala`, and there we notice that the interpolator only processes conversions, +but not tokens like `%n`. Looks like an easy fix. + + 18:44 ~/Projects/scala/sandbox (ticket/6725)$ git diff + diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/ + index 002a3fce82..4e8f02084d 100644 + --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala + +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala + @@ -117,7 +117,8 @@ abstract class MacroImplementations { + if (!strIsEmpty) { + val len = str.length + while (idx < len) { + - if (str(idx) == '%') { + + def notPercentN = str(idx) != '%' || (idx + 1 < len && str(idx + 1) != 'n') + + if (str(idx) == '%' && notPercentN) { + bldr append (str substring (start, idx)) append "%%" + start = idx + 1 + } + +After applying the fix and running `ant`, our simple test case in `sandbox/Test.scala` started working! + + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ cd .. + 18:51 ~/Projects/scala (ticket/6725)$ ant + Buildfile: /Users/xeno_by/Projects/scala/build.xml + + ... + + quick.comp: + [scalacfork] Compiling 1 file to /Users/xeno_by/Projects/scala/build/quick/classes/compiler + [propertyfile] Updating property file: /Users/xeno_by/Projects/scala/build/quick/classes/compiler/compiler.properties + [stopwatch] [quick.comp.timer: 6.588 sec] + + ... + + BUILD SUCCESSFUL + Total time: 18 seconds + + 18:51 ~/Projects/scala (ticket/6725)$ cd sandbox + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scalac Test.scala + 18:51 ~/Projects/scala/sandbox (ticket/6725)$ ../build/pack/bin/scala Test + 1 + 1 // no longer getting the %n here - it got transformed into a newline + +### Verify + +Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. +Read up [the partest guide](partest-guide.html) to learn the details about partest, but in a nutshell you can either +run `ant test` to go through the entire test suite (30+ minutes) or use wildcards to limit the tests to something manageable: + + 18:52 ~/Projects/scala/sandbox (ticket/6725)$ cd ../test + 18:56 ~/Projects/scala/test (ticket/6725)$ partest files/run/*interpol* + Testing individual files + testing: [...]/files/run/interpolationArgs.scala [ OK ] + testing: [...]/files/run/interpolationMultiline1.scala [ OK ] + testing: [...]/files/run/interpolationMultiline2.scala [ OK ] + testing: [...]/files/run/sm-interpolator.scala [ OK ] + testing: [...]/files/run/interpolation.scala [ OK ] + testing: [...]/files/run/stringinterpolation_macro-run.scala [ OK ] + All of 6 tests were successful (elapsed time: 00:00:08) + +## 4. Publish + +After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. +In a nutshell, this involves: + + 1. making sure that your code and commit messages are of high quality, + 2. clicking a few buttons in the Github interface, + 3. assigning one or more reviewers which will look through your pull request. + + Let's go into each of these points in more detail. + +### Commit + +The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. +There are two things you should know here: + + 1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. + + 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. + +Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. + + 19:22 ~/Projects/scala/test (ticket/6725)$ git add ../src/compiler/scala/tools/reflect/MacroImplementations.scala + 19:22 ~/Projects/scala/test (ticket/6725)$ git commit + [ticket/6725 3c3098693b] SI-6725 `f` interpolator now supports %n tokens + 1 file changed, 2 insertions(+), 1 deletion(-) + 19:34 ~/Projects/scala/test (ticket/6725)$ git push origin ticket/6725 + Username for 'https://github.com': xeno-by + Password for 'https://xeno-by@github.com': + Counting objects: 15, done. + Delta compression using up to 8 threads. + Compressing objects: 100% (8/8), done. + Writing objects: 100% (8/8), 1.00 KiB, done. + Total 8 (delta 5), reused 0 (delta 0) + To https://github.com/xeno-by/scala + * [new branch] ticket/6725 -> ticket/6725 + +### Submit + +Now, we must simply submit our proposed patch. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) +and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will +need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. + +
    Submit a pull request
    + +### Discuss + +After the pull request has been submitted, you need to pick a reviewer (usually the person you've contacted in the beginning of your +workflow) and be ready to elaborate and adjust your patch if necessary. In this example, we picked Martin, because we had such a nice chat on the mailing list: + +
    SAssign the reviewer
    + diff --git a/contribute/index.md b/contribute/index.md new file mode 100644 index 0000000000..c3be3be994 --- /dev/null +++ b/contribute/index.md @@ -0,0 +1,201 @@ +--- +layout: page +title: Get Involved +--- +# Contributing to the Scala project + +The Scala programming language is an open source project with a very +diverse community, where people from all over the world contribute their work, +with everyone benefitting from friendly help and advice, and +kindly helping others in return. So why not join the Scala community and help +everyone make things better? + +
    +
    +
    +

    Scala Internals

    +

    Get a peek into the inners of the Scala compiler.

    +
    +
    +

    Report an issue

    +

    File a bug report or a feature request.

    +
    +
    +

    Documentation

    +

    Improve the documentation itself.

    +
    +
    + +
    +
    +

    Write a SIP

    +

    Write a proposal for extending/improving Scala.

    +
    +
    +

    Hacker's guide

    +

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    +
    +
    +

    Community issues

    +

    Get cracking on some easy to approach issues.

    +
    +
    + +
    +
    +

    Unassigned issues

    +

    Get serious with some more complex issues.

    +
    +
    +

    Hall of Fame

    +

    Track your rockstar status in the community.

    +
    +
    +

    Test your contributions

    +

    Learn how to run the Scala test suite.

    +
    +
    +
    + + + +### Why contribute a patch to Scala? + +Just to name a few common reasons: + - contributing a patch is the best way to make sure your desired changes will be available in the next Scala version + - Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu + - last but not least, you will make it into the [Scala Contributor Hall of Fame](scala-fame.html). + +
    + +The main Scala project consists of the standard Scala library, the Scala reflection and macros library, +the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. +Typically the scaladoc tool provides a low entry point for new committers, so it is a good first step into contributing. + +On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. + +If you are interested in contributing code, we ask you to sign the +[Scala Contributor License Agreement](http://typesafe.com/contribute/cla/scala), +which allows us to ensure that all code submitted to the project is +unencumbered by copyrights or patents. + +
    + +### I have this idea that I'd like to add to Scala, how do I start? + +The first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea +and on the implementation plan. Starting point ("community") bugs are usually uncontroversial, so you can jump right +ahead to hacking the scala source tree and filing a pull request. For larger changes it is best to announce the change +on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list. + +Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against +the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. + +
    + + diff --git a/contribute/partest-guide.md b/contribute/partest-guide.md new file mode 100644 index 0000000000..e681c569fe --- /dev/null +++ b/contribute/partest-guide.md @@ -0,0 +1,66 @@ +--- +layout: page +title: Running the Test Suite +--- + +Partest is a custom parallel testing tool that we use to run the test suite for the Scala compiler and library. Go the scala project folder from your local checkout and run it via `ant` or standalone as follows. + +## Using ant + +The test suite can be run by using ant from the command line: + + $ ant test.suite + +## Standalone + +There are launch scripts `partest` and `partest.bat` in the `test` folder of the scala project. To have partest run failing tests only and print details about test failures to the console, you can use + + ./test/partest --show-diff --show-log --failed + +You can get a summary of the usage by running partest without arguments. + +* Most commonly you want to invoke partest with an option that tells it which part of the tests to run. For example `--all`, `--pos`, `--neg` or `--run`. +* You can test individual files by specifying individual test files (`.scala` files) as options. Several files can be tested if they are from the same category, e.g., `pos`. +* You can enable output of log and diff using the `-show-log` and `-show-diff` options. +* If you get into real trouble, and want to find out what partest does, you can run it with option `--verbose`. This info is useful as part of bug reports. +* Set custom path from where to load classes: `-classpath ` and `-buildpath `. +* You can use the `SCALAC_OPTS` environment variable to pass command line options to the compiler. +* You can use the `JAVA_OPTS` environment variable to pass command line options to the runner (e.g., for `run/jvm` tests). +* The launch scripts run partest as follows: + + scala -cp scala.tools.partest.nest.NestRunner + + Partest classes from a `quick` build, e.g., can be found in `./build/quick/classes/partest/`. + + Partest will tell you where it loads compiler/library classes from by adding the `partest.debug` property: + + scala -Dpartest.debug=true -cp scala.tools.partest.nest.NestRunner + + + +## ScalaCheck tests + +Tests that depend on [ScalaCheck](https://github.com/rickynils/scalacheck) can be added under folder `./test/files/scalacheck`. A sample test: + + import org.scalacheck._ + import Prop._ + + object Test { + val prop_ConcatLists = property{ (l1: ListInt, l2: ListInt) => + l1.size + l2.size == (l1 ::: l2).size + } + + val tests = List(("prop_ConcatLists", prop_ConcatLists)) + } + +## Troubleshooting + +### Windows + +Some tests might fail because line endings in the `.check` files and the produced results do not match. In that case, set either + + git config core.autocrlf false + +or + + git config core.autocrlf input \ No newline at end of file diff --git a/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md b/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md new file mode 100644 index 0000000000..fbdccb279c --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md @@ -0,0 +1,182 @@ +--- +layout: famearchive +title: Contributors of February 2013 +fame-year: 2013 +fame-month: 2 +fame-month-str: February +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 38 + linesAdded: 2578 + linesDeleted: 2114 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 31 + linesAdded: 7110 + linesDeleted: 9889 + rank: 2 + newContributor: false + - username: JamesIry + gravatar: https://secure.gravatar.com/avatar/72b1a6b08fd8bb3068bd281974461c3e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 23 + linesAdded: 1673 + linesDeleted: 740 + rank: 3 + newContributor: false + - username: paulp + gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 10 + linesAdded: 1466 + linesDeleted: 1097 + rank: 4 + newContributor: false + - username: gkossakowski + gravatar: https://secure.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 4 + linesDeleted: 1 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 29 + linesAdded: 2108 + linesDeleted: 724 + rank: 1 + newContributor: false + - username: lrytz + gravatar: https://secure.gravatar.com/avatar/d807dd5133a6fc14c821178e53c34091?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 3 + linesAdded: 213 + linesDeleted: 31 + rank: 2 + newContributor: false + - username: heathermiller + gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 2 + linesDeleted: 1333 + rank: 3 + newContributor: false + - username: VladUreche + gravatar: https://secure.gravatar.com/avatar/5658ed1cea041577df360fd663c570fa?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 86 + linesDeleted: 32 + rank: 3 + newContributor: false + - username: axel22 + gravatar: https://secure.gravatar.com/avatar/e9bdb4fada7e635fffb5e6f26e70cd1d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 9 + linesDeleted: 106 + rank: 4 + newContributor: false + - category: Community + authors: + - username: vigdorchik + gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 4 + linesAdded: 471 + linesDeleted: 410 + rank: 1 + newContributor: false + - username: vy + gravatar: https://secure.gravatar.com/avatar/bb8d759cf4230bcaa238fac0018af80c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 21 + linesDeleted: 21 + rank: 2 + newContributor: true + - username: u-abramchuk + gravatar: https://secure.gravatar.com/avatar/c70eb13a60582914b51966fdc1a18536?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 47 + linesDeleted: 13 + rank: 2 + newContributor: true + - username: viktorklang + gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 38 + linesDeleted: 10 + rank: 2 + newContributor: false + - username: jozic + gravatar: https://secure.gravatar.com/avatar/41fbba6d48e543a7dfa8c231b2d0286d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 8 + linesDeleted: 8 + rank: 3 + newContributor: true + - username: rnix + gravatar: https://secure.gravatar.com/avatar/0dcbf348a28f2295164c53a40d48a958?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 3 + newContributor: true + - username: mergeconflict + gravatar: https://secure.gravatar.com/avatar/9a58682929b182af7b01f0180e072fcd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 22 + linesDeleted: 15 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 26 + linesDeleted: 0 + rank: 3 + newContributor: false + - username: ViniciusMiana + gravatar: https://secure.gravatar.com/avatar/e05e828a92458c4075b498c7d2957ddd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 16 + linesDeleted: 0 + rank: 3 + newContributor: false + - username: mt2309 + gravatar: https://secure.gravatar.com/avatar/f70e1d36b9c1b9290d31e810fa1502f3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 3 + linesDeleted: 0 + rank: 3 + newContributor: false + - username: Blaisorblade + gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 0 + linesDeleted: 3 + rank: 3 + newContributor: false + - username: rkuhn + gravatar: https://secure.gravatar.com/avatar/262b1ab25e66b1e15a48fa3f68703aad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 3 + linesDeleted: 2 + rank: 3 + newContributor: false + - username: khernyo + gravatar: https://secure.gravatar.com/avatar/0e0d750a49edb4b16e8ec83816ea356e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 25 + linesDeleted: 1 + rank: 3 + newContributor: false + - username: som-snytt + gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 3 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md b/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md new file mode 100644 index 0000000000..51b489e84c --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md @@ -0,0 +1,126 @@ +--- +layout: famearchive +title: Contributors of March 2013 +fame-year: 2013 +fame-month: 3 +fame-month-str: March +fame-categories: + - category: Typesafe + authors: + - username: paulp + gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 51 + linesAdded: 38101 + linesDeleted: 37753 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 45 + linesAdded: 4824 + linesDeleted: 3092 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 26 + linesAdded: 2632 + linesDeleted: 5012 + rank: 3 + newContributor: false + - username: JamesIry + gravatar: https://secure.gravatar.com/avatar/72b1a6b08fd8bb3068bd281974461c3e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 7 + linesAdded: 1218 + linesDeleted: 171 + rank: 4 + newContributor: false + - username: dragos + gravatar: https://secure.gravatar.com/avatar/fbd384e9626d28d1648f023a5e22672f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 169 + linesDeleted: 2 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 7 + linesAdded: 212 + linesDeleted: 104 + rank: 1 + newContributor: false + - category: Community + authors: + - username: vigdorchik + gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 9 + linesAdded: 714 + linesDeleted: 619 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 7 + linesAdded: 2103 + linesDeleted: 2068 + rank: 2 + newContributor: false + - username: soc + gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 5 + linesAdded: 162 + linesDeleted: 96 + rank: 3 + newContributor: false + - username: kzys + gravatar: https://secure.gravatar.com/avatar/7828b45f8396aa361d85cead01fd99ca?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 5 + linesAdded: 129 + linesDeleted: 41 + rank: 3 + newContributor: false + - username: Blaisorblade + gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 3 + linesAdded: 72 + linesDeleted: 20 + rank: 4 + newContributor: false + - username: mesagie + gravatar: https://secure.gravatar.com/avatar/6e7dc465ed74b5250147168a0178d91c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 4 + linesDeleted: 5 + rank: 5 + newContributor: true + - username: srinivasreddy + gravatar: https://secure.gravatar.com/avatar/1f542afb3240b82fdf08632bf6cd5384?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 5 + newContributor: true + - username: mergeconflict + gravatar: https://secure.gravatar.com/avatar/9a58682929b182af7b01f0180e072fcd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 22 + linesDeleted: 15 + rank: 5 + newContributor: false + - username: sschaef + gravatar: https://secure.gravatar.com/avatar/dd80aab570fdb5f37e62de5422f44ed4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 13 + linesDeleted: 0 + rank: 5 + newContributor: false + - username: chuvoks + gravatar: https://secure.gravatar.com/avatar/415869059046602f37803890bd992fc0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 45 + linesDeleted: 24 + rank: 5 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md b/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md new file mode 100644 index 0000000000..ca59c6cdfb --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md @@ -0,0 +1,91 @@ +--- +layout: famearchive +title: Contributors of April 2013 +fame-year: 2013 +fame-month: 4 +fame-month-str: April +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 36 + linesAdded: 1274 + linesDeleted: 776 + rank: 1 + newContributor: false + - username: paulp + gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 26 + linesAdded: 1848 + linesDeleted: 1647 + rank: 2 + newContributor: false + - username: vigdorchik + gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 6 + linesAdded: 136 + linesDeleted: 186 + rank: 3 + newContributor: false + - username: adriaanm + gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 3 + linesDeleted: 1 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: magarciaEPFL + gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 9 + linesAdded: 147 + linesDeleted: 149 + rank: 1 + newContributor: false + - username: heathermiller + gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 2 + newContributor: false + - username: hubertp + gravatar: https://secure.gravatar.com/avatar/e0dec64f93778e5c689c3873078a406f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 54 + linesDeleted: 46 + rank: 2 + newContributor: false + - category: Community + authors: + - username: som-snytt + gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 11 + linesAdded: 1000 + linesDeleted: 509 + rank: 1 + newContributor: false + - username: soc + gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 3 + linesAdded: 37 + linesDeleted: 22 + rank: 2 + newContributor: false + - username: huitseeker + gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 15 + linesDeleted: 19 + rank: 3 + newContributor: false + - username: namin + gravatar: https://secure.gravatar.com/avatar/f2adf4eb83e1221b519d23bf0bdc98d2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 6 + linesDeleted: 11 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md new file mode 100644 index 0000000000..98fad6e629 --- /dev/null +++ b/contribute/scala-fame.md @@ -0,0 +1,14 @@ +--- +layout: page +title: Scala Contribuitor Hall of Fame +--- +# Scala Hall of Fame + +A big thank you to everyone who contributed to: + - [the Scala library and compiler](https://github.com/scala/scala/contributors) + - [the Scala documentation website](https://github.com/scala/scala.github.com/contributors) + +{% for data in site.categories.scala-fame-data limit:1 %} + {% assign famedata = data %} + {% include render-scala-fame.html %} +{% endfor %} From 8559ddab546a4548f3cca197793f3809e3fe8d7f Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 30 May 2013 13:26:48 +0100 Subject: [PATCH 0021/2265] Going back to having a 'Contribute' section, take 2 --- contribute/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index c3be3be994..6e07e5b84c 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,6 +1,6 @@ --- layout: page -title: Get Involved +title: Contribute --- # Contributing to the Scala project From 96c6854e2422b5a813d80ac737e4f58958a17c71 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Wed, 5 Jun 2013 11:50:04 +0200 Subject: [PATCH 0022/2265] Making contribute page full width --- contribute/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index 6e07e5b84c..9b6024dcf9 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,5 +1,5 @@ --- -layout: page +layout: page-full-width title: Contribute --- # Contributing to the Scala project From 2ddf889be5bad81e58ee391e1cf2cee85d3c5b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 6 Jun 2013 09:09:53 +0200 Subject: [PATCH 0023/2265] Added hall of fame of May 2013. --- .../_posts/2013-06-01-scala-fame-2013-05.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md diff --git a/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md b/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md new file mode 100644 index 0000000000..2829d6a4aa --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-06-01-scala-fame-2013-05.md @@ -0,0 +1,105 @@ +--- +layout: famearchive +title: Contributors of May 2013 +fame-year: 2013 +fame-month: 5 +fame-month-str: May +fame-categories: + - category: Typesafe + authors: + - username: paulp + gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 54 + linesAdded: 3465 + linesDeleted: 2035 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 13 + linesAdded: 525 + linesDeleted: 66 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 5 + linesAdded: 245 + linesDeleted: 81 + rank: 3 + newContributor: false + - username: viktorklang + gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 51 + linesDeleted: 32 + rank: 4 + newContributor: false + - username: phaller + gravatar: https://secure.gravatar.com/avatar/3b84657fdb075382e3781310ca8a9a70?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 1965 + linesDeleted: 1086 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 19 + linesAdded: 742 + linesDeleted: 468 + rank: 1 + newContributor: false + - username: magarciaEPFL + gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 11 + linesAdded: 1214 + linesDeleted: 1069 + rank: 2 + newContributor: false + - username: heathermiller + gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 10 + linesDeleted: 7 + rank: 3 + newContributor: false + - category: Community + authors: + - username: soc + gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 12 + linesAdded: 254 + linesDeleted: 1135 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 6 + linesAdded: 454 + linesDeleted: 403 + rank: 2 + newContributor: false + - username: vigdorchik + gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 42 + linesDeleted: 32 + rank: 3 + newContributor: false + - username: dcsobral + gravatar: https://secure.gravatar.com/avatar/6d43da5df0e52fc31c55e6a227bb23f4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 6 + linesDeleted: 2 + rank: 4 + newContributor: false + - username: kzys + gravatar: https://secure.gravatar.com/avatar/7828b45f8396aa361d85cead01fd99ca?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 25 + linesDeleted: 9 + rank: 4 + newContributor: false +--- From 81e54742affd89a43d638b815593089857f277cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 6 Jun 2013 09:17:01 +0200 Subject: [PATCH 0024/2265] 3-column layout for hall of fame pages. --- contribute/scala-fame.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index 98fad6e629..084c120e27 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -1,5 +1,5 @@ --- -layout: page +layout: page-full-width title: Scala Contribuitor Hall of Fame --- # Scala Hall of Fame From 5a8dd183d57819c319f69e3d92ee73aabf6c934f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 6 Jun 2013 09:28:28 +0200 Subject: [PATCH 0025/2265] Added namin in EPFL people. --- .../_posts/2013-03-01-scala-fame-2013-02.md | 63 +++++----- .../_posts/2013-04-01-scala-fame-2013-03.md | 63 ++++++---- .../_posts/2013-05-01-scala-fame-2013-04.md | 115 ++++++++++++------ 3 files changed, 152 insertions(+), 89 deletions(-) diff --git a/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md b/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md index fbdccb279c..376563abce 100644 --- a/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md +++ b/contribute/scala-fame-data/_posts/2013-03-01-scala-fame-2013-02.md @@ -35,20 +35,41 @@ fame-categories: linesDeleted: 1097 rank: 4 newContributor: false + - username: viktorklang + gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 3 + linesAdded: 84 + linesDeleted: 53 + rank: 5 + newContributor: false - username: gkossakowski gravatar: https://secure.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 2 linesAdded: 4 linesDeleted: 1 - rank: 5 + rank: 6 + newContributor: false + - username: huitseeker + gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 26 + linesDeleted: 0 + rank: 7 + newContributor: false + - username: rkuhn + gravatar: https://secure.gravatar.com/avatar/262b1ab25e66b1e15a48fa3f68703aad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 3 + linesDeleted: 2 + rank: 7 newContributor: false - category: EPFL authors: - username: xeno-by gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 29 - linesAdded: 2108 - linesDeleted: 724 + commits: 36 + linesAdded: 3379 + linesDeleted: 1635 rank: 1 newContributor: false - username: lrytz @@ -72,6 +93,13 @@ fame-categories: linesDeleted: 32 rank: 3 newContributor: false + - username: hubertp + gravatar: https://secure.gravatar.com/avatar/e0dec64f93778e5c689c3873078a406f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 2 + linesAdded: 297 + linesDeleted: 100 + rank: 3 + newContributor: false - username: axel22 gravatar: https://secure.gravatar.com/avatar/e9bdb4fada7e635fffb5e6f26e70cd1d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 @@ -102,13 +130,6 @@ fame-categories: linesDeleted: 13 rank: 2 newContributor: true - - username: viktorklang - gravatar: https://secure.gravatar.com/avatar/4f674b2e79f1663864ff78e07ce4c8a8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 2 - linesAdded: 38 - linesDeleted: 10 - rank: 2 - newContributor: false - username: jozic gravatar: https://secure.gravatar.com/avatar/41fbba6d48e543a7dfa8c231b2d0286d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 @@ -130,10 +151,10 @@ fame-categories: linesDeleted: 15 rank: 3 newContributor: false - - username: huitseeker - gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + - username: mt2309 + gravatar: https://secure.gravatar.com/avatar/f70e1d36b9c1b9290d31e810fa1502f3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 - linesAdded: 26 + linesAdded: 3 linesDeleted: 0 rank: 3 newContributor: false @@ -144,13 +165,6 @@ fame-categories: linesDeleted: 0 rank: 3 newContributor: false - - username: mt2309 - gravatar: https://secure.gravatar.com/avatar/f70e1d36b9c1b9290d31e810fa1502f3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 0 - rank: 3 - newContributor: false - username: Blaisorblade gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 @@ -158,13 +172,6 @@ fame-categories: linesDeleted: 3 rank: 3 newContributor: false - - username: rkuhn - gravatar: https://secure.gravatar.com/avatar/262b1ab25e66b1e15a48fa3f68703aad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 2 - rank: 3 - newContributor: false - username: khernyo gravatar: https://secure.gravatar.com/avatar/0e0d750a49edb4b16e8ec83816ea356e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 diff --git a/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md b/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md index 51b489e84c..0feb88618a 100644 --- a/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md +++ b/contribute/scala-fame-data/_posts/2013-04-01-scala-fame-2013-03.md @@ -16,16 +16,16 @@ fame-categories: newContributor: false - username: retronym gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 45 - linesAdded: 4824 + commits: 46 + linesAdded: 4908 linesDeleted: 3092 rank: 2 newContributor: false - username: adriaanm gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 26 - linesAdded: 2632 - linesDeleted: 5012 + commits: 27 + linesAdded: 2675 + linesDeleted: 5043 rank: 3 newContributor: false - username: JamesIry @@ -46,11 +46,18 @@ fame-categories: authors: - username: xeno-by gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 7 - linesAdded: 212 - linesDeleted: 104 + commits: 11 + linesAdded: 295 + linesDeleted: 129 rank: 1 newContributor: false + - username: magarciaEPFL + gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 6 + linesAdded: 89 + linesDeleted: 44 + rank: 2 + newContributor: false - category: Community authors: - username: vigdorchik @@ -69,8 +76,8 @@ fame-categories: newContributor: false - username: soc gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 5 - linesAdded: 162 + commits: 6 + linesAdded: 166 linesDeleted: 96 rank: 3 newContributor: false @@ -79,48 +86,62 @@ fame-categories: commits: 5 linesAdded: 129 linesDeleted: 41 - rank: 3 + rank: 4 newContributor: false - username: Blaisorblade gravatar: https://secure.gravatar.com/avatar/a3a676c96a88feb813010e67af012ca0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 3 linesAdded: 72 linesDeleted: 20 - rank: 4 + rank: 5 newContributor: false - - username: mesagie - gravatar: https://secure.gravatar.com/avatar/6e7dc465ed74b5250147168a0178d91c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + - username: starblood + gravatar: https://secure.gravatar.com/avatar/bd3514b960213c6a7ff5fd3186675429?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 - linesAdded: 4 - linesDeleted: 5 - rank: 5 + linesAdded: 1 + linesDeleted: 1 + rank: 6 newContributor: true - username: srinivasreddy gravatar: https://secure.gravatar.com/avatar/1f542afb3240b82fdf08632bf6cd5384?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 1 linesDeleted: 1 - rank: 5 + rank: 6 + newContributor: true + - username: mesagie + gravatar: https://secure.gravatar.com/avatar/6e7dc465ed74b5250147168a0178d91c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 4 + linesDeleted: 5 + rank: 6 newContributor: true - username: mergeconflict gravatar: https://secure.gravatar.com/avatar/9a58682929b182af7b01f0180e072fcd?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 22 linesDeleted: 15 - rank: 5 + rank: 6 newContributor: false - username: sschaef gravatar: https://secure.gravatar.com/avatar/dd80aab570fdb5f37e62de5422f44ed4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 13 linesDeleted: 0 - rank: 5 + rank: 6 + newContributor: false + - username: ihji + gravatar: https://secure.gravatar.com/avatar/866a258f0c9fa9529aa47ebd96fe599c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 33 + linesDeleted: 6 + rank: 6 newContributor: false - username: chuvoks gravatar: https://secure.gravatar.com/avatar/415869059046602f37803890bd992fc0?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 45 linesDeleted: 24 - rank: 5 + rank: 6 newContributor: false --- diff --git a/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md b/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md index ca59c6cdfb..e2cd419e9b 100644 --- a/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md +++ b/contribute/scala-fame-data/_posts/2013-05-01-scala-fame-2013-04.md @@ -7,85 +7,120 @@ fame-month-str: April fame-categories: - category: Typesafe authors: - - username: retronym - gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 36 - linesAdded: 1274 - linesDeleted: 776 - rank: 1 - newContributor: false - username: paulp gravatar: https://secure.gravatar.com/avatar/c25d674f69bb9c155f265a7482712be4?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 26 - linesAdded: 1848 - linesDeleted: 1647 + commits: 38 + linesAdded: 3745 + linesDeleted: 2973 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://secure.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 37 + linesAdded: 1309 + linesDeleted: 777 rank: 2 newContributor: false - - username: vigdorchik - gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 6 - linesAdded: 136 - linesDeleted: 186 + - username: huitseeker + gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 3 + linesAdded: 16 + linesDeleted: 24 rank: 3 newContributor: false - username: adriaanm gravatar: https://secure.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 1 - linesAdded: 3 - linesDeleted: 1 + commits: 2 + linesAdded: 35 + linesDeleted: 82 rank: 4 newContributor: false - category: EPFL authors: - username: magarciaEPFL gravatar: https://secure.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 9 - linesAdded: 147 - linesDeleted: 149 + commits: 11 + linesAdded: 238 + linesDeleted: 204 rank: 1 newContributor: false + - username: xeno-by + gravatar: https://secure.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 4 + linesAdded: 208 + linesDeleted: 121 + rank: 2 + newContributor: false + - username: namin + gravatar: https://secure.gravatar.com/avatar/f2adf4eb83e1221b519d23bf0bdc98d2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 6 + linesDeleted: 11 + rank: 3 + newContributor: false - username: heathermiller gravatar: https://secure.gravatar.com/avatar/54d0b6494927c0040b96ed327202e8dc?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 1 linesDeleted: 1 - rank: 2 + rank: 3 newContributor: false - username: hubertp gravatar: https://secure.gravatar.com/avatar/e0dec64f93778e5c689c3873078a406f?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 linesAdded: 54 linesDeleted: 46 - rank: 2 + rank: 3 newContributor: false - category: Community authors: - username: som-snytt gravatar: https://secure.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 11 - linesAdded: 1000 - linesDeleted: 509 + commits: 16 + linesAdded: 2561 + linesDeleted: 1150 rank: 1 newContributor: false + - username: vigdorchik + gravatar: https://secure.gravatar.com/avatar/d497b1b875b7f68414daff74485b8501?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 9 + linesAdded: 235 + linesDeleted: 321 + rank: 2 + newContributor: false - username: soc gravatar: https://secure.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png - commits: 3 - linesAdded: 37 - linesDeleted: 22 - rank: 2 + commits: 4 + linesAdded: 38 + linesDeleted: 26 + rank: 3 newContributor: false - - username: huitseeker - gravatar: https://secure.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + - username: ihji + gravatar: https://secure.gravatar.com/avatar/866a258f0c9fa9529aa47ebd96fe599c?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 2 - linesAdded: 15 - linesDeleted: 19 - rank: 3 + linesAdded: 13 + linesDeleted: 2 + rank: 4 newContributor: false - - username: namin - gravatar: https://secure.gravatar.com/avatar/f2adf4eb83e1221b519d23bf0bdc98d2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + - username: bjornregnell + gravatar: https://secure.gravatar.com/avatar/b1d20c98b0eeb72829523144b9174ca2?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png commits: 1 - linesAdded: 6 - linesDeleted: 11 - rank: 4 + linesAdded: 3 + linesDeleted: 2 + rank: 5 + newContributor: true + - username: aldenml + gravatar: https://secure.gravatar.com/avatar/bbf061bd484515c156f662a65820c226?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 4 + linesDeleted: 4 + rank: 5 + newContributor: true + - username: eed3si9n + gravatar: https://secure.gravatar.com/avatar/8f41595db400be30176f6f04630c2842?s=60&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + commits: 1 + linesAdded: 304 + linesDeleted: 6 + rank: 5 newContributor: false --- From 5056003f15841f8f8362b0240f141e2b0aced0a2 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Sat, 8 Jun 2013 00:45:43 +0200 Subject: [PATCH 0026/2265] Styling contents and other cleanups --- contribute/bug-reporting-guide.md | 2 -- contribute/hacker-guide.md | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index e286ce2002..f04503f968 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -3,8 +3,6 @@ layout: page title: Bug Reporting --- -# Reporting Bugs to the Scala Project - The Scala project tracker is located at [http://issues.scala-lang.org](http://issues.scala-lang.org). Before you submit a bug make sure that it is certainly a bug by following instructions in *Is it a Bug?*. ## Is it a Bug? diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 758bb17115..484d3036a1 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -1,10 +1,9 @@ --- layout: page title: Scala hacker guide +by: Eugene Burmako --- - -**Eugene Burmako** - +
    This guide is intended to help you get from an idea of fixing a bug or implementing a new feature into a nightly Scala build, and, ultimately, to a production release of Scala incorporating your idea. This guide covers the entire process, from the conception of your idea or bugfix to the point where it is merged into Scala. Throughout, we will use a running example of an idea or bugfix one might wish to contribute. From 43b72d980cd057dc11dafb6f73d37bbad1f6e491 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Sat, 8 Jun 2013 20:32:38 +0200 Subject: [PATCH 0027/2265] Formatting fix to hackers guide --- contribute/hacker-guide.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 484d3036a1..d3ee84456f 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -287,9 +287,9 @@ run `ant test` to go through the entire test suite (30+ minutes) or use wildcard After development is finished, it's time to publish the code and submit your patch for discussion and potential inclusion into Scala. In a nutshell, this involves: - 1. making sure that your code and commit messages are of high quality, - 2. clicking a few buttons in the Github interface, - 3. assigning one or more reviewers which will look through your pull request. +1. making sure that your code and commit messages are of high quality, +2. clicking a few buttons in the Github interface, +3. assigning one or more reviewers which will look through your pull request. Let's go into each of these points in more detail. @@ -298,9 +298,8 @@ In a nutshell, this involves: The [Git Basics](http://git-scm.com/book/en/Git-Basics) chapter in the Git online book covers most of the basic workflow during this stage. There are two things you should know here: - 1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. - - 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. +1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. +2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. From 05854a11c3be0fbd2dfb0f10b27d5fc89cdffcac Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Fri, 12 Jul 2013 12:25:39 +0200 Subject: [PATCH 0028/2265] Moving community tickets back to contribute section --- contribute/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contribute/index.md b/contribute/index.md index 9b6024dcf9..7338d06c2c 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -93,6 +93,10 @@ the Scala project source tree. The [hacker guide](hacker-guide.html) will explai
    +## Community Tickets + +
    + diff --git a/contribute/index.md b/contribute/index.md index 656109cf02..c7b822ae04 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -1,199 +1,19 @@ --- -layout: page-full-width +layout: page title: Contribute --- -# Contributing to the Scala project -The Scala programming language is an open source project with a very -diverse community, where people from all over the world contribute their work, -with everyone benefitting from friendly help and advice, and -kindly helping others in return. So why not join the Scala community and help -everyone make things better? +## How to help? -
    -
    -
    -

    Scala Internals

    -

    Get a peek into the inners of the Scala compiler.

    -
    -
    -

    Report an issue

    -

    File a bug report or a feature request.

    -
    -
    -

    Documentation

    -

    Improve the documentation itself.

    -
    -
    +### Reporting bugs -
    -
    -

    Write a SIP

    -

    Write a proposal for extending/improving Scala.

    -
    -
    -

    Hacker's guide

    -

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    -
    -
    -

    Community issues

    -

    Get cracking on some easy to approach issues.

    -
    -
    +See our [bug reporting guide](./bug-reporting-guide.html) to learn +how to efficiently report a bug. -
    -
    -

    Unassigned issues

    -

    Get serious with some more complex issues.

    -
    -
    -

    Hall of Fame

    -

    Track your rockstar status in the community.

    -
    -
    -

    Test your contributions

    -

    Learn how to run the Scala test suite.

    -
    -
    -
    +### Patch the core +Want to dive into the hardcore business? Check out our +[selection of community tickets](./community-tickets.html), +which are good starting points to contributing. - -### Why contribute a patch to Scala? - -Just to name a few common reasons: - - contributing a patch is the best way to make sure your desired changes will be available in the next Scala version - - Scala is written in Scala, so going through the source code and patching it will improve your Scala-fu - - last but not least, you will make it into the [Scala Contributor Hall of Fame](scala-fame.html). - -
    - -The main Scala project consists of the standard Scala library, the Scala reflection and macros library, -the Scala compiler and the Scaladoc tool. This means there's plenty to choose from when deciding what to work on. -Typically the scaladoc tool provides a low entry point for new committers, so it is a good first step into contributing. - -On the Scala bug tracker you will find many bugs that are [marked as good starting points to contributing ("community" bugs)](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12111) or [that are not currently assigned](https://issues.scala-lang.org/secure/IssueNavigator.jspa?requestId=12112) and that you could pick up. Once you decided on a ticket to look at, see the next step on how to proceed further. - -If you are interested in contributing code, we ask you to sign the -[Scala Contributor License Agreement](http://typesafe.com/contribute/cla/scala), -which allows us to ensure that all code submitted to the project is -unencumbered by copyrights or patents. - -
    - -### I have this idea that I'd like to add to Scala, how do I start? - -The first step to making a change is to discuss it with the community at large, to make sure everyone agrees on the idea -and on the implementation plan. Starting point ("community") bugs are usually uncontroversial, so you can jump right -ahead to hacking the scala source tree and filing a pull request. For larger changes it is best to announce the change -on the [scala-internals](http://groups.google.com/group/scala-internals) mailing list and get developer feedback. For really complex changes, a [Scala Improvement Process (SIP)](http://docs.scala-lang.org/sips/) document might be required, but the first step is always to discuss it on the mailing list. - -Contributions, big or small, simple or complex, controversial or undisputed, need to materialize as patches against -the Scala project source tree. The [hacker guide](hacker-guide.html) will explain how to materialize your idea into a full-fledged pull request against the Scala code base. - - +More info in our [contributing guide](./guide.html). From 22dc8088db52f999a4290dc3455e1231557b1aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Wed, 17 Jul 2013 17:31:21 +0200 Subject: [PATCH 0032/2265] A bit of rewording on the contribute page. --- contribute/index.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contribute/index.md b/contribute/index.md index c7b822ae04..3cd58f8631 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -10,10 +10,16 @@ title: Contribute See our [bug reporting guide](./bug-reporting-guide.html) to learn how to efficiently report a bug. -### Patch the core +### Help with the documentation + +An easy but very important way to contribute to Scala is to +[help with the documentation](http://docs.scala-lang.org/contribute.html). + +### Compiler and other tools Want to dive into the hardcore business? Check out our [selection of community tickets](./community-tickets.html), -which are good starting points to contributing. +which are good starting points to contributing to the compiler and +surrounding tools, like ScalaDoc. More info in our [contributing guide](./guide.html). From 684bb8b49fdd1baf968b04b74395adccd1e8962a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 18 Jul 2013 11:03:40 +0200 Subject: [PATCH 0033/2265] Dropped 3 boxes on the Contribute guide. * SIP * Unassigned tickets * Partest The two first are not supposed to be entry points, and they still have a link further down in the text. Partest is mentioned in the Hacker's guide. And there is no point in using partest without first going through the hacker's guide. --- contribute/guide.md | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index 28adc54e6b..4841496253 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -27,32 +27,17 @@ everyone make things better?
    -

    Write a SIP

    -

    Write a proposal for extending/improving Scala.

    +

    Community issues

    +

    Get cracking on some easy to approach issues.

    Hacker's guide

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    -
    -

    Community issues

    -

    Get cracking on some easy to approach issues.

    -
    -
    - -
    -
    -

    Unassigned issues

    -

    Get serious with some more complex issues.

    -

    Hall of Fame

    Track your rockstar status in the community.

    -
    -

    Test your contributions

    -

    Learn how to run the Scala test suite.

    -
    From 13462b997cddbc48e8392f6324fafb2a30b678b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 18 Jul 2013 11:10:07 +0200 Subject: [PATCH 0034/2265] Moved the contribute intro text to contribute/. Before it was in contribute/guide.html, but now contribute/ is the landing page for contributions. --- contribute/guide.md | 6 ------ contribute/index.md | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contribute/guide.md b/contribute/guide.md index 4841496253..ac27e53719 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -3,12 +3,6 @@ layout: page-full-width title: Contributing guide --- -The Scala programming language is an open source project with a very -diverse community, where people from all over the world contribute their work, -with everyone benefitting from friendly help and advice, and -kindly helping others in return. So why not join the Scala community and help -everyone make things better? -
    diff --git a/contribute/index.md b/contribute/index.md index 3cd58f8631..d2402cf4d2 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -3,6 +3,12 @@ layout: page title: Contribute --- +The Scala programming language is an open source project with a very +diverse community, where people from all over the world contribute their work, +with everyone benefitting from friendly help and advice, and +kindly helping others in return. So why not join the Scala community and help +everyone make things better? + ## How to help? ### Reporting bugs From 966a0f22e50d6cf9a2e2f0ac4cf042d369d69490 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Tue, 30 Jul 2013 10:01:55 -0700 Subject: [PATCH 0035/2265] Removing double title on the hall of fame --- contribute/scala-fame.md | 1 - 1 file changed, 1 deletion(-) diff --git a/contribute/scala-fame.md b/contribute/scala-fame.md index 084c120e27..81bb76ee3a 100644 --- a/contribute/scala-fame.md +++ b/contribute/scala-fame.md @@ -2,7 +2,6 @@ layout: page-full-width title: Scala Contribuitor Hall of Fame --- -# Scala Hall of Fame A big thank you to everyone who contributed to: - [the Scala library and compiler](https://github.com/scala/scala/contributors) From 688d5568e0a74ea8a7b83f3d56f08378fc1eb516 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Wed, 31 Jul 2013 01:34:52 +0200 Subject: [PATCH 0036/2265] =?UTF-8?q?Add=20section=20=E2=80=9CTest?= =?UTF-8?q?=E2=80=9D=20and=20=E2=80=9CMerge=E2=80=9D,=20rename=20=E2=80=9C?= =?UTF-8?q?Discuss=E2=80=9D=20to=20=E2=80=9CReview=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/hacker-guide.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index d3ee84456f..c471baceca 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -221,8 +221,8 @@ Tools like Scaladoc also welcome contributions. Unfortunately these smaller proj ### Interlude -To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725). Let's say we've tracked the `StringContext.f` interpolator -down to a macro implemented in `MacroImplementations.scala`, and there we notice that the interpolator only processes conversions, +To fix [the bug we're interested in](https://issues.scala-lang.org/browse/SI-6725) we've tracked the `StringContext.f` interpolator +down to a macro implemented in `MacroImplementations.scala` There we notice that the interpolator only processes conversions, but not tokens like `%n`. Looks like an easy fix. 18:44 ~/Projects/scala/sandbox (ticket/6725)$ git diff @@ -265,6 +265,17 @@ After applying the fix and running `ant`, our simple test case in `sandbox/Test. 1 1 // no longer getting the %n here - it got transformed into a newline +### Test + +To guard your change against accidental breakage in the future, it is important to add tests. +I have already written one test earlier, so that's a good start but not enough! Apart from obvious usages of our new functionality, we need to cover corner-cases as well. + +Adding tests to the test suite is as easy as moving them to the appropriate directory: + +* Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/master/test/files/pos) +* Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/master/test/files/neg) +* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/master/test/files/run) + ### Verify Now to make sure that my fix doesn't break anything I need to run the test suite using the `partest` tool we wrote to test Scala. @@ -326,10 +337,15 @@ need to sign the contributor license agreement, which [can be done online](http:
    Submit a pull request
    -### Discuss +### Review After the pull request has been submitted, you need to pick a reviewer (usually the person you've contacted in the beginning of your workflow) and be ready to elaborate and adjust your patch if necessary. In this example, we picked Martin, because we had such a nice chat on the mailing list:
    SAssign the reviewer
    +## Merge + +After your reviewer is happy with your code (usually signalled by a LGTM — “Looks good to me”), your job is done. +Note that there can be a gap between a successful review and the merge, because not every reviewer has merge rights. In that case, someone else from the team will pick up your pull request and merge it. +So don't be confused if your reviewer says “LGTM”, but your code doesn't get merged immediately. From 29705fcb98500b5c2c586cbf8f06c411a1b1d53e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 31 Jul 2013 08:10:21 -0400 Subject: [PATCH 0037/2265] minor copyediting to hacker guide --- contribute/hacker-guide.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index c471baceca..28ea69bc3f 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -26,11 +26,11 @@ Sometimes it's appealing to hack alone and not to have to interact with others o this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel -about things you want to implement. People proficient is certain areas of Scala usually monitor mailing lists, so you'll often get some help +Typically bug fixes and new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel +about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. -This is the list of language features/libraries along with their maintainers's full names and github usernames: +This is the list of language features/libraries along with their maintainers's full names and GitHub usernames: {% include maintainers.html %} @@ -65,7 +65,7 @@ If you're new to Git, don't be afraid of messing up-- there is no way you can co If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), -which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from github to your local machine) by running the following on the command line: +which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from GitHub to your local machine) by running the following on the command line: 16:35 ~/Projects$ git clone https://github.com/xeno-by/scala Cloning into 'scala'... @@ -76,7 +76,7 @@ which covers some of the things that will follow below. Then, _clone_ your repos Resolving deltas: 100% (182155/182155), done. This will create a local directory called `scala`, which contains a clone of your own copy of our repository. The changes that you make -in this directory can be propagated back to your copy hosted on github and, ultimately, pushed into Scala when your patch is ready. +in this directory can be propagated back to your copy hosted on GitHub and, ultimately, pushed into Scala when your patch is ready. ### Branch @@ -299,10 +299,10 @@ After development is finished, it's time to publish the code and submit your pat In a nutshell, this involves: 1. making sure that your code and commit messages are of high quality, -2. clicking a few buttons in the Github interface, -3. assigning one or more reviewers which will look through your pull request. +2. clicking a few buttons in the GitHub interface, +3. assigning one or more reviewers who will look through your pull request. - Let's go into each of these points in more detail. +Let's go into each of these points in more detail. ### Commit @@ -312,7 +312,7 @@ There are two things you should know here: 1. Commit messages are often the only way to understand the intentions of authors of code written a few years ago. Thus, writing a quality is of utmost importance. The more context you provide for the change you've introduced, the larger the chance that some future maintainer understand your intentions. Consult [the pull request policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for more information about the desired style of your commits. 2. Keeping Scala's git history clean is also important. Therefore we won't accept pull requests for bug fixes that have more than one commit. For features, it is okay to have several commits, but all tests need to pass after every single commit. To clean up your commit structure, you want to [rewrite history](http://git-scm.com/book/en/Git-Branching-Rebasing) using `git rebase` so that your commits are against the latest revision of `master`. -Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on Github. +Once you are satisfied with your work, synced with `master` and cleaned up your commits you are ready to submit a patch to the central Scala repository. Before proceeding make sure you have pushed all of your local changes to your fork on GitHub. 19:22 ~/Projects/scala/test (ticket/6725)$ git add ../src/compiler/scala/tools/reflect/MacroImplementations.scala 19:22 ~/Projects/scala/test (ticket/6725)$ git commit @@ -331,7 +331,7 @@ Once you are satisfied with your work, synced with `master` and cleaned up your ### Submit -Now, we must simply submit our proposed patch. Navigate to your branch in Github (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) +Now, we must simply submit our proposed patch. Navigate to your branch in GitHub (for me it was `https://github.com/xeno-by/scala/tree/ticket/6725`) and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. From 50d50417d01e7eb834088ce5a3bf924b862eb26f Mon Sep 17 00:00:00 2001 From: Antoine Gourlay Date: Wed, 31 Jul 2013 23:46:24 +0200 Subject: [PATCH 0038/2265] fix links in hacker guide and various typos. --- contribute/bug-reporting-guide.md | 4 ++-- contribute/hacker-guide.md | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index f04503f968..4160dcf438 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -45,7 +45,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be * Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) or [stackoveflow](http://stackoverflow.com/questions/tagged/scala). -In general, if you find yourself stuck on any of these steps, asking on one of following Scala mailing lists can be helpful: +In general, if you find yourself stuck on any of these steps, asking on one of the following Scala mailing lists can be helpful: - For unexpected behavior use [scala-language](https://groups.google.com/forum/?fromgroups#!forum/scala-language), or [scala-user](https://groups.google.com/forum/?fromgroups#!forum/scala-user) mailing lists. - For compiler bugs use the [scala-internals](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) mailing list. @@ -84,4 +84,4 @@ In the description of your issue, be as detailed as you can. Bug reports which h 2. The expected output. 3. The actual output, including the stacktrace. 4. Related discussion on the mailing lists, if applicable. - 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. \ No newline at end of file + 4. If you have already looked into the issue provide interesting insights or proposals for fixing the issue. diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 28ea69bc3f..69ed05d25e 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -37,7 +37,7 @@ This is the list of language features/libraries along with their maintainers's f Since Martin is the person who submitted the string interpolation Scala Improvement Proposal and implemented this language feature for Scala 2.10.0, he might be interested in learning of new bugfixes to that feature. As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, -in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user)about our issue. +in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user) about our issue.
    Posting to scala-user

    @@ -143,7 +143,7 @@ Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with [instructions for Intellij](https://github.com/scala/scala/blob/master/src/intellij/README). Both of those Scala plugins provide navigation, refactoring and error reporting functionality as well as integrated debugging. -There also exist lighter-weight editors such as Emacs, Sublime or jEdit which provide unparalleled are faster and much less memory/compute-intensive to run, while +There also exist lighter-weight editors such as Emacs, Sublime or jEdit which are faster and much less memory/compute-intensive to run, while lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, a helper program, which hosts a resident Scala compiler providing some of the features implemented in traditional IDEs. However despite having significantly matured over the last year, support for our particular code base is still being improved, and is not as mature as for Eclipse and IntelliJ. @@ -194,11 +194,11 @@ There are several areas that one could contribute to-- there is the Scala librar ##### The Scala Library -Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it.) +Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it). If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. -If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](http://docs.scala-lang.org/overviews/core/collections.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](http://docs.scala-lang.org/overviews/core/parallel-collections.html). (TODO double check these links!) +If you intend on contributing to Scala collections, please make sure you're familiar with the design of the Scala collections library. It can be easy to put an implementation in the wrong location if you are unfamiliar with the collections architecture. There is an excellent and very detailed guide covering [the Architecture of Scala Collections](http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html), as well as a larger more general [Scala collections Guide](http://docs.scala-lang.org/overviews/collections/introduction.html) covering the sequential portion of collections. For parallel collections, there also exists a detailed [Scala Parallel Collections Guide](http://docs.scala-lang.org/overviews/parallel-collections/overview.html). ##### The Scala Compiler @@ -272,9 +272,9 @@ I have already written one test earlier, so that's a good start but not enough! Adding tests to the test suite is as easy as moving them to the appropriate directory: -* Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/master/test/files/pos) -* Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/master/test/files/neg) -* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/master/test/files/run) +* Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/master/test/files/pos). +* Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/master/test/files/neg). +* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/master/test/files/run). ### Verify From ac890ec4475ccac7b4cde69954e0325d770429f5 Mon Sep 17 00:00:00 2001 From: Ricky Elrod Date: Wed, 31 Jul 2013 21:44:19 -0400 Subject: [PATCH 0039/2265] Make hacker-guide valid. --- contribute/hacker-guide.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 69ed05d25e..5e22223278 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -39,9 +39,8 @@ Since Martin is the person who submitted the string interpolation Scala Improvem As alluded to earlier, one must also choose an appropriate mailing list. Typically, one would use the scala-internals mailing list, as it is devoted to discussions about the core internal design and implementation of the Scala system. However, since this issue has been discussed previously on the scala-user mailing list, in this example, we post to the [the scala-user mailing list](http://groups.google.com/group/scala-user) about our issue. -
    Posting to scala-user
    -
    -
    Response from Martin
    +Posting to scala-user +Response from Martin Now that we have the approval of the feature's author, we can get to work! @@ -59,7 +58,7 @@ button in the top right corner of the page. This will create your own copy of ou If you're new to Git, don't be afraid of messing up-- there is no way you can corrupt our repository. -
    Fork scala/scala
    +Fork scala/scala ### Clone @@ -335,14 +334,14 @@ Now, we must simply submit our proposed patch. Navigate to your branch in GitHub and click the pull request button to submit your patch as a pull request to Scala. If you've never submitted patches to Scala, you will need to sign the contributor license agreement, which [can be done online](http://typesafe.com/contribute/cla/scala) within a few minutes. -
    Submit a pull request
    +Submit a pull request ### Review After the pull request has been submitted, you need to pick a reviewer (usually the person you've contacted in the beginning of your workflow) and be ready to elaborate and adjust your patch if necessary. In this example, we picked Martin, because we had such a nice chat on the mailing list: -
    SAssign the reviewer
    +SAssign the reviewer ## Merge From 38ef7cf6c68443939d834c4f5fe28bed129eb7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 30 Sep 2013 14:30:04 +0200 Subject: [PATCH 0040/2265] Add hall of fame for July and August 2013. --- .../_posts/2013-08-01-scala-fame-2013-07.md | 119 ++++++++++++++++++ .../_posts/2013-09-01-scala-fame-2013-08.md | 98 +++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md create mode 100644 contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md diff --git a/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md b/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md new file mode 100644 index 0000000000..b6670c42ce --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-08-01-scala-fame-2013-07.md @@ -0,0 +1,119 @@ +--- +layout: famearchive +title: Contributors of July 2013 +fame-year: 2013 +fame-month: 7 +fame-month-str: July +fame-categories: + - category: Typesafe + authors: + - username: gkossakowski + gravatar: https://0.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?d=https%3A%2F%2Fidenticons.github.com%2F8196e8d0f9ee7dfdfc7e11dbbfa30d77.png&s=60 + commits: 11 + linesAdded: 522 + linesDeleted: 311 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 + commits: 9 + linesAdded: 1068 + linesDeleted: 11436 + rank: 2 + newContributor: false + - username: retronym + gravatar: https://0.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 + commits: 8 + linesAdded: 416 + linesDeleted: 134 + rank: 3 + newContributor: false + - username: paulp + gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png + commits: 2 + linesAdded: 46 + linesDeleted: 27 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: magarciaEPFL + gravatar: https://2.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?d=https%3A%2F%2Fidenticons.github.com%2F8b7440eff98d923640c99b5535429144.png&s=60 + commits: 12 + linesAdded: 1208 + linesDeleted: 1069 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://2.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 + commits: 8 + linesAdded: 321 + linesDeleted: 95 + rank: 2 + newContributor: false + - username: VladUreche + gravatar: https://2.gravatar.com/avatar/5658ed1cea041577df360fd663c570fa?d=https%3A%2F%2Fidenticons.github.com%2Fa1ef2fed16f85a1af890467a80c30226.png&s=60 + commits: 2 + linesAdded: 104 + linesDeleted: 2 + rank: 3 + newContributor: false + - username: cvogt + gravatar: https://1.gravatar.com/avatar/669fb4eab529fba02f390051ddf3c8d3?d=https%3A%2F%2Fidenticons.github.com%2F78d9e7d7c73ac19ca8da9805762e5bb0.png&s=60 + commits: 1 + linesAdded: 19 + linesDeleted: 0 + rank: 4 + newContributor: false + - category: Community + authors: + - username: soc + gravatar: https://0.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?d=https%3A%2F%2Fidenticons.github.com%2F29f7ac3adbe1d3500c9404388aedcbfd.png&s=60 + commits: 19 + linesAdded: 2818 + linesDeleted: 4377 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://2.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 + commits: 16 + linesAdded: 1049 + linesDeleted: 553 + rank: 2 + newContributor: false + - username: densh + gravatar: https://0.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 + commits: 9 + linesAdded: 2632 + linesDeleted: 178 + rank: 3 + newContributor: false + - username: folone + gravatar: https://2.gravatar.com/avatar/50e7e3f60b3507383d2b327857b66a62?d=https%3A%2F%2Fidenticons.github.com%2F6c2bcbccd23191b40f4932e2b8450681.png&s=60 + commits: 3 + linesAdded: 106 + linesDeleted: 261 + rank: 4 + newContributor: false + - username: xuwei-k + gravatar: https://2.gravatar.com/avatar/18d8b1bf73827b2a15e2bd3e75b4b34a?d=https%3A%2F%2Fidenticons.github.com%2Fdab0069935d770e6285411ed1f4398b9.png&s=60 + commits: 3 + linesAdded: 5 + linesDeleted: 5 + rank: 4 + newContributor: false + - username: gourlaysama + gravatar: https://2.gravatar.com/avatar/8acf3c87222f89b18786c8db60eb365d?d=https%3A%2F%2Fidenticons.github.com%2F76004d7b1fac3a2b262caa5e6bdf15c9.png&s=60 + commits: 2 + linesAdded: 67 + linesDeleted: 3 + rank: 5 + newContributor: false + - username: ScrapCodes + gravatar: https://0.gravatar.com/avatar/e9813bbbab2caa993bf7e2b2d60de894?d=https%3A%2F%2Fidenticons.github.com%2F38c660c74f82a216b75167debab770ed.png&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 6 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md b/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md new file mode 100644 index 0000000000..c876e815d1 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-09-01-scala-fame-2013-08.md @@ -0,0 +1,98 @@ +--- +layout: famearchive +title: Contributors of August 2013 +fame-year: 2013 +fame-month: 8 +fame-month-str: August +fame-categories: + - category: Typesafe + authors: + - username: paulp + gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png + commits: 50 + linesAdded: 3703 + linesDeleted: 2269 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://0.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 + commits: 30 + linesAdded: 990 + linesDeleted: 167 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 + commits: 6 + linesAdded: 224 + linesDeleted: 11001 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://0.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?d=https%3A%2F%2Fidenticons.github.com%2F0777acff7c9ab34562699e4e1d05affb.png&s=60 + commits: 2 + linesAdded: 6 + linesDeleted: 6 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://2.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 + commits: 9 + linesAdded: 579 + linesDeleted: 419 + rank: 1 + newContributor: false + - username: magarciaEPFL + gravatar: https://2.gravatar.com/avatar/94ff1d59d6e0a3a4ab10c80ab12bfeed?d=https%3A%2F%2Fidenticons.github.com%2F8b7440eff98d923640c99b5535429144.png&s=60 + commits: 4 + linesAdded: 319 + linesDeleted: 105 + rank: 2 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://0.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 + commits: 19 + linesAdded: 687 + linesDeleted: 322 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://2.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 + commits: 12 + linesAdded: 455 + linesDeleted: 91 + rank: 2 + newContributor: false + - username: soc + gravatar: https://0.gravatar.com/avatar/6e4171314f4704b1e82aa4e5d9067e92?d=https%3A%2F%2Fidenticons.github.com%2F29f7ac3adbe1d3500c9404388aedcbfd.png&s=60 + commits: 4 + linesAdded: 64 + linesDeleted: 27 + rank: 3 + newContributor: false + - username: gourlaysama + gravatar: https://2.gravatar.com/avatar/8acf3c87222f89b18786c8db60eb365d?d=https%3A%2F%2Fidenticons.github.com%2F76004d7b1fac3a2b262caa5e6bdf15c9.png&s=60 + commits: 2 + linesAdded: 50 + linesDeleted: 9 + rank: 4 + newContributor: false + - username: ScrapCodes + gravatar: https://0.gravatar.com/avatar/e9813bbbab2caa993bf7e2b2d60de894?d=https%3A%2F%2Fidenticons.github.com%2F38c660c74f82a216b75167debab770ed.png&s=60 + commits: 1 + linesAdded: 3 + linesDeleted: 0 + rank: 5 + newContributor: false + - username: folone + gravatar: https://2.gravatar.com/avatar/50e7e3f60b3507383d2b327857b66a62?d=https%3A%2F%2Fidenticons.github.com%2F6c2bcbccd23191b40f4932e2b8450681.png&s=60 + commits: 1 + linesAdded: 55 + linesDeleted: 7 + rank: 5 + newContributor: false +--- From 1fad03554f97da791f28a74746dbb158f9109c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 10 Oct 2013 11:17:43 +0200 Subject: [PATCH 0041/2265] Add hall of fame for 2013-09. --- .../_posts/2013-10-01-scala-fame-2013-09.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md diff --git a/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md b/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md new file mode 100644 index 0000000000..23fa456fc0 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-10-01-scala-fame-2013-09.md @@ -0,0 +1,105 @@ +--- +layout: famearchive +title: Contributors of September 2013 +fame-year: 2013 +fame-month: 9 +fame-month-str: September +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://2.gravatar.com/avatar/5df8faf17a57ccab478a9b8056862fc3?d=https%3A%2F%2Fidenticons.github.com%2F75e4dffe50001cf8b96d3beecbe181be.png&s=60 + commits: 42 + linesAdded: 1459 + linesDeleted: 476 + rank: 1 + newContributor: false + - username: paulp + gravatar: https://identicons.github.com/bf65417dcecc7f2b0006e1f5793b7143.png + commits: 25 + linesAdded: 6603 + linesDeleted: 7419 + rank: 2 + newContributor: false + - username: huitseeker + gravatar: https://1.gravatar.com/avatar/dc11aab8ab70b10a828b5ee4735183e8?d=https%3A%2F%2Fidenticons.github.com%2F0777acff7c9ab34562699e4e1d05affb.png&s=60 + commits: 7 + linesAdded: 520 + linesDeleted: 536 + rank: 3 + newContributor: false + - username: gkossakowski + gravatar: https://0.gravatar.com/avatar/e608c8cb27858cc5aaf7d0c1e57958d7?d=https%3A%2F%2Fidenticons.github.com%2F8196e8d0f9ee7dfdfc7e11dbbfa30d77.png&s=60 + commits: 2 + linesAdded: 1443 + linesDeleted: 44 + rank: 4 + newContributor: false + - username: dragos + gravatar: https://2.gravatar.com/avatar/fbd384e9626d28d1648f023a5e22672f?d=https%3A%2F%2Fidenticons.github.com%2F6b660454242c937e501b88fd136132f8.png&s=60 + commits: 2 + linesAdded: 95 + linesDeleted: 13 + rank: 4 + newContributor: false + - username: jsuereth + gravatar: https://1.gravatar.com/avatar/5ed293320c06809a24812f56861201ad?d=https%3A%2F%2Fidenticons.github.com%2F11a5b5ef81cff76a0a1f3d042f635df3.png&s=60 + commits: 1 + linesAdded: 18 + linesDeleted: 37 + rank: 5 + newContributor: false + - username: adriaanm + gravatar: https://0.gravatar.com/avatar/d573d4b8a6bd9e2f41611d8d566c533e?d=https%3A%2F%2Fidenticons.github.com%2Ff0d91e20ef53ace520f6ccbf8402319f.png&s=60 + commits: 1 + linesAdded: 5 + linesDeleted: 5 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://1.gravatar.com/avatar/69e339fd10a5ad804c45e22c819c67ad?d=https%3A%2F%2Fidenticons.github.com%2F6a5b1b05e953818962474e94b67d1cc2.png&s=60 + commits: 5 + linesAdded: 434 + linesDeleted: 153 + rank: 1 + newContributor: false + - username: sjrd + gravatar: https://1.gravatar.com/avatar/bc554c7355c8476dd63375b314b1bd97?d=https%3A%2F%2Fidenticons.github.com%2F7f7549008d59643d2ce9846ce0364947.png&s=60 + commits: 4 + linesAdded: 30 + linesDeleted: 9 + rank: 2 + newContributor: true + - category: Community + authors: + - username: densh + gravatar: https://1.gravatar.com/avatar/5ed274e115ec061d062d9c32a539cdc9?d=https%3A%2F%2Fidenticons.github.com%2Fcd3e73ab183ea35424f0bf59101a74e4.png&s=60 + commits: 20 + linesAdded: 1415 + linesDeleted: 594 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://1.gravatar.com/avatar/ec5b08d0fe94845ba49fd4a263c7d99d?d=https%3A%2F%2Fidenticons.github.com%2Fd292a902ebb73981efd65c9ef416046b.png&s=60 + commits: 11 + linesAdded: 367 + linesDeleted: 106 + rank: 2 + newContributor: false + - username: Ichoran + gravatar: https://0.gravatar.com/avatar/3698349ad0b898d398a6573f4d1f867a?d=https%3A%2F%2Fidenticons.github.com%2Ffc12483537f3df99d480423de674e099.png&s=60 + commits: 3 + linesAdded: 75 + linesDeleted: 27 + rank: 3 + newContributor: true + - username: sschaef + gravatar: https://0.gravatar.com/avatar/dd80aab570fdb5f37e62de5422f44ed4?d=https%3A%2F%2Fidenticons.github.com%2Fb5a662bc30d97b377338f5dfb2b4cc66.png&s=60 + commits: 3 + linesAdded: 84 + linesDeleted: 139 + rank: 3 + newContributor: false +--- From 9b709e0b67f7e3b7594734b019f262fd1dcf6e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20van=20Delft?= Date: Mon, 6 Jan 2014 14:49:42 +0100 Subject: [PATCH 0042/2265] Update hacker-guide.md Added two more Git learning resources --- contribute/hacker-guide.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 5e22223278..46d252984e 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -48,8 +48,11 @@ Now that we have the approval of the feature's author, we can get to work! Hacking Scala begins with creating a branch for your work item. To develop Scala we use [Git](http://git-scm.com/) and [GitHub](http://github.com/). This section of the guide provides a short walkthrough, but if you are new to Git, -it probably makes sense to familiarize yourself with Git first. We recommend the [Git Pro](http://git-scm.com/book/en/) -online book. +it probably makes sense to familiarize yourself with Git first. We recommend + +* the [Git Pro](http://git-scm.com/book/en/) online book. +* the help page on [Forking a Git Repository](https://help.github.com/articles/fork-a-repo). +* this great training tool [LearnGitBranching](http://pcottle.github.io/learnGitBranching/). One hour hands-on training helps more than 1000 hours reading. ### Fork From 6f80442e6ac4050d70ab6b06ed5d59ee8187637f Mon Sep 17 00:00:00 2001 From: George Leontiev Date: Wed, 25 Jun 2014 17:43:17 +0200 Subject: [PATCH 0043/2265] Update hacker guide: add more info, fix broken links. --- contribute/hacker-guide.md | 99 ++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 46d252984e..895d925f48 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -26,7 +26,7 @@ Sometimes it's appealing to hack alone and not to have to interact with others o this might not be the very best idea. There are people in the Scala community who have spent years accumulating knowledge about Scala libraries and internals. They might provide unique insights and, what's even better, direct assistance in their areas, so it is not only advantageous, but recommended to communicate with the community about your new patch. -Typically bug fixes and new features start out as an idea or an experiment posted on one of our mailing lists [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel +Typically bug fixes and new features start out as an idea or an experiment posted on one of [our mailing lists]({{ site.baseurl }}/community/index.html#mailing_lists) to find out how people feel about things you want to implement. People proficient in certain areas of Scala usually monitor mailing lists, so you'll often get some help by simply posting a message. But the most efficient way to connect is to cc your message to one of the people responsible for maintaining the aspect of Scala which you wish to contribute to. @@ -67,7 +67,7 @@ If you're new to Git, don't be afraid of messing up-- there is no way you can co If everything went okay, you will be redirected to your own fork at `https://github.com/username/scala`, where `username` is your github user name. You might find it helpful to read [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/), -which covers some of the things that will follow below. Then, _clone_ your repository (_i.e._ pull a copy from GitHub to your local machine) by running the following on the command line: +which covers some of the things that will follow below. Then, _clone_ your repository (i.e. pull a copy from GitHub to your local machine) by running the following on the command line: 16:35 ~/Projects$ git clone https://github.com/xeno-by/scala Cloning into 'scala'... @@ -86,7 +86,7 @@ Before you start making changes, always create your own branch. Never work on th the changes you plan on making. Use a prefix that describes the nature of your change. There are essentially two kinds of changes: bug fixes and new features. -* For bug fixes, use `issue/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). +* For bug fixes, use `issue/NNNN` or `ticket/NNNN` for bug NNNN from the [Scala issue tracker](https://issues.scala-lang.org/). * For new feature use `topic/XXX` for feature XXX. Use feature names that make sense in the context of the whole Scala project and not just to you personally. For example, if you work on diagrams in Scaladoc, use `topic/scaladoc-diagrams` instead of just `topic/diagrams` would be a good branch name. Since in our example, we're going to fix an existing bug [SI-6725](https://issues.scala-lang.org/browse/SI-6725), we'll create a branch named `ticket/6725`. @@ -98,8 +98,7 @@ If you are new to Git and branching, read the [Branching Chapter](http://git-scm ### Build -The next step after cloning your fork is setting up your machine to build Scala. The definitive guide on building Scala is located at -[https://github.com/scala/scala/blob/master/README.rst](https://github.com/scala/scala/blob/master/README.rst), but here's the summary: +The next step after cloning your fork is setting up your machine to build Scala. * It is recommended to use Java `1.6` (not `1.7` or `1.8`, because they might cause occasional glitches). * The build tool is `ant`. @@ -140,10 +139,8 @@ with your hardware). There's no single editor of choice for working with Scala sources, as there are trade-offs associated with each available tool. -Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. Here are -[instructions for Eclipse](https://github.com/scala/scala/blob/master/src/eclipse/README.md) and -[instructions for Intellij](https://github.com/scala/scala/blob/master/src/intellij/README). Both of those Scala plugins provide -navigation, refactoring and error reporting functionality as well as integrated debugging. +Both Eclipse and IntelliJ IDEA have Scala plugins, which are known to work with our codebase. +Both of those Scala plugins provide navigation, refactoring and error reporting functionality as well as integrated debugging. There also exist lighter-weight editors such as Emacs, Sublime or jEdit which are faster and much less memory/compute-intensive to run, while lacking semantic services and debugging. To address this shortcoming, they can integrate with ENSIME, @@ -185,10 +182,33 @@ Here are also some tips & tricks that have proven useful in Scala development: just that trait, but it might also be necessary to recompile its users. The `ant` tool is not smart enough to do that, which might lead to very strange errors. Full-rebuilds fix the problem. Fortunately that's rarely necessary, because full-rebuilds take a lot of time-- the same 8-30 minutes as mentioned above. * Even on solid state drives packaging Scala distribution (i.e. creating jars from class files) is a non-trivial task. To save time here, - some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts to launch Scala from `build/quick/classes`. + some people in our team do `ant quick.comp` instead of `ant` and then create custom scripts ([here](https://github.com/adriaanm/binfu/blob/master/scafu.sh) are some examples to get you strarted) to launch Scala from `build/quick/classes`. * Don't underestimate the power of `print`. When starting with Scala, I spent a lot of time in the debugger trying to figure out how things work. However later I found out that print-based debugging is often more effective than jumping around. While it might be obvious - to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. + to some, I'd like to explicitly mention that it's also useful to print stack traces to understand the flow of execution. When working with `Trees`, you might want to use `showRaw` to get the `AST` representation. +* You can publish your newly-built scala version locally to use it from sbt. Here's how: + + $ ant publish-local-opt -Dmaven.version.suffix="-test" + $ sbt + [info] Set current project to test (in build file:/Users/georgii/workspace/test/) + > set resolvers += Resolver.mavenLocal + [info] Defining *:resolvers + [info] The new value will be used by *:externalResolvers + [info] Reapplying settings... + [info] Set current project to test (in build file:/Users/georgii/workspace/test/) + > ++2.12.0-test + [info] Setting version to 2.12.0-test + [info] Set current project to test (in build file:/Users/georgii/workspace/test/) + > console + [info] Starting scala interpreter... + [info] + Welcome to Scala version 2.12.0-20140623-155543-8bdacad317 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51). + Type in expressions to have them evaluated. + Type :help for more information. + + scala> + +* Adding a macro to the `Predef` is a pretty involved task. For the reason of bootstrapping, you cannot just throw a macro into it. There is a more involved process here. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you want to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. If that explanation does not sound very clear, [here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. ### Documentation @@ -196,7 +216,7 @@ There are several areas that one could contribute to-- there is the Scala librar ##### The Scala Library -Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left something cleaner than you found it). +Contributing to the Scala standard library is about the same as working on one of your own libraries. Beyond the Scala collections hierarchy, there are no complex internals or architectures to have to worry about. Just make sure that you code in a "don't-repeat-yourself" (DRY) style, obeying the "boy scout principle" (i.e. make sure you've left the code cleaner than you found it). If documentation is necessary for some trait/class/object/method/etc in the Scala standard library, typically maintainers will include inline comments describing their design decisions or rationale for implementing things the way they have, if it is not straightforward. @@ -206,7 +226,7 @@ If you intend on contributing to Scala collections, please make sure you're fami Documentation about the internal workings of the Scala compiler is scarce, and most of the knowledge is passed around by email (scala-internals mailing list), ticket, or word of mouth. However the situation is steadily improving. Here are the resources that might help: -* [Compiler internals videos by Martin Odersky](TODO) are quite dated, but still very useful. In this three-video +* [Compiler internals videos by Martin Odersky](http://www.scala-lang.org/old/node/598.html) are quite dated, but still very useful. In this three-video series Martin explains the general architecture of the compiler, and the basics of the front-end, which has recently become Scala reflection API. * [Reflection documentation](http://docs.scala-lang.org/overviews/reflection/overview.html) describes fundamental data structures (like `Tree`s, `Symbol`s, and `Types`) that are used to represent Scala programs and operations defined on then. Since much of the compiler has been factored out and made accessible via the Reflection API, all of the fundamentals needed for reflection are the same for the compiler. @@ -274,9 +294,56 @@ I have already written one test earlier, so that's a good start but not enough! Adding tests to the test suite is as easy as moving them to the appropriate directory: -* Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/master/test/files/pos). -* Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/master/test/files/neg). -* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/master/test/files/run). +* Code which should compile successfully, but doesn't need to be executed, needs to go into the [“pos” directory](https://github.com/scala/scala/tree/2.12.x/test/files/pos). +* Code which should not compile needs to go into the [“neg” directory](https://github.com/scala/scala/tree/2.12.x/test/files/neg). +* Code which should compile and get executed by the test suite needs to go into the [“run” directory](https://github.com/scala/scala/tree/2.12.x/test/files/run) and have a corresponding `.check` file with the expected output. You will get test failures if the content of a `.check` file is different from what the test produces while running. If the change in the output is an expected product of your work, you might not want to change the `.check` file by hand. To make partest change the `.check` file, run it with a `--update-check` flag, like so `./test/partest --update-check path/to/test.scala`. For more information on partest, please refer to its [documentation](http://docs.scala-lang.org/tutorials/partest-guide.html). +* Everything that can be unit-tested should go to ["junit" directory](https://github.com/scala/scala/tree/2.12.x/test/junit) +* Property-based tests go to the ["scalacheck" directory](https://github.com/scala/scala/tree/2.12.x/test/files/scalacheck) + +Here are some more testing tips: + +* If you have several tests, and want a tool for only running tests that conform to some regular expression, you can use `partest-ack` in the `tools` directory: `./tools/partest-ack "dottype"` +* If your tests fail with an like: + + test.bc: + [echo] Checking backward binary compatibility for scala-library (against 2.11.0) + [mima] Found 2 binary incompatibiities + [mima] ================================ + [mima] * synthetic method + [mima] scala$package$Class$method(java.lang.String)Unit in trait + [mima] scala.package.Class does not have a correspondent in old version + [mima] * synthetic method + [mima] scala$package$AnotherClass$anotherMethod(java.lang.String)Unit in trait + [mima] scala.package.AnotherClass does not have a correspondent in old version + [mima] Generated filter config definition + [mima] ================================== + [mima] + [mima] filter { + [mima] problems=[ + [mima] { + [mima] matchName="scala.package.Class$method" + [mima] problemName=MissingMethodProblem + [mima] }, + [mima] { + [mima] matchName="scala.package.AnotherClass$anotherMethod" + [mima] problemName=MissingMethodProblem + [mima] } + [mima] ] + [mima] } + [mima] + + BUILD FAILED + /localhome/jenkins/c/workspace/pr-scala-test/scala/build.xml:1530: The following error occurred while executing this line: + /localhome/jenkins/c/workspace/pr-scala-test/scala/build-ant-macros.xml:791: The following error occurred while executing this line: + /localhome/jenkins/c/workspace/pr-scala-test/scala/build-ant-macros.xml:773: Java returned: 2 + + Total time: 6 minutes 46 seconds + Build step 'Execute shell' marked build as failure + Archiving artifacts + Notifying upstream projects of job completion + Finished: FAILURE + +This means your change is backward or forward binary incompatible with the specified version (the check is performed by the [migration manager](https://github.com/typesafehub/migration-manager)). The error message is actually saying what you need to add to `bincompat-backward.whitelist.conf` or `bincompat-forward.whitelist.conf` to make the error go away. If you are getting this on an internal/experimental api, it should be safe to add suggested sections to the config. Otherwise, you might want to target a newer version of scala for this change. ### Verify From a076f43769050b80646fb196a9b109e6ed97228f Mon Sep 17 00:00:00 2001 From: George Leontiev Date: Thu, 26 Jun 2014 10:44:54 +0200 Subject: [PATCH 0044/2265] Address the feedback. --- contribute/hacker-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribute/hacker-guide.md b/contribute/hacker-guide.md index 895d925f48..08f5d40c09 100644 --- a/contribute/hacker-guide.md +++ b/contribute/hacker-guide.md @@ -208,7 +208,7 @@ Here are also some tips & tricks that have proven useful in Scala development: scala> -* Adding a macro to the `Predef` is a pretty involved task. For the reason of bootstrapping, you cannot just throw a macro into it. There is a more involved process here. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you want to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. If that explanation does not sound very clear, [here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. +* Adding a macro to the `Predef` object is a pretty involved task. Due to bootstrapping, you cannot just throw a macro into it. For this reason, the process is more involved. You might want to follow the way `StringContext.f` itself is added. In short, you need to define your macro under `src/compiler/scala/tools/reflect/` and provide no implementation in `Predef` (`def fn = macro ???`). Now you have to set up the wiring. Add the name of your macro to `src/reflect/scala/reflect/internal/StdNames.scala`, add the needed links to it to `src/reflect/scala/reflect/internal/Definitions.scala`, and finally specify the bindings in `src/compiler/scala/tools/reflect/FastTrack.scala`. [Here's](https://github.com/folone/scala/commit/59536ea833ca16c985339727baed5d70e577b0fe) an example of adding a macro. ### Documentation @@ -303,7 +303,7 @@ Adding tests to the test suite is as easy as moving them to the appropriate dire Here are some more testing tips: * If you have several tests, and want a tool for only running tests that conform to some regular expression, you can use `partest-ack` in the `tools` directory: `./tools/partest-ack "dottype"` -* If your tests fail with an like: +* If your tests fail in the following way: test.bc: [echo] Checking backward binary compatibility for scala-library (against 2.11.0) From 8f63cd0ebdf244c5051357d3781d985b54d126da Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 7 Jul 2014 20:28:10 +0200 Subject: [PATCH 0045/2265] Fix more references to spec --- contribute/bug-reporting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/bug-reporting-guide.md b/contribute/bug-reporting-guide.md index 4160dcf438..960f40b704 100644 --- a/contribute/bug-reporting-guide.md +++ b/contribute/bug-reporting-guide.md @@ -43,7 +43,7 @@ If you have a code snippet that is resulting in bytecode which you believe is be 5. If you want to file an improvement in the issue tracker please discuss it first on one of the mailing lists. They offer much bigger audience than issue tracker. The latter is not suitable for long discussions. -* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) or [stackoveflow](http://stackoverflow.com/questions/tagged/scala). +* Keep in mind that the behavior you are witnessing could be intended. Good formal resources for verifying whether or not the language behavior is intended is either in the [Scala Improvement Proposal Documents](http://docs.scala-lang.org/sips/sip-list.html) or in the [Scala Language Specification](http://www.scala-lang.org/files/archive/spec/2.11/). If in doubt, you may always ask on the [scala-internals mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-internals) or [stackoveflow](http://stackoverflow.com/questions/tagged/scala). In general, if you find yourself stuck on any of these steps, asking on one of the following Scala mailing lists can be helpful: From afc73aa06baf7b9204c11edd946b02e82b74fcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 29 Sep 2014 10:30:37 +0200 Subject: [PATCH 0046/2265] Hall of fame Auguest 2014. --- .../_posts/2014-09-01-scala-fame-2014-08.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md diff --git a/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md b/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md new file mode 100644 index 0000000000..1393e01705 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md @@ -0,0 +1,63 @@ +--- +layout: famearchive +title: Contributors of August 2014 +fame-year: 2014 +fame-month: 8 +fame-month-str: August +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 3 + linesAdded: 57 + linesDeleted: 4 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 2 + linesAdded: 57 + linesDeleted: 42 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 21 + linesAdded: 3764 + linesDeleted: 2122 + rank: 1 + newContributor: false + - category: Community + authors: + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 10 + linesAdded: 171 + linesDeleted: 7680 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 10 + linesAdded: 917 + linesDeleted: 543 + rank: 1 + newContributor: false + - username: dgruntz + gravatar: https://avatars3.githubusercontent.com/u/1516800?v=2&s=60 + commits: 1 + linesAdded: 18 + linesDeleted: 18 + rank: 2 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 1 + linesAdded: 26 + linesDeleted: 27 + rank: 2 + newContributor: false +--- From d4630ea3257b7740c390f5d728b6d2fd012f7fc1 Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Fri, 24 Oct 2014 16:36:48 +0200 Subject: [PATCH 0047/2265] Add 2014 scala-fame data --- .../_posts/2014-02-01-scala-fame-2014-01.md | 147 ++++++++++++++++++ .../_posts/2014-03-01-scala-fame-2014-02.md | 133 ++++++++++++++++ .../_posts/2014-04-01-scala-fame-2014-03.md | 112 +++++++++++++ .../_posts/2014-05-01-scala-fame-2014-04.md | 91 +++++++++++ .../_posts/2014-06-01-scala-fame-2014-05.md | 112 +++++++++++++ .../_posts/2014-07-01-scala-fame-2014-06.md | 98 ++++++++++++ .../_posts/2014-08-01-scala-fame-2014-07.md | 98 ++++++++++++ .../_posts/2014-09-01-scala-fame-2014-08.md | 7 + .../_posts/2014-10-01-scala-fame-2014-09.md | 84 ++++++++++ 9 files changed, 882 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md create mode 100644 contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md create mode 100644 contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md create mode 100644 contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md create mode 100644 contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md create mode 100644 contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md create mode 100644 contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md create mode 100644 contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md diff --git a/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md b/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md new file mode 100644 index 0000000000..ab8e808036 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-02-01-scala-fame-2014-01.md @@ -0,0 +1,147 @@ +--- +layout: famearchive +title: Contributors of January 2014 +fame-year: 2014 +fame-month: 1 +fame-month-str: January +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 37 + linesAdded: 2000 + linesDeleted: 2487 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 8 + linesAdded: 311 + linesDeleted: 175 + rank: 2 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 3 + linesAdded: 15 + linesDeleted: 5 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 2 + linesAdded: 81 + linesDeleted: 79 + rank: 4 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 2 + linesAdded: 7 + linesDeleted: 5 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 75 + linesAdded: 8908 + linesDeleted: 6023 + rank: 1 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 16 + linesAdded: 722 + linesDeleted: 295 + rank: 1 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 10 + linesAdded: 315 + linesDeleted: 103 + rank: 2 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 9 + linesAdded: 646 + linesDeleted: 201 + rank: 3 + newContributor: false + - username: VladimirNik + gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 + commits: 7 + linesAdded: 1729 + linesDeleted: 350 + rank: 4 + newContributor: false + - username: rklaehn + gravatar: https://avatars0.githubusercontent.com/u/248257?v=2&s=60 + commits: 6 + linesAdded: 1288 + linesDeleted: 39 + rank: 5 + newContributor: false + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 3 + linesAdded: 37 + linesDeleted: 7 + rank: 6 + newContributor: false + - username: cunei + gravatar: https://avatars2.githubusercontent.com/u/686260?v=2&s=60 + commits: 2 + linesAdded: 42 + linesDeleted: 12 + rank: 7 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 2 + linesAdded: 51 + linesDeleted: 33 + rank: 7 + newContributor: false + - username: havocp + gravatar: https://avatars2.githubusercontent.com/u/218689?v=2&s=60 + commits: 1 + linesAdded: 38 + linesDeleted: 2 + rank: 8 + newContributor: false + - username: clhodapp + gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 + commits: 1 + linesAdded: 22 + linesDeleted: 0 + rank: 8 + newContributor: false + - username: rjolly + gravatar: https://avatars3.githubusercontent.com/u/128610?v=2&s=60 + commits: 1 + linesAdded: 45 + linesDeleted: 38 + rank: 8 + newContributor: false + - username: xuwei-k + gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 8 + newContributor: false + - username: dotta + gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 + commits: 1 + linesAdded: 67 + linesDeleted: 67 + rank: 8 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md b/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md new file mode 100644 index 0000000000..065ab45d13 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-03-01-scala-fame-2014-02.md @@ -0,0 +1,133 @@ +--- +layout: famearchive +title: Contributors of February 2014 +fame-year: 2014 +fame-month: 2 +fame-month-str: February +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 47 + linesAdded: 1533 + linesDeleted: 1032 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 25 + linesAdded: 1043 + linesDeleted: 491 + rank: 2 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 4 + linesAdded: 1867 + linesDeleted: 1747 + rank: 3 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 3 + linesAdded: 427 + linesDeleted: 15 + rank: 4 + newContributor: false + - username: dragos + gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 + commits: 1 + linesAdded: 12 + linesDeleted: 3 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 47 + linesAdded: 3989 + linesDeleted: 1545 + rank: 1 + newContributor: false + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 1 + linesAdded: 18 + linesDeleted: 13 + rank: 2 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 23 + linesAdded: 1166 + linesDeleted: 515 + rank: 1 + newContributor: false + - username: VladimirNik + gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 + commits: 10 + linesAdded: 2647 + linesDeleted: 2416 + rank: 2 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 9 + linesAdded: 662 + linesDeleted: 339 + rank: 3 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 8 + linesAdded: 277 + linesDeleted: 75 + rank: 4 + newContributor: false + - username: pavelpavlov + gravatar: https://avatars0.githubusercontent.com/u/1330451?v=2&s=60 + commits: 3 + linesAdded: 44 + linesDeleted: 54 + rank: 5 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 3 + linesAdded: 6 + linesDeleted: 5 + rank: 5 + newContributor: false + - username: soc + gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 + commits: 3 + linesAdded: 476 + linesDeleted: 338 + rank: 5 + newContributor: false + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 2 + linesAdded: 7 + linesDeleted: 7 + rank: 6 + newContributor: false + - username: greenrd + gravatar: https://avatars1.githubusercontent.com/u/164965?v=2&s=60 + commits: 1 + linesAdded: 2 + linesDeleted: 3 + rank: 7 + newContributor: false + - username: clhodapp + gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 + commits: 1 + linesAdded: 228 + linesDeleted: 0 + rank: 7 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md b/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md new file mode 100644 index 0000000000..954a870612 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-04-01-scala-fame-2014-03.md @@ -0,0 +1,112 @@ +--- +layout: famearchive +title: Contributors of March 2014 +fame-year: 2014 +fame-month: 3 +fame-month-str: March +fame-categories: + - category: Typesafe + authors: + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 79 + linesAdded: 24547 + linesDeleted: 24999 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 21 + linesAdded: 622 + linesDeleted: 101 + rank: 2 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 3 + linesAdded: 236 + linesDeleted: 6 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 2 + linesAdded: 4 + linesDeleted: 2 + rank: 4 + newContributor: false + - username: szeiger + gravatar: https://avatars3.githubusercontent.com/u/54262?v=2&s=60 + commits: 1 + linesAdded: 8 + linesDeleted: 1 + rank: 5 + newContributor: false + - username: viktorklang + gravatar: https://avatars0.githubusercontent.com/u/10871?v=2&s=60 + commits: 1 + linesAdded: 7 + linesDeleted: 2 + rank: 5 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 1 + linesAdded: 20 + linesDeleted: 3 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 10 + linesAdded: 379 + linesDeleted: 76 + rank: 1 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 13 + linesAdded: 589 + linesDeleted: 115 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 4 + linesAdded: 31 + linesDeleted: 23 + rank: 2 + newContributor: false + - username: VladimirNik + gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 + commits: 2 + linesAdded: 1778 + linesDeleted: 1441 + rank: 3 + newContributor: false + - username: mkubala + gravatar: https://avatars0.githubusercontent.com/u/328844?v=2&s=60 + commits: 1 + linesAdded: 247 + linesDeleted: 53 + rank: 4 + newContributor: false + - username: puffnfresh + gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 + commits: 1 + linesAdded: 0 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: iainmcgin + gravatar: https://avatars0.githubusercontent.com/u/309153?v=2&s=60 + commits: 1 + linesAdded: 20 + linesDeleted: 19 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md b/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md new file mode 100644 index 0000000000..66c6819f17 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-05-01-scala-fame-2014-04.md @@ -0,0 +1,91 @@ +--- +layout: famearchive +title: Contributors of April 2014 +fame-year: 2014 +fame-month: 4 +fame-month-str: April +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 9 + linesAdded: 177 + linesDeleted: 34 + rank: 1 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 1 + linesAdded: 16 + linesDeleted: 1 + rank: 2 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 1 + linesAdded: 10 + linesDeleted: 3 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 1 + linesAdded: 34 + linesDeleted: 2 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 2 + linesAdded: 202 + linesDeleted: 75 + rank: 1 + newContributor: false + - username: VladUreche + gravatar: https://avatars0.githubusercontent.com/u/428706?v=2&s=60 + commits: 1 + linesAdded: 24 + linesDeleted: 3 + rank: 2 + newContributor: false + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 1 + linesAdded: 12 + linesDeleted: 1 + rank: 2 + newContributor: false + - category: Community + authors: + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 3 + linesAdded: 51 + linesDeleted: 5 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 2 + linesAdded: 110 + linesDeleted: 51 + rank: 2 + newContributor: false + - username: lefou + gravatar: https://avatars2.githubusercontent.com/u/1321393?v=2&s=60 + commits: 1 + linesAdded: 45 + linesDeleted: 8 + rank: 3 + newContributor: false + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 1 + linesAdded: 4 + linesDeleted: 5 + rank: 3 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md b/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md new file mode 100644 index 0000000000..f9191afb17 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-06-01-scala-fame-2014-05.md @@ -0,0 +1,112 @@ +--- +layout: famearchive +title: Contributors of May 2014 +fame-year: 2014 +fame-month: 5 +fame-month-str: May +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 32 + linesAdded: 951 + linesDeleted: 136 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 9 + linesAdded: 21 + linesDeleted: 70 + rank: 2 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 3 + linesAdded: 13 + linesDeleted: 18 + rank: 3 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 23 + linesAdded: 6048 + linesDeleted: 2325 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 3 + linesAdded: 93 + linesDeleted: 3 + rank: 2 + newContributor: false + - category: Community + authors: + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 12 + linesAdded: 442 + linesDeleted: 238 + rank: 1 + newContributor: false + - username: lefou + gravatar: https://avatars2.githubusercontent.com/u/1321393?v=2&s=60 + commits: 3 + linesAdded: 14 + linesDeleted: 24 + rank: 2 + newContributor: false + - username: tvierling + gravatar: https://avatars3.githubusercontent.com/u/397857?v=2&s=60 + commits: 2 + linesAdded: 35 + linesDeleted: 11 + rank: 3 + newContributor: true + - username: clhodapp + gravatar: https://avatars0.githubusercontent.com/u/108633?v=2&s=60 + commits: 2 + linesAdded: 98 + linesDeleted: 51 + rank: 3 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 2 + linesAdded: 55 + linesDeleted: 16 + rank: 3 + newContributor: false + - username: mkubala + gravatar: https://avatars0.githubusercontent.com/u/328844?v=2&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 0 + rank: 4 + newContributor: false + - username: jedesah + gravatar: https://avatars1.githubusercontent.com/u/1780116?v=2&s=60 + commits: 1 + linesAdded: 23 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: VladimirNik + gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 + commits: 1 + linesAdded: 78 + linesDeleted: 40 + rank: 4 + newContributor: false + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 1 + linesAdded: 14 + linesDeleted: 0 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md b/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md new file mode 100644 index 0000000000..5f051d08a7 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-07-01-scala-fame-2014-06.md @@ -0,0 +1,98 @@ +--- +layout: famearchive +title: Contributors of June 2014 +fame-year: 2014 +fame-month: 6 +fame-month-str: June +fame-categories: + - category: Typesafe + authors: + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 14 + linesAdded: 873 + linesDeleted: 661 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 8 + linesAdded: 166 + linesDeleted: 126 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 16 + linesAdded: 1865 + linesDeleted: 437 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 4 + linesAdded: 164 + linesDeleted: 44 + rank: 2 + newContributor: false + - username: odersky + gravatar: https://avatars2.githubusercontent.com/u/795990?v=2&s=60 + commits: 1 + linesAdded: 36 + linesDeleted: 10 + rank: 3 + newContributor: false + - category: Community + authors: + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 7 + linesAdded: 275 + linesDeleted: 57 + rank: 1 + newContributor: false + - username: jxcoder + gravatar: https://avatars1.githubusercontent.com/u/1075547?v=2&s=60 + commits: 4 + linesAdded: 41 + linesDeleted: 19 + rank: 2 + newContributor: true + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 2 + linesAdded: 20 + linesDeleted: 6 + rank: 3 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 2 + linesAdded: 146 + linesDeleted: 41 + rank: 3 + newContributor: false + - username: jrudolph + gravatar: https://avatars1.githubusercontent.com/u/9868?v=2&s=60 + commits: 1 + linesAdded: 97 + linesDeleted: 4 + rank: 4 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 1 + linesAdded: 6 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 1 + linesAdded: 17 + linesDeleted: 5 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md b/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md new file mode 100644 index 0000000000..c57474778d --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-08-01-scala-fame-2014-07.md @@ -0,0 +1,98 @@ +--- +layout: famearchive +title: Contributors of July 2014 +fame-year: 2014 +fame-month: 7 +fame-month-str: July +fame-categories: + - category: Typesafe + authors: + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 31 + linesAdded: 775 + linesDeleted: 712 + rank: 1 + newContributor: false + - username: phaller + gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 + commits: 3 + linesAdded: 161 + linesDeleted: 49 + rank: 2 + newContributor: false + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 1 + linesAdded: 35 + linesDeleted: 34 + rank: 3 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 4 + linesAdded: 84 + linesDeleted: 29 + rank: 1 + newContributor: false + - category: Community + authors: + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 11 + linesAdded: 330 + linesDeleted: 226 + rank: 1 + newContributor: false + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 5 + linesAdded: 217 + linesDeleted: 94 + rank: 2 + newContributor: false + - username: dhgarrette + gravatar: https://avatars2.githubusercontent.com/u/484190?v=2&s=60 + commits: 2 + linesAdded: 1 + linesDeleted: 3 + rank: 3 + newContributor: true + - username: pocket7878 + gravatar: https://avatars1.githubusercontent.com/u/236528?v=2&s=60 + commits: 2 + linesAdded: 21 + linesDeleted: 13 + rank: 3 + newContributor: true + - username: dgruntz + gravatar: https://avatars3.githubusercontent.com/u/1516800?v=2&s=60 + commits: 2 + linesAdded: 4 + linesDeleted: 4 + rank: 3 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 1 + linesAdded: 26 + linesDeleted: 9 + rank: 4 + newContributor: false + - username: kzys + gravatar: https://avatars2.githubusercontent.com/u/19111?v=2&s=60 + commits: 1 + linesAdded: 19 + linesDeleted: 0 + rank: 4 + newContributor: false + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 1 + linesAdded: 3 + linesDeleted: 1 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md b/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md index 1393e01705..afef86d3be 100644 --- a/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md +++ b/contribute/scala-fame-data/_posts/2014-09-01-scala-fame-2014-08.md @@ -46,6 +46,13 @@ fame-categories: linesDeleted: 543 rank: 1 newContributor: false + - username: gbasler + gravatar: https://avatars1.githubusercontent.com/u/273035?v=2&s=60 + commits: 1 + linesAdded: 14 + linesDeleted: 22 + rank: 2 + newContributor: false - username: dgruntz gravatar: https://avatars3.githubusercontent.com/u/1516800?v=2&s=60 commits: 1 diff --git a/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md b/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md new file mode 100644 index 0000000000..ee67016186 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-10-01-scala-fame-2014-09.md @@ -0,0 +1,84 @@ +--- +layout: famearchive +title: Contributors of September 2014 +fame-year: 2014 +fame-month: 9 +fame-month-str: September +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 12 + linesAdded: 182 + linesDeleted: 23 + rank: 1 + newContributor: false + - username: dragos + gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 + commits: 1 + linesAdded: 169 + linesDeleted: 169 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 6 + linesAdded: 262 + linesDeleted: 85 + rank: 1 + newContributor: false + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 3 + linesAdded: 1272 + linesDeleted: 1240 + rank: 2 + newContributor: false + - category: Community + authors: + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 9 + linesAdded: 1782 + linesDeleted: 1227 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 4 + linesAdded: 305 + linesDeleted: 125 + rank: 2 + newContributor: false + - username: puffnfresh + gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 + commits: 3 + linesAdded: 42 + linesDeleted: 7 + rank: 3 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 2 + linesAdded: 12 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: gbasler + gravatar: https://avatars1.githubusercontent.com/u/273035?v=2&s=60 + commits: 1 + linesAdded: 115 + linesDeleted: 41 + rank: 5 + newContributor: false + - username: soc + gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 + commits: 1 + linesAdded: 4 + linesDeleted: 1 + rank: 5 + newContributor: false +--- From bd730a6d4d147e313828cf8155e71a8ac47069be Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Fri, 24 Oct 2014 16:48:29 +0200 Subject: [PATCH 0048/2265] Add 2013 scala-fame data --- .../_posts/2013-02-01-scala-fame-2013-01.md | 175 ++++++++++++++++++ .../_posts/2013-11-01-scala-fame-2013-10.md | 105 +++++++++++ .../_posts/2013-12-01-scala-fame-2013-11.md | 126 +++++++++++++ .../_posts/2014-01-01-scala-fame-2013-12.md | 147 +++++++++++++++ 4 files changed, 553 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md create mode 100644 contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md create mode 100644 contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md create mode 100644 contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md diff --git a/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md b/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md new file mode 100644 index 0000000000..68e990a7b7 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-02-01-scala-fame-2013-01.md @@ -0,0 +1,175 @@ +--- +layout: famearchive +title: Contributors of January 2013 +fame-year: 2013 +fame-month: 1 +fame-month-str: January +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 67 + linesAdded: 7112 + linesDeleted: 3063 + rank: 1 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 37 + linesAdded: 1812 + linesDeleted: 1158 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 22 + linesAdded: 1397 + linesDeleted: 561 + rank: 3 + newContributor: false + - username: JamesIry + gravatar: https://avatars0.githubusercontent.com/u/478012?v=2&s=60 + commits: 20 + linesAdded: 1156 + linesDeleted: 208 + rank: 4 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 5 + linesAdded: 422 + linesDeleted: 9 + rank: 5 + newContributor: false + - username: viktorklang + gravatar: https://avatars0.githubusercontent.com/u/10871?v=2&s=60 + commits: 2 + linesAdded: 187 + linesDeleted: 12 + rank: 6 + newContributor: false + - username: phaller + gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 + commits: 2 + linesAdded: 21 + linesDeleted: 42 + rank: 6 + newContributor: false + - username: dragos + gravatar: https://avatars2.githubusercontent.com/u/133742?v=2&s=60 + commits: 1 + linesAdded: 6 + linesDeleted: 26 + rank: 7 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 28 + linesAdded: 8416 + linesDeleted: 2758 + rank: 1 + newContributor: false + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 8 + linesAdded: 1189 + linesDeleted: 418 + rank: 2 + newContributor: false + - username: heathermiller + gravatar: https://avatars0.githubusercontent.com/u/687163?v=2&s=60 + commits: 2 + linesAdded: 100 + linesDeleted: 15 + rank: 3 + newContributor: false + - username: namin + gravatar: https://avatars2.githubusercontent.com/u/6441?v=2&s=60 + commits: 1 + linesAdded: 23 + linesDeleted: 4 + rank: 4 + newContributor: false + - username: vjovanov + gravatar: https://avatars3.githubusercontent.com/u/352820?v=2&s=60 + commits: 1 + linesAdded: 38 + linesDeleted: 2 + rank: 4 + newContributor: false + - category: Community + authors: + - username: soc + gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 + commits: 13 + linesAdded: 886 + linesDeleted: 3152 + rank: 1 + newContributor: false + - username: kzys + gravatar: https://avatars2.githubusercontent.com/u/19111?v=2&s=60 + commits: 7 + linesAdded: 79 + linesDeleted: 40 + rank: 2 + newContributor: false + - username: danielhopkins + gravatar: https://avatars3.githubusercontent.com/u/91909?v=2&s=60 + commits: 2 + linesAdded: 146 + linesDeleted: 146 + rank: 3 + newContributor: true + - username: ViniciusMiana + gravatar: https://avatars1.githubusercontent.com/u/2053546?v=2&s=60 + commits: 2 + linesAdded: 47 + linesDeleted: 8 + rank: 3 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 2 + linesAdded: 53 + linesDeleted: 6 + rank: 3 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 2 + linesAdded: 236 + linesDeleted: 183 + rank: 3 + newContributor: false + - username: eed3si9n + gravatar: https://avatars1.githubusercontent.com/u/184683?v=2&s=60 + commits: 1 + linesAdded: 35 + linesDeleted: 2 + rank: 4 + newContributor: false + - username: mt2309 + gravatar: https://avatars2.githubusercontent.com/u/816245?v=2&s=60 + commits: 1 + linesAdded: 24 + linesDeleted: 0 + rank: 4 + newContributor: false + - username: puffnfresh + gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 + commits: 1 + linesAdded: 39 + linesDeleted: 3 + rank: 4 + newContributor: false + - username: khernyo + gravatar: https://avatars3.githubusercontent.com/u/447532?v=2&s=60 + commits: 1 + linesAdded: 2 + linesDeleted: 3 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md b/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md new file mode 100644 index 0000000000..557955d60c --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-11-01-scala-fame-2013-10.md @@ -0,0 +1,105 @@ +--- +layout: famearchive +title: Contributors of October 2013 +fame-year: 2013 +fame-month: 10 +fame-month-str: October +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 52 + linesAdded: 1917 + linesDeleted: 1778 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 18 + linesAdded: 1648 + linesDeleted: 1591 + rank: 2 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 9 + linesAdded: 871 + linesDeleted: 1346 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 1 + linesAdded: 3 + linesDeleted: 0 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 9 + linesAdded: 398 + linesDeleted: 2260 + rank: 1 + newContributor: false + - username: axel22 + gravatar: https://avatars1.githubusercontent.com/u/151774?v=2&s=60 + commits: 1 + linesAdded: 201 + linesDeleted: 74 + rank: 2 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 18 + linesAdded: 766 + linesDeleted: 422 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 4 + linesAdded: 114 + linesDeleted: 58 + rank: 2 + newContributor: false + - username: etaty + gravatar: https://avatars3.githubusercontent.com/u/461170?v=2&s=60 + commits: 2 + linesAdded: 2 + linesDeleted: 2 + rank: 3 + newContributor: false + - username: dotta + gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 + commits: 2 + linesAdded: 68 + linesDeleted: 6 + rank: 3 + newContributor: false + - username: qerub + gravatar: https://avatars2.githubusercontent.com/u/636?v=2&s=60 + commits: 1 + linesAdded: 8 + linesDeleted: 0 + rank: 4 + newContributor: false + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 1 + linesAdded: 31 + linesDeleted: 1 + rank: 4 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 1 + linesAdded: 215 + linesDeleted: 25 + rank: 4 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md b/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md new file mode 100644 index 0000000000..7fba955998 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2013-12-01-scala-fame-2013-11.md @@ -0,0 +1,126 @@ +--- +layout: famearchive +title: Contributors of November 2013 +fame-year: 2013 +fame-month: 11 +fame-month-str: November +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 44 + linesAdded: 1814 + linesDeleted: 1372 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 20 + linesAdded: 1945 + linesDeleted: 1463 + rank: 2 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 4 + linesAdded: 62 + linesDeleted: 659 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 2 + linesAdded: 137 + linesDeleted: 87 + rank: 4 + newContributor: false + - username: phaller + gravatar: https://avatars0.githubusercontent.com/u/289943?v=2&s=60 + commits: 1 + linesAdded: 105 + linesDeleted: 101 + rank: 5 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 5 + linesAdded: 82 + linesDeleted: 12 + rank: 1 + newContributor: false + - username: heathermiller + gravatar: https://avatars0.githubusercontent.com/u/687163?v=2&s=60 + commits: 1 + linesAdded: 8 + linesDeleted: 5 + rank: 2 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 10 + linesAdded: 1089 + linesDeleted: 884 + rank: 1 + newContributor: false + - username: skyluc + gravatar: https://avatars3.githubusercontent.com/u/1098830?v=2&s=60 + commits: 6 + linesAdded: 1911 + linesDeleted: 53 + rank: 2 + newContributor: false + - username: dotta + gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 + commits: 6 + linesAdded: 64 + linesDeleted: 47 + rank: 2 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 6 + linesAdded: 499 + linesDeleted: 197 + rank: 2 + newContributor: false + - username: soc + gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 + commits: 5 + linesAdded: 280 + linesDeleted: 97 + rank: 3 + newContributor: false + - username: sschaef + gravatar: https://avatars2.githubusercontent.com/u/488530?v=2&s=60 + commits: 4 + linesAdded: 182 + linesDeleted: 12 + rank: 4 + newContributor: false + - username: xuwei-k + gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 + commits: 2 + linesAdded: 3 + linesDeleted: 3 + rank: 5 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 2 + linesAdded: 1179 + linesDeleted: 0 + rank: 5 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 1 + linesAdded: 3 + linesDeleted: 3 + rank: 6 + newContributor: false +--- diff --git a/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md b/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md new file mode 100644 index 0000000000..80c4139b10 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-01-01-scala-fame-2013-12.md @@ -0,0 +1,147 @@ +--- +layout: famearchive +title: Contributors of December 2013 +fame-year: 2013 +fame-month: 12 +fame-month-str: December +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 28 + linesAdded: 901 + linesDeleted: 215 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 21 + linesAdded: 1386 + linesDeleted: 16746 + rank: 2 + newContributor: false + - username: paulp + gravatar: https://avatars2.githubusercontent.com/u/9135?v=2&s=60 + commits: 9 + linesAdded: 899 + linesDeleted: 409 + rank: 3 + newContributor: false + - username: huitseeker + gravatar: https://avatars2.githubusercontent.com/u/4142?v=2&s=60 + commits: 3 + linesAdded: 45 + linesDeleted: 38 + rank: 4 + newContributor: false + - category: EPFL + authors: + - username: xeno-by + gravatar: https://avatars1.githubusercontent.com/u/609152?v=2&s=60 + commits: 30 + linesAdded: 2170 + linesDeleted: 984 + rank: 1 + newContributor: false + - username: magarciaEPFL + gravatar: https://avatars2.githubusercontent.com/u/1249748?v=2&s=60 + commits: 5 + linesAdded: 47 + linesDeleted: 17 + rank: 2 + newContributor: false + - category: Community + authors: + - username: densh + gravatar: https://avatars2.githubusercontent.com/u/320966?v=2&s=60 + commits: 20 + linesAdded: 1604 + linesDeleted: 703 + rank: 1 + newContributor: false + - username: soc + gravatar: https://avatars0.githubusercontent.com/u/42493?v=2&s=60 + commits: 11 + linesAdded: 728 + linesDeleted: 606 + rank: 2 + newContributor: false + - username: Ichoran + gravatar: https://avatars3.githubusercontent.com/u/2298644?v=2&s=60 + commits: 8 + linesAdded: 1490 + linesDeleted: 286 + rank: 3 + newContributor: false + - username: som-snytt + gravatar: https://avatars2.githubusercontent.com/u/369425?v=2&s=60 + commits: 6 + linesAdded: 382 + linesDeleted: 224 + rank: 4 + newContributor: false + - username: dotta + gravatar: https://avatars2.githubusercontent.com/u/703748?v=2&s=60 + commits: 5 + linesAdded: 265 + linesDeleted: 13 + rank: 5 + newContributor: false + - username: VladimirNik + gravatar: https://avatars2.githubusercontent.com/u/2835001?v=2&s=60 + commits: 2 + linesAdded: 7 + linesDeleted: 8 + rank: 6 + newContributor: false + - username: rklaehn + gravatar: https://avatars0.githubusercontent.com/u/248257?v=2&s=60 + commits: 2 + linesAdded: 2 + linesDeleted: 83 + rank: 6 + newContributor: false + - username: qerub + gravatar: https://avatars2.githubusercontent.com/u/636?v=2&s=60 + commits: 1 + linesAdded: 10 + linesDeleted: 11 + rank: 7 + newContributor: false + - username: jrudolph + gravatar: https://avatars1.githubusercontent.com/u/9868?v=2&s=60 + commits: 1 + linesAdded: 4 + linesDeleted: 4 + rank: 7 + newContributor: false + - username: skyluc + gravatar: https://avatars3.githubusercontent.com/u/1098830?v=2&s=60 + commits: 1 + linesAdded: 112 + linesDeleted: 54 + rank: 7 + newContributor: false + - username: non + gravatar: https://avatars3.githubusercontent.com/u/218045?v=2&s=60 + commits: 1 + linesAdded: 19 + linesDeleted: 8 + rank: 7 + newContributor: false + - username: xuwei-k + gravatar: https://avatars3.githubusercontent.com/u/389787?v=2&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 7 + newContributor: false + - username: gourlaysama + gravatar: https://avatars2.githubusercontent.com/u/733438?v=2&s=60 + commits: 1 + linesAdded: 136 + linesDeleted: 55 + rank: 7 + newContributor: false +--- From 3d71e5bd8e4dae6dc1d318e8d72768b49e97bede Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Mon, 3 Nov 2014 16:34:38 +0100 Subject: [PATCH 0049/2265] Add scala-fame data --- .../_posts/2014-11-01-scala-fame-2014-10.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md diff --git a/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md b/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md new file mode 100644 index 0000000000..0c957577fb --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-11-01-scala-fame-2014-10.md @@ -0,0 +1,63 @@ +--- +layout: famearchive +title: Contributors of October 2014 +fame-year: 2014 +fame-month: 10 +fame-month-str: October +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars0.githubusercontent.com/u/65551?v=2&s=60 + commits: 11 + linesAdded: 414 + linesDeleted: 51 + rank: 1 + newContributor: false + - username: gkossakowski + gravatar: https://avatars0.githubusercontent.com/u/4217?v=2&s=60 + commits: 2 + linesAdded: 2 + linesDeleted: 2 + rank: 2 + newContributor: false + - username: adriaanm + gravatar: https://avatars2.githubusercontent.com/u/91083?v=2&s=60 + commits: 2 + linesAdded: 54 + linesDeleted: 18 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars3.githubusercontent.com/u/119636?v=2&s=60 + commits: 4 + linesAdded: 146 + linesDeleted: 171 + rank: 1 + newContributor: false + - category: Community + authors: + - username: roberthoedicke + gravatar: https://avatars0.githubusercontent.com/u/9093826?v=2&s=60 + commits: 9 + linesAdded: 15 + linesDeleted: 15 + rank: 1 + newContributor: true + - username: puffnfresh + gravatar: https://avatars1.githubusercontent.com/u/37715?v=2&s=60 + commits: 1 + linesAdded: 19 + linesDeleted: 10 + rank: 2 + newContributor: false + - username: Blaisorblade + gravatar: https://avatars2.githubusercontent.com/u/289960?v=2&s=60 + commits: 1 + linesAdded: 0 + linesDeleted: 93 + rank: 2 + newContributor: false +--- From 84d53a941025d8188d7ce2f8312748ed23ae6de6 Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Wed, 3 Dec 2014 16:47:25 +0100 Subject: [PATCH 0050/2265] Add scala-fame data --- .../_posts/2014-12-01-scala-fame-2014-11.md | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md diff --git a/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md b/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md new file mode 100644 index 0000000000..3c95eb2521 --- /dev/null +++ b/contribute/scala-fame-data/_posts/2014-12-01-scala-fame-2014-11.md @@ -0,0 +1,112 @@ +--- +layout: famearchive +title: Contributors of November 2014 +fame-year: 2014 +fame-month: 11 +fame-month-str: November +fame-categories: + - category: Typesafe + authors: + - username: retronym + gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 + commits: 24 + linesAdded: 650 + linesDeleted: 90 + rank: 1 + newContributor: false + - username: adriaanm + gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 + commits: 3 + linesAdded: 208 + linesDeleted: 54 + rank: 2 + newContributor: false + - username: phaller + gravatar: https://avatars1.githubusercontent.com/u/289943?v=3&s=60 + commits: 1 + linesAdded: 10 + linesDeleted: 8 + rank: 3 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 + commits: 6 + linesAdded: 782 + linesDeleted: 32 + rank: 1 + newContributor: false + - username: heathermiller + gravatar: https://avatars1.githubusercontent.com/u/687163?v=3&s=60 + commits: 2 + linesAdded: 64 + linesDeleted: 66 + rank: 2 + newContributor: false + - category: Community + authors: + - username: gourlaysama + gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 + commits: 7 + linesAdded: 245 + linesDeleted: 83 + rank: 1 + newContributor: false + - username: som-snytt + gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 + commits: 3 + linesAdded: 53 + linesDeleted: 53 + rank: 2 + newContributor: false + - username: advancedxy + gravatar: https://avatars1.githubusercontent.com/u/807537?v=3&s=60 + commits: 2 + linesAdded: 2 + linesDeleted: 2 + rank: 3 + newContributor: true + - username: kanielc + gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 + commits: 2 + linesAdded: 3 + linesDeleted: 3 + rank: 3 + newContributor: true + - username: gdickinson + gravatar: https://avatars3.githubusercontent.com/u/1130928?v=3&s=60 + commits: 2 + linesAdded: 0 + linesDeleted: 380 + rank: 3 + newContributor: true + - username: Ichoran + gravatar: https://avatars2.githubusercontent.com/u/2298644?v=3&s=60 + commits: 2 + linesAdded: 35 + linesDeleted: 18 + rank: 3 + newContributor: false + - username: ruippeixotog + gravatar: https://avatars1.githubusercontent.com/u/613493?v=3&s=60 + commits: 1 + linesAdded: 81 + linesDeleted: 8 + rank: 4 + newContributor: false + - username: mpociecha + gravatar: https://avatars0.githubusercontent.com/u/6143494?v=3&s=60 + commits: 1 + linesAdded: 5 + linesDeleted: 2 + rank: 4 + newContributor: false + - username: soc + gravatar: https://avatars1.githubusercontent.com/u/42493?v=3&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 4 + newContributor: false +--- From def0d83bc4a8ae5ab2c7d07928f1717eec682e0d Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Mon, 12 Jan 2015 09:52:21 -0800 Subject: [PATCH 0051/2265] Removed PHP issues page in favor of direct JIRA queries. --- contribute/community-tickets.md | 10 -------- contribute/guide.md | 2 +- contribute/index.md | 45 +++++++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 16 deletions(-) delete mode 100644 contribute/community-tickets.md diff --git a/contribute/community-tickets.md b/contribute/community-tickets.md deleted file mode 100644 index e458d3b6f2..0000000000 --- a/contribute/community-tickets.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: page-full-width -title: Community tickets ---- - -Below is a selection of tickets from -[Scala's bug tracker](https://issues.scala-lang.org/) -that we think are a good starting point for you, as the community. - -
    diff --git a/contribute/guide.md b/contribute/guide.md index ac27e53719..9446e6ce9c 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -21,7 +21,7 @@ title: Contributing guide
    -

    Community issues

    +

    Community issues

    Get cracking on some easy to approach issues.

    diff --git a/contribute/index.md b/contribute/index.md index d2402cf4d2..d1ba675f05 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -23,9 +23,44 @@ An easy but very important way to contribute to Scala is to ### Compiler and other tools -Want to dive into the hardcore business? Check out our -[selection of community tickets](./community-tickets.html), -which are good starting points to contributing to the compiler and -surrounding tools, like ScalaDoc. - More info in our [contributing guide](./guide.html). + +### Community Tickets + +The following links provide starting points for +various contributor activities: + +
    +
    +
    +

    Documentation

    +

    Help augment or correct the documentation.

    +
    +
    +

    Core Libraries

    +

    Community bugs and enhancements on the core libs.

    +
    +
    + +
    +
    +

    Tools

    +

    Help with the Scala tool chain.

    +
    +
    +

    Compiler

    +

    Ready for a challenge? Here's the compiler bugs.

    +
    +
    + +
    +
    +

    Bugs

    +

    All bugs marked with the label community.

    +
    +
    +

    All Issues

    +

    Bugs + Enhancements marked with the label community.

    +
    +
    +
    From 76fcdfafa32914a60a0dd16e0ee7c75094e9682f Mon Sep 17 00:00:00 2001 From: Fabien Salvi Date: Wed, 14 Jan 2015 11:24:27 +0100 Subject: [PATCH 0052/2265] Add scala-fame data --- .../_posts/2015-01-01-scala-fame-2014-12.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md diff --git a/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md b/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md new file mode 100644 index 0000000000..c11348b33a --- /dev/null +++ b/contribute/scala-fame-data/_posts/2015-01-01-scala-fame-2014-12.md @@ -0,0 +1,70 @@ +--- +layout: famearchive +title: Contributors of December 2014 +fame-year: 2014 +fame-month: 12 +fame-month-str: December +fame-categories: + - category: Typesafe + authors: + - username: adriaanm + gravatar: https://avatars3.githubusercontent.com/u/91083?v=3&s=60 + commits: 2 + linesAdded: 962 + linesDeleted: 290 + rank: 1 + newContributor: false + - username: retronym + gravatar: https://avatars1.githubusercontent.com/u/65551?v=3&s=60 + commits: 1 + linesAdded: 5 + linesDeleted: 1 + rank: 2 + newContributor: false + - category: EPFL + authors: + - username: lrytz + gravatar: https://avatars2.githubusercontent.com/u/119636?v=3&s=60 + commits: 4 + linesAdded: 61 + linesDeleted: 50 + rank: 1 + newContributor: false + - category: Community + authors: + - username: gbasler + gravatar: https://avatars0.githubusercontent.com/u/273035?v=3&s=60 + commits: 2 + linesAdded: 567 + linesDeleted: 1 + rank: 1 + newContributor: false + - username: kanielc + gravatar: https://avatars1.githubusercontent.com/u/1334074?v=3&s=60 + commits: 1 + linesAdded: 43 + linesDeleted: 6 + rank: 2 + newContributor: false + - username: xuwei-k + gravatar: https://avatars2.githubusercontent.com/u/389787?v=3&s=60 + commits: 1 + linesAdded: 2 + linesDeleted: 2 + rank: 2 + newContributor: false + - username: gourlaysama + gravatar: https://avatars3.githubusercontent.com/u/733438?v=3&s=60 + commits: 1 + linesAdded: 1 + linesDeleted: 1 + rank: 2 + newContributor: false + - username: som-snytt + gravatar: https://avatars3.githubusercontent.com/u/369425?v=3&s=60 + commits: 1 + linesAdded: 44 + linesDeleted: 3 + rank: 2 + newContributor: false +--- From fd4cf442dbb1b58fe5dd583068bbd1dcb2b07aca Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Wed, 14 Jan 2015 14:14:00 -0800 Subject: [PATCH 0053/2265] Add scaladoc contribution page and link up. --- contribute/contribute-scaladoc.md | 116 ++++++++++++++++++++++++++++++ contribute/index.md | 2 + 2 files changed, 118 insertions(+) create mode 100644 contribute/contribute-scaladoc.md diff --git a/contribute/contribute-scaladoc.md b/contribute/contribute-scaladoc.md new file mode 100644 index 0000000000..3bea0dea5a --- /dev/null +++ b/contribute/contribute-scaladoc.md @@ -0,0 +1,116 @@ +--- +layout: page +title: Scaladoc Contributions +--- + +This page is specific to scaladoc contributions. For contributions to the scala-lang +documentation site, [help with the documentation](http://docs.scala-lang.org/contribute.html). + +*Please note, these instructions cover contributions to the scala language and +core libraries only. For other scala projects please check those projects for +the contribution steps and guidelines. Thank you.* + +## Overview + +Since the scaladoc documentation is located in scala source code files, the +process for contributing scaladoc is similar to that of contributing bug-fixes +to the scala code base, but without the requirement that there be a JIRA bug +first (just use a `scaladoc/xxxx` branch name instead of `issue/NNNN`). +However, if an issue *does* exist, please use `issue/NNNN` (where NNNN is the bug id) +instead. + +If you would like to assist us by helping us find missing documentation and +submitting issues, [please read the following section](#submit-scaladoc-issues). +If you want to contribute scaladoc, +[jump down to the next section](#contribute-scaladoc). + +## Submit Scaladoc Issues + +You can also contribute by helping us to identify missing documentation. To do +this, [browse the current API documentation](http://www.scala-lang.org/api/current/) +and identify missing, incorrect or inadequate documentation. In particular pay +attention to the package objects for important packages (these often get overlooked +for documentation and are a good place for API overviews). + +If you find an issue, please log it in the [Scala issue browser](https://issues.scala-lang.org) +**after making sure it is not already logged as an issue**. To help with +disambiguation, please use the following format for issue title: + +* Use an action describing the work required. E.g. Add, Document, Correct, Remove +* Use the full package, class/trait/object name (or state package object if + that is the case). +* Extremely short description of what to do. +* More detail can (and should) go into the issue description, including a short + justification for the issue if it provides additional detail. + +Here is an example of the title and description for an example scaladoc issue: + +`Document scala.concurrent.Future object, include code examples` + +(note the explicit companion object called out in the title) + +and the description: + +`The methods on the Future companion object are critical` +`for using Futures effectively without blocking. Provide code` +`examples of how methods like sequence, transform, fold and` +`firstCompletedOf should be used.` + +In addition to following these conventions, please add `documentation` and +`community` labels to the issue, and put them in the `Documentation and API` +component so that they show up in the correct issue filters. + +## Contribute scaladoc + +### Required reading + +Please familiarize yourself with **all** of the following before contributing +scaladoc to save time, effort, mistakes and repetition. + +* [Forking the Repo](./hacker-guide.html#set-up) follow setup steps through + branch name. If providing scaladoc related to a JIRA issue, use `issue/NNNN` + or `ticket/NNNN` as the guide states. If providing scaladoc with no associated + JIRA issue, use `scaladoc/xxxx` instead, where xxxx is a descriptive but + short branch name, e.g. `scaladoc/future-object`. +* [Scaladoc basics](http://docs.scala-lang.org/overviews/scaladoc/basics.html) + covers the use of scaladoc tags, markdown and other features. +* [Scaladoc usage](http://docs.scala-lang.org/overviews/scaladoc/usage.html) if + you are unfamiliar with all of the features of scaladoc, e.g. switching between + companions, browsing package object documentation, searching, token searches + and so on. +* Prior to commit, be sure to read + [A note about git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). +* Also read the Scala [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). + Some of this document will clearly not apply (like the sections on providing tests, + however see below for some special requirements for documentation). Do still read + the whole document though, and pay close attention to the title and commit + message formats, noting *present tense*, *length limits* and that it must merge + cleanly. Remember that the title of the pull request will become the commit + message when merged. **Also**, be sure to assign one or more reviewers to the PR, list of + reviewers is at the bottom of this document, but the quick version is to add + `Review by @dickwall` **in the pull request comments**. + +### Extra Requirements for Scaladoc Commits + +Although some of the requirements for bug fix pull requests are not needed for +scaladoc commits, here are the step by step requirements to ensure your scaladoc +PR is merged in smoothly: + +* Any and all code examples provided should *be correct, compile and run* as + expected (ensure this in the REPL or your IDE). +* Spelling must be checked for all written language *and* code examples where + possible. Most editors have some spell checking feature available. Obviously + scala code is likely to flag as mis-spelled sometimes, but any written language + should be checked. If you can also use a grammar checker, even better. We + *will* ask for spelling and grammar to be corrected before acceptance. +* You **must** also run `ant docs`, fix any problems and check the formatting and + layout of your changes. Again, corrections will be required if formatting or + layout are inadequate. After running `ant docs` the generated documents can be + found under the `build/scaladoc/` folders (probably in the `library` folder + but maybe under the others depending on what section of the scala source you + are working on). +* All of these steps are required to save time for both the reviewers and + contributors. It benefits everyone to ensure that the PR to merge process is + as smooth and streamlined as possible. + +Thanks for helping us improve the scaladoc. diff --git a/contribute/index.md b/contribute/index.md index d2402cf4d2..995617634d 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -20,6 +20,8 @@ how to efficiently report a bug. An easy but very important way to contribute to Scala is to [help with the documentation](http://docs.scala-lang.org/contribute.html). +If you want to [contribute to scaladoc](./contribute-scaladoc.html), the +process is slightly different, since scaladoc lives alongside the source code. ### Compiler and other tools From b049734092803dafea95e4318322ff0e6102ff33 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Tue, 27 Jan 2015 09:20:21 -0800 Subject: [PATCH 0054/2265] Corrected JIRA search URL for compiler bugs. --- contribute/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index d1ba675f05..65c9c501cd 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -48,7 +48,7 @@ various contributor activities:

    Help with the Scala tool chain.

    -

    Compiler

    +

    Compiler

    Ready for a challenge? Here's the compiler bugs.

    From b53c6bd2d67eddb97f61c857ed35989425da73ee Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 29 Jan 2015 14:21:15 +0100 Subject: [PATCH 0055/2265] Wording tweaks --- contribute/contribute-scaladoc.md | 75 +++++++++++++++++-------------- contribute/index.md | 6 +-- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/contribute/contribute-scaladoc.md b/contribute/contribute-scaladoc.md index 3bea0dea5a..d9bd931de3 100644 --- a/contribute/contribute-scaladoc.md +++ b/contribute/contribute-scaladoc.md @@ -1,38 +1,45 @@ --- layout: page -title: Scaladoc Contributions +title: Contribute to API Documentation --- -This page is specific to scaladoc contributions. For contributions to the scala-lang -documentation site, [help with the documentation](http://docs.scala-lang.org/contribute.html). +This page is specific to API documentation contributions – that is, API +documentation for +[Scala's standard library](http://scala-lang.org/api/current/#package) – +sometimes referred to as Scaladoc contributions. -*Please note, these instructions cover contributions to the scala language and -core libraries only. For other scala projects please check those projects for -the contribution steps and guidelines. Thank you.* +For contributions to tutorial and guide-style documentation on +[docs.scala-lang.org](http://docs.scala-lang.org), +see the ["doc-site"'s contribution guide](http://docs.scala-lang.org/contribute.html). + +*Please note, these instructions cover documentation contributions Scala core +libraries only. For other Scala projects please check those projects for the +contribution steps and guidelines. Thank you.* ## Overview -Since the scaladoc documentation is located in scala source code files, the -process for contributing scaladoc is similar to that of contributing bug-fixes -to the scala code base, but without the requirement that there be a JIRA bug -first (just use a `scaladoc/xxxx` branch name instead of `issue/NNNN`). -However, if an issue *does* exist, please use `issue/NNNN` (where NNNN is the bug id) +Since API documentation is located in Scala source code files, the +process for contributing API documentation is similar to that of contributing bug-fixes +to the Scala code base, but without the requirement that there be an issue filed on JIRA +first (when forking/branching, just use a `scaladoc/xxxx` branch name instead of `issue/NNNN`). +However, if an issue *does* exist, please use `issue/NNNN` (where NNNN is the ticket number) instead. If you would like to assist us by helping us find missing documentation and -submitting issues, [please read the following section](#submit-scaladoc-issues). -If you want to contribute scaladoc, -[jump down to the next section](#contribute-scaladoc). +submitting bug reports for existing documentation, +[please read the following section](#contribute-api-documentation-bug-reports). +If you want to contribute new API documentation, +[jump down to the next section](#contribute-new-api-documentation). -## Submit Scaladoc Issues +## Contribute API Documentation Bug Reports -You can also contribute by helping us to identify missing documentation. To do -this, [browse the current API documentation](http://www.scala-lang.org/api/current/) -and identify missing, incorrect or inadequate documentation. In particular pay -attention to the package objects for important packages (these often get overlooked -for documentation and are a good place for API overviews). +One good way to contribute is by helping us to identify missing documentation. To do +this, [browse the current API documentationn](http://www.scala-lang.org/api/current/) +and identify missing, incorrect or inadequate documentation. A good place to start is +is package objects for important packages (these often get overlooked for documentation +and are a good place for API overviews). -If you find an issue, please log it in the [Scala issue browser](https://issues.scala-lang.org) +If you find an issue, please log it in the [Scala issue tracker](https://issues.scala-lang.org) **after making sure it is not already logged as an issue**. To help with disambiguation, please use the following format for issue title: @@ -43,7 +50,7 @@ disambiguation, please use the following format for issue title: * More detail can (and should) go into the issue description, including a short justification for the issue if it provides additional detail. -Here is an example of the title and description for an example scaladoc issue: +Here is an example of the title and description for an example API documentation issue: `Document scala.concurrent.Future object, include code examples` @@ -60,22 +67,22 @@ In addition to following these conventions, please add `documentation` and `community` labels to the issue, and put them in the `Documentation and API` component so that they show up in the correct issue filters. -## Contribute scaladoc +## Contribute New API Documentation -### Required reading +### Required Reading Please familiarize yourself with **all** of the following before contributing -scaladoc to save time, effort, mistakes and repetition. +new API documentation to save time, effort, mistakes and repetition. * [Forking the Repo](./hacker-guide.html#set-up) follow setup steps through - branch name. If providing scaladoc related to a JIRA issue, use `issue/NNNN` - or `ticket/NNNN` as the guide states. If providing scaladoc with no associated + branch name. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` + or `ticket/NNNN` as the guide states. If providing API documentation with no associated JIRA issue, use `scaladoc/xxxx` instead, where xxxx is a descriptive but short branch name, e.g. `scaladoc/future-object`. -* [Scaladoc basics](http://docs.scala-lang.org/overviews/scaladoc/basics.html) +* [Scaladoc for library authors](http://docs.scala-lang.org/overviews/scaladoc/for-library-authors.html) covers the use of scaladoc tags, markdown and other features. -* [Scaladoc usage](http://docs.scala-lang.org/overviews/scaladoc/usage.html) if - you are unfamiliar with all of the features of scaladoc, e.g. switching between +* [Scaladoc's interface](http://docs.scala-lang.org/overviews/scaladoc/interface.html) + covers all of the features of Scaladoc's interface, e.g. switching between companions, browsing package object documentation, searching, token searches and so on. * Prior to commit, be sure to read @@ -93,24 +100,24 @@ scaladoc to save time, effort, mistakes and repetition. ### Extra Requirements for Scaladoc Commits Although some of the requirements for bug fix pull requests are not needed for -scaladoc commits, here are the step by step requirements to ensure your scaladoc +API documentation commits, here are the step by step requirements to ensure your API documentation PR is merged in smoothly: * Any and all code examples provided should *be correct, compile and run* as expected (ensure this in the REPL or your IDE). * Spelling must be checked for all written language *and* code examples where possible. Most editors have some spell checking feature available. Obviously - scala code is likely to flag as mis-spelled sometimes, but any written language + Scala code is likely to flag as mis-spelled sometimes, but any written language should be checked. If you can also use a grammar checker, even better. We *will* ask for spelling and grammar to be corrected before acceptance. * You **must** also run `ant docs`, fix any problems and check the formatting and layout of your changes. Again, corrections will be required if formatting or layout are inadequate. After running `ant docs` the generated documents can be found under the `build/scaladoc/` folders (probably in the `library` folder - but maybe under the others depending on what section of the scala source you + but maybe under the others depending on what section of the Scala source you are working on). * All of these steps are required to save time for both the reviewers and contributors. It benefits everyone to ensure that the PR to merge process is as smooth and streamlined as possible. -Thanks for helping us improve the scaladoc. +Thanks for helping us improve the Scaladoc API documentation! diff --git a/contribute/index.md b/contribute/index.md index 995617634d..5dda418cbf 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -19,9 +19,9 @@ how to efficiently report a bug. ### Help with the documentation An easy but very important way to contribute to Scala is to -[help with the documentation](http://docs.scala-lang.org/contribute.html). -If you want to [contribute to scaladoc](./contribute-scaladoc.html), the -process is slightly different, since scaladoc lives alongside the source code. +[help with the guide/tutorial-style documentation on docs.scala-lang.org](http://docs.scala-lang.org/contribute.html). +If you want to [contribute to Scala standard library API docmentation](./contribute-scaladoc.html), the +process is slightly different, since API documentation lives within Scala standard library source code. ### Compiler and other tools From b27128fd7967d882e274a80fc0328c7d4df6f4c0 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 29 Jan 2015 14:25:00 +0100 Subject: [PATCH 0056/2265] Some reorganization and tweaks --- contribute/index.md | 2 +- ...-scaladoc.md => scala-standard-library-api-documentation.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename contribute/{contribute-scaladoc.md => scala-standard-library-api-documentation.md} (99%) diff --git a/contribute/index.md b/contribute/index.md index 5dda418cbf..f2bed88bae 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -20,7 +20,7 @@ how to efficiently report a bug. An easy but very important way to contribute to Scala is to [help with the guide/tutorial-style documentation on docs.scala-lang.org](http://docs.scala-lang.org/contribute.html). -If you want to [contribute to Scala standard library API docmentation](./contribute-scaladoc.html), the +If you want to [contribute to Scala standard library API docmentation](./scala-standard-library-api-documentation.html), the process is slightly different, since API documentation lives within Scala standard library source code. ### Compiler and other tools diff --git a/contribute/contribute-scaladoc.md b/contribute/scala-standard-library-api-documentation.md similarity index 99% rename from contribute/contribute-scaladoc.md rename to contribute/scala-standard-library-api-documentation.md index d9bd931de3..ec41aee3cb 100644 --- a/contribute/contribute-scaladoc.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -97,7 +97,7 @@ new API documentation to save time, effort, mistakes and repetition. reviewers is at the bottom of this document, but the quick version is to add `Review by @dickwall` **in the pull request comments**. -### Extra Requirements for Scaladoc Commits +### Extra Requirements for Scaladoc Documentation Commits Although some of the requirements for bug fix pull requests are not needed for API documentation commits, here are the step by step requirements to ensure your API documentation From 66f39d2e292cdc347b7d3c8d59835e83c59739f6 Mon Sep 17 00:00:00 2001 From: Justin Pihony Date: Mon, 2 Feb 2015 15:32:49 -0500 Subject: [PATCH 0057/2265] Fix the Forking url and grammatical consistency Review by @dickwall --- .../scala-standard-library-api-documentation.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index ec41aee3cb..de5a970bbe 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -21,8 +21,9 @@ contribution steps and guidelines. Thank you.* Since API documentation is located in Scala source code files, the process for contributing API documentation is similar to that of contributing bug-fixes to the Scala code base, but without the requirement that there be an issue filed on JIRA -first (when forking/branching, just use a `scaladoc/xxxx` branch name instead of `issue/NNNN`). -However, if an issue *does* exist, please use `issue/NNNN` (where NNNN is the ticket number) +first. When forking/branching, just use a `scaladoc/xxxx` branch name, where xxxx is a +descriptive, but short branch name (e.g. `scaladoc/future-object`). +However, if an issue *does* exist, please use `issue/NNNN`, where NNNN is the ticket number, instead. If you would like to assist us by helping us find missing documentation and @@ -35,8 +36,8 @@ If you want to contribute new API documentation, One good way to contribute is by helping us to identify missing documentation. To do this, [browse the current API documentationn](http://www.scala-lang.org/api/current/) -and identify missing, incorrect or inadequate documentation. A good place to start is -is package objects for important packages (these often get overlooked for documentation +and identify missing, incorrect or inadequate documentation. A good place to start is +package objects for important packages (these often get overlooked for documentation and are a good place for API overviews). If you find an issue, please log it in the [Scala issue tracker](https://issues.scala-lang.org) @@ -74,11 +75,10 @@ component so that they show up in the correct issue filters. Please familiarize yourself with **all** of the following before contributing new API documentation to save time, effort, mistakes and repetition. -* [Forking the Repo](./hacker-guide.html#set-up) follow setup steps through - branch name. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` +* [Forking the Repo](./hacker-guide.html#2_set_up) - follow the setup steps through + the Branch section. If providing new documentation related to an existing JIRA issue, use `issue/NNNN` or `ticket/NNNN` as the guide states. If providing API documentation with no associated - JIRA issue, use `scaladoc/xxxx` instead, where xxxx is a descriptive but - short branch name, e.g. `scaladoc/future-object`. + JIRA issue, use `scaladoc/xxxx` instead. * [Scaladoc for library authors](http://docs.scala-lang.org/overviews/scaladoc/for-library-authors.html) covers the use of scaladoc tags, markdown and other features. * [Scaladoc's interface](http://docs.scala-lang.org/overviews/scaladoc/interface.html) From f2a174cea939a311901274c187ffafadf17ebed0 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Mon, 2 Feb 2015 14:10:10 -0800 Subject: [PATCH 0058/2265] Correct a couple of spelling typos on contribution pages. --- contribute/index.md | 2 +- .../scala-standard-library-api-documentation.md | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contribute/index.md b/contribute/index.md index a065565a98..9ea981b115 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -5,7 +5,7 @@ title: Contribute The Scala programming language is an open source project with a very diverse community, where people from all over the world contribute their work, -with everyone benefitting from friendly help and advice, and +with everyone benefiting from friendly help and advice, and kindly helping others in return. So why not join the Scala community and help everyone make things better? diff --git a/contribute/scala-standard-library-api-documentation.md b/contribute/scala-standard-library-api-documentation.md index de5a970bbe..519c85a030 100644 --- a/contribute/scala-standard-library-api-documentation.md +++ b/contribute/scala-standard-library-api-documentation.md @@ -4,11 +4,11 @@ title: Contribute to API Documentation --- This page is specific to API documentation contributions – that is, API -documentation for -[Scala's standard library](http://scala-lang.org/api/current/#package) – +documentation for +[Scala's standard library](http://scala-lang.org/api/current/#package) – sometimes referred to as Scaladoc contributions. -For contributions to tutorial and guide-style documentation on +For contributions to tutorial and guide-style documentation on [docs.scala-lang.org](http://docs.scala-lang.org), see the ["doc-site"'s contribution guide](http://docs.scala-lang.org/contribute.html). @@ -21,13 +21,13 @@ contribution steps and guidelines. Thank you.* Since API documentation is located in Scala source code files, the process for contributing API documentation is similar to that of contributing bug-fixes to the Scala code base, but without the requirement that there be an issue filed on JIRA -first. When forking/branching, just use a `scaladoc/xxxx` branch name, where xxxx is a +first. When forking/branching, just use a `scaladoc/xxxx` branch name, where xxxx is a descriptive, but short branch name (e.g. `scaladoc/future-object`). However, if an issue *does* exist, please use `issue/NNNN`, where NNNN is the ticket number, instead. If you would like to assist us by helping us find missing documentation and -submitting bug reports for existing documentation, +submitting bug reports for existing documentation, [please read the following section](#contribute-api-documentation-bug-reports). If you want to contribute new API documentation, [jump down to the next section](#contribute-new-api-documentation). @@ -35,9 +35,9 @@ If you want to contribute new API documentation, ## Contribute API Documentation Bug Reports One good way to contribute is by helping us to identify missing documentation. To do -this, [browse the current API documentationn](http://www.scala-lang.org/api/current/) -and identify missing, incorrect or inadequate documentation. A good place to start is -package objects for important packages (these often get overlooked for documentation +this, [browse the current API documentation](http://www.scala-lang.org/api/current/) +and identify missing, incorrect or inadequate documentation. A good place to start is +package objects for important packages (these often get overlooked for documentation and are a good place for API overviews). If you find an issue, please log it in the [Scala issue tracker](https://issues.scala-lang.org) From db2a14f159ab6db8c802cb415885cc1645cbcb85 Mon Sep 17 00:00:00 2001 From: JustinPihony Date: Tue, 3 Feb 2015 21:35:08 -0500 Subject: [PATCH 0059/2265] Add u to docmentation typo Review by @dickwall --- contribute/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute/index.md b/contribute/index.md index 9ea981b115..338ff06a06 100644 --- a/contribute/index.md +++ b/contribute/index.md @@ -20,7 +20,7 @@ how to efficiently report a bug. An easy but very important way to contribute to Scala is to [help with the guide/tutorial-style documentation on docs.scala-lang.org](http://docs.scala-lang.org/contribute.html). -If you want to [contribute to Scala standard library API docmentation](./scala-standard-library-api-documentation.html), the +If you want to [contribute to Scala standard library API documentation](./scala-standard-library-api-documentation.html), the process is slightly different, since API documentation lives within Scala standard library source code. ### Compiler and other tools From eb1e3cbd55fa0fb19c8f0f9eb444cd16527d4d15 Mon Sep 17 00:00:00 2001 From: Dick Wall Date: Mon, 9 Feb 2015 14:51:26 -0800 Subject: [PATCH 0060/2265] Update contributor pages for bugs/issues - provide issue checklist - Individual changes to docs: - corelibs.md and tools.md - add placeholders/call for help - documentation.md - small changes and spelling only - guide.md - bugfix checklist with links to other resources for each step - hacker-guide.md - spelling corrections - index.md - organize by type of contribution - scala-internals.md - new doc describing use of scala-internals for coordination - scala-standard-library-api-documentation.md - spelling/minor --- contribute/corelibs.md | 8 + contribute/documentation.md | 92 ++++++++---- contribute/guide.md | 137 ++++-------------- contribute/hacker-guide.md | 6 +- contribute/index.md | 67 +++++++-- contribute/scala-internals.md | 45 ++++++ ...cala-standard-library-api-documentation.md | 6 +- contribute/tools.md | 8 + 8 files changed, 213 insertions(+), 156 deletions(-) create mode 100644 contribute/corelibs.md create mode 100644 contribute/scala-internals.md create mode 100644 contribute/tools.md diff --git a/contribute/corelibs.md b/contribute/corelibs.md new file mode 100644 index 0000000000..1429ec87ff --- /dev/null +++ b/contribute/corelibs.md @@ -0,0 +1,8 @@ +--- +layout: page +title: Core Library Contributions +--- +## Under Construction + +If you would like to help complete this document, welcome, and please head over and read [Documentation Contributions](./documentation.html#the-scala-language-site), +and let us know on the [scala-internals](https://groups.google.com/forum/#!forum/scala-internals) forum (suggested post title: `[docs] Core Library Contributions`) so that we can get you hooked up with the right people. \ No newline at end of file diff --git a/contribute/documentation.md b/contribute/documentation.md index 05b2455a5f..da20b9360d 100644 --- a/contribute/documentation.md +++ b/contribute/documentation.md @@ -2,28 +2,70 @@ layout: page title: Documentation Contributions --- -# Contributing documentation to the Scala project - -TODO - - +## Contributing Documentation to the Scala project + +There are several ways you can help out with the improvement of Scala documentation. These include: + +* Code examples and tutorials in activator templates. +* The Scala Wiki +* API Documentation in Scaladoc +* Guides, Overviews, Tutorials, Cheat Sheets and more on the docs.scala-lang.org site +* Updating Documents on the Main Scala Language Site (this one) + +Please read this page, and the pages linked from this one, fully before contributing documentation. Many of the questions you have will be answered in these resources. If you have a question that isn't answered, feel free to ask on the [scala-internals Google group](https://groups.google.com/forum/#!forum/scala-internals) and then, please, submit a pull request with updated documentation reflecting that answer. + +**General requirements** for documentation submissions include spell-checking all written language, ensuring code samples compile and run correctly, correct grammar, and clean formatting/layout of the documentation. + +Thanks + +### Examples/Tutorials in Activator Templates + +[Typesafe Activator](https://typesafe.com/community/core-tools/activator-and-sbt) +is a tool based on SBT, with a UI mode that is ideal for code based tutorials, overviews and walk-throughs. To contribute an example in activator, you can fork an existing template, edit it, add a tutorial, upload it to github and then submit the github project into the template repository. It's the fastest way to produce a working code example with tutorial. + +Please see [Contributing an Activator Template](https://typesafe.com/activator/template/contribute) for more details. + +### API Documentation (Scaladoc) + +The Scala API documentation lives with the scala project source code. There are many ways you can help with improving Scaladoc, including: + +* [Log issues for missing scaladoc documentation](./scala-standard-library-api-documentation.html#contribute-api-documentation-bug-reports) - +Please *follow the issue submission process closely* to help prevent duplicate issues being created. +* [Claim Scaladoc Issues and Provide Documentation](./scala-standard-library-api-documentation.html) - please claim issues prior to working on a specific scaladoc task to prevent duplication of effort. If you sit on an issue for too long without submitting a pull request, it will revert back to unassigned and you will need to re-claim it. +* You can also just +[submit new Scaladoc](./scala-standard-library-api-documentation.html) +without creating an issue, but please look to see if there is an issue already submitted for your task and claim it if there is. If not, please post your intention to work on a specific scaladoc task on scala-internals so that people know what you are doing. + +### The Scala Wiki + +The [Scala wiki](https://wiki.scala-lang.org/) could be a useful resource, but tends to get out of date quickly. It is perhaps best viewed as a place for information to temporarily live while it is constructed and refined, but with an aim to putting the material into the [docs.scala-lang.org](http://docs.scala-lang.org) site eventually (see the next section). Nonetheless, it is a fast way to add some public documentation. + +The wiki is self documenting, so make sure to take a look at the [home page](https://wiki.scala-lang.org/) to get started. Please consider contributions to [docs.scala-lang.org](docs.scala-lang.org) for more enduring documentation, even though it is more work to get through the review process for the main doc site. + +### The Main Scala Documentation Site + +[docs.scala-lang.org](https://wiki.scala-lang.org/) houses the primary source of written, non-API documentation for Scala. It's a github project that you can fork and submit pull requests from. It includes: + +* Overviews +* Tutorials +* Conversion Guides from Other Languages +* Cheat Sheets +* A Glossary +* The Scala Style Guide +* The Scala Language Specification +* SIP (Scala Improvement Process) Proposals +and more + +Please read [contributing to the docs.scala-lang.org site](http://docs.scala-lang.org/contribute.html) through before embarking on changes. The site uses +the [Jekyll](http://jekyllrb.com/) markdown engine so you will need to follow the instructions to get that running as well. + +### The Scala Language Site + +Additional high-level documentation (including documentation on contributing +to Scala and related projects) is provided on the main +[Scala Language site](http://scala-lang.org), and is also kept in the +[scala-lang github project](https://github.com/scala/scala-lang) which may be forked to create pull requests. + +Please read both the +[docs.scala-lang.org contribution](http://docs.scala-lang.org/contribute.html) document and the scala-lang.org github README file before embarking on any changes to the Scala language site, as it uses the same Jekyll markdown tool and many of the same conventions as the Scala documentation site. + diff --git a/contribute/guide.md b/contribute/guide.md index 9446e6ce9c..809c6558d5 100644 --- a/contribute/guide.md +++ b/contribute/guide.md @@ -1,5 +1,5 @@ --- -layout: page-full-width +layout: page title: Contributing guide --- @@ -13,10 +13,6 @@ title: Contributing guide

    Report an issue

    File a bug report or a feature request.

    -
    -

    Documentation

    -

    Improve the documentation itself.

    -
    @@ -28,10 +24,6 @@ title: Contributing guide

    Hacker's guide

    Learn to write good code and improve your chances of contributing to the Scala galaxy.

    -
    -

    Hall of Fame

    -

    Track your rockstar status in the community.

    -