From 9ff6a34edaecda2a36d0e157c582ed0bf35caa76 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 3 May 2012 14:30:40 +0200 Subject: [PATCH 0001/3174] 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/3174] 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/3174] 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/3174] 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/3174] "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/3174] 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/3174] 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 z^w=7y{t@jz!%D%(pK40BcU6~wf~6~>ZQB;SPuF2&V9`RWc6H6K>$?t@YcFjNkkcZx zTWRk2Kyptm73?@F+8PnHS z#mrwmG+LnX zr0f{M31T#_1>!BR^zh>LltdNA2q=M#ygMB8x9Pk|NM}5ii`xHNynHout_aMWFbADl zH9@Zq%~7>hU8KdH#=>ups6-SUv3ZJsBP&)0@1lc|gGzop`Q*u41*F$7%1H{5Aw{xd ze#(`v$o{tw?PbxeV|yjIrtyAIc=&)r8~e*3V%cU%L7;IHlb^yD)5axhpn5|keamb6jW(>8~dV@4C~3h zoC{oq3t&_F3FSZg`)R0Kr7UV!EXFP430S#!F2;Sm8lJ6(qD)Z=*cY~_aI$||6bGWb zFf{vykgq)XBeW$<2=^`b89Ng9y*LM1`wDPnt`%C=tz>BX8C$ecdG&8nN3X=ho;|CA zRj@4wOFQtShCDmVrm1sBL;@)zPv(UEjnq5ouf)jx!mQ=BoFyfLgu)pbt z_MO|}d9DnMdgMX;^39Vd{??Ot_|30St!z>JHtstNXg&tv?382=sqCATJF!)#DTJMj z=0Q~pqy8vF$Pd#`O|zZ+XB^qns#xaaL;7G*{8Z@K5~YiCfT2(%ZNur@i#>lvf--8# z0Y|e`qm)SnJE985U85vK?w|sRZ?4EoUDthvxm+X%q7aQJT7)(uAJX@z2_2uAX^A+% zX5GtHHb&cK9pP$P8-~A3C0V*}Ix5ufiGsY>E8~QeSt)9k*)C)+J{fVKL_7IVyhviK zADS0=$~G)7PNeG8t1rH2S+Nufgs}g#nJnUzlIo2>ZmC-K(|qp5S1l7E!6h(ed;_qn zVOrwG?Plf6$wQ?rn27#K>UDNT5_q`;T0Ac8mWFO(ytv9;zB0E(#2a-ktY8V$t6hUi zsvy-yWT`)m6U0D2>Emgn%uo!~t3|3;DIb||5H59Fhr9hlVq zx$BSOJootp`1@eXZ?n*4KwlJ@w;rYVMKv)#vWGP8H1`_y$AlS2*wQ;=?r-bRv{n@q z=3poX|3s^&J1P~4`IG~O{+xhB@j%E^Prc0z{9U+zlXoW`-iG(z+CYIgQ(XZRf9Vox zwYwE{N(3WF6bXfSV}WfTQwPN8-Uh#03f3v&$Sc+u6 zKe^F1coyaij`X1^xl>rK1X4FHaBxiH?F_&nRl_8-s-dh`>D;@D(#i#N;fr;NjDfe0%3vYJ~k$ z;C*oqo_l+$@=xKN+5W*H9H_ZMMi;4(X{>woT6VxQJ$yyfA| z4^_C29~;UWEkdzzy)pjCM?Y-UnPWmcsqk)R3JtPlNQ@i;Q>%o$?Vv%^c69j^Cyy6J z{~?d@mIz*v$1;?%bBDhoz#s8*_1Au`Pub=sM%M$GTc0@iJ6``W3oqZQKzEH|@0aXt zUJ9N@?hu#E$yPWq>dHeti&lul?8y@_;+|R9zkMyvBnP2Uok~2oHwc$04ApPg5J8@t zfTk;nRly@dD-p)(Rg3tf(!$OmUzHJI(6E`?pg4JOa^o8qLYt8{@z?EE<&^K~9NQJ- zY9b_&Y{Vp%XidcM1|2a%--=UK#s`!gZ zu)Qi)Pft?XAj>X!>qw=DYwju}$xuA9+~P(RItUEPd# z-jBz=x_bRq=tUXo0Ohq{=GJw9cElyPtgI<9C(&%c6K;sDGNL9hd%%@}q zqTk3DaQ56~JoDc7*v0)ZlizcME8X#4{O^Sa5WzzRvC$bgy>GVij7{WeZl5sR{m3&| zyL1-j&!37F{BxK{y!+C_D9T8^} zlJB`;c_#m~X)=(5M~}9wbR6KNqOxfic@p6}QQd*KeBKEI8wyN6Ze)Ap+$25gT}47> zOs5a7QucVx@Du|A02$HP$YHDH5@Nw2#-%V^v;toaU@>VuGo%E+(#6AQ^6>?6l{;v8 z=WUZZ&GE_15Andj&UiriuzMyqvi@w-Si!Hb~u(xN;A$m_6r2M39b*52+WXj@va|3GdG6aQf*k zOnz>8#npa>AnJ)Ap8ltPg3D;^UdXqwEcb1O7AS|JHQ9;NLB)~$uwyD%t_`YpF2%M@ zcXpf#KwB8uD;XGEm~*FUyz0n-wO||=%yh!#>p+IPq;G5=5E7~o?AdaC7Z2^GpL)R1 zPwlRWDD2svWO)Un*N{=%H(3Z@O`Ce_Ajtkj(VPbI3byCp`4*+BOvI#5KgCm{e^F_+>U=vM9{o6abZEwYHVNKA!6;9k z;6Mu7j3?*^7orBWaR3iy@ylEM@>vPGh4Eks(d1+-6OpwV;gKHo@c~!T9%0sx7gf zm;Oz<4{bt=$fRH^qK+R&<&xDY3}qpP2h+leSHo)~%i_OZ%)`_%_kzkbWokEUX0!3Z z?x|qex|lX+IbMG3PE;)(fFD177ek(&2sFD}Vde--vCOX|+q;2-l!H>LkQw3FgLoFI zPz!IZS&y*~_do&Gp)~fHN!&vo&XrC%EM1u8VCLOu-z*Q-CvR?>60@5EWAhqiaB}}< zjPBD?x%r8-Nuz|zl2j;Bb0_BFi31q_G`Bc(dkoEMlMapGBOD&xvjNliwZitd4@9G? zrIinp;p$`obR7CN#t(b~GdefLpl&Ud7BHRlB_<(_H)j+;r~4m6-%-zCSnsx6l@%>S z8uzJA;}fVASq|Cz4x+H!t833pStSsQgKwk=$2NYM=Pd4LohLs!;(ANphLZi ziia#J4R-H6fXF&^xsTZ>52yOcN68jwO$_5!9??vbp~hDg{l3Kr)x)P z=YkfABNFjt&Z<*6!wlh-G?JMsHIiqUrHiV0(O_&(bdZ3&A0{YjBs~?(XhRaCe8`?(Xie(ZI&tEm&~fxVvuP<4iy7o)RAOBjaCvd4KA^XT{NCdVdcg5FsEh2nq8 z^mRR{@qsS``ejurqvn5N2i0hzdneD(*E`mX{P~4SR|eQqa4>i zHbg>635|-{iLZk66&BVjqe)K${fk;!#0^6A*iqmDEK@LgPlEXQ(n~5GPz^V>D?80} z(*d7bE2XbM_zl>JKK_=)zknTV@(jnDsRj3~*baE8m^N*~lt-~C$sJt!&xkMAF3$CS z-kOvQ?_&8n_qO#vg4nd5fFL93MA_w`dQqf;j=Rho8fm}8PD@(| zp!4@fc59DgYyz*;x1ml@3hMkbMUvVBOjr+DE?fJAg{C?Sc$Rrgso;Ekeky)X`K9hF z3{rv7=O29BzH#cc98_|<6;T|O??J?(+jG`;PBUH zU3$-qwj}4I#*{;fIZLV9jP0CJ>DId`2|~^h=CdTh$U_je5J@aCVPsbbLON(!@u>*K z3vrh=#8N}NI#*;zZZ#uCpG9$cq9yP$HQl}5Rf0NnA<+qTafmPcT)0o`Og?|Pz&Y;l=^uC}dZ|4DFYe|Hj1dN&&RB{ZO>3xR zVs6>*Yl(+#v*0&6n!dHix;ht`Uc?4xCqEfh>VG1pnPUfXocjo3L{^M_rq>~fs9*rKK z`wLUpHg{gHGj=?^q6Axrzz~ZvA@wuG)D-`c$$J=goLFOoGggXdm! zp-xXEwe^p}Vcui|vg^=tU8~W0h_n<>Gf|H|;=s(7|34qHl0Rx}yvW&cgGXSt%GhdD zhd+@0@`&PFI>*E&^X>(UC7Ld-K&h(oz8prSGj>n5O6V~-t&qH$Q$kZWJJ#w$tlUUU zj|dlp)e`^91u#%8sJU%CW>T@@#I@;pKm<=A;T7T79#*9}7?Q$&{NakT<*R>0H6%8Zv?eYqK&;8Ft%=hwAYQ{oX2s9QL`?@{#@J8q>eR`mX`XYg(* z?E7`UG9PCV!)Cq@qJ!TRYLUlV*vC!Ym7+P*$mphB{rkwwY|RW^#I(SdEz?sJJpeby zS-b>DM!@nEHz*Kc3Di9;4{0DqY!EMk89Ua0vT^vQi09SDe2bM1m6(t7pW;n$WcdwK zfr7TeQQPBf^hexq7n5(;O0|2T#{}M}T<5RWeBw9@%E^KGy6)JyPJ73fr}73`Fo)hc zD>CjHcCpr*f>zflz0Lx4)tsCx*RWmoKC{&(E#IimQ8KXnc~SE9N@&$QCg4MqT 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/3174] 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/3174] 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/3174] 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/3174] 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 z8M(}4ZnD&~o(W3IXH8``*T2Lt(YwWOjDF#C8QJayNj%xv*z@)r4pB3kxG`gbzj0s7 zu+&ecXD9Lq)bXdspW)}d7p9=^6=`cB&c2`ZjCD%YY?Rm9K&N`sl5vaOj?fb`PaZxE z5bs!p{d_;%D4)&1>*gP#02iK<#p>t*zA+-YFU>oeZYQ@&^M7mk3g3;4KAHK-W~6;2g?drtj@CsKj}gNS ztR95Sp)&>BN(Mz!l`!(YXJ+tuUtsr*$S9>1?wpUc0h90+7L1h9=`JI~<7h2kaiwK% zn6~z@$Xq=KiAaQ@3Atx!f_$hi$JjIs8rvqZYg^dLlukTe9z`BUT(4UE{s+#wWW3nC&rQ(zO1w%dm!W!={I%u=gEX>|5mL z66F%eb5X&w52D3;Alh3?!+ELt>pdUM!Bq-a+7Gi&{cMR8m_|D!8cx3kMjRVRFAwyi zDToL&>;_Z139lvyZkS!_&_c;;TVr}u(%nFjqw4LecAU_;D&VFvkv}Utmi{tAS4#aQ zmgF28U)@0$khHZvE(;cOOnt$^#2h-+2EGN$!D+M&&EBa8h@5B3{T0Va?i}^sd|K8L zwKNteMS`p{JN;hjMgFuvJ?3W6a5CS$3AR>a2KgvQ8xo~Gi*aEA9XdMkE(Od_)r?l#hgS1|O2tOVJYh32+VrrE)coy|hSa;k(UWN3 zP$hsA1{DoDs+^fm)OxwRgq&Al!FcKNKM#ewOkSHEFBW&FbHpP!kMEjPreO5o1o_&+ z?lFnE(TOAX%iENa_<7RjjW@G}`t{i(NZPXaoA2a?tpf*y>)=dlKt4XJ7D;;t}_m@coKWc+YJ3 zXx>q6HiyaUv>#X_28J{WQ#6+6n^L(m?idP_Lffy@3IBmOzwkC4ZAf{Y7GaQ1Du%&f zJn4fZlkB-=Qp1j>YC;f*tit~{^;_b8S$ zt;C8@??IvK29>i<2TjOV8#AZMtQ@{SjM{{a^)$#Z!?x@ZsMdSIla_L-yM8OpK+7S^E6ILB|ig| z!)TF+GeIz9?(MngDLS)nKN9Ysorq&Pk2S{|mb zHkIOrxcy%LQoJQriy6o54xZR*RzVfUb$~*qT*y#~tmM^hL|+DTxX(*trF3Q&A{h{z zJPs$qLItZ6T{IzT*_IZW+0C7^vSHt9Y>8a{Bek&+YVK}deeHb5#i>dBx8U7BG}i!i z$F8Inh9L%4tI|O9FG^0|dsLPXYa2*#WY`|7$J&jsO5+3ck1 z-I9&vV-(~SMH-Q=;qkndXmLwx0mhqm^I2fjA8I_!$n5+?w$QKx`EYEH!fL8Q37pJ& zddqqms6O~VTWH>xT)$4FxYUv8w<9T%@@SE(_>;kb;ySK|adxhZR(}c17 zb3)``veM@!X2#O9n>nBXmpe*Bo^iw;iJ;v>ZGOD02npVXUE$6RAEcY8DxH?o^rH;aXikZZI1fg)-a;!7ssdp& zIw9|U4wg7;dDH6?M1^^n(~T?{)5kg(@OQ&Ve>J}L;&3#&I^QL3%Au`HK5H(0w2p(P z#^2h*tKFsP^|1F3oC;Y6?PKQ+r~=)+oiVM`bM!bphQ^e*uO3&MtM#2#4022+5oHfJ z8K`|Z#6i}}K6z>pQdrGSi*CD51Ll$V=dmW%(}W&ckX}>$xoV}QNVAwStM$C1neBa{ zd$du3lyjurebTG6j>WF}t_b%BzK^7(%K~9(r*&2s%1E+D=bQ|_3)jBHOI(#%h%=Ju zcJVqeUF<>93PhmLku}H3u63<`3F42Ma$_ZKMAncLopY_AeW^e8=qeI^i4X-O<_|BXE%@ChOZqw&>vGD@v4?n+ ztsaE|6joBcQ1P@rJ_>{Ci5v(&pkp{ZS^@}H^?BNisV~}|DR8q1|#1da-xxFGvcSJ*RJgACBpoF7Jc+ALqmRp4V*i6S!e)%QTiO zRqxr6s}=ZcF>t^5g?03f_a6XW%p;gS_Q$yXEgVu8&5i(&EKin&Rl}-aY}Pg{L;H5J zJAaB&_Ru+0qcsH(_g+_Z^eq#=E)M4tS2%rc7_XBH1Iim2aSU+9^e^%u?D_d5klrFF zMrSRP+ED8XC(o)s)B|VX#o3R8j@qRE3df)8ATRr@Ec&*A{`-13Ny788_|>z36G4?K zX0YhIxBoub8Mcs4gO;@O#Uuo=*f0`9b+rVtDW|TwBbj9@YV*+GtSyGHKOF|jR%t8%q zdcrTXogpAYgW*U3O@R%c3zw##DqDwoczV58C}((+Bvv%S7Eca58Cx#I;Ug&@5Sh%C z5OW1%lp;v=MQ&qgjsN=ejFt~qyC(*cQYXycSjM2kiQfanHh61a3nG%uw=gEYt!DQJiBxD z&d9a0Q8$}p__8GR5GH{ho%&uy1cuXfwW~?wD$oZx}W-^DSuC# zh4Quf=SMOQyRH&P-miTs($s9-KdI?5nk$gFVG}bzcagTxo>fQ9tdHu_Z2W*#{rQf$ zJGV}7Ue-lwSjXn^VLISxA`P0o8sjxp%n@B;*J)qtTsQ5jm(^G!p*W*Z+4nQbPWMJo zv2Mx3D99@Q7G^-om6sv6JGt_>XOD+z))B0kf@DW~S>47y&GVcNebXy(!`j4m zV$ugk6+;{iP?BP^Z`Zl&E!;7N!pTIwo~Bt{^;w_W0YHS3(z_Ip`37)K%4f}KwiEv_f7!-=ZUz4>ST3&MqCX;AL9{%dtY}JjWM=9^XCqX9 zV{?+tm1ELB02)~{SpZ>aa@Vb);}h0YSQXB|;1c!OVCiPvF^Mf+ZJIK@%h5LUnTPlv zJkZP!RlIDjNs?nt+W20C$xTvk^QcO0Ys*QFrP^JLLDjISH|4a_M8IUyJLFCwRw<0i$_InIN8PC z!1s!~q1jNF+`O{FEp^|pMa#+*+u*WIrjmgZAZ;8&Ok>Bh6TEDI2itl(97FCq`+=d< zUV68JZvS{7?rjHf-<-S#r;sV&!1H3<;5GYs);=qaPk-ZV-*}*(zz{@sJ$Vpc!sN<^ zOzXhWZ_Y_5achoX5&$e?a&qJS4bu)kk-AN{M^4BpkY#c0a_Ik=_Wo|@=+0H=MIYRp zy*vc$#s>`7ap$@BsBjVrw3hSo0E{<6$EK!okQ=hM*!4Z^v+_PW08O$ZQokcQ8{lBh z2{#~glDHP1nTJHiHhGa%_SE4rL+7_ML10*3m~ZaADj&Y&|9SV{*~`B_r$2NoGgmIq z)bo;@;w!Z`Poul*V@k_uNS&yoD>it>)kVKQo$pZpCV-L?>%4~_qRQS-pAitfO)G6( zIKF6aKY9>m(;}O(j#tl}WAk^?-@Jo+omjyzVt=k7W1em8BkmY~Ws-Zl^8E>V-*D-x zi$06#vGvjp`@_wGJKQPYY~#6OI2m~0c*8i%&Ofl|r$xBQ9+L?;n9+Yhn<3DcpSK4n z=Egl&9-jg~dmO++d{E!ELeV)mZ&s9VzKW)KYua+kd;y-^8Dt!uOphZ|l$Y$c^k~Xn z*|1$Qb|q-aUml9cU)geedwo9vXXN9-$HSaKfsW%wrc z#DpAEZMN+e2^@#Mt~;7xC1NHJS5uUmd!ItXyQo^eM( z_35Np-Hfd2m$pK{;osc4$OvB$zMw+{NI7EiumH!f+FJ^0EtH=Zi*L3Sbgdzd9ZcbCn0rCr(y<9AK(00nBf6I zs(N|^<0&-7-M{we$@k(y29x1JeA!Qz8%$4%yu3cjar%Tq!XOQ9n6MvY`O(PSE-&Xi zq={U;WQY`Uc}ibQ+cb3{wI|lsKWk2wF0~a^RcvYNQGM%ZoBjRC)=jl8_9$hfLkNJoFrI%5m`2Y zG6{*G4VO4pisd}{v~Q8#!hk-jY z`Je|8ePQ_1@i?`mjv)R49rNMtRpKk!W%C|t849F9O?YSIXV{<}$Zm9{FSD0`1e~_# zTmRB~_?M0SCUvY83ASXQPv(SJimFvgZLu@X;p|SU`{kcI1ARk-Em{*cUQkrx3ZNc@Ek3L#JsCeTLP?8Swvp+X0C9Sp10@#yf*(#X|} zQvV^>1mg zgR(tVG8V+Y%LfmnGc3TFNB74^}nkmO%Mgq z=C8>~$thvS@rGz2(Eaxr2!TCVUtXyUr)+Zs{B*j;JwW@aS%14VS$WbnM0)>2w(Ep? zKmUhrvG=$hqp7H>ZXX|qy7~_lp7#Yf$wA#+Sb=|EJ~@C)sD?db6fQ4JH3aD}IhVNRae>>@ehM!T+V`or?HH z0o;r!HM#ytV)P%9@b!zVxl46Ihr>68{Nmg0XuH#bT>Si+ARp9H07&S$4)9Im;DZ@r$%b2yf&%JrCSS5r zrPPQaRn(Y-3xiSb2{}Dc{D19b`!ZT6?#1=s*P`crvTUqS*pC@3i9 zPt}G!Jr$>uCaI^fP*XbCs5swvNvvKy3K*Z$YRpwSAoi z_d1aB&$l->B94w%ZnFtdy_EgcI5rS))x+`$du(j$US5#O z?~rf*uBY%=)yM^N&ffCnsp*!<@=$I-89FR~kDHYhy}P^nGxvaI7N2B>pnY-+S$Ngn z_gP~0cHejE+yF6O8iD7gnEz|VpB?a}W4r1xDe|urq{eK^N$GgCuoU!KHKy3q*Sp1G zxBYXSIc&VF@E)HRfT!N^t02Y4b8626wp|%)y-u|k|IOvjabSHtvs;1`xS?ghb z?z>^`2Y7DglOi+L;xo0~N>H7fSu!r>g#G{TS&nZgqu0`SvqGQQj;b*lJ5*# z?L!uI%qiUh?C@e?pkUIQv^^}wA_sUf1L4uMq&Wrzs!uNIdyrD z6ml8Hj6#{4ivGH@vojIH53i}*FVgB(qfmNj?Z+8_SEMHvt?!G3^2$1mNAf-le$Qg7YpMw?{ud+!Wz!`nz=zy^Mv~z z6pp$!KOgeU- z`zp3C)}=s2N0)reb@SaxJ(Cyx$EK7nnB0MgC@-qa6NfElVmcz>R+2t~U$eH9tbA$q;N-?nRUDa#NfnWX zWP<&qZeDl=a2CYgfj#{0-xEBhY+o}aPxL_j5N=Hnp22HJyR5H6RT)&Wt92Dr!rmZP zN!bLPXMn-R9u-<@lhQur$1w(__z{M;fkEE%j@zzpdzr&c(c)Kse+-2&Q3(m2+w#ln zR5&rphx7F)1Sgt^8V!UYgixhl^1{|t>)a=WfQ*~b=@KEj{r%GM)H5Zn6fwfeQJ)rq zgxzi>!?M&N*S*^^T00^{j95P%?=Uo4ajgZ9Iv#2q4u-w<_R~j#XSVBtx6l3>J3Yqu zD@Iqx6%d=RN1VzTtOL8`mE^HM43W%3K78@8^m7-w%z8kUxxSPZI2s~zax!HbqDaH& z@isFx>0#fA`|PCZVP{r+YG;4#(A;sr*(z`%acf#?L2{)i`Caofz?MKIPZ>16=#mf4 zf|i10RAe$Nq0Aj<{-Jtx4Q2<{`M9tFP$FIk1$yxnkt9}>;K|87UPcYhRs$fv7^7C` z)*%J?Rdy8@fL2N1b-N}|0YZ>e~-|;Y$v`ai&px>7Q!IjE2eoZrtJgt;t$Y?9{>63oo|FBeIV-PcQVqcwo&=mUbtJO|-yldeSy^-=u3;9JC- zh3U>EsQ9Obw4%a|EDy~>ckA&Sx*IJDO@#IB|~O z)7YQOR*HfQBJM)eo!WtjPt?mQO>1qEiYbgJHBYLUjr-zfRSV?Iv4m9j2T!PZYAaGW z;Z4a?y^-BKzwop0Cf4ViNT14kr1Hdw^o+&EU-J-7*{{c zr;4wv?05U?4zv$<%=b444JG`Y>pFNGE_OF9ITtxF-rH_{ioF`=noyp~$+k5d7YXwd zy-c?`OBgM<$a7XA9wyePaHj0*Lfd-Y!=Nd^^}e%;S7!@oh23G$%qNejM+@~|6_!Z_ zIPBpKJT3o$5I1lxEH|Kl(=lNZC!_h1+W!NJEt`@l`Pl5(%qqK=bYePheCtmEZ2YiF zi>1PHp(;WujqE&lgfr1HWxHrsS&9YvpGZ0#30({F7)S2)=z!f4woqJcT7P$Q=v~GU z>ThJ6ek>Wn0}+=(BXOx=F^bZL%_ah0Ho1s?qt^1Shf+SiV+(fi;`IrT?%^6LpiLF` ziEb%cny-0ohx$h&i-3-d@Q?BSlLWo?hD!j}aSX%;3!^M%koAgEJ)H_f)?pwD;&LCfs7;1Ze$I4 zNG44p7H<(1uQxKCVLkSM>Eo`^>1EJZPvJ(WR0eaKP9Nj8`1E;d!ecsTrHZj=Ca*uz zC4HePCnO1r;q7;8D-*l~hUm_f(f)YO0lD*6eYPHpIPsmkeOI+Q?QdT;SpeY0oc(V> z3vh4cr%?bVuaRb721t7($aQ!?)^ECtJ6lt4cdStSEu|PwKNj~ps~8F5PS}u^fs@}3 zpGey}9TkJO0kIGyAHpBWc|&7vP0F`v-A7A@8f>)qVHk|jyx$tRbW zPD5zv{q$rsHE=r}nRk!KhcOj7qSjvS|h83%cjp^0M-hMiqJm#0ng&p9KA7 zkgG8zS~c1)tQ-8ZjrLGAd7Pif;WuJ$R0qBf>fOh>zM~EwlZRJD)4lDrKZlj^vqqK# ztznKkg4u>uH`D##N>ygR12(nGXL9Q_#F2L59u*Or^bU!g#d6|62e5GG`!IgS^DV}t z{$E0N+B*pyFvS>}f!8g%Yg;K1OJq7)%O@2`cY^2|tr>*`H1};r*+!~`y&z+8EaPhq zVLQHjS=C2NbE&VL8%Jx&yPSu#?oB?LA66ZkZOn=n`NJ;NR-xhTuH{-`F+97=`Io!W zZSR*+EH>L!>9(mAPbD}2H13*ndu$oeoo(Gi__p0JU#sH-Y(S#8C&nfkQ|@4^p>J5_ z{NeWwAzZa;r6hZcdjB<&_0>y8KF2L)H74xBo08LD{`eRs2F;Gs8p~CgGnT3_{uo?* zt8|G8PLuZN@&T@)uuhsdH!~2QE7Bz0-SMgm7I;s;pIO)i&Undffjpyz*1q%V>L`@o&cnp$jWaE z;G44ux;EDVAxqqTn8W5V*DVRn zp@bwDumG#*Ea@X76V>27{6qfc`&&g#&=?NY+5iN%fY#EpK24Pdum?VH9ZFM|jDxcg zoRJciFkam(qYjAYz4SwL$$KJ}09(M~sWU{!EQnPMHYTBBVThgQI*m$N%HTZ+s*=vd zMs%?8^av3X@IUcB0P-TgQZY3;Jr}!!G%UBuXy8MkjJ6I^wHogUbQb7>pXYlduCe@> zOC(`(c2(Y)dKiZ)WihCQ`<4X}YweFCB;2Y<6HX#?Pt#3SE+#B>ipe$JS|HO^fjz9> zaqM_DqsrW>m5e~;e5Ny|&viXU198D;VwLI?v478b3f-F8`wP(U;?Fi>Y7yK?Ph9EQ zGX*MEDj0ZLZQuhAR3Cip^={A~MxF{4BlDid3gfIoZE? zP%oNLYRo(n(X9FRvtIhfT_AUcgu^@tRpe8}ov%c|IrPL<&L4aagI{r0w<)qq_xIdQ zOsr60iRiDCmz|gz?8Y!}ed8cD{dj~cYB?9_!KU2JeDwyM_1Qgb=XzXS?BSld2PPEl z&vtBm=eu1nr3QJRD)Ko}`EQ&CV%45*w@rVmKl&YiJ&jI=>f?!D7XN`oNaTfWMl=6j zZ-s06YP?+Uqg?1oQWCZiRHsR(&h`c|pj0EpzQCM%nAvsO-~nRGiExM|HuOg;MesJh zIhdjywA=70P_C6)C3BJtU&PSU+<9udm8p;8^^ggzTxiLbKQI6y1N0V0u z>d*ZEgJC|L3LXG0zUeaT7z~$K6O)@F{_OgMy3^Fq{cNc96W=cWjQ_f=7L{eA;h8RicZ-e5O-^Cp1;&Bw=;oaZ{ACeNQ?4z^y zCVYP>tRtEt9>FVGjl@v7vv#9RM>sH2=-%}l6+VwiwTCcKcE{GGoelj7HwwZSnxMbjsNFnmZHA@lH0?xdxI6gk(0z)F4(*_0A{K_CWGK=$Z zyT(}=z@Oql9;##LL^WcA%h~9`J?Gts{01|#45eAQjI;_Zc;HG%@P5ycnG>E~5ht0C z7wbIKzq0xB71MF&6aCC}PS-gNXM6l;Ao25>`Pg6n+1ZG}D_IKQl?J=AYd=x8vSrI@ zT72FgOcn!pJp1xhRH>_?7+HnRh2w<>(0MSNOcqmC+17-v?A6eve^18Et?d`3Gfn47 zOCiS-M-VB(*BTUx%^06{HvfB5>sT(4(U#ZG(n{lL=LB4T_mtv^nqiyCGh&z!9&*a$=>sg$q9q zI-P{>W#klxqk8{Aw%u&}5=+w=v-iu_O{x8uc;SA@siRwwp&D@uhaJPgWOnebp0%w;2R%z=LyUkMfuu=vMX;sVl8~~a`9Tl@hG;y| zl;g=DHzXw1&{f`)67w?hE0baG!Fh-B2g`3HzA<7KYpOh=RkWtoukvg6CH4C7*=bC} z>1Tt*UHw=4vZAT(suAJgFuPZPMI67Se`-qmou8V}ua-x8k&97I#=+D*gZ*1j zL>&Z$SvgnoNJ-f8Xz+16<>&EuvDRAueVmlF{&JJoZ+bG9`*w=cWy^bqnEDa1FQtRB z$mWtn%fk~ls_hG1ZpPh7$|%cUliQQah8!nFVnG5x&63@18kzAZq%HUz!S`j-V_6$E zhyC4G&kN28(beL~1eaGTgj$?&Ib8ChhscHV%e=rV=Zg|Cu%-lMY5h?#rsud0Ha!Dc{YdpO8gHsFlrbW|3 z-kUh=s^ed;O}k#-ae-K6~zif z!)CxXY!Im_%ASo}e-wgqVzQ=C#yScbUSNXImc*QnqIyl^jf}ct%L^U>w{r+cm{6pj z6op{BdX9a~EqAc%@t^T3o1K{!RBU|d#UI!G0wL8-ZiDN&BC$99wgi)mA*~MooKnlw z`eypY2z%ovWV_*ns#V`0z?$=i^rv3NX2#v6mxi`+B@KDR`$+Wnld0#$raZk=>HU5y zuc<+Vf`U5PaCLJl-)qO%ntVrTI%E)r<6L+NA2gZU*EBgR$Xk!JiCLMOkeAN(sp z_J;`7QARJoS>o9}^QFpJoh_Eo+Dn|h9gz=)sq30k4tRZe#Al0k@w#yjTT0&0tP-bg z{jM{cDNk_=MT&k5(I)7;Ma@wR{}zi+nqG?m(FB=^CX z;>_U)`lB)EK^%t)Vv>+a`QaGWSZC1YPDcwAW9<4RwOD1X=d`GJR6MoY|KWs^4o?f?x%Sp$Vt>n7&T1qMHhTf?t=8!9$5jp86)a3*j4<|YzmH+>eEd7s zyFKQznEF3IoFRf?)S>rsuCBAFq&{v(F5aAoD<@N< z{LK1*;@8&_PIbEqi#bxJ*GIq*(7w3Rg($AATGPb$k{qch?576b#Gs6v(?h)HPUOhd zwyHyg1!x5Q!}FM7-3LUW*R?&NrWx7x;e)$m;DRhRzsg4V8b8vc`W|~7+;Q#4vD$s? zE(35+ip?^q(QiV`t1M>rze5q%Ii>DOpXXX|W?B=jGd|os{hY2K)uB>I0y96JB|Y6< ze5k8-%jU*eLfnob@g3UWieVnMvl)~67(BNNEtsw6LPt02VTpa)AcO;jar|~taW;5S z^SfX1y5EdB&mm_0wzYwvR?enxucU{6u=t+RX>fj6p*eFh4#zO1k!9>i=sQ9U-yQ#& z+4T8lShrf*?}pC|-Sf6#hjNN(@Qw{F$49*1v9#T#*c}|;2rFXBvpqc4YO1#7D*oh*eAatc$plKS)2y7= zU+?l|KIxor8ck<=hP#2pxY$tkpF85|qdlG6V-o}d_E?3|HLs13x$M5ws9{15h_pNfn zgUWtfdeU`s4>S!GIha^jRgu6u%|;!d&y;oNN1q;I=aDz!WnP5Y)?|MSvH-|4D+DQ# zuTf>;e)&TDhBnzvP*5-&?@v5lplZBO^`JUlJD3{}7cqAw`@Mpr3YyA>lX_3-j)0%* zl!0k&%VG&L3$O(Zo-oS`6m9WRp=D{F=4WCF_D!3r(y&f8Fwvfy(`kV z)ceom6iFdAo^nd3UHv%t6Jcnv^6kcG)8*OoL9l#dTQ#K5eY@ijq= z$RCB&ObilVOM@A6GFdw6XKR0{M0tN$b}u(nR8gCD^5u>567+O^FgX@Na(gU6FR0XU zk}!rPEjp*DxzH%_z}fpYiWZLVSH^iJ)zL22i$P0Jn!DvRMCVoG;Pcj5yEpz;V`7dq zV$3dgMkZ9#2p*0VT_P_V!M&-!UfLNgyyfQgDBrB5yZ7;m5>i9!2D>6rz>ti8gsyuL zAIn+^N&n!rFb06sVPhG>Jm$;s|qT_A}K zuKm+mwNwmZ!OvnHHlype@pDhh@ebf+8bX813N}Ig2eM(nJ8ie28#|+5E7N*~jh>?? zm3jALQPkmZHKQ72dvl7n(b;!1_e<%n^|Lnu0)xDu@O(en=hvlbzDi>$Y&8sGu@4u( zpkb0^(MQIu)5R5H&AT<_Mb9fE{ripC35h{;iBngE6S@IykcPh;ivx9WMbV{LGt+&Pct(VwE&hP$_BAh>Z|+U=SnUQ$ImT>EnQzreTb;%!lAE z^klew4Zc6puJnwf1(;4oOyh>>LH*0A7E(drj z4`fhK!&fC)mK%yiZ~LBOWY7C^Y-u@O7J~E^I`|)^tN1v)$2xNP{s@1W-r!jerw3b! zQ=N*u2o17x0^f8scgLs#@=|{gEY*CVK?{ zoqTtH(1E*(@jErb{7SlMl0od47KYFNa4=+r0j>+nI~B5)+P`%hET*VkhPN^-aEXU? z9iTq^i{KxIQvl3cG9+2~okd{zr0S~gw9XlA10mnyb-W9w)(X`; zU9j@q&ta6fod!lrxR$d4AuoF#$o)TFcsjv#f`y!mhb)h_{jwka1OYR&1FZ3zv8!*V zSG~l>O(0noFg^+s?ySM6BR$nT~mlE zk)XuADx4#S>V?1lsJDPoQ|@^^eP&I_Ob{32In|BKXpl&~II8H#N3*Zt+G<0>vE9(yY)9R+f1lCeFOFvIs2fI= zuH7b#^J~;~U2{ZUY(zXzH0<99nii!)(`WX;mSR#|!9_|8FY}^qu;UZ)DGPB_WF~Pa z?|i1I8p^snlvQxt9DOhNm4lAzAm$VRS>?SmH$kQ3uma;J88>v)*K~D%lRFA>)>P+r z^K8@W@;X=PAS3t3*;XmeerH1|{JG4uvO|MuuyU4;QyoO6+ZJkY!349*Qo{F+z5dP&^Q>(M zs)8d+?C^+(KiR>JGw6CXwyeV_DIF}D$ta~}OqWlQkoo(hxZfqG)QFTu>J&jtrI>`? z@;y^{Emk|9)Gu|+Lwoa!?@JGEhU@7D@HlI$SF_=ouo1 z7^nl{d#qpK6J0@z!L*rPmp3K)Z+-)wAJ9Gfe?2DGs_p?Nyv+*#rrnphkDd$iMeKU= z0E))-m;#rLkm>XI@vU+SHr;R4uPg+3sl-gC(l1%pNie5#{c>%m_f8o5cUAwC`|y-? z-r#zF!wD)`MyXl5Vz(_MoUKzNc9lZu$Btj-y$G~8A^`Yzlj z9I4|}RZH7<@fAu+L1Cy?v*i0I<4{VZ7XNE`NS?(`{G*&iv%aE_s=dJb-SPzRqDmUJ zKHeGi%eRc@9r`_tv`PqBVzmJ{2}Qu(hR?`7-S;@(t2YWtIx7Df_Dk zKLJhg(x7v4f@o~#L5o`7Gl!&YbZSR182T+@XR!c!*wm&6O<^?s$VT}toL^ROu$E3h zjM7cY!)_%kY*}q^|CX<``Tt|<9m6wOw)f$gBoj=WOl;e>t%+^hwr$(CZQFigO>FC* zea>&6v(J0IU%RjFTI%Ymb=SHVh0VcJu0~e5(2u<&tS6=XITQ-9WPdT>v%WLpWb@qsAV3v9yB!XKnX===fI9LXQ96-re10f%0pHPT%0Q;6V#Yvw`8 zEe1Ud9N!qM*lrgCp;Wo4bzTw)rJUn!m}tFH587H4n3jB>P#S?yoCWZkOy8vw;(JH} z!1VXZz8cjwq}o764P%{o2wBH=l7oJF{``nTju^h|!mihHLp6@X3LQm(64r^p6c(z> zqy@R;eEi1G_M()GqQKCfG>FM0Af{8Pebwg@|<6{4bJU;Yr0*rK2vTFWEP+z zZ%kM6g%euQMVF5WXbOHSBb}u#>`FzY5w9}*R$Vl85*HYru;F?H#h(*RQaGOHPO{>L z|JZ}f>F_9|Qo{qfyupR$-S*1tARUq8knTk)G_}?Kqk1~cpWG^>{VHyp^g2Y4F1cG= zA|eV9IqpQi`WuxFsrS}I*hB4IR1@?(tpE6z#Xv&wOG@oRSg`8y&2+j%0N%7-4;*62WC*j1nCYprF-F1mdF2GY7wtz9zh? zTE+#6-lbq&9fJW65Q2Esg@z&=)Aju>8TI1Bs2whe&IOVB)ulIA z)a`I|zLp)(E+PWmv$J#AxARhILV>wuq=c8g^LGka4ts5SfWiDxBan?M;@!s!X zw%(ZW!nTljr5Kzjms0ML zavoLKvWXO|jG~F-*F-T*G}k7(Wo5rV8wfx$5S86&te8Do)gr~}2Bz-xTO`27__Bfh z&MHI{Xs7FrBwZib&!*_XrECnj+ccbDjkq0n?xo*be2XXWd*d9^ggsp2@Pv%Eea{+~ zt2HO{&GO*U&iwn%{8efV$Pn6~^0Q)L!^n`Xw{dZE6`~}?k9e{w$>T1mL z!ML0(^jHD%8E3u;R_}}Uhlkd*`bNeP6CuMHX!F-^5|?@F2e7+dc*C3@5|T$*owT8X zj>B=$HP7?VE{D&htmZbL>_xI_!ngf#Y%WLrR;2_)C^Fn{Bo%BKK7;DXdDfK4 zvWaE9xJ}k7L1kQqPbP?0(e2a1AS|AWS0=SSC4x|BcG#OKuTVwZbkNiZZAMmk7soe> z5nNDM97OgvI{5B?MVcaaVq&=sN%bx_)_6YD&`c_vNBSPlv=G4V!T9Xt0mTB8 z1qJxoSYC7p?$Lt62^8FK`$8Z+Lo3)z0f$3Ft&D0kIahDvuDl{zi-TAnSu*&&(DH4Lx>) zh@OPcuD)m&8^i++8r_W|EYWkiZ^oIPU(L?nJOrPbv)N_Qj6xwxUt-n@G483Mkzo3> z`g(u@?@>J}yX9 z-lbfNkSgEunaR_d6MlJ5Oqp)uoH{Fjf8%`xp=w`;qT_Hjb*4gh3}PW zucAMk70vMTrrNvS9}t#AEA0Ee@SM$XEA^1AXhu(%-Vbnn5g*3xFKv?ZtMT=`8j!%* zWmuZ;fZgipUa}Sru6n04n{c`4eS+5W^Hl6u`VbMi*cTyIR3gwdXr!kvW$=0hD+{q$ z4Ry1kq%1D$IpXXk3eYc6Gcdrdj}&tmcB!yEagXdNvN1&FCnr_wuTu5+vwJw@Wlb4kGR z$;)6B`Q;%jC|mZLS7Y-hON(iwsR#NW?6kbE@g-c?l4T9!V{yk-JDrbDt+|Pl>+O~z zzCL?&yp5fjASi=lV}BTYqH~7pFXmBJk_wriQSvz?T_ExwnQk8O`4EP zpJ-FRoL!LGEeDvr^nSDmF|=LC>4mw5nQQu)!k@2tOVTARbr zswy9co|QL3B#gQIo3q>%-czx0TrRv(B?rA{agrFEwO?!s?QUQo@*LEdKWs>ig0&RW zLfLR`CAS26?4H%z1|s@ewBD6}bv&SO(w!nfWiz75aJg`Nrgd<>PVvO@9amt65(P|H z1n>5nup31(2bz`{_D`V?S?S-O-EGoE?A6cn7Wd3i56fQ`{6?J}wPJKK$-pD@is+R% z2^EYKF%4af!}76iy5Lh&_;yc5)|*>Zf$2?xI9>y%ZPisVXmXpU*kF8P0svwgE zT})xE^LvG^WvBJsh)d-Tx~U*V7S+y#`awL;$scMpC3}RlO?OiENA!TV4opmL7at6+ z#~zxk7`5CQnJZ@cbYdu_44@Z5$_9u?6iMwM5;7kR+n)0L}V{cH~?$%_3!Uh}DW%Q47ud+KcsWpJ)0hC_i9> ze{xsUjW-!M}Lq`j2A{-@>yuqW6o=312y-E z0_-PS5UWUz^YQ65F4Vfj8KH$=sS zWJsJ~{R$LQ-k8YToE_P0#^QLu7B22G-l^O4gdZm|Q?&{eKM5Oc9z+<^E>JiQ7B0UdZ?qMa%hbFC4DK~Q0s>LRK?R2uV^N*GH9XGG zHKe193Ir91HR$%=FlHK;;zd?afzurt=88iVn(FG(3LJhdRjPz!zSgz8u49PldX;dT znt5D5w}MAX1*l_9Q`|%KL_TtbP5~3&#JBR~r3Eb0kOB#aLzyYV=hMJ(*t)EoBMRcpRu193l11(?GokM;6p^%Ru7p zl-S=7?{{+sY8h)s)}f0>k*3}}!16^G{4V??kHb_QgN-=%OXgk;4DZ$yJn*uz*z1V{ z6ru=2?;ZbKoUpEpG#((<`RJ%dE#{EZdymwgRx!c@-wtZ$z)p`oH59;D&!oIgm7|R1 zb+?a`mst$cMcMSJG;g~WKra8H+Sxwb^{w&*(-+OQT9Dlf2m%i;3*C0L(1)Td;whzx z6)tgOppv;N(=*aI9~@Dh8L*j97VfGm+GI15U2F5m;0IMEBC)fKg9*!gu40~%frC)} zrB6z=Ha2OqKKmM0zcZ{KYV>=q%V2}pWdOR5=b{tnlKT|}aGiW)dnz!!eGPUY*v%(E z>mlk5upa~oDq0J958)(WDZWYmCaPcSn#*&~OR$w02y5&Wma<+g;E+>0hSy4QWb2mg z#fc$6tQGz7?vA@c0BZ`*nPh!n7I8exV70nA_zQC_SjYqHMdL1Ju6V+b2bcVtBya0@ zG+@+VQdW)Fva57-WSA;~y%zKr{nGw0b}|ztR^@eB)5N2oQ+N3D**RHC`#Pcwmj^6= zfBvHOvNYMsl>U2|i<*QxgPc;Y_>?^o0ZuI4Lh)Mw@ z;>&|0|9ePdy`{HyqFOzMfOeWJ{J94+x3Nb=|-(*6vq?4DqI(XC)U1TD!$W^BU@%+Lrm+#6@iagqiVS%U42EM?#khaj zTSD6sqf4Ig=gylx2xH>Gn-0GR5A7>RX;k}Vcxk!f7`;SY@Oy&Bp;*=1yeGuk z_hlrd7pvaju+b>xYA4@NYGx!(@kpja5HMzVVkP~wvRNY;qw$0yIh0It~Y?CV;k48i&=8Tf@H#B@GR zN-Ue152rlM3x&-*7O^?1c(+X0t$}~Wr1FjyFmA$O_fwFFLVYdHVN6dF-;A^I{Lvsr zDY5AV9>{W9ay{--)k6%sY}~o5#gM-c%GM4uMR2!U0P~a{W4&$qH6S3v zEk#z(vt>!6;c{Tua=Rsi7dEV%$kqiE{iT5JGR)bd%NVrtDu=j6Aq~X@vWMnO5-i6BD;&4i1P*=d&&+ORrlE&SsYt+hOHeX!^8_tf^SX z+$Z+8b@>xx`!&y#ETwwTkvYl_U&p2rZ+NBtGmXoIbp>O=v)d-vc8(0 z_1b7DaA07a1>r|4K^BMtsPgglK=xbcujaV+jzxFf^q&I8I9?-%eD`i8WS?TV|6(L{ZUeOH2bS3%0T6E5T=AXd9Vap zMXJJLML+eWL_MxlKlT{|-rf#5mM}_SEpiNA5cwtiBujlQreZq4uPY9+!-BgYZvqKt zN?ZZ~w|ijEL0+{hWO2g{Hzp+Qu}Dc3&1Oy=k3Ylewf9;V-}ly zg)a1O26DKC$<^YcbG4$s!>gSzqe8CA2E1sRTHh>Bj#6?vv{qZRrux9H>3wZ(Ug18K{&9 zXs7`_ju$z6BR6;XW07>ewmWr)sMyKz=SUzpt3STT#O@z?M)|5aw9;N+Lf1IN$2Kfy zR9lWdc=pOd^A!yQrjNjgH|-BxbLU+I7u=s-5D6k@kF=xMyq^$3iw9@&j7 zy)3D-IGK-~E{0@=L^$~`w!A+PmHo*Vmt$U_Fr!emT%ZMBofIuICGb$4uOnT;;wO$T zxx;0)@&)55B>8MLuK@C}xiV!Vg=B^JUZI(C&x#$yV!36}35;I75$Po7L&6=v`f;th zJH?xZ>ERp*t|MJ9H9p58C$T#~z|e~LwMn5yaQ&_8{a=lhZx(>GnNoi}J~cogWOuoI z4i>YbJq}_iOZ6ar0-{;A-f6g>aiU-Mu2mPUd|U3PqjxL5YZ8J-UR$9*7N02J$Jpd| z*_gTgYN}NCT?CvH$J?(u5FK#7mbKHGEtnKI)7CiYz7INx3gJ3l4uT*5;u|iEzZ70d zIJ#QthpmHV!6j^^xp4i1XQBD>L(A($mawo;-+@G2Azp5$Kc1mtC=$c&75cL0F+2O< zDtxHZ+Z}YisLPK8XV2C}W7hsQvL}CwRi=)vO#~^iWCcVvWq14q zS)5AOs`E(qN!lAr=KY-yyIz=oim1Mez`7@rMWdAP{-ZN!Z?!a9pPVQBeQ=_Ad+GOJ zzu;x(2u&TDdZZ#e|p)1b~%O zvLH)vWxn9x$%&KpHvQ=-T&VIM%~iEF;z*wUm7cA}Lc~5AIaU3p9%7dVDnJh@36|dg&7@B_c=Ko|!ESIX zPA#`H^mfxKyfEMr)mWy^UG5wbfA0?llNW%~bA2>Sv@bwnXVkLLsU~C~F@7Wl%I4}Z zOqvoaQ#W+o@SV;mbx{DrYhTa@000a*FGJy9j|d8d6pp74ltG)<+M`ZG} zlmTZYs>=tK^OGBO{J!0-;{sF#V}DSQgtnL4eXc$948JQ2QUFOO{yw_Ycm4p`sIq@#0IQeFbE zQ`9qXn5QgVWCkK~F#j2HnpION@2qzj=$zfeE@q0b_1?WFyo`JvUDnq%DxxS*1TX*C zFAojrYGMINtBzH%BcX|ZUS0yV?r^U2&?qr_k)4e_0msIxv?D&LW!6)TvnEW6q-k8d z2DwCfPLyow6>Za#HhMAgAm7b@OEFFVSP%P@%~OyTj`hmAQNIPKaZ97TNdYELueZ05 zG1dBuxz^KBQx4+GS5hD1oNu)NlHP~gR&9;r^lK0ysmApdl(PD%6CPiLz~d&|>B{q4 zr5$A*qFAEDl#T|6t2NAH!beVKgpX77B+pJGb%@n|zN*BbXK`V0QC6<-4xaVvD8DVWVTSj!r@b4NK|7Y=ADP#MruiM*zorYb{N?-D9s zV~ohakB5~rqx(LD^~i>nr<&I5N_gW{@76*)vbT=rD7Z4-VHNt<1aYZpL|F}If7IIl zNeN;K$X}n1^9qk@Bm=7~+}htO-eN1#jhvl5HzwmjY-kGBCigt9nYMdrpJSQ6 zG!A1a4u*=b=EUX~mpPVO<4EOuq=yz6R?px%3HB&M+H9=b8A{LDQX7ONt5WL9ca?EM zuZg>g2kCRDY4SBhs&0^`B7H&AyFMj%22VFD!jj1`>*3iuW9W6YYOAI;Bd^r&#H#Xu*y zYcvg%jQI&{p#C}~GHXkRQ3psLYKS*B-)r6s$8l|1Oa1C~#Aa_kxg{gLHPVu5P+!g@ zb=tW&e;n5(JCWp=6Ox@tt2S=|im_HSAr&*I#tGWG5V>vdu(o@|qvo`Y-tKiTREDGD(Ai=y*eDx?EW|5-x1e zywZpehoUk$aKkq89`S=8)WN>8qv*!K zU5oF67gF!ocoR$Rp%TTP<9pVbEg3)GWRzawoM*4;M+^UWG#X7ntk14xH+Y81Z>H;c zz470T&Ygi>HzQX!E&pS*0XP$34Jm#E1a!YFZZ6s1Dmfz+%9Y9tbtR$!nm zC=;Z!x6R)a_t-Wcj1i>l>xhn8v8(CC8t|K(cFE;5*tm%q2^BoAc3t)sKA8Tk#=k7a z3^W;1zSu4rb*Icw5%S0VOTE9Y&-{CQU-{6#jx5p}iWf>7f;z6D`_4o7?j?T9mNuMs zUHn_do>JlMk^x27zT!4FhnIhu=)dnE1{!iQyA}IN<$c}Ybr;(Hm31+zg*W>=_pir| z(Sg!hvP_w(#@DOhXUZ`vm7|A>94#9DimWe(%EOuDlH?xYCaK_>cGY1wj;3Mv&#w6ox zV{543;KYW8hO91EImGvEvj6g_F9Yg#j8RjDNjg`D8g~DkS)pa{w;OP9v3OX5g{38C zug;6)X`xqfS#ES$Rn^s#=B0IID@Uupqv41@=ZEckE5h8h+20ZJxB6Z`f!yquWcXx) z7s1~m!2cvhA8wm*rtRfs|DVhuK1nTEp^a7J6@Q!jUjfD_$Sa{C(=R@+y7ae^|MH6s zF@8?yX{yR;+r zGY$X8-NyKT`Qraq8pP%KnmLE0e?-mB=5&+o>UBR29jTYJ@vLK=lWBSctHO!Jk<_6PEvx z?n~pIX}`b1aRJ!kSL4M-1LpkZD=L$XfTceLb<3_B)Nw4(2{dm=C9S$Vu6fY2s$Chu ze`56CVa=Kk|3%D%UVzj{^z;x;6SH8ANzLt!tK@x4*Ol=~)mBJCFq0ozv$V9-H#nH+ z&99r7@el#3h@$nsVsGyge06wWLMW@Q77%iUM(FGNs?86ssrkL2a3QEEfW_64TU7=U z-u?blLdnw4S_NoGh7;Bl0^STUS=1aWQq&-^R@79ArzpMNrYKu`eUX%bZ`i}{U8GtI` zl;g-b>c4uTaDo0cd)^N~u<*TZN=vdf}Bn~A$COLUuALq2TX>+0tUR^*F3Fd6W z|84i@fzAty=R5r}J0^Dv&a==#F)eJjq?jZ5e?FThCj1$4TO^}W(%^IyAmBHo**jS9 zfM$fIxxvG*?G)6r)fP~mimi}A3NPMFby^?~&NEikrS5aehB8JB8lGpFiB~WGo!~NX zew}iOx~m5X8T|*p#hgexhCnAJKmAS?iheVaM-hUKsEZ+cL@5q6jj?Jj+0)J$Yjf7? z-9K6~^wfo8Y#kVo$d!VLCTffc`iJV(d%=-B;&6;t85-rL*dp=abV$`q5_i|6E#xL=6BZ9{*By<+)&jgk0#G`L;Z88mS~DkyZO$w`@xpv9e8L?Nx?;e z71t`4gTeQz7nRdebbmPh@d-*J163j_GyH%Vadhl!$fhIpKbbY(A7&7#5>BUZpWolc! zJkEP716o6r*QL4`Dq_lEwZ`Foaez1p+-q&=+1Tj376e7%R*ysrUX;F=J~{bGBO}w|-hy%Qa5FBT?-~h`*p3$67x{1l&>`vF)Y7_ga?WF) zjC9A=+Pu1Xkh3jeUPNtz_$+FftV4H=;oU6~Z4B#mu&%R(qS!n+Gh`BnacOby>F-a` zSS)w4tmb(I5iI1JF0*)GEVNSJH7=mB(u=S$A|Dg~{Ld=lYdVjEx9Ou*E7E}jdd;zj zm^Z_Hyn+;xG(h!uK*kSAub<-}UIFI7=vkbJ-t-^V+gNi$GDKR+x{#8pS=m0+45a-B5QKIwtNK4 z82ZAuk^%*H8TngtorMKJKB&AZ3q;!)#ouP;GAR)<*7!EqT@_~OoO;NSMFZ$DjGyw; z3xe5d3%J?`{0@y4ZbJ@nhu=>@UDXe1i>7bPQGNRmDL@N2D95{+`U>|u#RRucp+xs^ zmcS}_q}WgnA8_oi$y>|R;Xw%{JX}ijXRs!ny^H>kkkb%beUZE-8ysZH4Zna9_KB=_ zr1O^;Ue`V)?LfzIl)M=tsQy>yuUcfY@fw?6evn~jq38xdp}Yw8lHoSP@!!W6p(neT z6&p3sx)I(3S34o$;DU!Al`8F2u=&E!e#z|=Clo)gHg=Ij&zRw`^!;kQhe0V-Ixt&> z3`0aE2UBDT;IVck@YlaNFSA>yHU3&>t`t%ACvm&S3H#uh-xjAdBmb&(AAD44Hben< z@c)wLa;XbwSyWEm2|kdhHJX6v+`owm(qC;#VsnpoOJ6-YsIahykxLCz_cXRYl z{_1$YL@l6|3D!Z{s#U8;#i`;A90Vn@oPZi9D&7ox(f4+VtmkdSjlUWd6p0xLBdcX& zYcC)>g-4mu9DJ}E84@5pV2!HR2c*za=O;<2dBf#&!4u$fJ5;# zpnQgqO?O9mvMr=LR1P;eZt1VxvBYZbMd!XV)VQx|c)V0-6=BR_s_PRqO*A?Z(2=DbcU++M-mUai@Ib76R_!C>g z-2qS2@jxw(+7L&MlI<;~7=SK-u>M=wmk6?pUs@N5ob){NVMrZZ>X>izfpq~}&3`!C z6EV;BM4HS%aTeR7-GXb*4VHfxoTh`r6TJzCI?tSm`%?$qh-xip(?5uSX$WIJD?QI9 z$%E?cO`zj_Rj$DBPQXV39@(QkL~u)93Uy$E5gMA=3nd0@Vj=%RA^8 z$758E?$WUJ$?QS0gXh&8WWd2k*%R;M@#R)!N^IzgZZ9SlIdJ-e1#5iyvm|eVrv>A( zlMPE^>0D$BPhdyY5zboj^IM?eJ?Z2#JPp?)P}oKvo!1+i4cUrsa#2_G+ngN;=!*?M zJr0<}2CdzIj)ApS1Z=m)h<(^7Pw199O{b3|m;{}{3Mt6qk`7Lmo>mI_P?5SJ3@vgV0&y$+!q`lB3+yNH0_<$pQQN; ze{|rlgHT@->JRz$=D&S@9F~{I`76;qN4{90U?>Qejv85$#j^f%i8-fi6K7f56^UK= z2ax7&jqR;d5SftG1~;WvcKG^-3(p3rrXXyKGLp{oA=V$vi!dY#mfgD3i-8%dP=`|) zNi$k^A=z+dTt{sswJ=|OnjY(^lj<=<;cvwq^pLMN!@a>Eo09~*p4)jc#i)$GNtheA zOd?L{z-##wXiB1cgBHzY)fDpj+FD!j8B0m3T6XD|nlab|o^_7GFY{_DFxkqJ^NH(< z`$%Wzhuk1|XF0NGE92ts#0wrV{Kvf*qQKg|b2qxWcz(cNk?Ngkc0;{dUO)BUD-$fN z|3Kqn&t-i?v)F6`_9ELPC5*mYC`FWu$B)f`3%-j~pZTo};S#8G)9JmpKbB(Bu=Jrg zbRYeX-7`r9Z+b}ij1*pIVJZjRS0P=Qaa?X3R%<+G!XZlT)}PQn>qJ?pxKx&UQd0~< zdL$U_pf<-&_ia)kSgcT*i2NlHDnT6pI|rOi*;u7nUxx!*jbkjm+HeEGr25gi2y^|3 zg>ED)Vfy8@G5UdmJ4Vs+Kk92~kn!eaW5=6VJA{>bKY!kq+OPWj(Ds@*xIib8n&Qa_ zHT#4!Fly_cdj4I znGu(bTrE~fY?y=)swuCsMDM}8>^T?orF7pv*ce!_xgp5Z9h4~7To1SDVl&(~v%ki) zANlT&EB0Fe7@H(W*%(D^3VO9@`L7KQLeyMcJW6jQ^pWLLv(vPKOy=IU?~9y+c=%)x zo$Ud;jm965HGf#|M*av@ZDMg(j8~+Yxqu1c)33A#CRYF zZDRnnV=K%r`#Kw^0<$*{5fL`*x(WcAZ8djp83#ks0L;uVVR5F<||SW&_jho4!q!MivuY1CXSzJ&db50E`DDiCkn*Vx|=siDMC&3boY=#V0)>| zFNxM|dpwSePC6f`s`O%2Snv@$#!_T;rz&xu?;8-+Eo~`14v({a_DhYmjAND~KP-$g zZE+FV-8Hu!j1d5{{nPW^LZ$wj_N02i>*pmmQDjyA$m~jhh~7vD(a(F5XXk4XHRF?{ zHu0}YmWwqsZeLxS(hX+ANVEh&b-KBriAb+qp_;P2f}SkRTHGSPUcWy;7#EZXNSeQSeYH8y zX(6|>Hj+K*qcr!_g!b_3pJ^14`6?V-Bo|n|b0`Ew+{OukNZty7;_ymeqUvwnq8!-g z@Q%J)(P3cs{6|V++gLECRb?&?ZrF<{=W?R~L4x_hAC?7>U{lJ;%H}_Q-MrmqUfny` z&4z;(S)h20B>^SUow%26QANmyFNU;t5(rNHSe38FOEelnv6}n`scO{=4nh`wUk-W! zqLR-v(e}cWi$%$D%QXZyZwR8&9fRZipAH-tC1Bzp0#CU}iei$&j^{(3eG_@ow1wY8#2VEjL z?oTfcd^I^9Ni&u3s-8KM9X@k`p1^EFvni{}iZGG--c4XG)`Khh+`R55u-cWU`zdfJ zd4r`h=^XA@0Uq=B;LbGsN?xIHZ*6omQUPjLBuQ0PS4aB=bv3+}dSf{W%mn!)C%2D! z?-!CF!Gf}uxQOe{SPI9Z13SZ(96Lktz)<+6&4-1)srOFiJ<&WDO7W1kY&G6sc4mHX z$lC&IWa-TysKC*Ac@_!ngZgs?kTdPZD1tv;>$=3ZO?eV|Yn%*U={zJX2I4IT7AG-e z0i?}|Wl%qmEJW{O8jTS@ZU-P)H5B+pDOm;}Y>IZc@^v*Xz8G|O(W(`{%2BX73#{B7 zhJ3M37mS)Z(~)-qo4a{6#L=NU52oN|^GOl>adwNK*q< zifWMki0{p8-#_xcCfcPJ-p;cHt~qR%snwG~Mi(_(5L4o331FP7PK3l{3h$FY@5uFO ztAp3DVu`?biDZYQAT@Nq%~ZP+5AQ|Cjz2)(!swhsOiXTAK%K~BLcAXY787pL9rubO zfjvQ;Q%E|@FX?SjMuy=@Ed1e6O&>3;SDb~K&;>Lt=?a55jqR7QfpK;J$YFEJl@EuE z5gOa?raOdDoo~>m^6N}9ypc_-g(e>iUlXy$WmewhW6%xiG&2lZ;z-xs6!)T)H)-5F zCObV`TpUkIUS7zqztB7uu`M2D1NM0jo!w4FPq> z3uoca898m0g3T^cKog90_q@*q8NABPqDFutR>%U(PRSIdpY^@fL<$|EDS)rrtKaR{ z@5#K5Hf#twF;-5?pIVP40-&~lR@)zA9f&cKSgZUe8`z`N3Il5+&cI=i_Oid_LPIt+ zY3pRZnt>m(Wq4nJX93khYkM@qEN?x71q=@8KV5M@{i$Se8S7;$nOu)Hq+rfjqgcK9 z4&)xeS>K#Ceyxt|<=b`xG!Sd-eLu(<(Xve(;M%SyaDeemlbO+09%&r(Y%i)>3!-AP(cY5 z(*A1F(Tjr1hX1wVjK(FDYtln2ike&L7rEgJiCJ?ejYGX?MbSDm>isGcHG)sNtQ^D{ z9>Qzrg$`8b88EkI&e2{bJX>u;U%l5|aE>%;Jlbm{gU#=sIki1*eOEwBi`8eK`=9BG z1aJF=Rw^9zS8GDyiXG(v_4Nui@T|XxX5s-(-%aByt% zp(s>geq`T~D;<}YKwLa#m>oP{C%ZL5#dwZ+E`C7ko8?|Gk{~SoLNPYj6BA8!jEZF2 zzMezjNB$Stl=LxY+9)hr>gpB5rH>ejG%pa#bIY|#(M7^kUL80X%n^Q@JScUW4v-#y z$)4y9A_8_~i_3{tour<|250OX9sI294*0fksfjo+SEncZaEGwqATBYraH95|7e?7l zi)%URkql<=H)~@IPxKnsLAd~j^WZG9ot5?@+PN2~{(yQBIh-ZM#9H~`UkIf?71ljy z?ao#?=gJs}LU+DsllYpauw0YQ;LkWxLVH3CitMRb%53-IC!t5lAVP?etnf_@pMeGP z;b~m=f?A>m$jEyV5$1qx9;17nQM4l>q;1Ev^~A}e18#_dUbit)BkG4Eh1A43^GJ!D ztvL<(iJ6(7f`@ef#PHed4V6#yi9=y?z!SVU%a=h{Rb~B&!HiasMhB1r-9tc$h}&WQ zw6FUuXV_m;yGK{y?Odk2fXm5_t(%)WK#MG^+e_XddP%Sw4=*4IOh$CE)JehOf<$rb z()>N2)=JRZMQ-6-0x9?@K*dUr;m%c412CJbA6JGWW6e_rapxoA`Qrg+f?w2woqDH? zpI`7Brz^Q&Gj%B`)yR;RmG~WWsPb3e^oB}I&Jm}VhMSst}6R0l8e6` z6VRF(bQ{gGN^G6vHg;fgWN5xvMM`e4h^?!$Vigb8-q@V|Nz-3c^N2!i@Nm*n3Y9_6 ziASE5Yg^-_7@lf-$o+@Z>F_2(io8Rn`XCn!cAOo4d9^&{-`>HZg{vd1$Zwh~2H2IT z_aUW&(tPSe2T@i*cT-PL4jtgRm@jvRGX9G>;w|ME2FRW8n)Zqz5~tW}t-EEx0{ zycUfu6?2F+DqZa-{5jS4EF&a#YmzljvTCoR_qCbbLbK@3({3s{$a%<7*D<+Bc}`a4 z9u9XZY(?J?qOYY>b_S&TLTZ=V>t=ZVlXCw;j2uAJ5?j#8(108D%cd-`Jdcm`@o@!1 z28zonP+y-4i*T{)f5G?F%bh<^^|SnT+yU3<1cvV;GL2tpyes}U&i8L1X9oQ31&$Te zHW7$L3_|f*tN{vbz8W^dNj6VO%)EUhb1L8;8?i6ul_1{oG9W3oIK#yv63<5lT;4iz zISabOx%%scn`To84P|i&hla?1JkxCivW9E>&V-_!{9okbU#e_7@bOM@&k6qr5BWa@ zXD+@_wZ;wQ*r}XL}u`g!tsR*h2kJ>wV$GzkG#v$+Hm>rz4e= ze)aYHpL|bf_-V?uL?S9PZ+B|(KY-*{WElO0*E4L@!H*9rI;cfgVe@8{M+$GZz?+Pd zA+=dzu~eKh^Qxb;Zy0GAOa7nf*RX)7LQZSJ%gMis5Kx6$Iy<_i8H6xo<MuBB=*?*TC!MK-za7w$CS9o^rdD2VE~}*^^fBx6k{=tRlsB_vj15GM z@3!ZSV-4%#X4{`#?$MNym?~_b_Vx~dM?Y~sqhvJ_HE-i*N^BTJKoH47+^JjRZa?Mc!)+sWHur%Qhx^=?gX!LF*Ra^kE&Z*pge*O8}v zcWiVFYXJT6qklS@Pz1hmNi^k_-MsvqMy*-;X`3dstKi@X<~{BhY~hK3f&wE8JMrq) zID020wMi-Mq4+-&DgF%cF1dc>pN1q^{KJED0n>66GxO+6bG0JriV~Ct+J{-i3=Itn z%=NTaHnSDvShnUTGTXO=8Y3$&aZDZ}3wLqtlg0Ud|A7VVMk2f_P(H^mnn9w%ima>a zYqr{^!Io%cOCbl-bWx34X5-zZrSgSX{dP- z|ITG5KYW?tmxpRF*EdSBZSa8`(1fdQNPsQ(a--2J z=A_G9Y;qg=iUs#_#rM@dYje@}+nlKk5(DSk0gX=&(z(NGDI1M!b~ z6UO)3SNc#D%qKK%4(M<~k#zW)0sEqufKh(;MpzN-xk@w6M5 z=TgqM6D||9MqU-uc9$tpXj8MBP{vwVdkp83`hWgD|GUbck!*$Z%<>x-_U1oSDA7`&*hW zPHr9^1!+uFH3*Ivo>qkreY#W`VT@vb{sBaU2GT z8Tgb3^BP?j`=LNYWPpfEC|WnvRVDOI5f0MK&af&g7|kShrtZmvG*F|Fbz}{dSJc6$ zi7n>(WQk(mavwM|LRTYe#;OD=3yVz4QlftU*cX`s9U|UGRt3xOlD>eaB~x;R#PyCy zHtji|O2-A&*WrZ-@i^sr>dZnsw8pjcM=4z>1TRXmYJJ~Hmx_m}GtBwsm*&l8wXjS(9$`X)Fy_qmIGNthE-e*h@Mtu5R%0a945ER9B&v{KT6&zA^~Z z)>NaWnG{JneMT;M@Ma#&L>hBo+|5ETsv!>M)+PG`Y-HcncIl?CXWzV1Z{z-)sHn^ ztGzY6y0_%h(XBC@fYj7%8@*Z65X(mYymxeK40NJ5lD_1_Zsff;D3=t#m}r`AtzBJQ z%&w3AiRlR&hrC$hk#fttm-A&c@pZ9Ds}UpVabiw4X|6W$;0#pps{FF`h+q0sBu@El z9*6jBJs!d3=w-CINIxf7@XuJkrnOhl8oo{UjN3(R!{B@7 zn6EZP@GJM!ST~|xCv8X@jlh|KfQ=oH>d}mj$cCcAgX|>A5f~iDzM_VmkdQd(6kU*? zUrfC~SA>KF*_V2c4U*`%xw?Cy{KzKsOw7Rj?|qAF&+d%>{@+ztSe=293H5m3k!LY% z=nz!1Z}jE4kF^c17<1v3xZ%o+5EbaD2%>c$Y?&%MQFd}QWjR>2dIPHJTu79gh+!R< zrUSxa(5-74yj*!!C`Xf{zUC~j3w3VGat~w8`i-cxd7ww{0f_Xk$I2ByAiua89Xt0x zr=&;{So5>EMjmR*@~~>nI#kv+&x3#{q&X(BBT|#&WgES9>}^@3c5EYU#b_^0o15B_ zT_JC7B%4J=rEFUjh=>g0l@k*ZkK&>-l$6yWEHt!Hs(rLL8(4=PKHk{7?t5I>dl**v z#lf$xfc5tO>|F=jhR zf`XtFrT5->`*Vni<%4@0~kyX6Bo@GiT16IYYBsY;!Wq z`gro_VzF4j_GB$CKot`3(VCBO$)usEDLIY@uAPDxRzzUko_8>+Z=yq8c9pWIy0{`Q z;~2K@+>N}VQaG_~2Zx5ES4uym^z25J1ul!r_tF)K|1p12&8Vea-iC%6L`4O%Z&BUN z_eMb^a6&>>PYjG(u;)lQP82sHDb62*lEm!RY0?m`iv7X<)C%NRHzO(DA3dYI*bape zJG*R2GOGJzJY~0*(Zx^t%EsDyy!vS-_B6WTsmr?|#G@H|)2dL@&_X-LZs^_3AATNW zWZ4gtR5Y@`=p=p8lAbCwh_-Oq?yL=sIG$6B%KBzbo?Ou*&KLfkREv@RjP1Od{Zd6; zv%-csVQ!2GxSP8R!UElm2~~$88u@iX*0EhExB6gUzZ6Dg-z4QA(Wb^a)LE?X@$(0} zPUY0MFAQs|6;%~wsAs-Bz5Nm3@6Y$PzM(@pXZ^^u>njV8k(Gz&#AF1~8j0#F&bE?H zNtlIDG+00>teU$vX7z9!(QrhR&~a*iMwF zSZj;$+o?0Lt&2Q}_nTjAz~$3Ma(rmylTErS92TA6ss;u%n^sO(LxI%XMTOj-h*ZOl;w1veS^#mS(@oZFwx^qH36A~Zzx!KCZT4s-qI@8R`N zzQN3^Z^7JYTG2)!b<>~M~9F?TfLETFjzU?f4ux7 z^bHR{BcEvN}=gTd)X2vKy_3m0U&r8A|-~STt|KSe! zvI-Q_Ndg9a^=nJri5nAJvE{49xc`=`uqDst?Qr?~J73_&OQyjMO{%@J;Amw&oQ10( zMYBH4rBCx&NJySlJxST5g6QNb<=}so#k@D(oA1o4SzaT22O2ED(3h}|;mv1BUD6OI z@x__%q|F)6rZlbnWW^Duwzx(F70)cU?csZ0q>Va}q56DH4n8|(!TbqPm_C4vFtJ{- zAs-JuQ-$9=mO#eUPcq-ua?En6@-Vcj3o?sK*5=~z^$mFG_U>d{y&1(QpJdR$P?3?x zHf)53V5R)n@Cx%Q@a(dDI0t&;m(ybq;qSulNpcFV997^KYpZbItSB_r)#1^1GVw?% z^{H$4EeE;c>O>#>fedZWpjN#3>2chDycy?tJHf)&R;J@cF42e3e_iK{^t+Q0=~9OW z-#Lj73#=%pk{P}W=EZp7w{zk!EK$tIwcwi#xtO!A66Y}=RaRQ?AdSP-O}J)I5dLyi z61=613~8%sqb)eQ!&07sHLE_xkmrEFzQx9 z+g(Q*_BY0z94*#`ew}@A^0t}F>VA>k@!W$qV(!lu;FbwJ@ak)CVadAvnAp=D zw@&PhCF?!#3 zTr>m?N8K^!qFET&JDzFRWABzV*mfin&p&)8`t|RJ>t~OLJ5?8CP;Q|rLK6ov>CRnT zxdhAsNoMv^9%nvJ9|nBXIvH*p1X`$%8`oMo{QfgviVRkAq_(`YU|I$&&+t-4* z%)_9Rc&@Uw!ctX)mCHXzc3v)SnEfF7r+ojc(wzW>uMZ$+atIe`gOPey6l8`WYcwQAc9^`u0b12oE)|xr%%a@*gZlMT-Y! zU3N8k#|5MN1Am2^Qwy%0IU23YH>>N#S3Q8grip~fXxECSJ!wTv+Li}Rz@_h8h4Hhl z;zX+#`Xu(jZ|}Yt5uO$-e&aP9$S%fR*Um;<+%C)>*B?#w4U~#;BO)37h6Xuhj+zQm zcY-~!ZE0b9qZtjul7ghofzDP>ZZsLj0BlPxY@b%PPi|nOIzlriI-+we2Y*Oh6BkiG zY2rjo;Wc?Au37m#%H}v1O1~w2gJ}~6f}1ZXjT9z8(srk$ zu94C-X_rFVl?|@ZrVe4^+;(ODMbhn9Px4O6^>1^`QyC|-Z*Q;0)M1e%ONk}F$*H3w z5Z^5b$%!_JA6tgxUz|+Lq(Jh_uSxxrJcjslX*|A_%$Ssx?2wo=X=92QPOSuppRGUO z)mhQx$_c*%7k=k%F0FX|Kn;pxopFz{h{3RIU&2gpKUfL)yJK<>AFL#^{m9`4T-wVA zvy;8Cc27Cp+Q#V?b+KQ*BnrMB&KT|2idauFuKaX;$@o=KGF#ce2iBPr>vZY2xp+3S z5z}KlF>9n34rSKh!~8lN`Y;P$-Ik057QMJm7&|9Kd%GZk#TRxi*24)gENdt1o`Aye zjX1dL8@NRdM@sj2m3L`#wKb(E%+0`oqle%U&`Y&7zBJ-+BjoOlUtq_fOpKpA4@uEs z$T++O8@GQ9zu*Xr9?+KojY+wRBR|B8EuJ?llgf=W48fiqppy(ka&Plf3~CdCqWj~H zyI(_KSf~o;OksjB=!TQL%e_IvkUF!Doy5c*X*#GjI5~^85lPpTQe!L2`!ym{M)O%t zbQ8-Wq@q+M%sdEf_6gDk*jA(sJCVURoTO=#qiaS{MPOWs|ehM>G|d8F>nY5rzBHK){OK++pz1varlOI!_-M*8Mg)XWxP1ms%%0?W`G$?}w9_MHrMA24`y( zcCP;h8@BF5d37T~qhm32_!tZw*bB}aKwQZfRup97t7Xe^^kfmjy7j@t(F0MOlY!zY zD~64qj5r?)zW#axpIb3#*ckLl3Rg_dj&Ii?Ew>Qe`VPX7e!aU-)=xoX%+kf!;#W&0LG3RgK!SSdp51Z?zC)$ zLDsQ-_-b`1h7aivUoSaD&8!IZy7Qk-+KmcmYg!7wPQr9-TPh{Nnl~~$R99BQ;>{iG zeDAB^WiZHzIu9 zQIMU6b?Z0a@Ui2lp(rgnHW4GnjmOaby*SZuLU}K2B5J2oSg?IOBc z3Z~DPh?<;K*3~wY)-=!x!YE7{I~@K#uE;*Vm+j>cqLO+c%HI`RHf=;_1}DpE!+2_meRYZ_-+_EW*qwWO5j+}0a%s%)Spx8sgt@qHP(0d zka=(-Lw)dA8IF`TBR0Vu$1*FhHOL7=dicSIOYQ+=);wH|MkGu1byaovW>*Og7mb;%H?^hG#D}uRb`dfnkp(RR6+6g!o+?dT<$k$?8&j9g)|c) zJUOurAq`JdGW^;-73d$r4$P$mYjzf3c%MLY3-d-*X*E9IUyBR-_#@c08LuC$2SPpY zySa%N6yuM{$psj>yFxfrSlIp+%umL(qAI|gxVll5rlcAVFFc7)3tREgHPHxmYr$uG zYS}DZ@QZ2Dm^B~-Ss8^WU6_lH${KL2upSA1%u^-H%E{3a*Y!j~hw({96Wju z!zNyj5ral5s-aXLt0>MTE~U0`65i&>a9Ow-cH(3%!eio4TbhUb;xc&o1))dJKGaMr zM0!R#>!Jnz!O`f}ElCLqB=3#vZ<~mXFl@OQ2hrpfh!EnIaUzwI{#N+CZ91{Dw%6!s1p@cHQ;c+aNJBmsx5FJP9I0Yk89py#o zNI!lY^*sDXXe1`}K}cW#`EqI3Ug+I#IQDw>=0rP9A|9&K>kKF9bh!LQiJ~*5HW87Dd^$*7Mv4eHD;C|xu($!(dt?XFxC|y; zjfZCt`bj8CrG%_vX83G&y1bPxSuV<{d&v`@%z;xnJ#khtzCM8=2=!+tL#L!B{J6h) z=PCT*{mppdtxqtBdR;DLuG9B^jcadw90RU=3==1gQ|YORyDWXFLMsyL$9y)^Rynd| z$;_EZpv0-XP`c&m?FWCE_#+RV?7&=F>#_8$zvId~9}~}Z?)A^scW1CR1j32X3D;d zHWXJ5u$hPVp@0*B@~mSR)H@bO+@o>)&^~Oa%!HFyAV!QBgez{k3okwTGO8@>{25Q} z_7>XAoFvCJ>9&+)$xF)9% z&R#*BjJcpF>i~Xr-E@4sNm%Fh?v2ma;~Gl+Yf5r3?}}^q(wl!GH@3UEmtBc{ix(lo z?uEa-w*tSs>H_4aZpHOC{t7`!JyD*K<`4q7^!CT`^rOF`T1zXIEPNjGJ84_DJ^l)w zy#FTDmFHvLRoC*P=#AMIMB|GUYms#8LyA3``2-5_36z|4t^J%O+DH460<&y#l?ql;hKzd!kRU96wAyGOeDXXG%TJXBKfO z{~#GmKX+`uGa1&J8a(#Kar`NbZNwCckyg;=3hcVACz^9BaM^psxS*dGT-c5-fB7Wd zyvLJ_s}EAsEAc^oGhUe-0548HKPqd+O+y3VM#<^+eK};JTygQVc!ZGwQ_K~aK_A|# z9*&IAiuDC}DbtGIObo}o!6B$EtH1zCZez(v4v3Yu0)&TnBTB{LiUTJW&D47>ENwzk zkQ>sns*s!2Os3e0Qq(~16Ce{S1$OK})k6!J!6UGE#3DXYB-ji?yaU*tXU(~l5_c!; z-$tgWo;{6 z^&tX6qFI$K@N{!VMP(V%)B2*RDjSuJ&hVf*Pg!{xMozf_qX!K}Rnakg@a{{PeZx~^ z_=0h0&zCq};*0?ICN#9VkGiO~&ed7QMBaYzfi zpTfmI9#J6yw8*m_J9lrvlo|8UJx1!Q89|Xri12De`iYZdTtjWBOAFCXBkV}DGjOOdFHXbhhf6#zG^@eeOMV+ zq*Is9N4ZYu+S9S8->f7k{>aQs#lgdeaQM)EEPekSe0wZIk?~^ZAWNhHR9z4kKnnoU zSBmXsVkOg9}i;~MPSFXg0m0#i0 zj~3$bCmzRMD$Gv3?q*7PW01CIlVVz<2A_|&KV6NilgIJ)bC04Y$EKTp_Y6*Qw!UfE z`-*8z9x@KEFJ6vq8@|S^m-I#7p`+p5XRwkowQ^uc7&wAy_Ek&6!fZ*t0>fif)&h7M zl{*K8?W;dgOzZer*W&BVdy$d4AAh{>7KT}mzrDQzMFlxnv5Znhx~HE10Q=K2v2XpC zxa|A^_~@DYusgj3w?4fXfB)^RSiO1`?tSVx986!LBz!VK5NEFwA|ZI#uv0JF-kVSD zuV#3Gw9|VVJ;!$@1@RL#j{~be!1)u#6Orw>=7vW^lc z)=v;EvAMAAnNHDEwP(+_nT{;?S5?=dc$c)H5cG_RM++xnVs2R8Rr6iX{zEAxor!4^ zN5hx;h@ZUknqpcZbOzZr=y~TlcBko&p8RD7p;Z&;Sxsmzw;{3b28-l!L9^Q|18y@QCjq;Luy!LGY!n#Lb?Hy65tZ708C*-T{OUB%O zoQyYFu<1}0rK#>1)yogn73>R`PI*xsF8^m5Mn02?aj$3M;+ImfJ4>XfRQVuN*+OZf zxC8qNaoyG$3?YMh^ZAkFnVaDo=!*xhOU7TWO+;L1xe2$RI0r#t(eUwQ!(^{3b?4?4 zz}1272&ELz*T+k#l^9=&{8~|7Sw+h!9@xKiITpVAEc=YNvH1Pxv3BDo)QjYp_}bHA z6n?h7wqDZXP~}jE+VjSKt~&$|BgSH~L2-@Y6-$dr4fs zHyknu$se8VqB=^sudS}3A3IGRMqr;d@&&&_H4sW16|=J+`==^P`6*ng{l^ox;O-Ob zu-m!bm^pp~JgDc?C?*W(3_GnV5e^`RpKS0^osj%UqRgQ2tfHtNVNe}=2+4uzC#JIc z4@<;TkKBW&>`~Bv$WWBFdf@Im79h&c4a<-0Qg4$Yx}ks1SdPs;=s#!}Ef_>1tRa!@^_R|6!k+*x9nKy#9d!u<6gHBwwNbW^RVrq}%!}wgD#!dc5toD8 z_o~Ol!9x)j849kbW7z1C=3eu0MPPI`wM4x2pfo;ID7(XOMh2pL!U&oV?;be+^ zX$c@0eUpWaqKY7Q`}UK#YA!~FlX1!v`MWFTUwJu( z_XvZ3O9_5QhSg`l6}aK5dFT=Dhl=sr@Yh$k34=^hi<~Sc3Df#V`OpRU^)D76iBi5{ zlrGECfg3-xl+EX7V=J8*KNWJ zi`U}km!8js;wHTF#P3voyAK|O#JDJ$m~+M8Q6n*;XBbW#*st12WFVJfmCWD3T}9~d zBlL|rAXXjTo$X^QmtW(l6P^@UOudkLB*plmTevUD)RVbjI*no;jhc*PVD{%yorf6B z7#My6cQL6s;xp5egNY36;i^Bz+U~?(C zcep2FD8+PR9SuwH#PI9}Y$W~r$*d0T>Bpmri{KLCih(@>5I}w6{FCK)|4=FtjvXL@4k)-tRpw%~WmaE^$lPJApSz77mO8w|o>KHFwlZ}VARN+v43+^8kj)9S0Ot%W3@)@+K^1{!e(L2xy zi%4sINdq2QnXl3b;in;U096;9j!iJ8=oWDi`?_0F0h=4Z^uOE&b4DY}@(~%j!jja0JtkzNdYyi?Ct@RbE2;IPoGw z9uX48#u&;8*B~;dWH!l|hEoEXpI41WGV{{RMQ302tBldqSj*Lo9vC!e5ZfsWLKT(ZPG>QE4!dHFP$n;H5hl{Xxe}F;kZyo zRf1Ub?llPO4i=!ghDTAeu4^j`k#_7by2Zy+k2ePMu6~eEa}pt{0+LZWW5uDF0+2Aw zz3O+gWD~_j#d_4UUaP9Am6=C3_9G3|ML5BgtbUVbBZd}9sMCXx*uLo3Cl#x9rmH-b z=4GI?-UB}yHX43jJ}g%Qe1a1(p#LZ=U%wmW<&<)>FJ^}WzrZlmP^eH#1!;FLa_I6s zw1-~hPyc8HekurjFUD0dl4?*oLl`712Y2=tcBk&mE=jz(+{I3kTb|g_I0WN^dREaL zUf6>ux+W#*JZj05ru3PNQKPA>Lbl+bg)FfPGdL`Exy8>LFrPFO`k(U&w#3I<_$ zlGN70UKXUdXenn+Fc;%*2C#dJf}q}K`` z)p;7ZHa6QxrVJ-bbZ+?K!L-2H)={c_s5hti`Hnzm+O|x{+v<&U zMMrJ~B_cfs#_#KEo}rN=WUX-lRqTofAWYq^~31pk0w z44g6@OOLIj4kjlVWQtU3)Jb;Zh8K039G8uwnXZekFi>R5XiiD=>clzGa)yyRqg76t zI1B;Qg{!J4S9*DaQbg*$OsxtB1_hwtU@?|{v=pzs@+Qd2DK}V2f#9R-l-SqqvS(nIRmn9pH3)b@unHfJRwS zA%oH=;%+iOZC@z8h4*SE6WZKhJj9c6B)g+@Bu5U3!N?)DueqTX&HP@3?UnscZj2}! z+Nxz|6rF|3?v-RT`*U~x7yC-_$eJQ1!??1|UpT+422NC(;K5Y}@{{b^xcRb?{>;z* zW0ly(`SLIN2Edb2O)<|#eGjg?YL|JFK zcw+LzIp`S|uil3S`BOLdByw}pQDYsdHkh@qd!gaV$*&<57n-8l<4Osm=-x{`NqL1~ zmPw(S7%IyAu{l{u^5lj`C4d#x2X3&H{R2jh%usT5%rEaHBerr#->5>^GAAa+Jh>vZ zf8)p4vrZ-n@|KvBnQXRrQ0Em$88jK$`5*CQzPGU1-5Y__k?qlI2*;QdMOR1~@fej! zxw=y#&{U0YmVJrh@=8jMZ4zJ?*(An(s-BEFP4oo?NDGunf^0nIia|gK=QwE$(ZYjL z>flVqT$ok^8xp4TrMj7mQC%J6nPa!bvQ<#Ho7XX1Tkn!ICmZpaFUYDr~m#E zE}1r5?dX>9GHaIDHI(ei@|^LZ^THXpycc8kiUFgSa*_x6bI4a$OQU84BcJTJxU31} zV%W&>xWKkS4496f)^g0gWe=8oxemYo1vkJ1bHJzJ1|Bc3Mpwe94?}z>$p+ z0dCcJWtYKn)KQO)V=GNEQ8$cCPiYQ!jRizAtfX#}l>8@0tbR1cCbk^ub?hj3et{eQfjyb>(_5ZMb=*2eEAHx ze7*_S&KSz%jLu&M9%U|xnNZmftkjLH)6sYp%qB)KZk86p@MDk=&bDk>RW-6QTHQTgx}I+s5pR z2Q#PW+Y%Ft3?X45NEkX6NZo|Bo3~)bd4srVoICV60J*nTII&8)b(-{Tv5d z6CrS;CLorszRC1s)h>MBvqx>W?# zv#KujXy(-sOEcW}x)Kb_`y-KlZd~3!K%1z49vOz0d()BzX$gZXdfe7# z>Lq$Pp_+3_F-jmTmxt)eQrf$EKUY4;c#iBYObMm^zVs&}of7GZFs`x)a~2ch1IpQO zoakAF0h8P`HDJ@>D&&w+x{h(*~nt8+zR8E0UMWN!wB;_Dl~UWk6{9baLg&1M}nJ z$$bOdsK`PqomE#dbRpp}w3;FoGlUSG?P5F_ze;x^AH~7r;eQ#3luU5 z5^ElQTy607Nx-dBqoE*0iar-Z6%}%Bxf}^Fj+17Jg^a#~V51uk^F(K`=7%+sN;| zg=2(FWZD204EWwCv8|Z;q7nEBBVc~bXH`V?kr=&=J)ZGh*`Il54`+OM@+{Inaq`W| zbKBRZ;!8MVFjt|}$0GjlWvCPu!o9Q zOD0UgYLn2EbL4KY=~}4(ju_CRt)3){wn{RuDtxCu4w#zn9pal_2KK57RNW{X__Dr+ z%i-Ku)5xLX@#mkzb1%KZo!w0|&R#{`ylORYsJLeP6Yy-#sB?Q>4R10lRQ>P{jl+a- zQ?|qEI@><%nEW`38i}1nnwQ6y+e~%>Y{Eb9V>;#6b;HHih$YD6=mU`ML zUdy^mqkjzI)DR4BKj}>m~+m$ zdSMrBwB_Su8N_UtJDE;@+BlWxO-CwFMQL?2m&9NGEE7YXK8`oGl%bVCDgy+xhdO6; zB%Zn?n$pQunt-Cd>!xB#o85TW2x*X6ttS`UzfTyC1`dS>rS9oDb=*+XOsN{pJ28$Y z36)Y(+f0T&E2|PuXEfrs{r!=kbWvLo5$%m3l+>|rd8r3KP0J#040Is zH(5>-Qztk{W!?u-T|psC`f6gxzG}&;JjJw52z0}Z6C*J+!HWlA)F3mTZIBGs_HB7c z`r}bt{muzwQCcjLygf&&L4Fq9X*bqi?f!DWi}{evvR*t`pq`tWB!pS-+$hNqB0mVc;A zo0XNyY>PezR|EY0sLD}DD+4karIcCaw*fhnXuJA`!Pi$NM$#K|GRZw5V){^o8fF=J zqn$?JCyT&YNnG1dFh)7s$J*w5+8ZZ!95PF6q7+FShiDFx{Lt9x%Dv2+<>NPPB{oVR zZa9#nOhfqM)w#0`mXx?zYI0PN21-BbxJ27f-^g@HpPh@Eom0Z$#v^6>*qE`spS+2? zvi6}ebqm(+&Omp@uCf?;l*H>Y=;2nW21R+cvV#^UY7MqwK;>IXq&iO0Z>W>b#u!Ld zhsJo#veZoGQCtBTD>1p4GGrpI9qWX5mcED!3Ql1D`TenR#oO4x4H}4_kE}g2G3%l^ zc<}iTvGI$yacA~Hgwt;5qK}qi`0!yU%dS&PMjinXNREnDwBLR8FF3Sq8FqgB9#UHp zl%LoQ6$QWa! z&=J2j$9BWXR6~;srd)CjZsTUTmsT92#QbV}_1R3CDzakjs$HnImSO5GzsKCEBWN*# zJA<#h6;Hjr9h7P!<81?@Zj%g#wi8`2Qrn~0u>kJh3U8l06|In}VpCO9gXINDL1p%^5!J0!#{d2#a5M1o;^UcqDE- zzJB!?>|wQ!yzya7nlYKuYhzhmCBmOB>r070+aqem`99YgZmt9M_&(m8kAm7p{CY+N zg;k_aCexzqo_bCEa-Ri{F3CVIsvjJtiolWD7CbaE0P&$R zO`(o7`>Cy!EE^?u-MOSMPKqTxV{u^(7VfLVFiQWL$cVqTDi;rb)&egw&09F({9-{e zM)nUvpRdcYqrifP-bqI{sw1pEX~D_*R@~i}rl4pxO>{^MCXsn#f8^xq&E@HEWabsA z)3N+{(u+v{j4&z-#D`1SlrTHiU`$e9>iw?AhHsX_Y5WC<2=GMe{tY;qRfO{{lubrL zhxCP^Gss9|WBw%#LS}Q@wl#2e^X8!yIYrg`G%4jj$Q z=0u{K+O!-Q)06%_*t~8j?RsB`m=Ky!OxuM$2lu1bsH>TGP8L`W4oKYim%~GShEY9( zbu4+|KkYOEKV<~I7vm}&igZ9GL-Jh!Nx$RV+JH4*EWyi5R-^yGZrthp0*#0dz^Ifs z&Ug)-K{38xPNnokZ~P6%{FC9jb2VOha}nb1T|nss_0UwO+Q~;r`YJ!P&l#O?9zqgJ zX;MpO+`=py468klWInmPJO093@WioPEM9*YdzLT6)Y~4#6}N`q!)G6%SrHC=EF(E< z#7!N75zfh!tgtg?=NA|j&(+t_@ZhdmwZtQx6|*Gi%b(Z?jf@?RfVdc?&m~w1Es?MW zhQ#1!qeq~S4E(`;N6~NASp4O^{Yau@@PiK*;)y3$&@xgyZhz=+xc~MW5Xpfma>7Me z^YN>A=&>iTf7!=q9XuI-_`~mUXw&D|VKofS!_^Ph|LQ?*GHAr!lNDI}?pOHDlm9@B zYYCpX_x}(`(_0oY@(KMW;M*N*@a*58!@`B{;Vb4WqURv|^}gTY#w#zRzN9OD|MD&b z{Qdv%;fITG`%RxQ1kiiL6uk5KLQEUpgG;7O7&7f*T(dO|nMJugVmCwS2TB>cY7^rB zUCyjk6UQ@YTSiz_Qwn8?Q(lsf8Zr=0RQ(XO330*<%HZZfeX)qBNTaT#&g3P3WT2LM zGU!Qrkr$>j0yJ9c;1`mJC*N9u@YFLe;OqC_P{yu$_8W*_|M7m@ecQE^p^ypXWTGcexM*sj9bx8G^6A3% zGj(V$pc_rwNWPf74^1Ep=fNB?QGSZ)va#w2?mHb1&+^54&;Av4zH#XLv#asP$NzvH zk^ZoFjlnz5JcK(QeGU)ab0=cYzY=e}^%i!M*;wkH$IW3UF)YpliIe-2c}`LKhEigg z@P&8d;UDX^;Q42t<;g`KU;~?_AIfAvCXd|ELh$IfZ8JME9Q^h?NX!G@05c_A7y+cA${sg|2~AL^F|<`H z3>sIzkrL=i-B88DD`qS#CK!vZwcwdmC5m}nPO`}!&iL!pNZd3bj8u$?w!LXfy6)7$ z?v5=7zE+k3{JH!u5<}IY@mHK1rK#Su+92|Ol_xTfZoZM2Jo8#?`1T8Yv*Il!&1`n| z#OSHlVL);cgBcsj6am|h^ou^ep_Ftgz?H8vvGMltQSHbK>q?2EKaa2z3n9(?K744p z%2W$+_wwOf)O_>j@TaJyZ-s52_o}7?a(PQ|0OyD~wmTSnki&4Gy zQ>^8nPKPRv!Zg)^ghGtK|&dpXWx)AbVzx%p8|FEQLofvd1vo{oZO^b3t#s_?y{S z7kDF&+Pnd-w6!M&)4gfLe&e#&F!jPv_&ivm@{o#Zy^|x*_BR4^3X&{pX|~%^Wer!TW+-RDZPuO zzK(jVPLvP?DjTwSIXS4{(z^$ZTgS)K!T@K^vb62u;l*V>F{qzMdx=#v;}r+j@)Njo zUVpq_I*OBlh191D;|dc8fR+Xn(}txJ@eZT0d2Y#4JK*IsC5xCLV|fB;RNG2PbZ%ZA zccEHo@H>n)55uTp$DOZ~U+84-Zy^YN{xpDXt>b1S z?zp91tjYA57@zJcOP_Lfy$emhgi|UaQa{10x{9hCw4@LaK>64iv@NM`4=(d%AJ~GK zBPL-{Y8Fpe3&9t!J&Bv1`j9)m>&a-e3rDab=P^DL&dy!=Cv5F5eqx`ApK zhD6?lb?whn#%iick)L0zju;Lg*3pq+G^NE&b~SZeZuV$1-P0)TiyVn7m;4NKK0I-Y zOr%==rlkZ|#n^Ii=HzMjw~H}$=8c$e^PlnYU+;pGr5L3=j3Oc?mJAuS>B`I5ZhUyU zn+x)Cvr$KhQz+F^0%`I{>?yMtN_9p~hBMo@q%Rwkl;b2z>YEbv#+hjVczt3WE>XEumTSdSnCYarN*|FcO}WMO zN>|pM9Zxh5LXcplgi|r3QV9CVvbMB0(@7ZPpaj#$c9k%;a!a4YglG`KqI7v>OR5iT zD@W2Yfdo?db)c#0fzsVpOBp`@@Hu#PpMeX;jb?e+|2ZVCcJ)gd)NwYW^N~TQ8*i;e z8JDsfxKYlR8;b(iFQ{Giw(L1xWYTY*)+YU-IFZUq`*vZ!Z6;}05n!Frua(TGOgQDl zH(7PFzq2#Hr_dktpOgb%GTCd}`B}}h7%f*hKmEVBU zk|I?WZ-Ke4P$RD~!i;L1%C)eC$%Y2k)S#x<=zIF?oD$pHkVGPY2n9}pBu z6$)>5s}(eeVdVxZZ(4KU24N3>_U)ePL_$yY-$%E9h7E`FaOoAdaPlG)1!L;P7ZeJR3B)rGT^M7S4u)*#U_Y#n%3{s*l&_pKHkX^`N0kxpwBv_no~v#ZT3Zl$7HR|D+?A zzxs+oT8c`=8vb>3EqTR8KBex6pTw&z&%@_=p?Haeq}HX5J8*%{`~Uzz07*naR4ayL zS;}5rS+0(9mAVLxluBScVkj0C8f2oxIup9h92_eun^-3S=-EpoS&~OlWvMp8F%gw# z5@t(LZAIlkl}kz`e*EQ+8t@rj4NCM^2{43}dfRmzNaG{p5gb8D9KW#&)*ow$y3m|h z@VMK^m_${t@~(<{zHVfeMMKA(6FjlPVAO??zT7LOf^{l%WMUB4t-DH2m5~z{(P>tC zmy%B@l+77*jE6SHM8c?Wjv>t$-|s3IcyfZvCTcj+ccn3VgRK(4=xxhe5I1541&Q=i z9P`3@H|tj77(kkFggGO#YJw{?7~aFn9o;CIHXOrB+mV>8WP?d?;$+Z#FQIJoj0m=H zOqaApVs1DIBlHbA;wRspVXw4(e0e7fvT4gyo=FbGry*j_ANpUXG%vyBNO-YE{+RtEzraH}@k~@d8uyP8&Op@j9M`vrpBFRa_XQC;vdx@o*wiPF` z5S5dZa!eoo@<8Han$Wgi?4U${9~|{^PyM9Ud=JB2N!p-DR1(6D37J{H-#HTK3&lsV zOPpO2hKJ_`x=yg1fod2Rgk#~BM$1E2n`Y+B88Rz;&ci)Z;lCdudi@P}`V%Kj{m45> zm#)a7k^N0LkT?%m@g0V>R|YRZ?FUYH9Lo)nY-|wIXK3)PDihbPnDXK=C!TFT&~Mr# z9mtf;m}z(|iQ-fQrk4CB<0>=EXG~#2#CDkgZ+=Jdb*0h&4($o3CV1deJ8`2rz^d-)qM;M7!)0(v?Uo08!nAP zKRr5?vg#jopl9|&mvshdjh%)U(6*2xtH77WUc0r?4K4J64SP8brpa0~E?r>X#GLN1 zq6bdHC0P*XvUw;AM_#8SY$ztxEK9YU<@hNW-7*`{p2D(abJjC>IZ7tfi3wrdrz-WL z8H3jZpaqVAtP}w(QQ}CMXe@Sh$)vacxKckD&H&o|&qif)STjm%%#8cYy&4lS!db9w zdG58*^>Ithcxs1IPFGgy!xu+lvO*d#_s52{D2XT5Wx`3|3LM+jhs%fV!+v!k%PT79 zfqAx_kVVHS@Zh8C9xHRo?!o<$Wv1v*zBW=A_*KMAssV+cXIEf^!rTX|rqeRhQ9n>? zMCvS`5G~>!5R|&Rb?9`8gn-8xDPPM=4;~1jZwq0 zeD=!SZ}9*uT;-1(1s(c2WrS|FTjqoH^kw!)w+V)|4~oT>`-#j+r7?;=t8w3hoG4}inuzw9rc$VH<3@R-$ z>hx3vlxWXk#uDU6Bh3vWUKV&L7i4euc2Sh5xOeEz;Z;4qoiWs3 z|2#S}cyQ#5JEp#4*cMY)lm=6}1wn!)KiP3vh7M_PmZ6v-w{L{(N)CKMOlh z-jh@b;%x_Q8O17?4Z9UQN(mTYh$Wb3u$Fp}g$|=caDsp8r@AW{fy<`g#}VXb-F=ouVYk z(d8?c)3amco zV$pHZY$IhiZNa;-dQRI@y0G^6P#?9McKJNDkNQzPjR{d3jiSzx&9vd*lq{(o?0{}j zK8e;cab!M*QiYqc)ZWe;WgpLZVLexty;~yZ+wa}TwH_fI6pSk)N>|9TpvE8iP(qV2 zc?k2PzREc{npDl^!sc#A!DFUr$!n&D4t_j5vzVbLIK=2Nnw2M6 z@AwBhgk@L-{HfDDiOuM|@5B=Cdjs?Q)k<7+#Z7kUjU(=r!r28kVwDdYhyXqqP=08R z{ioaOCK?Y>M|R)|mbmUnE`yPoA< zE3Q6P_U4W(z}|JBGSPRaW^ zlXWSq#KSA@Lr@y{%7uwZgvd-K&;Egi=yN5vc)K9E?utui#=q-QQqhtAALQL5B8k0t zB+ZaJw`OMv_?O0lB^mc1`ZV>SG<~zkl9AlhJx4gZ=g-fNXMNZ*KTJ7?DvUUX9!*m( zayk`%*Nami8c(y;e6-w-H;@+*nmw5uX^<7JuL|xRYM1eoxZ)IPqZIG#3$R$5ElRsP zL|^>5Ea_TiQW?g9*NIKCc0R_NIV`u~nveQycQE`Np5hCvE+ae%&*-ah`$4Zz$E8u@ zPPcaM!Hnzg6qi)YqG9r7%vIn9k{^A?7b7bwfpB!%7d4;{M9m#l0EK~5ca2M}j4Nh&q z`5k*@y&qj-Qiw-}VWOk=g*H*V?F|cqRAABR@_87>wt2D1Xa6x+fl+l8|M0RID{UjJ zww)mJ2}EYSp|ZK2WnWyMfTK~D>M4@ByN8q1 zZTSD{R1boif3VeYudoQ{7W>!!1P6m3lc6+T^*WHf5~NKk`7T5KGFFf`M-d;4P$SPL z0X6pz{r-K+cUhZ;gcKwxYh`;|xQUL#NI9k;wuP>;lPd)|_Bk08AxPP^Wa{a#l&X4O zaeKMCb7BwWu>F5%h}|vW-PoGw<|!Tnh2cVO>F1N6N<8MbeQw0vMMhkPN}_&Qjaf}i z07k^hG#xEU&(i+bMe@YHl;T{iav{j{ym zRbJ@D5{z3y5L(A&7R2e7TFXE|eY;mB-axvDWvG7xtXPy4PDsFwm_Bexcinxzkb;Zhm6M_3nOK=g{d?nN5 zf%!tTX3lrN<*1_OA23WDe?k!d8OG{({1VrLybmPoS&RRpr3dD(d90O6v}{~rrHYrqF(={ zee>62G9#eO2k*2i(X%N3!Przrnv6X87Hf|9kL#a)HV(*+Xw1JU{9l;izizRI`O8{x zl(YY$#r{>%_VgsV*b7dzYR=jJD51R2r?n-5`F#Jl4ip2^o*0mINiIqL)F`wwqbzB9 z`RJFcprb3fkd)}KO^+GP^p&7E zXvkwrZd1`sxFh8V=m0!c7GA(Z^-)BjB6AI$v2NCr@PCV!eO8`7i}+?kWCf!&#EtnR ziwjI*rzxhCq+}Wd5zTi~cil4h$%BgDU*XrLyu;eb)SlF1b zN+^uj%Ru2D8Cq0dT>WD*V2S*601gFShNL%q=Ya{SA3)-EKRKAzP>;-HSIokOe-BIl zk^KD71miZ*hBqCDj!K5WlcW)|6)P}=(b3LC#yJg4>?eBkh^<0hkC)9K;e`o*dP0|+ zsPP|=9-+zc@!^{a-3s(Rl}fv%yMyO+tph2Vi!wLVr=-t;eDNaX;{W2CZ48E=rcNww z*4D5V(PL&p_OUUYT@77HvDL=-c#l>TiWYZF<7z0sZ?>EtlL9>Vy${@90yKq##$?G>>j?CHJ6kiByoNK{l_HRBtws2v!0hBWJ$ABn1@KBYa1R>p9a+fHIY%ui%{y8dR_`9O08_WhhamVXMa!~ujg8V?n!;Uno zISpjAGt2x#+da;JKWIqJhQipj2>6!|{2K0Hp>$0DOZG#0#6-ax`v z0>KwZ<>G>-aJ|0!f>4aHor4`E3FXjJr>0QZR)+~O=uXN|1LsGXg$gWGo+~^ggM^He z#e}^H-?0{+zuK`!gp#n91;Dc!j86Q~#Klq4UMeN4#yD=fm%I!RphMhEob78V!uI!H zzbrxnNHK39+_4nYi2QBNdeoE11%)+Xv>e~n|3tJ~6XTlN{N9!{#m?M*jf=$!^Lt+f zA8?T?-O+O|Ea|-%zG6Nla^mij?qc*?bunNF^1MWMQS}oGIWI5rkc4&?Q3?ZxH(vGj z=Dli8V}iQ37yj-@Hh2f6=-j>yf-L`{B+=i5mZV!%r@XO`=b`Q-l2TFvnVp6lC^&sI z&jNz#2~j?|UWh8x6$lTJH7Fj4pek)b*VSR98LVrh3N3GZKuqn6CHxlU_|3P;=TJFY z7Js2UUwT#Mn@d>*E>0N?lEk;`YNG)FO-E2UYIi6HVvnSBQWDxiEn|t|EWtkp&Me}| zY==e%*Y!j!wOFP*s5@~n3pSwF4HCtSyKfF7L*@bx7HE6`Q+ZB}P)!jyxUpnGizZFm zVEBo6D0OjTQJOUahZ8(j=CARNd~_$t4iG>b?r8$bkN^=)Galu2#br-9$!_ADk(VhO zGhLN2cT|*KbjUOQlUz|&_w36<#13Js95?pU+@rlJ(~$;R7Mu($i5xe(ZKHB$l5>!& zk}v&r*>^?*Z{8a!OAxc_4Qjy#lu)@~_+dw@9!cgS-&x4&dUhi^7dxSsdbNyHjho7V z%9J7ibqQZj={;tT+;O zBObFia$%w>Y|snVa;Ee{l6E?7+NS>brJJ)H2JHIlDHOqydN6NXID5Ep;tN1{l_`!I z+Oai}Q-Y%AY<*B=)GP1iewx(X*$%x9|B$F3KB08Sayss}4mY`)jgYG;M5eb05-$Fd z$s|xWby{yjUyruEHb&a%X`k0yio(^nS&)}Mbsl=S!IhGQ258*MQ&9Bwe@5b5{2faO zr>o2U@f5_t1}2lm-(5&2GZnG&Su>4ua#*OF)yZ2Q?d-Ty$i4t0Z#3ayYc-{qna`8! zBK1+>_UXF@Cf_>3rqu(loC6@MP`vAj@nM@(w$0+sC5a}uoAszd240AHC-G&}i+65N zmSj!#i~Ev-M3q%nn{i`y_Q#V_#kgw=os{&Zr7p$5s-V5E<{Z4WtW&R!1$*Aj6Uy1= zl8JZzBCWhIS2ugwF&ExfOFT?e1S~6k3{xOW#w$u5w&?O$H)6z z==o1L`st+I*rfKjs<1m4n0`I_i;%UlIV^(x zkf>G8yX{O}fT2ndUEla)WMuW>yz8EEU=lZd<6L-^LVk za-Xq%Td~RI5P7i2Fim;SumLpf%~Az4luzx>vNZjCOCz-J*X-1d0&J!RqDevV6`gBg zHfT_kz~BpNg=M|}F5ge_TqiJj6Ya8!meUGnUiWyb2UWGzhk7zz?qDhv_~0lBP4CEM*e^Bgi;LI`_NJIWxu;w4i+kgRJLInF z@NV{mM`-cU-2L71Ly6JpTPpicu_A2#6gB$&1EP%`+$*?ZKOSu;)wTIc80byJ#Vp6R zuLoH}T$)r|-2WCA<9tQ^>~A!|A@;@J%B4sx5U5MOsNceN&x3*kI)3BqxGxGCNWnMl z&+gecgoI8?62&_Do>-g_bC*R{idNmx85TtB5XK1 zBt`v*SK{b@YSWi-VA+StVmqRu%nE^Fo?nrfIz10Jz(1lg{T`>n8dPg-Q7TAL1sx7O6)I)qyQ5Yto+HJL-+Hg z@IMGIXnKR*dv*VH!ZQNvane}^}#t7;mer_ZO~ zv^<1!Mi%z^U!?uNh1s1$exj!A1czEV*_h^PrT>1AM83~173EGF^dxvW-aifiC^Fp2 z!S$9VGG6A=kiRAllStCil=bfi4lHJ;ir!tX~g6dBsR%$5G3g$~=yWFOrhgJO|ju0MVR}cOpI&rcPO^UNkUs4+E z)#8tywyy0rwRm}MI$U?9(d8lWlCoBuHVa*uL)KW}@2_#koSF#+N#AAoM;)496rG9Cb91N`I+UFxOzS(3Sn8i}hV|Kop_FqxxCL$7NFhKg1 z`dTYZgI~!~mjzP?`wH$_ohRy)ESG(s64aSOljQb^RmF6MlCmTn?iEwM9aMXM~Mt+WGa6@aTF*cFSmxD;E6Nm(aGQ9fn&j3 z`EAR=1Ruprj{U1&CpW>Sz zOdxC+W^V$6TMFnpxaJ>d*4%Ob{XhN!!9QEb-WAB_!~QWBvV!&`vn*6I-J&1F|PCR-_Q2*iUuR2iX+s|&qRX6|C z{a^rNb>L%obT<6^An4!q*Rwz93tjmCR>7?(PasHo>Gs#NH-a00 z692Ha9f@;?Qjdn38Ylz!=dW^+0g6zwQrf}4G0@TTDl6gA+jXf*8}a^O&5h7!yQb&l z#7s|r=j6u821{?xM(pRV`tK_KEPk-yCfYW2kSc8zg+-EVW>)6r=H{16Km32xD=Wwc z7)S}y!u9nvjwh7*`0$8?uaZO5$+PI+E&r=fB=#_$d9MLBLE6gb*ObKU;MrASu*auv zHQF)xEtf+ofKyZm^kCN}N^l_mce--i+*5HT<>m^N2f_=^x3tPZ=C#s6z&`H|60I z@4uy3%)x-rf4LAeJ-+7Oi?*5bmkas9cx2W5{Yl+ie>EdlPZ8-qT}b&a7g8Xux%sbd z{x9hm%D-HQ65wq7_qy=+gZayazU{hn{?mnmx(UyBJmsfPNygS|=6d|~w#)fn^f;Nv zDD|)^@c($JE?^(bYN)#1`TxT>O(OfAu!^f%5DCDg)enfWil5`AJ6(?D%5wU0y>2ig zJYp8UU;L%;@!*fui7BNKCZwXrtdMro!^jbn6!s+0s6>&?Srn8ZrBs!4ffqqpIC%Ic zjMB={-g1@ss}L1)(k_UBxHeju__Yj2%XB8DU9I$ZAi=Ff`3??#BIfZ{9b8w= z4PRdHBO`qr+qYuQ=w*Gvm;Tj%-oZdH69Lj@o2Q0C9-2(wqsd9Teq#ZvZK0qlAqnji z5?7EpaiMdPtbu7@io-ftLU-QL_AXAuPxbMIAoLip)YfW=nl|>%t|4s^5y!tyXEN{$ zqOPQ6#)j3iHZ98%g#wOGX)Q*TMkf|=@Jm6p*Vd8;6z>gr&Dz@B^~JdIx)^6~L|rDnzbewIEh&I0X*McsD6M^7doFQB$KWun2Bj z^#K+{Jju)~olHgGbrLMqhk2(wC_`8;&dDu$aJU9 zVpHV7+3HHN=RN0Q{UukDS&x=ldG?KE{&6lu;~w6hY>P<`wYi?qk>ClxV7SO9?HsvS zvq4j~b)GryEV2uXp*PBk$zRytCf-sPf?0)$h%K#PZWeKW(4ZC`bT)l z`a8OEiJW*w$U0eElQfDZG~6EamZ%3)lbuFj)rxDu7k+fwJCkwwsNizzCV&=Lu5g$lHPO-)Y7!e$vVK z_20S`_f6X~+IDc`Fz|9B^btIwaOiM-L1;q3s7_CZIdE>~G+evT+bqM*xZ3*UdLJL; zNwzGNNqdl`9tdky4LnIo%Y`cFLwR?sT55e#;U$%_#G!wGC}R&Lmf5~3wJM*pU_v5r zk2+m$C6;WVv%xIra3fXPk7&3AxEyUsvMa}a9w_?53&vsng(IFUoW1v($0Ci6Pvx+1 z0(jBYQ>7#!+H4z8$BaN*)G-TV`pE@UR!S=l0NpJt_-20xEu5QUmQ?MyAlOAsgQ!8NH)S-*RD%>3Fv_g&?=-ERGi#bQ6dP4qs8n!i5b!W= zr!)O-kFQPWPqN{8}g9jhXm`0vlVtgS)du{N%g5;zSjlp zkxN;RK62vk-wSMu1D*8wnFVY;lQ1YM>c@InDHup8*SJ&+4|d}3Sf-lhb)I^c>_o>`EVX_l0OeJI3;wuUfM zJkg!nrYr6o3f13aW3BO%hR5=#IvBOZ>oH#^0^&5MFwjJT24A&ECJ41^6s0E97JA!u zYkNN=-$=@RGu_JJ;KvOk;D-|$dP+HG;WH8kI5Go%Ilvrhhq;c$cPy;g(L^8UNNW`Gn z-@x6voni!n)Z{=mH;six*X7&~>cLZAwFoKdn&WXEv23QO5)#!LarX@xKuB4Lf5-!E zsYbZ{n+aMV;!xKI?)tcCbjU-}<6;j&!pJ)Ovxxgl>3ZV%ERI{D*ce?ZEnyw$KZ5!* z0O4@;K3LbP!oVf0v*AAy+i8o`*p--+9;PZ><_2mLkv>wQ%SVC3%)3(Q%kXEnN5H*k z%c$>P{vASf`$2 z0zJh@7bo($F&|shJ5#MX6N?0#h&6dT%}|Ti-@jx(>l09Da|IhDep zVa=1m5Hj$M5{w+CF0I+aw89CDd*fp#Lo(*OaTK1$4EgDL6D9~`MN~-K2SeVqJMQZ9 zz8u;-dcHG@uJR!4fpZPhIt-T7bOib`jVlRv6v>h-tj#nIs+2gBvCI3lx%9Ry6^u$-qshzR`%fmtZ-cp@^LrA@{by^&@UHkS*OQf{o_ViJ!#2=O@l2BiHs_ z3g7CRAfp6miJv4!3?vnOlhBpNxPfeMZ?~924={A@Klk;Wt<^p%=9Y4u1tzBCqy%n% z$BkM$zckKfj-t-0MmlG1r3SRL<;OaVj%IBhZ57iRRNGcl(b0?Q>VDPXS=~B0sahrM z_YoSUNiOew#WOZLsLRB7e14*_(oUNz0S`{LSPLVf(ue2cVsH;MWDl<8Jm#> zF0p^qQ&;NAOvs*GpNPSW-9DKEy2SNF7AJpse@_hUPr_(8(9Fq2lmghFem?KLetvmT zHX9MqRy?ei^(kK^pf;g4)RX!`KEd4dmDn;ob#d>a+p1wg`CSTuYVZ;r|j%hdPnZ6J4xUOj7C1~M2cH~fBcq|UM#yfx!EUI)iW=7^by|AW!u)Vh`x$m~$7IPqo8 zH=JucCt=JH$;gh75J=CdK2l0Qb`&G3$KO)kX*I+QRi%xdZ?no)vm}7(qEkU9lk=~5 z-T#9Ej2_NmuR>K)%|VJ-+6Q#;>rLhKv*KvdzMMOhR+B3eJ1io&$WvO=a^<)R zZ`g=|(J8fXzKj&oq6;0s^EC0LlZ!C&OOU*S$mL1?#?}JoPcClK-@f*$l)KW74OXAC z#(PxKUq***Q%}{|U zC6qig>RLJ4=)~xROUpvspjT^7cL;((dPHF$QiAtN?Mz1=c*75&I}C(dO>{h$*RT)W z8+`%d}g>$QOUs0w{C*AfjUZ7brU-_p>0srg>fVaC8wf zG9uBfxb^WptRjTo+PFVvzih4L^A!ttvY=dep>QDOgulYkYI1&(SH}lN3~6}113&ll zFBl&F%!ayj?W=}|z1%v*$Kqo}VbLXV0PM3xhTHy{;D3eCk-T)PdPb*lqwEv-O+2XW zhZ=HsGH9X0q|I%3QM~tfTYy;mB1%7Mt{L^~JPLP6F9HF1Tv3S{zr?^l!9TD*5dNwH zV`prlt9L5%`(k(m(rg1=HMSe5r<+CK@N9xoGWVl{`^$F6S)Jh7`= zo*h{cuLgS+*1HwFKBZ=M-13pDdL$lfdd3uZBV1E9LQcdTE_Xprbw6OU{chBGS?;(R zEYWf$3z3M4tD5rhXbo3hc2Az{?QaUbA>oYpw7EQ?0uJYEjqVsyAJ0K#Gp|8N0^a(K zLnHh7+>gQz9LD=OkkQTi+Gcb^+(c=q>ktfp6JzLHCj!>2gW4|Ngil^b3?@8f{j4wy zw_Aw~#=g_8I>(B3@zZy?@`@vziv{!_go3>dN4umxO+hYtb7uJ-n3zvfV4zZH$H<>? z#@6j^RVb{Bx9IWAI&llp9BON`7BcLe39pojyKfdd03Jpb7`O8=GVfBuV$9xt!l)}; zIt=E@)C{K5(1&#KglV9ApwraCm)+VBvbz&42XTaOY|w*pb!R@xkmRURl3D8oS9wG+ zmC5`lSpSt4ON)(#zut~inq=}Q^w|zxi^`yI2M%Y|oFxze$!0l0o$n?R{KZWNo6x7Cyttr11 z2AUud2lln^Kwb@aUFgq9x$$~_@R_5kAwq61Y>iEr>c4dwku_mBhv5cQR0H7XL;{tR zQvH`My8N{-T+NR^S=|Cp@qvq;P&P|nQEk(I-fu-cmZlhDuH3v__y+a!A_#k|w<|Nq z0@qG{H!K&DlkE!Z&ZWsKTv`eGicX`ZsR@l>vk@w@{W&%2)9`zI*tGM#$-Oo>lS;|CHQ3H0sl`jz+W!ic zt|X^Sc-XotvFpQU;149g&zPyx_!UCerVq5s$<3PGRMQAT(=oC(Lm6tCtG6RdIP*UVB+(Gp=D=O}zA%t!lOh zD?+xK%VG@HFDeY6Vfp~jJ6v+L=)gb$8q<24A#5p5{Cu&J6rh?)Ha~X7f2axOMkElgMN2=oR`l zkWW!eA=y<2=LO4EkAW{lm5{ortl-MJo;Y_h_xjyusI?5=lr`1oRHz}TF(N>tFE+x3 z0wuaTTkOA5Hh_jb0q-i5Bn6J1efdYfQ`ra~ zf3I}pQG5M$Qt}?@;3nXoqU-(DEru|<#I6HmV5ZiC%Gyk*F%)nfq zh=W`e+B#nTv{pjYjTbD+tPK6-lbW5pA2q%CWvGmAGZ#k(a_4f`UQO0LUWC5Uv8h|` zH;onmQ%Sh94yv=)9`lt8?`Y!?ouu&fjK`ozJ(*tve0=6?CvSozDmbHF&{- z3iQ8si6pX}Jemp-WTath%@(9(eeXzFFSu}O>frlbpauhD6nfd|gA&1$_MNCEvfywe zbiGJlE4j=!>{!Kb&k%mt!kD%{vr;g~_ln?I%Vuzct3TL9WJuf(#*DGY4TP`Afq#dw zan^JY5%L6C&wixJ)=BW^k>p-sLloKuHUciLISX4FyOk&SV}{N5o8FvHreFjMi08R}hVNkP# zOUWQH`|zY>$XYNnGQ$2$g^ivJ7DS`L-t|jY7eTF21KRgJ8Ws08BgwApPYvNfo@%`C zF@m&^l0^sb85Lz4&AJM3YFiWyvkA|`^$JYi&)58*rfAU`02bPTV|nIV5Xr9Vh$Z1@ zqIsYo!<>J_M81d=Jw1*C+j-XkMbKkwL8XWcUX)(c-3o$X@16+qLIov%>N`D2TR(BD zjWXVP3p8Q-GmdT!AMVc5(KOYsa~-2i+pz(Wdfx%nl>Tq9*Y|Qq?mKN#SbP8;UW@4E zPJUzwSJSQ9nv%_OC7&d=cGVjSNrlB=F4%>9KWol;`uDF*fKZ2pagJOI9|kR3yeXn? zR37mG!@Xi$bD{99MAsq(+8et4pF2Rx;;rbFAyV3I)ua)0%B#C;?BN0zmUfdLTI(?e zqda4mjvrsm2@ZcD^1or2@DcW}HAhR->)VkcZr8qy_Gol&;WXGW1!Yx}x*m8L0V@=U zs+DOL7uT&V8Hu8X4kHK3RboBy)HhzZZE<-(_z8gKbDT)HnBLJU^1%m_m=7s6?}50w z?w}mnPF&uA?~`RdKbpSgx_xBSx~yXLi;5D{Z&RVfWC}ja3z6wTBCnR>U!ydU27~53 zW6*3j4;T&SLT>Gdxk1L8%t2^OJGO@7Ej1I?PBHx|Y?B-tKoclhF-|)jKM`(LXan40&K_CFutd6&92~UzMwL? zK6?S~!?)}yp>1%H#e1ERay}YB`n)6z$I8JqP&qNi&H-syV3WIp!BGwK1loSk$(2j8 z%u+NIImibTI+y)M3b`&CKJp1X#8X{(417GWe9yN+?&e=0bK8)xSHP8M6)K8-4;S;; z_Pw4-X5u2C1`f0~Q%EjzPH(5EU7^-H>9G@Xyx`8so`}yN?KfFcpWcJOHh=)SVm3%w zk6}70ik9nK9;or$L?Zr%p_l{1?Gt7Dr`QO9IkNfYK{&V*2GNr{#bguo4)#PmoEqP2 z;1nr6LYFTW{uX{)fz=SkBEX(q_mzl1kM0>Eu(jFD=L_ABAQA?0WI~{35V1pT`0t1e zVG6n`0pAa3wMmfIms?2WrE+L#SOvqSiH&ZbMNwJrXM><;SSHAHHkf|44hhotV%$m2 za(+y*JL3Hz>Q^7#J%w$N2m0qNFfqw{PM-BgV92)d? zU7wA*TyNAwM_}kV;48djI@%l+wGzK^%h3Ifz=aNCze9k`sIin1OTuy6$2SnwxL@uDfY zGR~0N9!H;G<0bqQ#M9#9)TNgNofR^I?E-aCb?6_#)+wq1Bv)3Y$I~bBYCer117u&R z71eA9p+)spA$+qN5F$3d(fwF=HlUg)Fv&QFD7uAr-o3SSP(sFRRwc^1LbchltR1Zb zk5E)pk^WHNDBQy!by>kM-pB0m-vyT0(De5=lmsUyZ!_-?SsiKftrxp+mPE_Msw;}; ztP6^Yx%Ae+)+;6^h#cjrAeE@tFB4wL9fkwDIWypp7*P> z79HVFfe@FMRfius760vQy^O3M(KLX*}!IZ>-m{iX@l zn6n7jXx<|RnnGHR6EfGTmC#yL!_9%OGQ?v$y+^O&d0SY>JL4ATDv$B0E*Ep)UNQKj zQ#QYR!Xz9VS4RBb3dl}6i?eB#$UA`yd5heC%#}7gX8g52n;By;}B^X@^ib0Ic zV$x*<=b6arfq_5wr1=hR=TT!=?tEozQ1_j%9zrRU#ZSC*rDqdWB{0mePpirTMb_(x8jBX@3jE1P3V!}mzjfN!+q7VbMYgiPnP7F6;} zfo^(!@EHh&-87}xwykgMch+N-Vj<+QHnrGzhXq>Q_@bFQhkmDnW)VRf{KJAm80k_k z3}!8(obFVnx+BmMNc_f}%Z`^OdpCO8hUE18<_p9yJO?$#ufpVC%DmtF33C#KV*7 zWs#%X+F9`Lg}^r`ZKCbbg>NI1=W%>h$)sPKHHB| zOl{8*a&r_(0Y=wbl*onVM>B`z9Oa*ea&efIpv?fs?L_mN)c3=wvMR08-VyVLi+T9I zn&a`Z8f%lQxB=S2@XSt~XcODFOX23|)#~u~LXxz8Sqy?Ay!Gg2imsoCoeG6^TRT|n zg@ozsP=*I;qeq&QqWA4sN_;tgWGVa~3bWP7KyR<1cEYSl<4 zVdTm1wVCfqugc^qx&~&n5!U^f6OUg4^hxf`^EkJ=%oF8k*Bs@bv^9(vPS;upUYhK^ zh_%E_;=bDl4!Yk)BcC1}29ACN98n!gUQcwYCP`dg!8+$n5V?tNvL&VH4~i)Ofn=JM z3E$(dkmS#pVNF$~RyEl*W684`utn8t!zs>|f0ijz80~F&=WmwxeEGr?ASEiKqK$?g z936*0#ng&=|5m5EMO-NIK9b!OpCkK{jCRly>M;!XSrjKgR?~QstNW*3TQYJuR?-EG zvQe*ENxb&=*lekW>3}r3+CxD8bE1e0<4D1Bhd;Auaz+ZJ6x+%AIO3F!m;T^ADW@Y9 z7Bpmp{azs7Pf{y;vMVB-Snqvjtbk;APTtmr3tT;A2MFGj+3!EL^h#9^iH_!60Pe{*ch-?{VvYVVo-F$ zvZJEtP;dqvwftu%A_AETvT7>~uy zg1UJNqr!qY%O@mX+kNTA>cOlq#|KCw797QiL)4Zf>>W0$Ev*3QyGb@lcc`{YZT>p4A^WN83)tO~x>cf}D3^EF$yPYt&v)J=6@RL0 z%mC1_A=t!>T=+#9jHMW!rMslE?9ky2I}M3EY{X;?>PmOHVFuI9y`u`fI^j>{t9pqx zutBx+oO4^XLP|_B9PBkbPTY8ARCvJYYHxunsQxMb^%LhOG6G2Gh=AnS0 zwp&cTeTGROlJA8nAJ;iJfNDV2%6>ROz05&}qZkB1rYq()H@nbRf!9s( z-t25=q|oRC(!_{J1j3zV=Wme85oGA8oIGjCY+A*$0SG7z64i_fQu4)PwxA{>t~-`T zXwO4sXPK#5_eZpRX%U4YJX5UK++u1b-CL4YM&OwIbZIZ(u3T>2nVJt%*Jnd(NW8zT z#vj}*2B}resQsvkp2E(fwHwd2_F`s7dGVx1cl%IGmOLc6+aZa!NL2|ePiT1ZtueL| z^~B`C7}lBecWa&RS6hCzzIaehtFz_6CqGZS2vrVvfNL%`Q9^IlKpfQ=An5rM)aj}^gP)H!px!S!hzPf`o_scyD8p6@J zD`awp>vekLCJ20h`?R@yKc^Ordm43>Ba64z25+z)GQ)BIHL4vV$${AN(eG+ag#*`&4{otS-KL2%9CNeSGF?XTG6yjyV4n zvg$9W4HkL-tsE=f7>OzZuRfZvo8yLKd%bK&(fOK+-I{jLslG<6WdCk5UG4GFW#_j5 z7b+d6Vo}|9v>ie}AoZ{F0KPXXKHjz1v{CRBvLxYK^es0k5$3A*cWpG2Jbtz9Rsj|$ z!pJUoVo9-A^r^?|wrZ%h4~lsArrDm&2PGaZcyqn%uLw<~P>8R?D3fU-mTbFhr(WgJKAlYyOW2F9(G{g$&6 z<)!y=(p=r_zW|9jFuzG;0Jwp(C7ELa4qYe}4Z8&pGxs33wg29>!64SnD3@7t?frw> z!C$bAK;$R9%y0VOBl z?8YIgun=qI*{yue*M1*G^`Q$TLTr2227{qiw#Unr##^slG%_BmE2}?}{Nar<_dEIW zRZF!qo~7KFnza9~tFsJfYs>n63l#U_uEpKGxH}}cyA^kLcPZ}fl;RXA6nA$B8r)r8 z?wxsO=DGQj4=2glJ8RonYyJL9HTLC#?&4L!eAQv(#$u*Xur!J-q5mWRo?D)N<%xR| z;^C=OajVUe&4HdnvYLHwm1MqFFZ3+cBVYZBSxY^7{Lse0ac|Zrh9PmBEWx?s27LEL zL#occ?Oj$fM)d|59xVP#uK1A}H0Frl02%^|4m@NBz7V2!_F zj%7}(`@7IXBIAY+UR$x~itF${gHiCJz-)U)3%|%a#`zDtT8*!GNAF*u$X3LdQ9u(t z(J&0ZOA%DQkfIZP{3TJUif&UyBh{|SVRz$O)BoAQw8Wxj&Y)}N4B9CZrNa|1GgHYaF_^X8&5NnB*p&{WjpyAidRV2nZ74k{<^TS4= z+dkmATSD~FwW-JaY^=XY7sevSN!8YUqABM4>jV1f!DMI+#%%8QVeHZ4pq;ZmaaT%b zR5ufW=Swg`%h{Y_yf7C!ahpzXvt?K~)|e8R$(*2JwXx+)&G@dy%?N)Zfjy-b=cVb3 zw$g+U0$-Ub(S9_%M*yf7*S{@EULs1T@$fNlZUoD4NEznY{4ff3ANuV* z^@eWSw{!r&pe&eid6=S5R?!8jmzxn!gzdUt#L{uQaB)8$%G?a2@3`I(Tjel?UW3u9 zq)|q=vytI%!PQoAoGKG0fBdG>mo*%PFi zrEUHI#~D6D)*23UZnJFFnCS2nQ8j>>_)b!qFV69QOt$(UP=-Og^GWk z*K94`ugFmxuLT^OKi)rN-o@+qapxT4kDLV4hqvEbMeE<8O03$^}vZ#G5LiqA~UE7U|$`X zBg8rw<_b8w4g@A>_yTS8J z)i##>|cN_V&qgP&O8~ypqOZ|;YjKD2Kh_ZgJ43w6B3iccD+ZQ`F6bBVL-Rp zK>3VuvD1SibmNh1nG30B%VosDXvIkIu220i=B>}D#cT}vdM6gWf|iag-k5Ze)#B#1 zX|o5;&5`7h|4+wst?1xa$FD!21z&y44W&!+WtB76x!!yy1+S z%Vpko+XaOpcMr#f?2E{7>l-Vaw&9P@xfa3VwjT9ViyIL5+3Ny?pn9>x_XBN&$!BSJ z8f;aEKd|Oy&umIf5vR&>N3#Cwm3zY$6ZUKsdzrjb{usp@P(5W5$h!aqh06yz`SxJc3iyjzIAOZ=~Tc=Xglm#*(to( zZNz-3E=%;9x(@IHi`k~Gmkl}QYKJ- ztY5MwMS$Ut7oBjh?1<+obS0g^=tzF2RN4w%%WD_fhAs$VPfc6T1S~7G=E7gQF0-|{ zwv`;AwZw0~4ul&VM{NYBSkIG1xO+HtE#f>@4_q#x)_zjR$(rsfwliT_UDh`zA0a0Y zeH2rrTJi}vg~{TOUhKk-7%D%9x9I+4hIS4L`!e0KG7#%CFvZA=chk}yCO43_XHK3o zVe;YbW9+7l^c*94pH_u_&P%Wl-@P4oc=u##c+4&`_Nt`Y(I1Y*IvOJJ-EoUQZi;d? zTyr_a*(SvVJ+YAG;YAxiYe&DH_mkX^PN+y}XrJP*Vo)hk7@Sn7FM3f#=!@(I)(jlNk z6BbS-c}XwaVOG{|#TI3Zf?v-=R1>rFvB)xhEtW=k3NFk62M#h9~usHGF4F(X7KWXU}tu=k}&_s;%Nd_jSP;QCi0{DKv z&$ZXPk6ZOgQw765tybr?)kKf0AAYTgpwuW?DgKPf1K6|l7MxW+iIEM7Vg1Zk4s2x- z%n*Sv-HL1&u7@zWAhb?tb0nd7i+H8b8c${0HEbkJpW__X|LpQv>fwVw9b9JpH@o89 z*o=|&PN>jF+{(?6*`W_ISe39~RKk9$BpQq&vvl<*HQTSJO6G^uE=pvMhjtAzfm0H6 z7ijz#dJ=fjR1YJJD1o^x?-&-U0L9(v4y5~D?9tS2XnD(Pq#pI&!T`5?UdeTF_3%Oi zx?63ZI#4JS*p(h5c+y|mTGp^0EzTYIGg%lqaaAkzltLw~VKJsJN_AJ|&C$+~j~o>~ zt)et&L0sPh5MA4{q}FOHS9+*D*A>7r$CXKCoQoH|pB6PjVPuNBNN=Oa%ADF$I2(~6 zo`(<;ud7KwGtmTPX&u;lpz~$^K$XZ~TcBVWYlO~4ilkgTd z5n;rLjJhscP6u$O)n)HV42vDk4m3?M^EO=)?H0TF=T@z}y*!zpe4L^O8lOoA98FR7beJZaw}_T}Q7JpkGdD%7-Ve-tu5|0_ zGa9HeiJrfQ*gOUg-D*z5Md*;`^j|+Dk9V@-7f%qsm2Yxt z=uGyAmH7H4OYDqTx%P-Slm6Vk6)zoTevcs!R{ZISuesdLkN=>o!Hnij`TcG*<&Ol> zA(pf!jpMETvRYG`5fwv^V0M=VNSEy@Pn6O})UW1R%kc&>Mp=aKvB=tNBd89lj z&Ou3`+`C1vNc4#jw`rbCQC#ZF z$x-OtZh8{8gonwwN!HagZqRVrNkF<e;bg~3Z}+v?nMv8km!NL;@n@YnHte$3UEw-b+8w3|8S{U!-s9K-2r@b; ztcRbzm6@XdY15mRpi*AT&u$_in>aOFYfw;Ro)C*Z>8n7leC#kQRr7g?iyKA0h%*KZ zltqZIc`PtWu5qi8t3UnnA(~ch@N<|pQd}L53uiM)$q@;9P#pE*0&w1Tryvkr>fljQ1a=*>#DFOD?QwqeRA1V zebTZOFi|olKD2@r2)Dd5cwR!0f={&w(^hP`;4H#UCL)xrJt z`4Bi4Q3r6^0alu*J2a+LVX;1{{To($T|jF&$69!E>3aYls%4!hQ5gR+-c@U& zMgAY$EK3N2V;^}!KPUBn`1^kgSIMGI_T4ZAs3ZJ?T5EY%x&e9Sqs?9Z0}gyef5+Kg zWDVv-{(;glvcF@RdKO|o`Tuj{f91b*LH)(Kp=Htty9DCo7vS;)obwj^!V{V~4U>wENk+rlLeIkP%zt^>zqvv$s8bR zH)SH59pRN4fc|M(;i}S-iOP62bKg3H_jciMSgEO-rRloj0%~+3{Qdp$YCe%kuEL9@ z61)Ln4!@;tZX6yO7(FW=k*u?WmREibJAXbu^kLZ0&fYWpb>r&N(*UUFHkU{F%hDNd@!r`O9kG>!6*24nri@d4-Lu&fLK?9*_(6{`&Vv|lVasGmk>7fXESKwHn_}&mpxE??` z!j&&9Ms?-1pKmA2U-TyncR8Fja$G(&SLDHjvU zE+*?Kx`#wOyS;sIZ7x$*`l)ws523d5&SBUs+SsO&Y_n5J<@tVe@F?x94a`2R^uWUZ zAG6(W-=M}bTQUgiAL#65U~~b1(9L+%(JY?NQP@m?8YoB@WVP2iFc=K)5|oA0Ct6Ik zP?vTUrmi|9FBY3nlTk&DE(*|A%@GbAwce}UQT3sBpvV?J*vWg$$yavqox{sm{c^HM z6y1IyaoxJ@a(y5IvNC)ewwMEt(#?T)2VVi|%0J$eswyvse$@7`s zpE%C_n6MWOBro^ARqKYL&dI_$@~vjx35I?)Idt^LtYx^Rc7*avDj()mTySY+P`ex$ zM0nk)LA2G~^ii4sbscR%tk-kGz~!5M|ET5i)uOyAE z9nmJw+zvqM)J@9jv_X zX=`t<4ABN{cs}1dI3F)g>B(geaN1>>(qY5*GEv(LrwQ}ZmIbNzyXDP|EiEnDRg!Qa zJcygxU!4cnHk(tzp&=9@na(@5v}t|Nrcp54kAH6YJ+UC$Uw<}w<RZCLR9Hg0@+lQ7x<50vO*sLLeL^z@@7#llxN}|r1J}i-LZy%aeh~VAf zV_=A1hhnz+eC$jh=!h{8OZ2Bci#50nFz~}2CU2u|YBSVYPUa597bX+8k54M=!@yV+oca`0OQq_Ujmp5V&1aK+;lHv zX1}~b3)7o>jg5~6SEKu(QKf$SQ@}X-eL#WWSh_5qY9<9JrI%W9U(oEM#9_!3#Z{^6 zP=thYW3s32GZAmJM|CGFJ5mO}@(DjQx%x53C-(8b8VGL$5OX%0iU%aw2DN&f7%UtS zl}lSgoEn6@&Lk|()f85tlua!yI9_+B;tMspbI1_dO*R2tU0sPuiHU)$tE)3sMy^Ga zn$qs4;8J_)YN$@8_D^>@e6aY~z9HpjK2h)+d*4}YS+$^24PJq{TS-iNWISvr0m3~8 zT#kr#1YVyY1hVSvdd%GohEW>FW5j$x$fMega5s=IQ)dnM_A`sh=k?q@TFD_x`rhH+ ze03uGf+^ggIm9ZPvK=OT+(;WtMb#OTI>PNlXlbROt~}HdU0~0;ULkySTL_SA?7~m{ zc!)agBru4VLaB)T5G{#p&p}ZW`J!b)!;VQ8hdbshLW0;yRPy4r3Wo0mstH2;XsZ^x z*og2szlrK8(`4!JPqv9-@VXs-K#3y1{iYc!K&8u4^^J?;hRMWktyh0@x{*)|s>PtE zVE6p|ru%v62aEe+e_eb_YT7QD?{6!cxH!p#G29sKMv1c)qVp^J{M)b7uP5&%1R)*M za|@&J$@uQR$_>m@oEXKd`ezTwPSFn{$)?px-1Pv-OI%=)PgkR3GMl$egwdWM@bhFB z?80HK4N&>D;hJo9!sJ(O^JaUH2+6g{oBQDX&`a7x^Z>M+wy|N&&Dc898S>K%+KnRO+n8 zBo0l4M_jW}7dqKivkB|Gu6Qv#Li4=TtO+(I90`ZTHNvr7?bc*E=_X04C_$dLVgkfm z6vrA-3ubrFqPO_#`$q1eUSzxZmLuNbvFdKqtZoK05W88};@MayaREYz&| z7bPQdw?F0Ss+l{VE=G#2Cv2CA*yuLnX}c1B#g(Mh3y7I){ze=O{WM3N#?G@H;o?iNy8`pJVT z&Uo%Jh1-!#wHU>A2^sq)T-+b13pm27JNo>elg)EAERI>u)u0M&g^e*~*QFwT*(F`@ z+{}z>_DHP<{hhbBH;Hde^M-HxG7%jkBeKxDt1Hs!i+Y8WgA$vL=f&4iN;LPoD@~0? zN1i?37s|cSC$twPq8O~3)$=3sZ$^EKeDP;Hak3J~Va-lxM6E7}dQaDqDdM=&;781M z=9j(9I>G!8o$WuVEEW2LJ~Iwn-aM&ioeBATURb@Pjx|p)oc(T%w$u$N)Fp%qY3GA1 z$qHZTjU~=B;|UZ-&}7aavpn*adwJx7;<5`C(Xz?)vw+Zh*fGE7w2Cxf!uNgl=50D- zzU0ZVhjP+?#TgiewCqF%cp$u#vrld<_PBe$?(##0{_LML{QVxyp$0HL;$C=tR$r~! zmX?wl&!bez##>NHjL%5;gwpku9mN{fIvt5Yt2wY1MhHtd%3S&Jqs>xM`1h8N2UD#a z$aZ=GHy7>d%iB+!Tb1AZg53%MIGo+Um9I)X+Yp7|}8e$r*aVi?i-wxcT$EJx}CPsKJ~eYRxXK6*`CO@iPt z_Hz0%Ol9p!eq#8*Am{n^-=7Td-21E%iQOCoedjb>>;Sph2-)il$q9MFN~$8Jr6wkN zAFtJatmHZq&RpaM%^|~GSl644C}47Noj@T|6;F9;$@e-<$8C#wep&5!ne6cRoTyBf zk!S;xB!^}4WoxCjOG2w0{}CB4uq+&v{tc{6zh*JG(r(G)yOH6~Se3c;8@hKPH58Yv zOWe~}I)!qUn%u&2yc=c1JGL;S=77%t7W(=$prh~P-sM4SkU+{(k9N=J2`SbDm4x^cn=#r+!{ZD2exig4c>9lV zO}9{Zw}+;V_}O6`EKYWlG~=$P?wv^nz}vv@?ZxfqfOV-tc3ldfs{QO2zR+KBXq$EO z;NNxTAJ@Wk1DbPnB51B$LHz@{!aYOTEw?>D`xjG(x?Ku`+tqJdi)~z|J|GXB)j|$r z8yzTXS60E?7syjQJ}A3W)_gylHR6m&%Lze$gMFQj+fh-CRx9#`$jkWLbbk*vs@^VL z6#mC)>y|1v$(<6SP;3SxRde6)6#PFuwc6a%Yz>$WObj&Y6mva8Au}TpgDzlckqcH{ zN%lSv5Ao*3XK9Mujm=wYXoG|Bk@IPD**ecBJsrLdx>&-c*qGV95W3Jj2YWP4L*7*QBUF_wbwlNHR z=xCTTxUV%jS*8rdAyfFGjJN@lUwcR)aKli@IH+==>Jcw8Imyawfrz*`FcOkDy27-P zj#5=kn*}&py6MD}g=go=7F1&G6!-{$8gY|aL!9-2$$F0{B@CZimfIPXHTLe0nawtm zY3siaO08M~*^zHc->z&Fax-}so;l#Eep_N`N-LYz;|^ceyY^eLAI*NQ7CpMC2+(D) z%(7w%Q~Yg@-qUmLG^;H?kpk#; zb0?$+JMQZU^sCJE&<+%ZiTRZ7$7tDS-G0*oUZ8o28|t&J&Qy)Aw#{lI%t;|%;jc6V zz}qFc%}2DB%g6*9MY+%G5Ja)28g<4@o)XQ)+QL|?FGq!%?oiM7Q>}lHL?$hc7$vIu z*FD5n`7@fpk?$*Tp^fMU=(_O!<-<{;9`3;HSziP?laAY5zXitT$2x`Xu+cT%)gON+_!x$6ycY>%gv%b*p^RCKDXg9?FUB$;>v$z~yemq9@ z4+?(Y|6*9*1>F9A{Ph`;kU)Utb{wYO`|4&egpZZrX}jL*o4<1>xIBGuf;%`W@=Fq2+f|`Fjz=);uWc*OKvKS-HlUf zR>XZKNuMc4H?jMsuc|Ew=P(6)0x+#P$-z7Qi$CP)ZF3HYW)ghsS#eOC;nSfxVMVvG z2oLr2*N)4 zL1nNk4rCE%UGn(VQQ%f_izQyQ1VE+w?T(Ac?>c6Gz&x3jUH`&-zrY81(P*YDxFtFU zH!%kVT0pf{4Nlq73h<$D`Lh&xHstVuDB)}wONW$}dR}G}f{*dbOGpboBr^=i z@;(RN8$@i?IOV8~OYe&`NirG7g4F-)(_vA}en4Q{Fi!CcUHzf-QOrj@_C6AY#z5Rm z56uGSPwLM~0|o|V3LY+oBuMgCV_lAXQ`fb-sPiSs0n2LJh?0Eysn8lIy;DXRsw>=t zXa46P)D=o}$=h%Jv2sl@qlh;XYt12e+&LzE$Tq7OH!alBU#vLksoFx=gJ$*+n{e?J zST{W7dzB_~Z3FgA4z9P&R?c08?G*BT0{)#>^|xQg;jgFE$Q!l5rSyye$Icor5H?-v z;_J)P%rb`t!)YS>OsOI;s-th>#wI8Qq1S>xI0%2pMw$ga%A=Qrpr&{DBvDFX#WgxG zE(uBDI*NeT2m@Z05Djz^NdaqMp6{Qa*)50y%;fRO*{k3=U| zjP1u&Kn&1zm+TsAX z0ZQfI!?i?2B&$2u)Lb2cfRq)yB=u?HCh!oDY?^YWWJa4zlw3gpT^=ROCVGcywsOyT zg#B7_xD8*G%}60K8~=pw)m&@t^|o^AGRHzjiAu&!Hb25**=;~!Z%DLUH^`#l?Nnc5 zEs-%D^%;6|nG?b5K2Lrrpww!P5|aQi9uFCOlFCbDrDoA`-K9Lt8!xXr*4vaTH7KOP zp^U#g_>Vg@z>geaUtT9FGIBN+qTySmb5VtpnRNfKnv#-|u|sM+Ac6^@Zn@Di2u1Mz z!yc&WbgiA7f#D>M1s#F}F+3_t(9;LLsg$oEL7xRe<_?rT^wzUL-0|U!gxK|3-hp{7 zQZGm%&+ABHP+sv*?AntuJVFP*ZgPkmYvp0#iE|owq5Fe=uruS^(cR6 zv8+X?Y1zI$3b{n=pUIJ0;N#$-{ZhWc(=zd7@EsSuR&WscQ=a^c=QT{s!0ibP>RJuT z;Z))$7?f)~ZjAdK%+ZGe#CBi3uuLHz8F}(35$Mn_Q$qu{*?d!EO-zi$lj^%j7)C1< zrlSiaX^eJQ8WCMX!?YG0W8))|@k0$Eaq-c-Q8eiRi4SQ|!<#gR8DvNN=s*~t9ZO0= zc6CkWuXamm$?_&4er}%})pBxD)gB{gO9`5cvQ(ApA z_QQx5qzP1D)0M%YF;OK3;)RMnSC|UjrEJ-3>Gf7H4fl6vblp%yC^tgY;Bgy2*QvRD z+FSu*V{cJL6xtw7BAyguFIufNrO`#l4OsZMX&rHhIZSKP1}DcQXgWzAM`dV85nmqE z0#%qSfg{q>0wQ(R21SD2^&K*e;ix*>8HIaJi=Y|-&vL)ka!F?Ec>)5S)co+ugvtc3 z%bvACSNK0M3;Ho1P_`Y`Q$1kk+1sK}wSiiePI3E_1L+~P1VzPE#9=X?oHq@6Q*5c8 zq_A=q99w`|g-%X02|4ECRQ0`w|1+e}Aoj&|`c)d8!77b5ODdW`d0BZwL(+F&ZQide zN`(60IvLa>05V*HjaSN;ek(Q}UIpwx28VV0cPXLKvNE<_@*>%`_v{qEfPwYzAvr)H z|Fl!wfN%PK@ZZMV(TH!Nev2Bz7*hBcmddfA2R5nJ%wmzVFjX|ds zK%ricaf2c`pX8TosYNVoZ_Y#6GpgF}FU`e?`~or`oaCg%5?vuERBsVL<~oRu;&oHo zMVG~~^l;e}q2+p%H8Uw8rKH2InfJEQ`GF1x7C)!YQ%`5#Hg=rW0q&W`Wqh_7m13HB%7J09U-|g@$Zz@CMsP3oZZ^fk)WVNe=Nchl8 z`ZZS?O&zQ&rDE~Mbj_J6sb(plx8?TvJnCAuXOc8s1GL2yOr@xBosfz~ajBRHOQY{) z4O%_=kQkJfFRz9Zca$WA$D0%sx9zzXrfgf5C6Ia%Z4s#Lqm z%x6?`exZdf3ZNscXAMWe1w>49!?gWHk|(?FuaHEWcmJTxRZSO)d|C#xiyrBocN5Mx zz`~YP35;pKM~lzTPiI|MoFFrS7$$E<;ch~s*fQW$SJ;`zRie=I3vm^>(0GlyqC$&Ze327wJ;hHxaEDjVR1oX$C?xe4q z?=!Frf?m4`v7CmctT0X;&Y6 zHK=__OGlUTRP|I2533o!y_;E$UAIr@iK=ml{_El@ibT46A(MC`DGX8LvdF-R?FZnm zz{Qo5`=wibW34?zn}>_qx{FL%TxnU8?5|p`XnJ}Vv^S=2{-#Wwp#_@h)08XIatgDU zVuy!)5N*1=_I1c}UW^EZy`#@YZMHIEKHIoD-&5j1&mQ03;{2v$MHmzkDT>Ya^NQj< zqd!JiH&7uh&6I2|<_hgRuU=nof;zl{1f**nE+VAt`)G{|K@H{(?E`V!KhFvS^hh45 zDJL?X*s)SDD_JB4xD&*H(xhNB#NpiP;0gVx<@d5tq=Lwu0xue3cg9)}Poq(?TYT=Q zFzYLlX*hALWhIi{V#;G=2^0ONSE(s#JPDhgrRKkX*K0@{a~0tB@q)pD z>rBq*8;y*=xGig;m7lW@WD2&@ZxS(O&v0TlW#Nji;n97|floqb(Wh7;_ zCeJSny)Q3Nr_D@^PYHgFI^>8j>C)KkOfoE%|NbcztthOijGOAV-c$cb-Xhky_4-Rs zZm2qsWmQB>vfpUyN_I;9D*rM$;j8Y}>8TzD<2`!JAOsN=H|o#Z#ap?yb6U#>E-N8- z6a}IOsv@(3EtYPEPwZ#Tg*}4>`{g#i8PMB|1M+>!*^71il zRG!s*Zl}T5q<2@Bmw_%76%}=MYrK>Z479ZH@tpXou&G5J2wXZ00a3+@Dp5)r$g|Z( z6h;BY7n%GDzvhISWgQ~EbCQ2{o*EK^!zniPJ+zQeJyV{LC%AdC++*|%n;JfshDX_g zMyj`)nxxJsn&smlj8K?X3>Z6HJY+q${KR?wLnt{@&(yi@$I0{VaXP6gu6^KGed3yAsNRlagtk#n=pEXR}8X1 zp#mn{%o<)aM*%&8M7k;`Q%cpxd1xnEk%R}`vS8Ofo z26r6rz+4m*bp{z)oFPlF?AXA^9E*|Bxf~?;@4i6399$utTdWUtqhRrzn%PIkG775x zl4?L^$6Ge$Yc-1rvRsXz;*Tx;9JwZzB|fO zHiC&c@lKX0Rpl^H@(8vNa6^2GZ3byu1Afc@#Fg$`BWw|l@I{QdTP14tY~8eQmz>bR zWFvlG9sPy7Neock3t;&%90U~CM#gItY}{QSd3kv^Z#*&6*XoVKSbrr-Y083O8XFsv zcl;R>q?{`&D^nWPi|Rzwc608XPfkw(r}g}*B?hhv3ign1><0&9>w198;Dq3B?Fqxn zM@wBBmB*czCobeZ3&C&0LQJ52p%*wjM!l~mAsQDVJaA3X;;-tVC|^|CZ+*wy z{@s6OSbjJtA{q6sMXA#KdM@p2sOXh0n!5-3oPr50GU$->*+o^WnIeI-(z6K5%gbtI zz_bx@>C|GbvJt-w>-!Qq7w4So;-nq0_fS+L&&rjvrWZb0!1P1g+PQTZQWVCZk5_gM zGVkw=cIRvmt1c2^>AoN=5>A(=?xqgzqaA0539I4{u>qYT|}qW9VwhnKAS<%LI@3zN%m>v12VYYJBymf@;T zEP1Z#tUR#Et>?DR-X9R3Jj+X1v7>TnDJ@eR0UK?;b+u0d$FSSXn*TLF0W5!V-_136 zW-#AbExLl!b{T3)@jd>|!1--mj<8LZnvoHJR^Mc|RuQ`=PH4~{i8*Xf$Hj%c(q#L) zMz=j)B(OdEwC?iiYI1p5BJ9M8EOB_?>Gf*QWRV6174FE%K)^%aF*(KI z$+lq`Yebq%$mL{ZRsG`d#O0%jUD^xF1w=I@XJ&BTj9HFspM{LsME~wJ zGa9Np35d4a;?gQ@habMXNcYE(AUuUU{(p?b{C=SMgAIWqr}GI~lyzXii1`Q0|3BmW zHH(=u&~UJHo!L=lqsQK-^j{zU`~2fCY+yuwF0?Vf>{D0j? 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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 4710175a1aa0bf25bb949b6c0717ed6a9d448655 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 13 Mar 2018 12:57:29 -0700 Subject: [PATCH 0144/3174] remove dead links to Java 5 this came up in a CI run for an unrelated PR, see https://platform-ci.scala-lang.org/scala/docs.scala-lang/374 --- _es/tour/generic-classes.md | 2 +- _es/tour/variances.md | 2 +- _ko/tour/generic-classes.md | 2 +- _ko/tour/variances.md | 2 +- _pt-br/tour/generic-classes.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_es/tour/generic-classes.md b/_es/tour/generic-classes.md index 949baba87c..5236628353 100644 --- a/_es/tour/generic-classes.md +++ b/_es/tour/generic-classes.md @@ -13,7 +13,7 @@ next-page: implicit-parameters previous-page: extractor-objects --- -Tal como en Java 5 ([JDK 1.5](http://java.sun.com/j2se/1.5/)), Scala provee soporte nativo para clases parametrizados con tipos. Eso es llamado clases genéricas y son especialmente importantes para el desarrollo de clases tipo colección. +Tal como en Java 5, Scala provee soporte nativo para clases parametrizados con tipos. Eso es llamado clases genéricas y son especialmente importantes para el desarrollo de clases tipo colección. A continuación se muestra un ejemplo: diff --git a/_es/tour/variances.md b/_es/tour/variances.md index ad4a8fc3c2..e437375545 100644 --- a/_es/tour/variances.md +++ b/_es/tour/variances.md @@ -13,7 +13,7 @@ next-page: implicit-conversions previous-page: unified-types --- -Scala soporta anotaciones de varianza para parámetros de tipo para [clases genéricas](generic-classes.html). A diferencia de Java 5 ([JDK 1.5](http://java.sun.com/j2se/1.5/)), las anotaciones de varianza pueden ser agregadas cuando una abstracción de clase es definidia, mientras que en Java 5, las anotaciones de varianza son dadas por los clientes cuando una albstracción de clase es usada. +Scala soporta anotaciones de varianza para parámetros de tipo para [clases genéricas](generic-classes.html). A diferencia de Java 5, las anotaciones de varianza pueden ser agregadas cuando una abstracción de clase es definidia, mientras que en Java 5, las anotaciones de varianza son dadas por los clientes cuando una albstracción de clase es usada. En el artículo sobre clases genéricas dimos un ejemplo de una pila mutable. Explicamos que el tipo definido por la clase `Stack[T]` es objeto de subtipos invariantes con respecto al parámetro de tipo. Esto puede restringir el reuso de la abstracción (la clase). Ahora derivaremos una implementación funcional (es decir, inmutable) para pilas que no tienen esta restricción. Nótese que este es un ejemplo avanzado que combina el uso de [métodos polimórficos](polymorphic-methods.html), [límites de tipado inferiores](lower-type-bounds.html), y anotaciones de parámetros de tipo covariante de una forma no trivial. Además hacemos uso de [clases internas](inner-classes.html) para encadenar los elementos de la pila sin enlaces explícitos. diff --git a/_ko/tour/generic-classes.md b/_ko/tour/generic-classes.md index fbca0a9dc4..fa4eeffb8e 100644 --- a/_ko/tour/generic-classes.md +++ b/_ko/tour/generic-classes.md @@ -13,7 +13,7 @@ next-page: variances previous-page: extractor-objects --- -자바 5(다른 이름은 [JDK 1.5](http://java.sun.com/j2se/1.5/))와 같이, 스칼라는 타입으로 파라미터화된 클래스의 빌트인 지원을 제공한다. 이런 제네릭 클래스는 특히 컬렉션 클래스의 개발에 유용하다. 이에 관한 예제를 살펴보자. +자바 5(다른 이름은 JDK 1.5와 같이, 스칼라는 타입으로 파라미터화된 클래스의 빌트인 지원을 제공한다. 이런 제네릭 클래스는 특히 컬렉션 클래스의 개발에 유용하다. 이에 관한 예제를 살펴보자. class Stack[T] { var elems: List[T] = Nil diff --git a/_ko/tour/variances.md b/_ko/tour/variances.md index aa0c5102e2..5e0a4d82f3 100644 --- a/_ko/tour/variances.md +++ b/_ko/tour/variances.md @@ -13,7 +13,7 @@ next-page: upper-type-bounds previous-page: generic-classes --- -스칼라는 [제네릭 클래스](generic-classes.html)의 타입 파라미터에 관한 가변성 어노테이션을 지원한다. 자바 5(다른 이름은 [JDK 1.5](http://java.sun.com/j2se/1.5/))에선 추상화된 클래스가 사용될 때 클라이언트가 가변성 어노테이션을 결정하지만, 반면에 스칼라는 추상화된 클래스를 정의할 때 가변성 어노테이션을 추가할 수 있다. +스칼라는 [제네릭 클래스](generic-classes.html)의 타입 파라미터에 관한 가변성 어노테이션을 지원한다. 자바 5(다른 이름은 JDK 1.5)에선 추상화된 클래스가 사용될 때 클라이언트가 가변성 어노테이션을 결정하지만, 반면에 스칼라는 추상화된 클래스를 정의할 때 가변성 어노테이션을 추가할 수 있다. [제네릭 클래스](generic-classes.html)에 관한 페이지에선 변경 가능한 스택의 예제를 살펴보면서, 클래스 `Stack[T]`에서 정의한 타입은 타입 파라미터의 서브타입이 불변자여야 함을 설명했었다. 이는 추상화된 클래스의 재사용을 제한할 수 있다. 지금부턴 이런 제약이 없는 함수형(즉, 변경이 불가능한) 스택의 구현을 알아본다. 이 구현은 [다형성 메소드](polymorphic-methods.html), [하위 타입 경계](lower-type-bounds.html), 순가변 타입 파라미터 어노테이션 등의 중요 개념을 조합한 좀 더 어려운 예제임을 알아두자. 또한 [내부 클래스](inner-classes.html)를 사용해 명시적인 연결 없이도 스택의 항목을 서로 묶을 수 있도록 만들었다. diff --git a/_pt-br/tour/generic-classes.md b/_pt-br/tour/generic-classes.md index f892ed9514..4a31269598 100644 --- a/_pt-br/tour/generic-classes.md +++ b/_pt-br/tour/generic-classes.md @@ -12,7 +12,7 @@ previous-page: extractor-objects language: pt-br --- -Semelhante ao Java 5 (aka. [JDK 1.5](http://java.sun.com/j2se/1.5/)), Scala tem suporte nativo para classes parametrizadas com tipos. Essas classes genéricas são particularmente úteis para o desenvolvimento de classes que representam coleções de dados. +Semelhante ao Java 5 (aka. JDK 1.5), Scala tem suporte nativo para classes parametrizadas com tipos. Essas classes genéricas são particularmente úteis para o desenvolvimento de classes que representam coleções de dados. Aqui temos um exemplo que demonstra isso: ```tut From 202dbdea08110e9de7725fe2b66ed0423a98adf8 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Wed, 14 Mar 2018 09:06:18 +0100 Subject: [PATCH 0145/3174] Tell htmlproofer to ignore 401 no error status codes --- scripts/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci.sh b/scripts/ci.sh index b0a3d2be09..8721df92cd 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -10,6 +10,6 @@ rm -r tut-tmp bundle exec jekyll build # Checking for docs.scala-lang/blob/master leads to a chicken and egg problem because of the edit links of new pages. -bundle exec htmlproofer ./_site/ --only-4xx --empty-alt-ignore --allow-hash-href --url-ignore '/https://github.com/scala/docs.scala-lang/blob/master/.*/' +bundle exec htmlproofer ./_site/ --only-4xx --http-status-ignore "401" --empty-alt-ignore --allow-hash-href --url-ignore '/https://github.com/scala/docs.scala-lang/blob/master/.*/' exit 0 From 7f6a045c1ce7345c7f16e2073bd4df343083f9b1 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 17 Mar 2018 23:08:54 -0400 Subject: [PATCH 0146/3174] port compiler plugins guide from old site http://www.scala-lang.org/old/node/140 converted from HTML to Markdown using pandoc and slightly reformatted subsequent commits will bring the content up to date --- _data/overviews.yml | 11 +- _overviews/plugins/index.md | 343 ++++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 _overviews/plugins/index.md diff --git a/_data/overviews.yml b/_data/overviews.yml index 326449ee54..1df1f4a9c3 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -63,7 +63,7 @@ description: "When two versions of Scala are binary compatible, it is safe to compile your project on one Scala version and link against another Scala version at run time. Safe run-time linkage (only!) means that the JVM does not throw a (subclass of) LinkageError when executing your program in the mixed scenario, assuming that none arise when compiling and running on the same version of Scala. Concretely, this means you may have external dependencies on your run-time classpath that use a different version of Scala than the one you’re compiling with, as long as they’re binary compatible. In other words, separate compilation on different binary compatible versions does not introduce problems compared to compiling and running everything on the same version of Scala." icon: puzzle-piece url: "core/binary-compatibility-of-scala-releases.html" - - title: Binary Compatibility for library authors + - title: Binary Compatibility for Library Authors description: "A diverse and comprehensive set of libraries is important to any productive software ecosystem. While it is easy to develop and distribute Scala libraries, good library authorship goes beyond just writing code and publishing it. In this guide, we cover the important topic of Binary Compatibility." icon: puzzle-piece url: "core/binary-compatibility-for-library-authors.html" @@ -137,8 +137,8 @@ label-color: "#899295" label-text: deprecated -- category: Metaprogramming - description: "Guides and overviews covering the experimental reflection API introduced in Scala 2.10, and Scala's tools for metaprogramming (def macros, macro annotations, and more), also introduced in Scala 2.10" +- category: Compiler + description: "Guides and overviews covering the Scala compiler: compiler plugins, reflection, and metaprogramming tools such as macros." overviews: - title: Reflection by: Heather Miller, Eugene Burmako, and Philipp Haller @@ -225,3 +225,8 @@ url: "quasiquotes/terminology.html" - title: Future prospects url: "quasiquotes/future.html" + - title: Compiler Plugins + by: Lex Spoon + icon: puzzle-piece + url: "plugins/index.html" + description: "Compiler plugins permit customizing and extending the Scala compiler." diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md new file mode 100644 index 0000000000..9fce7eaa67 --- /dev/null +++ b/_overviews/plugins/index.md @@ -0,0 +1,343 @@ +--- +layout: multipage-overview +title: Scala Compiler Plugins + +discourse: true +--- + +**Lex Spoon (2008)** + +## Introduction + +This tutorial briefly walks you through writing a plugin for the Scala +compiler. It does not go into depth, but just shows you the very basics +needed to write a plugin and hook it into the Scala compiler. For the +details on how to make your plugin accomplish some task, you must +consult other documentation. At the time of writing, your best option is +to look at other plugins and to study existing phases within the +compiler source code. + +The command lines given in this tutorial assume you are using a Unixy +Bourne shell and that you have the `SCALA_HOME` environment variable +pointing to the root of your Scala installation. + +## When to write a plugin + +A compiler plugin lets you modify the behavior of the compiler itself +without needing to change the main Scala distribution. You should not +actually need to modify the Scala compiler very frequently, because +Scala's light, flexible syntax will frequently allow you to provide a +better solution using a clever library. There are some times, though, +where a compiler modification is the best choice even for Scala. Here +are a few examples: + +- You might want to add additional compile-time checks, as with Gilad + Bracha's pluggable types point of view. +- You might want to add compile-time optimizations for a heavily used + library. +- You might want to rewrite Scala syntax into an entirely different, + custom meaning. Beware of this kind of plugin, however, because any + code relying on the plugin will be unusable when the plugin is not + available. + +Compiler plugins lets you make and distribute a compiler modification +without needing to change the main Scala distribution. You can instead +write a compiler plugin that embodies your compiler modification, and +then anyone you distribute the plugin to will be able to access your +modification. These modifications fall into two large categories with +the current plugin support: + +- You can add a phase to the compiler, thus adding extra checks or + extra tree rewrites that apply after type checking has finished. +- You can tell the compiler type-checking information about an + annotation that is intended to be applied to types. + +This tutorial walks through the most basic aspects of writing compiler +plugins. For more information, you will need to read the source of other +people's compiler plugins and of the compiler itself. + +## A simple plugin, beginning to end {#Asimplepluginbeginningtoend} + +A plugin is a kind of compiler component that lives in a separate jar +file from the main compiler. The compiler can then load that plugin and +gain extra functionality. + +This section walks through writing a simple plugin. Suppose you want to +write a plugin that detects division by zero in obvious cases. For +example, suppose someone compiles a silly program like this: + + object Test { + val five = 5 + val amount = five / 0 + def main(args: Array[String]) { + println(amount) + } + } + +Your plugin could generate an error like this: + + Test.scala:3: error: definitely division by zero + val amount = five / 0 + ^ + one error found + +There are several steps to making the plugin. First you need to write +and compile the source of the plugin itself. Here is the source code for +it: + + package localhost + + import scala.tools.nsc + import nsc.Global + import nsc.Phase + import nsc.plugins.Plugin + import nsc.plugins.PluginComponent + + class DivByZero(val global: Global) extends Plugin { + import global._ + + val name = "divbyzero" + val description = "checks for division by zero" + val components = List[PluginComponent](Component) + + private object Component extends PluginComponent { + val global: DivByZero.this.global.type = DivByZero.this.global + val runsAfter = "refchecks" + // Using the Scala Compiler 2.8.x the runsAfter should be written as below + // val runsAfter = List[String]("refchecks"); + val phaseName = DivByZero.this.name + def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) + + class DivByZeroPhase(prev: Phase) extends StdPhase(prev) { + override def name = DivByZero.this.name + def apply(unit: CompilationUnit) { + for ( tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body; + if rcvr.tpe <:< definitions.IntClass.tpe) + { + unit.error(tree.pos, "definitely division by zero") + } + } + } + } + } + +There is a lot going on even with this simple plugin. Here are a few +aspects of note. + +- The plugin is described by a top-level class that inherits from + `Plugin`, takes a `Global` as a constructor parameter, and exports + that parameter as a `val` named `global`. +- The plugin must define one or more component objects that inherits + from `PluginComponent`. In this case the sole component is the + nested `Component` object. The components of a plugin are listed in + the `components` field. +- Each component must define `newPhase` method that creates the + component's sole compiler phase. That phase will be inserted just + after the specified compiler phase, in this case `refchecks`. +- Each phase must define a method `apply` that does whatever you + desire on the given compilation unit. Usually this involves + examining the trees within the unit and doing some transformation on + the tree. + +Beginning with the Scala Compiler version 2.8 a new system for handling +compiler phases will be introduced. This new system gives the plugin +writer greater control over when the phase is executed. As seen in the +comment in the code example above, the runsAfter constraint is now a +list of phase names. This makes is possible to specify multiple phase +names to preceed the plugin. It is also possible, but optional, to +specify a runsBefore constraint of phase names that this phase should +preceed. It is also possible, but again optional, to specify a +runsRightAfter constraint on a specific phase. Examples of this can be +seen below and more information on these constraints and how they are +resolved can be found in [Compiler Phase and Plug-in Initialization +SID](../sid/2.html#). + + private object Component extends PluginComponent { + val global = DivByZero.this.global + val runsAfter = List[String]("refchecks","typer"); + override val runsBefore = List[String]("tailcalls"); + // Enable this and both runsAfter and runsBefore will have no effect + // override val runsRightAfter = "refcheks" + val phaseName = DivByZero.this.name + def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) + } + +That's the plugin itself. The next thing you need to do is write a +plugin descriptor for it. A plugin descriptor is a small XML file giving +the name and the entry point for the plugin. In this case it should look +as follows: + + + divbyzero + localhost.DivByZero + + +The name of the plugin should match what is specified in your `Plugin` +subclass, and the `classname` of the plugin is the name of the `Plugin` +subclass. All other information about your plugin is in the `Plugin` +subclass. + +Put this XML in a file named `scalac-plugin.xml` and then create a jar +with that file plus your compiled code: + + mkdir classes + fsc -d classes ExPlugin.scala + cp scalac-plugin.xml classes + (cd classes; jar cf ../divbyzero.jar .) + +Now you can use your plugin with `scalac` by adding the `-Xplugin:` +option: + + $ scalac -Xplugin:divbyzero.jar Test.scala + Test.scala:3: error: definitely division by zero + val amount = five / 0 + ^ + one error found + $ + +When you are happy with how the plugin behaves, you can install it by +putting it in the directory `misc/scala-devel/plugins` within your Scala +installation. You can install your plugin with the following commands: + + $ mkdir -p $SCALA_HOME/misc/scala-devel/plugins + $ cp divbyzero.jar $SCALA_HOME/misc/scala-devel/plugins + $ + +Now the plugin will be loaded by default: + + $ scalac Test.scala + Test.scala:3: error: definitely division by zero + val amount = five / 0 + ^ + one error found + $ + +## Useful compiler options + +The previous section walked you through the basics of writing, using, +and installing a compiler plugin. There are several compiler options +related to plugins that you should know about. + +- `-Xshow-phases`---show a list of all compiler phases, including ones + that come from plugins. +- `-Xplugin-list`---show a list of all loaded plugins. +- `-Xplugin-disable:`---disable a plugin. Whenever the compiler + encounters a plugin descriptor for the named plugin, it will skip + over it and not even load the associated `Plugin` subclass. +- `-Xplugin-require:`---require that a plugin is loaded or else abort. + This is mostly useful in build scripts. +- `-Xpluginsdir`---specify the directory the compiler will scan to + load plugins. Again, this is mostly useful for build scripts. + +The following options are not specific to writing plugins, but are +frequently used by plugin writers: + +- `-Xprint:`---print out the compiler trees immediately after the + specified phase runs. +- `-Ybrowse:`---like `-Xprint:`, but instead of printing the trees, + opens a Swing-based GUI for browsing the trees. + +## Adding your own options + +A compiler plugin can provide command-line options to the user. All such +option start with `-P:` followed by the name of the plugin. For example, +`-P:foo:bar` will pass option `bar` to plugin `foo`. + +To add options to your own plugin, you must do two things. First, add a +`processOptions` method to your `Plugin` subclass with the following +type signature: + + override def processOptions( + options: List[String], + error: String => Unit) + +The compiler will invoke this method with all options the users +specifies for your plugin. For convenience, the common prefix of `-P:` +followed by your plugin name will already be stripped from all of the +options passed in. + +The second thing you should do is add a help message for your plugins +options. All you need to do is override the `val` named `optionsHelp`. +The string you specify will be printed out as part of the compiler's +`-help` output. By convention, each option is printed on one line. The +option itself is printed starting in column 3, and the description of +the option is printed starting in column 31. Type `scalac -help` to make +sure you got the help string looking right. + +Here is a complete plugin that has an option. This plugin has no +behavior other than to print out its option. + + package localhost + + import scala.tools.nsc + import nsc.Global + import nsc.Phase + import nsc.plugins.Plugin + import nsc.plugins.PluginComponent + + class Silly(val global: Global) extends Plugin { + import global._ + + val name = "silly" + val description = "goose" + val components = List[PluginComponent](Component) + + var level = 1000000 + + override def processOptions(options: List[String], error: String => Unit) { + for (option <- options) { + if (option.startsWith("level:")) { + level = option.substring("level:".length).toInt + } else { + error("Option not understood: "+option) + } + } + } + + override val optionsHelp: Option[String] = Some( + " -P:silly:level:n set the silliness to level n") + + private object Component extends PluginComponent { + val global: Silly.this.global.type = Silly.this.global + val runsAfter = "refchecks" + // Using the Scala Compiler 2.8.x the runsAfter should be written as shown below + // val runsAfter = List[String]("refchecks"); + val phaseName = Silly.this.name + def newPhase(_prev: Phase) = new SillyPhase(_prev) + + class SillyPhase(prev: Phase) extends StdPhase(prev) { + override def name = Silly.this.name + def apply(unit: CompilationUnit) { + println("Silliness level: " + level) + } + } + } + } + +## Going further + +### Download the code + +The above code can be found in the scala developer code examples as a +template compiler plugin. The example code also shows how to modify the +trees and types instead of only traversing them. + + + +You can use [sbaz](../tools/sbaz/index.html) to install the examples +locally.  Type \"`sbaz install scala-devel-docs`\" and navigate to the +directory `docs/scala-devel-docs/examples/plugintemplate`. + +### Develop using Eclipse + +Based on a [discussion on the +scala-tools](http://www.nabble.com/-scala-tools--running-debuging-compiler-plugin-from-Eclipse-to21328595.html) +mailing list, here is how to develop and debug a compiler plugin using +Eclipse: + +- put scala-compiler.jar in the class path +- create a launch configuration for scala.tools.nsc.Main +- pass the -Xplugin argument within this configuration which points to + a jar containing the scalac-plugin-xml (but not any classfiles) +- provide the plugin-implementation in a project referenced from the + launch configuration From 7ad140755be60af2d705980f1dd25fcb32e46675 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sun, 18 Mar 2018 00:13:31 -0400 Subject: [PATCH 0147/3174] round of rewriting, additions, and removals --- _data/overviews.yml | 4 +- _overviews/plugins/index.md | 260 ++++++++++++++++++------------------ 2 files changed, 130 insertions(+), 134 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index 1df1f4a9c3..0f091c2f5a 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -226,7 +226,7 @@ - title: Future prospects url: "quasiquotes/future.html" - title: Compiler Plugins - by: Lex Spoon + by: Lex Spoon and Seth Tisue icon: puzzle-piece url: "plugins/index.html" - description: "Compiler plugins permit customizing and extending the Scala compiler." + description: "Compiler plugins permit customizing and extending the Scala compiler. This tutorial describes the plugin facility and walks you through how to create a simple plugin." diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md index 9fce7eaa67..d6cdde9ee3 100644 --- a/_overviews/plugins/index.md +++ b/_overviews/plugins/index.md @@ -1,90 +1,109 @@ --- -layout: multipage-overview +layout: singlepage-overview title: Scala Compiler Plugins discourse: true --- -**Lex Spoon (2008)** +**Lex Spoon (2008)** +**Seth Tisue (2018)** ## Introduction -This tutorial briefly walks you through writing a plugin for the Scala -compiler. It does not go into depth, but just shows you the very basics -needed to write a plugin and hook it into the Scala compiler. For the -details on how to make your plugin accomplish some task, you must -consult other documentation. At the time of writing, your best option is -to look at other plugins and to study existing phases within the -compiler source code. +A compiler plugin is a compiler component that lives in a separate JAR +file from the main compiler. The compiler can then load that plugin and +gain extra functionality. -The command lines given in this tutorial assume you are using a Unixy -Bourne shell and that you have the `SCALA_HOME` environment variable -pointing to the root of your Scala installation. +This tutorial briefly walks you through writing a plugin for the Scala +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. ## When to write a plugin -A compiler plugin lets you modify the behavior of the compiler itself -without needing to change the main Scala distribution. You should not -actually need to modify the Scala compiler very frequently, because -Scala's light, flexible syntax will frequently allow you to provide a -better solution using a clever library. There are some times, though, -where a compiler modification is the best choice even for Scala. Here -are a few examples: - -- You might want to add additional compile-time checks, as with Gilad - Bracha's pluggable types point of view. -- You might want to add compile-time optimizations for a heavily used - library. -- You might want to rewrite Scala syntax into an entirely different, - custom meaning. Beware of this kind of plugin, however, because any - code relying on the plugin will be unusable when the plugin is not - available. - -Compiler plugins lets you make and distribute a compiler modification -without needing to change the main Scala distribution. You can instead -write a compiler plugin that embodies your compiler modification, and -then anyone you distribute the plugin to will be able to access your -modification. These modifications fall into two large categories with -the current plugin support: - -- You can add a phase to the compiler, thus adding extra checks or - extra tree rewrites that apply after type checking has finished. -- You can tell the compiler type-checking information about an - annotation that is intended to be applied to types. - -This tutorial walks through the most basic aspects of writing compiler -plugins. For more information, you will need to read the source of other -people's compiler plugins and of the compiler itself. - -## A simple plugin, beginning to end {#Asimplepluginbeginningtoend} - -A plugin is a kind of compiler component that lives in a separate jar -file from the main compiler. The compiler can then load that plugin and -gain extra functionality. +Plugins let you modify the behavior of the Scala compiler without +changing the main Scala distribution. If you write a compiler +plugin that contains your compiler modification, then anyone you +distribute the plugin to will be able to use your modification. + +You should not actually need to modify the Scala compiler very +frequently, because Scala's light, flexible syntax will frequently +allow you to provide a better solution using a clever library. + +There are some times, though, where a compiler modification is the +best choice even for Scala. Popular compiler plugins (as of 2018) +include: + +- Alternate compiler back ends such as Scala.js, Scala Native, and + Fortify SCA for Scala. +- Linters such as Wartremover and Scapegoat. +- Plugins that support reformatting and other changes + to source code, such as scalafix and scalafmt (which are + built on the semanticdb and scalahost compiler plugins). +- Plugins that alter Scala's syntax, such as kind-projector. +- Plugins that alter Scala's behavior around errors and warnings, + such as silencer. +- Plugins that analyze the structure of source code, such as + Sculpt and acyclic. +- Plugins that instrument user code to collect information, + such as the code coverage tool scoverage. +- Plugins that add metaprogramming facilities to Scala, + such as Macro Paradise. +- Plugins that add entirely new constructs to Scala by + restructuring user code, such as scala-continuations. + +Some tasks that required a compiler plugin in very early Scala +versions can now be done using macros instead; see [Macros]({{ site.baseurl }}/overviews/macros/overview.html). + +## How it works -This section walks through writing a simple plugin. Suppose you want to -write a plugin that detects division by zero in obvious cases. For -example, suppose someone compiles a silly program like this: +A compiler plugin consists of: + +- Some code that implements an additional compiler phase. +- Some code that uses the compiler plugin API to specify + when exactly this new phase should run. +- Additional code that specifies what options the plugin + accepts. +- An XML file containing metadata about the plugin + +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:...`. + +All of this will be described in more detail below. + +## A simple plugin, beginning to end + +This section walks through writing a simple plugin. + +Suppose you want to write a plugin that detects division by zero in +obvious cases. For example, suppose someone compiles a silly program +like this: object Test { val five = 5 val amount = five / 0 - def main(args: Array[String]) { + def main(args: Array[String]): Unit = { println(amount) } } -Your plugin could generate an error like this: +Our plugin will generate an error like: Test.scala:3: error: definitely division by zero val amount = five / 0 ^ - one error found There are several steps to making the plugin. First you need to write and compile the source of the plugin itself. Here is the source code for it: + // IMPORTANT: + // this code was written for Scala 2.8. + // it needs to be updated for Scala 2.12. + // the changes required are modest. + package localhost import scala.tools.nsc @@ -99,20 +118,17 @@ it: val name = "divbyzero" val description = "checks for division by zero" val components = List[PluginComponent](Component) - + private object Component extends PluginComponent { val global: DivByZero.this.global.type = DivByZero.this.global - val runsAfter = "refchecks" - // Using the Scala Compiler 2.8.x the runsAfter should be written as below - // val runsAfter = List[String]("refchecks"); + val runsAfter = List[String]("refchecks") val phaseName = DivByZero.this.name - def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) - + def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) class DivByZeroPhase(prev: Phase) extends StdPhase(prev) { override def name = DivByZero.this.name def apply(unit: CompilationUnit) { - for ( tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body; - if rcvr.tpe <:< definitions.IntClass.tpe) + for ( tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body + if rcvr.tpe <:< definitions.IntClass.tpe) { unit.error(tree.pos, "definitely division by zero") } @@ -139,28 +155,21 @@ aspects of note. examining the trees within the unit and doing some transformation on the tree. -Beginning with the Scala Compiler version 2.8 a new system for handling -compiler phases will be introduced. This new system gives the plugin -writer greater control over when the phase is executed. As seen in the -comment in the code example above, the runsAfter constraint is now a -list of phase names. This makes is possible to specify multiple phase -names to preceed the plugin. It is also possible, but optional, to -specify a runsBefore constraint of phase names that this phase should -preceed. It is also possible, but again optional, to specify a -runsRightAfter constraint on a specific phase. Examples of this can be -seen below and more information on these constraints and how they are -resolved can be found in [Compiler Phase and Plug-in Initialization -SID](../sid/2.html#). +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 +phase names. This makes it possible to specify multiple phase names to +preceed the plugin. It is also possible, but optional, to specify a +`runsBefore` constraint of phase names that this phase should +precede. And it is also possible, but again optional, to specify a +`runsRightAfter` constraint to run immediately after a specific +phase. - private object Component extends PluginComponent { - val global = DivByZero.this.global - val runsAfter = List[String]("refchecks","typer"); - override val runsBefore = List[String]("tailcalls"); - // Enable this and both runsAfter and runsBefore will have no effect - // override val runsRightAfter = "refcheks" - val phaseName = DivByZero.this.name - def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) - } +More information on how phase ordering is controlled can be +found in the [Compiler Phase and Plug-in Initialization +SID](http://www.scala-lang.org/old/sid/2). (This document was last +updated in 2009, so may be outdated in some details.) + +The simplest way to specify an order is to implement `runsRightAfter`. That's the plugin itself. The next thing you need to do is write a plugin descriptor for it. A plugin descriptor is a small XML file giving @@ -181,7 +190,7 @@ Put this XML in a file named `scalac-plugin.xml` and then create a jar with that file plus your compiled code: mkdir classes - fsc -d classes ExPlugin.scala + scalac -d classes ExPlugin.scala cp scalac-plugin.xml classes (cd classes; jar cf ../divbyzero.jar .) @@ -193,24 +202,24 @@ option: val amount = five / 0 ^ one error found - $ -When you are happy with how the plugin behaves, you can install it by -putting it in the directory `misc/scala-devel/plugins` within your Scala -installation. You can install your plugin with the following commands: +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. - $ mkdir -p $SCALA_HOME/misc/scala-devel/plugins - $ cp divbyzero.jar $SCALA_HOME/misc/scala-devel/plugins - $ +sbt, for example, provides an `addCompilerPlugin` method you can +call in your build definition, e.g.: -Now the plugin will be loaded by default: + addCompilerPlugin("org.divbyzero" % "divbyzero" % "1.0") - $ scalac Test.scala - Test.scala:3: error: definitely division by zero - val amount = five / 0 - ^ - one error found - $ +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`. ## Useful compiler options @@ -221,10 +230,10 @@ related to plugins that you should know about. - `-Xshow-phases`---show a list of all compiler phases, including ones that come from plugins. - `-Xplugin-list`---show a list of all loaded plugins. -- `-Xplugin-disable:`---disable a plugin. Whenever the compiler +- `-Xplugin-disable:...`---disable a plugin. Whenever the compiler encounters a plugin descriptor for the named plugin, it will skip over it and not even load the associated `Plugin` subclass. -- `-Xplugin-require:`---require that a plugin is loaded or else abort. +- `-Xplugin-require:...`---require that a plugin is loaded or else abort. This is mostly useful in build scripts. - `-Xpluginsdir`---specify the directory the compiler will scan to load plugins. Again, this is mostly useful for build scripts. @@ -267,6 +276,11 @@ sure you got the help string looking right. Here is a complete plugin that has an option. This plugin has no behavior other than to print out its option. + // IMPORTANT: + // this code was written for Scala 2.8. + // it needs to be updated for Scala 2.12. + // the changes required are modest. + package localhost import scala.tools.nsc @@ -281,9 +295,9 @@ behavior other than to print out its option. val name = "silly" val description = "goose" val components = List[PluginComponent](Component) - + var level = 1000000 - + override def processOptions(options: List[String], error: String => Unit) { for (option <- options) { if (option.startsWith("level:")) { @@ -293,18 +307,18 @@ behavior other than to print out its option. } } } - + override val optionsHelp: Option[String] = Some( " -P:silly:level:n set the silliness to level n") - + private object Component extends PluginComponent { val global: Silly.this.global.type = Silly.this.global val runsAfter = "refchecks" // Using the Scala Compiler 2.8.x the runsAfter should be written as shown below // val runsAfter = List[String]("refchecks"); val phaseName = Silly.this.name - def newPhase(_prev: Phase) = new SillyPhase(_prev) - + def newPhase(_prev: Phase) = new SillyPhase(_prev) + class SillyPhase(prev: Phase) extends StdPhase(prev) { override def name = Silly.this.name def apply(unit: CompilationUnit) { @@ -316,28 +330,10 @@ behavior other than to print out its option. ## Going further -### Download the code - -The above code can be found in the scala developer code examples as a -template compiler plugin. The example code also shows how to modify the -trees and types instead of only traversing them. - - - -You can use [sbaz](../tools/sbaz/index.html) to install the examples -locally.  Type \"`sbaz install scala-devel-docs`\" and navigate to the -directory `docs/scala-devel-docs/examples/plugintemplate`. - -### Develop using Eclipse - -Based on a [discussion on the -scala-tools](http://www.nabble.com/-scala-tools--running-debuging-compiler-plugin-from-Eclipse-to21328595.html) -mailing list, here is how to develop and debug a compiler plugin using -Eclipse: +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). -- put scala-compiler.jar in the class path -- create a launch configuration for scala.tools.nsc.Main -- pass the -Xplugin argument within this configuration which points to - a jar containing the scalac-plugin-xml (but not any classfiles) -- provide the plugin-implementation in a project referenced from the - launch configuration +It's also useful to look at other plugins and to study existing phases +within the compiler source code. From ac12059b7a375a4efe8e48233a014bb0d42c0c82 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 22 Mar 2018 13:26:18 +0100 Subject: [PATCH 0148/3174] Elaborate on our policy for supporting JVM versions There are two axes regarding the required or supported JVM version: - running Scala code, - compiling Scala code, and on both there is a lower and upper bound of the supported JVM. --- _overviews/jdk-compatibility/overview.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 8acd337a85..1654d734ea 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -13,18 +13,25 @@ permalink: /overviews/jdk-compatibility/:title.html Scala runs primarily on the Java Virtual Machine (JVM). As Scala and the JVM improve independently over time, Scala drops compatibility with older versions of the Java Developer Kit (JDK) in order to focus development efforts on supporting new JVM features that benefit Scala. -This table shows the first Scala release in each series that functions on each JDK. +This table shows the first Scala release in each series that functions on each JVM release. -| JDK version | First Scala release supporting JDK version per series | +| JVM version | First Scala compiler release supported to run on this JVM | |:-----------:|:-----------------------------------------------------| | 9 | 2.12.4, 2.11.12, 2.10.7 | | 8 | 2.12.0, 2.11.0, 2.10.0 | | 7 | 2.11.0, 2.10.0 | | 6 | 2.11.0, 2.10.0 | +### Running versus compiling and required / supported JVM +For most users, we recommend using Java 8 for *compiling* (and running) Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to *run* your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9. The Scala compiler does usually need updates to run properly on newer versions of the JVM, so make sure to use the appropriate JVM when compiling your code. + +Issues with using the Scala compiler on *non-LTS* versions of Java will not necessarily be considered blockers for releases, but we will do our best to run CI on more versions of Java to catch bugs early, and to fix them as quickly as reasonably possible. If regressions do occur with non-LTS (or, generally, unsupported) versions of Java, we may bring the next minor release deadline a bit closer, so that these issues are generally resolved within a month or two. Lightbend does offer commercial support for faster resolution of issues like this. + +The next step is to bump the *required* JVM versions for a Scala release, as we did for Scala 2.12 (raising the minimum JVM for compiling and running from version from 6 to 8). To leverage new features offered by a JVM release, we generally must drop support for older JVMs. + ### JDK 9 compatibility notes -As of Scala 2.12.4 and 2.11.12, **JDK 9 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. +As of Scala 2.12.5 and 2.11.12, **JDK 9 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. JDK 9 support requires minimum sbt version 1.1.0, or 0.13.17 in the 0.13.x series. From 528ecedde41a12fe3bdd4120e3a7e6ec1afd3c43 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Fri, 23 Mar 2018 11:34:48 +0000 Subject: [PATCH 0149/3174] Tweak how sbt is written in the bincompat guide (#1044) --- .../tutorials/binary-compatibility-for-library-authors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_overviews/tutorials/binary-compatibility-for-library-authors.md b/_overviews/tutorials/binary-compatibility-for-library-authors.md index cc8cd49ea5..d8cf3002da 100644 --- a/_overviews/tutorials/binary-compatibility-for-library-authors.md +++ b/_overviews/tutorials/binary-compatibility-for-library-authors.md @@ -66,7 +66,7 @@ Because of this, having multiple versions of the same library in the classpath i * Need to fetch and bundle multiple library versions when only one is actually used * Unexpected runtime behavior if the order of class files changes -Therefore, build tools like SBT and Gradle will pick one version and **evict** the rest when resolving JARs to use for compilation and packaging. +Therefore, build tools like sbt and Gradle will pick one version and **evict** the rest when resolving JARs to use for compilation and packaging. By default they pick the latest version of each library, but it is possible to specify another version if required. ### Source Compatibility @@ -147,8 +147,8 @@ The [Migration Manager for Scala](https://github.com/lightbend/migration-manager It works by comparing the class files of two provided JARs and report any binary incompatibilities found. Both backwards and forwards binary incompatibility can be detected by swapping input order of the JARs. -By incorporating [MiMa SBT plugin](https://github.com/lightbend/migration-manager/wiki/Sbt-plugin) into your SBT build, you can easily check whether -you have accidentally introduced binary incompatible changes. Detailed instruction on how to use the SBT plugin can be found in the link. +By incorporating MiMa's [sbt plugin](https://github.com/lightbend/migration-manager/wiki/sbt-plugin) into your sbt build, you can easily check whether +you have accidentally introduced binary incompatible changes. Detailed instruction on how to use the sbt plugin can be found in the link. We strongly encourage every library author to incorporate MiMa into their continuous integration and release workflow. From 0a68110685be9724b3e6eb745344f731a625ade7 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Fri, 23 Mar 2018 20:35:18 +0900 Subject: [PATCH 0150/3174] Scala 2.10.0 and 2.10.1 does not support Java 8 (#1043) - https://github.com/scala/scala/commit/b2c67b328daeaf51e - https://github.com/scala/scala/commit/28a6574554799ec4 ``` $ scala Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_151). Type in expressions to have them evaluated. Type :help for more information. scala> [init] error: error while loading AnnotatedElement, class file '/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/rt.jar(java/lang/reflect/AnnotatedElement.class)' is broken (class java.lang.RuntimeException/bad constant pool tag 18 at byte 76) [init] error: error while loading CharSequence, class file '/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/rt.jar(java/lang/CharSequence.class)' is broken (class java.lang.RuntimeException/bad constant pool tag 18 at byte 10) ``` --- _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 8acd337a85..bb8fc0f99e 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -18,7 +18,7 @@ This table shows the first Scala release in each series that functions on each J | JDK version | First Scala release supporting JDK version per series | |:-----------:|:-----------------------------------------------------| | 9 | 2.12.4, 2.11.12, 2.10.7 | -| 8 | 2.12.0, 2.11.0, 2.10.0 | +| 8 | 2.12.0, 2.11.0, 2.10.2 | | 7 | 2.11.0, 2.10.0 | | 6 | 2.11.0, 2.10.0 | From bde7e5679df9ff142b5fb452a75818cece82bc3d Mon Sep 17 00:00:00 2001 From: Angad Gill Date: Fri, 23 Mar 2018 04:35:56 -0700 Subject: [PATCH 0151/3174] Fixes minor typo in docs on Implicit Parameter page (#1041) --- _tour/implicit-parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/implicit-parameters.md b/_tour/implicit-parameters.md index d5182ce211..f06da371a9 100644 --- a/_tour/implicit-parameters.md +++ b/_tour/implicit-parameters.md @@ -62,7 +62,7 @@ In our `main` method we call `sum` twice, and only provide the `xs` parameter. S > Scala will first look for implicit definitions and implicit parameters that can be accessed directly (without a prefix) at the point the method with the implicit parameter block is called. -`intMonoid` is an implicit definition that can be accessed directly directly in `main`. It is also of the correct type, so it's passed to the sum method automatically. +`intMonoid` is an implicit definition that can be accessed directly in `main`. It is also of the correct type, so it's passed to the sum method automatically. The second call to `sum` passes a `List[String]`, which means that `A` is `String`. Implicit lookup will go the same way as with `Int`, but will this time find `stringMonoid`, and passes that automatically as `m`. From 1e9f9d07c94d7a1e01b38ade907aade6bde9e12a Mon Sep 17 00:00:00 2001 From: Gommorach Date: Fri, 23 Mar 2018 11:36:23 +0000 Subject: [PATCH 0152/3174] Fix typos in extractor-objects.md (#1040) Provide consistent punctuation --- _tour/extractor-objects.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_tour/extractor-objects.md b/_tour/extractor-objects.md index 3935fac2bd..db8ee5bbbf 100644 --- a/_tour/extractor-objects.md +++ b/_tour/extractor-objects.md @@ -53,8 +53,8 @@ val CustomerID(name2) = "--asdfasdfasdf" The return type of an `unapply` should be chosen as follows: -* If it is just a test, return a `Boolean`. For instance `case even()` -* If it returns a single sub-value of type T, return an `Option[T]` +* If it is just a test, return a `Boolean`. For instance `case even()`. +* If it returns a single sub-value of type T, return an `Option[T]`. * If you want to return several sub-values `T1,...,Tn`, group them in an optional tuple `Option[(T1,...,Tn)]`. Sometimes, the number of sub-values isn't fixed and we would like to return a sequence. For this reason, you can also define patterns through `unapplySeq` which returns `Option[Seq[T]]` This mechanism is used for instance in pattern `case List(x1, ..., xn)`. From e01af0a75ea2d24f969e8d4344bb20b9553478da Mon Sep 17 00:00:00 2001 From: Ryuji Yamashita Date: Fri, 23 Mar 2018 20:37:22 +0900 Subject: [PATCH 0153/3174] Fix broken ul-li (#1038) --- _ja/overviews/collections/maps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/overviews/collections/maps.md b/_ja/overviews/collections/maps.md index 8d9bd394cc..c824f55b8d 100644 --- a/_ja/overviews/collections/maps.md +++ b/_ja/overviews/collections/maps.md @@ -18,7 +18,7 @@ language: ja * **検索演算** には `apply`、`get`、`getOrElse`、`contains`、および `isDefinedAt` がある。これらはマップをキーから値への部分関数に変える。マップの最も基本的な検索メソッドは `def get(key): Option[Value]` だ。"`m get key`" という演算はマップが `key` に関連する値があるかを調べる。もしあれば、マップはその関連する値を `Some` に包んで返す。`key` がマップ中に定義されていなければ `get` は `None` を返す。マップはまた、任意のキーに関連する値を `Option` に包まずに直接返す `apply` メソッドも定義する。マップにキーが定義されていない場合は、例外が発生する。 * **加算と更新演算**である `+`、`++`、`updated` は、マップに新しい対応関係を追加するか、既存の対応関係を更新する。 -
  • 減算である --- は、対応関係をマップから削除する。
  • +* **減算**である `-`、 `--` は、対応関係をマップから削除する。 * **サブコレクション取得演算**である `keys`、`keySet`、`keysIterator`、`values`、`valuesIterator` は、マップのキーや値を様々な形で別に返す。 * **変換演算**である `filterKeys` と `mapValues` は、既存のマップの対応関係をフィルターしたり変換することで新たなマップを生成する。 From ebd14c0fc8dd017d0bf8b597cab287d73eddf1a8 Mon Sep 17 00:00:00 2001 From: Ryuji Yamashita Date: Fri, 23 Mar 2018 20:37:41 +0900 Subject: [PATCH 0154/3174] Change JavaConversions to JavaConverters in _ja (#1039) --- ...ions-between-java-and-scala-collections.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/_ja/overviews/collections/conversions-between-java-and-scala-collections.md b/_ja/overviews/collections/conversions-between-java-and-scala-collections.md index 49f2ab39a1..3de4df0782 100644 --- a/_ja/overviews/collections/conversions-between-java-and-scala-collections.md +++ b/_ja/overviews/collections/conversions-between-java-and-scala-collections.md @@ -15,8 +15,7 @@ language: ja Scala と同様に、Java にも豊富なコレクションライブラリがある。両者には多くの共通点がある。例えば、両方のライブラリともイテレータ、`Iterable`、集合、マップ、そして列を提供する。しかし、両者には重要な違いもある。特に、Scala では不変コレクションに要点を置き、コレクションを別のものに変換する演算も多く提供している。 -時として、コレクションを一方のフレームワークから他方へと渡す必要がある。例えば、既存の Java のコレクションを Scala のコレクションであるかのようにアクセスしたいこともあるだろう。もしくは、Scala のコレクションを Java のコレクションを期待している Java メソッドに渡したいと思うかもしれない。Scala は [`JavaConversions`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConversions$.html) オブジェクトにより主要なコレクション間の暗黙の変換 (implicit conversion) -を提供するため、簡単に相互運用できる。特に以下の型に関しては、双方向変換を提供する。 +時として、コレクションを一方のフレームワークから他方へと渡す必要がある。例えば、既存の Java のコレクションを Scala のコレクションであるかのようにアクセスしたいこともあるだろう。もしくは、Scala のコレクションを Java のコレクションを期待している Java メソッドに渡したいと思うかもしれない。Scala は [JavaConverters](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConverters$.html) オブジェクトにより主要なコレクション間の暗黙の変換を提供するため、簡単に相互運用できる。特に以下の型に関しては、双方向変換を提供する。 Iterator <=> java.util.Iterator Iterator <=> java.util.Enumeration @@ -27,25 +26,25 @@ Scala と同様に、Java mutable.Map <=> java.util.Map mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap -このような変換を作動させるには、[`JavaConversions`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConversions$.html) オブジェクトからインポートするだけでいい: +このような変換を作動させるには、[JavaConverters](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConverters$.html) オブジェクトからインポートするだけでいい: - scala> import collection.JavaConversions._ - import collection.JavaConversions._ + scala> import collection.JavaConverters._ + import collection.JavaConverters._ -これで Scala コレクションとそれに対応する Java コレクションの自動変換が行われる。 +これで `asScala` 及び `asJava` 拡張メソッドを呼び出すことで Scala コレクションとそれに対応する Java コレクションの変換が行われる。 scala> import collection.mutable._ import collection.mutable._ - scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3) + scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] - scala> val buf: Seq[Int] = jul + scala> val buf: Seq[Int] = jul.asScala buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) - scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2) + scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava m: java.util.Map[String,Int] = {hello=2, abc=1} 内部では、このような変換は全ての演算を委譲する「ラッパー」オブジェクトを作ることで実現されている。そのため、Java と Scala の間でコレクションを変換してもコレクションはコピーされることはない。興味深い特性として、例えば Java 型から対応する Scala 型に変換して再び Java 型に逆変換するといった、ラウンドトリップを実行した場合、始めた時と同一のオブジェクトが返ってくるというものがある。 -Scala コレクションの中には、Java 型に変換できるが、逆変換はできないというものもある。それらは以下の通り: +他の Scala コレクションも Java に変換できるが、元の Scala 型には逆変換できない。それらは以下の通り: Seq => java.util.List mutable.Seq => java.utl.List @@ -54,8 +53,9 @@ Scala コレクションの中には、Java 型に変換できるが、逆変換 Java は可変コレクションと不変コレクションを型で区別しないため、例えば `scala.immutable.List` からの変換は、上書き演算を呼び出すと `UnsupportedOperationException` を発生する `java.util.List` を返す。次に具体例で説明する: - scala> jul = List(1, 2, 3) + scala> val jul = List(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] + scala> jul.add(7) java.lang.UnsupportedOperationException - at java.util.AbstractList.add(AbstractList.java:131) + at java.util.AbstractList.add(AbstractList.java:148) From bd928eb7e17911a0288c98618a56c6993ec4d1c8 Mon Sep 17 00:00:00 2001 From: Ryuji Yamashita Date: Fri, 23 Mar 2018 20:39:08 +0900 Subject: [PATCH 0155/3174] Fix typo _ja/overviews/collections/*.md (#1037) * Fix typo in _ja/overviews/collections/overview.md * Fix typo in _ja/overviews/collections/trait-traversable.md * Fix typo in _ja/overviews/collections/trait-iterable.md * Fix typo in _ja/overviews/collections/seqs.md * Fix typo in _ja/overviews/collections/sets.md * Fix typo in _ja/overviews/collections/arrays.md * Fix typo in _ja/overviews/collections/views.md --- _ja/overviews/collections/arrays.md | 4 ++-- _ja/overviews/collections/overview.md | 8 ++++---- _ja/overviews/collections/seqs.md | 4 ++-- _ja/overviews/collections/sets.md | 2 +- _ja/overviews/collections/trait-iterable.md | 2 +- _ja/overviews/collections/trait-traversable.md | 8 ++++---- _ja/overviews/collections/views.md | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/_ja/overviews/collections/arrays.md b/_ja/overviews/collections/arrays.md index 705ce2ddf9..a2b72591d8 100644 --- a/_ja/overviews/collections/arrays.md +++ b/_ja/overviews/collections/arrays.md @@ -28,7 +28,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ scala> val seq: Seq[Int] = a1 seq: Seq[Int] = WrappedArray(1, 2, 3) - scala> val a4: Array[Int] = s.toArray + scala> val a4: Array[Int] = seq.toArray a4: Array[Int] = Array(1, 2, 3) scala> a1 eq a4 res1: Boolean = true @@ -50,7 +50,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ 実際には `WrappedArray` である `seq` に対して `reverse` を呼ぶと再び `WrappedArray` が返っているのが分かる。`WrappedArray` は `Seq` であり、`Seq` に対して `reverse` を呼ぶと再び `Seq` が返るため、この結果は論理的だ。一方、`ArrayOps` クラスの値 `ops` に対して `reverse` を呼ぶと、`Seq` ではなく、`Array` が返る。 -上記の `ArrayOps` の例は。`WrappedArray` との違いを示すためだけのかなり恣意的な物で、通常は `ArrayOps` クラスの値を定義することはありえない。単に配列に対して `Seq` メソッドを呼び出すだけでいい: +上記の `ArrayOps` の例は `WrappedArray` との違いを示すためだけのかなり恣意的な物で、通常は `ArrayOps` クラスの値を定義することはありえない。単に配列に対して `Seq` メソッドを呼び出すだけでいい: scala> a1.reverse res4: Array[Int] = Array(3, 2, 1) diff --git a/_ja/overviews/collections/overview.md b/_ja/overviews/collections/overview.md index 0261e1d9a4..8cdae22a13 100644 --- a/_ja/overviews/collections/overview.md +++ b/_ja/overviews/collections/overview.md @@ -14,7 +14,7 @@ language: ja Scala のコレクションは、体系的に可変および不変コレクションを区別している。**可変** (mutable) コレクションは上書きしたり拡張することができる。これは副作用としてコレクションの要素を変更、追加、または削除することができることを意味する。一方、**不変** (immutable) コレクションは変わることが無い。追加、削除、または更新を模倣した演算は提供されるが、全ての場合において演算は新しいコレクションを返し、古いコレクションは変わることがない。 -コレクションクラスの全ては `scala.collection` パッケージもしくは `mutable`、`immutable`、`generic` のどれかのサブパッケージに定義されている。クライアントコードに必要なコレクションのクラスのほどんどには可変性に関して異なる特性を持つ 3つの形態が定義されおり、ぞれぞれ `scala.collection`、`scala.collection.immutable`、か `scala.collection.mutable` のパッケージに存在する。 +コレクションクラスの全ては `scala.collection` パッケージもしくは `mutable`、`immutable`、`generic` のどれかのサブパッケージに定義されている。クライアントコードに必要なコレクションのクラスのほとんどには可変性に関して異なる特性を持つ 3つの形態が定義されており、それぞれ `scala.collection`、`scala.collection.immutable`、か `scala.collection.mutable` のパッケージに存在する。 `scala.collection.immutable` パッケージのコレクションは、誰にとっても不変であることが保証されている。 そのようなコレクションは作成後には一切変更されることがない。したがって、異なる時点で何回同じコレクションの値にアクセスしても常に同じ要素を持つコレクションが得られることに依存できる。 @@ -40,7 +40,7 @@ Scala のコレクションは、体系的に可変および不変コレクシ このパッケージには、コレクションを実装するための基本的なパーツが含まれている。 コレクションクラスがいくつかの演算を `generic` 内のクラスに委譲することはよくあるが、 フレームワークのユーザーが `generic` 内のクラスが必要になることは普通はありえない。 -利便性と後方互換性のために、いつくかの重要な型は `scala` パッケージ内に別名を定義してあるため、インポート無しで単純な名前でコレクションを使うことができる。[`List`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html) 型が良い例で、以下の名前でもアクセスすることができる +利便性と後方互換性のために、いくつかの重要な型は `scala` パッケージ内に別名を定義してあるため、インポート無しで単純な名前でコレクションを使うことができる。[`List`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html) 型が良い例で、以下の名前でもアクセスすることができる scala.collection.immutable.List // 定義元 scala.List // scala パッケージのエイリアス経由 @@ -89,7 +89,7 @@ Scala のコレクションは、体系的に可変および不変コレクシ すべてのコレクションが `Traversable` によって提供される API をサポートするが、理にかなうところでは型を特殊化している。 たとえば、`Traversable` クラスの `map` メソッドは別の `Traversable` を戻り値として返すが、結果の型はサブクラスでオーバーライドされる。 -たとえば、`List` が `map` を呼び出しても再び `List` が返ってき、`Set` が `map` を呼び出すと `Set` が返ってくる、といういう具合だ。 +たとえば、`List` が `map` を呼び出しても再び `List` が返ってき、`Set` が `map` を呼び出すと `Set` が返ってくる、という具合だ。 scala> List(1, 2, 3) map (_ + 1) res0: List[Int] = List(2, 3, 4) @@ -101,4 +101,4 @@ Scala のコレクションは、体系的に可変および不変コレクシ コレクションの階層のクラスのほとんどは基底、不変、可変の3種類とも存在する。 唯一の例外は、可変コレクションにのみ存在する `Buffer` トレイトだ。 -これより、これらのクラスを一つづつ見ていく。 +これより、これらのクラスを一つずつ見ていく。 diff --git a/_ja/overviews/collections/seqs.md b/_ja/overviews/collections/seqs.md index ba414a79bc..d9b392365a 100644 --- a/_ja/overviews/collections/seqs.md +++ b/_ja/overviews/collections/seqs.md @@ -17,7 +17,7 @@ language: ja 以下の表にまとめられた列の演算は以下のカテゴリーに分けることができる: * **添字と長さの演算** `apply`、 `isDefinedAt`、 `length`、 `indices`、および `lengthCompare`。`Seq` では `apply` メソッドは添字の意味で使われるため、`Seq[T]`型の列は `Int` を引数 (添字) としてをとり、`T`型の要素を返す部分関数だ。つまり、`Seq[T]` は `PartialFunction[Int, T]` を継承する。列内の要素はゼロから列の長さ (`length`) − 1 まで添字付けられている。列の `length` メソッドは一般コレクションにおける `size` メソッドの別名だ。`lengthCompare` メソッドは、たとえどちらかの列が無限の長さを持っていても、二つの列の長さを比較することができる。 -* **添字検索演算**である `indexOf`、 `lastIndexOf`、 `indexofSlice`、 `lastIndexOfSlice`、 `indexWhere`、 `lastIndexWhere`、 `segmentLength`、 `prefixLength` は、渡された値もしくは条件関数に合致する要素の添字を返す。 +* **添字検索演算**である `indexOf`、 `lastIndexOf`、 `indexOfSlice`、 `lastIndexOfSlice`、 `indexWhere`、 `lastIndexWhere`、 `segmentLength`、 `prefixLength` は、渡された値もしくは条件関数に合致する要素の添字を返す。 * **加算**である `+:`、`:+`、`padTo` は、列の先頭か最後に要素を追加した新しい列を返す。 * **更新演算**である `updated`、`patch` は、元の列に何らかの要素を上書きした列を返す。 * **並べ替え演算**である `sorted`、`sortWith`、`sortBy` は、列内の要素を何らかの基準に基づいて並べ替える。 @@ -82,7 +82,7 @@ Scala の他の構文の例にならって、`seq(idx) = elem` は `seq.update(i よく使われる線形列の例に `scala.collection.immutable.List` と `scala.collection.immutable.Stream` がある。よく使われる添字付き列の例としては `scala.Array` と `scala.collection.mutable.ArrayBuffer` がある。 `Vector` は添字付き列と線形列の間の興味深い折衷案だ。 事実上定数時間のオーバーヘッドで添字アクセスと線形アクセスを提供するからだ。 -そのため、ベクトルは添字アクセスと線形アクセスの両方を混合して使用してるアクセスパターンにおける良い基盤となる。 +そのため、ベクトルは添字アクセスと線形アクセスの両方を混合して使用しているアクセスパターンにおける良い基盤となる。 ベクトルに関しては、また[後ほど詳しくみていく](concrete-immutable-collection-classes.html)。 ### バッファ ### diff --git a/_ja/overviews/collections/sets.md b/_ja/overviews/collections/sets.md index 679c9641ea..816cb61ef6 100644 --- a/_ja/overviews/collections/sets.md +++ b/_ja/overviews/collections/sets.md @@ -91,7 +91,7 @@ language: ja scala> s res2: scala.collection.immutable.Set[Int] = Set(1, 3, 4) -ここでは `immutable.Set`型の `var` に対して `+=` と `-=` を使った。`s += 4` のようなステートメントは、`s = s + 4` の略だ。つまり、これは集合 `s` に対して追加メソッドの `+` を呼び出して、結果を変数`s` に代入しなおしてる。次に、可変集合でのやりとりを見てほしい。 +ここでは `immutable.Set`型の `var` に対して `+=` と `-=` を使った。`s += 4` のようなステートメントは、`s = s + 4` の略だ。つまり、これは集合 `s` に対して追加メソッドの `+` を呼び出して、結果を変数`s` に代入しなおしている。次に、可変集合でのやりとりを見てほしい。 scala> val s = collection.mutable.Set(1, 2, 3) s: scala.collection.mutable.Set[Int] = Set(1, 2, 3) diff --git a/_ja/overviews/collections/trait-iterable.md b/_ja/overviews/collections/trait-iterable.md index 49fdf4cfbe..8b63926456 100644 --- a/_ja/overviews/collections/trait-iterable.md +++ b/_ja/overviews/collections/trait-iterable.md @@ -12,7 +12,7 @@ num: 4 language: ja --- -反復可能 ([`Iterable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) トレイトはコレクション階層の上から2番目に位置する。このトレイトの全メソッドは、コレクション内の要素を1つづつ返す抽象メソッド `iterator` に基づいている。`Iterable` では、`Traversable` トレイトの `foreach` メソッドも `iterator`に基づいて実装されている。以下が実際の実装だ: +反復可能 ([`Iterable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) トレイトはコレクション階層の上から2番目に位置する。このトレイトの全メソッドは、コレクション内の要素を1つずつ返す抽象メソッド `iterator` に基づいている。`Iterable` では、`Traversable` トレイトの `foreach` メソッドも `iterator`に基づいて実装されている。以下が実際の実装だ: def foreach[U](f: Elem => U): Unit = { val it = iterator diff --git a/_ja/overviews/collections/trait-traversable.md b/_ja/overviews/collections/trait-traversable.md index b95d158a63..eed29ac4de 100644 --- a/_ja/overviews/collections/trait-traversable.md +++ b/_ja/overviews/collections/trait-traversable.md @@ -16,7 +16,7 @@ language: ja def foreach[U](f: Elem => U) -`Traverable` を実装するコレクションクラスは、このメソッドを定義するだけでいい。逆に言うと、その他全てのメソッドは `Traversable` から継承することができる。 +`Traversable` を実装するコレクションクラスは、このメソッドを定義するだけでいい。逆に言うと、その他全てのメソッドは `Traversable` から継承することができる。 `foreach` メソッドは、コレクション中の全ての要素を走査して、渡された演算 `f` を各々の要素に適用することを意図している。 この演算の型は `Elem => U` であり、`Elem` はコレクションの要素の型で、`U` は任意の戻り値型だ。 `f` の呼び出しはそれに伴う副作用のためだけに行われ、`f` の戻り値の全ては `foreach` によって破棄される。 @@ -28,13 +28,13 @@ language: ja * **変換演算**である `toArray`、`toList`、`toIterable`、`toSeq`、`toIndexedSeq`、`toStream`、`toSet`、`toMap` は `Traversable` なコレクションを別のより特定のものに変える。実行時のコレクション型が既に要求されているコレクション型と一致する場合、これらの全ての変換は引数をそのまま返す。例えば、リストに `toList` を適用した場合、リストそのものを返す。 * **コピー演算** `copyToBuffer` と `copyToArray`。名前のとおり、これらの演算はコレクションの要素をバッファまたは配列にコピーする。 * **サイズ演算** `isEmpty`、`nonEmpty`、`size`、および `hasDefiniteSize`。 `Traversable` なコレクションは有限または無限のサイズを取りうる。無限の `Traversable` コレクションの例としては自然数のストリームである `Stream.from(0)` がある。 -`hasDefiniteSize` メソッドはコレクションが無限である可能性があるかを示す。`hasDefiniteSize` が `true` を返す場合、コレクション確実に有限だ。`false` を返す場合、コレクションはまだ完全に展開されていないことを示し、それは無限か有限のどちらである可能性もある。 +`hasDefiniteSize` メソッドはコレクションが無限である可能性があるかを示す。`hasDefiniteSize` が `true` を返す場合、コレクションは確実に有限だ。`false` を返す場合、コレクションはまだ完全に展開されていないことを示し、それは無限か有限のどちらである可能性もある。 * **要素取得演算** `head`、`last`、`headOption`、`lastOption`、および `find`。これらはコレクションの最初または最後の要素、または他の条件に一致する最初の要素を選択する。しかし、全てのコレクションにおいて「最初」と「最後」の意味が明確に定義されているわけではないことに注意してほしい。たとえば、ハッシュ集合はハッシュキーの並びで要素を格納するかもしれないが、ハッシュキーは実行するたびに変わる可能性がある。その場合、ハッシュ集合の「最初」の要素はプログラムを実行するたびに異なるかもしれない。 あるコレクションから常に同じ順序で要素を得られる場合、そのコレクションは**順序付け** (ordered) されているという。 ほとんどのコレクションは順序付けされているが、(ハッシュ集合など)いくつかののコレクションは順序付けされていない ― 順序付けを省くことで多少効率が上がるのだ。順序付けは再現性のあるテストを書くのに不可欠であり、デバッグの役に立つ。 そのため Scala のコレクションは、全てのコレクション型に対して順序付けされた選択肢を用意してある。 -例えば、`HashSet` に代わる順次付けされたものは `LinkedHashSet` だ。 +例えば、`HashSet` に代わる順序付けされたものは `LinkedHashSet` だ。 * **サブコレクション取得演算** `tail`、`init`、`slice`、`take`、`drop`、`takeWhile`、`dropWhile`、`filter`、`filterNot`、`withFilter`。 これら全ての演算は添字の範囲や何らかの条件関数によって識別されたサブコレクションを返す。 * **分割演算**である `splitAt`、`span`、`partition`、`groupBy` の全てはコレクションの要素をいくつかのサブコレクションに分割する。 @@ -56,7 +56,7 @@ language: ja | **map 演算:** | | | `xs map f` |`xs` 内の全ての要素に関数 `f` を適用することによって得られるコレクション。| | `xs flatMap f` |`xs` 内の全ての要素に対してコレクション値を返す関数 `f` を適用し、その結果を連結したコレクション。| -| `xs collect f` |`xs` 内の全ての要素に対して部分関数 `f` が定義されている場合のみ適応し、その結果を集めたコレクション。| +| `xs collect f` |`xs` 内の全ての要素に対して部分関数 `f` が定義されている場合のみ適用し、その結果を集めたコレクション。| | **変換演算:** | | | `xs.toArray` |コレクションを配列に変換する。 | | `xs.toList` |コレクションをリストに変換する。 | diff --git a/_ja/overviews/collections/views.md b/_ja/overviews/collections/views.md index f3bf540cc4..650858d07e 100644 --- a/_ja/overviews/collections/views.md +++ b/_ja/overviews/collections/views.md @@ -15,7 +15,7 @@ language: ja コレクションには新たなコレクションを構築するメソッドがたくさんある。例えば `map`、`filter`、`++` などがある。これらのメソッドは1つ以上のコレクションをレシーバとして取り、戻り値として別のコレクションを生成するため**変換演算子** (transformer) と呼ばれる。 -変換演算子を実装するには主に二つの方法がある。**正格** (strict) 法は変換演算子の戻り値として全ての要素を含む新たなコレクションを返す。非正格法、もしくは**遅延** (lazy) 法と呼ばれる方法は、結果のコレクションの代理のみを構築して返し、実際の要素は必用に応じて構築される。 +変換演算子を実装するには主に二つの方法がある。**正格** (strict) 法は変換演算子の戻り値として全ての要素を含む新たなコレクションを返す。非正格法、もしくは**遅延** (lazy) 法と呼ばれる方法は、結果のコレクションの代理のみを構築して返し、実際の要素は必要に応じて構築される。 非正格な変換演算子の具体例として、以下の遅延 map 演算の実装を見てほしい: @@ -25,7 +25,7 @@ language: ja `lazyMap` は、渡されたコレクション `coll` の全要素を総なめすることなく新しい `Iterable` を構築していることに注意してほしい。代わりに、渡された関数の `f` が新しいコレクションの `iterator` に必要に応じて適用される。 -全ての変換演算子を遅延実装している `Stream` を除いて、Scala のコレクションは全ての変換演算子をデフォルトで正格法で実装している。しかし、コレクションのビューにより、体系的に全てのコレクションを遅延したものに変え、また逆に戻すことができる。**ビュー** (view) は特殊なコレクションの一種で、何らかのコレクションに基づいているが全ての変換演算子を遅延実装してる。 +全ての変換演算子を遅延実装している `Stream` を除いて、Scala のコレクションは全ての変換演算子をデフォルトで正格法で実装している。しかし、コレクションのビューにより、体系的に全てのコレクションを遅延したものに変え、また逆に戻すことができる。**ビュー** (view) は特殊なコレクションの一種で、何らかのコレクションに基づいているが全ての変換演算子を遅延実装している。 あるコレクションからそのビューへと移行するには、そのコレクションに対して `view` メソッドを呼び出す。`xs` というコレクションがあるとすると、`xs.view` は変換演算子が遅延実装されている以外は同一のコレクションだ。ビューから正格なコレクションに戻るには `force` メソッドを使う。 From f5d84cd03a6dfc0c84fcf2b60884a5d9201242fd Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 23 Mar 2018 10:58:03 -0400 Subject: [PATCH 0156/3174] reorganize Overviews page * split "Core Scala" into "Language" and "Standard Library" * make a new "Compatibility" section --- _data/overviews.yml | 115 +++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index 0f091c2f5a..dfdcd77757 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -1,6 +1,27 @@ -- category: Core Scala - description: "Guides and overviews covering central libraries in the Scala standard library, core language features, and more." +- category: Language + description: "Guides and overviews covering features in the Scala language." + overviews: + - title: String Interpolation + icon: usd + url: "core/string-interpolation.html" + description: > + String Interpolation allows users to embed variable references directly in processed string literals. Here’s an example: +
    val name = "James"
    +          println(s"Hello, $name")  // Hello, James
    + In the above, the literal s"Hello, $name" is a processed string literal. This means that the compiler does some additional work to this literal. A processed string literal is denoted by a set of characters preceding the ". String interpolation was introduced by SIP-11, which contains all details of the implementation. + - title: Implicit Classes + by: Josh Suereth + description: "Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope." + url: "core/implicit-classes.html" + - title: Value Classes and Universal Traits + by: Mark Harrah + description: "Value classes are a new mechanism in Scala to avoid allocating runtime objects. This is accomplished through the definition of new AnyVal subclasses." + icon: diamond + url: "core/value-classes.html" + +- category: Standard Library + description: "Guides and overviews covering the Scala standard library." overviews: - title: Collections by: Martin Odersky @@ -42,58 +63,6 @@ url: "core/architecture-of-scala-collections.html" by: Martin Odersky and Lex Spoon description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - - title: String Interpolation - icon: usd - url: "core/string-interpolation.html" - description: > - String Interpolation allows users to embed variable references directly in processed string literals. Here’s an example: -
    val name = "James"
    -          println(s"Hello, $name")  // Hello, James
    - In the above, the literal s"Hello, $name" is a processed string literal. This means that the compiler does some additional work to this literal. A processed string literal is denoted by a set of characters preceding the ". String interpolation was introduced by SIP-11, which contains all details of the implementation. - - title: Implicit Classes - by: Josh Suereth - description: "Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope." - url: "core/implicit-classes.html" - - title: Value Classes and Universal Traits - by: Mark Harrah - description: "Value classes are a new mechanism in Scala to avoid allocating runtime objects. This is accomplished through the definition of new AnyVal subclasses." - icon: diamond - url: "core/value-classes.html" - - title: Binary Compatibility of Scala Releases - description: "When two versions of Scala are binary compatible, it is safe to compile your project on one Scala version and link against another Scala version at run time. Safe run-time linkage (only!) means that the JVM does not throw a (subclass of) LinkageError when executing your program in the mixed scenario, assuming that none arise when compiling and running on the same version of Scala. Concretely, this means you may have external dependencies on your run-time classpath that use a different version of Scala than the one you’re compiling with, as long as they’re binary compatible. In other words, separate compilation on different binary compatible versions does not introduce problems compared to compiling and running everything on the same version of Scala." - icon: puzzle-piece - url: "core/binary-compatibility-of-scala-releases.html" - - title: Binary Compatibility for Library Authors - description: "A diverse and comprehensive set of libraries is important to any productive software ecosystem. While it is easy to develop and distribute Scala libraries, good library authorship goes beyond just writing code and publishing it. In this guide, we cover the important topic of Binary Compatibility." - icon: puzzle-piece - url: "core/binary-compatibility-for-library-authors.html" - -- category: "Reference/Documentation" - description: "Reference material on core Scala tools like Scaladoc and the Scala REPL." - overviews: - - title: Scaladoc - url: "scaladoc/overview.html" - icon: book - description: "Scala's API documentation generation tool." - subdocs: - - title: Overview - url: "scaladoc/overview.html" - - title: Scaladoc for Library Authors - url: "scaladoc/for-library-authors.html" - - title: Using the Scaladoc Interface - url: "scaladoc/interface.html" - - title: Scala REPL - icon: terminal - url: "repl/overview.html" - description: | - The Scala REPL is a tool (scala) for evaluating expressions in Scala. -

    - The scala command will execute a source script by wrapping it in a template and then compiling and executing the resulting program - - title: JDK Version Compatibility - icon: coffee - url: "jdk-compatibility/overview.html" - description: "Which Scala versions work on what JDK versions" - - category: Parallel and Concurrent Programming description: "Complete guides covering some of Scala's libraries for parallel and concurrent programming." overviews: @@ -137,6 +106,44 @@ label-color: "#899295" label-text: deprecated +- category: Compatibility + description: "What works with what (or doesn't)." + overviews: + - title: JDK Version Compatibility + description: "Which Scala versions work on what JDK versions" + icon: coffee + url: "jdk-compatibility/overview.html" + - title: Binary Compatibility of Scala Releases + description: "When two versions of Scala are binary compatible, it is safe to compile your project on one Scala version and link against another Scala version at run time. Safe run-time linkage (only!) means that the JVM does not throw a (subclass of) LinkageError when executing your program in the mixed scenario, assuming that none arise when compiling and running on the same version of Scala. Concretely, this means you may have external dependencies on your run-time classpath that use a different version of Scala than the one you’re compiling with, as long as they’re binary compatible. In other words, separate compilation on different binary compatible versions does not introduce problems compared to compiling and running everything on the same version of Scala." + icon: puzzle-piece + url: "core/binary-compatibility-of-scala-releases.html" + - title: Binary Compatibility for Library Authors + description: "A diverse and comprehensive set of libraries is important to any productive software ecosystem. While it is easy to develop and distribute Scala libraries, good library authorship goes beyond just writing code and publishing it. In this guide, we cover the important topic of Binary Compatibility." + icon: puzzle-piece + url: "core/binary-compatibility-for-library-authors.html" + +- category: "Tools" + description: "Reference material on core Scala tools like the Scala REPL and Scaladoc generation." + overviews: + - title: Scala REPL + icon: terminal + url: "repl/overview.html" + description: | + The Scala REPL is a tool (scala) for evaluating expressions in Scala. +

    + The scala command will execute a source script by wrapping it in a template and then compiling and executing the resulting program + - title: Scaladoc + url: "scaladoc/overview.html" + icon: book + description: "Scala's API documentation generation tool." + subdocs: + - title: Overview + url: "scaladoc/overview.html" + - title: Scaladoc for Library Authors + url: "scaladoc/for-library-authors.html" + - title: Using the Scaladoc Interface + url: "scaladoc/interface.html" + - category: Compiler description: "Guides and overviews covering the Scala compiler: compiler plugins, reflection, and metaprogramming tools such as macros." overviews: From 5b25bc4d51013583707bce3701b57efc1d37da5f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 23 Mar 2018 10:59:17 -0400 Subject: [PATCH 0157/3174] remove obsolete actors guides --- _data/overviews.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index dfdcd77757..f6ea574830 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -93,18 +93,6 @@ url: "parallel-collections/configuration.html" - title: Measuring Performance url: "parallel-collections/performance.html" - - title: The Scala Actors Migration Guide - by: Vojin Jovanovic and Philipp Haller - icon: truck - url: "core/actors-migration-guide.html" - description: "To ease the migration from Scala Actors to Akka we have provided the Actor Migration Kit (AMK). The AMK consists of an extension to Scala Actors which is enabled by including the scala-actors-migration.jar on a project’s classpath. In addition, Akka 2.1 includes features, such as the ActorDSL singleton, which enable a simpler conversion of code using Scala Actors to Akka. The purpose of this document is to guide users through the migration process and explain how to use the AMK." - - title: The Scala Actors API - by: Philipp Haller and Stephen Tu - icon: users - url: "core/actors.html" - description: "This guide describes the API of the scala.actors package of Scala 2.8/2.9. The organization follows groups of types that logically belong together. The trait hierarchy is taken into account to structure the individual sections. The focus is on the run-time behavior of the various methods that these traits define, thereby complementing the existing Scaladoc-based API documentation." - label-color: "#899295" - label-text: deprecated - category: Compatibility description: "What works with what (or doesn't)." From 9052c40dcc39f376c466c67368fac6862b9a7c88 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 23 Mar 2018 11:17:11 -0400 Subject: [PATCH 0158/3174] improve structure & appearance of JDK compatibility page --- _overviews/jdk-compatibility/overview.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index bb8fc0f99e..ce71d9dd24 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -1,19 +1,15 @@ --- -layout: multipage-overview -title: Overview - +layout: singlepage-overview +title: JDK Compatibility discourse: true - -partof: jdk-compatibility -overview-name: JDK Compatibility - -num: 1 -permalink: /overviews/jdk-compatibility/:title.html +permalink: /overviews/jdk-compatibility/overview.html --- Scala runs primarily on the Java Virtual Machine (JVM). As Scala and the JVM improve independently over time, Scala drops compatibility with older versions of the Java Developer Kit (JDK) in order to focus development efforts on supporting new JVM features that benefit Scala. -This table shows the first Scala release in each series that functions on each JDK. +## Version compatibility table + +This shows the first Scala release in each series that functions on each JDK. | JDK version | First Scala release supporting JDK version per series | |:-----------:|:-----------------------------------------------------| @@ -22,7 +18,7 @@ This table shows the first Scala release in each series that functions on each J | 7 | 2.11.0, 2.10.0 | | 6 | 2.11.0, 2.10.0 | -### JDK 9 compatibility notes +## JDK 9 compatibility notes As of Scala 2.12.4 and 2.11.12, **JDK 9 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. From dce41f9e4c20b6bc102fcfa6dce8f6d212174542 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 23 Mar 2018 13:03:01 -0400 Subject: [PATCH 0159/3174] general copyediting --- _overviews/jdk-compatibility/overview.md | 33 +++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 0e3f65a3c2..94eacbaf5c 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -5,30 +5,39 @@ discourse: true permalink: /overviews/jdk-compatibility/overview.html --- -Scala runs primarily on the Java Virtual Machine (JVM). As Scala and the JVM improve independently over time, Scala drops compatibility with older versions of the Java Developer Kit (JDK) in order to focus development efforts on supporting new JVM features that benefit Scala. +Scala runs primarily on the Java Virtual Machine (JVM). + +Sometimes new JVM versions require us to update Scala to remain compatible. + +And as Scala and the JVM improve independently over time, Scala may drop compatibility with older JVM versions, in order to better take advantage of new JVM features. ## Version compatibility table -This table shows the first Scala release in each series that functions on each JVM release. +This table shows the first Scala release in each series that works with each JVM release. -| JVM version | First Scala compiler release supported to run on this JVM | +| JVM version | Minimum Scala versions | |:-----------:|:-----------------------------------------------------| -| 9 | 2.12.4, 2.11.12, 2.10.7 | +| 9, 10 | 2.12.4, 2.11.12, 2.10.7 | | 8 | 2.12.0, 2.11.0, 2.10.2 | | 7 | 2.11.0, 2.10.0 | | 6 | 2.11.0, 2.10.0 | -## Running versus compiling and required / supported JVM -For most users, we recommend using Java 8 for *compiling* (and running) Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to *run* your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9. The Scala compiler does usually need updates to run properly on newer versions of the JVM, so make sure to use the appropriate JVM when compiling your code. +## Running versus compiling + +For most users, we still recommend using Java 8 for *compiling* (and running) Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to *run* your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9. The Scala compiler does usually need updates to run properly on newer versions of the JVM, so make sure to use the appropriate JVM when compiling your code. + +Issues with using the Scala compiler on *non-LTS* ("Long Term Support"; see http://www.oracle.com/technetwork/java/eol-135779.html) versions of Java will not necessarily be considered blockers for releases, but we will do our best to run CI on more versions of Java to catch bugs early, and to fix them as quickly as reasonably possible. If regressions do occur with non-LTS (or, generally, unsupported) versions of Java, we may bring the next minor release deadline a bit closer, so that these issues are generally resolved within a month or two. Lightbend does offer commercial support for faster resolution of issues like this. + +## Dropping old JVMs -Issues with using the Scala compiler on *non-LTS* versions of Java will not necessarily be considered blockers for releases, but we will do our best to run CI on more versions of Java to catch bugs early, and to fix them as quickly as reasonably possible. If regressions do occur with non-LTS (or, generally, unsupported) versions of Java, we may bring the next minor release deadline a bit closer, so that these issues are generally resolved within a month or two. Lightbend does offer commercial support for faster resolution of issues like this. +Some Scala releases increase the *required* JVM versions for a Scala release. To leverage new features offered by a JVM release, we must sometimes drop support for older JVMs. -The next step is to bump the *required* JVM versions for a Scala release, as we did for Scala 2.12 (raising the minimum JVM for compiling and running from version from 6 to 8). To leverage new features offered by a JVM release, we generally must drop support for older JVMs. +For example, Scala 2.12 raised the minimum JVM, for both compiling and running, from version from 6 to 8. This was done so we could take advantage of new features in 8 such as lambdas and default methods. -## JDK 9 compatibility notes +## JDK 9 & 10 compatibility notes -As of Scala 2.12.5 and 2.11.12, **JDK 9 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. +As of Scala 2.12.5 and 2.11.12, **JDK 9 & 10 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. -JDK 9 support requires minimum sbt version 1.1.0, or 0.13.17 in the 0.13.x series. +JDK 9 & 10 support requires minimum sbt version 1.1.0, or 0.13.17 in the 0.13.x series. -For more information on JDK 9 compatibility, watch the ["Support JDK 9"](https://github.com/scala/scala-dev/issues/139 "scala/scala-dev #139") issue on GitHub. +For more information on JDK 9 & 10 compatibility, watch the ["Support JDK 9"](https://github.com/scala/scala-dev/issues/139 "scala/scala-dev #139") issue on GitHub. From dc9eabb374e0af44296941884948770dfef5c61e Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 27 Mar 2018 15:35:42 +0200 Subject: [PATCH 0160/3174] Drop sips/pending redirect_from (see #872) --- _sips/sips/2011-10-13-uncluttering-control.md | 1 - 1 file changed, 1 deletion(-) diff --git a/_sips/sips/2011-10-13-uncluttering-control.md b/_sips/sips/2011-10-13-uncluttering-control.md index d855b1287d..bf07845907 100644 --- a/_sips/sips/2011-10-13-uncluttering-control.md +++ b/_sips/sips/2011-10-13-uncluttering-control.md @@ -1,7 +1,6 @@ --- layout: sip title: SIP-12 - Uncluttering Scala’s syntax for control structures. -redirect_from: "/sips/pending/uncluttering-control.html" vote-status: rejected vote-text: The committee votes unanimously to reject the change. The conclusion is that there is not a clear benefit for it and the required invested time and efforts would be too high. For more explanation, read the minutes. From 7ef247dfde602c48875b9926a7e88cd12976e11d Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 27 Mar 2018 15:36:46 +0200 Subject: [PATCH 0161/3174] Drop `sips/pending` redirect_from (#872) --- _sips/sips/2016-06-25-trailing-commas.md | 1 - 1 file changed, 1 deletion(-) diff --git a/_sips/sips/2016-06-25-trailing-commas.md b/_sips/sips/2016-06-25-trailing-commas.md index 42fa51adfb..25af1608d9 100644 --- a/_sips/sips/2016-06-25-trailing-commas.md +++ b/_sips/sips/2016-06-25-trailing-commas.md @@ -2,7 +2,6 @@ layout: inner-page-no-masthead discourse: true title: SIP-27 - Trailing Commas -redirect_from: "/sips/pending/trailing-commas.html" vote-status: complete vote-text: This SIP has already been accepted and completed, and is a part of Scala 2.12.2. From 8f5426d59c23b737087e4402403526905468fb44 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 27 Mar 2018 15:38:23 +0200 Subject: [PATCH 0162/3174] Also redirect sips/pending to new url --- _sips/all.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_sips/all.md b/_sips/all.md index d04931bd6d..50b6f94479 100644 --- a/_sips/all.md +++ b/_sips/all.md @@ -3,6 +3,7 @@ layout: sips title: List of All SIPs redirect_from: "/sips/sip-list.html" +redirect_from: "/sips/pending/index.html" --- From 5567bcbfde5d2a183d04196c5cf8d607327d8bd2 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 31 Mar 2018 22:00:13 -0500 Subject: [PATCH 0163/3174] swap order of first two sections as suggested by Heather --- _data/overviews.yml | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index f6ea574830..be5a9d95ac 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -1,25 +1,4 @@ -- category: Language - description: "Guides and overviews covering features in the Scala language." - overviews: - - title: String Interpolation - icon: usd - url: "core/string-interpolation.html" - description: > - String Interpolation allows users to embed variable references directly in processed string literals. Here’s an example: -
    val name = "James"
    -          println(s"Hello, $name")  // Hello, James
    - In the above, the literal s"Hello, $name" is a processed string literal. This means that the compiler does some additional work to this literal. A processed string literal is denoted by a set of characters preceding the ". String interpolation was introduced by SIP-11, which contains all details of the implementation. - - title: Implicit Classes - by: Josh Suereth - description: "Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope." - url: "core/implicit-classes.html" - - title: Value Classes and Universal Traits - by: Mark Harrah - description: "Value classes are a new mechanism in Scala to avoid allocating runtime objects. This is accomplished through the definition of new AnyVal subclasses." - icon: diamond - url: "core/value-classes.html" - - category: Standard Library description: "Guides and overviews covering the Scala standard library." overviews: @@ -63,6 +42,28 @@ url: "core/architecture-of-scala-collections.html" by: Martin Odersky and Lex Spoon description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." + +- category: Language + description: "Guides and overviews covering features in the Scala language." + overviews: + - title: String Interpolation + icon: usd + url: "core/string-interpolation.html" + description: > + String Interpolation allows users to embed variable references directly in processed string literals. Here’s an example: +
    val name = "James"
    +          println(s"Hello, $name")  // Hello, James
    + In the above, the literal s"Hello, $name" is a processed string literal. This means that the compiler does some additional work to this literal. A processed string literal is denoted by a set of characters preceding the ". String interpolation was introduced by SIP-11, which contains all details of the implementation. + - title: Implicit Classes + by: Josh Suereth + description: "Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope." + url: "core/implicit-classes.html" + - title: Value Classes and Universal Traits + by: Mark Harrah + description: "Value classes are a new mechanism in Scala to avoid allocating runtime objects. This is accomplished through the definition of new AnyVal subclasses." + icon: diamond + url: "core/value-classes.html" + - category: Parallel and Concurrent Programming description: "Complete guides covering some of Scala's libraries for parallel and concurrent programming." overviews: From 0ed3269ed86a705c0833d299e07adcfc37a1dca8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 31 Mar 2018 22:02:35 -0500 Subject: [PATCH 0164/3174] restore actors links in a new "Legacy" section --- _data/overviews.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/_data/overviews.yml b/_data/overviews.yml index be5a9d95ac..005309a7de 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -226,3 +226,19 @@ icon: puzzle-piece url: "plugins/index.html" description: "Compiler plugins permit customizing and extending the Scala compiler. This tutorial describes the plugin facility and walks you through how to create a simple plugin." + +- category: Legacy + description: "Guides covering features no longer relevant to recent Scala versions (2.11+)." + overviews: + - title: The Scala Actors Migration Guide + by: Vojin Jovanovic and Philipp Haller + icon: truck + url: "core/actors-migration-guide.html" + description: "To ease the migration from Scala Actors to Akka we have provided the Actor Migration Kit (AMK). The AMK consists of an extension to Scala Actors which is enabled by including the scala-actors-migration.jar on a project’s classpath. In addition, Akka 2.1 includes features, such as the ActorDSL singleton, which enable a simpler conversion of code using Scala Actors to Akka. The purpose of this document is to guide users through the migration process and explain how to use the AMK." + - title: The Scala Actors API + by: Philipp Haller and Stephen Tu + icon: users + url: "core/actors.html" + description: "This guide describes the API of the scala.actors package of Scala 2.8/2.9. The organization follows groups of types that logically belong together. The trait hierarchy is taken into account to structure the individual sections. The focus is on the run-time behavior of the various methods that these traits define, thereby complementing the existing Scaladoc-based API documentation." + label-color: "#899295" + label-text: deprecated From 6ab4af402c2af0b2f2d61c088295957a45239e98 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 2 Apr 2018 11:25:10 +0200 Subject: [PATCH 0165/3174] Add redirect_froms in all the SIPs --- _sips/sips/2009-05-28-scala-compiler-phase-plugin-in.md | 1 + _sips/sips/2009-06-02-early-member-definitions.md | 1 + _sips/sips/2009-11-02-scala-swing-overview.md | 1 + _sips/sips/2010-01-22-named-and-default-arguments.md | 1 + _sips/sips/2010-01-22-scala-2-8-arrays.md | 1 + _sips/sips/2010-01-27-internals-of-scala-annotations.md | 1 + _sips/sips/2010-05-06-scala-specialization.md | 1 + _sips/sips/2010-06-01-picked-signatures.md | 1 + _sips/sips/2010-07-20-new-collection-classes.md | 1 + _sips/sips/2011-10-12-implicit-classes.md | 1 + _sips/sips/2011-10-13-string-interpolation.md | 1 + _sips/sips/2011-10-13-uncluttering-control.md | 1 + _sips/sips/2012-01-21-futures-promises.md | 1 + _sips/sips/2012-01-30-value-classes.md | 1 + _sips/sips/2012-03-09-self-cleaning-macros.md | 1 + _sips/sips/2012-03-13-type-dynamic.md | 1 + _sips/sips/2012-03-17-modularizing-language-features.md | 1 + _sips/sips/2012-03-30-source-locations.md | 1 + _sips/sips/2013-05-31-improved-lazy-val-initialization.md | 1 + _sips/sips/2013-06-10-spores.md | 1 + _sips/sips/2013-06-30-async.md | 1 + _sips/sips/2014-06-27-42.type.md | 1 + _sips/sips/2015-6-18-repeated-byname.md | 1 + _sips/sips/2015-6-18-trait-parameters.md | 1 + _sips/sips/2016-01-11-static-members.md | 1 + _sips/sips/2016-06-25-trailing-commas.md | 1 + _sips/sips/2016-07-25-unsigned-integers.md | 1 + _sips/sips/2016-09-09-inline-meta.md | 1 + _sips/sips/2017-01-11-refer-other-arguments-in-args.md | 1 + _sips/sips/2017-01-13-binary-compatibility.md | 1 + _sips/sips/2017-02-07-priority-based-infix-type-precedence.md | 1 + _sips/sips/2017-02-22-comonadic-comprehensions.md | 1 + _sips/sips/2017-07-12-right-associative-by-name-operators.md | 1 + _sips/sips/2017-09-20-opaque-types.md | 1 + _sips/sips/2017-10-25-adding-prefix-types.md | 1 + _sips/sips/2017-11-20-byname-implicits.md | 1 + 36 files changed, 36 insertions(+) diff --git a/_sips/sips/2009-05-28-scala-compiler-phase-plugin-in.md b/_sips/sips/2009-05-28-scala-compiler-phase-plugin-in.md index f66a14dae3..264be3bab5 100644 --- a/_sips/sips/2009-05-28-scala-compiler-phase-plugin-in.md +++ b/_sips/sips/2009-05-28-scala-compiler-phase-plugin-in.md @@ -4,6 +4,7 @@ title: SID-2 Scala Compiler Phase and Plug-In Initialization for Scala 2.8 vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/scala-compiler-phase-plugin-in.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/2) diff --git a/_sips/sips/2009-06-02-early-member-definitions.md b/_sips/sips/2009-06-02-early-member-definitions.md index 62d75cd00f..3b4847be44 100644 --- a/_sips/sips/2009-06-02-early-member-definitions.md +++ b/_sips/sips/2009-06-02-early-member-definitions.md @@ -4,6 +4,7 @@ title: SID-4 - Early Member Definitions vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/early-member-definitions.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/4) diff --git a/_sips/sips/2009-11-02-scala-swing-overview.md b/_sips/sips/2009-11-02-scala-swing-overview.md index 512bef381f..30cc03d95f 100644 --- a/_sips/sips/2009-11-02-scala-swing-overview.md +++ b/_sips/sips/2009-11-02-scala-swing-overview.md @@ -4,6 +4,7 @@ title: SID-8 - Scala Swing Overview vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/scala-swing-overview.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/8) diff --git a/_sips/sips/2010-01-22-named-and-default-arguments.md b/_sips/sips/2010-01-22-named-and-default-arguments.md index f023434109..fecaed1b71 100644 --- a/_sips/sips/2010-01-22-named-and-default-arguments.md +++ b/_sips/sips/2010-01-22-named-and-default-arguments.md @@ -4,6 +4,7 @@ title: SID-1 Named and Default Arguments vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/named-and-default-arguments.html --- **Lukas Rytz** diff --git a/_sips/sips/2010-01-22-scala-2-8-arrays.md b/_sips/sips/2010-01-22-scala-2-8-arrays.md index 0d25473b08..407dc19bf1 100644 --- a/_sips/sips/2010-01-22-scala-2-8-arrays.md +++ b/_sips/sips/2010-01-22-scala-2-8-arrays.md @@ -4,6 +4,7 @@ title: SID-7 - Scala 2.8 Arrays vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/scala-2-8-arrays.html --- *(This is an older SID, its original PDF can be found [here](http://www.scala-lang.org/sid/7))* diff --git a/_sips/sips/2010-01-27-internals-of-scala-annotations.md b/_sips/sips/2010-01-27-internals-of-scala-annotations.md index 06dbb7381e..747c9af8b7 100644 --- a/_sips/sips/2010-01-27-internals-of-scala-annotations.md +++ b/_sips/sips/2010-01-27-internals-of-scala-annotations.md @@ -4,6 +4,7 @@ title: SID-5 - Internals of Scala Annotations vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/internals-of-scala-annotations.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/5) diff --git a/_sips/sips/2010-05-06-scala-specialization.md b/_sips/sips/2010-05-06-scala-specialization.md index b34ebde14c..3acdeab4b0 100644 --- a/_sips/sips/2010-05-06-scala-specialization.md +++ b/_sips/sips/2010-05-06-scala-specialization.md @@ -4,6 +4,7 @@ title: SID-9 - Scala Specialization vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/scala-specialization.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/9) diff --git a/_sips/sips/2010-06-01-picked-signatures.md b/_sips/sips/2010-06-01-picked-signatures.md index cdcef3c707..cffc271a45 100644 --- a/_sips/sips/2010-06-01-picked-signatures.md +++ b/_sips/sips/2010-06-01-picked-signatures.md @@ -4,6 +4,7 @@ title: SID-10 - Storage of pickled Scala signatures in class files vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/picked-signatures.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/10) diff --git a/_sips/sips/2010-07-20-new-collection-classes.md b/_sips/sips/2010-07-20-new-collection-classes.md index 25bff50646..4144a639b8 100644 --- a/_sips/sips/2010-07-20-new-collection-classes.md +++ b/_sips/sips/2010-07-20-new-collection-classes.md @@ -4,6 +4,7 @@ title: SID-3 - New Collection classes vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/new-collection-classes.html --- This was an older SID that can be found [here](http://www.scala-lang.org/sid/3) diff --git a/_sips/sips/2011-10-12-implicit-classes.md b/_sips/sips/2011-10-12-implicit-classes.md index 084fb7d4a5..e8757e4c72 100644 --- a/_sips/sips/2011-10-12-implicit-classes.md +++ b/_sips/sips/2011-10-12-implicit-classes.md @@ -6,6 +6,7 @@ title: SIP-13 - Implicit classes vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/implicit-classes.html --- **By: Josh Suereth** diff --git a/_sips/sips/2011-10-13-string-interpolation.md b/_sips/sips/2011-10-13-string-interpolation.md index de12564ff7..69b807a6da 100644 --- a/_sips/sips/2011-10-13-string-interpolation.md +++ b/_sips/sips/2011-10-13-string-interpolation.md @@ -5,6 +5,7 @@ title: SIP-11 - String Interpolation vote-status: complete vote-text: This SIP has already been accepted and completed. We expect a SIP for 2.11 that will allow the desugared form of interpolated strings in the pattern matcher to become valid syntax. This SIP only allows the sugared interpolated strings to work. permalink: /sips/:title.html +redirect_from: /sips/pending/string-interpolation.html --- **By: Martin Odersky** diff --git a/_sips/sips/2011-10-13-uncluttering-control.md b/_sips/sips/2011-10-13-uncluttering-control.md index bf07845907..5f4dea8d64 100644 --- a/_sips/sips/2011-10-13-uncluttering-control.md +++ b/_sips/sips/2011-10-13-uncluttering-control.md @@ -5,6 +5,7 @@ title: SIP-12 - Uncluttering Scala’s syntax for control structures. vote-status: rejected vote-text: The committee votes unanimously to reject the change. The conclusion is that there is not a clear benefit for it and the required invested time and efforts would be too high. For more explanation, read the minutes. permalink: /sips/:title.html +redirect_from: /sips/pending/uncluttering-control.html --- **By: Martin Odersky** diff --git a/_sips/sips/2012-01-21-futures-promises.md b/_sips/sips/2012-01-21-futures-promises.md index 38a41f4f75..a1b8d43666 100644 --- a/_sips/sips/2012-01-21-futures-promises.md +++ b/_sips/sips/2012-01-21-futures-promises.md @@ -6,6 +6,7 @@ title: SIP-14 - Futures and Promises vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/futures-promises.html --- **By: Philipp Haller, Aleksandar Prokopec, Heather Miller, Viktor Klang, Roland Kuhn, and Vojin Jovanovic** diff --git a/_sips/sips/2012-01-30-value-classes.md b/_sips/sips/2012-01-30-value-classes.md index ec9b91e346..cf8ac211db 100644 --- a/_sips/sips/2012-01-30-value-classes.md +++ b/_sips/sips/2012-01-30-value-classes.md @@ -5,6 +5,7 @@ title: SIP-15 - Value Classes vote-status: complete vote-text: This SIP has already been accepted and completed. There has been concern for numerical computing. We think future SIP(s), using work from SIP-15, can provide more benefit to numerical computing users. The SIP as it exists benefits all users of implicit enrichment classes, and takes us much further to unboxed high performance code. This SIP does not exclude further work towards improving numerical computing in Scala. permalink: /sips/:title.html +redirect_from: /sips/pending/value-classes.html --- **By: Martin Odersky and Jeff Olson and Paul Phillips and Joshua Suereth** diff --git a/_sips/sips/2012-03-09-self-cleaning-macros.md b/_sips/sips/2012-03-09-self-cleaning-macros.md index 65572f5d05..32d50df49f 100644 --- a/_sips/sips/2012-03-09-self-cleaning-macros.md +++ b/_sips/sips/2012-03-09-self-cleaning-macros.md @@ -5,6 +5,7 @@ title: SIP-16 - Self-cleaning Macros vote-status: rejected vote-text: The proposal is rejected unanimously because Scala Meta, the successor metaprogramming tool, is coming soon. For more explanation, read the minutes. permalink: /sips/:title.html +redirect_from: /sips/pending/self-cleaning-macros.html --- diff --git a/_sips/sips/2012-03-13-type-dynamic.md b/_sips/sips/2012-03-13-type-dynamic.md index 16ff7799ac..37385c3c02 100644 --- a/_sips/sips/2012-03-13-type-dynamic.md +++ b/_sips/sips/2012-03-13-type-dynamic.md @@ -5,6 +5,7 @@ title: SIP-17 - Type Dynamic vote-status: complete vote-text: This SIP has already been accepted and completed. permalink: /sips/:title.html +redirect_from: /sips/pending/type-dynamic.html --- diff --git a/_sips/sips/2012-03-17-modularizing-language-features.md b/_sips/sips/2012-03-17-modularizing-language-features.md index 420aedf4d1..b3178ba83f 100644 --- a/_sips/sips/2012-03-17-modularizing-language-features.md +++ b/_sips/sips/2012-03-17-modularizing-language-features.md @@ -5,6 +5,7 @@ title: SIP-18 - Modularizing Language Features vote-status: complete vote-text: This SIP has already been accepted and completed. Let the record show Paul is against it. permalink: /sips/:title.html +redirect_from: /sips/pending/modularizing-language-features.html --- diff --git a/_sips/sips/2012-03-30-source-locations.md b/_sips/sips/2012-03-30-source-locations.md index 255f719d4b..a326ebbd1b 100644 --- a/_sips/sips/2012-03-30-source-locations.md +++ b/_sips/sips/2012-03-30-source-locations.md @@ -6,6 +6,7 @@ title: SIP-19 - Implicit Source Locations vote-status: rejected vote-text: The proposal is rejected. We expect this to be easily implemented using macros without going through a full SIP. A modern implementation can be found here. permalink: /sips/:title.html +redirect_from: /sips/pending/source-locations.html --- **Philipp Haller** diff --git a/_sips/sips/2013-05-31-improved-lazy-val-initialization.md b/_sips/sips/2013-05-31-improved-lazy-val-initialization.md index cdffa3c486..b3fc711ced 100644 --- a/_sips/sips/2013-05-31-improved-lazy-val-initialization.md +++ b/_sips/sips/2013-05-31-improved-lazy-val-initialization.md @@ -6,6 +6,7 @@ title: SIP-20 - Improved Lazy Vals Initialization vote-status: dormant vote-text: This proposal lacks an implementation for Scalac and is looking for a new owner. permalink: /sips/:title.html +redirect_from: /sips/pending/improved-lazy-val-initialization.html --- **By: Aleksandar Prokopec, Dmitry Petrashko, Miguel Garcia, Jason Zaugg, Hubert Plociniczak, Viktor Klang, Martin Odersky** diff --git a/_sips/sips/2013-06-10-spores.md b/_sips/sips/2013-06-10-spores.md index f1f595b621..d182e7d026 100644 --- a/_sips/sips/2013-06-10-spores.md +++ b/_sips/sips/2013-06-10-spores.md @@ -6,6 +6,7 @@ title: SIP-21 - Spores vote-status: "under-review" vote-text: Next iteration takes place in January/February 2017 by request of the authors. permalink: /sips/:title.html +redirect_from: /sips/pending/spores.html --- **By: Heather Miller, Martin Odersky, and Philipp Haller** diff --git a/_sips/sips/2013-06-30-async.md b/_sips/sips/2013-06-30-async.md index 22d8eb48f1..90d602e27e 100644 --- a/_sips/sips/2013-06-30-async.md +++ b/_sips/sips/2013-06-30-async.md @@ -6,6 +6,7 @@ title: SIP-22 - Async vote-status: dormant vote-text: Authors have marked this proposal as dormant. Details in the implementation need to be figured out. Check July 2016's minutes. permalink: /sips/:title.html +redirect_from: /sips/pending/async.html --- **By: Philipp Haller and Jason Zaugg** diff --git a/_sips/sips/2014-06-27-42.type.md b/_sips/sips/2014-06-27-42.type.md index f9ba3c7836..acc3ea1a77 100644 --- a/_sips/sips/2014-06-27-42.type.md +++ b/_sips/sips/2014-06-27-42.type.md @@ -5,6 +5,7 @@ title: SIP-23 - Literal-based singleton types vote-status: complete permalink: /sips/:title.html +redirect_from: /sips/pending/42.type.html --- **Authors: George Leontiev, Eugene Burmako, Jason Zaugg, Adriaan Moors, Paul Phillips, Oron Port, Miles diff --git a/_sips/sips/2015-6-18-repeated-byname.md b/_sips/sips/2015-6-18-repeated-byname.md index 019bed8f99..382767a741 100644 --- a/_sips/sips/2015-6-18-repeated-byname.md +++ b/_sips/sips/2015-6-18-repeated-byname.md @@ -6,6 +6,7 @@ discourse: true vote-status: dormant vote-text: Looking for a new owner. This proposal needs to be updated according to the SIP meeting in November 2016. permalink: /sips/:title.html +redirect_from: /sips/pending/repeated-byname.html --- diff --git a/_sips/sips/2015-6-18-trait-parameters.md b/_sips/sips/2015-6-18-trait-parameters.md index 7460c0bd3d..59b0338140 100644 --- a/_sips/sips/2015-6-18-trait-parameters.md +++ b/_sips/sips/2015-6-18-trait-parameters.md @@ -6,6 +6,7 @@ discourse: true vote-status: "under-review" vote-text: The board agreed to schedule the next iteration of the evaluation process in 6 months, since there’s no implementation yet and the authors need time to produce one. permalink: /sips/:title.html +redirect_from: /sips/pending/trait-parameters.html --- __Martin Odersky__ diff --git a/_sips/sips/2016-01-11-static-members.md b/_sips/sips/2016-01-11-static-members.md index d7f3e83eb8..15f04ffe01 100644 --- a/_sips/sips/2016-01-11-static-members.md +++ b/_sips/sips/2016-01-11-static-members.md @@ -6,6 +6,7 @@ discourse: true vote-status: "under-review" vote-text: Authors need to update the proposal before the next review. permalink: /sips/:title.html +redirect_from: /sips/pending/static-members.html --- __Dmitry Petrashko, Sébastien Doeraene and Martin Odersky__ diff --git a/_sips/sips/2016-06-25-trailing-commas.md b/_sips/sips/2016-06-25-trailing-commas.md index 25af1608d9..9b9023718a 100644 --- a/_sips/sips/2016-06-25-trailing-commas.md +++ b/_sips/sips/2016-06-25-trailing-commas.md @@ -6,6 +6,7 @@ title: SIP-27 - Trailing Commas vote-status: complete vote-text: This SIP has already been accepted and completed, and is a part of Scala 2.12.2. permalink: /sips/:title.html +redirect_from: /sips/pending/trailing-commas.html --- **By: Dale Wijnand** diff --git a/_sips/sips/2016-07-25-unsigned-integers.md b/_sips/sips/2016-07-25-unsigned-integers.md index 8d2d8a5484..8ac64cb337 100644 --- a/_sips/sips/2016-07-25-unsigned-integers.md +++ b/_sips/sips/2016-07-25-unsigned-integers.md @@ -5,6 +5,7 @@ title: SIP-26 - Unsigned Integers vote-status: rejected vote-text: The committee votes to reject the proposal because of a 6% performance hit on the provided implementation by the authors. permalink: /sips/:title.html +redirect_from: /sips/pending/unsigned-integers.html --- __Sébastien Doeraene and Denys Shabalin__ diff --git a/_sips/sips/2016-09-09-inline-meta.md b/_sips/sips/2016-09-09-inline-meta.md index a58cde17f8..803d6dfc05 100644 --- a/_sips/sips/2016-09-09-inline-meta.md +++ b/_sips/sips/2016-09-09-inline-meta.md @@ -6,6 +6,7 @@ title: SIP-28 and SIP-29 - Inline meta vote-status: "under-revision" vote-text: The following proposal has been split and numbered as SIP-28 (Inline) and SIP-29 (Meta). For more information on this decision, check the minutes. The authors need to split the proposal and update it. permalink: /sips/:title.html +redirect_from: /sips/pending/inline-meta.html --- **By: Eugene Burmako, Sébastien Doeraene, Vojin Jovanovic, Martin Odersky, Dmitry Petrashko, Denys Shabalin** diff --git a/_sips/sips/2017-01-11-refer-other-arguments-in-args.md b/_sips/sips/2017-01-11-refer-other-arguments-in-args.md index 9a1adf8ef2..ee6c66f91c 100644 --- a/_sips/sips/2017-01-11-refer-other-arguments-in-args.md +++ b/_sips/sips/2017-01-11-refer-other-arguments-in-args.md @@ -5,6 +5,7 @@ title: SIP-NN - Allow referring to other arguments in default parameters vote-status: pending permalink: /sips/:title.html +redirect_from: /sips/pending/refer-other-arguments-in-args.html --- **By: Pathikrit Bhowmick** diff --git a/_sips/sips/2017-01-13-binary-compatibility.md b/_sips/sips/2017-01-13-binary-compatibility.md index d156a4cc8b..f860dbc678 100644 --- a/_sips/sips/2017-01-13-binary-compatibility.md +++ b/_sips/sips/2017-01-13-binary-compatibility.md @@ -5,6 +5,7 @@ discourse: true vote-status: pending permalink: /sips/:title.html +redirect_from: /sips/pending/binary-compatibility.html --- __Dmitry Petrashko__ diff --git a/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md b/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md index 350e7880b8..95c73ab90d 100644 --- a/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md +++ b/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md @@ -5,6 +5,7 @@ title: SIP-33 - Priority-based infix type precedence vote-status: complete permalink: /sips/:title.html +redirect_from: /sips/pending/priority-based-infix-type-precedence.html --- **By: Oron Port** diff --git a/_sips/sips/2017-02-22-comonadic-comprehensions.md b/_sips/sips/2017-02-22-comonadic-comprehensions.md index 726a0391bf..3b56dacf2b 100644 --- a/_sips/sips/2017-02-22-comonadic-comprehensions.md +++ b/_sips/sips/2017-02-22-comonadic-comprehensions.md @@ -5,6 +5,7 @@ title: SIP-NN - comonadic-comprehensions vote-status: rejected permalink: /sips/:title.html +redirect_from: /sips/pending/comonadic-comprehensions.html --- **By: Shimi Bandiel** diff --git a/_sips/sips/2017-07-12-right-associative-by-name-operators.md b/_sips/sips/2017-07-12-right-associative-by-name-operators.md index 38fa789572..bf85d747a7 100644 --- a/_sips/sips/2017-07-12-right-associative-by-name-operators.md +++ b/_sips/sips/2017-07-12-right-associative-by-name-operators.md @@ -5,6 +5,7 @@ title: SIP-34 - Right-Associative By-Name Operators vote-status: accepted permalink: /sips/:title.html +redirect_from: /sips/pending/right-associative-by-name-operators.html --- **By: Stefan Zeiger** diff --git a/_sips/sips/2017-09-20-opaque-types.md b/_sips/sips/2017-09-20-opaque-types.md index 8e0a0fa9bd..7c8d5e3444 100644 --- a/_sips/sips/2017-09-20-opaque-types.md +++ b/_sips/sips/2017-09-20-opaque-types.md @@ -4,6 +4,7 @@ title: SIP-35 - Opaque types vote-status: pending permalink: /sips/:title.html +redirect_from: /sips/pending/opaque-types.html --- **Authors: Erik Osheim and Jorge Vicente Cantero** diff --git a/_sips/sips/2017-10-25-adding-prefix-types.md b/_sips/sips/2017-10-25-adding-prefix-types.md index b0b492fe3a..1c9d1aa347 100644 --- a/_sips/sips/2017-10-25-adding-prefix-types.md +++ b/_sips/sips/2017-10-25-adding-prefix-types.md @@ -5,6 +5,7 @@ title: SIP-36 - Adding prefix types vote-status: pending permalink: /sips/:title.html +redirect_from: /sips/pending/adding-prefix-types.html --- **By: Oron Port** diff --git a/_sips/sips/2017-11-20-byname-implicits.md b/_sips/sips/2017-11-20-byname-implicits.md index 9129e018e7..d9ac182339 100644 --- a/_sips/sips/2017-11-20-byname-implicits.md +++ b/_sips/sips/2017-11-20-byname-implicits.md @@ -5,6 +5,7 @@ title: SIP-NN - Byname implicit arguments vote-status: pending permalink: /sips/:title.html +redirect_from: /sips/pending/byname-implicits.html --- **Author: Miles Sabin** From 179402e1ddef5de35bf51059c3ece3b64ad3241a Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 2 Apr 2018 11:32:45 +0200 Subject: [PATCH 0166/3174] Fix link broken by rename of file --- _sips/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sips/index.md b/_sips/index.md index 413cb896ea..bdb8fee062 100644 --- a/_sips/index.md +++ b/_sips/index.md @@ -39,7 +39,7 @@ Please read [Submitting a SIP](./sip-submission.html) and our > Historical note: The SIP replaces the older SID (Scala Improvement Document) process. > Completed SID documents remain available in the -> [completed section of the SIP list](sip-list.html). +> [completed section of the SIP list](all.html). ## Scala Platform Process (SPP) From c4edc235fc7c08e9d82cc4e2526405297a821ed0 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 2 Apr 2018 11:55:49 +0200 Subject: [PATCH 0167/3174] Make the link checker pass --- _sips/minutes/2016-07-15-sip-minutes.md | 6 +- .../2016-08-16-sip-10th-august-minutes.md | 8 +- .../2016-09-20-sip-20th-september-minutes.md | 2 +- _sips/minutes/2016-10-25-sip-minutes.md | 2 +- _sips/minutes/2016-11-29-sip-minutes.md | 8 +- _sips/minutes/2017-02-14-sip-minutes.md | 8 +- _sips/minutes/2017-09-21-sip-minutes.md | 2 +- _sips/minutes/2017-10-24-sip-minutes.md | 2 +- .../minutes/_posts/2017-02-14-sip-minutes.md | 260 ------------------ _sips/sip-submission.md | 2 +- 10 files changed, 20 insertions(+), 280 deletions(-) delete mode 100644 _sips/minutes/_posts/2017-02-14-sip-minutes.md diff --git a/_sips/minutes/2016-07-15-sip-minutes.md b/_sips/minutes/2016-07-15-sip-minutes.md index d72ed724cc..40d2083b5f 100644 --- a/_sips/minutes/2016-07-15-sip-minutes.md +++ b/_sips/minutes/2016-07-15-sip-minutes.md @@ -12,10 +12,10 @@ The following agenda was distributed to attendees: | Topic | Reviewer | | --- | --- | | [Discussion of the new SIP process](http://docs.scala-lang.org/sips/sip-submission.html) | Jorge Vicente Cantero | -| [SIP 25 - Trait parameters](http://docs.scala-lang.org/sips/pending/trait-parameters.html) | Adriaan Moors | +| [SIP 25 - Trait parameters](http://docs.scala-lang.org/sips/trait-parameters.html) | Adriaan Moors | | [SIP 26 - Unsigned Integer Data Types](https://github.com/scala/slip/pull/30) | Martin Odersky | -| [SIP 22 - Async](http://docs.scala-lang.org/sips/pending/async.html) | Eugene Burmako | -| [SIP 20 - Improved lazy val initialization](http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html) | Sébastien Doeraene | +| [SIP 22 - Async](http://docs.scala-lang.org/sips/async.html) | Eugene Burmako | +| [SIP 20 - Improved lazy val initialization](http://docs.scala-lang.org/sips/improved-lazy-val-initialization.html) | Sébastien Doeraene | | [Trailing commas SIP](https://github.com/scala/docs.scala-lang/pull/533) | Eugene Burmako | Quick iteration through all the SLIPs: diff --git a/_sips/minutes/2016-08-16-sip-10th-august-minutes.md b/_sips/minutes/2016-08-16-sip-10th-august-minutes.md index c10feb9347..9971d5810c 100644 --- a/_sips/minutes/2016-08-16-sip-10th-august-minutes.md +++ b/_sips/minutes/2016-08-16-sip-10th-august-minutes.md @@ -11,11 +11,11 @@ The following agenda was distributed to attendees: | Topic | Reviewer | | --- | --- | -| [SIP-12: Uncluttering Scala's syntax for control structures](http://docs.scala-lang.org/sips/pending/uncluttering-control.html) | Seth Tisue | +| [SIP-12: Uncluttering Scala's syntax for control structures](http://docs.scala-lang.org/sips/uncluttering-control.html) | Seth Tisue | | [SIP-16: Self-cleaning macros](http://docs.scala-lang.org/sips/self-cleaning-macros.html) | Eugene Burmako | -| [SIP-21: Spores](http://docs.scala-lang.org/sips/pending/spores.html) | Martin Odersky | -| [SIP-23: Literal-based singleton types](http://docs.scala-lang.org/sips/pending/42.type.html) | Adriaan Moors | -| [SIP-24: Repeated by-name parameters](http://docs.scala-lang.org/sips/pending/repeated-byname.html) | Andrew Marki | +| [SIP-21: Spores](http://docs.scala-lang.org/sips/spores.html) | Martin Odersky | +| [SIP-23: Literal-based singleton types](http://docs.scala-lang.org/sips/42.type.html) | Adriaan Moors | +| [SIP-24: Repeated by-name parameters](http://docs.scala-lang.org/sips/repeated-byname.html) | Andrew Marki | | [SIP-27: Trailing commas](https://github.com/scala/docs.scala-lang/pull/533#issuecomment-232959066) | Eugene Burmako | Jorge Vicente Cantero was the Process Lead and acting secretary of the meeting. diff --git a/_sips/minutes/2016-09-20-sip-20th-september-minutes.md b/_sips/minutes/2016-09-20-sip-20th-september-minutes.md index fd163d66d7..fe5bd46fe5 100644 --- a/_sips/minutes/2016-09-20-sip-20th-september-minutes.md +++ b/_sips/minutes/2016-09-20-sip-20th-september-minutes.md @@ -12,7 +12,7 @@ The following agenda was distributed to attendees: | Topic | Reviewer | | --- | --- | | [SIP-NN: Scala Meta SIP](https://github.com/scala/docs.scala-lang/pull/567) | Iulian Dragos and Josh Suereth | -| [SIP-21: Spores](http://docs.scala-lang.org/sips/pending/spores.html) | Martin Odersky | +| [SIP-21: Spores](http://docs.scala-lang.org/sips/spores.html) | Martin Odersky | | [SIP-26: Unsigned Integer Data Types](https://github.com/scala/slip/pull/30) | Martin Odersky | | [SIP-27: Trailing commas](https://github.com/scala/docs.scala-lang/pull/533#issuecomment-232959066) | Eugene Burmako | diff --git a/_sips/minutes/2016-10-25-sip-minutes.md b/_sips/minutes/2016-10-25-sip-minutes.md index 572737e611..e4db397ee6 100644 --- a/_sips/minutes/2016-10-25-sip-minutes.md +++ b/_sips/minutes/2016-10-25-sip-minutes.md @@ -12,7 +12,7 @@ The following agenda was distributed to attendees: | Topic | Reviewer | | --- | --- | | Discussion of the voting system | N/A | -| [SIP-20: Improved Lazy Val Initialization](http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html) | Sébastien Doeraene | +| [SIP-20: Improved Lazy Val Initialization](http://docs.scala-lang.org/sips/improved-lazy-val-initialization.html) | Sébastien Doeraene | | [SIP-27: Trailing commas](https://github.com/scala/docs.scala-lang/pull/533#issuecomment-232959066) | Eugene Burmako | Jorge Vicente Cantero was the Process Lead and acting secretary of the meeting. diff --git a/_sips/minutes/2016-11-29-sip-minutes.md b/_sips/minutes/2016-11-29-sip-minutes.md index 9ccb1b21ad..81b1e6e3e0 100644 --- a/_sips/minutes/2016-11-29-sip-minutes.md +++ b/_sips/minutes/2016-11-29-sip-minutes.md @@ -11,8 +11,8 @@ The following agenda was distributed to attendees: |Topic|Reviewers| Accepted/Rejected | | --- | --- | --- | -| [SIP-28 and SIP-29 - Inline and meta](http://docs.scala-lang.org/sips/pending/inline-meta.html) | Josh Suereth and Iulian Dragos | Pending | -| [SIP-24 - Repeated By Name Parameters](http://docs.scala-lang.org/sips/pending/repeated-byname.html) | Heather Miller | Pending | +| [SIP-28 and SIP-29 - Inline and meta](http://docs.scala-lang.org/sips/inline-meta.html) | Josh Suereth and Iulian Dragos | Pending | +| [SIP-24 - Repeated By Name Parameters](http://docs.scala-lang.org/sips/repeated-byname.html) | Heather Miller | Pending | | [SIP-25:Static](https://github.com/scala/docs.scala-lang/pull/491/files)| Adriaan Moors | Pending | |[SIP-27: Trailing commas](http://docs.scala-lang.org/sips/completed/trailing-commas.html)|Eugene Burkamo| Accepted | @@ -42,7 +42,7 @@ Minutes were taken by Travis Lee. **Jorge** We'll talk about the SIPS for Scala Meta. Eugene will start. -### [SIP-28 and SIP-29 - Inline and meta](http://docs.scala-lang.org/sips/pending/inline-meta.html) +### [SIP-28 and SIP-29 - Inline and meta](http://docs.scala-lang.org/sips/inline-meta.html) Eugene and co have been working hard for two months on inline and Scala Meta. Previously discussed new macro system with new inline and meta features. Inline provides a facility to declare methods with inline right hand side into call side (0:01:24) and meta implements compile-time function execution to do meta-programming. Martin implemented inline mechanism in Dotty. Eugene worked on macro notations. New style macros will integrate with tools. Eugene shows how it works in IntelliJ. For example, you can print the value of the parameters. Meta blocks supported by IntelliJ. So are quasi-quotes. You can also expand macros. Will greatly help debugability. @@ -52,7 +52,7 @@ The spec needs to be updated based on Martin's Dotty implementation. We need to **Conclusion** This proposal needs at least another iteration to shape up and provide concrete implementation and specification details. This proposal is therefore under revision -- Eugene, the author, will gather and address more feedback and will resubmit the proposal to analysis when it's ready. -### [SIP-24 - Repeated By Name Parameters](http://docs.scala-lang.org/sips/pending/repeated-byname.html) +### [SIP-24 - Repeated By Name Parameters](http://docs.scala-lang.org/sips/repeated-byname.html) Heather says the debate is about the semantics or translation rules. All arguments are evaluated each time the parameter is referenced in the method. This is implemented in Dotty. Should this be implemented in Scalac? diff --git a/_sips/minutes/2017-02-14-sip-minutes.md b/_sips/minutes/2017-02-14-sip-minutes.md index 6e96dc9931..b58ea431f5 100644 --- a/_sips/minutes/2017-02-14-sip-minutes.md +++ b/_sips/minutes/2017-02-14-sip-minutes.md @@ -11,10 +11,10 @@ The following agenda was distributed to attendees: | Topic | Reviewer | | --- | --- | -| [SIP-XX: Improving binary compatibility with @stableABI](http://docs.scala-lang.org/sips/pending/binary-compatibility.html) | Dmitry Petrashko | -| [SIP-NN - Allow referring to other arguments in default parameters](http://docs.scala-lang.org/sips/pending/refer-other-arguments-in-args.html) | Pathikrit Bhowmick | -| [SIP 25 - @static fields and methods in Scala objects(SI-4581)](http://docs.scala-lang.org/sips/pending/static-members.html) | Dmitry Petrashko, Sébastien Doeraene and Martin Odersky | -| [SIP-33 - Match infix & prefix types to meet expression rules](http://docs.scala-lang.org/sips/pending/make-types-behave-like-expressions.html) | Oron Port | +| [SIP-XX: Improving binary compatibility with @stableABI](http://docs.scala-lang.org/sips/binary-compatibility.html) | Dmitry Petrashko | +| [SIP-NN - Allow referring to other arguments in default parameters](http://docs.scala-lang.org/sips/refer-other-arguments-in-args.html) | Pathikrit Bhowmick | +| [SIP 25 - @static fields and methods in Scala objects(SI-4581)](http://docs.scala-lang.org/sips/static-members.html) | Dmitry Petrashko, Sébastien Doeraene and Martin Odersky | +| [SIP-33 - Match infix & prefix types to meet expression rules](http://docs.scala-lang.org/sips/priority-based-infix-type-precedence.html) | Oron Port | Jorge Vicente Cantero was the Process Lead. Travis (@travissarles) was acting secretary of the meeting. diff --git a/_sips/minutes/2017-09-21-sip-minutes.md b/_sips/minutes/2017-09-21-sip-minutes.md index 75fceb11ab..62e862a24a 100644 --- a/_sips/minutes/2017-09-21-sip-minutes.md +++ b/_sips/minutes/2017-09-21-sip-minutes.md @@ -87,7 +87,7 @@ Syntax "new" "type" Still waiting on the implementation updates, therefore this item will be discussed in the next SIP Meeting. -### [SIP-28 and SIP-29: Inline and meta](http://docs.scala-lang.org/sips/pending/inline-meta.html) +### [SIP-28 and SIP-29: Inline and meta](http://docs.scala-lang.org/sips/inline-meta.html) [YouTube time: 51'40'' until the end](https://youtu.be/yzTpVbTUj18?t=3100) **Eugene** gives a brief history of this SIP development, shares the good news and suggests how to proceed. diff --git a/_sips/minutes/2017-10-24-sip-minutes.md b/_sips/minutes/2017-10-24-sip-minutes.md index 0f9c9cc4f0..f821138c57 100644 --- a/_sips/minutes/2017-10-24-sip-minutes.md +++ b/_sips/minutes/2017-10-24-sip-minutes.md @@ -75,7 +75,7 @@ The feedback will be given to the author. -### [SIP-28 and SIP-29: Inline and meta](http://docs.scala-lang.org/sips/pending/inline-meta.html) +### [SIP-28 and SIP-29: Inline and meta](http://docs.scala-lang.org/sips/inline-meta.html) [YouTube time: 10'05'' until the end](https://youtu.be/aIc-o1pcRhw?t=605) **Jorge** introduces **Olaf** as a new Team Lead of SIP-28 and SIP-29. diff --git a/_sips/minutes/_posts/2017-02-14-sip-minutes.md b/_sips/minutes/_posts/2017-02-14-sip-minutes.md deleted file mode 100644 index bede6382e2..0000000000 --- a/_sips/minutes/_posts/2017-02-14-sip-minutes.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -layout: sips -title: SIP Meeting Minutes - 14th February 2017 ---- - -# Minutes - -The following agenda was distributed to attendees: - -| Topic | Reviewer | -| --- | --- | -| [SIP-XX: Improving binary compatibility with @stableABI](http://docs.scala-lang.org/sips/pending/binary-compatibility.html) | Dmitry Petrashko | -| [SIP-NN - Allow referring to other arguments in default parameters](http://docs.scala-lang.org/sips/pending/refer-other-arguments-in-args.html) | Pathikrit Bhowmick | -| [SIP 25 - @static fields and methods in Scala objects(SI-4581)](http://docs.scala-lang.org/sips/pending/static-members.html) | Dmitry Petrashko, Sébastien Doeraene and Martin Odersky | -| [SIP-33 - Match infix & prefix types to meet expression rules](http://docs.scala-lang.org/sips/pending/make-types-behave-like-expressions.html) | Oron Port | - -Jorge Vicente Cantero was the Process Lead. Travis (@travissarles) was acting secretary of the meeting. - -## Date, Time and Location - -The meeting took place at 5:00pm Central European Time / 8:00am Pacific Daylight -Time on Tuesday, 14th February 2017 via Google Hangouts. - -Minutes were taken by Travis Lee, acting secretary. - -## Attendees - -Attendees Present: - -* Martin Odersky ([@odersky](https://github.com/odersky)), EPFL -* Dmitry Petrashko ([@DarkDimius](https://github.com/DarkDimius)), EPFL -* Lukas Rytz (Taking Adriaan Moore's place) ([@lrytz](https://github.com/lrytz)), Lightbend -* Seth Tisue ([@SethTisue](https://github.com/SethTisue)), Lightbend -* Iulian Dragos ([@dragos](https://github.com/dragos)), Independent -* Sébastien Doeraene ([@sjrd](https://github.com/sjrd)), EPFL -* Eugene Burmako ([@xeno-by](https://github.com/xeno-by)), EPFL -* Jorge Vicente Cantero ([@jvican](https://github.com/jvican)), Process Lead - -Absent: -* Heather Miller ([@heathermiller](https://github.com/heathermiller)), Scala Center -* Josh Suereth ([jsuereth](https://github.com/jsuereth)), Independent - -## Proceedings - -### Opening Remarks - -### SIP 25 - @static fields and methods in Scala objects(SI-4581) -Jorge asks Dmitry to explain the biggest changes since the last proposal. -The biggest changes were addressing the feedback of the reader. -**Dmitry** First, he covers whether the static annotation can behave like the tail recursive annotation, which doesn't actually impact compilation but only warns if it isn't possible to make something static. Dmitry doesn't think the static annotation should have the same semantics because it affects binary compatibility. - -Also, it depends on the superclass. If the superclass defined a field with the same name, the subclass can't have it. If we decide to make something static, we only be able to do it if the superclass doesn't have the fields with the same name. If static is done automatically and not triggered by the user we will enforce very strong requirements on superclass objects which is no-go. - -I proposed a scheme (which I elaborate more on the details frictions in the SIP). I present several examples of possible issues in this case. - -The other question was clarify how does the static effect initialization order and also describe if it effects binary compatibility. In general, emitting fields as static changes when they get initialized. They get initialized when the class is being class-loaded. The SIP in the current state requires static fields to be the first field defined in the object which means that these fields will be initialized before the other fields (indepenently of whether they are marked static or not). This leads to the fact that inside the object itself it will be possible to observe if something is static or not. Unless you rely on some class loader magic or reflection. At the same time, it is still possible to observe whether a field is static or not using multiple classes. Let's say you have a superclass of the object. If the superclass tries to see if the static field is initialized. In the case the field is static, it will be initialized before the superclass constructor executes. In case it's not static, it won't be initialized. - -In short, it can make initlization happen earlier but never later. By enforcing syntax restriction would make it harder to observe this. But still it is possible to observe initialization requirements. This is a sweet spot because static should be independent. The point is you want some fields to be initialized without the initialization of an entire object. There is a side-effect that an object is initialized and there are multiple ways to observe it somehow. - -The current SIP tries to make it behave as expected by the users in common cases. - -**Lukas** Let's take a simple example, you have an object with a static field and a non-static field. Now the user code, the program access the non=static field first. That means the module gets initialized, but the static field lives in the companion class, right? So the static field is not initialized necessary even though you access the module. Assuming the field initializers have side effects then you can observe the differences. Then the static field will only be initialized at some point later when you use the class and not when you access the module. - -**Dmitry** The idea is that the module should force execution of static initializers of the fields of the companion class. Which means that you won't be able to observe the difference in the order. It will look like all of them initialized at the same time. - -**Martin** How can that be done? - -**Dmitry** Just refer to the class in bytecode. Just mention the signature. - -**Martin** Does that mean we have to change the immediate code to enforce that? - -**Dmitry** Yeah you need to make one reference. It's very easy to write an expression in Scala which returns a null but ____ (7:45) - -**Martin** Sure but we can't do that right now. - -**Dmitry** I wouldn't do it. - -**Martin** Are there good reasons to do that anyway? - -**Dmitry** Maintaining semantics. If we don't do it, you can observe the fact that some fields are initialized, some aren't. - -**Martin** But we only have to do it for those companion objects that have both statics and fields. It doesn't leak into binary compatibility. - -**Jorge** You mentioned syntactic restrictions. Which kind? - -**Dmitry** Static fields should proceed any non-static fields. the fact that static fields can be initialized earlier but not later means that you won't be able to observe the fact ____ (8:40). If we were to allow non static fields to proceed, because static fields can be initialized earlier, you can see ____. - -**Sébastien** What about non-field statements? - -**Dmitry** They should also be after all the statics. - -**Sébastien** That's not written in the SIP. - -**Dmitry** Will update. The last question is whether it will effect binary compatibility. YES! The point is you should be able to call and access stuff which is static through a more efficient way on the JVM. So removing @static annotation will be a binary incompatible change. If we add forwarders, adding static won't be a binary incompatible change because you'll still have fowarders which forward to the static thing. Both methods and fields. - -**Lukas** But static fields are emitted as just fields and there's not getters and setters? - -**Dmitry** Yes, but all the static stuff is emitted in the class. The question would be whether we emit anything in the object. We can still emit getter and setter in the object which will allow us to maintian binary compatibility with stuff which was compiled before static annotation was added. By following this idea, adding static is binary compatible,removing isn't. - -**Sébastien** There's also an accessory to implement abstract definitions coming from a superclass or even overriding. - -**Dmitry** With current the current proposal static fields don't implement and don't override stuff. It's forbidden to define a static field or method if there is a thing with the same name defined in any of the superclasses. - -**Jorge** That would mean that you can't add static fields without hurting binary compatibility because if you cannot override, then you want to emit a static field which has a concrete name but that name is inherited from a super trait. - -**Dmitry** It won't compile then. It doesn't follow the requirements. If it compiles, it will be binary compatible. - -**Sébastien** What if the superclass of the object defines something with the same name? There's nothing that prevents me from implemnting or overriding something from the superclass of the object. I think that's fine. - -**Dmitry** The question would be about the initialization order - -**Sébastien** It's not a problem because if you call it via the super class it means you haven't initialized the object completely anyway already. - -**Dmitry** First of all it will disallow us to emit the final flag simply because final static fields can only be initialized from the static constructor. So if you have a final static field it can't implement setters. - -**Sébastien** But you can't have a getter and a setter that read and write the static field. - -**Dmitry** You can't write a _static final_ field again. Static fields are fine. If the static initialization is final, the only place where instructions which are writing it are allowed by hotspot are static initializer. So a possible restriction would be to say static final fields can't implement super class signatures. It would be very good to emit real static final fields because hotspot includes optimizations of those. Let's say if you were to discover some configuration statically and then use this to decide whether your implementation will take one branch or another, JIT will be able to ____ (14:32) eliminate this stuff. If the field isn't static, isn't final you don't have this guarantee. - -**Iulian** And do you need the setter even for vars? If you've marked it final only for vars would that work? - -**Dmitry** If it implements a super-trait vals, traits still have setters, even for vals. - -**Sébastien** Yes, but that's only if it's mixed in. If it's overridden in the object, you don't need the setter. And if it's mixed in from the interface it doesn't have the static annotation anyway because that's now how ____ (15:20). - -**Martin** Does it even have setters anymore? In dotty it definitely doesn't. I thought in 2.12 they changed the scheme now as well for trait vals. I don't think they require setters anymore. - -**Dmitry** We don't require them but I'm not sure about Scalac. Does Scalac use initializers or trait setters? - -**Sébastien** Trait setters. - -**Dmitry** For us, we can easily say that we support final but we're trying to take into account scalac. So is there some important use case where you want to have static fields implement not-static signatures. - -**Sébastien** No. - -**Dmitry** Would you be willing to lean on a conservative way in this case? - -**Sébastien** I was just trying to understand why there is a restriction. There doesn't seem to be any reason to but if there is a reason to, I don't see a use case. - -**Dmitry** I would propose to record this but not change the SIP. To summarize in short, static is an annotation which does affect the compilation scheme which enforces some requirements where it can be which try to hide the fact that semantic would have changed by making it hard to observe this. The assumption is that most common users won't be able to observe the difference in semantics because we've restricted the syntax so that it would be hard to observe it. At the same time, for advanced users, it would allow to emit static fields and methods which will help if someone wants to write highly optimized code or interact with Java. I think the SIP is good as is. Given the fact ____ proposed some suggestions and clarifications about actual changes. - -**Jorge** The question is whether this should be accepted or not. The problem is we don't have any implementation for Scalac. Does someone at Lightbend plan to work on this sometime soon? - -**Seth** I don't think that's something we've discussed as a team yet. - -**Jorge** We have to pass here both on this proposal as is right now but I think this could be dangerous in the case where we don't have an implementation for Scalac because maybe the details change and assume something in Scalac that the SIP is not able to predict or guard against it. Let's wait until next month and I will double check whether this is possible or not. Then I will get in touch with the Lightbend team to see whether this can be implemented or not. We'll decide in a month whether it should be accepted. - -**Sébastien** ScalaJS already implemented it under another name but it's supposed to be conservative with respect to the aesthetic SIP in the sense that things that are allowed now with @jsstatic will also be allowed with @static. @static might open up a little bit more. - -**Conclusion** The static SIP proposal has to be implemented in Scala, as it's already present in Dotty. Triplequote (Iulian Dragos and Mirco Dotta) has offered to provide an implementation targeting 2.12.3. - -### SIP-NN - [Allow referring to other arguments in default parameters](https://github.com/scala/docs.scala-lang/pull/653) (22:30) -Sébastien is the reviewer of this proposal. - -**Sébastien** The SIP is a generalization of why we can use in default values of parameters. Especially referring to other arguments. In current Scala we can refer to arguments in previous parameter lists. This SIP wants to open that up. The way it's currently written, any parameter whether it's in the same parameter list or a previous one, it's also allowed to refer to argument on the right. The text needs to be elaborated on use cases. Doesn't address implementation concerns. Jorge answered on the PR with analysis of feasibility. I'm convinced that the version where we can also refer to a parameter on the right is infeasible because you can have arbitrary cycles and you don't know _______ ( 24:55) and it's completely impossible. - -Other than that, in principle the SIP looks reasonable. It's possible to implement but it will cause more bytecode because now the third parameter will always need to receive the first two parameters to decide its value. We cannot decide that whether based on the default value actually refers to the previous parameters because that would be unstable in respect to binary compatibility. You need to always give to the default accessor all the prior parameters and that means it can potentially increase bytecode size. That needs to be analyzed maybe with a prototype, compare with Scala library. - -**Jorge** I implemented this. I did a study and analysis of whether referring to parameters on the right is visible and I've explained in a comment in the PR why it's not. Basically this is a change that would require breaking binary compatibility and this would be targeting 2.13 so we are not gonna see it any time soon. I think that it would be very useful to have a look at the numbers to see how it affects bytecode size. I'll run some benchmarks and [report the results in the PR](https://github.com/scala/scala/pull/5641). - -**Sébastien** SIP addendum, Type Members: In current Scala in the same way that you can only refer to parameters on terms previous parameter lists you can also only refer to path-dependent types of parameters in previous parameter lists and there is a small section in the SIP that says in the same vein we should allow to refer to path-dependent types of parameters in the same parameter list probably on the left. But for that one I don't have a good intuition of what effects it would have on type inference because type inference works parameter list per parameter list. The fact that you cannot refer to path-dependent types from the same parameter list means you can complete type inference from one parameter list without juggling path-dependent types within the same thing. Then when you move to the next one it's already inferred from the previous parameters. So it seems simpler but it's just a guest. Martin, would that be problematic? - -**Martin** It would be a completely sweeping change. It's one of the key types that suddenly becomes recursive. So you can imagine what that means. Every time we construct such a type we can't do it inductively anymore. So basically it's the difference between polytypes and method types. I'm not saying it's impossible but it would be a huge change the compiler to do that. It's probably beyond what we can do for Scalac and just for Dotty we could think about it but it would be a very big change. - -**Conclusion** The proposal has been numbered as SIP-32. The reference to type members seems tricky in implementation and interaction and it may be removed as the analysis of this SIP continues. The reference to other arguments in the same parameter list has been implemented by Jorge in [scala/scala#5641](https://github.com/scala/scala/pull/5641). - -### SIP-XX: Improving binary compatibility with @stableABI (33:30) -**Dmitry** This proposes annotations which does not change the compilation scheme. A bit of background, Scala is being released with versions which can be either minor or major. So 2.11 is major version compared to 2.10. 2.11.1 and 2.11.2 are minor versions. Scala currently guarantees binary-compatibility between minor versions. At the same time, big parts of the scala community live in different major versions of the compiler which require them to publish artifacts multiple times because the same artifact will be incompatible if used in a different compiler. - -**Martin** Or write it in Java - -**Dmitry** The current situations has several solutions. The first is write it in Java, the second is make it a source dependency, download the source, and compile it in runtime and the third one use your best judgement is to try to write Scala which you assume will be safe. At the same time there is a tool which is called MiMa which helps you to see whether you did it right. MiMa allows you to compare two already-compiled artifacts and say whether they're compatible or not. This SIP proposes something which will complement MiMa in indicating whether the thing will be compatible with the next version. So currently if you were to write a file in Scala compiled with 2.10 and then compile it to 2.11, MiMa can after-the-fact say that it's incompatible and previous version should have been more conservative with the features it used. It does it after the fact when 2.11 was already released. Your artifacts are already on Bintray and it's too late. stableABI augments this use case by allowing you to get a guarantee that this artifact will be reliably compiled by all the compilers which call themselves Scala, across all the major versions, and can be used by the code compiled by those compilers. The idea would be that stableABI classes can be either used for projects which need to survive multiple Scala major versions or for other languages which don't have such a strong binary API guarantee such as Java and Kotlin. And additionally it has a very strong use case of allowing to use features of future compilers and future language releases in libraries which try to support users who are still on the old versions. - -There are multiple use cases covered by this SIP. I think the two most important ones which are coming now are the migration from Dotty to Scala and the fact that we'll have two major releases existing at the same time. It would be nice if there was a common language for two compilers where people can reliably be in the safe situation publishing wise. If they publish an artifact compiled by Dotty, it can be safely used by Scalac, even if internally they use DOT advanced features. At the same time they won't be sure that they can use some features of Scalac that Dotty doesn't support and they will be able to use them inside the classes as long as they don't leak. So stableABI adds a check to the compiler which more or less ensures that there is no leakage of advanced features being used which could affect binaryABI. The guarantee which is assumed to be provided is if the same class is compiled with stableABI and it succeeds compilation it can be a replacement for the previous class if compiled by a different compiler. If the class has been changed by the user, they should use MiMa to find that the change was binary incompatible. - -**Eugene** The migration to Dotty is something that is highly anticipated in the community. Concrete proposals are hard to facilitate this change. It's gonna be a big change. Very welcome. How do you write stuff that's going to be used from Java reliably? - -**Martin** What I didn't see in the proposal was, so to move this forward you need to specify a minimum set of features that will be under stableABI. So if I write stableABI, you have to specify at least which sort of features will be accepted by the compiler. - -**Dmitry** Instead of specify which features will be accepted, I said that the ground truth will be the source code. So the rule that is currently written is if compiler changes the signature from the one written by the user, it shouldn't be stableABI. The current specification more or less says if something isn't de-sugared in a way that affects stableABI, it's supported. We can additionally list features which aren't affected by this. But I think that the actual implementation, true, should be a strong overestimation. - -**Martin** But in the end because it's something that binds not just the current compilers but all future compilers, once you guarantee a feature of stableABI you have to keep it. You can't change it anymore. So it needs to have a very strong specification what this is and the minimal one too. We don't want to overcommit ourselves. - -**Dmitry** stableABI says how do you consume the class if it's successfully compiled. So let's say a future compiler fails to compile it, it's perfectly fine. We're talking about stableABI, not stable source code. Similarly, one of the motivations is there is some use cases which are compiled by Scalac... - -**Martin** You say I have stableABI and Scala 2.12 accepts it and then Scala 2.13 comes up and says now I changed this thing so I won't compile this anymore. - -**Dmitry** But you can still use the artifact compiled by the previous one. - -**Martin** So you can break it, but you have to tell the user that you broke it. - -**Dmitry** There will be a compilation error that says doesn't compile. - -**Martin** I guess there would be a strong normative thing to say, well once one compiler guarantees certain things are okay under stableABI, future compilers will try not to break that. Otherwise, it wouldn't be that useful. - -**Dmitry** It would be a nice guarantee to have. But so far the SIP tries to ensure more or less safe publication on the maven so the artifact can be consumed reliably by the users. It's more providing safety for the users, not for the creator of the library. - -**Martin** In the end the compiler will have to check it and I think we have to give guidance to compilers what they should accept under stableABI. - -**Dmitry** Do you think there should be a minimal set of features which is accepted and there should be a warning if there is a feature used outside of this set? - -**Martin** Yes. We want to start now. Because I use something that a future compiler will break and it's not very useful to find out I can't upgrade my stuff because it's no longer stableABI. It will be useful that the compiler tells me now, look this thing is not guaranteed to be maintained in all future versions. Don't use it if you want to have an abstraction that for interchange. - -**Dmitry** The binary compatibility is if you've already compiled it, you can just give the compiled artifact to the future compiler which will safely consume it. It doesn't mean that the future compiler can compile it. But you can use the already compiled artifact. - -**Martin** I would think it would be much more interesting if it were source as well. That the future compiler would guarantee to compile it to the same bytecodes. Why do people write stuff in Java instead of Scala? Because you can't recompile this thing in a future compiler. We don't know whether the layout is the same or not so that was the thing where we need an antidote and say no if you write stableABI then even a Scala compiler will guarantee that it will be the same in future versions. If the thing succeeds in source, then it will be mapped to the same binary signatures as previously. We need to define a feature set now where that will be the case. Otherwise how are you going to implement that? - -**Dmitry** The current proposed criteria is it's the same signature written by the user. No de-sugarings for users. Let's say a user uses repeated arguments. Repeated arguments changes the binary signature. If the compiler can't add new members to stableABI classes and the compiler can't change the binary ____ for existing members. For vals, we synthesize a getter. You have a member of the class which was written by the user. Similarly for vars you also get a setter. Lazy vals gets the accessor which lazy vals synthesize two members which have funny signatures and they have funny names. Default methods is a thing which is checked explicitly here. It's the only thing. - -**We need this both in spec and doc**. - -**Dmitry** If you have a stableABI class, can it's arguments take a Scala Option or not? Currently Option is not a stableABI class which means you can be in a funny situation in which you succeed to call a method which takes an option, during the execution it fails _____ (50:13). The current proposal says that if you take non-stableABI classes as arguments or return types it gives you a warning. There isn't an all-or nothing approach that gets implemented. The proposal is that one day the library may decide to have some superclasses which it promises are stableABI for collections, for options, for all the types that are stable. This will be API to use those classes from stableABI classes and from other languages. - -**Sébastien** The goal is to be able to reuse artifacts from another compiler version or from a different compiler entirely but what happens to the @scala annotations? Is the classfile API might be the same between the same between 2.11 and 2.12 but it doesn't mean that the serialized form of the Scala signature notation is the same and can be read by the other compiler. So if you compile you source code against the binary artifacts that was published on maven your compilation will fail potentially with a crash or something like that because it cannot read the Scala-specific information from the class. - -**Dmitry** The proposal is not to emit stable Scala signatures. - -**Sébastien** So it really looks like a Java class file. Needs to be mentioned in the proposal. - -**Martin** If you don't emit a Scala signature then you can't have a co- or contravariant type parameter because they are only expressed in Scala signatures, in Java it's not there. I don't see how that follows from the current proposal. Also, isn't it platform dependent? - -**Sébastien** We do have a Java signature. Scala-JS doesn't disable classfile emission. When you say quickly compile, it uses the classfiles to quickly compile. when you use macros, it will extend from those classfiles. When you use an IDE it reduces the classfiles to identify things. When you use sbt, it uses classfiles to detect the changes. However, they aren't used by the ScalaJS linker. - -**Seth** Does this need to be part of the compiler or can it move forward as a plugin or just as a check performed in MiMa? MiMa just compares two different APIs. Can it have this other job as well: seeing if it does anything outside of the boundaries. - -**Dmitry** It could be a plugin, but it's not the right responsibility. Whoever develops the pluin does not have a way to enforce its rules by future compilers. Even though it provides guarantees to users, people providing these guarantees should be the people building the future versions. MiMa would need to be come half compiler. It's possible but not practical. If we say we emit Scala signatures, it's a strong promise and we allow users more. If everyone agrees, I would be glad. - -**Martin** Five years from now, do we even know whether Scala compilers will emit Java signatures? To put that in the spec seems too pre-implemention-oriented. We might need a minimum Scala signature, even if we don't emit a Java one. The way the signatures are treated should be an implemenation aspect which should be exactly orthogonal to what we do with stableABI that we want to have something that is stable across lots of implementations. - -**Jorge** We could make an exception that if we change the platform, then this annotation wouldn't apply. - -**Dmitry** The current proposal proposes only top-level classes by _____ (1:01:43). - -**Martin** It just has to be the guarantee of the whole package. The compiler has to translate this somehow so that future compilers will be able to read it in all eternity. That's the contract of stableABI. - -**Dmitry** Does this automatically mean that all future compilers should emit Scala signatures? - -**Martin** No, they just have to read whatever the previous one produced that had this thing. - -**Dmitry** So it means that the artifact compiled by Dotty that doesn't emit Scala signatures won't be able to consume it from Scalac. - -**Martin** That is true. You want to make a rule that newer compilers can ____ (1:02:54) the older ones but not the other way around. - -**Conclusion**: This proposal has been numbered as SIP-34. This is a complicated proposal that needs synchronization between the Scala and Dotty team to decide which encodings are good enough to make binary compatible. When Dmitry, the author of this proposal, figures out which features should be binary compatible and has more information on the future implementation, the SIP Committee will start the review period. - -### SIP-33 - Match infix & prefix types to meet expression rules (1:04:00) - -**Jorge** Making a change to the parser to make types behave as expressions. The other part of the proposal is about prefix types. Just like unary operators, he wants to have unary prefixes for type. So you can create a unary operator for types. - -**Iulian** Covariant and contravariant operators can cause confusion. - -**Eugene** But at least it's not ambiguous. - -**Sébastien** At least as long as we don't have Covariant type alias or abstract type members. If I could define `type +A`, what does that mean? - -**Eugene** If it's on the lefthand side of the equals signs type member, then it's covariant. As long as it's in a binding position, unary infix, should work. - -**Jorge** We will vote later. - -**Conclusion** The vote took place outside the meeting and the proposal was numbered. All of the committee members (including those absent) have accepted the change. diff --git a/_sips/sip-submission.md b/_sips/sip-submission.md index 66f160062b..bffbc2eda9 100644 --- a/_sips/sip-submission.md +++ b/_sips/sip-submission.md @@ -320,7 +320,7 @@ Scala compiler. The process to submit is simple: * Fork the Scala documentation repository, [http://github.com/scala/docs.scala-lang](http://github.com/scala/docs.scala-lang). -* Create a new SIP file in the `sips/pending/_posts/`. 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/master/_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](http://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. From f032dcedf67f47ffccab2da66bd7ca62ec40194b Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Fri, 6 Apr 2018 21:16:25 +0100 Subject: [PATCH 0168/3174] Grammar fix (#1050) Change "amount" to "number" in cases where amount is incorrect. One instance actually used number correctly in the next sentence :P Amount refers to a continuous value as opposed to a discrete count, so number of processors / threads, amount of water or code. --- _overviews/core/futures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index 0659b276e0..6fcfc7b698 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -74,13 +74,13 @@ although this should only be done in rare cases. `ExecutionContext.global` is an `ExecutionContext` backed by a [ForkJoinPool](http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html). It should be sufficient for most situations but requires some care. -A `ForkJoinPool` manages a limited amount of threads (the maximum amount of threads being referred to as *parallelism level*). +A `ForkJoinPool` manages a limited number of threads (the maximum number of threads being referred to as *parallelism level*). The number of concurrently blocking computations can exceed the parallelism level only if each blocking call is wrapped inside a `blocking` call (more on that below). Otherwise, there is a risk that the thread pool in the global execution context is starved, and no computation can proceed. -By default the `ExecutionContext.global` sets the parallelism level of its underlying fork-join pool to the amount of available processors +By default the `ExecutionContext.global` sets the parallelism level of its underlying fork-join pool to the number of available processors ([Runtime.availableProcessors](http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#availableProcessors%28%29)). This configuration can be overridden by setting one (or more) of the following VM attributes: @@ -90,7 +90,7 @@ This configuration can be overridden by setting one (or more) of the following V The parallelism level will be set to `numThreads` as long as it remains within `[minThreads; maxThreads]`. -As stated above the `ForkJoinPool` can increase the amount of threads beyond its `parallelismLevel` in the presence of blocking computation. +As stated above the `ForkJoinPool` can increase the number of threads beyond its `parallelismLevel` in the presence of blocking computation. As explained in the `ForkJoinPool` API, this is only possible if the pool is explicitly notified: import scala.concurrent.Future From 5d64b04dedc66f734bd7db28562d5f3998a207a0 Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Sat, 7 Apr 2018 19:39:30 +0100 Subject: [PATCH 0169/3174] Removed references to deprecated onSuccess and onFailure methods. --- _overviews/core/futures.md | 122 ++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 71 deletions(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index 6fcfc7b698..688aa2df0b 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -338,47 +338,35 @@ a `List[String]`-- a list of recent textual posts: The `onComplete` method is general in the sense that it allows the client to handle the result of both failed and successful future -computations. To handle only successful results, the `onSuccess` -callback is used (which takes a partial function): +computations. In the case where only successful results need to be +handled, the `foreach` callback can be used: val f: Future[List[String]] = Future { session.getRecentPosts } - f onSuccess { - case posts => for (post <- posts) println(post) + f foreach { posts => + for (post <- posts) println(post) } -To handle failed results, the `onFailure` callback is used: +To handle failed results, the `foreach` callback can be used on the +`Future[Throwable]` obtained via the `failed` projection (which is +explained [below](#projections)): val f: Future[List[String]] = Future { session.getRecentPosts } - f onFailure { - case t => println("An error has occured: " + t.getMessage) + f.failed foreach { t => + println("An error has occured: " + t.getMessage) } - f onSuccess { - case posts => for (post <- posts) println(post) + f foreach { posts => + for (post <- posts) println(post) } -The `onFailure` callback is only executed if the future fails, that -is, if it contains an exception. - -Since partial functions have the `isDefinedAt` method, the -`onFailure` method only triggers the callback if it is defined for a -particular `Throwable`. In the following example the registered `onFailure` -callback is never triggered: - - val f = Future { - 2 / 0 - } - - f onFailure { - case npe: NullPointerException => - println("I'd be amazed if this printed out.") - } +The `failed.foreach` callback is only executed if the future fails, that +is, if the original `Future` contains an exception. Coming back to the previous example with searching for the first occurrence of a keyword, you might want to print the position @@ -389,16 +377,14 @@ of the keyword to the screen: source.toSeq.indexOfSlice("myKeyword") } - firstOccurrence onSuccess { - case idx => println("The keyword first appears at position: " + idx) + firstOccurrence onComplete { + case Success(idx) => println("The keyword first appears at position: " + idx) + case Failure(t) => println("Could not process file: " + t.getMessage) } - firstOccurrence onFailure { - case t => println("Could not process file: " + t.getMessage) - } -The `onComplete`, `onSuccess`, and -`onFailure` methods have result type `Unit`, which means invocations +The `onComplete` and `foreach` methods both have result type `Unit`, which +means invocations of these methods cannot be chained. Note that this design is intentional, to avoid suggesting that chained invocations may imply an ordering on the execution of the registered @@ -427,12 +413,12 @@ text. "na" * 16 + "BATMAN!!!" } - text onSuccess { - case txt => totalA += txt.count(_ == 'a') + text foreach { txt => + totalA += txt.count(_ == 'a') } - text onSuccess { - case txt => totalA += txt.count(_ == 'A') + text foreach { txt => + totalA += txt.count(_ == 'A') } Above, the two callbacks may execute one after the other, in @@ -448,9 +434,9 @@ For the sake of completeness the semantics of callbacks are listed here: ensures that the corresponding closure is invoked after the future is completed, eventually. -2. Registering an `onSuccess` or `onFailure` callback has the same +2. Registering a `foreach` callback has the same semantics as `onComplete`, with the difference that the closure is only called -if the future is completed successfully or fails, respectively. +if the future is completed successfully. 3. Registering a callback on the future which is already completed will result in the callback being executed eventually (as implied by @@ -488,21 +474,21 @@ be done using callbacks: connection.getCurrentValue(USD) } - rateQuote onSuccess { case quote => + rateQuote foreach { quote => val purchase = Future { if (isProfitable(quote)) connection.buy(amount, quote) else throw new Exception("not profitable") } - purchase onSuccess { - case _ => println("Purchased " + amount + " USD") + purchase foreach { _ => + println("Purchased " + amount + " USD") } } We start by creating a future `rateQuote` which gets the current exchange rate. After this value is obtained from the server and the future successfully -completed, the computation proceeds in the `onSuccess` callback and we are +completed, the computation proceeds in the `foreach` callback and we are ready to decide whether to buy or not. We therefore create another future `purchase` which makes a decision to buy only if it's profitable to do so, and then sends a request. @@ -510,16 +496,16 @@ Finally, once the purchase is completed, we print a notification message to the standard output. This works, but is inconvenient for two reasons. First, we have to use -`onSuccess`, and we have to nest the second `purchase` future within +`foreach` and nest the second `purchase` future within it. Imagine that after the `purchase` is completed we want to sell some other currency. We would have to repeat this pattern within the -`onSuccess` callback, making the code overly indented, bulky and hard +`foreach` callback, making the code overly indented, bulky and hard to reason about. Second, the `purchase` future is not in the scope with the rest of -the code-- it can only be acted upon from within the `onSuccess` +the code-- it can only be acted upon from within the `foreach` callback. This means that other parts of the application do not -see the `purchase` future and cannot register another `onSuccess` +see the `purchase` future and cannot register another `foreach` callback to it, for example, to sell some other currency. For these two reasons, futures provide combinators which allow a @@ -541,11 +527,11 @@ Let's rewrite the previous example using the `map` combinator: else throw new Exception("not profitable") } - purchase onSuccess { - case _ => println("Purchased " + amount + " USD") + purchase foreach { _ => + println("Purchased " + amount + " USD") } -By using `map` on `rateQuote` we have eliminated one `onSuccess` callback and, +By using `map` on `rateQuote` we have eliminated one `foreach` callback and, more importantly, the nesting. If we now decide to sell some other currency, it suffices to use `map` on `purchase` again. @@ -567,8 +553,8 @@ contains the same exception. This exception propagating semantics is present in the rest of the combinators, as well. One of the design goals for futures was to enable their use in for-comprehensions. -For this reason, futures also have the `flatMap`, `filter` and -`foreach` combinators. The `flatMap` method takes a function that maps the value +For this reason, futures also have the `flatMap` and `withFilter` +combinators. The `flatMap` method takes a function that maps the value to a new future `g`, and then returns a future which is completed once `g` is completed. @@ -586,8 +572,8 @@ Here is an example of `flatMap` and `withFilter` usage within for-comprehensions if isProfitable(usd, chf) } yield connection.buy(amount, chf) - purchase onSuccess { - case _ => println("Purchased " + amount + " CHF") + purchase foreach { _ => + println("Purchased " + amount + " CHF") } The `purchase` future is completed only once both `usdQuote` @@ -627,13 +613,6 @@ calling `filter` has exactly the same effect as does calling `withFilter`. The relationship between the `collect` and `filter` combinator is similar to the relationship of these methods in the collections API. -It is important to note that calling the `foreach` combinator does not -block to traverse the value once it becomes available. -Instead, the function for the `foreach` gets asynchronously -executed only if the future is completed successfully. This means that -the `foreach` has exactly the same semantics as the `onSuccess` -callback. - Since the `Future` trait can conceptually contain two types of values (computation results and exceptions), there exists a need for combinators which handle exceptions. @@ -688,7 +667,7 @@ the case it fails to obtain the dollar value: val anyQuote = usdQuote fallbackTo chfQuote - anyQuote onSuccess { println(_) } + anyQuote foreach { println(_) } The `andThen` combinator is used purely for side-effecting purposes. It returns a new future with exactly the same result as the current @@ -844,8 +823,9 @@ by the clients-- they can only be called by the execution context. When asynchronous computations throw unhandled exceptions, futures associated with those computations fail. Failed futures store an instance of `Throwable` instead of the result value. `Future`s provide -the `onFailure` callback method, which accepts a `PartialFunction` to -be applied to a `Throwable`. The following special exceptions are +the `failed` projection method, which allows this `Throwable` to be +treated as the success value of another `Future`. +The following special exceptions are treated differently: 1. `scala.runtime.NonLocalReturnControl[_]` -- this exception holds a value @@ -903,8 +883,8 @@ that value. This passing of the value is done using a promise. val consumer = Future { startDoingSomething() - f onSuccess { - case r => doSomethingWithResult() + f foreach { r => + doSomethingWithResult() } } @@ -977,8 +957,8 @@ the result of that future as well. The following program prints `1`: p completeWith f - p.future onSuccess { - case x => println(x) + p.future foreach { x => + println(x) } When failing a promise with an exception, three subtypes of `Throwable`s @@ -1001,12 +981,12 @@ Here is an example of how to do it: def first[T](f: Future[T], g: Future[T]): Future[T] = { val p = promise[T] - f onSuccess { - case x => p.trySuccess(x) + f foreach { x => + p.trySuccess(x) } - g onSuccess { - case x => p.trySuccess(x) + g foreach { x => + p.trySuccess(x) } p.future From f31dfccfe866507e0c15b4409c38688fed2c894a Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Mon, 9 Apr 2018 12:45:15 +0100 Subject: [PATCH 0170/3174] Hard-wrapping. --- _overviews/core/futures.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index 688aa2df0b..53ed50c3a4 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -824,9 +824,8 @@ When asynchronous computations throw unhandled exceptions, futures associated with those computations fail. Failed futures store an instance of `Throwable` instead of the result value. `Future`s provide the `failed` projection method, which allows this `Throwable` to be -treated as the success value of another `Future`. -The following special exceptions are -treated differently: +treated as the success value of another `Future`. The following special +exceptions are treated differently: 1. `scala.runtime.NonLocalReturnControl[_]` -- this exception holds a value associated with the return. Typically, `return` constructs in method From e02526a84ac69197411b61813638cc8c21709adb Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Mon, 9 Apr 2018 16:14:33 +0100 Subject: [PATCH 0171/3174] PR comments; deferred explanation of failed projection until the appropriate section. --- _overviews/core/futures.md | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index 53ed50c3a4..5fff1467e9 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -349,24 +349,10 @@ handled, the `foreach` callback can be used: for (post <- posts) println(post) } -To handle failed results, the `foreach` callback can be used on the -`Future[Throwable]` obtained via the `failed` projection (which is -explained [below](#projections)): - - val f: Future[List[String]] = Future { - session.getRecentPosts - } - - f.failed foreach { t => - println("An error has occured: " + t.getMessage) - } - - f foreach { posts => - for (post <- posts) println(post) - } - -The `failed.foreach` callback is only executed if the future fails, that -is, if the original `Future` contains an exception. +`Future`s provide a clean way of handling only failed results using +the `failed` projection which converts a `Failure[Throwable]` to a +`Success[Throwable]`. An example of doing this is provided in the +section below on [projections](#projections). Coming back to the previous example with searching for the first occurrence of a keyword, you might want to print the position @@ -710,12 +696,18 @@ which prints the exception to the screen: } for (exc <- f.failed) println(exc) +The for-comprehension in this example is translated to: + + f.failed.foreach(exc => println(exc)) + +Because `f` is unsuccessful here, the closure is registered to +the `foreach` callback on a newly-successful `Future[Throwable]`. The following example does not print anything to the screen: - val f = Future { + val g = Future { 4 / 2 } - for (exc <- f.failed) println(exc) + for (exc <- g.failed) println(exc) + {% for choice in option.choices %} +
    {{ option.option | xml_escape }}{{ option_argument_separator }}{{ choice.choice | xml_escape }}
    + {% if choice.deprecated %}
    Deprecated: {{ choice.deprecated | markdownify | remove: '

    ' | remove: '

    '}}
    {% endif %} + {% if choice.description %}
    {{ choice.description | markdownify}}
    {% endif %} + {% if choice.note %}
    Note: {{ choice.note | markdownify | remove: '

    ' | remove: '

    '}}
    {% endif %} + {% endfor %} + + + {% endif %} +{% endfor %} + + +{% endfor %} + + +## Additional resources + +### Compilation Phases + +
    +
    initial
    +
    initializing compiler
    + +
    parse
    +
    parse source files
    + +
    namer
    +
    create symbols
    + +
    analyze
    +
    name and type analysis
    + +
    refcheck
    +
    reference checking
    + +
    uncurry
    +
    uncurry function types and applications
    + +
    lambdalift
    +
    lambda lifter
    + +
    typesasvalues
    +
    represent types as values
    + +
    addaccessors
    +
    add accessors for constructor arguments
    + +
    explicitouterclasses
    +
    make links from inner classes to enclosing one explicit
    + +
    addconstructors
    +
    add explicit constructor for each class
    + +
    tailcall
    +
    add tail-calls
    + +
    wholeprog
    +
    perform whole program analysis
    + +
    addinterfaces
    +
    add one interface per class
    + +
    expandmixins
    +
    expand mixins by code copying
    + +
    boxing
    +
    makes boxing explicit
    + +
    erasure
    +
    type eraser
    + +
    icode
    +
    generate icode
    + +
    codegen
    +
    enable code generation
    + +
    terminal
    +
    compilation terminated
    + +
    all
    +
    matches all phases
    +
    + \ No newline at end of file diff --git a/_sass/layout/type-md.scss b/_sass/layout/type-md.scss index 0964604b1a..38b09dbbd4 100755 --- a/_sass/layout/type-md.scss +++ b/_sass/layout/type-md.scss @@ -141,7 +141,11 @@ } li, - p { + p, + tr, + td, + dt, + dd { code { font-family: 'Consolas'; @include border-radius($border-radius-small); From f2c5cc229f89b249f75ec3b9fc2decfb3be12c85 Mon Sep 17 00:00:00 2001 From: exoego Date: Tue, 1 May 2018 22:13:52 +0900 Subject: [PATCH 0184/3174] Fix typo --- _overviews/compiler-options/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index ae2ac68c17..3e65a94511 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -47,7 +47,7 @@ This page come to the rescue for the people to find... scalac [ ] ``` -E.g. `scalac -encoding utf8 -Xfalta-warnings Hello.scala` +E.g. `scalac -encoding utf8 -Xfatal-warnings Hello.scala` From 4f8eb61187f1eba3e256b004edcebb3f6fefd398 Mon Sep 17 00:00:00 2001 From: exoego Date: Wed, 2 May 2018 22:43:02 +0900 Subject: [PATCH 0185/3174] Move choices to schema since choices are valid for some types. --- _data/compiler-options.yml | 178 +++++++++++++-------------- _overviews/compiler-options/index.md | 4 +- 2 files changed, 91 insertions(+), 91 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 3d812c877d..37b1d077d3 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -66,13 +66,13 @@ type: Choice arg: level default: vars - description: "Set level of generated debugging info." - choices: + choices: - choice: none - choice: source - choice: line - choice: vars - choice: notailcalls + description: "Set level of generated debugging info." - option: -help schema: type: Boolean @@ -95,12 +95,12 @@ scheam: type: Choice default: jvm-1.8 - description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." - choices: + choices: - choice: jvm-1.5 - choice: jvm-1.6 - choice: jvm-1.7 - choice: jvm-1.8 + description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." - option: -unchecked schema: type: Boolean @@ -134,8 +134,7 @@ type: Choice multiple: true arg: feat - description: "Enable or disable language features." - choices: + choices: - choice: dynamics description: "Allow direct or indirect subclasses of `scala.Dynamic`." - choice: postfixOps @@ -150,6 +149,7 @@ description: "Existential types (besides wildcard types) can be written and inferred." - choice: experimental.macros description: "Allow macro definition (besides implementation and application." + description: "Enable or disable language features." - option: -release schema: type: String @@ -388,22 +388,22 @@ type: Choice arg: mode default: true - description: "Generate forwarder methods in classes inhering concrete methods from traits." - choices: + choices: - choice: true description: "Always generate mixin forwarders." - choice: junit description: "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods)." - choice: false description: "Only generate mixin forwarders required for program correctness." + description: "Generate forwarder methods in classes inhering concrete methods from traits." - option: -Xxml schema: type: Choice arg: property - description: "Configure XML parsing." - choices: + choices: - choice: coalescing description: "Convert PCData to Text and coalesce sibling nodes." + description: "Configure XML parsing." @@ -463,11 +463,11 @@ type: Choice arg: strategy default: error - description: "Resolve term conflicts." - choices: + choices: - choice: package - choice: object - choice: error + description: "Resolve term conflicts." - option: -Ylog schema: type: Phases @@ -570,11 +570,11 @@ type: Choice arg: policy default: normal - description: "Control expansion of macros, useful for scaladoc and presentation compiler." - choices: + choices: - choice: none - choice: normal - choice: discard + description: "Control expansion of macros, useful for scaladoc and presentation compiler." - option: -Ymacro-no-expand schema: type: Boolean @@ -616,10 +616,10 @@ type: Choice arg: strategy default: method - description: "Strategy used for translating lambdas into JVM code." - choices: + choices: - choice: inline - choice: method + description: "Strategy used for translating lambdas into JVM code." - option: -Ybackend-parallelism schema: type: Int @@ -648,29 +648,27 @@ schema: type: Choice default: none - description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." - choices: + choices: - choice: none description: "Don't cache class loader." - choice: last-modified description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." - option: -Ycache-macro-class-loader schema: type: Choice default: none - description: "Policy for caching class loaders for macros that are dynamically loaded." - choices: + choices: - choice: none description: "Don't cache class loader." - choice: last-modified description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for macros that are dynamically loaded." - option: -opt schema: type: Choice multiple: true - description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." - note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." - choices: + choices: - choice: unreachable-code description: "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers)." - choice: simplify-jumps @@ -704,6 +702,8 @@ - choice: l:classpath description: "Enable cross-method optimizations across the entire classpath." deprecated: "Use `-opt:l:inline -opt-inline-from` instead." + description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." + note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." - option: -opt-inline-from schema: type: String @@ -715,18 +715,17 @@ type: Choice arg: strategy default: default - description: "Set the heuristics for inlining decisions." - choices: + choices: - choice: at-inline-annotated - choice: everything - choice: default + description: "Set the heuristics for inlining decisions." - option: -opt-warnings schema: type: Choice multiple: true default: at-inline-failed - description: "Enable optimizer warnings." - choices: + choices: - choice: none description: "No optimizer warnings." - choice: at-inline-failed-summary @@ -741,6 +740,7 @@ description: "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath." - choice: no-inline-missing-attribute description: "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute." + description: "Enable optimizer warnings." - option: -Yopt-trace schema: type: String @@ -899,8 +899,7 @@ schema: type: Choice arg: mode - description: "Enable lint warnings on macro expansions." - choices: + choices: - choice: none description: "Do not inspect expansions or their original trees when generating unused symbol warnings." - choice: before @@ -909,6 +908,7 @@ description: "Only inspect expanded trees when generating unused symbol warnings." - choice: both description: "Inspect both user-written code and expanded trees when generating unused symbol warnings." + description: "Enable lint warnings on macro expansions." - option: -Ywarn-dead-code schema: type: Boolean @@ -928,25 +928,25 @@ multiple: true arg: warn default: _ + choices: + - choice: imports + description: "Warn if an import selector is not referenced." + - choice: patvars + description: "Warn if a variable bound in a pattern is unused." + - choice: privates + description: "Warn if a private member is unused." + - choice: locals + description: "Warn if a local definition is unused." + - choice: explicits + description: "Warn if an explicit parameter is unused." + - choice: implicits + description: "Warn if an implicit parameter is unused." + - choice: params + description: "Enable `-Ywarn-unused:explicits,implicits`." + - choice: linted + description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." + note: "Alias is `-Xlint:unused`." description: "Enable or disable specific `unused` warnings." - choices: - - choice: imports - description: "Warn if an import selector is not referenced." - - choice: patvars - description: "Warn if a variable bound in a pattern is unused." - - choice: privates - description: "Warn if a private member is unused." - - choice: locals - description: "Warn if a local definition is unused." - - choice: explicits - description: "Warn if an explicit parameter is unused." - - choice: implicits - description: "Warn if an implicit parameter is unused." - - choice: params - description: "Enable `-Ywarn-unused:explicits,implicits`." - - choice: linted - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." - note: "Alias is `-Xlint:unused`." - option: -Ywarn-unused-import schema: type: Boolean @@ -965,47 +965,47 @@ multiple: true arg: warn default: _ + choices: + - choice: adapted-args + description: "Warn if an argument list is modified to match the receiver." + note: "Alias is `-Ywarn-adapted-args`." + - choice: nullary-unit + description: "Warn when nullary methods return Unit." + note: "Alias is `-Ywarn-nullary-unit`." + - choice: inaccessible + description: "Warn about inaccessible types in method signatures." + note: "Alias is `-Ywarn-inaccessible`." + - choice: nullary-override + description: "Warn when non-nullary `def f()` overrides nullary `def f`." + note: "Alias is `-Ywarn-nullary-override`." + - choice: infer-any + description: "Warn when a type argument is inferred to be `Any`." + note: "Alias is `-Ywarn-infer-any`." + - choice: missing-interpolator + description: "A string literal appears to be missing an interpolator id." + - choice: doc-detached + description: "A Scaladoc comment appears to be detached from its element." + - choice: private-shadow + description: "A private field (or class parameter) shadows a superclass field." + - choice: type-parameter-shadow + description: "A local type parameter shadows a type already in scope." + - choice: poly-implicit-overload + description: "Parameterized overloaded implicit methods are not visible as view bounds." + - choice: option-implicit + description: "Option.apply used implicit view." + - choice: delayedinit-select + description: "Selecting member of DelayedInit." + - choice: by-name-right-associative + description: "By-name parameter of right associative operator." + - choice: package-object-classes + description: "Class or object defined in package object." + - choice: unsound-match + description: "Pattern match may not be typesafe." + - choice: stars-align + description: "Pattern sequence wildcard must align with sequence component." + - choice: constant + description: "Evaluation of a constant arithmetic expression results in an error." + - choice: unused + description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." description: "Enable or disable specific warnings." note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." - choices: - - choice: adapted-args - description: "Warn if an argument list is modified to match the receiver." - note: "Alias is `-Ywarn-adapted-args`." - - choice: nullary-unit - description: "Warn when nullary methods return Unit." - note: "Alias is `-Ywarn-nullary-unit`." - - choice: inaccessible - description: "Warn about inaccessible types in method signatures." - note: "Alias is `-Ywarn-inaccessible`." - - choice: nullary-override - description: "Warn when non-nullary `def f()` overrides nullary `def f`." - note: "Alias is `-Ywarn-nullary-override`." - - choice: infer-any - description: "Warn when a type argument is inferred to be `Any`." - note: "Alias is `-Ywarn-infer-any`." - - choice: missing-interpolator - description: "A string literal appears to be missing an interpolator id." - - choice: doc-detached - description: "A Scaladoc comment appears to be detached from its element." - - choice: private-shadow - description: "A private field (or class parameter) shadows a superclass field." - - choice: type-parameter-shadow - description: "A local type parameter shadows a type already in scope." - - choice: poly-implicit-overload - description: "Parameterized overloaded implicit methods are not visible as view bounds." - - choice: option-implicit - description: "Option.apply used implicit view." - - choice: delayedinit-select - description: "Selecting member of DelayedInit." - - choice: by-name-right-associative - description: "By-name parameter of right associative operator." - - choice: package-object-classes - description: "Class or object defined in package object." - - choice: unsound-match - description: "Pattern match may not be typesafe." - - choice: stars-align - description: "Pattern sequence wildcard must align with sequence component." - - choice: constant - description: "Evaluation of a constant arithmetic expression results in an error." - - choice: unused - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index 3e65a94511..47536e5036 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -91,11 +91,11 @@ scalacOptions ++= Seq( {% if option.schema.max %}Max: {{ option.schema.max }}
    {% endif %} {% if option.note %}
    Note: {{ option.note | markdownify | remove: '

    ' | remove: '

    '}}
    {% endif %} - {% if option.choices %} + {% if option.schema.choices %}
    - {% for choice in option.choices %} + {% for choice in option.schema.choices %}
    {{ option.option | xml_escape }}{{ option_argument_separator }}{{ choice.choice | xml_escape }}
    {% if choice.deprecated %}
    Deprecated: {{ choice.deprecated | markdownify | remove: '

    ' | remove: '

    '}}
    {% endif %} {% if choice.description %}
    {{ choice.description | markdownify}}
    {% endif %} From c0b8084b6d6d137ea0c9f66d73d185e14be87981 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 06:28:59 +0900 Subject: [PATCH 0186/3174] Add quotes so that number and string can be distinguished --- _data/compiler-options.yml | 1022 ++++++++++++++++++------------------ 1 file changed, 510 insertions(+), 512 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 37b1d077d3..2d7d50d35c 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -1,413 +1,412 @@ -- category: Standard Settings +- category: "Standard Settings" description: "A set of standard options that are supported on the current development environment and will be supported in future releases." options: # Path related settings. - - option: -classpath - abbreviation: -cp + - option: "-classpath" + abbreviation: "-cp" schema: - type: Path - arg: path + type: "Path" + arg: "path" description: "Specify where to find user class files." - - option: -bootclasspath + - option: "-bootclasspath" schema: - type: Path - arg: path - default: Defaults.scalaBootClassPath + type: "Path" + arg: "path" + default: "Defaults.scalaBootClassPath" description: "Override location of bootstrap class files." - - option: -extdirs + - option: "-extdirs" schema: - type: Path - arg: path - default: Defaults.scalaExtDirs + type: "Path" + arg: "path" + default: "Defaults.scalaExtDirs" description: "Override location of installed extensions." - - option: -javabootclasspath + - option: "-javabootclasspath" schema: - type: Path - arg: path - default: Defaults.javaBootClassPath + type: "Path" + arg: "path" + default: "Defaults.javaBootClassPath" description: "Override java boot classpath." - - option: -javaextdirs + - option: "-javaextdirs" schema: - type: Path - arg: path - default: Defaults.javaExtDirs + type: "Path" + arg: "path" + default: "Defaults.javaExtDirs" description: "Override java extdirs classpath." - - option: -sourcepath + - option: "-sourcepath" schema: - type: Path + type: "Path" description: "Specify location(s) of source files." -# other settings - - option: -dependencyfile + - option: "-dependencyfile" schema: - type: String - arg: file - default: .scala_dependencies + type: "String" + arg: "file" + default: ".scala_dependencies" description: "Set dependency tracking file." - - option: -deprecation + - option: "-deprecation" schema: - type: Boolean + type: "Boolean" description: "Emit warning and location for usages of deprecated APIs." - - option: -encoding + - option: "-encoding" schema: - type: String - arg: encoding - default: Properties.sourceEncoding + type: "String" + arg: "encoding" + default: "Properties.sourceEncoding" description: "Specify character encoding used by source files." - - option: -explaintypes + - option: "-explaintypes" schema: - type: Boolean + type: "Boolean" description: "Explain type errors in more detail." - - option: -feature + - option: "-feature" schema: - type: Boolean + type: "Boolean" description: "Emit warning and location for usages of features that should be imported explicitly." - - option: -g + - option: "-g" schema: - type: Choice - arg: level - default: vars + type: "Choice" + arg: "level" + default: "vars" choices: - - choice: none - - choice: source - - choice: line - - choice: vars - - choice: notailcalls + - choice: "none" + - choice: "source" + - choice: "line" + - choice: "vars" + - choice: "notailcalls" description: "Set level of generated debugging info." - - option: -help + - option: "-help" schema: - type: Boolean + type: "Boolean" description: "Print a synopsis of standard options." - - option: -nowarn + - option: "-nowarn" schema: - type: Boolean + type: "Boolean" description: "Generate no warnings." - - option: -optimise - abbreviation: -optimize + - option: "-optimise" + abbreviation: "-optimize" schema: - type: Boolean + type: "Boolean" description: "Compiler flag for the optimizer in Scala 2.11." deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." - - option: -print + - option: "-print" schema: - type: Boolean + type: "Boolean" description: "Print program with Scala-specific features removed." - - option: -target + - option: "-target" scheam: - type: Choice - default: jvm-1.8 + type: "Choice" + default: "jvm-1.8" choices: - - choice: jvm-1.5 - - choice: jvm-1.6 - - choice: jvm-1.7 - - choice: jvm-1.8 + - choice: "jvm-1.5" + - choice: "jvm-1.6" + - choice: "jvm-1.7" + - choice: "jvm-1.8" description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." - - option: -unchecked + - option: "-unchecked" schema: - type: Boolean + type: "Boolean" description: "Enable additional warnings where generated code depends on assumptions." - - option: -uniqid + - option: "-uniqid" schema: - type: Boolean + type: "Boolean" description: "Uniquely tag all identifiers in debugging output." - - option: -usejavacp + - option: "-usejavacp" schema: - type: Boolean + type: "Boolean" description: "Utilize the `java.class.path` in classpath resolution." - - option: -usemanifestcp + - option: "-usemanifestcp" schema: - type: Boolean + type: "Boolean" description: "Utilize the manifest in classpath resolution." - - option: -verbose + - option: "-verbose" schema: - type: Boolean + type: "Boolean" description: "Output messages about what the compiler is doing." - - option: -version + - option: "-version" schema: - type: Boolean + type: "Boolean" description: "Print product version and exit." - - option: -no-specialization + - option: "-no-specialization" schema: - type: Boolean + type: "Boolean" description: "Ignore `@specialize` annotations." - - option: -language + - option: "-language" schema: - type: Choice + type: "Choice" multiple: true - arg: feat + arg: "feat" choices: - - choice: dynamics + - choice: "dynamics" description: "Allow direct or indirect subclasses of `scala.Dynamic`." - - choice: postfixOps + - choice: "postfixOps" description: "Allow postfix operator notation, such as `1 to 10 toList`." - - choice: reflectiveCalls + - choice: "reflectiveCalls" description: "Allow reflective access to members of structural types." - - choice: implicitConversions + - choice: "implicitConversions" description: "Allow definition of implicit functions called views." - - choice: higherKinds + - choice: "higherKinds" description: "Allow higher-kinded types." - - choice: existentials + - choice: "existentials" description: "Existential types (besides wildcard types) can be written and inferred." - - choice: experimental.macros + - choice: "experimental.macros" description: "Allow macro definition (besides implementation and application." description: "Enable or disable language features." - - option: -release + - option: "-release" schema: - type: String - arg: release + type: "String" + arg: "release" description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." -- category: JVM Settings +- category: "JVM Settings" description: "Settings influencing the runtime system." options: - - option: -Jflag + - option: "-Jflag" schema: - type: Prefix + type: "Prefix" description: "Pass `flag` directly to the runtime system." - - option: -Dproperty=value + - option: "-Dproperty=value" schema: - type: Prefix + type: "Prefix" description: "Pass `-Dproperty=value` directly to the runtime system." - - option: -nobootcp + - option: "-nobootcp" schema: - type: Boolean + type: "Boolean" description: "Do not use the boot classpath for the scala jars." -- category: Plugin Settings +- category: "Plugin Settings" description: "" options: - - option: -P + - option: "-P" schema: - type: Prefix + type: "Prefix" arg: ":plugin:opt" description: "Pass an option to a plugin in the form of `-P::`." note: "If you use sbt, [compiler plugins support](https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html) may be useful." -- category: Advanced Settings +- category: "Advanced Settings" description: "Options that starts with `-X` are maybe renamed or removed in future releases." options: - - option: -X + - option: "-X" schema: - type: Boolean + type: "Boolean" description: "Print a synopsis of advanced options." - - option: -Xcheckinit + - option: "-Xcheckinit" schema: - type: Boolean + type: "Boolean" description: "Wrap field accessors to throw an exception on uninitialized access." - - option: -Xdev + - option: "-Xdev" schema: - type: Boolean + type: "Boolean" description: "Indicates user is a developer - issue warnings about anything which seems amiss." - - option: -Xdisable-assertions + - option: "-Xdisable-assertions" schema: - type: Boolean + type: "Boolean" description: "Generate no assertions or assumptions." - - option: -Xelide-below + - option: "-Xelide-below" schema: - type: Int - arg: min - default: Int.MinValue + type: "Int" + arg: "min" + default: "Int.MinValue" description: "Calls to `@elidable` methods are omitted if method priority is lower than argument." - - option: -Xno-forwarders + - option: "-Xno-forwarders" schema: - type: Boolean + type: "Boolean" description: "Do not generate static forwarders in mirror classes." - - option: -Xgenerate-phase-graph + - option: "-Xgenerate-phase-graph" schema: - type: String - arg: file + type: "String" + arg: "file" description: "Generate the phase graphs (outputs .dot files) to fileX.dot." - - option: -Xlog-implicits + - option: "-Xlog-implicits" schema: - type: Boolean + type: "Boolean" description: "Show more detail on why some implicits are not applicable." - - option: -Xlog-implicit-conversions + - option: "-Xlog-implicit-conversions" schema: - type: Boolean + type: "Boolean" description: "Print a message whenever an implicit conversion is inserted." - - option: -Xlog-reflective-calls + - option: "-Xlog-reflective-calls" schema: - type: Boolean + type: "Boolean" description: "Print a message when a reflective method call is generated." - - option: -Xlog-free-terms + - option: "-Xlog-free-terms" schema: - type: Boolean + type: "Boolean" description: "Print a message when reification creates a free term." - - option: -Xlog-free-types + - option: "-Xlog-free-types" schema: - type: Boolean + type: "Boolean" description: "Print a message when reification resorts to generating a free type." - - option: -Xmax-classfile-name + - option: "-Xmax-classfile-name" schema: - type: Int - arg: max + type: "Int" + arg: "max" default: 255 min: 72 max: 255 description: "Maximum filename length for generated classes." - - option: -Xmaxerrs + - option: "-Xmaxerrs" schema: - type: Int - arg: max + type: "Int" + arg: "max" default: 100 description: "Maximum errors to print." - - option: -Xmaxwarns + - option: "-Xmaxwarns" schema: - type: Int - arg: max + type: "Int" + arg: "max" default: 100 description: "Maximum warnings to print." - - option: -Xmigration + - option: "-Xmigration" schema: - type: ScalaVersion - arg: version - default: any + type: "ScalaVersion" + arg: "version" + default: "any" description: "Warn about constructs whose behavior may have changed since version." - - option: -Xno-uescape + - option: "-Xno-uescape" schema: - type: Boolean + type: "Boolean" description: "Disable handling of \\u unicode escapes." - - option: -Xnojline + - option: "-Xnojline" schema: - type: Boolean + type: "Boolean" description: "Do not use JLine for editing." - - option: -Xverify + - option: "-Xverify" schema: - type: Boolean + type: "Boolean" description: "Verify generic signatures in generated bytecode." - - option: -Xplugin + - option: "-Xplugin" schema: - type: String + type: "String" multiple: true - arg: path + arg: "path" description: "Load a plugin from each classpath." - - option: -Xplugin-disable + - option: "-Xplugin-disable" schema: - type: String + type: "String" multiple: true - arg: plugin + arg: "plugin" description: "Disable plugins by name." - - option: -Xplugin-list + - option: "-Xplugin-list" schema: - type: Boolean + type: "Boolean" description: "Print a synopsis of loaded plugins." - - option: -Xplugin-require + - option: "-Xplugin-require" schema: - type: String + type: "String" multiple: true - arg: plugin + arg: "plugin" description: "Abort if a named plugin is not loaded." - - option: -Xpluginsdir + - option: "-Xpluginsdir" schema: - type: String - arg: path - default: Defaults.scalaPluginPath + type: "String" + arg: "path" + default: "Defaults.scalaPluginPath" description: "Path to search for plugin archives." - - option: -Xprint + - option: "-Xprint" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Print out program after PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Xprint-pos + - option: "-Xprint-pos" schema: - type: Boolean + type: "Boolean" description: "Print tree positions, as offsets." - - option: -Xprint-types + - option: "-Xprint-types" schema: - type: Boolean + type: "Boolean" description: "Print tree types (debugging option)." - - option: -Xprint-args + - option: "-Xprint-args" schema: - type: Boolean + type: "Boolean" description: "Print all compiler arguments and exit." - - option: -Xprompt + - option: "-Xprompt" schema: - type: Boolean + type: "Boolean" description: "Display a prompt after each error (debugging option)." - - option: -Xresident + - option: "-Xresident" schema: - type: Boolean + type: "Boolean" description: "Compiler stays resident: read source filenames from standard input." - - option: -Xscript + - option: "-Xscript" schema: - type: String - arg: object + type: "String" + arg: "object" description: "Treat the source file as a script and wrap it in a main method." - - option: -Xmain-class + - option: "-Xmain-class" schema: - type: String - arg: path + type: "String" + arg: "path" description: "Class for manifest's Main-Class entry (only useful with `-d `)" - - option: -Xshow-class + - option: "-Xshow-class" schema: - type: String - arg: class + type: "String" + arg: "class" description: "Show internal representation of class." - - option: -Xshow-object + - option: "-Xshow-object" schema: - type: String - arg: object + type: "String" + arg: "object" description: "Show internal representation of object." - - option: -Xshow-phases + - option: "-Xshow-phases" schema: - type: Boolean + type: "Boolean" description: "Print a synopsis of compiler phases." - - option: -Xsource-reader + - option: "-Xsource-reader" schema: - type: String - arg: classname + type: "String" + arg: "classname" description: "Specify a custom method for reading source files." - - option: -Xreporter + - option: "-Xreporter" schema: - type: String - arg: classname - default: scala.tools.nsc.reporters.ConsoleReporter + type: "String" + arg: "classname" + default: "scala.tools.nsc.reporters.ConsoleReporter" description: "Specify a custom reporter for compiler messages." - - option: -Xstrict-inference + - option: "-Xstrict-inference" schema: - type: Boolean + type: "Boolean" description: "Don't infer known-unsound types." - - option: -Xsource + - option: "-Xsource" schema: - type: Scala Version - arg: version - default: 2.13 + type: "Scala Version" + arg: "version" + default: "2.13" description: "Treat compiler input as Scala source for the specified version, see [scala/bug#8126](https://github.com/scala/bug/issues/8126)." - - option: -Xno-patmat-analysis + - option: "-Xno-patmat-analysis" schema: - type: Boolean + type: "Boolean" description: "Don't perform exhaustivity/unreachability analysis. Also, ignore `@switch` annotation." - - option: -Xfull-lubs + - option: "-Xfull-lubs" schema: - type: Boolean + type: "Boolean" description: "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds." - - option: -Xmixin-force-forwarders + - option: "-Xmixin-force-forwarders" schema: - type: Choice - arg: mode - default: true + type: "Choice" + arg: "mode" + default: "true" choices: - - choice: true + - choice: "true" description: "Always generate mixin forwarders." - - choice: junit + - choice: "junit" description: "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods)." - - choice: false + - choice: "false" description: "Only generate mixin forwarders required for program correctness." description: "Generate forwarder methods in classes inhering concrete methods from traits." - - option: -Xxml + - option: "-Xxml" schema: - type: Choice - arg: property + type: "Choice" + arg: "property" choices: - - choice: coalescing + - choice: "coalescing" description: "Convert PCData to Text and coalesce sibling nodes." description: "Configure XML parsing." -- category: Private Settings +- category: "Private Settings" description: | Options with `-Y` prefix are more experimental and unstable than those with `-X` prefix. @@ -415,472 +414,471 @@ Some optimization-related options, e.g. `-opt:**` and `-opt-inline-form` are included in this section, since **REASON_HERE**. options: - - option: -Y + - option: "-Y" schema: - type: Boolean + type: "Boolean" description: "Print a synopsis of private options." - - option: -Yoverride-objects + - option: "-Yoverride-objects" schema: - type: Boolean + type: "Boolean" description: "Allow member objects to be overridden." - - option: -Yoverride-vars + - option: "-Yoverride-vars" schema: - type: Boolean + type: "Boolean" description: "Allow vars to be overridden." - - option: -Ybreak-cycles + - option: "-Ybreak-cycles" schema: - type: Boolean + type: "Boolean" description: "Attempt to break cycles encountered during typing." - - option: -Ybrowse + - option: "-Ybrowse" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Browse the abstract syntax tree after PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Ycheck + - option: "-Ycheck" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Check the tree at the end of PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Yshow + - option: "-Yshow" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "(Requires `-Xshow-class` or `-Xshow-object`) Show after PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Ycompact-trees + - option: "-Ycompact-trees" schema: - type: Boolean + type: "Boolean" description: "Use compact tree printer when displaying trees." - - option: -Yno-completion + - option: "-Yno-completion" schema: - type: Boolean + type: "Boolean" description: "Disable tab-completion in the REPL." - - option: -Ydebug + - option: "-Ydebug" schema: - type: Boolean + type: "Boolean" description: "Increase the quantity of debugging output." - - option: -Yresolve-term-conflict + - option: "-Yresolve-term-conflict" schema: - type: Choice - arg: strategy - default: error + type: "Choice" + arg: "strategy" + default: "error" choices: - - choice: package - - choice: object - - choice: error + - choice: "package" + - choice: "object" + - choice: "error" description: "Resolve term conflicts." - - option: -Ylog + - option: "-Ylog" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Log operations during PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Ylog-classpath + - option: "-Ylog-classpath" schema: - type: Boolean + type: "Boolean" description: "Output information about what classpath is being applied." - - option: -Yno-generic-signatures + - option: "-Yno-generic-signatures" schema: - type: Boolean + type: "Boolean" description: "Suppress generation of generic signatures for Java." - - option: -Yno-imports + - option: "-Yno-imports" schema: - type: Boolean + type: "Boolean" description: "Compile without importing scala.*, java.lang.*, or Predef." - - option: -Yno-predef + - option: "-Yno-predef" schema: - type: Boolean + type: "Boolean" description: "Compile without importing Predef." - - option: -Yno-adapted-args + - option: "-Yno-adapted-args" schema: - type: Boolean + type: "Boolean" description: "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver." - - option: -Yrecursion + - option: "-Yrecursion" schema: - type: Int - arg: depth + type: "Int" + arg: "depth" default: 0 min: 0 max: Int.MaxValue description: "Set recursion depth used when locking symbols." - - option: -Yshow-trees + - option: "-Yshow-trees" schema: - type: Boolean + type: "Boolean" description: "(Requires `-Xprint:`) Print detailed ASTs in formatted form." - - option: -Yshow-trees-compact + - option: "-Yshow-trees-compact" schema: - type: Boolean + type: "Boolean" description: "(Requires `-Xprint:`) Print detailed ASTs in compact form." - - option: -Yshow-trees-stringified + - option: "-Yshow-trees-stringified" schema: - type: Boolean + type: "Boolean" description: "(Requires `-Xprint:`) Print stringifications along with detailed ASTs." - - option: -Yshow-syms + - option: "-Yshow-syms" schema: - type: Boolean + type: "Boolean" description: "Print the AST symbol hierarchy after each phase." - - option: -Yshow-symkinds + - option: "-Yshow-symkinds" schema: - type: Boolean + type: "Boolean" description: "Print abbreviated symbol kinds next to symbol names." - - option: -Yshow-symowners + - option: "-Yshow-symowners" schema: - type: Boolean + type: "Boolean" description: "Print owner identifiers next to symbol names." - - option: -Yskip + - option: "-Yskip" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Skip PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Ygen-asmp + - option: "-Ygen-asmp" schema: - type: String - arg: dir + type: "String" + arg: "dir" description: "Generate a parallel output directory of .asmp files (ie ASM Textifier output)." - - option: -Ydump-classes + - option: "-Ydump-classes" schema: - type: String - arg: dir + type: "String" + arg: "dir" description: "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders)." - - option: -Ystop-after - abbreviation: -stop + - option: "-Ystop-after" + abbreviation: "-stop" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Ystop-before + - option: "-Ystop-before" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" description: "Stop before PHASES (see [Compilation Phases](#compilation-phases))" - - option: -Yrangepos + - option: "-Yrangepos" schema: - type: Boolean + type: "Boolean" description: "Use range positions for syntax trees." - - option: -Yshow-member-pos + - option: "-Yshow-member-pos" schema: - type: String - arg: style + type: "String" + arg: "style" description: "Show start and end positions of members." note: "`-Yrangepos` is enabled at the same time." - - option: -Yreify-copypaste + - option: "-Yreify-copypaste" schema: - type: Boolean + type: "Boolean" description: "Dump the reified trees in copypasteable representation." - - option: -Ymacro-expand + - option: "-Ymacro-expand" schema: - type: Choice - arg: policy - default: normal + type: "Choice" + arg: "policy" + default: "normal" choices: - - choice: none - - choice: normal - - choice: discard + - choice: "none" + - choice: "normal" + - choice: "discard" description: "Control expansion of macros, useful for scaladoc and presentation compiler." - - option: -Ymacro-no-expand + - option: "-Ymacro-no-expand" schema: - type: Boolean + type: "Boolean" description: "Don't expand macros. Might be useful for scaladoc and presentation compiler, but will crash anything which uses macros and gets past typer." deprecated: "Use `-Ymacro-expand:none` instead." - - option: -Yrepl-sync + - option: "-Yrepl-sync" schema: - type: Boolean + type: "Boolean" description: "Do not use asynchronous code for REPL startup." - - option: -Yrepl-class-based + - option: "-Yrepl-class-based" schema: - type: Boolean + type: "Boolean" description: "Use classes to wrap REPL snippets instead of objects." - - option: -Yrepl-outdir + - option: "-Yrepl-outdir" schema: - type: String - arg: path + type: "String" + arg: "path" description: "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" - - option: -Yinfer-argument-types + - option: "-Yinfer-argument-types" schema: - type: Boolean + type: "Boolean" description: "Infer types for arguments of overridden methods." - - option: -YdisableFlatCpCaching + - option: "-YdisableFlatCpCaching" schema: - type: Boolean + type: "Boolean" description: "Do not cache flat classpath representation of classpath elements from jars across compiler instances." - - option: -Yvirtpatmat + - option: "-Yvirtpatmat" schema: - type: Boolean + type: "Boolean" description: "Enable pattern matcher virtualization." - - option: -Yexpose-empty-package + - option: "-Yexpose-empty-package" # TODO: internal only internalOnly: true schema: - type: Boolean + type: "Boolean" description: "Internal only: expose the empty package." - - option: -Ydelambdafy + - option: "-Ydelambdafy" schema: - type: Choice - arg: strategy - default: method + type: "Choice" + arg: "strategy" + default: "method" choices: - - choice: inline - - choice: method + - choice: "inline" + - choice: "method" description: "Strategy used for translating lambdas into JVM code." - - option: -Ybackend-parallelism + - option: "-Ybackend-parallelism" schema: - type: Int - arg: threads + type: "Int" + arg: "threads" default: 1 min: 1 max: 16 description: "Maximum worker threads for backend." - - option: -Ybackend-worker-queue + - option: "-Ybackend-worker-queue" description: "Backend threads worker queue size." schema: - type: Int - arg: size + type: "Int" + arg: "size" default: 0 min: 0 max: 1000 - - option: -Yjar-compression-level + - option: "-Yjar-compression-level" schema: - type: Int - arg: level - default: Deflater.DEFAULT_COMPRESSION - min: Deflater.DEFAULT_COMPRESSION - max: Deflater.BEST_COMPRESSION + type: "Int" + arg: "level" + default: "Deflater.DEFAULT_COMPRESSION" + min: "Deflater.DEFAULT_COMPRESSION" + max: "Deflater.BEST_COMPRESSION" description: "Compression level to use when writing jar files." - - option: -Ycache-plugin-class-loader + - option: "-Ycache-plugin-class-loader" schema: - type: Choice - default: none + type: "Choice" + default: "none" choices: - - choice: none + - choice: "none" description: "Don't cache class loader." - - choice: last-modified + - choice: "last-modified" description: "Cache class loader, using file last-modified time to invalidate." description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." - - option: -Ycache-macro-class-loader + - option: "-Ycache-macro-class-loader" schema: - type: Choice - default: none + type: "Choice" + default: "none" choices: - - choice: none + - choice: "none" description: "Don't cache class loader." - - choice: last-modified + - choice: "last-modified" description: "Cache class loader, using file last-modified time to invalidate." description: "Policy for caching class loaders for macros that are dynamically loaded." - - option: -opt + - option: "-opt" schema: - type: Choice + type: "Choice" multiple: true choices: - - choice: unreachable-code + - choice: "unreachable-code" description: "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers)." - - choice: simplify-jumps + - choice: "simplify-jumps" description: "Simplify branching instructions, eliminate unnecessary ones." - - choice: compact-locals + - choice: "compact-locals" description: "Eliminate empty slots in the sequence of local variables." - - choice: copy-propagation + - choice: "copy-propagation" description: "Eliminate redundant local variables and unused values (including closures). Enables unreachable-code." - - choice: redundant-casts + - choice: "redundant-casts" description: "Eliminate redundant casts using a type propagation analysis." - - choice: box-unbox + - choice: "box-unbox" description: "Eliminate box-unbox pairs within the same method (also tuples, xRefs, value class instances). Enables unreachable-code." - choice: "nullness-tracking" description: "Track nullness / non-nullness of local variables and apply optimizations." - - choice: closure-invocations + - choice: "closure-invocations" description: "Rewrite closure invocations to the implementation method." - - choice: inline + - choice: "inline" description: "Inline method invocations according to `-Yopt-inline-heuristics` and `-opt-inline-from`." - - choice: l:none + - choice: "l:none" description: "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox." note: "Unlike the other optimizer levels, `l:none` appears up in the `opt.value` set because it's not an expanding option." - - choice: l:default + - choice: "l:default" description: "Enable default optimizations: `unreachable-code`." - - choice: l:method + - choice: "l:method" description: "Enable intra-method optimizations: `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`." - - choice: l:inline + - choice: "l:inline" description: "Enable cross-method optimizations (note: inlining requires `-opt-inline-from`): `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`, `inline`." - - choice: l:project + - choice: "l:project" description: "Enable cross-method optimizations within the current project." deprecated: "Use `-opt:l:inline -opt-inline-from` instead." - - choice: l:classpath + - choice: "l:classpath" description: "Enable cross-method optimizations across the entire classpath." deprecated: "Use `-opt:l:inline -opt-inline-from` instead." description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." - - option: -opt-inline-from + - option: "-opt-inline-from" schema: - type: String + type: "String" multiple: true - arg: pattern + arg: "pattern" description: "Patterns for classfile names from which to allow inlining, `help` for details." - - option: -Yopt-inline-heuristics + - option: "-Yopt-inline-heuristics" schema: - type: Choice - arg: strategy - default: default + type: "Choice" + arg: "strategy" + default: "default" choices: - - choice: at-inline-annotated - - choice: everything - - choice: default + - choice: "at-inline-annotated" + - choice: "everything" + - choice: "default" description: "Set the heuristics for inlining decisions." - - option: -opt-warnings + - option: "-opt-warnings" schema: - type: Choice + type: "Choice" multiple: true - default: at-inline-failed + default: "at-inline-failed" choices: - - choice: none + - choice: "none" description: "No optimizer warnings." - - choice: at-inline-failed-summary + - choice: "at-inline-failed-summary" description: "One-line summary if there were `@inline` method calls that could not be inlined." - - choice: at-inline-failed + - choice: "at-inline-failed" description: "A detailed warning for each `@inline` method call that could not be inlined." - - choice: any-inline-failed + - choice: "any-inline-failed" description: "A detailed warning for every callsite that was chosen for inlining by the heuristics, but could not be inlined." - - choice: no-inline-mixed + - choice: "no-inline-mixed" description: "In mixed compilation, warn at callsites methods defined in java sources (the inlining decision cannot be made without bytecode)." - - choice: no-inline-missing-bytecode + - choice: "no-inline-missing-bytecode" description: "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath." - - choice: no-inline-missing-attribute + - choice: "no-inline-missing-attribute" description: "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute." description: "Enable optimizer warnings." - - option: -Yopt-trace + - option: "-Yopt-trace" schema: - type: String - arg: package/Class.method + type: "String" + arg: "package/Class.method" description: "Trace the optimizer progress for methods; `_` to print all, prefix match to select." - - option: -Yopt-log-inline + - option: "-Yopt-log-inline" schema: - type: String - arg: package/Class.method + type: "String" + arg: "package/Class.method" description: "Print a summary of inliner activity; `_` to print all, prefix match to select." - - option: -Ystatistics + - option: "-Ystatistics" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" default: "parser,typer,patmat,erasure,cleanup,jvm" description: "Print compiler statistics for specific phases. (see [Compilation Phases](#compilation-phases))" - - option: -Yhot-statistics-enabled + - option: "-Yhot-statistics-enabled" schema: - type: Boolean + type: "Boolean" description: "Enable `-Ystatistics` to print hot statistics." - - option: -Yprofile-enabled + - option: "-Yprofile-enabled" schema: - type: Boolean + type: "Boolean" description: "Enable profiling." - - option: -Yprofile-destination - arg: file + - option: "-Yprofile-destination" + arg: "file" schema: - type: String + type: "String" description: "where to send profiling output - specify a file, default is to the console." note: "`-Yprofile-enabled` is enabled at the same time." - - option: -Yprofile-external-tool + - option: "-Yprofile-external-tool" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" default: "typer" description: "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase." note: "`-Yprofile-enabled` is enabled at the same time." - - option: -Yprofile-run-gc + - option: "-Yprofile-run-gc" schema: - type: Phases - arg: phases + type: "Phases" + arg: "phases" default: "_" description: "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or `all`." note: "`-Yprofile-enabled` is enabled at the same time." # Area-specific debug output. - - option: -Ydoc-debug + - option: "-Ydoc-debug" schema: - type: Boolean + type: "Boolean" description: "Trace all scaladoc activity." - - option: -Yide-debug + - option: "-Yide-debug" schema: - type: Boolean + type: "Boolean" description: "Generate, validate and output trees using the interactive compiler." - - option: -Yissue-debug + - option: "-Yissue-debug" schema: - type: Boolean + type: "Boolean" description: "Print stack traces when a context issues an error." - - option: -Ymacro-debug-lite + - option: "-Ymacro-debug-lite" schema: - type: Boolean + type: "Boolean" description: "Trace essential macro-related activities." - - option: -Ymacro-debug-verbose + - option: "-Ymacro-debug-verbose" schema: - type: Boolean + type: "Boolean" description: "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions." - - option: -Ypos-debug + - option: "-Ypos-debug" schema: - type: Boolean + type: "Boolean" description: "Trace position validation." - - option: -Yreify-debug + - option: "-Yreify-debug" schema: - type: Boolean + type: "Boolean" description: "Trace reification." - - option: -Ytyper-debug + - option: "-Ytyper-debug" schema: - type: Boolean + type: "Boolean" description: "Trace all type assignments." - - option: -Ypatmat-debug + - option: "-Ypatmat-debug" schema: - type: Boolean + type: "Boolean" description: "Trace pattern matching translation." - - option: -Ypatmat-exhaust-depth + - option: "-Ypatmat-exhaust-depth" schema: - type: Int - arg: off + type: "Int" + arg: "off" default: 20 min: 10 max: Int.MaxValue description: "off" - - option: -Yquasiquote-debug + - option: "-Yquasiquote-debug" schema: - type: Boolean + type: "Boolean" description: "Trace quasiquote-related activities." # Groups of Settings. - - option: -Xfuture + - option: "-Xfuture" schema: - type: Boolean + type: "Boolean" description: "Turn on future language features." - enablingIfNotSetByUser: futureSettings - - option: -Xexperimental + - option: "-Xexperimental" schema: - type: Boolean + type: "Boolean" description: "Enable experimental extensions in Scala 2.12 and earlier." deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." - - option : -Xmacro-settings + - option : "-Xmacro-settings" schema: - type: String + type: "String" multiple: true description: "Custom settings for macros." # * IDE-specific settings - - option: -Ypresentation-verbose + - option: "-Ypresentation-verbose" schema: - type: Boolean + type: "Boolean" description: "Print information about presentation compiler tasks." - - option: -Ypresentation-debug + - option: "-Ypresentation-debug" schema: - type: Boolean + type: "Boolean" description: "Enable debugging output for the presentation compiler." - - option: -Ypresentation-any-thread + - option: "-Ypresentation-any-thread" schema: - type: Boolean + type: "Boolean" description: "Allow use of the presentation compiler from any thread." - - option: -Ypresentation-strict + - option: "-Ypresentation-strict" schema: - type: Boolean + type: "Boolean" description: "Do not report type errors in sources with syntax errors." - - option: -Ypresentation-log + - option: "-Ypresentation-log" schema: - type: String - arg: file + type: "String" + arg: "file" description: "Log presentation compiler events into file." - - option: -Ypresentation-replay + - option: "-Ypresentation-replay" schema: - type: String - arg: file + type: "String" + arg: "file" description: "Replay presentation compiler events from file." - - option: -Ypresentation-delay + - option: "-Ypresentation-delay" schema: - type: Int - arg: miliseconds + type: "Int" + arg: "miliseconds" default: 0 min: 0 max: 999 @@ -888,124 +886,124 @@ -- category: Warning Settings +- category: "Warning Settings" description: "This section assembles the `-X` and `-Y` options those influence the printing of warnings." options: - - option: -Xfatal-warnings + - option: "-Xfatal-warnings" schema: - type: Boolean + type: "Boolean" description: "Fail the compilation if there are any warnings." - - option: -Ywarn-macros + - option: "-Ywarn-macros" schema: - type: Choice - arg: mode + type: "Choice" + arg: "mode" choices: - - choice: none + - choice: "none" description: "Do not inspect expansions or their original trees when generating unused symbol warnings." - - choice: before + - choice: "before" description: "Only inspect unexpanded user-written code for unused symbols." - - choice: after + - choice: "after" description: "Only inspect expanded trees when generating unused symbol warnings." - - choice: both + - choice: "both" description: "Inspect both user-written code and expanded trees when generating unused symbol warnings." description: "Enable lint warnings on macro expansions." - - option: -Ywarn-dead-code + - option: "-Ywarn-dead-code" schema: - type: Boolean + type: "Boolean" description: "Warn when dead code is identified." - - option: -Ywarn-value-discard + - option: "-Ywarn-value-discard" schema: - type: Boolean + type: "Boolean" description: "Warn when non-Unit expression results are unused." note: "To reduce noises for common idiom, warning are suppressed if type of results are `this.type`." - - option: -Ywarn-numeric-widen + - option: "-Ywarn-numeric-widen" schema: - type: Boolean + type: "Boolean" description: "Warn when numerics are widened." - - option: -Ywarn-unused + - option: "-Ywarn-unused" schema: - type: Choice + type: "Choice" multiple: true - arg: warn - default: _ + arg: "warn" + default: "_" choices: - - choice: imports + - choice: "imports" description: "Warn if an import selector is not referenced." - - choice: patvars + - choice: "patvars" description: "Warn if a variable bound in a pattern is unused." - - choice: privates + - choice: "privates" description: "Warn if a private member is unused." - - choice: locals + - choice: "locals" description: "Warn if a local definition is unused." - - choice: explicits + - choice: "explicits" description: "Warn if an explicit parameter is unused." - - choice: implicits + - choice: "implicits" description: "Warn if an implicit parameter is unused." - - choice: params + - choice: "params" description: "Enable `-Ywarn-unused:explicits,implicits`." - - choice: linted + - choice: "linted" description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." note: "Alias is `-Xlint:unused`." description: "Enable or disable specific `unused` warnings." - - option: -Ywarn-unused-import + - option: "-Ywarn-unused-import" schema: - type: Boolean + type: "Boolean" description: "Warn when imports are unused." - - option: -Ywarn-extra-implicit + - option: "-Ywarn-extra-implicit" schema: - type: Boolean + type: "Boolean" description: "Warn when more than one implicit parameter section is defined." - - option: -Ywarn-self-implicit + - option: "-Ywarn-self-implicit" schema: - type: Boolean + type: "Boolean" description: "Warn when an implicit resolves to an enclosing self-definition." - - option: -Xlint + - option: "-Xlint" schema: - type: Choice + type: "Choice" multiple: true - arg: warn - default: _ + arg: "warn" + default: "_" choices: - - choice: adapted-args + - choice: "adapted-args" description: "Warn if an argument list is modified to match the receiver." note: "Alias is `-Ywarn-adapted-args`." - - choice: nullary-unit + - choice: "nullary-unit" description: "Warn when nullary methods return Unit." note: "Alias is `-Ywarn-nullary-unit`." - - choice: inaccessible + - choice: "inaccessible" description: "Warn about inaccessible types in method signatures." note: "Alias is `-Ywarn-inaccessible`." - - choice: nullary-override + - choice: "nullary-override" description: "Warn when non-nullary `def f()` overrides nullary `def f`." note: "Alias is `-Ywarn-nullary-override`." - - choice: infer-any + - choice: "infer-any" description: "Warn when a type argument is inferred to be `Any`." note: "Alias is `-Ywarn-infer-any`." - - choice: missing-interpolator + - choice: "missing-interpolator" description: "A string literal appears to be missing an interpolator id." - - choice: doc-detached + - choice: "doc-detached" description: "A Scaladoc comment appears to be detached from its element." - - choice: private-shadow + - choice: "private-shadow" description: "A private field (or class parameter) shadows a superclass field." - - choice: type-parameter-shadow + - choice: "type-parameter-shadow" description: "A local type parameter shadows a type already in scope." - - choice: poly-implicit-overload + - choice: "poly-implicit-overload" description: "Parameterized overloaded implicit methods are not visible as view bounds." - - choice: option-implicit + - choice: "option-implicit" description: "Option.apply used implicit view." - - choice: delayedinit-select + - choice: "delayedinit-select" description: "Selecting member of DelayedInit." - - choice: by-name-right-associative + - choice: "by-name-right-associative" description: "By-name parameter of right associative operator." - - choice: package-object-classes + - choice: "package-object-classes" description: "Class or object defined in package object." - - choice: unsound-match + - choice: "unsound-match" description: "Pattern match may not be typesafe." - - choice: stars-align + - choice: "stars-align" description: "Pattern sequence wildcard must align with sequence component." - - choice: constant + - choice: "constant" description: "Evaluation of a constant arithmetic expression results in an error." - - choice: unused + - choice: "unused" description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." description: "Enable or disable specific warnings." note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." From e5dd280f3743077480e04b1dcd3f75c5f06102d3 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 06:49:35 +0900 Subject: [PATCH 0187/3174] Make abbreviations multiple --- _data/compiler-options.yml | 9 ++++++--- _overviews/compiler-options/index.md | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 2d7d50d35c..8b815f0d14 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -3,11 +3,12 @@ options: # Path related settings. - option: "-classpath" - abbreviation: "-cp" schema: type: "Path" arg: "path" description: "Specify where to find user class files." + abbreviations: + - "-cp" - option: "-bootclasspath" schema: type: "Path" @@ -81,10 +82,11 @@ type: "Boolean" description: "Generate no warnings." - option: "-optimise" - abbreviation: "-optimize" schema: type: "Boolean" description: "Compiler flag for the optimizer in Scala 2.11." + abbreviations: + - "-optimize" deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." - option: "-print" schema: @@ -540,11 +542,12 @@ arg: "dir" description: "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders)." - option: "-Ystop-after" - abbreviation: "-stop" schema: type: "Phases" arg: "phases" description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" + abbreviations: + - "-stop" - option: "-Ystop-before" schema: type: "Phases" diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index 47536e5036..69e2338a82 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -81,7 +81,11 @@ scalacOptions ++= Seq( {% capture option_argument %}{% if option.schema.type != "Boolean" and option.schema.type != "Prefix" %}{{ option_argument_separator }}{{ option_argument_placeholder }}{% if option.schema.multiple %}1,{{ option_argument_placeholder }}2{% endif %}{% endif %}{% endcapture %}
    {{ option.option | xml_escape }}{{ option_argument }} - {% if option.abbreviation %} or {{ option.abbreviation | xml_escape }}{{ option_argument }}{% endif %} + {% if option.abbreviations %} + {% for abbreviation in option.abbreviations %} + or {{ abbreviation | xml_escape }}{{ option_argument }} + {% endfor %} + {% endif %}
    {% if option.deprecated %}
    Deprecated: {{ option.deprecated | markdownify | remove: '

    ' | remove: '

    '}}
    {% endif %}
    From 15ce710f546d4d47b20519edb9bdaffcd46a9eb7 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 06:51:43 +0900 Subject: [PATCH 0188/3174] Indent array elements uniformly (no indent) --- _data/compiler-options.yml | 1944 ++++++++++++++++++------------------ 1 file changed, 972 insertions(+), 972 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 8b815f0d14..1c01c40fbd 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -2,409 +2,409 @@ description: "A set of standard options that are supported on the current development environment and will be supported in future releases." options: # Path related settings. - - option: "-classpath" - schema: - type: "Path" - arg: "path" - description: "Specify where to find user class files." - abbreviations: - - "-cp" - - option: "-bootclasspath" - schema: - type: "Path" - arg: "path" - default: "Defaults.scalaBootClassPath" - description: "Override location of bootstrap class files." - - option: "-extdirs" - schema: - type: "Path" - arg: "path" - default: "Defaults.scalaExtDirs" - description: "Override location of installed extensions." - - option: "-javabootclasspath" - schema: - type: "Path" - arg: "path" - default: "Defaults.javaBootClassPath" - description: "Override java boot classpath." - - option: "-javaextdirs" - schema: - type: "Path" - arg: "path" - default: "Defaults.javaExtDirs" - description: "Override java extdirs classpath." - - option: "-sourcepath" - schema: - type: "Path" - description: "Specify location(s) of source files." - - option: "-dependencyfile" - schema: - type: "String" - arg: "file" - default: ".scala_dependencies" - description: "Set dependency tracking file." - - option: "-deprecation" - schema: - type: "Boolean" - description: "Emit warning and location for usages of deprecated APIs." - - option: "-encoding" - schema: - type: "String" - arg: "encoding" - default: "Properties.sourceEncoding" - description: "Specify character encoding used by source files." - - option: "-explaintypes" - schema: - type: "Boolean" - description: "Explain type errors in more detail." - - option: "-feature" - schema: - type: "Boolean" - description: "Emit warning and location for usages of features that should be imported explicitly." - - option: "-g" - schema: - type: "Choice" - arg: "level" - default: "vars" - choices: - - choice: "none" - - choice: "source" - - choice: "line" - - choice: "vars" - - choice: "notailcalls" - description: "Set level of generated debugging info." - - option: "-help" - schema: - type: "Boolean" - description: "Print a synopsis of standard options." - - option: "-nowarn" - schema: - type: "Boolean" - description: "Generate no warnings." - - option: "-optimise" - schema: - type: "Boolean" - description: "Compiler flag for the optimizer in Scala 2.11." - abbreviations: - - "-optimize" - deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." - - option: "-print" - schema: - type: "Boolean" - description: "Print program with Scala-specific features removed." - - option: "-target" - scheam: - type: "Choice" - default: "jvm-1.8" - choices: - - choice: "jvm-1.5" - - choice: "jvm-1.6" - - choice: "jvm-1.7" - - choice: "jvm-1.8" - description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." - - option: "-unchecked" - schema: - type: "Boolean" - description: "Enable additional warnings where generated code depends on assumptions." - - option: "-uniqid" - schema: - type: "Boolean" - description: "Uniquely tag all identifiers in debugging output." - - option: "-usejavacp" - schema: - type: "Boolean" - description: "Utilize the `java.class.path` in classpath resolution." - - option: "-usemanifestcp" - schema: - type: "Boolean" - description: "Utilize the manifest in classpath resolution." - - option: "-verbose" - schema: - type: "Boolean" - description: "Output messages about what the compiler is doing." - - option: "-version" - schema: - type: "Boolean" - description: "Print product version and exit." - - option: "-no-specialization" - schema: - type: "Boolean" - description: "Ignore `@specialize` annotations." - - option: "-language" - schema: - type: "Choice" - multiple: true - arg: "feat" - choices: - - choice: "dynamics" - description: "Allow direct or indirect subclasses of `scala.Dynamic`." - - choice: "postfixOps" - description: "Allow postfix operator notation, such as `1 to 10 toList`." - - choice: "reflectiveCalls" - description: "Allow reflective access to members of structural types." - - choice: "implicitConversions" - description: "Allow definition of implicit functions called views." - - choice: "higherKinds" - description: "Allow higher-kinded types." - - choice: "existentials" - description: "Existential types (besides wildcard types) can be written and inferred." - - choice: "experimental.macros" - description: "Allow macro definition (besides implementation and application." - description: "Enable or disable language features." - - option: "-release" - schema: - type: "String" - arg: "release" - description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." + - option: "-classpath" + schema: + type: "Path" + arg: "path" + description: "Specify where to find user class files." + abbreviations: + - "-cp" + - option: "-bootclasspath" + schema: + type: "Path" + arg: "path" + default: "Defaults.scalaBootClassPath" + description: "Override location of bootstrap class files." + - option: "-extdirs" + schema: + type: "Path" + arg: "path" + default: "Defaults.scalaExtDirs" + description: "Override location of installed extensions." + - option: "-javabootclasspath" + schema: + type: "Path" + arg: "path" + default: "Defaults.javaBootClassPath" + description: "Override java boot classpath." + - option: "-javaextdirs" + schema: + type: "Path" + arg: "path" + default: "Defaults.javaExtDirs" + description: "Override java extdirs classpath." + - option: "-sourcepath" + schema: + type: "Path" + description: "Specify location(s) of source files." + - option: "-dependencyfile" + schema: + type: "String" + arg: "file" + default: ".scala_dependencies" + description: "Set dependency tracking file." + - option: "-deprecation" + schema: + type: "Boolean" + description: "Emit warning and location for usages of deprecated APIs." + - option: "-encoding" + schema: + type: "String" + arg: "encoding" + default: "Properties.sourceEncoding" + description: "Specify character encoding used by source files." + - option: "-explaintypes" + schema: + type: "Boolean" + description: "Explain type errors in more detail." + - option: "-feature" + schema: + type: "Boolean" + description: "Emit warning and location for usages of features that should be imported explicitly." + - option: "-g" + schema: + type: "Choice" + arg: "level" + default: "vars" + choices: + - choice: "none" + - choice: "source" + - choice: "line" + - choice: "vars" + - choice: "notailcalls" + description: "Set level of generated debugging info." + - option: "-help" + schema: + type: "Boolean" + description: "Print a synopsis of standard options." + - option: "-nowarn" + schema: + type: "Boolean" + description: "Generate no warnings." + - option: "-optimise" + schema: + type: "Boolean" + description: "Compiler flag for the optimizer in Scala 2.11." + abbreviations: + - "-optimize" + deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." + - option: "-print" + schema: + type: "Boolean" + description: "Print program with Scala-specific features removed." + - option: "-target" + scheam: + type: "Choice" + default: "jvm-1.8" + choices: + - choice: "jvm-1.5" + - choice: "jvm-1.6" + - choice: "jvm-1.7" + - choice: "jvm-1.8" + description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." + - option: "-unchecked" + schema: + type: "Boolean" + description: "Enable additional warnings where generated code depends on assumptions." + - option: "-uniqid" + schema: + type: "Boolean" + description: "Uniquely tag all identifiers in debugging output." + - option: "-usejavacp" + schema: + type: "Boolean" + description: "Utilize the `java.class.path` in classpath resolution." + - option: "-usemanifestcp" + schema: + type: "Boolean" + description: "Utilize the manifest in classpath resolution." + - option: "-verbose" + schema: + type: "Boolean" + description: "Output messages about what the compiler is doing." + - option: "-version" + schema: + type: "Boolean" + description: "Print product version and exit." + - option: "-no-specialization" + schema: + type: "Boolean" + description: "Ignore `@specialize` annotations." + - option: "-language" + schema: + type: "Choice" + multiple: true + arg: "feat" + choices: + - choice: "dynamics" + description: "Allow direct or indirect subclasses of `scala.Dynamic`." + - choice: "postfixOps" + description: "Allow postfix operator notation, such as `1 to 10 toList`." + - choice: "reflectiveCalls" + description: "Allow reflective access to members of structural types." + - choice: "implicitConversions" + description: "Allow definition of implicit functions called views." + - choice: "higherKinds" + description: "Allow higher-kinded types." + - choice: "existentials" + description: "Existential types (besides wildcard types) can be written and inferred." + - choice: "experimental.macros" + description: "Allow macro definition (besides implementation and application." + description: "Enable or disable language features." + - option: "-release" + schema: + type: "String" + arg: "release" + description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." - category: "JVM Settings" description: "Settings influencing the runtime system." options: - - option: "-Jflag" - schema: - type: "Prefix" - description: "Pass `flag` directly to the runtime system." - - option: "-Dproperty=value" - schema: - type: "Prefix" - description: "Pass `-Dproperty=value` directly to the runtime system." - - option: "-nobootcp" - schema: - type: "Boolean" - description: "Do not use the boot classpath for the scala jars." + - option: "-Jflag" + schema: + type: "Prefix" + description: "Pass `flag` directly to the runtime system." + - option: "-Dproperty=value" + schema: + type: "Prefix" + description: "Pass `-Dproperty=value` directly to the runtime system." + - option: "-nobootcp" + schema: + type: "Boolean" + description: "Do not use the boot classpath for the scala jars." - category: "Plugin Settings" description: "" options: - - option: "-P" - schema: - type: "Prefix" - arg: ":plugin:opt" - description: "Pass an option to a plugin in the form of `-P::`." - note: "If you use sbt, [compiler plugins support](https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html) may be useful." + - option: "-P" + schema: + type: "Prefix" + arg: ":plugin:opt" + description: "Pass an option to a plugin in the form of `-P::`." + note: "If you use sbt, [compiler plugins support](https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html) may be useful." - category: "Advanced Settings" description: "Options that starts with `-X` are maybe renamed or removed in future releases." options: - - option: "-X" - schema: - type: "Boolean" - description: "Print a synopsis of advanced options." - - option: "-Xcheckinit" - schema: - type: "Boolean" - description: "Wrap field accessors to throw an exception on uninitialized access." - - option: "-Xdev" - schema: - type: "Boolean" - description: "Indicates user is a developer - issue warnings about anything which seems amiss." - - option: "-Xdisable-assertions" - schema: - type: "Boolean" - description: "Generate no assertions or assumptions." - - option: "-Xelide-below" - schema: - type: "Int" - arg: "min" - default: "Int.MinValue" - description: "Calls to `@elidable` methods are omitted if method priority is lower than argument." - - option: "-Xno-forwarders" - schema: - type: "Boolean" - description: "Do not generate static forwarders in mirror classes." - - option: "-Xgenerate-phase-graph" - schema: - type: "String" - arg: "file" - description: "Generate the phase graphs (outputs .dot files) to fileX.dot." - - option: "-Xlog-implicits" - schema: - type: "Boolean" - description: "Show more detail on why some implicits are not applicable." - - option: "-Xlog-implicit-conversions" - schema: - type: "Boolean" - description: "Print a message whenever an implicit conversion is inserted." - - option: "-Xlog-reflective-calls" - schema: - type: "Boolean" - description: "Print a message when a reflective method call is generated." - - option: "-Xlog-free-terms" - schema: - type: "Boolean" - description: "Print a message when reification creates a free term." - - option: "-Xlog-free-types" - schema: - type: "Boolean" - description: "Print a message when reification resorts to generating a free type." - - option: "-Xmax-classfile-name" - schema: - type: "Int" - arg: "max" - default: 255 - min: 72 - max: 255 - description: "Maximum filename length for generated classes." - - option: "-Xmaxerrs" - schema: - type: "Int" - arg: "max" - default: 100 - description: "Maximum errors to print." - - option: "-Xmaxwarns" - schema: - type: "Int" - arg: "max" - default: 100 - description: "Maximum warnings to print." - - option: "-Xmigration" - schema: - type: "ScalaVersion" - arg: "version" - default: "any" - description: "Warn about constructs whose behavior may have changed since version." - - option: "-Xno-uescape" - schema: - type: "Boolean" - description: "Disable handling of \\u unicode escapes." - - option: "-Xnojline" - schema: - type: "Boolean" - description: "Do not use JLine for editing." - - option: "-Xverify" - schema: - type: "Boolean" - description: "Verify generic signatures in generated bytecode." - - option: "-Xplugin" - schema: - type: "String" - multiple: true - arg: "path" - description: "Load a plugin from each classpath." - - option: "-Xplugin-disable" - schema: - type: "String" - multiple: true - arg: "plugin" - description: "Disable plugins by name." - - option: "-Xplugin-list" - schema: - type: "Boolean" - description: "Print a synopsis of loaded plugins." - - option: "-Xplugin-require" - schema: - type: "String" - multiple: true - arg: "plugin" - description: "Abort if a named plugin is not loaded." - - option: "-Xpluginsdir" - schema: - type: "String" - arg: "path" - default: "Defaults.scalaPluginPath" - description: "Path to search for plugin archives." - - option: "-Xprint" - schema: - type: "Phases" - arg: "phases" - description: "Print out program after PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Xprint-pos" - schema: - type: "Boolean" - description: "Print tree positions, as offsets." - - option: "-Xprint-types" - schema: - type: "Boolean" - description: "Print tree types (debugging option)." - - option: "-Xprint-args" - schema: - type: "Boolean" - description: "Print all compiler arguments and exit." - - option: "-Xprompt" - schema: - type: "Boolean" - description: "Display a prompt after each error (debugging option)." - - option: "-Xresident" - schema: - type: "Boolean" - description: "Compiler stays resident: read source filenames from standard input." - - option: "-Xscript" - schema: - type: "String" - arg: "object" - description: "Treat the source file as a script and wrap it in a main method." - - option: "-Xmain-class" - schema: - type: "String" - arg: "path" - description: "Class for manifest's Main-Class entry (only useful with `-d `)" - - option: "-Xshow-class" - schema: - type: "String" - arg: "class" - description: "Show internal representation of class." - - option: "-Xshow-object" - schema: - type: "String" - arg: "object" - description: "Show internal representation of object." - - option: "-Xshow-phases" - schema: - type: "Boolean" - description: "Print a synopsis of compiler phases." - - option: "-Xsource-reader" - schema: - type: "String" - arg: "classname" - description: "Specify a custom method for reading source files." - - option: "-Xreporter" - schema: - type: "String" - arg: "classname" - default: "scala.tools.nsc.reporters.ConsoleReporter" - description: "Specify a custom reporter for compiler messages." - - option: "-Xstrict-inference" - schema: - type: "Boolean" - description: "Don't infer known-unsound types." - - option: "-Xsource" - schema: - type: "Scala Version" - arg: "version" - default: "2.13" - description: "Treat compiler input as Scala source for the specified version, see [scala/bug#8126](https://github.com/scala/bug/issues/8126)." - - option: "-Xno-patmat-analysis" - schema: - type: "Boolean" - description: "Don't perform exhaustivity/unreachability analysis. Also, ignore `@switch` annotation." - - option: "-Xfull-lubs" - schema: - type: "Boolean" - description: "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds." - - option: "-Xmixin-force-forwarders" - schema: - type: "Choice" - arg: "mode" - default: "true" - choices: - - choice: "true" - description: "Always generate mixin forwarders." - - choice: "junit" - description: "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods)." - - choice: "false" - description: "Only generate mixin forwarders required for program correctness." - description: "Generate forwarder methods in classes inhering concrete methods from traits." - - option: "-Xxml" - schema: - type: "Choice" - arg: "property" - choices: - - choice: "coalescing" - description: "Convert PCData to Text and coalesce sibling nodes." - description: "Configure XML parsing." + - option: "-X" + schema: + type: "Boolean" + description: "Print a synopsis of advanced options." + - option: "-Xcheckinit" + schema: + type: "Boolean" + description: "Wrap field accessors to throw an exception on uninitialized access." + - option: "-Xdev" + schema: + type: "Boolean" + description: "Indicates user is a developer - issue warnings about anything which seems amiss." + - option: "-Xdisable-assertions" + schema: + type: "Boolean" + description: "Generate no assertions or assumptions." + - option: "-Xelide-below" + schema: + type: "Int" + arg: "min" + default: "Int.MinValue" + description: "Calls to `@elidable` methods are omitted if method priority is lower than argument." + - option: "-Xno-forwarders" + schema: + type: "Boolean" + description: "Do not generate static forwarders in mirror classes." + - option: "-Xgenerate-phase-graph" + schema: + type: "String" + arg: "file" + description: "Generate the phase graphs (outputs .dot files) to fileX.dot." + - option: "-Xlog-implicits" + schema: + type: "Boolean" + description: "Show more detail on why some implicits are not applicable." + - option: "-Xlog-implicit-conversions" + schema: + type: "Boolean" + description: "Print a message whenever an implicit conversion is inserted." + - option: "-Xlog-reflective-calls" + schema: + type: "Boolean" + description: "Print a message when a reflective method call is generated." + - option: "-Xlog-free-terms" + schema: + type: "Boolean" + description: "Print a message when reification creates a free term." + - option: "-Xlog-free-types" + schema: + type: "Boolean" + description: "Print a message when reification resorts to generating a free type." + - option: "-Xmax-classfile-name" + schema: + type: "Int" + arg: "max" + default: 255 + min: 72 + max: 255 + description: "Maximum filename length for generated classes." + - option: "-Xmaxerrs" + schema: + type: "Int" + arg: "max" + default: 100 + description: "Maximum errors to print." + - option: "-Xmaxwarns" + schema: + type: "Int" + arg: "max" + default: 100 + description: "Maximum warnings to print." + - option: "-Xmigration" + schema: + type: "ScalaVersion" + arg: "version" + default: "any" + description: "Warn about constructs whose behavior may have changed since version." + - option: "-Xno-uescape" + schema: + type: "Boolean" + description: "Disable handling of \\u unicode escapes." + - option: "-Xnojline" + schema: + type: "Boolean" + description: "Do not use JLine for editing." + - option: "-Xverify" + schema: + type: "Boolean" + description: "Verify generic signatures in generated bytecode." + - option: "-Xplugin" + schema: + type: "String" + multiple: true + arg: "path" + description: "Load a plugin from each classpath." + - option: "-Xplugin-disable" + schema: + type: "String" + multiple: true + arg: "plugin" + description: "Disable plugins by name." + - option: "-Xplugin-list" + schema: + type: "Boolean" + description: "Print a synopsis of loaded plugins." + - option: "-Xplugin-require" + schema: + type: "String" + multiple: true + arg: "plugin" + description: "Abort if a named plugin is not loaded." + - option: "-Xpluginsdir" + schema: + type: "String" + arg: "path" + default: "Defaults.scalaPluginPath" + description: "Path to search for plugin archives." + - option: "-Xprint" + schema: + type: "Phases" + arg: "phases" + description: "Print out program after PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Xprint-pos" + schema: + type: "Boolean" + description: "Print tree positions, as offsets." + - option: "-Xprint-types" + schema: + type: "Boolean" + description: "Print tree types (debugging option)." + - option: "-Xprint-args" + schema: + type: "Boolean" + description: "Print all compiler arguments and exit." + - option: "-Xprompt" + schema: + type: "Boolean" + description: "Display a prompt after each error (debugging option)." + - option: "-Xresident" + schema: + type: "Boolean" + description: "Compiler stays resident: read source filenames from standard input." + - option: "-Xscript" + schema: + type: "String" + arg: "object" + description: "Treat the source file as a script and wrap it in a main method." + - option: "-Xmain-class" + schema: + type: "String" + arg: "path" + description: "Class for manifest's Main-Class entry (only useful with `-d `)" + - option: "-Xshow-class" + schema: + type: "String" + arg: "class" + description: "Show internal representation of class." + - option: "-Xshow-object" + schema: + type: "String" + arg: "object" + description: "Show internal representation of object." + - option: "-Xshow-phases" + schema: + type: "Boolean" + description: "Print a synopsis of compiler phases." + - option: "-Xsource-reader" + schema: + type: "String" + arg: "classname" + description: "Specify a custom method for reading source files." + - option: "-Xreporter" + schema: + type: "String" + arg: "classname" + default: "scala.tools.nsc.reporters.ConsoleReporter" + description: "Specify a custom reporter for compiler messages." + - option: "-Xstrict-inference" + schema: + type: "Boolean" + description: "Don't infer known-unsound types." + - option: "-Xsource" + schema: + type: "Scala Version" + arg: "version" + default: "2.13" + description: "Treat compiler input as Scala source for the specified version, see [scala/bug#8126](https://github.com/scala/bug/issues/8126)." + - option: "-Xno-patmat-analysis" + schema: + type: "Boolean" + description: "Don't perform exhaustivity/unreachability analysis. Also, ignore `@switch` annotation." + - option: "-Xfull-lubs" + schema: + type: "Boolean" + description: "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds." + - option: "-Xmixin-force-forwarders" + schema: + type: "Choice" + arg: "mode" + default: "true" + choices: + - choice: "true" + description: "Always generate mixin forwarders." + - choice: "junit" + description: "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods)." + - choice: "false" + description: "Only generate mixin forwarders required for program correctness." + description: "Generate forwarder methods in classes inhering concrete methods from traits." + - option: "-Xxml" + schema: + type: "Choice" + arg: "property" + choices: + - choice: "coalescing" + description: "Convert PCData to Text and coalesce sibling nodes." + description: "Configure XML parsing." @@ -416,597 +416,597 @@ Some optimization-related options, e.g. `-opt:**` and `-opt-inline-form` are included in this section, since **REASON_HERE**. options: - - option: "-Y" - schema: - type: "Boolean" - description: "Print a synopsis of private options." - - option: "-Yoverride-objects" - schema: - type: "Boolean" - description: "Allow member objects to be overridden." - - option: "-Yoverride-vars" - schema: - type: "Boolean" - description: "Allow vars to be overridden." - - option: "-Ybreak-cycles" - schema: - type: "Boolean" - description: "Attempt to break cycles encountered during typing." - - option: "-Ybrowse" - schema: - type: "Phases" - arg: "phases" - description: "Browse the abstract syntax tree after PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Ycheck" - schema: - type: "Phases" - arg: "phases" - description: "Check the tree at the end of PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Yshow" - schema: - type: "Phases" - arg: "phases" - description: "(Requires `-Xshow-class` or `-Xshow-object`) Show after PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Ycompact-trees" - schema: - type: "Boolean" - description: "Use compact tree printer when displaying trees." - - option: "-Yno-completion" - schema: - type: "Boolean" - description: "Disable tab-completion in the REPL." - - option: "-Ydebug" - schema: - type: "Boolean" - description: "Increase the quantity of debugging output." - - option: "-Yresolve-term-conflict" - schema: - type: "Choice" - arg: "strategy" - default: "error" - choices: - - choice: "package" - - choice: "object" - - choice: "error" - description: "Resolve term conflicts." - - option: "-Ylog" - schema: - type: "Phases" - arg: "phases" - description: "Log operations during PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Ylog-classpath" - schema: - type: "Boolean" - description: "Output information about what classpath is being applied." - - option: "-Yno-generic-signatures" - schema: - type: "Boolean" - description: "Suppress generation of generic signatures for Java." - - option: "-Yno-imports" - schema: - type: "Boolean" - description: "Compile without importing scala.*, java.lang.*, or Predef." - - option: "-Yno-predef" - schema: - type: "Boolean" - description: "Compile without importing Predef." - - option: "-Yno-adapted-args" - schema: - type: "Boolean" - description: "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver." - - option: "-Yrecursion" - schema: - type: "Int" - arg: "depth" - default: 0 - min: 0 - max: Int.MaxValue - description: "Set recursion depth used when locking symbols." - - option: "-Yshow-trees" - schema: - type: "Boolean" - description: "(Requires `-Xprint:`) Print detailed ASTs in formatted form." - - option: "-Yshow-trees-compact" - schema: - type: "Boolean" - description: "(Requires `-Xprint:`) Print detailed ASTs in compact form." - - option: "-Yshow-trees-stringified" - schema: - type: "Boolean" - description: "(Requires `-Xprint:`) Print stringifications along with detailed ASTs." - - option: "-Yshow-syms" - schema: - type: "Boolean" - description: "Print the AST symbol hierarchy after each phase." - - option: "-Yshow-symkinds" - schema: - type: "Boolean" - description: "Print abbreviated symbol kinds next to symbol names." - - option: "-Yshow-symowners" - schema: - type: "Boolean" - description: "Print owner identifiers next to symbol names." - - option: "-Yskip" - schema: - type: "Phases" - arg: "phases" - description: "Skip PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Ygen-asmp" - schema: - type: "String" - arg: "dir" - description: "Generate a parallel output directory of .asmp files (ie ASM Textifier output)." - - option: "-Ydump-classes" - schema: - type: "String" - arg: "dir" - description: "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders)." - - option: "-Ystop-after" - schema: - type: "Phases" - arg: "phases" - description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" - abbreviations: - - "-stop" - - option: "-Ystop-before" - schema: - type: "Phases" - arg: "phases" - description: "Stop before PHASES (see [Compilation Phases](#compilation-phases))" - - option: "-Yrangepos" - schema: - type: "Boolean" - description: "Use range positions for syntax trees." - - option: "-Yshow-member-pos" - schema: - type: "String" - arg: "style" - description: "Show start and end positions of members." - note: "`-Yrangepos` is enabled at the same time." - - option: "-Yreify-copypaste" - schema: - type: "Boolean" - description: "Dump the reified trees in copypasteable representation." - - option: "-Ymacro-expand" - schema: - type: "Choice" - arg: "policy" - default: "normal" - choices: - - choice: "none" - - choice: "normal" - - choice: "discard" - description: "Control expansion of macros, useful for scaladoc and presentation compiler." - - option: "-Ymacro-no-expand" - schema: - type: "Boolean" - description: "Don't expand macros. Might be useful for scaladoc and presentation compiler, but will crash anything which uses macros and gets past typer." - deprecated: "Use `-Ymacro-expand:none` instead." - - option: "-Yrepl-sync" - schema: - type: "Boolean" - description: "Do not use asynchronous code for REPL startup." - - option: "-Yrepl-class-based" - schema: - type: "Boolean" - description: "Use classes to wrap REPL snippets instead of objects." - - option: "-Yrepl-outdir" - schema: - type: "String" - arg: "path" - description: "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" - - option: "-Yinfer-argument-types" - schema: - type: "Boolean" - description: "Infer types for arguments of overridden methods." - - option: "-YdisableFlatCpCaching" - schema: - type: "Boolean" - description: "Do not cache flat classpath representation of classpath elements from jars across compiler instances." - - option: "-Yvirtpatmat" - schema: - type: "Boolean" - description: "Enable pattern matcher virtualization." - - option: "-Yexpose-empty-package" + - option: "-Y" + schema: + type: "Boolean" + description: "Print a synopsis of private options." + - option: "-Yoverride-objects" + schema: + type: "Boolean" + description: "Allow member objects to be overridden." + - option: "-Yoverride-vars" + schema: + type: "Boolean" + description: "Allow vars to be overridden." + - option: "-Ybreak-cycles" + schema: + type: "Boolean" + description: "Attempt to break cycles encountered during typing." + - option: "-Ybrowse" + schema: + type: "Phases" + arg: "phases" + description: "Browse the abstract syntax tree after PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Ycheck" + schema: + type: "Phases" + arg: "phases" + description: "Check the tree at the end of PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Yshow" + schema: + type: "Phases" + arg: "phases" + description: "(Requires `-Xshow-class` or `-Xshow-object`) Show after PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Ycompact-trees" + schema: + type: "Boolean" + description: "Use compact tree printer when displaying trees." + - option: "-Yno-completion" + schema: + type: "Boolean" + description: "Disable tab-completion in the REPL." + - option: "-Ydebug" + schema: + type: "Boolean" + description: "Increase the quantity of debugging output." + - option: "-Yresolve-term-conflict" + schema: + type: "Choice" + arg: "strategy" + default: "error" + choices: + - choice: "package" + - choice: "object" + - choice: "error" + description: "Resolve term conflicts." + - option: "-Ylog" + schema: + type: "Phases" + arg: "phases" + description: "Log operations during PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Ylog-classpath" + schema: + type: "Boolean" + description: "Output information about what classpath is being applied." + - option: "-Yno-generic-signatures" + schema: + type: "Boolean" + description: "Suppress generation of generic signatures for Java." + - option: "-Yno-imports" + schema: + type: "Boolean" + description: "Compile without importing scala.*, java.lang.*, or Predef." + - option: "-Yno-predef" + schema: + type: "Boolean" + description: "Compile without importing Predef." + - option: "-Yno-adapted-args" + schema: + type: "Boolean" + description: "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver." + - option: "-Yrecursion" + schema: + type: "Int" + arg: "depth" + default: 0 + min: 0 + max: Int.MaxValue + description: "Set recursion depth used when locking symbols." + - option: "-Yshow-trees" + schema: + type: "Boolean" + description: "(Requires `-Xprint:`) Print detailed ASTs in formatted form." + - option: "-Yshow-trees-compact" + schema: + type: "Boolean" + description: "(Requires `-Xprint:`) Print detailed ASTs in compact form." + - option: "-Yshow-trees-stringified" + schema: + type: "Boolean" + description: "(Requires `-Xprint:`) Print stringifications along with detailed ASTs." + - option: "-Yshow-syms" + schema: + type: "Boolean" + description: "Print the AST symbol hierarchy after each phase." + - option: "-Yshow-symkinds" + schema: + type: "Boolean" + description: "Print abbreviated symbol kinds next to symbol names." + - option: "-Yshow-symowners" + schema: + type: "Boolean" + description: "Print owner identifiers next to symbol names." + - option: "-Yskip" + schema: + type: "Phases" + arg: "phases" + description: "Skip PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Ygen-asmp" + schema: + type: "String" + arg: "dir" + description: "Generate a parallel output directory of .asmp files (ie ASM Textifier output)." + - option: "-Ydump-classes" + schema: + type: "String" + arg: "dir" + description: "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders)." + - option: "-Ystop-after" + schema: + type: "Phases" + arg: "phases" + description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" + abbreviations: + - "-stop" + - option: "-Ystop-before" + schema: + type: "Phases" + arg: "phases" + description: "Stop before PHASES (see [Compilation Phases](#compilation-phases))" + - option: "-Yrangepos" + schema: + type: "Boolean" + description: "Use range positions for syntax trees." + - option: "-Yshow-member-pos" + schema: + type: "String" + arg: "style" + description: "Show start and end positions of members." + note: "`-Yrangepos` is enabled at the same time." + - option: "-Yreify-copypaste" + schema: + type: "Boolean" + description: "Dump the reified trees in copypasteable representation." + - option: "-Ymacro-expand" + schema: + type: "Choice" + arg: "policy" + default: "normal" + choices: + - choice: "none" + - choice: "normal" + - choice: "discard" + description: "Control expansion of macros, useful for scaladoc and presentation compiler." + - option: "-Ymacro-no-expand" + schema: + type: "Boolean" + description: "Don't expand macros. Might be useful for scaladoc and presentation compiler, but will crash anything which uses macros and gets past typer." + deprecated: "Use `-Ymacro-expand:none` instead." + - option: "-Yrepl-sync" + schema: + type: "Boolean" + description: "Do not use asynchronous code for REPL startup." + - option: "-Yrepl-class-based" + schema: + type: "Boolean" + description: "Use classes to wrap REPL snippets instead of objects." + - option: "-Yrepl-outdir" + schema: + type: "String" + arg: "path" + description: "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" + - option: "-Yinfer-argument-types" + schema: + type: "Boolean" + description: "Infer types for arguments of overridden methods." + - option: "-YdisableFlatCpCaching" + schema: + type: "Boolean" + description: "Do not cache flat classpath representation of classpath elements from jars across compiler instances." + - option: "-Yvirtpatmat" + schema: + type: "Boolean" + description: "Enable pattern matcher virtualization." + - option: "-Yexpose-empty-package" # TODO: internal only - internalOnly: true - schema: - type: "Boolean" - description: "Internal only: expose the empty package." - - option: "-Ydelambdafy" - schema: - type: "Choice" - arg: "strategy" - default: "method" - choices: - - choice: "inline" - - choice: "method" - description: "Strategy used for translating lambdas into JVM code." - - option: "-Ybackend-parallelism" - schema: - type: "Int" - arg: "threads" - default: 1 - min: 1 - max: 16 - description: "Maximum worker threads for backend." - - option: "-Ybackend-worker-queue" - description: "Backend threads worker queue size." - schema: - type: "Int" - arg: "size" - default: 0 - min: 0 - max: 1000 - - option: "-Yjar-compression-level" - schema: - type: "Int" - arg: "level" - default: "Deflater.DEFAULT_COMPRESSION" - min: "Deflater.DEFAULT_COMPRESSION" - max: "Deflater.BEST_COMPRESSION" - description: "Compression level to use when writing jar files." - - option: "-Ycache-plugin-class-loader" - schema: - type: "Choice" - default: "none" - choices: - - choice: "none" - description: "Don't cache class loader." - - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." - - option: "-Ycache-macro-class-loader" - schema: - type: "Choice" - default: "none" - choices: - - choice: "none" - description: "Don't cache class loader." - - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for macros that are dynamically loaded." - - option: "-opt" - schema: - type: "Choice" - multiple: true - choices: - - choice: "unreachable-code" - description: "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers)." - - choice: "simplify-jumps" - description: "Simplify branching instructions, eliminate unnecessary ones." - - choice: "compact-locals" - description: "Eliminate empty slots in the sequence of local variables." - - choice: "copy-propagation" - description: "Eliminate redundant local variables and unused values (including closures). Enables unreachable-code." - - choice: "redundant-casts" - description: "Eliminate redundant casts using a type propagation analysis." - - choice: "box-unbox" - description: "Eliminate box-unbox pairs within the same method (also tuples, xRefs, value class instances). Enables unreachable-code." - - choice: "nullness-tracking" - description: "Track nullness / non-nullness of local variables and apply optimizations." - - choice: "closure-invocations" - description: "Rewrite closure invocations to the implementation method." - - choice: "inline" - description: "Inline method invocations according to `-Yopt-inline-heuristics` and `-opt-inline-from`." - - choice: "l:none" - description: "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox." - note: "Unlike the other optimizer levels, `l:none` appears up in the `opt.value` set because it's not an expanding option." - - choice: "l:default" - description: "Enable default optimizations: `unreachable-code`." - - choice: "l:method" - description: "Enable intra-method optimizations: `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`." - - choice: "l:inline" - description: "Enable cross-method optimizations (note: inlining requires `-opt-inline-from`): `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`, `inline`." - - choice: "l:project" - description: "Enable cross-method optimizations within the current project." - deprecated: "Use `-opt:l:inline -opt-inline-from` instead." - - choice: "l:classpath" - description: "Enable cross-method optimizations across the entire classpath." - deprecated: "Use `-opt:l:inline -opt-inline-from` instead." - description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." - note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." - - option: "-opt-inline-from" - schema: - type: "String" - multiple: true - arg: "pattern" - description: "Patterns for classfile names from which to allow inlining, `help` for details." - - option: "-Yopt-inline-heuristics" - schema: - type: "Choice" - arg: "strategy" - default: "default" - choices: - - choice: "at-inline-annotated" - - choice: "everything" - - choice: "default" - description: "Set the heuristics for inlining decisions." - - option: "-opt-warnings" - schema: - type: "Choice" - multiple: true - default: "at-inline-failed" - choices: - - choice: "none" - description: "No optimizer warnings." - - choice: "at-inline-failed-summary" - description: "One-line summary if there were `@inline` method calls that could not be inlined." - - choice: "at-inline-failed" - description: "A detailed warning for each `@inline` method call that could not be inlined." - - choice: "any-inline-failed" - description: "A detailed warning for every callsite that was chosen for inlining by the heuristics, but could not be inlined." - - choice: "no-inline-mixed" - description: "In mixed compilation, warn at callsites methods defined in java sources (the inlining decision cannot be made without bytecode)." - - choice: "no-inline-missing-bytecode" - description: "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath." - - choice: "no-inline-missing-attribute" - description: "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute." - description: "Enable optimizer warnings." - - option: "-Yopt-trace" - schema: - type: "String" - arg: "package/Class.method" - description: "Trace the optimizer progress for methods; `_` to print all, prefix match to select." - - option: "-Yopt-log-inline" - schema: - type: "String" - arg: "package/Class.method" - description: "Print a summary of inliner activity; `_` to print all, prefix match to select." - - option: "-Ystatistics" - schema: - type: "Phases" - arg: "phases" - default: "parser,typer,patmat,erasure,cleanup,jvm" - description: "Print compiler statistics for specific phases. (see [Compilation Phases](#compilation-phases))" - - option: "-Yhot-statistics-enabled" - schema: - type: "Boolean" - description: "Enable `-Ystatistics` to print hot statistics." - - option: "-Yprofile-enabled" - schema: - type: "Boolean" - description: "Enable profiling." - - option: "-Yprofile-destination" - arg: "file" - schema: - type: "String" - description: "where to send profiling output - specify a file, default is to the console." - note: "`-Yprofile-enabled` is enabled at the same time." - - option: "-Yprofile-external-tool" - schema: - type: "Phases" - arg: "phases" - default: "typer" - description: "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase." - note: "`-Yprofile-enabled` is enabled at the same time." - - option: "-Yprofile-run-gc" - schema: - type: "Phases" - arg: "phases" - default: "_" - description: "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or `all`." - note: "`-Yprofile-enabled` is enabled at the same time." + internalOnly: true + schema: + type: "Boolean" + description: "Internal only: expose the empty package." + - option: "-Ydelambdafy" + schema: + type: "Choice" + arg: "strategy" + default: "method" + choices: + - choice: "inline" + - choice: "method" + description: "Strategy used for translating lambdas into JVM code." + - option: "-Ybackend-parallelism" + schema: + type: "Int" + arg: "threads" + default: 1 + min: 1 + max: 16 + description: "Maximum worker threads for backend." + - option: "-Ybackend-worker-queue" + description: "Backend threads worker queue size." + schema: + type: "Int" + arg: "size" + default: 0 + min: 0 + max: 1000 + - option: "-Yjar-compression-level" + schema: + type: "Int" + arg: "level" + default: "Deflater.DEFAULT_COMPRESSION" + min: "Deflater.DEFAULT_COMPRESSION" + max: "Deflater.BEST_COMPRESSION" + description: "Compression level to use when writing jar files." + - option: "-Ycache-plugin-class-loader" + schema: + type: "Choice" + default: "none" + choices: + - choice: "none" + description: "Don't cache class loader." + - choice: "last-modified" + description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." + - option: "-Ycache-macro-class-loader" + schema: + type: "Choice" + default: "none" + choices: + - choice: "none" + description: "Don't cache class loader." + - choice: "last-modified" + description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for macros that are dynamically loaded." + - option: "-opt" + schema: + type: "Choice" + multiple: true + choices: + - choice: "unreachable-code" + description: "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers)." + - choice: "simplify-jumps" + description: "Simplify branching instructions, eliminate unnecessary ones." + - choice: "compact-locals" + description: "Eliminate empty slots in the sequence of local variables." + - choice: "copy-propagation" + description: "Eliminate redundant local variables and unused values (including closures). Enables unreachable-code." + - choice: "redundant-casts" + description: "Eliminate redundant casts using a type propagation analysis." + - choice: "box-unbox" + description: "Eliminate box-unbox pairs within the same method (also tuples, xRefs, value class instances). Enables unreachable-code." + - choice: "nullness-tracking" + description: "Track nullness / non-nullness of local variables and apply optimizations." + - choice: "closure-invocations" + description: "Rewrite closure invocations to the implementation method." + - choice: "inline" + description: "Inline method invocations according to `-Yopt-inline-heuristics` and `-opt-inline-from`." + - choice: "l:none" + description: "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox." + note: "Unlike the other optimizer levels, `l:none` appears up in the `opt.value` set because it's not an expanding option." + - choice: "l:default" + description: "Enable default optimizations: `unreachable-code`." + - choice: "l:method" + description: "Enable intra-method optimizations: `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`." + - choice: "l:inline" + description: "Enable cross-method optimizations (note: inlining requires `-opt-inline-from`): `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`, `inline`." + - choice: "l:project" + description: "Enable cross-method optimizations within the current project." + deprecated: "Use `-opt:l:inline -opt-inline-from` instead." + - choice: "l:classpath" + description: "Enable cross-method optimizations across the entire classpath." + deprecated: "Use `-opt:l:inline -opt-inline-from` instead." + description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." + note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." + - option: "-opt-inline-from" + schema: + type: "String" + multiple: true + arg: "pattern" + description: "Patterns for classfile names from which to allow inlining, `help` for details." + - option: "-Yopt-inline-heuristics" + schema: + type: "Choice" + arg: "strategy" + default: "default" + choices: + - choice: "at-inline-annotated" + - choice: "everything" + - choice: "default" + description: "Set the heuristics for inlining decisions." + - option: "-opt-warnings" + schema: + type: "Choice" + multiple: true + default: "at-inline-failed" + choices: + - choice: "none" + description: "No optimizer warnings." + - choice: "at-inline-failed-summary" + description: "One-line summary if there were `@inline` method calls that could not be inlined." + - choice: "at-inline-failed" + description: "A detailed warning for each `@inline` method call that could not be inlined." + - choice: "any-inline-failed" + description: "A detailed warning for every callsite that was chosen for inlining by the heuristics, but could not be inlined." + - choice: "no-inline-mixed" + description: "In mixed compilation, warn at callsites methods defined in java sources (the inlining decision cannot be made without bytecode)." + - choice: "no-inline-missing-bytecode" + description: "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath." + - choice: "no-inline-missing-attribute" + description: "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute." + description: "Enable optimizer warnings." + - option: "-Yopt-trace" + schema: + type: "String" + arg: "package/Class.method" + description: "Trace the optimizer progress for methods; `_` to print all, prefix match to select." + - option: "-Yopt-log-inline" + schema: + type: "String" + arg: "package/Class.method" + description: "Print a summary of inliner activity; `_` to print all, prefix match to select." + - option: "-Ystatistics" + schema: + type: "Phases" + arg: "phases" + default: "parser,typer,patmat,erasure,cleanup,jvm" + description: "Print compiler statistics for specific phases. (see [Compilation Phases](#compilation-phases))" + - option: "-Yhot-statistics-enabled" + schema: + type: "Boolean" + description: "Enable `-Ystatistics` to print hot statistics." + - option: "-Yprofile-enabled" + schema: + type: "Boolean" + description: "Enable profiling." + - option: "-Yprofile-destination" + arg: "file" + schema: + type: "String" + description: "where to send profiling output - specify a file, default is to the console." + note: "`-Yprofile-enabled` is enabled at the same time." + - option: "-Yprofile-external-tool" + schema: + type: "Phases" + arg: "phases" + default: "typer" + description: "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase." + note: "`-Yprofile-enabled` is enabled at the same time." + - option: "-Yprofile-run-gc" + schema: + type: "Phases" + arg: "phases" + default: "_" + description: "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or `all`." + note: "`-Yprofile-enabled` is enabled at the same time." # Area-specific debug output. - - option: "-Ydoc-debug" - schema: - type: "Boolean" - description: "Trace all scaladoc activity." - - option: "-Yide-debug" - schema: - type: "Boolean" - description: "Generate, validate and output trees using the interactive compiler." - - option: "-Yissue-debug" - schema: - type: "Boolean" - description: "Print stack traces when a context issues an error." - - option: "-Ymacro-debug-lite" - schema: - type: "Boolean" - description: "Trace essential macro-related activities." - - option: "-Ymacro-debug-verbose" - schema: - type: "Boolean" - description: "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions." - - option: "-Ypos-debug" - schema: - type: "Boolean" - description: "Trace position validation." - - option: "-Yreify-debug" - schema: - type: "Boolean" - description: "Trace reification." - - option: "-Ytyper-debug" - schema: - type: "Boolean" - description: "Trace all type assignments." - - option: "-Ypatmat-debug" - schema: - type: "Boolean" - description: "Trace pattern matching translation." - - option: "-Ypatmat-exhaust-depth" - schema: - type: "Int" - arg: "off" - default: 20 - min: 10 - max: Int.MaxValue - description: "off" - - option: "-Yquasiquote-debug" - schema: - type: "Boolean" - description: "Trace quasiquote-related activities." + - option: "-Ydoc-debug" + schema: + type: "Boolean" + description: "Trace all scaladoc activity." + - option: "-Yide-debug" + schema: + type: "Boolean" + description: "Generate, validate and output trees using the interactive compiler." + - option: "-Yissue-debug" + schema: + type: "Boolean" + description: "Print stack traces when a context issues an error." + - option: "-Ymacro-debug-lite" + schema: + type: "Boolean" + description: "Trace essential macro-related activities." + - option: "-Ymacro-debug-verbose" + schema: + type: "Boolean" + description: "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions." + - option: "-Ypos-debug" + schema: + type: "Boolean" + description: "Trace position validation." + - option: "-Yreify-debug" + schema: + type: "Boolean" + description: "Trace reification." + - option: "-Ytyper-debug" + schema: + type: "Boolean" + description: "Trace all type assignments." + - option: "-Ypatmat-debug" + schema: + type: "Boolean" + description: "Trace pattern matching translation." + - option: "-Ypatmat-exhaust-depth" + schema: + type: "Int" + arg: "off" + default: 20 + min: 10 + max: Int.MaxValue + description: "off" + - option: "-Yquasiquote-debug" + schema: + type: "Boolean" + description: "Trace quasiquote-related activities." # Groups of Settings. - - option: "-Xfuture" - schema: - type: "Boolean" - description: "Turn on future language features." - - option: "-Xexperimental" - schema: - type: "Boolean" - description: "Enable experimental extensions in Scala 2.12 and earlier." - deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." - - option : "-Xmacro-settings" - schema: - type: "String" - multiple: true - description: "Custom settings for macros." + - option: "-Xfuture" + schema: + type: "Boolean" + description: "Turn on future language features." + - option: "-Xexperimental" + schema: + type: "Boolean" + description: "Enable experimental extensions in Scala 2.12 and earlier." + deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." + - option : "-Xmacro-settings" + schema: + type: "String" + multiple: true + description: "Custom settings for macros." # * IDE-specific settings - - option: "-Ypresentation-verbose" - schema: - type: "Boolean" - description: "Print information about presentation compiler tasks." - - option: "-Ypresentation-debug" - schema: - type: "Boolean" - description: "Enable debugging output for the presentation compiler." - - option: "-Ypresentation-any-thread" - schema: - type: "Boolean" - description: "Allow use of the presentation compiler from any thread." - - option: "-Ypresentation-strict" - schema: - type: "Boolean" - description: "Do not report type errors in sources with syntax errors." - - option: "-Ypresentation-log" - schema: - type: "String" - arg: "file" - description: "Log presentation compiler events into file." - - option: "-Ypresentation-replay" - schema: - type: "String" - arg: "file" - description: "Replay presentation compiler events from file." - - option: "-Ypresentation-delay" - schema: - type: "Int" - arg: "miliseconds" - default: 0 - min: 0 - max: 999 - description: "Wait number of ms after typing before starting typechecking." + - option: "-Ypresentation-verbose" + schema: + type: "Boolean" + description: "Print information about presentation compiler tasks." + - option: "-Ypresentation-debug" + schema: + type: "Boolean" + description: "Enable debugging output for the presentation compiler." + - option: "-Ypresentation-any-thread" + schema: + type: "Boolean" + description: "Allow use of the presentation compiler from any thread." + - option: "-Ypresentation-strict" + schema: + type: "Boolean" + description: "Do not report type errors in sources with syntax errors." + - option: "-Ypresentation-log" + schema: + type: "String" + arg: "file" + description: "Log presentation compiler events into file." + - option: "-Ypresentation-replay" + schema: + type: "String" + arg: "file" + description: "Replay presentation compiler events from file." + - option: "-Ypresentation-delay" + schema: + type: "Int" + arg: "miliseconds" + default: 0 + min: 0 + max: 999 + description: "Wait number of ms after typing before starting typechecking." - category: "Warning Settings" description: "This section assembles the `-X` and `-Y` options those influence the printing of warnings." options: - - option: "-Xfatal-warnings" - schema: - type: "Boolean" - description: "Fail the compilation if there are any warnings." - - option: "-Ywarn-macros" - schema: - type: "Choice" - arg: "mode" - choices: - - choice: "none" - description: "Do not inspect expansions or their original trees when generating unused symbol warnings." - - choice: "before" - description: "Only inspect unexpanded user-written code for unused symbols." - - choice: "after" - description: "Only inspect expanded trees when generating unused symbol warnings." - - choice: "both" - description: "Inspect both user-written code and expanded trees when generating unused symbol warnings." - description: "Enable lint warnings on macro expansions." - - option: "-Ywarn-dead-code" - schema: - type: "Boolean" - description: "Warn when dead code is identified." - - option: "-Ywarn-value-discard" - schema: - type: "Boolean" - description: "Warn when non-Unit expression results are unused." - note: "To reduce noises for common idiom, warning are suppressed if type of results are `this.type`." - - option: "-Ywarn-numeric-widen" - schema: - type: "Boolean" - description: "Warn when numerics are widened." - - option: "-Ywarn-unused" - schema: - type: "Choice" - multiple: true - arg: "warn" - default: "_" - choices: - - choice: "imports" - description: "Warn if an import selector is not referenced." - - choice: "patvars" - description: "Warn if a variable bound in a pattern is unused." - - choice: "privates" - description: "Warn if a private member is unused." - - choice: "locals" - description: "Warn if a local definition is unused." - - choice: "explicits" - description: "Warn if an explicit parameter is unused." - - choice: "implicits" - description: "Warn if an implicit parameter is unused." - - choice: "params" - description: "Enable `-Ywarn-unused:explicits,implicits`." - - choice: "linted" - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." - note: "Alias is `-Xlint:unused`." - description: "Enable or disable specific `unused` warnings." - - option: "-Ywarn-unused-import" - schema: - type: "Boolean" - description: "Warn when imports are unused." - - option: "-Ywarn-extra-implicit" - schema: - type: "Boolean" - description: "Warn when more than one implicit parameter section is defined." - - option: "-Ywarn-self-implicit" - schema: - type: "Boolean" - description: "Warn when an implicit resolves to an enclosing self-definition." - - option: "-Xlint" - schema: - type: "Choice" - multiple: true - arg: "warn" - default: "_" - choices: - - choice: "adapted-args" - description: "Warn if an argument list is modified to match the receiver." - note: "Alias is `-Ywarn-adapted-args`." - - choice: "nullary-unit" - description: "Warn when nullary methods return Unit." - note: "Alias is `-Ywarn-nullary-unit`." - - choice: "inaccessible" - description: "Warn about inaccessible types in method signatures." - note: "Alias is `-Ywarn-inaccessible`." - - choice: "nullary-override" - description: "Warn when non-nullary `def f()` overrides nullary `def f`." - note: "Alias is `-Ywarn-nullary-override`." - - choice: "infer-any" - description: "Warn when a type argument is inferred to be `Any`." - note: "Alias is `-Ywarn-infer-any`." - - choice: "missing-interpolator" - description: "A string literal appears to be missing an interpolator id." - - choice: "doc-detached" - description: "A Scaladoc comment appears to be detached from its element." - - choice: "private-shadow" - description: "A private field (or class parameter) shadows a superclass field." - - choice: "type-parameter-shadow" - description: "A local type parameter shadows a type already in scope." - - choice: "poly-implicit-overload" - description: "Parameterized overloaded implicit methods are not visible as view bounds." - - choice: "option-implicit" - description: "Option.apply used implicit view." - - choice: "delayedinit-select" - description: "Selecting member of DelayedInit." - - choice: "by-name-right-associative" - description: "By-name parameter of right associative operator." - - choice: "package-object-classes" - description: "Class or object defined in package object." - - choice: "unsound-match" - description: "Pattern match may not be typesafe." - - choice: "stars-align" - description: "Pattern sequence wildcard must align with sequence component." - - choice: "constant" - description: "Evaluation of a constant arithmetic expression results in an error." - - choice: "unused" - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." - description: "Enable or disable specific warnings." - note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." + - option: "-Xfatal-warnings" + schema: + type: "Boolean" + description: "Fail the compilation if there are any warnings." + - option: "-Ywarn-macros" + schema: + type: "Choice" + arg: "mode" + choices: + - choice: "none" + description: "Do not inspect expansions or their original trees when generating unused symbol warnings." + - choice: "before" + description: "Only inspect unexpanded user-written code for unused symbols." + - choice: "after" + description: "Only inspect expanded trees when generating unused symbol warnings." + - choice: "both" + description: "Inspect both user-written code and expanded trees when generating unused symbol warnings." + description: "Enable lint warnings on macro expansions." + - option: "-Ywarn-dead-code" + schema: + type: "Boolean" + description: "Warn when dead code is identified." + - option: "-Ywarn-value-discard" + schema: + type: "Boolean" + description: "Warn when non-Unit expression results are unused." + note: "To reduce noises for common idiom, warning are suppressed if type of results are `this.type`." + - option: "-Ywarn-numeric-widen" + schema: + type: "Boolean" + description: "Warn when numerics are widened." + - option: "-Ywarn-unused" + schema: + type: "Choice" + multiple: true + arg: "warn" + default: "_" + choices: + - choice: "imports" + description: "Warn if an import selector is not referenced." + - choice: "patvars" + description: "Warn if a variable bound in a pattern is unused." + - choice: "privates" + description: "Warn if a private member is unused." + - choice: "locals" + description: "Warn if a local definition is unused." + - choice: "explicits" + description: "Warn if an explicit parameter is unused." + - choice: "implicits" + description: "Warn if an implicit parameter is unused." + - choice: "params" + description: "Enable `-Ywarn-unused:explicits,implicits`." + - choice: "linted" + description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." + note: "Alias is `-Xlint:unused`." + description: "Enable or disable specific `unused` warnings." + - option: "-Ywarn-unused-import" + schema: + type: "Boolean" + description: "Warn when imports are unused." + - option: "-Ywarn-extra-implicit" + schema: + type: "Boolean" + description: "Warn when more than one implicit parameter section is defined." + - option: "-Ywarn-self-implicit" + schema: + type: "Boolean" + description: "Warn when an implicit resolves to an enclosing self-definition." + - option: "-Xlint" + schema: + type: "Choice" + multiple: true + arg: "warn" + default: "_" + choices: + - choice: "adapted-args" + description: "Warn if an argument list is modified to match the receiver." + note: "Alias is `-Ywarn-adapted-args`." + - choice: "nullary-unit" + description: "Warn when nullary methods return Unit." + note: "Alias is `-Ywarn-nullary-unit`." + - choice: "inaccessible" + description: "Warn about inaccessible types in method signatures." + note: "Alias is `-Ywarn-inaccessible`." + - choice: "nullary-override" + description: "Warn when non-nullary `def f()` overrides nullary `def f`." + note: "Alias is `-Ywarn-nullary-override`." + - choice: "infer-any" + description: "Warn when a type argument is inferred to be `Any`." + note: "Alias is `-Ywarn-infer-any`." + - choice: "missing-interpolator" + description: "A string literal appears to be missing an interpolator id." + - choice: "doc-detached" + description: "A Scaladoc comment appears to be detached from its element." + - choice: "private-shadow" + description: "A private field (or class parameter) shadows a superclass field." + - choice: "type-parameter-shadow" + description: "A local type parameter shadows a type already in scope." + - choice: "poly-implicit-overload" + description: "Parameterized overloaded implicit methods are not visible as view bounds." + - choice: "option-implicit" + description: "Option.apply used implicit view." + - choice: "delayedinit-select" + description: "Selecting member of DelayedInit." + - choice: "by-name-right-associative" + description: "By-name parameter of right associative operator." + - choice: "package-object-classes" + description: "Class or object defined in package object." + - choice: "unsound-match" + description: "Pattern match may not be typesafe." + - choice: "stars-align" + description: "Pattern sequence wildcard must align with sequence component." + - choice: "constant" + description: "Evaluation of a constant arithmetic expression results in an error." + - choice: "unused" + description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." + description: "Enable or disable specific warnings." + note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." From 7a30e3b1fcc3dcf103d3604e9ab2b565dd796b77 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 07:03:42 +0900 Subject: [PATCH 0189/3174] Reorder to reduce difference from the generated one --- _data/compiler-options.yml | 145 ++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 74 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 1c01c40fbd..5f1a70a38a 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -1,7 +1,6 @@ - category: "Standard Settings" description: "A set of standard options that are supported on the current development environment and will be supported in future releases." options: -# Path related settings. - option: "-classpath" schema: type: "Path" @@ -9,6 +8,43 @@ description: "Specify where to find user class files." abbreviations: - "-cp" + - option: "-no-specialization" + schema: + type: "Boolean" + description: "Ignore `@specialize` annotations." + - option: "-language" + schema: + type: "Choice" + multiple: true + arg: "feat" + choices: + - choice: "dynamics" + description: "Allow direct or indirect subclasses of `scala.Dynamic`." + - choice: "postfixOps" + description: "Allow postfix operator notation, such as `1 to 10 toList`." + - choice: "reflectiveCalls" + description: "Allow reflective access to members of structural types." + - choice: "implicitConversions" + description: "Allow definition of implicit functions called views." + - choice: "higherKinds" + description: "Allow higher-kinded types." + - choice: "existentials" + description: "Existential types (besides wildcard types) can be written and inferred." + - choice: "experimental.macros" + description: "Allow macro definition (besides implementation and application." + description: "Enable or disable language features." + - option: "-release" + schema: + type: "String" + arg: "release" + description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." + - option: "-optimise" + schema: + type: "Boolean" + description: "Compiler flag for the optimizer in Scala 2.11." + abbreviations: + - "-optimize" + deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." - option: "-bootclasspath" schema: type: "Path" @@ -81,13 +117,6 @@ schema: type: "Boolean" description: "Generate no warnings." - - option: "-optimise" - schema: - type: "Boolean" - description: "Compiler flag for the optimizer in Scala 2.11." - abbreviations: - - "-optimize" - deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." - option: "-print" schema: type: "Boolean" @@ -126,36 +155,6 @@ schema: type: "Boolean" description: "Print product version and exit." - - option: "-no-specialization" - schema: - type: "Boolean" - description: "Ignore `@specialize` annotations." - - option: "-language" - schema: - type: "Choice" - multiple: true - arg: "feat" - choices: - - choice: "dynamics" - description: "Allow direct or indirect subclasses of `scala.Dynamic`." - - choice: "postfixOps" - description: "Allow postfix operator notation, such as `1 to 10 toList`." - - choice: "reflectiveCalls" - description: "Allow reflective access to members of structural types." - - choice: "implicitConversions" - description: "Allow definition of implicit functions called views." - - choice: "higherKinds" - description: "Allow higher-kinded types." - - choice: "existentials" - description: "Existential types (besides wildcard types) can be written and inferred." - - choice: "experimental.macros" - description: "Allow macro definition (besides implementation and application." - description: "Enable or disable language features." - - option: "-release" - schema: - type: "String" - arg: "release" - description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." - category: "JVM Settings" @@ -405,6 +404,20 @@ - choice: "coalescing" description: "Convert PCData to Text and coalesce sibling nodes." description: "Configure XML parsing." + - option: "-Xfuture" + schema: + type: "Boolean" + description: "Turn on future language features." + - option: "-Xexperimental" + schema: + type: "Boolean" + description: "Enable experimental extensions in Scala 2.12 and earlier." + deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." + - option : "-Xmacro-settings" + schema: + type: "String" + multiple: true + description: "Custom settings for macros." @@ -603,6 +616,26 @@ schema: type: "Boolean" description: "Do not cache flat classpath representation of classpath elements from jars across compiler instances." + - option: "-Ycache-plugin-class-loader" + schema: + type: "Choice" + default: "none" + choices: + - choice: "none" + description: "Don't cache class loader." + - choice: "last-modified" + description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." + - option: "-Ycache-macro-class-loader" + schema: + type: "Choice" + default: "none" + choices: + - choice: "none" + description: "Don't cache class loader." + - choice: "last-modified" + description: "Cache class loader, using file last-modified time to invalidate." + description: "Policy for caching class loaders for macros that are dynamically loaded." - option: "-Yvirtpatmat" schema: type: "Boolean" @@ -646,26 +679,6 @@ min: "Deflater.DEFAULT_COMPRESSION" max: "Deflater.BEST_COMPRESSION" description: "Compression level to use when writing jar files." - - option: "-Ycache-plugin-class-loader" - schema: - type: "Choice" - default: "none" - choices: - - choice: "none" - description: "Don't cache class loader." - - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." - - option: "-Ycache-macro-class-loader" - schema: - type: "Choice" - default: "none" - choices: - - choice: "none" - description: "Don't cache class loader." - - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for macros that are dynamically loaded." - option: "-opt" schema: type: "Choice" @@ -836,22 +849,6 @@ schema: type: "Boolean" description: "Trace quasiquote-related activities." -# Groups of Settings. - - option: "-Xfuture" - schema: - type: "Boolean" - description: "Turn on future language features." - - option: "-Xexperimental" - schema: - type: "Boolean" - description: "Enable experimental extensions in Scala 2.12 and earlier." - deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." - - option : "-Xmacro-settings" - schema: - type: "String" - multiple: true - description: "Custom settings for macros." -# * IDE-specific settings - option: "-Ypresentation-verbose" schema: type: "Boolean" From 3f5ea020ea9196fbd04d0d35e7a96c407755b1b7 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 09:07:52 +0900 Subject: [PATCH 0190/3174] Use generated YAML from Scala 2.12.6 --- _data/compiler-options.yml | 279 +++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 150 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 5f1a70a38a..295a38f582 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -5,46 +5,56 @@ schema: type: "Path" arg: "path" + default: "." description: "Specify where to find user class files." abbreviations: - "-cp" + - option: "-d" + schema: + type: "String" + arg: "directory|jar" + default: "." + description: "destination for generated classfiles." - option: "-no-specialization" schema: type: "Boolean" - description: "Ignore `@specialize` annotations." + description: "Ignore @specialize annotations." - option: "-language" schema: type: "Choice" + arg: "feature" multiple: true - arg: "feat" choices: - choice: "dynamics" - description: "Allow direct or indirect subclasses of `scala.Dynamic`." + description: "Allow direct or indirect subclasses of scala.Dynamic" - choice: "postfixOps" - description: "Allow postfix operator notation, such as `1 to 10 toList`." + description: "Allow postfix operator notation, such as `1 to 10 toList`" - choice: "reflectiveCalls" - description: "Allow reflective access to members of structural types." + description: "Allow reflective access to members of structural types" - choice: "implicitConversions" - description: "Allow definition of implicit functions called views." + description: "Allow definition of implicit functions called views" - choice: "higherKinds" - description: "Allow higher-kinded types." + description: "Allow higher-kinded types" - choice: "existentials" - description: "Existential types (besides wildcard types) can be written and inferred." + description: "Existential types (besides wildcard types) can be written and inferred" - choice: "experimental.macros" - description: "Allow macro definition (besides implementation and application." - description: "Enable or disable language features." + description: "Allow macro definition (besides implementation and application)" + description: "Enable or disable language features: `_` for all, `-language:help` to list choices." - option: "-release" schema: type: "String" arg: "release" - description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9." + description: "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9" - option: "-optimise" schema: type: "Boolean" - description: "Compiler flag for the optimizer in Scala 2.11." + description: "Compiler flag for the optimizer in Scala 2.11" abbreviations: - "-optimize" - deprecated: "In 2.12, `-optimise` enables `-opt:l:inline -opt-inline-from:**`. Check `-opt:help` for using the Scala 2.12 optimizer." + - option: "value-overrides" + schema: + type: "Boolean" + description: "Generated value class method overrides an implementation." - option: "-bootclasspath" schema: type: "Path" @@ -56,7 +66,7 @@ type: "Path" arg: "path" default: "Defaults.scalaExtDirs" - description: "Override location of installed extensions." + description: "Override location of installed extensions." - option: "-javabootclasspath" schema: type: "Path" @@ -72,6 +82,7 @@ - option: "-sourcepath" schema: type: "Path" + arg: "path" description: "Specify location(s) of source files." - option: "-dependencyfile" schema: @@ -108,11 +119,11 @@ - choice: "line" - choice: "vars" - choice: "notailcalls" - description: "Set level of generated debugging info." + description: "Set level of generated debugging info. Choices: (none,source,line,vars,notailcalls), default: vars." - option: "-help" schema: type: "Boolean" - description: "Print a synopsis of standard options." + description: "Print a synopsis of standard options" - option: "-nowarn" schema: type: "Boolean" @@ -122,15 +133,16 @@ type: "Boolean" description: "Print program with Scala-specific features removed." - option: "-target" - scheam: + schema: type: "Choice" + arg: "target" default: "jvm-1.8" choices: - choice: "jvm-1.5" - choice: "jvm-1.6" - choice: "jvm-1.7" - choice: "jvm-1.8" - description: "Target platform for object files. All JVM `1.5` - `1.7` targets are deprecated." + description: "Target platform for object files. All JVM 1.5 - 1.7 targets are deprecated. Choices: (jvm-1.5,jvm-1.6,jvm-1.7,jvm-1.8), default: jvm-1.8." - option: "-unchecked" schema: type: "Boolean" @@ -142,7 +154,7 @@ - option: "-usejavacp" schema: type: "Boolean" - description: "Utilize the `java.class.path` in classpath resolution." + description: "Utilize the java.class.path in classpath resolution." - option: "-usemanifestcp" schema: type: "Boolean" @@ -155,36 +167,31 @@ schema: type: "Boolean" description: "Print product version and exit." - - - category: "JVM Settings" description: "Settings influencing the runtime system." options: - option: "-Jflag" schema: type: "Prefix" - description: "Pass `flag` directly to the runtime system." + description: "Pass flag directly to the runtime system." - option: "-Dproperty=value" schema: type: "Prefix" - description: "Pass `-Dproperty=value` directly to the runtime system." + description: "Pass -Dproperty=value directly to the runtime system." - option: "-nobootcp" schema: type: "Boolean" description: "Do not use the boot classpath for the scala jars." - - - category: "Plugin Settings" description: "" options: - option: "-P" schema: - type: "Prefix" - arg: ":plugin:opt" - description: "Pass an option to a plugin in the form of `-P::`." + type: "String" + arg: "plugin:opt" + multiple: true + description: "Pass an option to a plugin" note: "If you use sbt, [compiler plugins support](https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html) may be useful." - - - category: "Advanced Settings" description: "Options that starts with `-X` are maybe renamed or removed in future releases." options: @@ -199,7 +206,7 @@ - option: "-Xdev" schema: type: "Boolean" - description: "Indicates user is a developer - issue warnings about anything which seems amiss." + description: "Indicates user is a developer - issue warnings about anything which seems amiss" - option: "-Xdisable-assertions" schema: type: "Boolean" @@ -207,9 +214,8 @@ - option: "-Xelide-below" schema: type: "Int" - arg: "min" default: "Int.MinValue" - description: "Calls to `@elidable` methods are omitted if method priority is lower than argument." + description: "Calls to @elidable methods are omitted if method priority is lower than argument" - option: "-Xno-forwarders" schema: type: "Boolean" @@ -230,7 +236,7 @@ - option: "-Xlog-reflective-calls" schema: type: "Boolean" - description: "Print a message when a reflective method call is generated." + description: "Print a message when a reflective method call is generated" - option: "-Xlog-free-terms" schema: type: "Boolean" @@ -242,28 +248,25 @@ - option: "-Xmax-classfile-name" schema: type: "Int" - arg: "max" default: 255 min: 72 max: 255 - description: "Maximum filename length for generated classes." + description: "Maximum filename length for generated classes" - option: "-Xmaxerrs" schema: type: "Int" - arg: "max" default: 100 - description: "Maximum errors to print." + description: "Maximum errors to print" - option: "-Xmaxwarns" schema: type: "Int" - arg: "max" default: 100 - description: "Maximum warnings to print." + description: "Maximum warnings to print" - option: "-Xmigration" schema: type: "ScalaVersion" arg: "version" - default: "any" + default: "none" description: "Warn about constructs whose behavior may have changed since version." - option: "-Xno-uescape" schema: @@ -280,14 +283,14 @@ - option: "-Xplugin" schema: type: "String" + arg: "paths" multiple: true - arg: "path" description: "Load a plugin from each classpath." - option: "-Xplugin-disable" schema: type: "String" - multiple: true arg: "plugin" + multiple: true description: "Disable plugins by name." - option: "-Xplugin-list" schema: @@ -296,8 +299,8 @@ - option: "-Xplugin-require" schema: type: "String" - multiple: true arg: "plugin" + multiple: true description: "Abort if a named plugin is not loaded." - option: "-Xpluginsdir" schema: @@ -308,8 +311,7 @@ - option: "-Xprint" schema: type: "Phases" - arg: "phases" - description: "Print out program after PHASES (see [Compilation Phases](#compilation-phases))" + description: "Print out program after phases (see [Compilation Phases](#compilation-phases))" - option: "-Xprint-pos" schema: type: "Boolean" @@ -339,7 +341,7 @@ schema: type: "String" arg: "path" - description: "Class for manifest's Main-Class entry (only useful with `-d `)" + description: "Class for manifest's Main-Class entry (only useful with -d jar)" - option: "-Xshow-class" schema: type: "String" @@ -368,17 +370,17 @@ - option: "-Xstrict-inference" schema: type: "Boolean" - description: "Don't infer known-unsound types." + description: "Don't infer known-unsound types" - option: "-Xsource" schema: - type: "Scala Version" + type: "ScalaVersion" arg: "version" - default: "2.13" + default: "2.12.0" description: "Treat compiler input as Scala source for the specified version, see [scala/bug#8126](https://github.com/scala/bug/issues/8126)." - option: "-Xno-patmat-analysis" schema: type: "Boolean" - description: "Don't perform exhaustivity/unreachability analysis. Also, ignore `@switch` annotation." + description: "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation." - option: "-Xfull-lubs" schema: type: "Boolean" @@ -395,15 +397,16 @@ description: "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods)." - choice: "false" description: "Only generate mixin forwarders required for program correctness." - description: "Generate forwarder methods in classes inhering concrete methods from traits." + description: "Generate forwarder methods in classes inhering concrete methods from traits. Default: `true`, `help` to list choices." - option: "-Xxml" schema: type: "Choice" arg: "property" + multiple: true choices: - choice: "coalescing" - description: "Convert PCData to Text and coalesce sibling nodes." - description: "Configure XML parsing." + description: "Convert PCData to Text and coalesce sibling nodes" + description: "Configure XML parsing.: `_` for all, `-Xxml:help` to list choices." - option: "-Xfuture" schema: type: "Boolean" @@ -413,14 +416,12 @@ type: "Boolean" description: "Enable experimental extensions in Scala 2.12 and earlier." deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." - - option : "-Xmacro-settings" + - option: "-Xmacro-settings" schema: type: "String" + arg: "option" multiple: true description: "Custom settings for macros." - - - - category: "Private Settings" description: | Options with `-Y` prefix are more experimental and unstable than those with `-X` prefix. @@ -444,22 +445,19 @@ - option: "-Ybreak-cycles" schema: type: "Boolean" - description: "Attempt to break cycles encountered during typing." + description: "Attempt to break cycles encountered during typing" - option: "-Ybrowse" schema: type: "Phases" - arg: "phases" - description: "Browse the abstract syntax tree after PHASES (see [Compilation Phases](#compilation-phases))" + description: "Browse the abstract syntax tree after phases (see [Compilation Phases](#compilation-phases))" - option: "-Ycheck" schema: type: "Phases" - arg: "phases" description: "Check the tree at the end of PHASES (see [Compilation Phases](#compilation-phases))" - option: "-Yshow" schema: type: "Phases" - arg: "phases" - description: "(Requires `-Xshow-class` or `-Xshow-object`) Show after PHASES (see [Compilation Phases](#compilation-phases))" + description: "(Requires -Xshow-class or -Xshow-object) Show after PHASES (see [Compilation Phases](#compilation-phases))" - option: "-Ycompact-trees" schema: type: "Boolean" @@ -481,12 +479,11 @@ - choice: "package" - choice: "object" - choice: "error" - description: "Resolve term conflicts." + description: "Resolve term conflicts. Choices: (package,object,error), default: error." - option: "-Ylog" schema: type: "Phases" - arg: "phases" - description: "Log operations during PHASES (see [Compilation Phases](#compilation-phases))" + description: "Log operations during phases" - option: "-Ylog-classpath" schema: type: "Boolean" @@ -510,23 +507,22 @@ - option: "-Yrecursion" schema: type: "Int" - arg: "depth" default: 0 min: 0 - max: Int.MaxValue + max: 2147483647 description: "Set recursion depth used when locking symbols." - option: "-Yshow-trees" schema: type: "Boolean" - description: "(Requires `-Xprint:`) Print detailed ASTs in formatted form." + description: "(Requires -Xprint:) Print detailed ASTs in formatted form." - option: "-Yshow-trees-compact" schema: type: "Boolean" - description: "(Requires `-Xprint:`) Print detailed ASTs in compact form." + description: "(Requires -Xprint:) Print detailed ASTs in compact form." - option: "-Yshow-trees-stringified" schema: type: "Boolean" - description: "(Requires `-Xprint:`) Print stringifications along with detailed ASTs." + description: "(Requires -Xprint:) Print stringifications along with detailed ASTs." - option: "-Yshow-syms" schema: type: "Boolean" @@ -542,8 +538,7 @@ - option: "-Yskip" schema: type: "Phases" - arg: "phases" - description: "Skip PHASES (see [Compilation Phases](#compilation-phases))" + description: "Skip phases (see [Compilation Phases](#compilation-phases))" - option: "-Ygen-asmp" schema: type: "String" @@ -557,14 +552,12 @@ - option: "-Ystop-after" schema: type: "Phases" - arg: "phases" description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" abbreviations: - "-stop" - option: "-Ystop-before" schema: type: "Phases" - arg: "phases" description: "Stop before PHASES (see [Compilation Phases](#compilation-phases))" - option: "-Yrangepos" schema: @@ -573,8 +566,8 @@ - option: "-Yshow-member-pos" schema: type: "String" - arg: "style" - description: "Show start and end positions of members." + arg: "output style" + description: "Show start and end positions of members" note: "`-Yrangepos` is enabled at the same time." - option: "-Yreify-copypaste" schema: @@ -586,10 +579,10 @@ arg: "policy" default: "normal" choices: - - choice: "none" - choice: "normal" + - choice: "none" - choice: "discard" - description: "Control expansion of macros, useful for scaladoc and presentation compiler." + description: "Control expansion of macros, useful for scaladoc and presentation compiler. Choices: (normal,none,discard), default: normal." - option: "-Ymacro-no-expand" schema: type: "Boolean" @@ -598,11 +591,11 @@ - option: "-Yrepl-sync" schema: type: "Boolean" - description: "Do not use asynchronous code for REPL startup." + description: "Do not use asynchronous code for repl startup" - option: "-Yrepl-class-based" schema: type: "Boolean" - description: "Use classes to wrap REPL snippets instead of objects." + description: "Use classes to wrap REPL snippets instead of objects" - option: "-Yrepl-outdir" schema: type: "String" @@ -619,30 +612,34 @@ - option: "-Ycache-plugin-class-loader" schema: type: "Choice" + arg: "policy" default: "none" choices: - choice: "none" - description: "Don't cache class loader." + description: "Don't cache class loader" - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for compiler plugins that are dynamically loaded." + description: "Cache class loader, using file last-modified time to invalidate" + description: "Policy for caching class loaders for compiler plugins that are dynamically loaded. Default: `none`, `help` to list choices." - option: "-Ycache-macro-class-loader" schema: type: "Choice" + arg: "policy" default: "none" choices: - choice: "none" - description: "Don't cache class loader." + description: "Don't cache class loader" - choice: "last-modified" - description: "Cache class loader, using file last-modified time to invalidate." - description: "Policy for caching class loaders for macros that are dynamically loaded." + description: "Cache class loader, using file last-modified time to invalidate" + description: "Policy for caching class loaders for macros that are dynamically loaded. Default: `none`, `help` to list choices." + - option: "-Ypartial-unification" + schema: + type: "Boolean" + description: "Enable partial unification in type constructor inference" - option: "-Yvirtpatmat" schema: type: "Boolean" - description: "Enable pattern matcher virtualization." + description: "Enable pattern matcher virtualization" - option: "-Yexpose-empty-package" -# TODO: internal only - internalOnly: true schema: type: "Boolean" description: "Internal only: expose the empty package." @@ -654,34 +651,32 @@ choices: - choice: "inline" - choice: "method" - description: "Strategy used for translating lambdas into JVM code." + description: "Strategy used for translating lambdas into JVM code. Choices: (inline,method), default: method." - option: "-Ybackend-parallelism" schema: type: "Int" - arg: "threads" default: 1 min: 1 max: 16 - description: "Maximum worker threads for backend." + description: "maximum worker threads for backend" - option: "-Ybackend-worker-queue" - description: "Backend threads worker queue size." schema: type: "Int" - arg: "size" default: 0 min: 0 max: 1000 + description: "backend threads worker queue size" - option: "-Yjar-compression-level" schema: type: "Int" - arg: "level" - default: "Deflater.DEFAULT_COMPRESSION" - min: "Deflater.DEFAULT_COMPRESSION" - max: "Deflater.BEST_COMPRESSION" - description: "Compression level to use when writing jar files." + default: -1 + min: -1 + max: 9 + description: "compression level to use when writing jar files" - option: "-opt" schema: type: "Choice" + arg: "optimization" multiple: true choices: - choice: "unreachable-code" @@ -689,7 +684,7 @@ - choice: "simplify-jumps" description: "Simplify branching instructions, eliminate unnecessary ones." - choice: "compact-locals" - description: "Eliminate empty slots in the sequence of local variables." + description: "Eliminate empty slots in the sequence of local variables." - choice: "copy-propagation" description: "Eliminate redundant local variables and unused values (including closures). Enables unreachable-code." - choice: "redundant-casts" @@ -701,29 +696,28 @@ - choice: "closure-invocations" description: "Rewrite closure invocations to the implementation method." - choice: "inline" - description: "Inline method invocations according to `-Yopt-inline-heuristics` and `-opt-inline-from`." + description: "Inline method invocations according to -Yopt-inline-heuristics and -opt-inline-from." - choice: "l:none" - description: "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox." - note: "Unlike the other optimizer levels, `l:none` appears up in the `opt.value` set because it's not an expanding option." + description: "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don`t enable box-unbox." - choice: "l:default" - description: "Enable default optimizations: `unreachable-code`." + description: "Enable default optimizations: unreachable-code." - choice: "l:method" - description: "Enable intra-method optimizations: `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`." + description: "Enable intra-method optimizations: unreachable-code,simplify-jumps,compact-locals,copy-propagation,redundant-casts,box-unbox,nullness-tracking,closure-invocations." - choice: "l:inline" - description: "Enable cross-method optimizations (note: inlining requires `-opt-inline-from`): `unreachable-code`, `simplify-jumps`, `compact-locals`, `copy-propagation`, `redundant-casts`, `box-unbox`, `nullness-tracking`, `closure-invocations`, `inline`." + description: "Enable cross-method optimizations (note: inlining requires -opt-inline-from): l:method,inline." - choice: "l:project" - description: "Enable cross-method optimizations within the current project." + description: "[deprecated, use -opt:l:inline, -opt-inline-from] Enable cross-method optimizations within the current project." deprecated: "Use `-opt:l:inline -opt-inline-from` instead." - choice: "l:classpath" - description: "Enable cross-method optimizations across the entire classpath." + description: "[deprecated, use -opt:l:inline, -opt-inline-from] Enable cross-method optimizations across the entire classpath." deprecated: "Use `-opt:l:inline -opt-inline-from` instead." - description: "Enable optimizations. Check `-opt:help` for using the Scala 2.12 optimizer." + description: "Enable optimizations: `_` for all, `-opt:help` to list choices." note: "if `inline` not contained and either `l:project` or `l:classpath` are contained, then `l:inline` is enabled." - option: "-opt-inline-from" schema: type: "String" + arg: "patterns" multiple: true - arg: "pattern" description: "Patterns for classfile names from which to allow inlining, `help` for details." - option: "-Yopt-inline-heuristics" schema: @@ -734,19 +728,19 @@ - choice: "at-inline-annotated" - choice: "everything" - choice: "default" - description: "Set the heuristics for inlining decisions." + description: "Set the heuristics for inlining decisions. Choices: (at-inline-annotated,everything,default), default: default." - option: "-opt-warnings" schema: type: "Choice" + arg: "warning" multiple: true - default: "at-inline-failed" choices: - choice: "none" description: "No optimizer warnings." - choice: "at-inline-failed-summary" - description: "One-line summary if there were `@inline` method calls that could not be inlined." + description: "One-line summary if there were @inline method calls that could not be inlined." - choice: "at-inline-failed" - description: "A detailed warning for each `@inline` method call that could not be inlined." + description: "A detailed warning for each @inline method call that could not be inlined." - choice: "any-inline-failed" description: "A detailed warning for every callsite that was chosen for inlining by the heuristics, but could not be inlined." - choice: "no-inline-mixed" @@ -755,7 +749,7 @@ description: "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath." - choice: "no-inline-missing-attribute" description: "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute." - description: "Enable optimizer warnings." + description: "Enable optimizer warnings: `_` for all, `-opt-warnings:help` to list choices." - option: "-Yopt-trace" schema: type: "String" @@ -769,9 +763,8 @@ - option: "-Ystatistics" schema: type: "Phases" - arg: "phases" default: "parser,typer,patmat,erasure,cleanup,jvm" - description: "Print compiler statistics for specific phases. (see [Compilation Phases](#compilation-phases))" + description: "Print compiler statistics for specific phases phases (default: parser,typer,patmat,erasure,cleanup,jvm) (see [Compilation Phases](#compilation-phases))" - option: "-Yhot-statistics-enabled" schema: type: "Boolean" @@ -781,26 +774,23 @@ type: "Boolean" description: "Enable profiling." - option: "-Yprofile-destination" - arg: "file" schema: type: "String" + arg: "file" description: "where to send profiling output - specify a file, default is to the console." note: "`-Yprofile-enabled` is enabled at the same time." - option: "-Yprofile-external-tool" schema: type: "Phases" - arg: "phases" default: "typer" - description: "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase." + description: "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase phases (default: typer)" note: "`-Yprofile-enabled` is enabled at the same time." - option: "-Yprofile-run-gc" schema: type: "Phases" - arg: "phases" default: "_" - description: "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or `all`." + description: "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or all phases (default: _)" note: "`-Yprofile-enabled` is enabled at the same time." -# Area-specific debug output. - option: "-Ydoc-debug" schema: type: "Boolean" @@ -840,10 +830,9 @@ - option: "-Ypatmat-exhaust-depth" schema: type: "Int" - arg: "off" default: 20 min: 10 - max: Int.MaxValue + max: 2147483647 description: "off" - option: "-Yquasiquote-debug" schema: @@ -860,7 +849,7 @@ - option: "-Ypresentation-any-thread" schema: type: "Boolean" - description: "Allow use of the presentation compiler from any thread." + description: "Allow use of the presentation compiler from any thread" - option: "-Ypresentation-strict" schema: type: "Boolean" @@ -869,23 +858,19 @@ schema: type: "String" arg: "file" - description: "Log presentation compiler events into file." + description: "Log presentation compiler events into file" - option: "-Ypresentation-replay" schema: type: "String" arg: "file" - description: "Replay presentation compiler events from file." + description: "Replay presentation compiler events from file" - option: "-Ypresentation-delay" schema: type: "Int" - arg: "miliseconds" default: 0 min: 0 max: 999 - description: "Wait number of ms after typing before starting typechecking." - - - + description: "Wait number of ms after typing before starting typechecking" - category: "Warning Settings" description: "This section assembles the `-X` and `-Y` options those influence the printing of warnings." options: @@ -897,6 +882,7 @@ schema: type: "Choice" arg: "mode" + default: "before" choices: - choice: "none" description: "Do not inspect expansions or their original trees when generating unused symbol warnings." @@ -906,7 +892,7 @@ description: "Only inspect expanded trees when generating unused symbol warnings." - choice: "both" description: "Inspect both user-written code and expanded trees when generating unused symbol warnings." - description: "Enable lint warnings on macro expansions." + description: "Enable lint warnings on macro expansions. Default: `before`, `help` to list choices." - option: "-Ywarn-dead-code" schema: type: "Boolean" @@ -923,9 +909,8 @@ - option: "-Ywarn-unused" schema: type: "Choice" + arg: "warning" multiple: true - arg: "warn" - default: "_" choices: - choice: "imports" description: "Warn if an import selector is not referenced." @@ -940,15 +925,10 @@ - choice: "implicits" description: "Warn if an implicit parameter is unused." - choice: "params" - description: "Enable `-Ywarn-unused:explicits,implicits`." + description: "Enable -Ywarn-unused:explicits,implicits." - choice: "linted" - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." - note: "Alias is `-Xlint:unused`." - description: "Enable or disable specific `unused` warnings." - - option: "-Ywarn-unused-import" - schema: - type: "Boolean" - description: "Warn when imports are unused." + description: "-Xlint:unused." + description: "Enable or disable specific `unused` warnings: `_` for all, `-Ywarn-unused:help` to list choices." - option: "-Ywarn-extra-implicit" schema: type: "Boolean" @@ -960,9 +940,8 @@ - option: "-Xlint" schema: type: "Choice" + arg: "warning" multiple: true - arg: "warn" - default: "_" choices: - choice: "adapted-args" description: "Warn if an argument list is modified to match the receiver." @@ -1004,6 +983,6 @@ - choice: "constant" description: "Evaluation of a constant arithmetic expression results in an error." - choice: "unused" - description: "Enable `-Ywarn-unused:imports,privates,locals,implicits`." - description: "Enable or disable specific warnings." + description: "Enable -Ywarn-unused:imports,privates,locals,implicits." + description: "Enable or disable specific warnings: `_` for all, `-Xlint:help` to list choices." note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." From f4062b832026ed1920354b24f2b8025a9fe9409e Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 12:48:53 +0900 Subject: [PATCH 0191/3174] Fix typo --- _data/compiler-options.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 295a38f582..497f0b4c75 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -428,7 +428,7 @@ Those influencing to language semantics are likely to be deprecated in Scala 2.13 (see [scala/scala-dev#430](https://github.com/scala/scala-dev/issues/430)). - Some optimization-related options, e.g. `-opt:**` and `-opt-inline-form` are included in this section, since **REASON_HERE**. + Some optimization-related options, e.g. `-opt:**` and `-opt-inline-from` are included in this section, since **REASON_HERE**. options: - option: "-Y" schema: From c79b55a633017d7b5fe3e818b7a527a6bd4527f6 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 13:04:18 +0900 Subject: [PATCH 0192/3174] Add reason why `-opt` and `-opt-inline-from` are part of private settings. --- _data/compiler-options.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 497f0b4c75..2f91d99764 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -426,9 +426,9 @@ description: | Options with `-Y` prefix are more experimental and unstable than those with `-X` prefix. - Those influencing to language semantics are likely to be deprecated in Scala 2.13 (see [scala/scala-dev#430](https://github.com/scala/scala-dev/issues/430)). + Some without `-Y` prefix (e.g. `-opt:**` and `-opt-inline-from`) are also included, since such granular optimization-related options are changeable. - Some optimization-related options, e.g. `-opt:**` and `-opt-inline-from` are included in this section, since **REASON_HERE**. + Those influencing to language semantics are likely to be deprecated in Scala 2.13 (see [scala/scala-dev#430](https://github.com/scala/scala-dev/issues/430)). options: - option: "-Y" schema: From b79e0d436361606cd6a04fe7a03fbe72103c4605 Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 18:43:59 +0900 Subject: [PATCH 0193/3174] Move additional information to `note` so it does not conflict the description extracted from source. --- _data/compiler-options.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 2f91d99764..6805c00599 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -311,7 +311,8 @@ - option: "-Xprint" schema: type: "Phases" - description: "Print out program after phases (see [Compilation Phases](#compilation-phases))" + description: "Print out program after phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Xprint-pos" schema: type: "Boolean" @@ -414,8 +415,8 @@ - option: "-Xexperimental" schema: type: "Boolean" - description: "Enable experimental extensions in Scala 2.12 and earlier." - deprecated: "In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." + description: "Enable experimental extensions." + deprecated: "For in Scala 2.12 and earlier. In 2.13 all options previously enabled by `-Xexperimental` are enabled by default or removed." - option: "-Xmacro-settings" schema: type: "String" @@ -449,15 +450,18 @@ - option: "-Ybrowse" schema: type: "Phases" - description: "Browse the abstract syntax tree after phases (see [Compilation Phases](#compilation-phases))" + description: "Browse the abstract syntax tree after phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Ycheck" schema: type: "Phases" - description: "Check the tree at the end of PHASES (see [Compilation Phases](#compilation-phases))" + description: "Check the tree at the end of phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Yshow" schema: type: "Phases" - description: "(Requires -Xshow-class or -Xshow-object) Show after PHASES (see [Compilation Phases](#compilation-phases))" + description: "(Requires -Xshow-class or -Xshow-object) Show after phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Ycompact-trees" schema: type: "Boolean" @@ -538,7 +542,8 @@ - option: "-Yskip" schema: type: "Phases" - description: "Skip phases (see [Compilation Phases](#compilation-phases))" + description: "Skip phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Ygen-asmp" schema: type: "String" @@ -552,13 +557,15 @@ - option: "-Ystop-after" schema: type: "Phases" - description: "Stop after PHASES (see [Compilation Phases](#compilation-phases))" + description: "Stop after phases" + note: "See [Compilation Phases](#compilation-phases)" abbreviations: - "-stop" - option: "-Ystop-before" schema: type: "Phases" - description: "Stop before PHASES (see [Compilation Phases](#compilation-phases))" + description: "Stop before phases" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Yrangepos" schema: type: "Boolean" @@ -764,7 +771,8 @@ schema: type: "Phases" default: "parser,typer,patmat,erasure,cleanup,jvm" - description: "Print compiler statistics for specific phases phases (default: parser,typer,patmat,erasure,cleanup,jvm) (see [Compilation Phases](#compilation-phases))" + description: "Print compiler statistics for specific phases phases (default: parser,typer,patmat,erasure,cleanup,jvm)" + note: "See [Compilation Phases](#compilation-phases)" - option: "-Yhot-statistics-enabled" schema: type: "Boolean" From 6346423e38df303284f665a2731ad94d6fa37c0b Mon Sep 17 00:00:00 2001 From: exoego Date: Thu, 3 May 2018 19:33:46 +0900 Subject: [PATCH 0194/3174] Separate IDE specific settings that most developer do not need to care. --- _data/compiler-options.yml | 69 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/_data/compiler-options.yml b/_data/compiler-options.yml index 6805c00599..c50ae356b8 100644 --- a/_data/compiler-options.yml +++ b/_data/compiler-options.yml @@ -846,39 +846,6 @@ schema: type: "Boolean" description: "Trace quasiquote-related activities." - - option: "-Ypresentation-verbose" - schema: - type: "Boolean" - description: "Print information about presentation compiler tasks." - - option: "-Ypresentation-debug" - schema: - type: "Boolean" - description: "Enable debugging output for the presentation compiler." - - option: "-Ypresentation-any-thread" - schema: - type: "Boolean" - description: "Allow use of the presentation compiler from any thread" - - option: "-Ypresentation-strict" - schema: - type: "Boolean" - description: "Do not report type errors in sources with syntax errors." - - option: "-Ypresentation-log" - schema: - type: "String" - arg: "file" - description: "Log presentation compiler events into file" - - option: "-Ypresentation-replay" - schema: - type: "String" - arg: "file" - description: "Replay presentation compiler events from file" - - option: "-Ypresentation-delay" - schema: - type: "Int" - default: 0 - min: 0 - max: 999 - description: "Wait number of ms after typing before starting typechecking" - category: "Warning Settings" description: "This section assembles the `-X` and `-Y` options those influence the printing of warnings." options: @@ -994,3 +961,39 @@ description: "Enable -Ywarn-unused:imports,privates,locals,implicits." description: "Enable or disable specific warnings: `_` for all, `-Xlint:help` to list choices." note: "If this options contains `unused`, it enables `-Ywarn-unused:linted`. Otherwise it disables `-Ywarn-unused:linted`." +- category: "IDE Specific Settings" + description: "" + options: + - option: "-Ypresentation-verbose" + schema: + type: "Boolean" + description: "Print information about presentation compiler tasks." + - option: "-Ypresentation-debug" + schema: + type: "Boolean" + description: "Enable debugging output for the presentation compiler." + - option: "-Ypresentation-any-thread" + schema: + type: "Boolean" + description: "Allow use of the presentation compiler from any thread" + - option: "-Ypresentation-strict" + schema: + type: "Boolean" + description: "Do not report type errors in sources with syntax errors." + - option: "-Ypresentation-log" + schema: + type: "String" + arg: "file" + description: "Log presentation compiler events into file" + - option: "-Ypresentation-replay" + schema: + type: "String" + arg: "file" + description: "Replay presentation compiler events from file" + - option: "-Ypresentation-delay" + schema: + type: "Int" + default: 0 + min: 0 + max: 999 + description: "Wait number of ms after typing before starting typechecking" From 6f26b06721a2e886a772d6a6331dbd610e6f5a70 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 4 May 2018 10:19:16 -0700 Subject: [PATCH 0195/3174] FAQ rejiggered for implicit scope --- _overviews/FAQ/finding-implicits.md | 194 ++++++++++++++++++++-------- 1 file changed, 141 insertions(+), 53 deletions(-) diff --git a/_overviews/FAQ/finding-implicits.md b/_overviews/FAQ/finding-implicits.md index f10847c167..c12d7b2748 100644 --- a/_overviews/FAQ/finding-implicits.md +++ b/_overviews/FAQ/finding-implicits.md @@ -131,64 +131,116 @@ it implicitly to `sorted`. ## Where do Implicits Come From? -When the compiler sees the need for an implicit, either because you are calling -a method which does not exist on the object's class, or because you are calling -a method that requires an implicit parameter, it will search for an implicit -that will fit the need. - -This search obeys certain rules that define which implicits are visible and -which are not. The following table showing where the compiler will search for -implicits was taken from an excellent [presentation][1] about implicits by Josh -Suereth, which is heartily recommend to anyone wanting to improve their Scala -knowledge. It has been complemented since then with feedback and updates. - -The implicits available under number 1 below have precedence over the ones under -number 2. Other than that, if there are several eligible arguments which match -the implicit parameter’s type, a most specific one will be chosen using the rules -of static overloading resolution (see [Scala Specification][5] §6.26.4). - -1. First look in current scope - * Implicits defined in current scope - * Explicit imports - * wildcard imports - * Same scope in other files -2. Now look at associated types in - * Companion objects of a type - * Implicit scope of an argument's type **(2.9.1)** - * Implicit scope of type arguments **(2.8.0)** - * Outer objects for nested types - -Let's give examples for them. - -### Implicits Defined in Current Scope +As described above, there are several contexts in which an implicit value may be required +for an expression to typecheck. The required implicit type is what determines +which value is selected. That value is found either in lexical scope or, +failing that, in what is called implicit scope. - implicit val n: Int = 5 - def add(x: Int)(implicit y: Int) = x + y - add(5) // takes n from the current scope, res: Int = 10 +### Implicits Defined in Lexical Scope -### Explicit Imports +When a value of a certain name is required, lexical scope is searched for +a value with that name. Similarly, when an implicit value of a certain type is required, +lexical scope is searched for a value with that type. - import scala.collection.JavaConversions.mapAsScalaMap - def env = System.getenv() // Java map - val term = env("TERM") // implicit conversion from Java Map to Scala Map +Any such value which can be referenced with its "simple" name, without +selecting from another value using dotted syntax, is an eligible implicit value. -### Wildcard Imports +For example, here is a function that takes an implicit scaling factor. +The function requires a parameter of type `Int`, and there is a value +of that type in scope. The variable name `n` does not matter in this +case. - def sum[T : Integral](list: List[T]): T = { - val integral = implicitly[Integral[T]] - import integral._ // get the implicits in question into scope - list.foldLeft(integral.zero)(_ + _) + implicit val n: Int = 5 + def scale(x: Int)(implicit y: Int) = x * y + scale(5) // takes n from the current scope, with the result 25 + +The invocation can be rewritten `scale(5)(n)`. If `n` can be referenced +using its simple name, as shown here, it is eligible as an implicit value. + +An implicit value can be introduced into scope by an import statement: + + import scala.collection.JavaConverters._ + def env = System.getenv().asScala // extension method enabled by imported implicit + val term = env("TERM") // it's a Scala Map + +There may be more than one such value because they have different names. + +In that case, overload resolution is used to pick one of them. The algorithm +for overload resolution is the same used to choose the reference for a +given name, when more than one term in scope has that name. For example, +`println` is overloaded, and each overload takes a different parameter type. +An invocation of `println` requires selecting the correct overloaded method. + +In implicit search, overload resolution chooses a value among more than one +that have the same required type. Usually this entails selecting a narrower +type or a value defined in a subclass relative to other eligible values. + +The rule that the value must be accessible using its simple name means +that the normal rules for name binding apply. + +In summary, a definition for `x` shadows a definition in +an enclosing scope. But a binding for `x` can also be introduced by +local imports. Imported symbols can't override definitions of the same +name in an enclosing scope. Similarly, wildcard imports can't override +an import of a specific name, and names in the current package that are +visible from other source files can't override imports or local definitions. + +These are the normal rules for deciding what `x` means in a given context, +and also determine which value `x` is accessible by its simple name and +is eligible as an implicit. + +This means that an implicit in scope can be disabled by shadowing it with +a term of the same name. + +For example, here, `X.f` is supplied the imported `X.s`: `X.f(s)`. +The body of `f` uses an implicit `Int`, from the immediate scope, +which shadows the `n` from `Y`, which is therefore not an eligible +implicit value. The parameter `s` shadows the member `s`. + +The method `g` does not compile because the implicit `t` is shadowed +by a `t` that is not implicit, so no implicit `T` is in scope. + + object Y { + implicit val n: Int = 17 + trait T { + implicit val i: Int = 17 + implicit def t: T = ??? + } + object X extends T { + implicit val n: Int = 42 + implicit val s: String = "hello, world\n" + def f(implicit s: String) = implicitly[String] * implicitly[Int] + override def t: T = ??? + def g = implicitly[T] + } } + import Y.X._ + f + +The invocation of `f` was enabled by importing from `Y.X.`. But it is +not convenient to require an import to access implicit values +providied by a package. -### Same Scope in Other Files +If an implicit value is not found in lexical scope, implicit search +continues in implicit scope. -**Edit**: It seems this does not have a different precedence. If you have some -example that demonstrates a precedence distinction, please make a comment. -Otherwise, don't rely on this one. +### Implicits Defined in Implicit Scope -This is like the first example, but assuming the implicit definition is in a -different file than its usage. See also how [package objects][2] might be used -in to bring in implicits. +Implicit syntax can avoid the [import tax][1], which of course is a "sin tax," +by leveraging "implicit scope", which depends on the type of the implicit +instead of imports in lexical scope. + +When an implicit of type `T` is required, implicit scope includes +the companion object `T`: + + trait T + object T { implicit val t: T = new T { } } + +When an `F[T]` is required, implicit scope includes both the companion +of `F` and the companion of the type argument, e.g., `object C` for `F[C]`. + +In addition, implicit scope includes the companions of the base classes +of `F` and `C`, including package objects, such as `p` for `p.F`. ### Companion Objects of a Type @@ -254,8 +306,6 @@ conversions of that parameter alone, but of the whole expression. For example: // because it is converted into this: A.fromInt(1) + new A(1) -**This available only since Scala 2.9.1.** - ### Implicit scope of type arguments This is required to make the type class pattern really work. Consider @@ -290,8 +340,6 @@ parameter. The implicit looked for above is `Ordering[A]`, where `A` is an actual type, not type parameter: it is a _type argument_ to `Ordering`. See section 7.2 of the [Scala Specification][6]. -**This available only since Scala 2.8.0.** - ### Outer Objects for Nested Types The principle is simple: @@ -308,6 +356,46 @@ The principle is simple: A real world example of this would be welcome. Please share your example! +### Package Objects Can Contribute Implicit Values + +An implicit value in a package object can be made available either +in lexical scope or in implicit scope. + +To be available in lexical scope, the packages must be declared as nested packages: + + package object p { implicit val s: String = "hello, world" } + package p { + package q { + object X { def f = implicitly[String] } + } + } + +This is sensitive to name binding rules. The following example compiles +only if the package object is in a separate file, in which case the import is used: + + package object p { implicit val s: String = "hello, world" } + package p { + package q { + object Y { + implicit val s: String = "bye" + } + object X { + import Y._ + def f = implicitly[String] + } + } + } + +A package object can also offer implicit values of types in subpackages: + + package object p { implicit val c: q.C = new q.C } + package p.q { + class C + object X { def f = implicitly[C] } + } + +Here, the implicit is supplied in implicit scope of `C`. + ### Call To Action Avoid taking this question as being the final arbiter of what is happening. From 9faa3cfe46350123f35dfc406b9fe7e2940bc61d Mon Sep 17 00:00:00 2001 From: Harrison Houghton <28076058+hrhino@users.noreply.github.com> Date: Tue, 8 May 2018 09:35:25 -0400 Subject: [PATCH 0196/3174] reference 2.12.6 in the API docs page --- api/all.md | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/api/all.md b/api/all.md index 305e4c602b..2d629fc943 100644 --- a/api/all.md +++ b/api/all.md @@ -5,14 +5,14 @@ includeTOC: true --- ## Latest releases -* Scala 2.12.4 - * [Library API](http://www.scala-lang.org/api/2.12.4/) - * [Compiler API](http://www.scala-lang.org/api/2.12.4/scala-compiler/scala/) - * [Reflection API](http://www.scala-lang.org/api/2.12.4/scala-reflect/scala/reflect/) - * Scala Modules - * [XML API](http://www.scala-lang.org/api/2.12.4/scala-xml/scala/xml/) - * [Parser Combinators API](http://www.scala-lang.org/api/2.12.4/scala-parser-combinators/scala/util/parsing/) - * [Swing API](http://www.scala-lang.org/api/2.12.4/scala-swing/scala/swing/) +* Scala 2.12.6 + * [Library API](http://www.scala-lang.org/api/2.12.6/) + * [Compiler API](http://www.scala-lang.org/api/2.12.6/scala-compiler/scala/) + * [Reflection API](http://www.scala-lang.org/api/2.12.6/scala-reflect/scala/reflect/) + * Scala Modules + * [XML API](http://www.scala-lang.org/api/2.12.6/scala-xml/scala/xml/) + * [Parser Combinators API](http://www.scala-lang.org/api/2.12.6/scala-parser-combinators/scala/util/parsing/) + * [Swing API](http://www.scala-lang.org/api/2.12.6/scala-swing/scala/swing/) * Scala 2.11.12 * [Library API](http://www.scala-lang.org/api/2.11.12/) * [Compiler API](http://www.scala-lang.org/api/2.11.12/scala-compiler/) @@ -36,6 +36,22 @@ includeTOC: true ## Previous releases +* Scala 2.12.5 + * [Library API](http://www.scala-lang.org/api/2.12.5/) + * [Compiler API](http://www.scala-lang.org/api/2.12.5/scala-compiler/scala/) + * [Reflection API](http://www.scala-lang.org/api/2.12.5/scala-reflect/scala/reflect/) + * Scala Modules + * [XML API](http://www.scala-lang.org/api/2.12.5/scala-xml/scala/xml/) + * [Parser Combinators API](http://www.scala-lang.org/api/2.12.5/scala-parser-combinators/scala/util/parsing/) + * [Swing API](http://www.scala-lang.org/api/2.12.5/scala-swing/scala/swing/) +* Scala 2.12.4 + * [Library API](http://www.scala-lang.org/api/2.12.4/) + * [Compiler API](http://www.scala-lang.org/api/2.12.4/scala-compiler/scala/) + * [Reflection API](http://www.scala-lang.org/api/2.12.4/scala-reflect/scala/reflect/) + * Scala Modules + * [XML API](http://www.scala-lang.org/api/2.12.4/scala-xml/scala/xml/) + * [Parser Combinators API](http://www.scala-lang.org/api/2.12.4/scala-parser-combinators/scala/util/parsing/) + * [Swing API](http://www.scala-lang.org/api/2.12.4/scala-swing/scala/swing/) * Scala 2.12.3 * [Library API](http://www.scala-lang.org/api/2.12.3/) * [Compiler API](http://www.scala-lang.org/api/2.12.3/scala-compiler/scala/) From 94d33f922b669c81d93f848eb02275cc515fbe41 Mon Sep 17 00:00:00 2001 From: Tony Bye <37843657+tbye-pfp@users.noreply.github.com> Date: Tue, 8 May 2018 15:35:16 -0400 Subject: [PATCH 0197/3174] Calc example, add note on calc object The code for the Calc example will not compile as is. It can be very frustrating to someone trying to learn a new language to figure out how to get the example code to compile. I added a note about wrapping some of the code in a Calc object. There is probably a better way to include that in the tutorial, but I think this is better than nothing. --- _overviews/tutorials/scala-for-java-programmers.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_overviews/tutorials/scala-for-java-programmers.md b/_overviews/tutorials/scala-for-java-programmers.md index cbbd95aa7a..d53fdb75c4 100644 --- a/_overviews/tutorials/scala-for-java-programmers.md +++ b/_overviews/tutorials/scala-for-java-programmers.md @@ -532,7 +532,9 @@ computes its derivative relative to `x` and then `y`. println("Derivative relative to y:\n " + derive(exp, "y")) } -Executing this program, we get the expected output: +You will need to wrap the `Environment` type and `eval`, `derive`, and +`main` methods in a `Calc` object before compiling. Executing this +program, we get the expected output: Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y))) Evaluation with x=5, y=7: 24 From 8bab3d277dd39e36c97cd5febfeca91ec3d02bf5 Mon Sep 17 00:00:00 2001 From: Bradford Lynch Date: Thu, 10 May 2018 08:58:09 -0700 Subject: [PATCH 0198/3174] Updated page metadata to include in tour The Traits page wasn't being included in the tour TOC, but was being referenced by the tour pages before and after it, Classes and Class Composition with Mixins respectively. Updated the page metadata to include it in the tour, and fix the other tags. --- _tour/traits.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/_tour/traits.md b/_tour/traits.md index 282f3321eb..bc01ac1f2d 100644 --- a/_tour/traits.md +++ b/_tour/traits.md @@ -4,12 +4,15 @@ title: Traits discourse: true -tutorial: scala-tour -categories: tour +partof: scala-tour + num: 5 next-page: mixin-class-composition previous-page: classes -assumed-knowledge: expressions, classes, generics, objects, companion-objects +topics: traits +prerequisite-knowledge: expressions, classes, generics, objects, companion-objects + +redirect_from: "/tutorials/tour/traits.html" --- Traits are used to share interfaces and fields between classes. They are similar to Java 8's interfaces. Classes and objects can extend traits but traits cannot be instantiated and therefore have no parameters. From a03bf0c1212a29bb2633d1725d23ce776ea72228 Mon Sep 17 00:00:00 2001 From: Patchino <39184950+Patchino@users.noreply.github.com> Date: Fri, 11 May 2018 16:42:28 +0800 Subject: [PATCH 0199/3174] Modify the first two paragraphs The translation of the first two paragraphs is not accurate enough, thus it makes confusion. --- _zh-cn/overviews/collections/trait-iterable.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/overviews/collections/trait-iterable.md b/_zh-cn/overviews/collections/trait-iterable.md index 066639c768..d04a568b5b 100644 --- a/_zh-cn/overviews/collections/trait-iterable.md +++ b/_zh-cn/overviews/collections/trait-iterable.md @@ -11,14 +11,14 @@ num: 4 language: zh-cn --- -自下而上的容器(collection)层次结构具有可迭代的Trait。Trait的所有方法可定义为一个抽象方法,逐个生成容器(collection)元素迭代器。Traversable Trait的foreach方法实现了迭代器的Iterable。下面是具体的实现。 +容器(collection)结构的上层还有另一个trait。这个trait里所有方法的定义都基于一个抽象方法,迭代器(iterator,会逐一的产生集合的所有元素)。从Traversable trait里继承来的foreach方法在这里也是利用iterator实现。下面是具体的实现。 def foreach[U](f: Elem => U): Unit = { val it = iterator while (it.hasNext) f(it.next()) } -许多Iterable 的子类覆写了Iteable的foreach标准实现,因为它们提供了更多有效的实现。记住,由于性能问题,foreach是Traversable所有操作能够实现的基础。 +许多Iterable 的子类覆写了Iteable的foreach标准实现,因为它们能提供更高效的实现。记住,foreach是Traversable所有操作的基础,所以它的性能表现很关键。 Iterable有两个方法返回迭代器:grouped和sliding。然而,这些迭代器返回的不是单个元素,而是原容器(collection)元素的全部子序列。这些最大的子序列作为参数传给这些方法。grouped方法返回元素的增量分块,sliding方法生成一个滑动元素的窗口。两者之间的差异通过REPL的作用能够清楚看出。 From 8925abdb77ecad7eeb4a3616b13a888be92d6d2e Mon Sep 17 00:00:00 2001 From: Bradford Lynch Date: Fri, 11 May 2018 07:44:26 -0700 Subject: [PATCH 0200/3174] Updated page metadata to include in tour The Traits page wasn't being included in the tour TOC, but was being referenced by the tour pages before and after it, Inner Classes and Compound Types respectively. Updated the page metadata to include it in the tour, and fix the other tags. --- _tour/abstract-types.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_tour/abstract-types.md b/_tour/abstract-types.md index 61de402795..aded7a17a9 100644 --- a/_tour/abstract-types.md +++ b/_tour/abstract-types.md @@ -4,13 +4,14 @@ title: Abstract Types discourse: true -tutorial: scala-tour -categories: tour +partof: scala-tour num: 23 next-page: compound-types previous-page: inner-classes +topics: abstract types prerequisite-knowledge: variance, upper-type-bound +redirect_from: "/tutorials/tour/abstract-types.html" --- Traits and abstract classes can have an abstract type member. This means that the concrete implementations define the actual type. Here's an example: From 4ef9e209aaed2ffa3956c4487af26bf5b0606d39 Mon Sep 17 00:00:00 2001 From: Bradford Lynch Date: Fri, 11 May 2018 07:48:10 -0700 Subject: [PATCH 0201/3174] Updated page metadata to include in tour The Self Types page wasn't being included in the tour TOC, but was being referenced by the tour pages before and after it, Compound Types and Implicit Parameters respectively. Updated the page metadata to include it in the tour, and fix the other tags. --- _tour/self-types.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/_tour/self-types.md b/_tour/self-types.md index a2a8a93c6e..f54e62ae18 100644 --- a/_tour/self-types.md +++ b/_tour/self-types.md @@ -4,12 +4,15 @@ title: Self-type discourse: true -tutorial: scala-tour -categories: tour +partof: scala-tour + num: 25 next-page: implicit-parameters previous-page: compound-types +topics: self-types prerequisite-knowledge: nested-classes, mixin-class-composition + +redirect_from: "/tutorials/tour/self-types.html" --- Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn't directly extend it. That makes the members of the dependency available without imports. From 3e391d4b291142888d5eb8d69ffe518c1053a303 Mon Sep 17 00:00:00 2001 From: bartecheck Date: Sun, 13 May 2018 07:43:37 +0200 Subject: [PATCH 0202/3174] Update futures.md erroneous 'method' --- _overviews/core/futures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index b8ac14a754..68d4d50269 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -834,7 +834,7 @@ completed, but does not retrieve its result. In the same way, calling that method will not throw an exception if the future is failed. The `Future` trait implements the `Awaitable` trait with methods -method `ready()` and `result()`. These methods cannot be called directly +`ready()` and `result()`. These methods cannot be called directly by the clients-- they can only be called by the execution context. From 9a634500a8920a38eef90cf26d7287cd80dd5b37 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 21 May 2018 16:08:17 +0200 Subject: [PATCH 0203/3174] version bump in jdk compat guide --- _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 d7a02c5ad4..e53d09f7ca 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -38,7 +38,7 @@ Like the 2.12.x series, the Scala 2.13.x series will support Java 8 and higher. ## JDK 9 & 10 compatibility notes -As of Scala 2.12.5 and 2.11.12, **JDK 9 & 10 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. +As of Scala 2.12.6 and 2.11.12, **JDK 9 & 10 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. JDK 9 & 10 support requires minimum sbt version 1.1.0, or 0.13.17 in the 0.13.x series. From addad666fd1f3889795024e2ec5282a598ebb84a Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sun, 27 May 2018 09:00:30 -0700 Subject: [PATCH 0204/3174] Words about Predef in REPL --- _overviews/repl/overview.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/_overviews/repl/overview.md b/_overviews/repl/overview.md index 428cf53bdf..8d8e981b97 100644 --- a/_overviews/repl/overview.md +++ b/_overviews/repl/overview.md @@ -27,6 +27,8 @@ The REPL also provides some command facilities, described below. An alternative REPL is available in [the Ammonite project](https://github.com/lihaoyi/Ammonite), which also provides a richer shell environment. +### Features + Useful REPL features include: - the REPL's IMain is bound to `$intp`. @@ -34,16 +36,38 @@ Useful REPL features include: - use tab for completion. - use `//print` to show typed desugarings. - use `:help` for a list of commands. + - use `:load` to load a file of REPL input. - use `:paste` to enter a class and object as companions. - use `:paste -raw` to disable code wrapping, to define a package. - use `:javap` to inspect class artifacts. - use `-Yrepl-outdir` to inspect class artifacts with external tools. - use `:power` to enter power mode and import compiler components. + - use `:settings` to modify compiler settings; some settings require `:replay`. + - use `:replay` to replay the session with modified settings. Implementation notes: - user code can be wrapped in either an object (so that the code runs during class initialization) or a class (so that the code runs during instance construction). The switch is `-Yrepl-class-based`. + - every line of input is compiled separately. + - dependencies on previous lines are included by automatically generated imports. + - implicit import of `scala.Predef` can be controlled by inputting an explicit import. + +**Example:** + + scala> import Predef.{any2stringadd => _, _} + import Predef.{any2stringadd=>_, _} + + scala> new Object + "a string" + :13: error: value + is not a member of Object + new Object + "a string" + ^ + + scala> import Predef._ + import Predef._ + + scala> new Object + "a string" + res1: String = java.lang.Object@787a0fd6a string ### Power Mode From 8f92a7d139609671f9d091b3dae4c11467e4ca3c Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 May 2018 11:02:07 +0200 Subject: [PATCH 0205/3174] =?UTF-8?q?Port=20=E2=80=9CThe=20Architecture=20?= =?UTF-8?q?of=20Scala=20Collections=E2=80=9D=20to=20the=20new=20architectu?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of replacing the existing documentation, it creates a new page for 2.13’s collections. --- _data/overviews.yml | 5 + .../architecture-of-scala-213-collections.md | 1348 +++++++++++++++++ resources/images/collections-architecture.svg | 1 + 3 files changed, 1354 insertions(+) create mode 100644 _overviews/core/architecture-of-scala-213-collections.md create mode 100644 resources/images/collections-architecture.svg diff --git a/_data/overviews.yml b/_data/overviews.yml index 005309a7de..9eddbfd0d9 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -42,6 +42,11 @@ url: "core/architecture-of-scala-collections.html" by: Martin Odersky and Lex Spoon description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." + - title: The Architecture of Scala 2.13’s Collections + icon: building + url: "core/architecture-of-scala-213-collections.html" + by: Martin Odersky, Lex Spoon and Julien Richard-Foy + description: "These pages describe the architecture of the collections framework introduced in Scala 2.13. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - category: Language description: "Guides and overviews covering features in the Scala language." diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md new file mode 100644 index 0000000000..3b5f6c350b --- /dev/null +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -0,0 +1,1348 @@ +--- +layout: singlepage-overview +title: The Architecture of Scala 2.13’s Collections + +permalink: /overviews/core/:title.html +--- + +**Martin Odersky, Lex Spoon and Julien Richard-Foy** + +These pages describe the architecture of the Scala collections +framework in detail. Compared to +[the Collections Introduction]({{ site.baseurl }}/overviews/collections/introduction.html) you +will find out more about the internal workings of the framework. You +will also learn how this architecture helps you define your own +collections in a few lines of code, while reusing the overwhelming +part of collection functionality from the framework. + +[The Collections API]({{ site.baseurl }}/overviews/collections/introduction.html) +contains a large number of collection +operations, which exist uniformly on many different collection +implementations. Implementing every collection operation anew for +every collection type would lead to an enormous amount of code, most +of which would be copied from somewhere else. Such code duplication +could lead to inconsistencies over time, when an operation is added or +modified in one part of the collection library but not in others. The +principal design objective of the collections framework is to +avoid any duplication, defining every operation in as few places as +possible. (Ideally, everything should be defined in one place only, +but there are a few exceptions where things needed to be redefined.) +The design approach was to implement most operations in collection +"templates" that can be flexibly inherited from individual base +classes and implementations. The following pages explain these +templates and other classes and traits that constitute the "building +blocks" of the framework, as well as the construction principles they +support. + +## Factoring out common operations ## + +This section presents the variability found in collections, which has to +be abstracted over to define reusable operation implementations. + +We can group collection operations into two categories: + +- **transformation** operations, which return another collection (e.g. + `map`, `filter`, `zip`, …), +- **reduction** operations, which return a single value (e.g. `isEmpty`, + `foldLeft`, `find`, …). + +Transformation operations are harder to implement in template traits +because we want them to return collection types that are unknown yet. +For instance, consider the signature of the `map` operation on `List[A]` +and `Vector[A]`: + +~~~ scala +trait List[A] { + def map[B](f: A => B): List[B] +} + +trait Vector[A] { + def map[B](f: A => B): Vector[B] +} +~~~ + +To generalize the type signature of `map` we have to abstract over +the resulting *collection type constructor*. + +A slightly different example is `filter`. Consider its type signature on +`List[A]` and `Map[K, V]`: + +~~~ scala +trait List[A] { + def filter(p: A => Boolean): List[A] +} + +trait Map[K, V] { + def filter(p: ((K, V)) => Boolean): Map[K, V] +} +~~~ + +To generalize the type signature of `filter` we have to abstract +over the resulting *collection type*. + +In summary, operations that change the elements type (`map`, +`flatMap`, `collect`, etc.) need to abstract over the resulting +collection type constructor, and operations that keep the same +elements type (`filter`, `take`, `drop`, etc.) need to abstract +over the resulting collection type. + +### Abstracting over collection types ### + +The template trait `IterableOps` implements the operations available +on the `Iterable[A]` collection type. + +Here is the header of trait `IterableOps`: + +~~~ scala +trait IterableOps[+A, +CC[_], +C] { … } +~~~ + +The type parameter `A` stands for the element type of the iterable, +the type parameter `CC` stands for the collection type constructor +and the type parameter `C` stands for the collection type. + +This allows us to define the signature of `filter` and `map` like +so: + +~~~ scala +trait IterableOps[+A, +CC[_], +C] { + def filter(p: A => Boolean): C = … + def map[B](f: A => B): CC[B] = … +} +~~~ + +And then leaf collection types appropriately instantiate the type +parameters. For instance, in the case of `List[A]` we want `CC` to +be `List` and `C` to be `List[A]`: + +~~~ scala +trait List[+A] extends Iterable[A] + with IterableOps[A, List, List[A]] +~~~ + +### Four branches of templates traits ### + +The astute reader might have noticed that the given type signature +for the `map` operation doesn’t work with `Map` collections because +the `CC[_]` type parameter of the `IterableOps` trait takes one type +parameter whereas `Map[K, V]` takes two type parameters. + +To support collection types constructors with two types parameters +we have another template trait named `MapOps`: + +~~~ scala +trait MapOps[K, +V, +CC[_, _], +C] extends IterableOps[(K, V), Iterable, C] { + def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = … +} +~~~ + +And then `Map[K, V]` can extend this trait and appropriately instantiate its +type parameters: + +~~~ scala +trait Map[K, V] extends Iterable[(K, V)] + with MapOps[K, V, Map, Map[K, V]] +~~~ + +Note that the `MapOps` trait inherits from `IterableOps` so that operations +defined in `IterableOps` are also available in `MapOps`. Also note that +the collection type constructor passed to the `IterableOps` trait is +`Iterable`. This means that `Map[K, V]` inherits two overloads of the `map` +operation: + +~~~ scala +// from MapOps +def map[K2, V2](f: ((K, V)) => (K2, V2)): Map[K2, V2] + +// from IterableOps +def map[B](f: ((K, V)) => B): Iterable[B] +~~~ + +At use-site, if you call the `map` operation, the overloading resolution rules +first try the definition that comes from `MapOps` (because `MapOps` is more +specific than `IterableOps`), which returns a `Map`, but if it doesn’t type +check (in case the return type of the function passed to the `map` call is not +a pair), it fallbacks to the definition from `IterableOps`, which returns an +`Iterable`. This is how we follow the “same-result-type” principle: wherever +possible a transformation method on a collection yields a collection of the +same type. + +In summary, the fact that `Map` collection types take two type parameters makes +it impossible to unify their transformation operations with the ones from +`IterableOps`, hence the specialized `MapOps` template trait. + +There is another situation where the type signatures of the transformation +operations defined in `IterableOps` don’t match the type signature of a +more concrete collection type: `SortedSet[A]`. In that case the type +signature of the `map` operation is the following: + +~~~ scala +def map[B](f: A => B)(implicit ord: Ordering[B]): SortedSet[B] +~~~ + +The difference with the signature we have in `IterableOps` is that here +we need an implicit `Ordering` instance for the type of elements. + +Like for `Map`, `SortedSet` needs a specialized template trait with +overloads for transformation operations: + +~~~ scala +trait SortedSetOps[A, +CC[_], +C] extends IterableOps[A, Set, C] { + + def map[B](f: A => B)(implicit ord: Ordering[B]): CC[B] = … + +} +~~~ + +And then collection types that inherit the `SortedSetOps` trait appropriately +instantiate its type parameters: + +~~~ scala +trait SortedSet[A] extends SortedSetOps[A, SortedSet, SortedSet[A]] +~~~ + +Last, there is a fourth kind of collection that requires a specialized template +trait: `SortedMap[K, V]`. This type of collection has two type parameters and +needs an implicit ordering instance on the type of keys. Therefore we have a +`SortedMapOps` template trait that provides the appropriate overloads. + +In total, we’ve seen that we have four branches of template traits: + + + kind | not sorted | sorted +===========|===============|=============== +`CC[_]` | `IterableOps` | `SortedSetOps` +`CC[_, _]` | `MapOps` | `SortedMapOps` + +Here is a diagram illustrating the architecture: + +![]({{ site.baseurl }}/resources/images/collections-architecture.svg) + +Template traits are in grey whereas collection types are in white. + +### Strict and non-strict collections ### + +Another difference that has been taken into account in the design of the +collections framework is the fact that some collection types eagerly +evaluate their elements (e.g. `List`, `Set`, etc.), whereas others +delay their evaluation until the element is effectively accessed (e.g. +`LazyList` and `View`). The former category of collections is said to +be “strict”, whereas the latter is said to be “non-strict”. + +Thus, the default implementation of transformation operations must +preserve the “strictness” of the concrete collection type that inherits +these implementations. For instance, we want the default `map` implementation +to be non-strict when inherited by a `View`, and strict when inherited +by a `List`. + +### Operations implementation ### + +Now that we are more familiar with the hierarchy of the template traits, we can have +a look at the actual implementation of some operations. Consider for instance the +implementations of `filter` and `map`: + +~~~ scala +trait IterableOps[+A, +CC[_], +C] { + + def filter(pred: A => Boolean): C = + fromSpecificIterable(new View.Filter(this, pred)) + + def map[B](f: A => B): CC[B] = + fromIterable(new View.Map(this, f)) + + protected def fromSpecificIterable(coll: Iterable[A]): C + protected def fromIterable[E](it: Iterable[E]): CC[E] +} +~~~ + +Let’s detail the implementation of `filter`, step by step: + +- the instantiation of `View.Filter` creates a (non-strict) `View` that filters the elements + of the underlying collection ; +- the call to `fromSpecificIterable` turns the `View` into a concrete + collection `C`. The implementation of `fromSpecificIterable` is left to + concrete collections: they can decide to evaluate in a strict or non-strict way + the elements resulting from the operation. + +The implementation of `map` is similar, excepted that instead of using +`fromSpecificIterable` it uses `fromIterable` which takes as parameter an +iterable whose element type `E` is arbitrary. + +Actually, `fromIterable` is not abstract in `IterableOps`: it delegates to an +`iterableFactory` member (which is abstract): + +~~~ scala +trait IterableOps[+A, +CC[_], +C] { + + protected def fromIterable[E](it: Iterable[E]): CC[E] = + iterableFactory.from(it) + + def iterableFactory: IterableFactory[CC] + +} +~~~ + +This `iterableFactory` member is implemented by concrete collections and typically +refer to their companion object, which provides factory methods to create concrete +collection instances. Here is an excerpt of the definition of `IterableFactory`: + +~~~ scala +trait IterableFactory[+CC[_]] { + def from[A](source: IterableOnce[A]): CC[A] +} +~~~ + +Last but not least, as explained in the above sections, since we have four branches +of template traits, we have four corresponding branches of factories. For instance, +here are the relevant parts of code of the `map` operation implementation in `Map`: + +~~~ scala +trait MapOps[K, +V, +CC[_, _], +C] + extends IterableOps[(K, V), Iterable, C] { + + def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = + mapFromIterable(new View.Map(this, f)) + + // Similar to fromIterable, but returns a Map collection type + protected def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): CC[K2, V2] = + mapFactory.from(it) + + def mapFactory: MapFactory[CC] + +} + +trait MapFactory[+CC[_, _]] { + def from[K, V](it: IterableOnce[(K, V)]): CC[K, V] +} +~~~ + +### When a strict evaluation is preferable (or unavoidable) ### + +In the previous sections we explained that the “strictness” of concrete collections +should be preserved by default operation implementations. However in some cases this +leads to less efficient implementations. For instance, `partition` has to perform +two traversals of the underlying collection. In some other case (e.g. `groupBy`) it +is simply not possible to implement the operation without evaluating the collection +elements. + +For those cases, we also provide ways to implement operations in a strict mode. +The pattern is different: instead of being based on a `View`, it is based on a +`Builder`. Here is an outline of the `Builder` trait: + +~~~ scala +package scala.collection.mutable + +trait Builder[-A, +C] { + def addOne(elem: A): this.type + def result(): C +} +~~~ + +Builders are generic in both the element type `A` and the type of collection they +return, `C`. +You can add an element `x` to a builder `b` with `b.addOne(x)` (or `b += x`). The +`result()` method returns a collection from a builder. + +By symmetry with `fromSpecificIterable` and `fromIterable`, template traits provide +ways to get a builder resulting in a collection with the same type of elements, and +to get a builder resulting in a collection of the same type but with a different +type of elements. The following code shows the relevant parts of `IterableOps` and +`IterableFactory` to build collections in both strict and non-strict modes: + +~~~ scala +trait IterableOps[+A, +CC[_], +C] { + def iterableFactory: IterableFactory[CC] + protected def fromSpecificIterable(coll: Iterable[A]): C + protected def newSpecificBuilder(): Builder[A, C] +} + +trait IterableFactory[+CC[_]] { + def from[A](source: IterableOnce[A]): CC[A] + def newBuilder[A](): Builder[A, CC[A]] +} +~~~ + +Note that, in general, an operation that doesn’t *have to* be strict should +be implemented in a non-strict mode, otherwise it would lead to surprising +behaviour when used on a non-strict concrete collection. That being said, +the strict mode is often more efficient. This is why we provide template +traits whose operation implementations have been overridden to take +advantage of strict builders. The name of these template traits always +starts with `StrictOptimized`. You should use such a template trait for +your custom collection if it is a strict collection. + +## Integrating a new collection: capped sequence ## + +What needs to be done if you want to integrate a new collection class, +so that it can profit from all predefined operations with the right +types? In the next few sections you’ll be walked through three examples +that do this, namely capped sequences, sequences of RNA +bases and prefix maps implemented with Patricia tries. + +Say you want to create a collection containing *at most* `n` elements: +if more elements are added then the first elements are removed. Such a +collection can be efficiently implemented using an `Array` with a fixed +capacity: random access and element insertion are O(1) operations. + +The first task is to find the supertype of our collection: is it +`Seq`, `Set`, `Map` or just `Iterable`? In our case, it is tempting +to choose `Seq` because our collection can contain duplicates and +iteration order is determined by insertion order. However, some +properties of `Seq` are not satisfied: + +~~~ scala +(xs ++ ys).size == xs.size + ys.size +~~~ + +Consequently, the only sensible choice as a base collection type +is `Iterable`. + +### First version of `Capped` class ### + +~~~ scala +import scala.collection._ + +class Capped1[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] { self => + + def this(capacity: Int) = + this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) + + def appended[B >: A](elem: B): Capped1[B] = { + val newElems = Array.ofDim[Any](capacity) + Array.copy(elems, 0, newElems, 0, capacity) + val (newOffset, newLength) = + if (length == capacity) { + newElems(offset) = elem + ((offset + 1) % capacity, length) + } else { + newElems(length) = elem + (offset, length + 1) + } + new Capped1[B](capacity, newLength, newOffset, newElems) + } + + @`inline` def :+ [B >: A](elem: B): Capped1[B] = appended(elem) + + def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] + + def iterator: Iterator[A] = new AbstractIterator[A] { + private var current = 0 + def hasNext = current < self.length + def next(): A = { + val elem = self(current) + current += 1 + elem + } + } + +} +~~~ + +The above listing presents the first version of our capped collection +implementation. It will be refined later. The class `Capped1` has a +private constructor that takes the collection capacity, length, +offset (first element index) and the underlying array as parameters. +The public constructor takes only the capacity of the collection. It +sets the length and offset to 0, and uses an empty array of elements. + +The `appended` method defines how elements can be appended to a given +`Capped1` collection: it creates a new underlying array of elements, +copies the current elements and adds the new element. As long as the +number of elements does not exceed the `capacity`, the new element +is appended after the previous elements. However, as soon as the +maximal capacity has been reached, the new element replaces the first +element of the collection (at `offset` index). + +The `apply` method implements indexed access: it translates the given +index into its corresponding index in the underlying array by adding +the `offset`. + +These two methods, `appended` and `apply`, implement the specific +behavior of the `Capped1` collection type. In addition to them, we have +to implement `iterator` to make the generic collection operations +(such as `foldLeft`, `count`, etc.) work on `Capped` collections. +Here we implement it by using indexed access. + +Here are some interactions with the `Capped1` collection: + +~~~ scala +scala> new Capped1(capacity = 4) +res0: Capped1[Nothing] = Capped1() + +scala> res0 :+ 1 :+ 2 :+ 3 +res1: Capped1[Int] = Capped1(1, 2, 3) + +scala> res1.length +res2: Int = 3 + +scala> res1.lastOption +res3: Option[Int] = Some(3) + +scala> res1 :+ 4 :+ 5 :+ 6 +res4: Capped1[Int] = Capped1(3, 4, 5, 6) + +scala> res4.take(3) +res5: collection.immutable.Iterable[Int] = List(3, 4, 5) +~~~ + +You can see that if we try to grow the collection with more than four +elements, the first elements are dropped (see `res4`). The operations +behave as expected except for the last one: after calling `take` we +get back a `List` instead of the expected `Capped1` collection. This +is because all that was done in class +[`Capped1`](#first-version-of-capped-class) was making `Capped1` extend +`immutable.Iterable`. This class has a `take` method +that returns an `immutable.Iterable`, and that’s implemented in terms of +`immutable.Iterable`’s default implementation, `List`. So, that’s what +you were seeing on the last line of the previous interaction. + +Now that you understand why things are the way they are, the next +question should be what needs to be done to change them? One way to do +this would be to override the `take` method in class `Capped1`, maybe like +this: + + def take(count: Int): Capped1 = … + +This would do the job for `take`. But what about `drop`, or `filter`, or +`init`? In fact there are over fifty methods on collections that return +again a collection. For consistency, all of these would have to be +overridden. This looks less and less like an attractive +option. Fortunately, there is a much easier way to achieve the same +effect, as shown in the next section. + +### Second version of `Capped` class ### + +~~~ scala +class Capped2[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] + with IterableOps[A, Capped2, Capped2[A]] { self => + + def this(capacity: Int) = // as before + + def appended[B >: A](elem: B): Capped2[B] = // as before + @`inline` def :+ [B >: A](elem: B): Capped2[B] = // as before + def apply(i: Int): A = // as before + + def iterator: Iterator[A] = // as before + + override val iterableFactory: IterableFactory[Capped2] = new Capped2Factory(capacity) + +} + +class Capped2Factory(capacity: Int) extends IterableFactory[Capped2] { + + def from[A](source: IterableOnce[A]): Capped2[A] = + (newBuilder[A] ++= source).result() + + def empty[A]: Capped2[A] = new Capped2[A](capacity) + + def newBuilder[A]: Builder[A, Capped2[A]] = + new ImmutableBuilder[A, Capped2[A]](empty) { + def addOne(elem: A): this.type = { elems = elems :+ elem; this } + } +} +~~~ + +The Capped class needs to inherit not only from `Iterable`, but also +from its implementation trait `IterableOps`. This is shown in the +above listing of class `Capped2`. The new implementation differs +from the previous one in only two aspects. First, class `Capped2` +now also extends `IterableOps[A, Capped2, Capped2[A]]`. Second, +its `iterableFactory` member is overridden to return an +`IterableFactory[Capped2]`. As explained in the +previous sections, the `IterableOps` trait implements all concrete +methods of `Iterable` in a generic way. For instance, the +return type of methods like `take`, `drop`, `filter` or `init` +is the third type parameter passed to class `IterableOps`, i.e., +in class `Capped2`, it is `Capped2[A]`. Similarly, the return +type of methods like `map`, `flatMap` or `concat` is defined +by the second type parameter passed to class `IterableOps`, +i.e., in class `Capped2`, it is `Capped2` itself. + +To construct a `Capped2`, the `fromSpecificIterable` and +`newSpecificBuilder` implementations inherited from `immutable.Iterable` +delegate to the `iterableFactory` member, which is overridden here to +return an instance of `Capped2Factory`. This class +provides convenient factory methods to build collections. Eventually, +these methods delegate to `empty`, which builds an empty `Capped2` +instance, and `newBuilder`, which uses the `appended` operation +to grow a `Capped2` collection. + +With the refined implementation of the [`Capped2` class](#second-version-of-capped-class), +the transformation operations work now as expected, and the +`Capped2Factory` class provides seamless conversions from other collections: + +~~~ scala +scala> object Capped extends Capped2Factory(capacity = 4) +defined object Capped + +scala> Capped(1, 2, 3) +res0: Capped2[Int] = Capped2(1, 2, 3) + +scala> res0.take(2) +res1: Capped2[Int] = Capped2(1, 2) + +scala> res0.filter(x => x % 2 == 1) +res2: Capped2[Int] = Capped2(1, 3) + +scala> res0.map(x => x * x) +res3: Capped2[Int] = Capped2(1, 4, 9) + +scala> List(1, 2, 3, 4, 5).to(Capped) +res4: Capped2[Int] = Capped2(2, 3, 4, 5) +~~~ + +This implementation now behaves correctly, but we can still improve +a few things. Since our collection is strict, we can take advantage +of the better performance offered by +of strict implementations for transformation operations. + +### Final version of `Capped` class ### + +~~~ scala +final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] + with IterableOps[A, Capped, Capped[A]] + with StrictOptimizedIterableOps[A, Capped, Capped[A]] { self => + + def this(capacity: Int) = + this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) + + def appended[B >: A](elem: B): Capped[B] = { + val newElems = Array.ofDim[Any](capacity) + Array.copy(elems, 0, newElems, 0, capacity) + val (newOffset, newLength) = + if (length == capacity) { + newElems(offset) = elem + ((offset + 1) % capacity, length) + } else { + newElems(length) = elem + (offset, length + 1) + } + new Capped[B](capacity, newLength, newOffset, newElems) + } + + @`inline` def :+ [B >: A](elem: B): Capped[B] = appended(elem) + + def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] + + def iterator: Iterator[A] = view.iterator + + override def view: IndexedSeqView[A] = new IndexedSeqView[A] { + def length: Int = self.length + def apply(i: Int): A = self(i) + } + + override def knownSize: Int = length + + override val iterableFactory: IterableFactory[Capped] = new CappedFactory(capacity) + +} + +class CappedFactory(capacity: Int) extends IterableFactory[Capped] { + + def from[A](source: IterableOnce[A]): Capped[A] = + source match { + case capped: Capped[A] if capped.capacity == capacity => capped + case _ => (newBuilder[A] ++= source).result() + } + + def empty[A]: Capped[A] = new Capped[A](capacity) + + def newBuilder[A]: Builder[A, Capped[A]] = + new ImmutableBuilder[A, Capped[A]](empty) { + def addOne(elem: A): this.type = { elems = elems :+ elem; this } + } + +} +~~~ + +That is it. The final [`Capped` class](#final-version-of-capped-class): + +- extends the `StrictOptimizedIterableOps` trait, which overrides all + transformation operations to take advantage of strict builders, +- overrides a few operations for performance: the `view` now uses + indexed access, and the `iterator` delegates to the view. The + `knownSize` operation is also overridden because the size is always + known. + +Its implementation requires a little bit of protocol. In essence, you +have to inherit from the `Ops` template trait in addition to just +inheriting from a collection type, override the `iterableFactory` +member to return a more specific factory, and finally implement abstract +methods (such as `iterator` in our case), if any. + +## Integrating a new collection: RNA sequences ## + +To start with the second example, we define the four RNA Bases: + + abstract class Base + case object A extends Base + case object U extends Base + case object G extends Base + case object C extends Base + + object Base { + val fromInt: Int => Base = Array(A, U, G, C) + val toInt: Base => Int = Map(A -> 0, U -> 1, G -> 2, C -> 3) + } + +Say you want to create a new sequence type for RNA strands, which are +sequences of bases A (adenine), U (uracil), G (guanine), and C +(cytosine). The definitions for bases are easily set up as shown in the +listing of RNA bases above. + +Every base is defined as a case object that inherits from a common +abstract class `Base`. The `Base` class has a companion object that +defines two functions that map between bases and the integers 0 to 3. +You can see in the examples two different ways to use collections +to implement these functions. The `toInt` function is implemented as a +`Map` from `Base` values to integers. The reverse function, `fromInt`, is +implemented as an array. This makes use of the fact that both maps and +arrays *are* functions because they inherit from the `Function1` trait. + +The next task is to define a class for strands of RNA. Conceptually, a +strand of RNA is simply a `Seq[Base]`. However, RNA strands can get +quite long, so it makes sense to invest some work in a compact +representation. Because there are only four bases, a base can be +identified with two bits, and you can therefore store sixteen bases as +two-bit values in an integer. The idea, then, is to construct a +specialized subclass of `Seq[Base]`, which uses this packed +representation. + +### First version of RNA strands class ### + + import collection.immutable.{ IndexedSeq, IndexedSeqOps } + + final class RNA1 private ( + val groups: Array[Int], + val length: Int + ) extends IndexedSeq[Base] + with IndexedSeqOps[Base, IndexedSeq, RNA1] { + + import RNA1._ + + def apply(idx: Int): Base = { + if (idx < 0 || length <= idx) + throw new IndexOutOfBoundsException + Base.fromInt(groups(idx / N) >> (idx % N * S) & M) + } + + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 = + fromSeq(coll.toSeq) + override protected def newSpecificBuilder: Builder[Base, RNA1] = + iterableFactory.newBuilder[Base].mapResult(fromSeq) + } + + object RNA1 { + + // Number of bits necessary to represent group + private val S = 2 + + // Number of groups that fit in an Int + private val N = 32 / S + + // Bitmask to isolate a group + private val M = (1 << S) - 1 + + def fromSeq(buf: Seq[Base]): RNA1 = { + val groups = new Array[Int]((buf.length + N - 1) / N) + for (i <- 0 until buf.length) + groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) + new RNA1(groups, buf.length) + } + + def apply(bases: Base*) = fromSeq(bases) + } + +The [RNA strands class listing](#first-version-of-rna-strands-class) above +presents the first version of this +class. The class `RNA1` has a constructor that +takes an array of `Int`s as its first argument. This array contains the +packed RNA data, with sixteen bases in each element, except for the +last array element, which might be partially filled. The second +argument, `length`, specifies the total number of bases on the array +(and in the sequence). Class `RNA1` extends `IndexedSeq[Base]` and +`IndexedSeqOps[Base, IndexedSeq, RNA1]`. These traits define the following +abstract methods: + +- `length`, automatically implemented by defining a parametric field of + the same name, +- `apply` (indexing method), implemented by first extracting an integer value + from the `groups` array, then extracting the correct two-bit number from that + integer using right shift (`>>`) and mask (`&`). The private constants `S`, + `N`, and `M` come from the `RNA1` companion object. `S` specifies the size of + each packet (i.e., two); `N` specifies the number of two-bit packets per + integer; and `M` is a bit mask that isolates the lowest `S` bits in a + word. + +We also override the following members used by transformation operations +such as `filter` and `take`: + +- `fromSpecificIterable`, implemented by the `fromSeq` method of the `RNA1` + companion object, +- `newSpecificBuilder`, implemented by using the default `IndexedSeq` builder + and transforming its result into an `RNA1` with the `mapResult` method. + +Note that the constructor of class `RNA1` is `private`. This means that +clients cannot create `RNA1` sequences by calling `new`, which makes +sense, because it hides the representation of `RNA1` sequences in terms +of packed arrays from the user. If clients cannot see what the +representation details of RNA sequences are, it becomes possible to +change these representation details at any point in the future without +affecting client code. In other words, this design achieves a good +decoupling of the interface of RNA sequences and its +implementation. However, if constructing an RNA sequence with `new` is +impossible, there must be some other way to create new RNA sequences, +else the whole class would be rather useless. In fact there are two +alternatives for RNA sequence creation, both provided by the `RNA1` +companion object. The first way is method `fromSeq`, which converts a +given sequence of bases (i.e., a value of type `Seq[Base]`) into an +instance of class `RNA1`. The `fromSeq` method does this by packing all +the bases contained in its argument sequence into an array, then +calling `RNA1`'s private constructor with that array and the length of +the original sequence as arguments. This makes use of the fact that a +private constructor of a class is visible in the class's companion +object. + +The second way to create an `RNA1` value is provided by the `apply` method +in the `RNA1` object. It takes a variable number of `Base` arguments and +simply forwards them as a sequence to `fromSeq`. Here are the two +creation schemes in action: + + scala> val xs = List(A, G, U, A) + xs: List[Base] = List(A, G, U, A) + + scala> RNA1.fromSeq(xs) + res1: RNA1 = RNA1(A, G, U, A) + + scala> val rna1 = RNA1(A, U, G, G, C) + rna1: RNA1 = RNA1(A, U, G, G, C) + +Also note that the type parameters of the `IndexedSeqOps` trait that +we inherit from are: `Base`, `IndexedSeq` and `RNA1`. The first one +stands for the type of elements, the second one stands for the +type constructor used by transformation operations that return +a collection with a different type of elements, and the third one +stands for the type used by transformation operations that return +a collection with the same type of elements. In our case, it is +worth noting that the second one is `IndexedSeq` whereas the +third one is `RNA1`. This means that operations like `map` or +`flatMap` return an `IndexedSeq`, whereas operations like `take` or +`filter` return an `RNA1`. + +Here is an example showing the usage of `take` and `filter`: + + scala> rna1.take(3) + res5: RNA1 = RNA1(A, U, G) + + scala> rna1.filter(_ != U) + res6: RNA1 = RNA1(A, G, G, C) + +### Dealing with map and friends ### + +However, transformation operations that return a collection with a +different element type always return an `IndexedSeq`. + +How should these +methods be adapted to RNA strands? The desired behavior would be to get +back an RNA strand when mapping bases to bases or appending two RNA strands +with `++`: + + scala> val rna = RNA(A, U, G, G, C) + rna: RNA = RNA(A, U, G, G, C) + + scala> rna map { case A => U case b => b } + res7: RNA = RNA(U, U, G, G, C) + + scala> rna ++ rna + res8: RNA = RNA(A, U, G, G, C, A, U, G, G, C) + +On the other hand, mapping bases to some other type over an RNA strand +cannot yield another RNA strand because the new elements have the +wrong type. It has to yield a sequence instead. In the same vein +appending elements that are not of type `Base` to an RNA strand can +yield a general sequence, but it cannot yield another RNA strand. + + scala> rna map Base.toInt + res2: IndexedSeq[Int] = Vector(0, 1, 2, 2, 3) + + scala> rna ++ List("missing", "data") + res3: IndexedSeq[java.lang.Object] = + Vector(A, U, G, G, C, missing, data) + +This is what you'd expect in the ideal case. But this is not what the +[`RNA1` class](#first-version-of-rna-strands-class) provides. In fact, all +examples will return instances of `Vector`, not just the last two. If you run +the first three commands above with instances of this class you obtain: + + scala> val rna1 = RNA1(A, U, G, G, C) + rna1: RNA1 = RNA1(A, U, G, G, C) + + scala> rna1 map { case A => U case b => b } + res0: IndexedSeq[Base] = Vector(U, U, G, G, C) + + scala> rna1 ++ rna1 + res1: IndexedSeq[Base] = Vector(A, U, G, G, C, A, U, G, G, C) + +So the result of `map` and `++` is never an RNA strand, even if the +element type of the generated collection is `Base`. To see how to do +better, it pays to have a close look at the signature of the `map` +method (or of `++`, which has a similar signature). The `map` method is +originally defined in class `scala.collection.IterableOps` with the +following signature: + + def map[B](f: A => B): CC[B] + +Here `A` is the type of elements of the collection, and `CC` is the type +constructor passed as a second parameter to the `IterableOps` trait. + +In our `RNA1` implementation, this `CC` type constructor is `IndexedSeq`, +this is why we always get a `Vector` as a result. + +### Second version of RNA strands class ### + + final class RNA2 private (val groups: Array[Int], val length: Int) + extends IndexedSeq[Base] with IndexedSeqOps[Base, IndexedSeq, RNA2] { + + import RNA2._ + + def apply(idx: Int): Base = // as before + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before + override protected def newSpecificBuilder: Builder[Base, RNA2] = // as before + + // Overloading of `appended`, `prepended`, `appendedAll`, + // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2` + // when possible + def appended(base: Base): RNA2 = + fromSpecificIterable(new View.Append(this, base)) + def appendedAll(suffix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(this, suffix)) + def prepended(base: Base): RNA2 = + fromSpecificIterable(new View.Prepend(base, this)) + def prependedAll(prefix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(prefix, this)) + def map(f: Base => Base): RNA2 = + fromSpecificIterable(new View.Map(this, f)) + def flatMap(f: Base => IterableOnce[Base]): RNA2 = + fromSpecificIterable(new View.FlatMap(this, f)) + def concat(suffix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(this, suffix)) + } + +To address this shortcoming, you need to overload the methods that +return an `IndexedSeq[B]` for the case where `B` is known to be `Base`, +to return an `RNA2` instead. + +Compared to [class `RNA1`](#first-version-of-rna-strands-class) +we added overloads for methods `appended`, `appendedAll`, `prepended`, +`prependedAll`, `map` and `flatMap`. + +This implementation now behaves correctly, but we can still improve a few things. Since our +collection is strict, we could take advantage of the better performance offered by strict builders +in transformation operations. +Also, if we try to convert an `Iterable[Base]` into an `RNA2` it fails: + +~~~ +scala> val bases: Iterable[Base] = List(A, U, C, C) +bases: Iterable[Base] = List(A, U, C, C) + +scala> bases.to(RNA2) + ^ + error: type mismatch; + found : RNA2.type + required: scala.collection.Factory[Base,?] +~~~ + +### Final version of RNA strands class ### + +~~~ scala +final class RNA private ( + val groups: Array[Int], + val length: Int +) extends IndexedSeq[Base] + with IndexedSeqOps[Base, IndexedSeq, RNA] + with StrictOptimizedSeqOps[Base, IndexedSeq, RNA] { rna => + + import RNA._ + + // Mandatory implementation of `apply` in `IndexedSeqOps` + def apply(idx: Int): Base = { + if (idx < 0 || length <= idx) + throw new IndexOutOfBoundsException + Base.fromInt(groups(idx / N) >> (idx % N * S) & M) + } + + // Mandatory implementation of `fromSpecificIterable` and + // `newSpecificBuilder`, from `IterableOps` + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA = + RNA.fromSpecific(coll) + override protected def newSpecificBuilder: Builder[Base, RNA] = + RNA.newBuilder + + // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`, + // `map`, `flatMap` and `concat` to return an `RNA` when possible + def appended(base: Base): RNA = + (newSpecificBuilder ++= this += base).result() + def appendedAll(suffix: Iterable[Base]): RNA = + (newSpecificBuilder ++= this ++= suffix).result() + def prepended(base: Base): RNA = + (newSpecificBuilder += base ++= this).result() + def prependedAll(prefix: Iterable[Base]): RNA = + (newSpecificBuilder ++= prefix ++= this).result() + def map(f: Base => Base): RNA = { + var b = newSpecificBuilder + for (base <- this) { + b += f(base) + } + b.result() + } + def flatMap(f: Base => IterableOnce[Base]): RNA = { + var b = newSpecificBuilder + for (base <- this) { + b ++= f(base) + } + b.result() + } + def concat(suffix: IterableOnce[Base]): RNA = { + val b = newSpecificBuilder + b ++= this + b ++= suffix + b.result() + } + + // Optional re-implementation of iterator, + // to make it more efficient. + override def iterator: Iterator[Base] = new AbstractIterator[Base] { + private var i = 0 + private var b = 0 + def hasNext: Boolean = i < rna.length + def next(): Base = { + b = if (i % N == 0) groups(i / N) else b >>> S + i += 1 + Base.fromInt(b & M) + } + } + +} + +object RNA extends SpecificIterableFactory[Base, RNA] { + + private val S = 2 // number of bits in group + private val M = (1 << S) - 1 // bitmask to isolate a group + private val N = 32 / S // number of groups in an Int + + def fromSeq(buf: Seq[Base]): RNA = { + val groups = new Array[Int]((buf.length + N - 1) / N) + for (i <- 0 until buf.length) + groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) + new RNA(groups, buf.length) + } + + // Mandatory factory methods: `empty`, `newBuilder` + // and `fromSpecific` + def empty: RNA = fromSeq(Seq.empty) + + def newBuilder(): Builder[Base, RNA] = + ArrayBuffer.newBuilder[Base]().mapResult(fromSeq) + + def fromSpecific(it: IterableOnce[Base]): RNA = it match { + case seq: Seq[Base] => fromSeq(seq) + case _ => fromSeq(ArrayBuffer.from(it)) + } +} +~~~ + +The final [`RNA` class](#final-version-of-rna-strands-class): + +- extends the `StrictOptimizedSeqOps` trait, which overrides all transformation + operations to take advantage of strict builders, +- uses a strict mode for overloads of transformation operations that return + an `RNA`, +- has a companion object that extends `SpecificFactory[Base, RNA]`, which makes + it possible to use it as a parameter of a `to` call (to convert any collection + of bases to an `RNA`), +- moves the `newSpecificBuilder` and `fromSpecificIterable` implementations + to the companion object. + +The discussion so far centered on the minimal amount of definitions +needed to define new sequences with methods that obey certain +types. But in practice you might also want to add new functionality to +your sequences or to override existing methods for better +efficiency. An example of this is the overridden `iterator` method in +class `RNA`. `iterator` is an important method in its own right because it +implements loops over collections. Furthermore, many other collection +methods are implemented in terms of `iterator`. So it makes sense to +invest some effort optimizing the method's implementation. The +standard implementation of `iterator` in `IndexedSeq` will simply select +every `i`'th element of the collection using `apply`, where `i` ranges from +0 to the collection's length minus one. So this standard +implementation selects an array element and unpacks a base from it +once for every element in an RNA strand. The overriding `iterator` in +class `RNA` is smarter than that. For every selected array element it +immediately applies the given function to all bases contained in +it. So the effort for array selection and bit unpacking is much +reduced. + +## Integrating a new prefix map ## + +As a third example you'll learn how to integrate a new kind of map +into the collection framework. The idea is to implement a mutable map +with `String` as the type of keys by a "Patricia trie". The term +*Patricia* is in fact an abbreviation for "Practical Algorithm to +Retrieve Information Coded in Alphanumeric" and *trie* comes from +re*trie*val (a trie is also called a radix tree or prefix tree). +The idea is to store a set or a map as a tree where subsequent +characters in a search key +uniquely determine a path through the tree. For instance a Patricia trie +storing the strings "abc", "abd", "al", "all" and "xy" would look +like this: + +A sample patricia trie: + + +To find the node corresponding to the string "abc" in this trie, +simply follow the subtree labeled "a", proceed from there to the +subtree labelled "b", to finally reach its subtree labelled "c". If +the Patricia trie is used as a map, the value that's associated with a +key is stored in the nodes that can be reached by the key. If it is a +set, you simply store a marker saying that the node is present in the +set. + +Patricia tries support very efficient lookups and updates. Another +nice feature is that they support selecting a subcollection by giving +a prefix. For instance, in the patricia tree above you can obtain the +sub-collection of all keys that start with an "a" simply by following +the "a" link from the root of the tree. + +Based on these ideas we will now walk you through the implementation +of a map that's implemented as a Patricia trie. We call the map a +`PrefixMap`, which means that it provides a method `withPrefix` that +selects a submap of all keys starting with a given prefix. We'll first +define a prefix map with the keys shown in the running example: + + scala> val m = PrefixMap("abc" -> 0, "abd" -> 1, "al" -> 2, + "all" -> 3, "xy" -> 4) + m: PrefixMap[Int] = Map((abc,0), (abd,1), (al,2), (all,3), (xy,4)) + +Then calling `withPrefix` on `m` will yield another prefix map: + + scala> m withPrefix "a" + res14: PrefixMap[Int] = Map((bc,0), (bd,1), (l,2), (ll,3)) + +### Patricia trie implementation ### + +~~~ scala +import scala.collection._ +import scala.collection.mutable.{ GrowableBuilder, Builder } + +class PrefixMap[A] + extends mutable.Map[String, A] + with mutable.MapOps[String, A, mutable.Map, PrefixMap[A]] + with StrictOptimizedIterableOps[(String, A), mutable.Iterable, PrefixMap[A]] { + + var suffixes: immutable.Map[Char, PrefixMap[A]] = immutable.Map.empty + var value: Option[A] = None + + def get(s: String): Option[A] = + if (s.isEmpty) value + else suffixes get (s(0)) flatMap (_.get(s substring 1)) + + def withPrefix(s: String): PrefixMap[A] = + if (s.isEmpty) this + else { + val leading = s(0) + suffixes get leading match { + case None => + suffixes = suffixes + (leading -> empty) + case _ => + } + suffixes(leading) withPrefix (s substring 1) + } + + def iterator: Iterator[(String, A)] = + (for (v <- value.iterator) yield ("", v)) ++ + (for ((chr, m) <- suffixes.iterator; + (s, v) <- m.iterator) yield (chr +: s, v)) + + def addOne(kv: (String, A)): this.type = { + withPrefix(kv._1).value = Some(kv._2) + this + } + + def subtractOne(s: String): this.type = { + if (s.isEmpty) { val prev = value; value = None; prev } + else suffixes get (s(0)) flatMap (_.remove(s substring 1)) + this + } + + // Overloading of transformation methods that should return a PrefixMap + def map[B](f: ((String, A)) => (String, B)): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + for (kv <- this) { + b += f(kv) + } + b.result() + } + def flatMap[B](f: ((String, A)) => IterableOnce[(String, B)]): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + for (kv <- this) { + b ++= f(kv) + } + b.result() + } + + // Override `concat` and `empty` methods to refine their return type + override def concat[B >: A](suffix: Iterable[(String, B)]): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + b ++= this + b ++= suffix + b.result() + } + override def empty: PrefixMap[A] = new PrefixMap + + // Members declared in scala.collection.mutable.Clearable + def clear(): Unit = suffixes = immutable.Map.empty + // Members declared in scala.collection.IterableOps + override protected def fromSpecificIterable(coll: Iterable[(String, A)]): PrefixMap[A] = PrefixMap.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(String, A), PrefixMap[A]] = PrefixMap.newBuilder +} + +object PrefixMap { + def empty[A] = new PrefixMap[A] + + def from[A](source: IterableOnce[(String, A)]): PrefixMap[A] = + source match { + case pm: PrefixMap[A] => pm + case _ => (newBuilder ++= source).result() + } + + def apply[A](kvs: (String, A)*): PrefixMap[A] = from(kvs) + + def newBuilder[A]: mutable.Builder[(String, A), PrefixMap[A]] = + new mutable.GrowableBuilder[(String, A), PrefixMap[A]](empty) + + implicit def toFactory[A](self: this.type): Factory[(String, A), PrefixMap[A]] = + new Factory[(String, A), PrefixMap[A]] { + def fromSpecific(it: IterableOnce[(String, A)]): PrefixMap[A] = self.from(it) + def newBuilder: mutable.Builder[(String, A), PrefixMap[A]] = self.newBuilder + } + +} +~~~ + +The previous listing shows the definition of `PrefixMap`. The map has +keys of type `String` and the values are of parametric type `A`. It extends +`mutable.Map[String, A]` and `mutable.MapOps[String, A, mutable.Map, PrefixMap[A]]`. +You have seen this pattern already for sequences in the +RNA strand example; then as now inheriting an implementation class +such as `MapOps` serves to get the right result type for +transformations such as `filter`. + +A prefix map node has two mutable fields: `suffixes` and `value`. The +`value` field contains an optional value that's associated with the +node. It is initialized to `None`. The `suffixes` field contains a map +from characters to `PrefixMap` values. It is initialized to the empty +map. + +You might ask why we picked an immutable map as the implementation +type for `suffixes`? Would not a mutable map have been more standard, +since `PrefixMap` as a whole is also mutable? The answer is that +immutable maps that contain only a few elements are very efficient in +both space and execution time. For instance, maps that contain fewer +than 5 elements are represented as a single object. By contrast, the +standard mutable map is a `HashMap`, which typically occupies around 80 +bytes, even if it is empty. So if small collections are common, it's +better to pick immutable over mutable. In the case of Patricia tries, +we'd expect that most nodes except the ones at the very top of the +tree would contain only a few successors. So storing these successors +in an immutable map is likely to be more efficient. + +Now have a look at the first method that needs to be implemented for a +map: `get`. The algorithm is as follows: To get the value associated +with the empty string in a prefix map, simply select the optional +`value` stored in the root of the tree (the current map). +Otherwise, if the key string is +not empty, try to select the submap corresponding to the first +character of the string. If that yields a map, follow up by looking up +the remainder of the key string after its first character in that +map. If the selection fails, the key is not stored in the map, so +return with `None`. The combined selection over an option value `opt` is +elegantly expressed using `opt.flatMap(x => f(x))`. When applied to an +optional value that is `None`, it returns `None`. Otherwise `opt` is +`Some(x)` and the function `f` is applied to the encapsulated value `x`, +yielding a new option, which is returned by the flatmap. + +The next two methods to implement for a mutable map are `addOne` and `subtractOne`. + +The `subtractOne` method is very similar to `get`, except that before returning +any associated value, the field containing that value is set to +`None`. The `addOne` method first calls `withPrefix` to navigate to the tree +node that needs to be updated, then sets the `value` field of that node +to the given value. The `withPrefix` method navigates through the tree, +creating sub-maps as necessary if some prefix of characters is not yet +contained as a path in the tree. + +The last abstract method to implement for a mutable map is +`iterator`. This method needs to produce an iterator that yields all +key/value pairs stored in the map. For any given prefix map this +iterator is composed of the following parts: First, if the map +contains a defined value, `Some(x)`, in the `value` field at its root, +then `("", x)` is the first element returned from the +iterator. Furthermore, the iterator needs to traverse the iterators of +all submaps stored in the `suffixes` field, but it needs to add a +character in front of every key string returned by those +iterators. More precisely, if `m` is the submap reached from the root +through a character `chr`, and `(s, v)` is an element returned from +`m.iterator`, then the root's iterator will return `(chr +: s, v)` +instead. This logic is implemented quite concisely as a concatenation +of two `for` expressions in the implementation of the `iterator` method in +`PrefixMap`. The first `for` expression iterates over `value.iterator`. This +makes use of the fact that `Option` values define an iterator method +that returns either no element, if the option value is `None`, or +exactly one element `x`, if the option value is `Some(x)`. + +However, in all these cases, to build the right kind of collection +you need to start with an empty collection of that kind. This is +provided by the `empty` method, which is the last method defined in +`PrefixMap`. This method simply returns a fresh `PrefixMap`. + +We'll now turn to the companion object `PrefixMap`. In fact it is not +strictly necessary to define this companion object, as class `PrefixMap` +can stand well on its own. The main purpose of object `PrefixMap` is to +define some convenience factory methods. It also defines an implicit +`Factory` for a better interoperability with other collections. + +The two convenience methods are `empty` and `apply`. The same methods are +present for all other collections in Scala's collection framework so +it makes sense to define them here, too. With the two methods, you can +write `PrefixMap` literals like you do for any other collection: + + scala> PrefixMap("hello" -> 5, "hi" -> 2) + res0: PrefixMap[Int] = PrefixMap(hello -> 5, hi -> 2) + + scala> res0 += "foo" -> 3 + res1: res0.type = PrefixMap(hello -> 5, hi -> 2, foo -> 3) + +## Summary ## + +To summarize, if you want to fully integrate a new collection class +into the framework you need to pay attention to the following points: + +1. Decide whether the collection should be mutable or immutable. +2. Pick the right base traits for the collection. +3. Inherit from the right implementation trait to implement most + collection operations. + +You have now seen how Scala's collections are built and how you can +add new kinds of collections. Because of Scala's rich support for +abstraction, each new collection type has a large number of +methods without having to reimplement them all over again. + +### Acknowledgement ### + +These pages contain material adapted from the 2nd edition of +[Programming in Scala](http://www.artima.com/shop/programming_in_scala) by +Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its +publication. diff --git a/resources/images/collections-architecture.svg b/resources/images/collections-architecture.svg new file mode 100644 index 0000000000..f9abbe1ad4 --- /dev/null +++ b/resources/images/collections-architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file From 502befdde17293349507cb45245e1b5dd6b4b17e Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 May 2018 12:02:37 +0200 Subject: [PATCH 0206/3174] Address reviewers feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Start by listing the challenges addressed by the collections framework, - Fix the markdown syntax used for tables so that they can be rendered by GitHub, - Mention that custom collections can be mutables or immutables, - Add an appendix listing the transformation operations that are candidates to be overloaded to support the “same result type” principle, - Add an appendix showing how to cross-build custom collection implementations with sbt. --- .../architecture-of-scala-213-collections.md | 100 +++++++++++++++--- 1 file changed, 83 insertions(+), 17 deletions(-) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index 3b5f6c350b..4bab504c04 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -29,10 +29,29 @@ possible. (Ideally, everything should be defined in one place only, but there are a few exceptions where things needed to be redefined.) The design approach was to implement most operations in collection "templates" that can be flexibly inherited from individual base -classes and implementations. The following pages explain these -templates and other classes and traits that constitute the "building -blocks" of the framework, as well as the construction principles they -support. +classes and implementations. + +More precisely, these templates address the following challenges: + +- some transformation operations return the same concrete collection + type (e.g. `filter`, called on a `List[Int]` returns a `List[Int]`), +- some transformation operations return the same concrete collection + type with a different type of elements (e.g. `map`, called on a + `List[Int]`, can return a `List[String]`), +- some collections have a single element type (e.g. `List[A]`), while + some others have two (e.g. `Map[K, V]`), +- some operations on collections return a different concrete collection + depending on the element type. For example, `map` called on a `Map` + returns a `Map` if the mapping function returns a key-value pair, but + otherwise returns an `Iterable`, +- transformation operations on some collections require additional + implicit parameters (e.g. `map` on `SortedSet` takes an implicit + `Ordering`), +- some collections are strict (e.g. `List`), while some others are + non-strict (e.g. `View` and `LazyList`). + +The following sections explain how the templates address these +challenges. ## Factoring out common operations ## @@ -210,7 +229,7 @@ In total, we’ve seen that we have four branches of template traits: kind | not sorted | sorted -===========|===============|=============== +-----------|---------------|---------------- `CC[_]` | `IterableOps` | `SortedSetOps` `CC[_, _]` | `MapOps` | `SortedMapOps` @@ -353,12 +372,12 @@ type of elements. The following code shows the relevant parts of `IterableOps` a trait IterableOps[+A, +CC[_], +C] { def iterableFactory: IterableFactory[CC] protected def fromSpecificIterable(coll: Iterable[A]): C - protected def newSpecificBuilder(): Builder[A, C] + protected def newSpecificBuilder: Builder[A, C] } trait IterableFactory[+CC[_]] { def from[A](source: IterableOnce[A]): CC[A] - def newBuilder[A](): Builder[A, CC[A]] + def newBuilder[A]: Builder[A, CC[A]] } ~~~ @@ -379,23 +398,21 @@ types? In the next few sections you’ll be walked through three examples that do this, namely capped sequences, sequences of RNA bases and prefix maps implemented with Patricia tries. -Say you want to create a collection containing *at most* `n` elements: -if more elements are added then the first elements are removed. Such a -collection can be efficiently implemented using an `Array` with a fixed -capacity: random access and element insertion are O(1) operations. +Say you want to create an immutable collection containing *at most* `n` elements: +if more elements are added then the first elements are removed. The first task is to find the supertype of our collection: is it `Seq`, `Set`, `Map` or just `Iterable`? In our case, it is tempting to choose `Seq` because our collection can contain duplicates and iteration order is determined by insertion order. However, some -properties of `Seq` are not satisfied: +properties of [`Seq`](/overviews/collections/seqs.html) are not satisfied: ~~~ scala (xs ++ ys).size == xs.size + ys.size ~~~ Consequently, the only sensible choice as a base collection type -is `Iterable`. +is `collection.immutable.Iterable`. ### First version of `Capped` class ### @@ -688,7 +705,7 @@ To start with the second example, we define the four RNA Bases: val toInt: Base => Int = Map(A -> 0, U -> 1, G -> 2, C -> 3) } -Say you want to create a new sequence type for RNA strands, which are +Say you want to create a new immutable sequence type for RNA strands, which are sequences of bases A (adenine), U (uracil), G (guanine), and C (cytosine). The definitions for bases are easily set up as shown in the listing of RNA bases above. @@ -1087,7 +1104,7 @@ reduced. ## Integrating a new prefix map ## -As a third example you'll learn how to integrate a new kind of map +As a third example you'll learn how to integrate a new kind of mutable map into the collection framework. The idea is to implement a mutable map with `String` as the type of keys by a "Patricia trie". The term *Patricia* is in fact an abbreviation for "Practical Algorithm to @@ -1124,12 +1141,12 @@ define a prefix map with the keys shown in the running example: scala> val m = PrefixMap("abc" -> 0, "abd" -> 1, "al" -> 2, "all" -> 3, "xy" -> 4) - m: PrefixMap[Int] = Map((abc,0), (abd,1), (al,2), (all,3), (xy,4)) + m: PrefixMap[Int] = PrefixMap((abc,0), (abd,1), (al,2), (all,3), (xy,4)) Then calling `withPrefix` on `m` will yield another prefix map: scala> m withPrefix "a" - res14: PrefixMap[Int] = Map((bc,0), (bd,1), (l,2), (ll,3)) + res14: PrefixMap[Int] = PrefixMap((bc,0), (bd,1), (l,2), (ll,3)) ### Patricia trie implementation ### @@ -1334,6 +1351,9 @@ into the framework you need to pay attention to the following points: 2. Pick the right base traits for the collection. 3. Inherit from the right implementation trait to implement most collection operations. +4. Overload desired operations that do not return, by default, a + collection as specific as they could. A complete list of such + operations is given as an appendix. You have now seen how Scala's collections are built and how you can add new kinds of collections. Because of Scala's rich support for @@ -1346,3 +1366,49 @@ These pages contain material adapted from the 2nd edition of [Programming in Scala](http://www.artima.com/shop/programming_in_scala) by Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its publication. + +## Appendix: Methods to overload to support the “same result type” principle ## + +You want to add overloads to specialize a transformation operations such that they return a more specific result. Examples are: +- `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), +- `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), +- `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a +`SortedSet` (instead of a `Set`). + +The following table lists transformation operations that might return a too wide type. You might want to overload +these operations to return a more specific type. + + Collection | Operations +---------------|-------------- +`Iterable` | `map`, `flatMap`, `collect`, `scanLeft`, `scanRight`, `groupMap`, `concat`, `zip`, `zipAll`, `unzip` +`Seq` | `prepended`, `appended`, `prependedAll`, `appendedAll`, `padTo`, `patch` +`immutable.Seq`| `updated` +`SortedSet` | `map`, `flatMap`, `collect`, `zip` +`Map` | `map`, `flatMap`, `collect`, `concat` +`immutable.Map`| `updated`, `transform` +`SortedMap` | `map`, `flatMap`, `collect`, `concat` +`immutable.SortedMap` | `updated` + +## Appendix: Cross-building custom collections ## + +Since the new internal API of the Scala 2.13 collections is very different from the previous +collections API, authors of custom collection types should use separate source directories +(per Scala version) to define them. + +With sbt you can achieve this by adding the following setting to your project: + +~~~ scala +// Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer +// and a `src/main/scala-2.13-` source directory for Scala version older than 2.13 +unmanagedSourceDirectories in Compile += { + val sourceDir = (sourceDirectory in Compile).value + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+" + case _ => sourceDir / "scala-2.13-" + } +} +~~~ + +And then you can define a Scala 2.13 compatible implementation of your collection +in the `src/main/scala-2.13+` source directory, and an implementation for the +previous Scala versions in the `src/main/scala-2.13-` source directory. From 5b76d0e9b40057eca7e5ec673dc188b2f1f1fa50 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 May 2018 13:33:34 +0200 Subject: [PATCH 0207/3174] =?UTF-8?q?Reference=20EPFL=E2=80=99s=20Open=20e?= =?UTF-8?q?dX=20instance=20in=20our=20learning=20resources=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- learn.md | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/learn.md b/learn.md index 36ef71e4fb..adaf2fd4df 100644 --- a/learn.md +++ b/learn.md @@ -10,17 +10,29 @@ 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. -### Coursera courses from EPFL -There are a few interactive resources for trying out Scala, to get a look and feel of the language: - - * [Functional Programming in Scala Specialization](https://www.coursera.org/specializations/scala), free on Coursera. The Specialization provides a hands-on introduction to functional programming using Scala. You can access the courses material and exercises by either signing up for the specialization or auditing the courses individually. The specialization has the following courses. - * [Functional Programming Principles in Scala](https://www.coursera.org/learn/progfun1) - * [Functional Program Design in Scala](https://www.coursera.org/learn/progfun2) - * [Parallel programming](https://www.coursera.org/learn/parprog1) - * [Big Data Analysis with Scala and Spark](https://www.coursera.org/learn/scala-spark-big-data) - * [Functional Programming in Scala Capstone](https://www.coursera.org/learn/scala-capstone) - -Note : There is a paid version available. The only difference between the free and the paid version is that you get a certificate of completion from Coursera on the paid version. You can learn more about coursera certificates in [this help document](https://learner.coursera.help/hc/en-us/articles/209819053-Get-a-Course-Certificate). +### Online Courses from EPFL + +The following courses are available for free. They teach you the main features of the Scala language and introduce you +to functional programming. They are published on both [Coursera](https://www.coursera.org) and an EPFL-hosted Open edX +instance at [courseware.epfl.ch](https://courseware.epfl.ch/). + + * Functional Programming in Scala Specialization (on [Coursera](https://www.coursera.org/specializations/scala)). + The Specialization provides a hands-on introduction to functional programming using Scala. You can access the courses + material and exercises by either signing up for the specialization or auditing the courses individually. The + specialization has the following courses. + * Functional Programming Principles in Scala ([Coursera](https://www.coursera.org/learn/progfun1) and + [Open edX](https://courseware.epfl.ch/courses/course-v1:EPFL+progfun1+2018_T1/about)), + * Functional Program Design in Scala ([Coursera](https://www.coursera.org/learn/progfun2) and + [Open edX](https://courseware.epfl.ch/courses/course-v1:EPFL+progfun2+2018_T1/about)), + * Parallel programming ([Coursera](https://www.coursera.org/learn/parprog1) and + [Open edX](https://courseware.epfl.ch/courses/course-v1:EPFL+parprog1+2018_T1/about)), + * Big Data Analysis with Scala and Spark ([Coursera](https://www.coursera.org/learn/scala-spark-big-data) and + [Open edX](https://courseware.epfl.ch/courses/course-v1:EPFL+scala-spark-big-data+2018-T1/about)), + * Functional Programming in Scala Capstone ([Coursera](https://www.coursera.org/learn/scala-capstone) only). + +Note : On Coursera there is a paid version available. The only difference between the free and the paid version is that +you get a certificate of completion from Coursera on the paid version. You can learn more about coursera certificates in +[this help document](https://learner.coursera.help/hc/en-us/articles/209819053-Get-a-Course-Certificate). ### Dr.Mark C Lewis's Lectures from Trinity University From ae663f137ee4fbb5f018cda99dfa6ef8c92465ce Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 May 2018 13:39:36 +0200 Subject: [PATCH 0208/3174] Add a link to the 'learn.html' page to the navigation header --- _data/doc-nav-header.yml | 2 ++ learn.md | 16 +++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_data/doc-nav-header.yml b/_data/doc-nav-header.yml index e3962dd19e..f7a4ff3ea2 100644 --- a/_data/doc-nav-header.yml +++ b/_data/doc-nav-header.yml @@ -16,6 +16,8 @@ url: "/tour/tour-of-scala.html" - title: Scala for Java Programmers url: "/tutorials/scala-for-java-programmers.html" + - title: Online Resources + url: "/learn.html" - title: Reference url: "#" submenu: diff --git a/learn.md b/learn.md index adaf2fd4df..a2d69833df 100644 --- a/learn.md +++ b/learn.md @@ -1,16 +1,14 @@ --- -title: Learning Resources +title: Online Resources layout: inner-page-no-masthead redirect_from: - /documentation/books.html --- -## Online Learning - -### Quick Online Exercises +## 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. -### Online Courses from EPFL +## Online Courses from EPFL The following courses are available for free. They teach you the main features of the Scala language and introduce you to functional programming. They are published on both [Coursera](https://www.coursera.org) and an EPFL-hosted Open edX @@ -34,7 +32,7 @@ Note : On Coursera there is a paid version available. The only difference betwee you get a certificate of completion from Coursera on the paid version. You can learn more about coursera certificates in [this help document](https://learner.coursera.help/hc/en-us/articles/209819053-Get-a-Course-Certificate). -### Dr.Mark C Lewis's Lectures from Trinity University +## Dr.Mark C Lewis's Lectures from Trinity University * [Dr.Mark C Lewis](http://www.cs.trinity.edu/~mlewis/) from Trinity University, San Antonio, TX, teaches programming courses using the Scala language. Course videos are available in Youtube for free. Some of the courses below. * [Introduction to Programming and Problem Solving Using Scala](https://www.youtube.com/playlist?list=PLLMXbkbDbVt9MIJ9DV4ps-_trOzWtphYO) @@ -43,11 +41,11 @@ you get a certificate of completion from Coursera on the paid version. You can l You can visit his [Youtube channel](https://www.youtube.com/user/DrMarkCLewis/featured) for more videos. -### Try Scala In Your Browser! +## Try Scala In Your Browser! There are a handful of websites where you can interactively run Scala code in your browser! Have a look at [ScalaFiddle](https://scalafiddle.io/) and [Scastie](http://scastie.org/). -### allaboutscala +## allaboutscala [allaboutscala](http://allaboutscala.com/) provides detailed tutorials for beginners. -### ScalaCourses +## ScalaCourses [Independent Courseware](http://getscala.com), online self-study or instructor-led Scala and Play courses for a fee. From 28e564682a8fa0df1964c3f6df0b92f5e883ecec Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 28 May 2018 13:45:50 +0200 Subject: [PATCH 0209/3174] Fix 'Documentation' link in the navigation header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was previously always pointing to the “current” page instead of pointing to the index of the documentation. --- _data/nav-header.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/nav-header.yml b/_data/nav-header.yml index fc7def1c8f..26bd280020 100644 --- a/_data/nav-header.yml +++ b/_data/nav-header.yml @@ -1,5 +1,5 @@ - title: Documentation - url: "" + url: "/" - title: Download url: https://www.scala-lang.org/download/ - title: Community From 5a7567caffab5e0766c01d57bf86035d364376b4 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Tue, 29 May 2018 11:51:50 +0800 Subject: [PATCH 0210/3174] Fix wrong statement --- _overviews/collections/trait-traversable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections/trait-traversable.md b/_overviews/collections/trait-traversable.md index b223cb2cb1..ad749d8097 100644 --- a/_overviews/collections/trait-traversable.md +++ b/_overviews/collections/trait-traversable.md @@ -27,7 +27,7 @@ The `foreach` method is meant to traverse all elements of the collection, and ap * **Map** operations `map`, `flatMap`, and `collect`, which produce a new collection by applying some function to collection elements. * **Conversions** `toArray`, `toList`, `toIterable`, `toSeq`, `toIndexedSeq`, `toStream`, `toSet`, `toMap`, which turn a `Traversable` collection into something more specific. All these conversions return their receiver argument unchanged if the run-time type of the collection already matches the demanded collection type. For instance, applying `toList` to a list will yield the list itself. * **Copying operations** `copyToBuffer` and `copyToArray`. As their names imply, these copy collection elements to a buffer or array, respectively. -* **Size info** operations `isEmpty`, `nonEmpty`, `size`, and `hasDefiniteSize`: Traversable collections can be finite or infinite. An example of an infinite traversable collection is the stream of natural numbers `Stream.from(0)`. The method `hasDefiniteSize` indicates whether a collection is possibly infinite. If `hasDefiniteSize` returns true, the collection is certainly finite. If it returns false, the collection has not been not fully elaborated yet, so it might be infinite or finite. +* **Size info** operations `isEmpty`, `nonEmpty`, `size`, and `hasDefiniteSize`: Traversable collections can be finite or infinite. An example of an infinite traversable collection is the stream of natural numbers `Stream.from(0)`. The method `hasDefiniteSize` indicates whether a collection is possibly infinite. If `hasDefiniteSize` returns true, the collection is certainly finite. If it returns false, the collection has not been fully elaborated yet, so it might be infinite or finite. * **Element retrieval** operations `head`, `last`, `headOption`, `lastOption`, and `find`. These select the first or last element of a collection, or else the first element matching a condition. Note, however, that not all collections have a well-defined meaning of what "first" and "last" means. For instance, a hash set might store elements according to their hash keys, which might change from run to run. In that case, the "first" element of a hash set could also be different for every run of a program. A collection is _ordered_ if it always yields its elements in the same order. Most collections are ordered, but some (_e.g._ hash sets) are not-- dropping the ordering gives a little bit of extra efficiency. Ordering is often essential to give reproducible tests and to help in debugging. That's why Scala collections give ordered alternatives for all collection types. For instance, the ordered alternative for `HashSet` is `LinkedHashSet`. * **Sub-collection retrieval operations** `tail`, `init`, `slice`, `take`, `drop`, `takeWhile`, `dropWhile`, `filter`, `filterNot`, `withFilter`. These all return some sub-collection identified by an index range or some predicate. * **Subdivision operations** `splitAt`, `span`, `partition`, `groupBy`, which split the elements of this collection into several sub-collections. From e6e8be1ab36cc71ccdc221e68b27ca6fd7932274 Mon Sep 17 00:00:00 2001 From: dgruntz Date: Tue, 29 May 2018 13:36:49 +0200 Subject: [PATCH 0211/3174] Fixes minor typo in value-classes.md Changes trait from plural to singular. --- _overviews/core/value-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/core/value-classes.md b/_overviews/core/value-classes.md index ef44e45fa9..6a8a7176e9 100644 --- a/_overviews/core/value-classes.md +++ b/_overviews/core/value-classes.md @@ -22,7 +22,7 @@ The following shows a very minimal value class definition: It has a single, public `val` parameter that is the underlying runtime representation. The type at compile time is `Wrapper`, but at runtime, the representation is an `Int`. -A value class can define `def`s, but no `val`s, `var`s, or nested `traits`s, `class`es or `object`s: +A value class can define `def`s, but no `val`s, `var`s, or nested `trait`s, `class`es or `object`s: class Wrapper(val underlying: Int) extends AnyVal { def foo: Wrapper = new Wrapper(underlying * 19) From 7e9e43a40108702e723d9e60ceac8034741ec7da Mon Sep 17 00:00:00 2001 From: Julien Roubieu Date: Wed, 30 May 2018 16:38:18 -0300 Subject: [PATCH 0212/3174] Fixed _root_ package name Removed duplicated underscores. --- _tour/packages-and-imports.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_tour/packages-and-imports.md b/_tour/packages-and-imports.md index 79e4c2218c..35c9b198b2 100644 --- a/_tour/packages-and-imports.md +++ b/_tour/packages-and-imports.md @@ -73,11 +73,11 @@ def sqrtplus1(x: Int) = { sqrt(x) + 1.0 } ``` -In the event there is a naming conflict and you need to import something from the root of the project, prefix the package name with `__root__`: +In the event there is 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._ +import _root_.users._ ``` From c6d2d86f6325cc6b619abfa87d8c30905a0fdbc1 Mon Sep 17 00:00:00 2001 From: som-snytt Date: Fri, 1 Jun 2018 01:35:12 -0700 Subject: [PATCH 0213/3174] Mini-SIP for case if (#1076) --- _sips/sips/2018-05-26-case-if.md | 95 ++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 _sips/sips/2018-05-26-case-if.md diff --git a/_sips/sips/2018-05-26-case-if.md b/_sips/sips/2018-05-26-case-if.md new file mode 100644 index 0000000000..f246fcfe6c --- /dev/null +++ b/_sips/sips/2018-05-26-case-if.md @@ -0,0 +1,95 @@ +--- +layout: sips +discourse: true +title: SIP-NN - Uncluttering Abuse of Match + +vote-status: new +vote-text: +permalink: /sips/:title.html +redirect_from: /sips/pending/case-if.html + +--- + +**By: Som Snytt and A. P. Marki** + +## History + +| Date | Version | +|---------------|---------------| +| May 26th 2018 | Initial Draft | + +## Motivation + +Since the demise of SIP-12, we have relied on Marie Kondo to declutter +what remains of our lives. But we can do better. + +Currently, `case` syntax requires an underscore to represent a pattern, +even if the code of interest is the guard that follows. + +Anxiety over this underscore is expressed in [a StackOverflow question][1] +in which a programmer mulls the question of "Abuse of Match" and whether +it actually makes you go blind. + +We propose to go underscoreless, pace the famous consultancy. + +If we can't have SIP-12 then we can have tidy syntax for `if-then` in `case` blocks. + +## Syntax + +In lieu of + + 42 match { + case _ if now isAfter midnight => nothingGoodHappens() + } + +we write + + 42 match { + case if now isAfter midnight => nothingGoodHappens() + } + +The syntax accepts either a pattern with optional guard, or a guard with no pattern: + + CaseClause ::= ‘case’ (Pattern [Guard] | Guard) ‘=>’ Block + Guard ::= ‘if’ PostfixExpr + +A guard with no pattern is taken as though the pattern were an underscore, which matches +any value. + +This modest proposal eschews dispensing with the pattern altogether, `case =>`. + +## Further Justifications + +In a respected online [forum][2] which brooks no fools, [Mulliganaceous][3] has posted +an "accepted" answer using the idiom, "in case if". This supports `case if` as +a natural locution. + +In a response to one judgment about abuse of match, [one Scala user][4] whose handle I can +never spell quite right let alone pronounce finds the match version +"clearer and visually more pleasant" than the cluttered `if` expression. + +From the beginning, Scala has made great strides in reducing vertical space in source code. +However, we are still constrained horizontally, despite curved OLED screens. +Recently, [a suggested edit][5] was declined because of maximum line length restrictions. +Every wasted character brings us closer to an unfortunate line break. + +## Implementation + +An implementation is [available][6]. It's pretty slick. + +## References + +1. [Abuse of Match?][1] +2. [Reputation requirements for creating tags and tag synonyms][2] +3. [Mulliganaceous user profile][3] +4. [huynhjl user profile][4] +5. [Sample line length limitation in a Scala project][5] +6. [Implementation][6] + +[1]: https://stackoverflow.com/questions/12556236/abuse-of-match "Abuse of Match?" +[2]: https://meta.stackoverflow.com/a/368537/1296806 "Reputation requirements for creating tags and tag synonyms" +[3]: https://meta.stackoverflow.com/users/8242447/mulliganaceous "Mulliganaceous" +[4]: https://stackoverflow.com/users/257449/huynhjl "huynhjl" +[5]: https://github.com/apache/spark/pull/21369/files#r189794046 "scala-style enforces a max of 100 chars per line" +[6]: https://github.com/scala/scala/pull/6241 "Implementation PR 6241" + From e50f06572a32f23bca0a53c5e6944882e78b9376 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 4 Jun 2018 10:29:44 +0200 Subject: [PATCH 0214/3174] Fix typos --- .../core/architecture-of-scala-213-collections.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index 4bab504c04..5d93592836 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -613,7 +613,7 @@ res4: Capped2[Int] = Capped2(2, 3, 4, 5) This implementation now behaves correctly, but we can still improve a few things. Since our collection is strict, we can take advantage of the better performance offered by -of strict implementations for transformation operations. +strict implementations of transformation operations. ### Final version of `Capped` class ### @@ -1077,7 +1077,7 @@ The final [`RNA` class](#final-version-of-rna-strands-class): operations to take advantage of strict builders, - uses a strict mode for overloads of transformation operations that return an `RNA`, -- has a companion object that extends `SpecificFactory[Base, RNA]`, which makes +- has a companion object that extends `SpecificIterableFactory[Base, RNA]`, which makes it possible to use it as a parameter of a `to` call (to convert any collection of bases to an `RNA`), - moves the `newSpecificBuilder` and `fromSpecificIterable` implementations @@ -1159,8 +1159,8 @@ class PrefixMap[A] with mutable.MapOps[String, A, mutable.Map, PrefixMap[A]] with StrictOptimizedIterableOps[(String, A), mutable.Iterable, PrefixMap[A]] { - var suffixes: immutable.Map[Char, PrefixMap[A]] = immutable.Map.empty - var value: Option[A] = None + private var suffixes: immutable.Map[Char, PrefixMap[A]] = immutable.Map.empty + private var value: Option[A] = None def get(s: String): Option[A] = if (s.isEmpty) value @@ -1369,13 +1369,13 @@ publication. ## Appendix: Methods to overload to support the “same result type” principle ## -You want to add overloads to specialize a transformation operations such that they return a more specific result. Examples are: +You want to add overloads to specialize transformation operations such that they return a more specific result type. Examples are: - `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), - `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), - `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a `SortedSet` (instead of a `Set`). -The following table lists transformation operations that might return a too wide type. You might want to overload +The following table lists transformation operations that might return an undesirably wide type. You might want to overload these operations to return a more specific type. Collection | Operations From 2a69f83a926870867202a48036e0fc05d137a393 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 4 Jun 2018 13:42:01 +0200 Subject: [PATCH 0215/3174] Address lrytz comments --- .../architecture-of-scala-213-collections.md | 83 ++++++++++++------- resources/images/collections-architecture.svg | 2 +- 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index 5d93592836..ff9276ba3c 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -130,7 +130,7 @@ trait IterableOps[+A, +CC[_], +C] { } ~~~ -And then leaf collection types appropriately instantiate the type +Leaf collection types appropriately instantiate the type parameters. For instance, in the case of `List[A]` we want `CC` to be `List` and `C` to be `List[A]`: @@ -177,14 +177,15 @@ def map[K2, V2](f: ((K, V)) => (K2, V2)): Map[K2, V2] def map[B](f: ((K, V)) => B): Iterable[B] ~~~ -At use-site, if you call the `map` operation, the overloading resolution rules -first try the definition that comes from `MapOps` (because `MapOps` is more -specific than `IterableOps`), which returns a `Map`, but if it doesn’t type -check (in case the return type of the function passed to the `map` call is not -a pair), it fallbacks to the definition from `IterableOps`, which returns an -`Iterable`. This is how we follow the “same-result-type” principle: wherever -possible a transformation method on a collection yields a collection of the -same type. +At use-site, when you call the `map` operation, the compiler selects one of +the two overloads. If the function passed as argument to `map` returns a pair, +both functions are applicable. In this case, the version from `MapOps` is used +because it is more specific by the rules of overloading resolution, so the +resulting collection is a `Map`. If the argument function does not return a pair, +only the version defined in `IterableOps` is applicable. In this case, the +resulting collection is an `Iterable`. This is how we follow the +“same-result-type” principle: wherever possible a transformation method on a +collection yields a collection of the same type. In summary, the fact that `Map` collection types take two type parameters makes it impossible to unify their transformation operations with the ones from @@ -405,7 +406,7 @@ The first task is to find the supertype of our collection: is it `Seq`, `Set`, `Map` or just `Iterable`? In our case, it is tempting to choose `Seq` because our collection can contain duplicates and iteration order is determined by insertion order. However, some -properties of [`Seq`](/overviews/collections/seqs.html) are not satisfied: +[properties of `Seq`](/overviews/collections/seqs.html) are not satisfied: ~~~ scala (xs ++ ys).size == xs.size + ys.size @@ -507,8 +508,8 @@ You can see that if we try to grow the collection with more than four elements, the first elements are dropped (see `res4`). The operations behave as expected except for the last one: after calling `take` we get back a `List` instead of the expected `Capped1` collection. This -is because all that was done in class -[`Capped1`](#first-version-of-capped-class) was making `Capped1` extend +is because all that was done in [class +`Capped1`](#first-version-of-capped-class) was making `Capped1` extend `immutable.Iterable`. This class has a `take` method that returns an `immutable.Iterable`, and that’s implemented in terms of `immutable.Iterable`’s default implementation, `List`. So, that’s what @@ -531,6 +532,8 @@ effect, as shown in the next section. ### Second version of `Capped` class ### ~~~ scala +import scala.collection._ + class Capped2[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) extends immutable.Iterable[A] with IterableOps[A, Capped2, Capped2[A]] { self => @@ -554,8 +557,8 @@ class Capped2Factory(capacity: Int) extends IterableFactory[Capped2] { def empty[A]: Capped2[A] = new Capped2[A](capacity) - def newBuilder[A]: Builder[A, Capped2[A]] = - new ImmutableBuilder[A, Capped2[A]](empty) { + def newBuilder[A]: mutable.Builder[A, Capped2[A]] = + new mutable.ImmutableBuilder[A, Capped2[A]](empty) { def addOne(elem: A): this.type = { elems = elems :+ elem; this } } } @@ -618,6 +621,8 @@ strict implementations of transformation operations. ### Final version of `Capped` class ### ~~~ scala +import scala.collection._ + final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) extends immutable.Iterable[A] with IterableOps[A, Capped, Capped[A]] @@ -667,8 +672,8 @@ class CappedFactory(capacity: Int) extends IterableFactory[Capped] { def empty[A]: Capped[A] = new Capped[A](capacity) - def newBuilder[A]: Builder[A, Capped[A]] = - new ImmutableBuilder[A, Capped[A]](empty) { + def newBuilder[A]: mutable.Builder[A, Capped[A]] = + new mutable.ImmutableBuilder[A, Capped[A]](empty) { def addOne(elem: A): this.type = { elems = elems :+ elem; this } } @@ -730,6 +735,7 @@ representation. ### First version of RNA strands class ### + import collection.mutable import collection.immutable.{ IndexedSeq, IndexedSeqOps } final class RNA1 private ( @@ -748,7 +754,7 @@ representation. override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 = fromSeq(coll.toSeq) - override protected def newSpecificBuilder: Builder[Base, RNA1] = + override protected def newSpecificBuilder: mutable.Builder[Base, RNA1] = iterableFactory.newBuilder[Base].mapResult(fromSeq) } @@ -763,7 +769,7 @@ representation. // Bitmask to isolate a group private val M = (1 << S) - 1 - def fromSeq(buf: Seq[Base]): RNA1 = { + def fromSeq(buf: collection.Seq[Base]): RNA1 = { val groups = new Array[Int]((buf.length + N - 1) / N) for (i <- 0 until buf.length) groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) @@ -920,6 +926,9 @@ this is why we always get a `Vector` as a result. ### Second version of RNA strands class ### + import scala.collection.{ View, mutable } + import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } + final class RNA2 private (val groups: Array[Int], val length: Int) extends IndexedSeq[Base] with IndexedSeqOps[Base, IndexedSeq, RNA2] { @@ -927,7 +936,7 @@ this is why we always get a `Vector` as a result. def apply(idx: Int): Base = // as before override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before - override protected def newSpecificBuilder: Builder[Base, RNA2] = // as before + override protected def newSpecificBuilder: mutable.Builder[Base, RNA2] = // as before // Overloading of `appended`, `prepended`, `appendedAll`, // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2` @@ -975,6 +984,9 @@ scala> bases.to(RNA2) ### Final version of RNA strands class ### ~~~ scala +import scala.collection.{ AbstractIterator, SpecificIterableFactory, StrictOptimizedSeqOps, View, mutable } +import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } + final class RNA private ( val groups: Array[Int], val length: Int @@ -995,16 +1007,16 @@ final class RNA private ( // `newSpecificBuilder`, from `IterableOps` override protected def fromSpecificIterable(coll: Iterable[Base]): RNA = RNA.fromSpecific(coll) - override protected def newSpecificBuilder: Builder[Base, RNA] = + override protected def newSpecificBuilder: mutable.Builder[Base, RNA] = RNA.newBuilder // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`, // `map`, `flatMap` and `concat` to return an `RNA` when possible - def appended(base: Base): RNA = + def appended(base: Base): RNA = (newSpecificBuilder ++= this += base).result() def appendedAll(suffix: Iterable[Base]): RNA = (newSpecificBuilder ++= this ++= suffix).result() - def prepended(base: Base): RNA = + def prepended(base: Base): RNA = (newSpecificBuilder += base ++= this).result() def prependedAll(prefix: Iterable[Base]): RNA = (newSpecificBuilder ++= prefix ++= this).result() @@ -1050,7 +1062,7 @@ object RNA extends SpecificIterableFactory[Base, RNA] { private val M = (1 << S) - 1 // bitmask to isolate a group private val N = 32 / S // number of groups in an Int - def fromSeq(buf: Seq[Base]): RNA = { + def fromSeq(buf: collection.Seq[Base]): RNA = { val groups = new Array[Int]((buf.length + N - 1) / N) for (i <- 0 until buf.length) groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) @@ -1061,12 +1073,12 @@ object RNA extends SpecificIterableFactory[Base, RNA] { // and `fromSpecific` def empty: RNA = fromSeq(Seq.empty) - def newBuilder(): Builder[Base, RNA] = - ArrayBuffer.newBuilder[Base]().mapResult(fromSeq) + def newBuilder: mutable.Builder[Base, RNA] = + mutable.ArrayBuffer.newBuilder[Base].mapResult(fromSeq) def fromSpecific(it: IterableOnce[Base]): RNA = it match { - case seq: Seq[Base] => fromSeq(seq) - case _ => fromSeq(ArrayBuffer.from(it)) + case seq: collection.Seq[Base] => fromSeq(seq) + case _ => fromSeq(mutable.ArrayBuffer.from(it)) } } ~~~ @@ -1079,7 +1091,7 @@ The final [`RNA` class](#final-version-of-rna-strands-class): an `RNA`, - has a companion object that extends `SpecificIterableFactory[Base, RNA]`, which makes it possible to use it as a parameter of a `to` call (to convert any collection - of bases to an `RNA`), + of bases to an `RNA`, e.g. `List(U, A, G, C).to(RNA)`), - moves the `newSpecificBuilder` and `fromSpecificIterable` implementations to the companion object. @@ -1329,7 +1341,12 @@ We'll now turn to the companion object `PrefixMap`. In fact it is not strictly necessary to define this companion object, as class `PrefixMap` can stand well on its own. The main purpose of object `PrefixMap` is to define some convenience factory methods. It also defines an implicit -`Factory` for a better interoperability with other collections. +conversion to `Factory` for a better interoperability with other +collections. This conversion is triggered when one writes, for instance, +`List("foo" -> 3).to(PrefixMap)`. The `to` operation takes a `Factory` +as parameter but the `PrefixMap` companion object does not extend `Factory` (and it +can not because a `Factory` fixes the type of collection elements, +whereas `PrefixMap` has a polymorphic type of values). The two convenience methods are `empty` and `apply`. The same methods are present for all other collections in Scala's collection framework so @@ -1375,6 +1392,10 @@ You want to add overloads to specialize transformation operations such that they - `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a `SortedSet` (instead of a `Set`). +Typically, this happens when the collection fixes some type parameter of its template trait. For instance in +the case of the `RNA` collection type, we fix the element type to `Base`, and in the case of the `PrefixMap[A]` +collection type, we fix the type of keys to `String`. + The following table lists transformation operations that might return an undesirably wide type. You might want to overload these operations to return a more specific type. @@ -1412,3 +1433,7 @@ unmanagedSourceDirectories in Compile += { And then you can define a Scala 2.13 compatible implementation of your collection in the `src/main/scala-2.13+` source directory, and an implementation for the previous Scala versions in the `src/main/scala-2.13-` source directory. + +You can see how this has been put in practice in +[scalacheck](https://github.com/rickynils/scalacheck/pull/411) and +[scalaz](https://github.com/scalaz/scalaz/pull/1730). diff --git a/resources/images/collections-architecture.svg b/resources/images/collections-architecture.svg index f9abbe1ad4..844a3655fc 100644 --- a/resources/images/collections-architecture.svg +++ b/resources/images/collections-architecture.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 656809217dc809e80717409cbe5eaa80f14b4fa3 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 4 Jun 2018 16:47:35 +0200 Subject: [PATCH 0216/3174] Add a paragraph about views --- .../core/architecture-of-scala-213-collections.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index ff9276ba3c..be8eab1a2a 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -255,6 +255,21 @@ these implementations. For instance, we want the default `map` implementation to be non-strict when inherited by a `View`, and strict when inherited by a `List`. +To achieve that, operations are, by default, implemented in terms of a +non-strict `View`. For the record, a `View` “describes” an operation applied +to a collection but does not evaluate its result until the `View` is +effectively traversed. Here is the (simplified) definition of `View`: + +~~~ scala +trait View[+A] extends Iterable[A] with IterableOps[A, View, View[A]] { + def iterator: Iterator[A] +} +~~~ + +A `View` is an `Iterable` that has only one abstract method returning +an `Iterator` for traversing its elements. The `View` elements are +evaluated only when its `Iterator` is traversed. + ### Operations implementation ### Now that we are more familiar with the hierarchy of the template traits, we can have From fb3881b3332bd5338d7e371f6a77545e741c7107 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 5 Jun 2018 10:59:03 +0200 Subject: [PATCH 0217/3174] Split in two pages --- _data/overviews.yml | 9 +- .../architecture-of-scala-213-collections.md | 1080 +---------------- _overviews/core/custom-collections.md | 1059 ++++++++++++++++ 3 files changed, 1094 insertions(+), 1054 deletions(-) create mode 100644 _overviews/core/custom-collections.md diff --git a/_data/overviews.yml b/_data/overviews.yml index 9eddbfd0d9..c89891ee18 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -43,10 +43,15 @@ by: Martin Odersky and Lex Spoon description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - title: The Architecture of Scala 2.13’s Collections - icon: building + icon: sitemap url: "core/architecture-of-scala-213-collections.html" + by: Julien Richard-Foy + description: "These pages describe the architecture of the collections framework introduced in Scala 2.13. Compared to the Collections API you will find out more about the internal workings of the framework." + - title: Custom Collection Types + icon: building + url: "core/custom-collections.html" by: Martin Odersky, Lex Spoon and Julien Richard-Foy - description: "These pages describe the architecture of the collections framework introduced in Scala 2.13. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." + description: "In this document you will learn how the collections framework helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - category: Language description: "Guides and overviews covering features in the Scala language." diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index be8eab1a2a..5144b83f45 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -5,9 +5,9 @@ title: The Architecture of Scala 2.13’s Collections permalink: /overviews/core/:title.html --- -**Martin Odersky, Lex Spoon and Julien Richard-Foy** +**Julien Richard-Foy** -These pages describe the architecture of the Scala collections +This document describes the architecture of the Scala collections framework in detail. Compared to [the Collections Introduction]({{ site.baseurl }}/overviews/collections/introduction.html) you will find out more about the internal workings of the framework. You @@ -105,7 +105,7 @@ collection type constructor, and operations that keep the same elements type (`filter`, `take`, `drop`, etc.) need to abstract over the resulting collection type. -### Abstracting over collection types ### +## Abstracting over collection types ## The template trait `IterableOps` implements the operations available on the `Iterable[A]` collection type. @@ -139,7 +139,7 @@ trait List[+A] extends Iterable[A] with IterableOps[A, List, List[A]] ~~~ -### Four branches of templates traits ### +## Four branches of templates traits ## The astute reader might have noticed that the given type signature for the `map` operation doesn’t work with `Map` collections because @@ -240,7 +240,7 @@ Here is a diagram illustrating the architecture: Template traits are in grey whereas collection types are in white. -### Strict and non-strict collections ### +## Strict and non-strict collections ## Another difference that has been taken into account in the design of the collections framework is the fact that some collection types eagerly @@ -270,7 +270,7 @@ A `View` is an `Iterable` that has only one abstract method returning an `Iterator` for traversing its elements. The `View` elements are evaluated only when its `Iterator` is traversed. -### Operations implementation ### +## Operations implementation ## Now that we are more familiar with the hierarchy of the template traits, we can have a look at the actual implementation of some operations. Consider for instance the @@ -351,7 +351,7 @@ trait MapFactory[+CC[_, _]] { } ~~~ -### When a strict evaluation is preferable (or unavoidable) ### +## When a strict evaluation is preferable (or unavoidable) ## In the previous sections we explained that the “strictness” of concrete collections should be preserved by default operation implementations. However in some cases this @@ -399,1056 +399,32 @@ trait IterableFactory[+CC[_]] { Note that, in general, an operation that doesn’t *have to* be strict should be implemented in a non-strict mode, otherwise it would lead to surprising -behaviour when used on a non-strict concrete collection. That being said, +behaviour when used on a non-strict concrete collection (you can read more +about that statement in +[this article](https://www.scala-lang.org/blog/2017/11/28/view-based-collections.html)). +That being said, the strict mode is often more efficient. This is why we provide template traits whose operation implementations have been overridden to take advantage of strict builders. The name of these template traits always starts with `StrictOptimized`. You should use such a template trait for your custom collection if it is a strict collection. -## Integrating a new collection: capped sequence ## - -What needs to be done if you want to integrate a new collection class, -so that it can profit from all predefined operations with the right -types? In the next few sections you’ll be walked through three examples -that do this, namely capped sequences, sequences of RNA -bases and prefix maps implemented with Patricia tries. - -Say you want to create an immutable collection containing *at most* `n` elements: -if more elements are added then the first elements are removed. - -The first task is to find the supertype of our collection: is it -`Seq`, `Set`, `Map` or just `Iterable`? In our case, it is tempting -to choose `Seq` because our collection can contain duplicates and -iteration order is determined by insertion order. However, some -[properties of `Seq`](/overviews/collections/seqs.html) are not satisfied: - -~~~ scala -(xs ++ ys).size == xs.size + ys.size -~~~ - -Consequently, the only sensible choice as a base collection type -is `collection.immutable.Iterable`. - -### First version of `Capped` class ### - -~~~ scala -import scala.collection._ - -class Capped1[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) - extends immutable.Iterable[A] { self => - - def this(capacity: Int) = - this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) - - def appended[B >: A](elem: B): Capped1[B] = { - val newElems = Array.ofDim[Any](capacity) - Array.copy(elems, 0, newElems, 0, capacity) - val (newOffset, newLength) = - if (length == capacity) { - newElems(offset) = elem - ((offset + 1) % capacity, length) - } else { - newElems(length) = elem - (offset, length + 1) - } - new Capped1[B](capacity, newLength, newOffset, newElems) - } - - @`inline` def :+ [B >: A](elem: B): Capped1[B] = appended(elem) - - def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] - - def iterator: Iterator[A] = new AbstractIterator[A] { - private var current = 0 - def hasNext = current < self.length - def next(): A = { - val elem = self(current) - current += 1 - elem - } - } - -} -~~~ - -The above listing presents the first version of our capped collection -implementation. It will be refined later. The class `Capped1` has a -private constructor that takes the collection capacity, length, -offset (first element index) and the underlying array as parameters. -The public constructor takes only the capacity of the collection. It -sets the length and offset to 0, and uses an empty array of elements. - -The `appended` method defines how elements can be appended to a given -`Capped1` collection: it creates a new underlying array of elements, -copies the current elements and adds the new element. As long as the -number of elements does not exceed the `capacity`, the new element -is appended after the previous elements. However, as soon as the -maximal capacity has been reached, the new element replaces the first -element of the collection (at `offset` index). - -The `apply` method implements indexed access: it translates the given -index into its corresponding index in the underlying array by adding -the `offset`. - -These two methods, `appended` and `apply`, implement the specific -behavior of the `Capped1` collection type. In addition to them, we have -to implement `iterator` to make the generic collection operations -(such as `foldLeft`, `count`, etc.) work on `Capped` collections. -Here we implement it by using indexed access. - -Here are some interactions with the `Capped1` collection: - -~~~ scala -scala> new Capped1(capacity = 4) -res0: Capped1[Nothing] = Capped1() - -scala> res0 :+ 1 :+ 2 :+ 3 -res1: Capped1[Int] = Capped1(1, 2, 3) - -scala> res1.length -res2: Int = 3 - -scala> res1.lastOption -res3: Option[Int] = Some(3) - -scala> res1 :+ 4 :+ 5 :+ 6 -res4: Capped1[Int] = Capped1(3, 4, 5, 6) - -scala> res4.take(3) -res5: collection.immutable.Iterable[Int] = List(3, 4, 5) -~~~ - -You can see that if we try to grow the collection with more than four -elements, the first elements are dropped (see `res4`). The operations -behave as expected except for the last one: after calling `take` we -get back a `List` instead of the expected `Capped1` collection. This -is because all that was done in [class -`Capped1`](#first-version-of-capped-class) was making `Capped1` extend -`immutable.Iterable`. This class has a `take` method -that returns an `immutable.Iterable`, and that’s implemented in terms of -`immutable.Iterable`’s default implementation, `List`. So, that’s what -you were seeing on the last line of the previous interaction. - -Now that you understand why things are the way they are, the next -question should be what needs to be done to change them? One way to do -this would be to override the `take` method in class `Capped1`, maybe like -this: - - def take(count: Int): Capped1 = … - -This would do the job for `take`. But what about `drop`, or `filter`, or -`init`? In fact there are over fifty methods on collections that return -again a collection. For consistency, all of these would have to be -overridden. This looks less and less like an attractive -option. Fortunately, there is a much easier way to achieve the same -effect, as shown in the next section. - -### Second version of `Capped` class ### - -~~~ scala -import scala.collection._ - -class Capped2[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) - extends immutable.Iterable[A] - with IterableOps[A, Capped2, Capped2[A]] { self => - - def this(capacity: Int) = // as before - - def appended[B >: A](elem: B): Capped2[B] = // as before - @`inline` def :+ [B >: A](elem: B): Capped2[B] = // as before - def apply(i: Int): A = // as before - - def iterator: Iterator[A] = // as before - - override val iterableFactory: IterableFactory[Capped2] = new Capped2Factory(capacity) - -} - -class Capped2Factory(capacity: Int) extends IterableFactory[Capped2] { - - def from[A](source: IterableOnce[A]): Capped2[A] = - (newBuilder[A] ++= source).result() - - def empty[A]: Capped2[A] = new Capped2[A](capacity) - - def newBuilder[A]: mutable.Builder[A, Capped2[A]] = - new mutable.ImmutableBuilder[A, Capped2[A]](empty) { - def addOne(elem: A): this.type = { elems = elems :+ elem; this } - } -} -~~~ - -The Capped class needs to inherit not only from `Iterable`, but also -from its implementation trait `IterableOps`. This is shown in the -above listing of class `Capped2`. The new implementation differs -from the previous one in only two aspects. First, class `Capped2` -now also extends `IterableOps[A, Capped2, Capped2[A]]`. Second, -its `iterableFactory` member is overridden to return an -`IterableFactory[Capped2]`. As explained in the -previous sections, the `IterableOps` trait implements all concrete -methods of `Iterable` in a generic way. For instance, the -return type of methods like `take`, `drop`, `filter` or `init` -is the third type parameter passed to class `IterableOps`, i.e., -in class `Capped2`, it is `Capped2[A]`. Similarly, the return -type of methods like `map`, `flatMap` or `concat` is defined -by the second type parameter passed to class `IterableOps`, -i.e., in class `Capped2`, it is `Capped2` itself. - -To construct a `Capped2`, the `fromSpecificIterable` and -`newSpecificBuilder` implementations inherited from `immutable.Iterable` -delegate to the `iterableFactory` member, which is overridden here to -return an instance of `Capped2Factory`. This class -provides convenient factory methods to build collections. Eventually, -these methods delegate to `empty`, which builds an empty `Capped2` -instance, and `newBuilder`, which uses the `appended` operation -to grow a `Capped2` collection. - -With the refined implementation of the [`Capped2` class](#second-version-of-capped-class), -the transformation operations work now as expected, and the -`Capped2Factory` class provides seamless conversions from other collections: - -~~~ scala -scala> object Capped extends Capped2Factory(capacity = 4) -defined object Capped - -scala> Capped(1, 2, 3) -res0: Capped2[Int] = Capped2(1, 2, 3) - -scala> res0.take(2) -res1: Capped2[Int] = Capped2(1, 2) - -scala> res0.filter(x => x % 2 == 1) -res2: Capped2[Int] = Capped2(1, 3) - -scala> res0.map(x => x * x) -res3: Capped2[Int] = Capped2(1, 4, 9) - -scala> List(1, 2, 3, 4, 5).to(Capped) -res4: Capped2[Int] = Capped2(2, 3, 4, 5) -~~~ - -This implementation now behaves correctly, but we can still improve -a few things. Since our collection is strict, we can take advantage -of the better performance offered by -strict implementations of transformation operations. - -### Final version of `Capped` class ### - -~~~ scala -import scala.collection._ - -final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) - extends immutable.Iterable[A] - with IterableOps[A, Capped, Capped[A]] - with StrictOptimizedIterableOps[A, Capped, Capped[A]] { self => - - def this(capacity: Int) = - this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) - - def appended[B >: A](elem: B): Capped[B] = { - val newElems = Array.ofDim[Any](capacity) - Array.copy(elems, 0, newElems, 0, capacity) - val (newOffset, newLength) = - if (length == capacity) { - newElems(offset) = elem - ((offset + 1) % capacity, length) - } else { - newElems(length) = elem - (offset, length + 1) - } - new Capped[B](capacity, newLength, newOffset, newElems) - } - - @`inline` def :+ [B >: A](elem: B): Capped[B] = appended(elem) - - def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] - - def iterator: Iterator[A] = view.iterator - - override def view: IndexedSeqView[A] = new IndexedSeqView[A] { - def length: Int = self.length - def apply(i: Int): A = self(i) - } - - override def knownSize: Int = length - - override val iterableFactory: IterableFactory[Capped] = new CappedFactory(capacity) - -} - -class CappedFactory(capacity: Int) extends IterableFactory[Capped] { - - def from[A](source: IterableOnce[A]): Capped[A] = - source match { - case capped: Capped[A] if capped.capacity == capacity => capped - case _ => (newBuilder[A] ++= source).result() - } - - def empty[A]: Capped[A] = new Capped[A](capacity) - - def newBuilder[A]: mutable.Builder[A, Capped[A]] = - new mutable.ImmutableBuilder[A, Capped[A]](empty) { - def addOne(elem: A): this.type = { elems = elems :+ elem; this } - } - -} -~~~ - -That is it. The final [`Capped` class](#final-version-of-capped-class): - -- extends the `StrictOptimizedIterableOps` trait, which overrides all - transformation operations to take advantage of strict builders, -- overrides a few operations for performance: the `view` now uses - indexed access, and the `iterator` delegates to the view. The - `knownSize` operation is also overridden because the size is always - known. - -Its implementation requires a little bit of protocol. In essence, you -have to inherit from the `Ops` template trait in addition to just -inheriting from a collection type, override the `iterableFactory` -member to return a more specific factory, and finally implement abstract -methods (such as `iterator` in our case), if any. - -## Integrating a new collection: RNA sequences ## - -To start with the second example, we define the four RNA Bases: - - abstract class Base - case object A extends Base - case object U extends Base - case object G extends Base - case object C extends Base - - object Base { - val fromInt: Int => Base = Array(A, U, G, C) - val toInt: Base => Int = Map(A -> 0, U -> 1, G -> 2, C -> 3) - } - -Say you want to create a new immutable sequence type for RNA strands, which are -sequences of bases A (adenine), U (uracil), G (guanine), and C -(cytosine). The definitions for bases are easily set up as shown in the -listing of RNA bases above. - -Every base is defined as a case object that inherits from a common -abstract class `Base`. The `Base` class has a companion object that -defines two functions that map between bases and the integers 0 to 3. -You can see in the examples two different ways to use collections -to implement these functions. The `toInt` function is implemented as a -`Map` from `Base` values to integers. The reverse function, `fromInt`, is -implemented as an array. This makes use of the fact that both maps and -arrays *are* functions because they inherit from the `Function1` trait. - -The next task is to define a class for strands of RNA. Conceptually, a -strand of RNA is simply a `Seq[Base]`. However, RNA strands can get -quite long, so it makes sense to invest some work in a compact -representation. Because there are only four bases, a base can be -identified with two bits, and you can therefore store sixteen bases as -two-bit values in an integer. The idea, then, is to construct a -specialized subclass of `Seq[Base]`, which uses this packed -representation. - -### First version of RNA strands class ### - - import collection.mutable - import collection.immutable.{ IndexedSeq, IndexedSeqOps } - - final class RNA1 private ( - val groups: Array[Int], - val length: Int - ) extends IndexedSeq[Base] - with IndexedSeqOps[Base, IndexedSeq, RNA1] { - - import RNA1._ - - def apply(idx: Int): Base = { - if (idx < 0 || length <= idx) - throw new IndexOutOfBoundsException - Base.fromInt(groups(idx / N) >> (idx % N * S) & M) - } - - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 = - fromSeq(coll.toSeq) - override protected def newSpecificBuilder: mutable.Builder[Base, RNA1] = - iterableFactory.newBuilder[Base].mapResult(fromSeq) - } - - object RNA1 { - - // Number of bits necessary to represent group - private val S = 2 - - // Number of groups that fit in an Int - private val N = 32 / S - - // Bitmask to isolate a group - private val M = (1 << S) - 1 - - def fromSeq(buf: collection.Seq[Base]): RNA1 = { - val groups = new Array[Int]((buf.length + N - 1) / N) - for (i <- 0 until buf.length) - groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) - new RNA1(groups, buf.length) - } - - def apply(bases: Base*) = fromSeq(bases) - } - -The [RNA strands class listing](#first-version-of-rna-strands-class) above -presents the first version of this -class. The class `RNA1` has a constructor that -takes an array of `Int`s as its first argument. This array contains the -packed RNA data, with sixteen bases in each element, except for the -last array element, which might be partially filled. The second -argument, `length`, specifies the total number of bases on the array -(and in the sequence). Class `RNA1` extends `IndexedSeq[Base]` and -`IndexedSeqOps[Base, IndexedSeq, RNA1]`. These traits define the following -abstract methods: - -- `length`, automatically implemented by defining a parametric field of - the same name, -- `apply` (indexing method), implemented by first extracting an integer value - from the `groups` array, then extracting the correct two-bit number from that - integer using right shift (`>>`) and mask (`&`). The private constants `S`, - `N`, and `M` come from the `RNA1` companion object. `S` specifies the size of - each packet (i.e., two); `N` specifies the number of two-bit packets per - integer; and `M` is a bit mask that isolates the lowest `S` bits in a - word. - -We also override the following members used by transformation operations -such as `filter` and `take`: - -- `fromSpecificIterable`, implemented by the `fromSeq` method of the `RNA1` - companion object, -- `newSpecificBuilder`, implemented by using the default `IndexedSeq` builder - and transforming its result into an `RNA1` with the `mapResult` method. - -Note that the constructor of class `RNA1` is `private`. This means that -clients cannot create `RNA1` sequences by calling `new`, which makes -sense, because it hides the representation of `RNA1` sequences in terms -of packed arrays from the user. If clients cannot see what the -representation details of RNA sequences are, it becomes possible to -change these representation details at any point in the future without -affecting client code. In other words, this design achieves a good -decoupling of the interface of RNA sequences and its -implementation. However, if constructing an RNA sequence with `new` is -impossible, there must be some other way to create new RNA sequences, -else the whole class would be rather useless. In fact there are two -alternatives for RNA sequence creation, both provided by the `RNA1` -companion object. The first way is method `fromSeq`, which converts a -given sequence of bases (i.e., a value of type `Seq[Base]`) into an -instance of class `RNA1`. The `fromSeq` method does this by packing all -the bases contained in its argument sequence into an array, then -calling `RNA1`'s private constructor with that array and the length of -the original sequence as arguments. This makes use of the fact that a -private constructor of a class is visible in the class's companion -object. - -The second way to create an `RNA1` value is provided by the `apply` method -in the `RNA1` object. It takes a variable number of `Base` arguments and -simply forwards them as a sequence to `fromSeq`. Here are the two -creation schemes in action: - - scala> val xs = List(A, G, U, A) - xs: List[Base] = List(A, G, U, A) - - scala> RNA1.fromSeq(xs) - res1: RNA1 = RNA1(A, G, U, A) - - scala> val rna1 = RNA1(A, U, G, G, C) - rna1: RNA1 = RNA1(A, U, G, G, C) - -Also note that the type parameters of the `IndexedSeqOps` trait that -we inherit from are: `Base`, `IndexedSeq` and `RNA1`. The first one -stands for the type of elements, the second one stands for the -type constructor used by transformation operations that return -a collection with a different type of elements, and the third one -stands for the type used by transformation operations that return -a collection with the same type of elements. In our case, it is -worth noting that the second one is `IndexedSeq` whereas the -third one is `RNA1`. This means that operations like `map` or -`flatMap` return an `IndexedSeq`, whereas operations like `take` or -`filter` return an `RNA1`. - -Here is an example showing the usage of `take` and `filter`: - - scala> rna1.take(3) - res5: RNA1 = RNA1(A, U, G) - - scala> rna1.filter(_ != U) - res6: RNA1 = RNA1(A, G, G, C) - -### Dealing with map and friends ### - -However, transformation operations that return a collection with a -different element type always return an `IndexedSeq`. - -How should these -methods be adapted to RNA strands? The desired behavior would be to get -back an RNA strand when mapping bases to bases or appending two RNA strands -with `++`: - - scala> val rna = RNA(A, U, G, G, C) - rna: RNA = RNA(A, U, G, G, C) - - scala> rna map { case A => U case b => b } - res7: RNA = RNA(U, U, G, G, C) - - scala> rna ++ rna - res8: RNA = RNA(A, U, G, G, C, A, U, G, G, C) - -On the other hand, mapping bases to some other type over an RNA strand -cannot yield another RNA strand because the new elements have the -wrong type. It has to yield a sequence instead. In the same vein -appending elements that are not of type `Base` to an RNA strand can -yield a general sequence, but it cannot yield another RNA strand. - - scala> rna map Base.toInt - res2: IndexedSeq[Int] = Vector(0, 1, 2, 2, 3) - - scala> rna ++ List("missing", "data") - res3: IndexedSeq[java.lang.Object] = - Vector(A, U, G, G, C, missing, data) - -This is what you'd expect in the ideal case. But this is not what the -[`RNA1` class](#first-version-of-rna-strands-class) provides. In fact, all -examples will return instances of `Vector`, not just the last two. If you run -the first three commands above with instances of this class you obtain: - - scala> val rna1 = RNA1(A, U, G, G, C) - rna1: RNA1 = RNA1(A, U, G, G, C) - - scala> rna1 map { case A => U case b => b } - res0: IndexedSeq[Base] = Vector(U, U, G, G, C) - - scala> rna1 ++ rna1 - res1: IndexedSeq[Base] = Vector(A, U, G, G, C, A, U, G, G, C) - -So the result of `map` and `++` is never an RNA strand, even if the -element type of the generated collection is `Base`. To see how to do -better, it pays to have a close look at the signature of the `map` -method (or of `++`, which has a similar signature). The `map` method is -originally defined in class `scala.collection.IterableOps` with the -following signature: - - def map[B](f: A => B): CC[B] - -Here `A` is the type of elements of the collection, and `CC` is the type -constructor passed as a second parameter to the `IterableOps` trait. - -In our `RNA1` implementation, this `CC` type constructor is `IndexedSeq`, -this is why we always get a `Vector` as a result. - -### Second version of RNA strands class ### - - import scala.collection.{ View, mutable } - import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } - - final class RNA2 private (val groups: Array[Int], val length: Int) - extends IndexedSeq[Base] with IndexedSeqOps[Base, IndexedSeq, RNA2] { - - import RNA2._ - - def apply(idx: Int): Base = // as before - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before - override protected def newSpecificBuilder: mutable.Builder[Base, RNA2] = // as before - - // Overloading of `appended`, `prepended`, `appendedAll`, - // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2` - // when possible - def appended(base: Base): RNA2 = - fromSpecificIterable(new View.Append(this, base)) - def appendedAll(suffix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(this, suffix)) - def prepended(base: Base): RNA2 = - fromSpecificIterable(new View.Prepend(base, this)) - def prependedAll(prefix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(prefix, this)) - def map(f: Base => Base): RNA2 = - fromSpecificIterable(new View.Map(this, f)) - def flatMap(f: Base => IterableOnce[Base]): RNA2 = - fromSpecificIterable(new View.FlatMap(this, f)) - def concat(suffix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(this, suffix)) - } - -To address this shortcoming, you need to overload the methods that -return an `IndexedSeq[B]` for the case where `B` is known to be `Base`, -to return an `RNA2` instead. - -Compared to [class `RNA1`](#first-version-of-rna-strands-class) -we added overloads for methods `appended`, `appendedAll`, `prepended`, -`prependedAll`, `map` and `flatMap`. - -This implementation now behaves correctly, but we can still improve a few things. Since our -collection is strict, we could take advantage of the better performance offered by strict builders -in transformation operations. -Also, if we try to convert an `Iterable[Base]` into an `RNA2` it fails: - -~~~ -scala> val bases: Iterable[Base] = List(A, U, C, C) -bases: Iterable[Base] = List(A, U, C, C) - -scala> bases.to(RNA2) - ^ - error: type mismatch; - found : RNA2.type - required: scala.collection.Factory[Base,?] -~~~ - -### Final version of RNA strands class ### - -~~~ scala -import scala.collection.{ AbstractIterator, SpecificIterableFactory, StrictOptimizedSeqOps, View, mutable } -import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } - -final class RNA private ( - val groups: Array[Int], - val length: Int -) extends IndexedSeq[Base] - with IndexedSeqOps[Base, IndexedSeq, RNA] - with StrictOptimizedSeqOps[Base, IndexedSeq, RNA] { rna => - - import RNA._ - - // Mandatory implementation of `apply` in `IndexedSeqOps` - def apply(idx: Int): Base = { - if (idx < 0 || length <= idx) - throw new IndexOutOfBoundsException - Base.fromInt(groups(idx / N) >> (idx % N * S) & M) - } - - // Mandatory implementation of `fromSpecificIterable` and - // `newSpecificBuilder`, from `IterableOps` - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA = - RNA.fromSpecific(coll) - override protected def newSpecificBuilder: mutable.Builder[Base, RNA] = - RNA.newBuilder - - // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`, - // `map`, `flatMap` and `concat` to return an `RNA` when possible - def appended(base: Base): RNA = - (newSpecificBuilder ++= this += base).result() - def appendedAll(suffix: Iterable[Base]): RNA = - (newSpecificBuilder ++= this ++= suffix).result() - def prepended(base: Base): RNA = - (newSpecificBuilder += base ++= this).result() - def prependedAll(prefix: Iterable[Base]): RNA = - (newSpecificBuilder ++= prefix ++= this).result() - def map(f: Base => Base): RNA = { - var b = newSpecificBuilder - for (base <- this) { - b += f(base) - } - b.result() - } - def flatMap(f: Base => IterableOnce[Base]): RNA = { - var b = newSpecificBuilder - for (base <- this) { - b ++= f(base) - } - b.result() - } - def concat(suffix: IterableOnce[Base]): RNA = { - val b = newSpecificBuilder - b ++= this - b ++= suffix - b.result() - } - - // Optional re-implementation of iterator, - // to make it more efficient. - override def iterator: Iterator[Base] = new AbstractIterator[Base] { - private var i = 0 - private var b = 0 - def hasNext: Boolean = i < rna.length - def next(): Base = { - b = if (i % N == 0) groups(i / N) else b >>> S - i += 1 - Base.fromInt(b & M) - } - } - -} - -object RNA extends SpecificIterableFactory[Base, RNA] { - - private val S = 2 // number of bits in group - private val M = (1 << S) - 1 // bitmask to isolate a group - private val N = 32 / S // number of groups in an Int - - def fromSeq(buf: collection.Seq[Base]): RNA = { - val groups = new Array[Int]((buf.length + N - 1) / N) - for (i <- 0 until buf.length) - groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) - new RNA(groups, buf.length) - } - - // Mandatory factory methods: `empty`, `newBuilder` - // and `fromSpecific` - def empty: RNA = fromSeq(Seq.empty) - - def newBuilder: mutable.Builder[Base, RNA] = - mutable.ArrayBuffer.newBuilder[Base].mapResult(fromSeq) - - def fromSpecific(it: IterableOnce[Base]): RNA = it match { - case seq: collection.Seq[Base] => fromSeq(seq) - case _ => fromSeq(mutable.ArrayBuffer.from(it)) - } -} -~~~ - -The final [`RNA` class](#final-version-of-rna-strands-class): - -- extends the `StrictOptimizedSeqOps` trait, which overrides all transformation - operations to take advantage of strict builders, -- uses a strict mode for overloads of transformation operations that return - an `RNA`, -- has a companion object that extends `SpecificIterableFactory[Base, RNA]`, which makes - it possible to use it as a parameter of a `to` call (to convert any collection - of bases to an `RNA`, e.g. `List(U, A, G, C).to(RNA)`), -- moves the `newSpecificBuilder` and `fromSpecificIterable` implementations - to the companion object. - -The discussion so far centered on the minimal amount of definitions -needed to define new sequences with methods that obey certain -types. But in practice you might also want to add new functionality to -your sequences or to override existing methods for better -efficiency. An example of this is the overridden `iterator` method in -class `RNA`. `iterator` is an important method in its own right because it -implements loops over collections. Furthermore, many other collection -methods are implemented in terms of `iterator`. So it makes sense to -invest some effort optimizing the method's implementation. The -standard implementation of `iterator` in `IndexedSeq` will simply select -every `i`'th element of the collection using `apply`, where `i` ranges from -0 to the collection's length minus one. So this standard -implementation selects an array element and unpacks a base from it -once for every element in an RNA strand. The overriding `iterator` in -class `RNA` is smarter than that. For every selected array element it -immediately applies the given function to all bases contained in -it. So the effort for array selection and bit unpacking is much -reduced. - -## Integrating a new prefix map ## - -As a third example you'll learn how to integrate a new kind of mutable map -into the collection framework. The idea is to implement a mutable map -with `String` as the type of keys by a "Patricia trie". The term -*Patricia* is in fact an abbreviation for "Practical Algorithm to -Retrieve Information Coded in Alphanumeric" and *trie* comes from -re*trie*val (a trie is also called a radix tree or prefix tree). -The idea is to store a set or a map as a tree where subsequent -characters in a search key -uniquely determine a path through the tree. For instance a Patricia trie -storing the strings "abc", "abd", "al", "all" and "xy" would look -like this: - -A sample patricia trie: - - -To find the node corresponding to the string "abc" in this trie, -simply follow the subtree labeled "a", proceed from there to the -subtree labelled "b", to finally reach its subtree labelled "c". If -the Patricia trie is used as a map, the value that's associated with a -key is stored in the nodes that can be reached by the key. If it is a -set, you simply store a marker saying that the node is present in the -set. - -Patricia tries support very efficient lookups and updates. Another -nice feature is that they support selecting a subcollection by giving -a prefix. For instance, in the patricia tree above you can obtain the -sub-collection of all keys that start with an "a" simply by following -the "a" link from the root of the tree. - -Based on these ideas we will now walk you through the implementation -of a map that's implemented as a Patricia trie. We call the map a -`PrefixMap`, which means that it provides a method `withPrefix` that -selects a submap of all keys starting with a given prefix. We'll first -define a prefix map with the keys shown in the running example: - - scala> val m = PrefixMap("abc" -> 0, "abd" -> 1, "al" -> 2, - "all" -> 3, "xy" -> 4) - m: PrefixMap[Int] = PrefixMap((abc,0), (abd,1), (al,2), (all,3), (xy,4)) - -Then calling `withPrefix` on `m` will yield another prefix map: - - scala> m withPrefix "a" - res14: PrefixMap[Int] = PrefixMap((bc,0), (bd,1), (l,2), (ll,3)) - -### Patricia trie implementation ### - -~~~ scala -import scala.collection._ -import scala.collection.mutable.{ GrowableBuilder, Builder } - -class PrefixMap[A] - extends mutable.Map[String, A] - with mutable.MapOps[String, A, mutable.Map, PrefixMap[A]] - with StrictOptimizedIterableOps[(String, A), mutable.Iterable, PrefixMap[A]] { - - private var suffixes: immutable.Map[Char, PrefixMap[A]] = immutable.Map.empty - private var value: Option[A] = None - - def get(s: String): Option[A] = - if (s.isEmpty) value - else suffixes get (s(0)) flatMap (_.get(s substring 1)) - - def withPrefix(s: String): PrefixMap[A] = - if (s.isEmpty) this - else { - val leading = s(0) - suffixes get leading match { - case None => - suffixes = suffixes + (leading -> empty) - case _ => - } - suffixes(leading) withPrefix (s substring 1) - } - - def iterator: Iterator[(String, A)] = - (for (v <- value.iterator) yield ("", v)) ++ - (for ((chr, m) <- suffixes.iterator; - (s, v) <- m.iterator) yield (chr +: s, v)) - - def addOne(kv: (String, A)): this.type = { - withPrefix(kv._1).value = Some(kv._2) - this - } - - def subtractOne(s: String): this.type = { - if (s.isEmpty) { val prev = value; value = None; prev } - else suffixes get (s(0)) flatMap (_.remove(s substring 1)) - this - } - - // Overloading of transformation methods that should return a PrefixMap - def map[B](f: ((String, A)) => (String, B)): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - for (kv <- this) { - b += f(kv) - } - b.result() - } - def flatMap[B](f: ((String, A)) => IterableOnce[(String, B)]): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - for (kv <- this) { - b ++= f(kv) - } - b.result() - } - - // Override `concat` and `empty` methods to refine their return type - override def concat[B >: A](suffix: Iterable[(String, B)]): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - b ++= this - b ++= suffix - b.result() - } - override def empty: PrefixMap[A] = new PrefixMap - - // Members declared in scala.collection.mutable.Clearable - def clear(): Unit = suffixes = immutable.Map.empty - // Members declared in scala.collection.IterableOps - override protected def fromSpecificIterable(coll: Iterable[(String, A)]): PrefixMap[A] = PrefixMap.from(coll) - override protected def newSpecificBuilder: mutable.Builder[(String, A), PrefixMap[A]] = PrefixMap.newBuilder -} - -object PrefixMap { - def empty[A] = new PrefixMap[A] - - def from[A](source: IterableOnce[(String, A)]): PrefixMap[A] = - source match { - case pm: PrefixMap[A] => pm - case _ => (newBuilder ++= source).result() - } - - def apply[A](kvs: (String, A)*): PrefixMap[A] = from(kvs) - - def newBuilder[A]: mutable.Builder[(String, A), PrefixMap[A]] = - new mutable.GrowableBuilder[(String, A), PrefixMap[A]](empty) - - implicit def toFactory[A](self: this.type): Factory[(String, A), PrefixMap[A]] = - new Factory[(String, A), PrefixMap[A]] { - def fromSpecific(it: IterableOnce[(String, A)]): PrefixMap[A] = self.from(it) - def newBuilder: mutable.Builder[(String, A), PrefixMap[A]] = self.newBuilder - } - -} -~~~ - -The previous listing shows the definition of `PrefixMap`. The map has -keys of type `String` and the values are of parametric type `A`. It extends -`mutable.Map[String, A]` and `mutable.MapOps[String, A, mutable.Map, PrefixMap[A]]`. -You have seen this pattern already for sequences in the -RNA strand example; then as now inheriting an implementation class -such as `MapOps` serves to get the right result type for -transformations such as `filter`. - -A prefix map node has two mutable fields: `suffixes` and `value`. The -`value` field contains an optional value that's associated with the -node. It is initialized to `None`. The `suffixes` field contains a map -from characters to `PrefixMap` values. It is initialized to the empty -map. - -You might ask why we picked an immutable map as the implementation -type for `suffixes`? Would not a mutable map have been more standard, -since `PrefixMap` as a whole is also mutable? The answer is that -immutable maps that contain only a few elements are very efficient in -both space and execution time. For instance, maps that contain fewer -than 5 elements are represented as a single object. By contrast, the -standard mutable map is a `HashMap`, which typically occupies around 80 -bytes, even if it is empty. So if small collections are common, it's -better to pick immutable over mutable. In the case of Patricia tries, -we'd expect that most nodes except the ones at the very top of the -tree would contain only a few successors. So storing these successors -in an immutable map is likely to be more efficient. - -Now have a look at the first method that needs to be implemented for a -map: `get`. The algorithm is as follows: To get the value associated -with the empty string in a prefix map, simply select the optional -`value` stored in the root of the tree (the current map). -Otherwise, if the key string is -not empty, try to select the submap corresponding to the first -character of the string. If that yields a map, follow up by looking up -the remainder of the key string after its first character in that -map. If the selection fails, the key is not stored in the map, so -return with `None`. The combined selection over an option value `opt` is -elegantly expressed using `opt.flatMap(x => f(x))`. When applied to an -optional value that is `None`, it returns `None`. Otherwise `opt` is -`Some(x)` and the function `f` is applied to the encapsulated value `x`, -yielding a new option, which is returned by the flatmap. - -The next two methods to implement for a mutable map are `addOne` and `subtractOne`. - -The `subtractOne` method is very similar to `get`, except that before returning -any associated value, the field containing that value is set to -`None`. The `addOne` method first calls `withPrefix` to navigate to the tree -node that needs to be updated, then sets the `value` field of that node -to the given value. The `withPrefix` method navigates through the tree, -creating sub-maps as necessary if some prefix of characters is not yet -contained as a path in the tree. - -The last abstract method to implement for a mutable map is -`iterator`. This method needs to produce an iterator that yields all -key/value pairs stored in the map. For any given prefix map this -iterator is composed of the following parts: First, if the map -contains a defined value, `Some(x)`, in the `value` field at its root, -then `("", x)` is the first element returned from the -iterator. Furthermore, the iterator needs to traverse the iterators of -all submaps stored in the `suffixes` field, but it needs to add a -character in front of every key string returned by those -iterators. More precisely, if `m` is the submap reached from the root -through a character `chr`, and `(s, v)` is an element returned from -`m.iterator`, then the root's iterator will return `(chr +: s, v)` -instead. This logic is implemented quite concisely as a concatenation -of two `for` expressions in the implementation of the `iterator` method in -`PrefixMap`. The first `for` expression iterates over `value.iterator`. This -makes use of the fact that `Option` values define an iterator method -that returns either no element, if the option value is `None`, or -exactly one element `x`, if the option value is `Some(x)`. - -However, in all these cases, to build the right kind of collection -you need to start with an empty collection of that kind. This is -provided by the `empty` method, which is the last method defined in -`PrefixMap`. This method simply returns a fresh `PrefixMap`. - -We'll now turn to the companion object `PrefixMap`. In fact it is not -strictly necessary to define this companion object, as class `PrefixMap` -can stand well on its own. The main purpose of object `PrefixMap` is to -define some convenience factory methods. It also defines an implicit -conversion to `Factory` for a better interoperability with other -collections. This conversion is triggered when one writes, for instance, -`List("foo" -> 3).to(PrefixMap)`. The `to` operation takes a `Factory` -as parameter but the `PrefixMap` companion object does not extend `Factory` (and it -can not because a `Factory` fixes the type of collection elements, -whereas `PrefixMap` has a polymorphic type of values). - -The two convenience methods are `empty` and `apply`. The same methods are -present for all other collections in Scala's collection framework so -it makes sense to define them here, too. With the two methods, you can -write `PrefixMap` literals like you do for any other collection: - - scala> PrefixMap("hello" -> 5, "hi" -> 2) - res0: PrefixMap[Int] = PrefixMap(hello -> 5, hi -> 2) - - scala> res0 += "foo" -> 3 - res1: res0.type = PrefixMap(hello -> 5, hi -> 2, foo -> 3) - ## Summary ## -To summarize, if you want to fully integrate a new collection class -into the framework you need to pay attention to the following points: - -1. Decide whether the collection should be mutable or immutable. -2. Pick the right base traits for the collection. -3. Inherit from the right implementation trait to implement most - collection operations. -4. Overload desired operations that do not return, by default, a - collection as specific as they could. A complete list of such - operations is given as an appendix. - -You have now seen how Scala's collections are built and how you can -add new kinds of collections. Because of Scala's rich support for -abstraction, each new collection type has a large number of -methods without having to reimplement them all over again. - -### Acknowledgement ### - -These pages contain material adapted from the 2nd edition of -[Programming in Scala](http://www.artima.com/shop/programming_in_scala) by -Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its -publication. - -## Appendix: Methods to overload to support the “same result type” principle ## - -You want to add overloads to specialize transformation operations such that they return a more specific result type. Examples are: -- `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), -- `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), -- `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a -`SortedSet` (instead of a `Set`). - -Typically, this happens when the collection fixes some type parameter of its template trait. For instance in -the case of the `RNA` collection type, we fix the element type to `Base`, and in the case of the `PrefixMap[A]` -collection type, we fix the type of keys to `String`. - -The following table lists transformation operations that might return an undesirably wide type. You might want to overload -these operations to return a more specific type. - - Collection | Operations ----------------|-------------- -`Iterable` | `map`, `flatMap`, `collect`, `scanLeft`, `scanRight`, `groupMap`, `concat`, `zip`, `zipAll`, `unzip` -`Seq` | `prepended`, `appended`, `prependedAll`, `appendedAll`, `padTo`, `patch` -`immutable.Seq`| `updated` -`SortedSet` | `map`, `flatMap`, `collect`, `zip` -`Map` | `map`, `flatMap`, `collect`, `concat` -`immutable.Map`| `updated`, `transform` -`SortedMap` | `map`, `flatMap`, `collect`, `concat` -`immutable.SortedMap` | `updated` - -## Appendix: Cross-building custom collections ## - -Since the new internal API of the Scala 2.13 collections is very different from the previous -collections API, authors of custom collection types should use separate source directories -(per Scala version) to define them. - -With sbt you can achieve this by adding the following setting to your project: - -~~~ scala -// Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer -// and a `src/main/scala-2.13-` source directory for Scala version older than 2.13 -unmanagedSourceDirectories in Compile += { - val sourceDir = (sourceDirectory in Compile).value - CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+" - case _ => sourceDir / "scala-2.13-" - } -} -~~~ - -And then you can define a Scala 2.13 compatible implementation of your collection -in the `src/main/scala-2.13+` source directory, and an implementation for the -previous Scala versions in the `src/main/scala-2.13-` source directory. - -You can see how this has been put in practice in -[scalacheck](https://github.com/rickynils/scalacheck/pull/411) and -[scalaz](https://github.com/scalaz/scalaz/pull/1730). +This document explains that: +- collection operations are implemented in template traits suffixed + with `Ops` (e.g. `IterableOps[A, CC[_], C]`), +- these template traits abstract over the type of collection elements (`A`), + the type constructor of returned collections (`CC`) and the type of + returned collections (`C`), +- there are four branches of template traits (`IterableOps`, `MapOps`, + `SortedSetOps` and `SortedMapOps`), +- some transformation operations (e.g. `map`) are overloaded to return + different result types according to their arguments type, +- the logic of transformation operations is primarily implemented in + views but there are specialized versions of template traits + (prefixed with `StrictOptimized`) that override these operations + to use a builder based approach. + +You now have all the required knowledge to implement +[custom collection types]({{ site.baseurl }}/overviews/core/custom-collections.html). diff --git a/_overviews/core/custom-collections.md b/_overviews/core/custom-collections.md new file mode 100644 index 0000000000..9fca0df42d --- /dev/null +++ b/_overviews/core/custom-collections.md @@ -0,0 +1,1059 @@ +--- +layout: singlepage-overview +title: Custom Collection Types + +permalink: /overviews/core/:title.html +--- + +**Martin Odersky, Lex Spoon and Julien Richard-Foy** + +This article shows how to implement custom collection types on top of +the collections framework. It is recommended to first read the article +about the [architecture of the collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html). + +What needs to be done if you want to integrate a new collection class, +so that it can profit from all predefined operations with the right +types? In the next few sections you’ll be walked through three examples +that do this, namely capped sequences, sequences of RNA +bases and prefix maps implemented with Patricia tries. + +## Capped sequence ## + +Say you want to create an immutable collection containing *at most* `n` elements: +if more elements are added then the first elements are removed. + +The first task is to find the supertype of our collection: is it +`Seq`, `Set`, `Map` or just `Iterable`? In our case, it is tempting +to choose `Seq` because our collection can contain duplicates and +iteration order is determined by insertion order. However, some +[properties of `Seq`](/overviews/collections/seqs.html) are not satisfied: + +~~~ scala +(xs ++ ys).size == xs.size + ys.size +~~~ + +Consequently, the only sensible choice as a base collection type +is `collection.immutable.Iterable`. + +### First version of `Capped` class ### + +~~~ scala +import scala.collection._ + +class Capped1[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] { self => + + def this(capacity: Int) = + this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) + + def appended[B >: A](elem: B): Capped1[B] = { + val newElems = Array.ofDim[Any](capacity) + Array.copy(elems, 0, newElems, 0, capacity) + val (newOffset, newLength) = + if (length == capacity) { + newElems(offset) = elem + ((offset + 1) % capacity, length) + } else { + newElems(length) = elem + (offset, length + 1) + } + new Capped1[B](capacity, newLength, newOffset, newElems) + } + + @`inline` def :+ [B >: A](elem: B): Capped1[B] = appended(elem) + + def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] + + def iterator: Iterator[A] = new AbstractIterator[A] { + private var current = 0 + def hasNext = current < self.length + def next(): A = { + val elem = self(current) + current += 1 + elem + } + } + +} +~~~ + +The above listing presents the first version of our capped collection +implementation. It will be refined later. The class `Capped1` has a +private constructor that takes the collection capacity, length, +offset (first element index) and the underlying array as parameters. +The public constructor takes only the capacity of the collection. It +sets the length and offset to 0, and uses an empty array of elements. + +The `appended` method defines how elements can be appended to a given +`Capped1` collection: it creates a new underlying array of elements, +copies the current elements and adds the new element. As long as the +number of elements does not exceed the `capacity`, the new element +is appended after the previous elements. However, as soon as the +maximal capacity has been reached, the new element replaces the first +element of the collection (at `offset` index). + +The `apply` method implements indexed access: it translates the given +index into its corresponding index in the underlying array by adding +the `offset`. + +These two methods, `appended` and `apply`, implement the specific +behavior of the `Capped1` collection type. In addition to them, we have +to implement `iterator` to make the generic collection operations +(such as `foldLeft`, `count`, etc.) work on `Capped` collections. +Here we implement it by using indexed access. + +Here are some interactions with the `Capped1` collection: + +~~~ scala +scala> new Capped1(capacity = 4) +res0: Capped1[Nothing] = Capped1() + +scala> res0 :+ 1 :+ 2 :+ 3 +res1: Capped1[Int] = Capped1(1, 2, 3) + +scala> res1.length +res2: Int = 3 + +scala> res1.lastOption +res3: Option[Int] = Some(3) + +scala> res1 :+ 4 :+ 5 :+ 6 +res4: Capped1[Int] = Capped1(3, 4, 5, 6) + +scala> res4.take(3) +res5: collection.immutable.Iterable[Int] = List(3, 4, 5) +~~~ + +You can see that if we try to grow the collection with more than four +elements, the first elements are dropped (see `res4`). The operations +behave as expected except for the last one: after calling `take` we +get back a `List` instead of the expected `Capped1` collection. This +is because all that was done in [class +`Capped1`](#first-version-of-capped-class) was making `Capped1` extend +`immutable.Iterable`. This class has a `take` method +that returns an `immutable.Iterable`, and that’s implemented in terms of +`immutable.Iterable`’s default implementation, `List`. So, that’s what +you were seeing on the last line of the previous interaction. + +Now that you understand why things are the way they are, the next +question should be what needs to be done to change them? One way to do +this would be to override the `take` method in class `Capped1`, maybe like +this: + + def take(count: Int): Capped1 = … + +This would do the job for `take`. But what about `drop`, or `filter`, or +`init`? In fact there are over fifty methods on collections that return +again a collection. For consistency, all of these would have to be +overridden. This looks less and less like an attractive +option. Fortunately, there is a much easier way to achieve the same +effect, as shown in the next section. + +### Second version of `Capped` class ### + +~~~ scala +import scala.collection._ + +class Capped2[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] + with IterableOps[A, Capped2, Capped2[A]] { self => + + def this(capacity: Int) = // as before + + def appended[B >: A](elem: B): Capped2[B] = // as before + @`inline` def :+ [B >: A](elem: B): Capped2[B] = // as before + def apply(i: Int): A = // as before + + def iterator: Iterator[A] = // as before + + override val iterableFactory: IterableFactory[Capped2] = new Capped2Factory(capacity) + +} + +class Capped2Factory(capacity: Int) extends IterableFactory[Capped2] { + + def from[A](source: IterableOnce[A]): Capped2[A] = + (newBuilder[A] ++= source).result() + + def empty[A]: Capped2[A] = new Capped2[A](capacity) + + def newBuilder[A]: mutable.Builder[A, Capped2[A]] = + new mutable.ImmutableBuilder[A, Capped2[A]](empty) { + def addOne(elem: A): this.type = { elems = elems :+ elem; this } + } +} +~~~ + +The Capped class needs to inherit not only from `Iterable`, but also +from its implementation trait `IterableOps`. This is shown in the +above listing of class `Capped2`. The new implementation differs +from the previous one in only two aspects. First, class `Capped2` +now also extends `IterableOps[A, Capped2, Capped2[A]]`. Second, +its `iterableFactory` member is overridden to return an +`IterableFactory[Capped2]`. As explained in the +previous sections, the `IterableOps` trait implements all concrete +methods of `Iterable` in a generic way. For instance, the +return type of methods like `take`, `drop`, `filter` or `init` +is the third type parameter passed to class `IterableOps`, i.e., +in class `Capped2`, it is `Capped2[A]`. Similarly, the return +type of methods like `map`, `flatMap` or `concat` is defined +by the second type parameter passed to class `IterableOps`, +i.e., in class `Capped2`, it is `Capped2` itself. + +To construct a `Capped2`, the `fromSpecificIterable` and +`newSpecificBuilder` implementations inherited from `immutable.Iterable` +delegate to the `iterableFactory` member, which is overridden here to +return an instance of `Capped2Factory`. This class +provides convenient factory methods to build collections. Eventually, +these methods delegate to `empty`, which builds an empty `Capped2` +instance, and `newBuilder`, which uses the `appended` operation +to grow a `Capped2` collection. + +With the refined implementation of the [`Capped2` class](#second-version-of-capped-class), +the transformation operations work now as expected, and the +`Capped2Factory` class provides seamless conversions from other collections: + +~~~ scala +scala> object Capped extends Capped2Factory(capacity = 4) +defined object Capped + +scala> Capped(1, 2, 3) +res0: Capped2[Int] = Capped2(1, 2, 3) + +scala> res0.take(2) +res1: Capped2[Int] = Capped2(1, 2) + +scala> res0.filter(x => x % 2 == 1) +res2: Capped2[Int] = Capped2(1, 3) + +scala> res0.map(x => x * x) +res3: Capped2[Int] = Capped2(1, 4, 9) + +scala> List(1, 2, 3, 4, 5).to(Capped) +res4: Capped2[Int] = Capped2(2, 3, 4, 5) +~~~ + +This implementation now behaves correctly, but we can still improve +a few things. Since our collection is strict, we can take advantage +of the better performance offered by +strict implementations of transformation operations. + +### Final version of `Capped` class ### + +~~~ scala +import scala.collection._ + +final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) + extends immutable.Iterable[A] + with IterableOps[A, Capped, Capped[A]] + with StrictOptimizedIterableOps[A, Capped, Capped[A]] { self => + + def this(capacity: Int) = + this(capacity, length = 0, offset = 0, elems = Array.ofDim(capacity)) + + def appended[B >: A](elem: B): Capped[B] = { + val newElems = Array.ofDim[Any](capacity) + Array.copy(elems, 0, newElems, 0, capacity) + val (newOffset, newLength) = + if (length == capacity) { + newElems(offset) = elem + ((offset + 1) % capacity, length) + } else { + newElems(length) = elem + (offset, length + 1) + } + new Capped[B](capacity, newLength, newOffset, newElems) + } + + @`inline` def :+ [B >: A](elem: B): Capped[B] = appended(elem) + + def apply(i: Int): A = elems((i + offset) % capacity).asInstanceOf[A] + + def iterator: Iterator[A] = view.iterator + + override def view: IndexedSeqView[A] = new IndexedSeqView[A] { + def length: Int = self.length + def apply(i: Int): A = self(i) + } + + override def knownSize: Int = length + + override val iterableFactory: IterableFactory[Capped] = new CappedFactory(capacity) + +} + +class CappedFactory(capacity: Int) extends IterableFactory[Capped] { + + def from[A](source: IterableOnce[A]): Capped[A] = + source match { + case capped: Capped[A] if capped.capacity == capacity => capped + case _ => (newBuilder[A] ++= source).result() + } + + def empty[A]: Capped[A] = new Capped[A](capacity) + + def newBuilder[A]: mutable.Builder[A, Capped[A]] = + new mutable.ImmutableBuilder[A, Capped[A]](empty) { + def addOne(elem: A): this.type = { elems = elems :+ elem; this } + } + +} +~~~ + +That is it. The final [`Capped` class](#final-version-of-capped-class): + +- extends the `StrictOptimizedIterableOps` trait, which overrides all + transformation operations to take advantage of strict builders, +- overrides a few operations for performance: the `view` now uses + indexed access, and the `iterator` delegates to the view. The + `knownSize` operation is also overridden because the size is always + known. + +Its implementation requires a little bit of protocol. In essence, you +have to inherit from the `Ops` template trait in addition to just +inheriting from a collection type, override the `iterableFactory` +member to return a more specific factory, and finally implement abstract +methods (such as `iterator` in our case), if any. + +## RNA sequences ## + +To start with the second example, we define the four RNA Bases: + + abstract class Base + case object A extends Base + case object U extends Base + case object G extends Base + case object C extends Base + + object Base { + val fromInt: Int => Base = Array(A, U, G, C) + val toInt: Base => Int = Map(A -> 0, U -> 1, G -> 2, C -> 3) + } + +Say you want to create a new immutable sequence type for RNA strands, which are +sequences of bases A (adenine), U (uracil), G (guanine), and C +(cytosine). The definitions for bases are easily set up as shown in the +listing of RNA bases above. + +Every base is defined as a case object that inherits from a common +abstract class `Base`. The `Base` class has a companion object that +defines two functions that map between bases and the integers 0 to 3. +You can see in the examples two different ways to use collections +to implement these functions. The `toInt` function is implemented as a +`Map` from `Base` values to integers. The reverse function, `fromInt`, is +implemented as an array. This makes use of the fact that both maps and +arrays *are* functions because they inherit from the `Function1` trait. + +The next task is to define a class for strands of RNA. Conceptually, a +strand of RNA is simply a `Seq[Base]`. However, RNA strands can get +quite long, so it makes sense to invest some work in a compact +representation. Because there are only four bases, a base can be +identified with two bits, and you can therefore store sixteen bases as +two-bit values in an integer. The idea, then, is to construct a +specialized subclass of `Seq[Base]`, which uses this packed +representation. + +### First version of RNA strands class ### + + import collection.mutable + import collection.immutable.{ IndexedSeq, IndexedSeqOps } + + final class RNA1 private ( + val groups: Array[Int], + val length: Int + ) extends IndexedSeq[Base] + with IndexedSeqOps[Base, IndexedSeq, RNA1] { + + import RNA1._ + + def apply(idx: Int): Base = { + if (idx < 0 || length <= idx) + throw new IndexOutOfBoundsException + Base.fromInt(groups(idx / N) >> (idx % N * S) & M) + } + + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 = + fromSeq(coll.toSeq) + override protected def newSpecificBuilder: mutable.Builder[Base, RNA1] = + iterableFactory.newBuilder[Base].mapResult(fromSeq) + } + + object RNA1 { + + // Number of bits necessary to represent group + private val S = 2 + + // Number of groups that fit in an Int + private val N = 32 / S + + // Bitmask to isolate a group + private val M = (1 << S) - 1 + + def fromSeq(buf: collection.Seq[Base]): RNA1 = { + val groups = new Array[Int]((buf.length + N - 1) / N) + for (i <- 0 until buf.length) + groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) + new RNA1(groups, buf.length) + } + + def apply(bases: Base*) = fromSeq(bases) + } + +The [RNA strands class listing](#first-version-of-rna-strands-class) above +presents the first version of this +class. The class `RNA1` has a constructor that +takes an array of `Int`s as its first argument. This array contains the +packed RNA data, with sixteen bases in each element, except for the +last array element, which might be partially filled. The second +argument, `length`, specifies the total number of bases on the array +(and in the sequence). Class `RNA1` extends `IndexedSeq[Base]` and +`IndexedSeqOps[Base, IndexedSeq, RNA1]`. These traits define the following +abstract methods: + +- `length`, automatically implemented by defining a parametric field of + the same name, +- `apply` (indexing method), implemented by first extracting an integer value + from the `groups` array, then extracting the correct two-bit number from that + integer using right shift (`>>`) and mask (`&`). The private constants `S`, + `N`, and `M` come from the `RNA1` companion object. `S` specifies the size of + each packet (i.e., two); `N` specifies the number of two-bit packets per + integer; and `M` is a bit mask that isolates the lowest `S` bits in a + word. + +We also override the following members used by transformation operations +such as `filter` and `take`: + +- `fromSpecificIterable`, implemented by the `fromSeq` method of the `RNA1` + companion object, +- `newSpecificBuilder`, implemented by using the default `IndexedSeq` builder + and transforming its result into an `RNA1` with the `mapResult` method. + +Note that the constructor of class `RNA1` is `private`. This means that +clients cannot create `RNA1` sequences by calling `new`, which makes +sense, because it hides the representation of `RNA1` sequences in terms +of packed arrays from the user. If clients cannot see what the +representation details of RNA sequences are, it becomes possible to +change these representation details at any point in the future without +affecting client code. In other words, this design achieves a good +decoupling of the interface of RNA sequences and its +implementation. However, if constructing an RNA sequence with `new` is +impossible, there must be some other way to create new RNA sequences, +else the whole class would be rather useless. In fact there are two +alternatives for RNA sequence creation, both provided by the `RNA1` +companion object. The first way is method `fromSeq`, which converts a +given sequence of bases (i.e., a value of type `Seq[Base]`) into an +instance of class `RNA1`. The `fromSeq` method does this by packing all +the bases contained in its argument sequence into an array, then +calling `RNA1`'s private constructor with that array and the length of +the original sequence as arguments. This makes use of the fact that a +private constructor of a class is visible in the class's companion +object. + +The second way to create an `RNA1` value is provided by the `apply` method +in the `RNA1` object. It takes a variable number of `Base` arguments and +simply forwards them as a sequence to `fromSeq`. Here are the two +creation schemes in action: + + scala> val xs = List(A, G, U, A) + xs: List[Base] = List(A, G, U, A) + + scala> RNA1.fromSeq(xs) + res1: RNA1 = RNA1(A, G, U, A) + + scala> val rna1 = RNA1(A, U, G, G, C) + rna1: RNA1 = RNA1(A, U, G, G, C) + +Also note that the type parameters of the `IndexedSeqOps` trait that +we inherit from are: `Base`, `IndexedSeq` and `RNA1`. The first one +stands for the type of elements, the second one stands for the +type constructor used by transformation operations that return +a collection with a different type of elements, and the third one +stands for the type used by transformation operations that return +a collection with the same type of elements. In our case, it is +worth noting that the second one is `IndexedSeq` whereas the +third one is `RNA1`. This means that operations like `map` or +`flatMap` return an `IndexedSeq`, whereas operations like `take` or +`filter` return an `RNA1`. + +Here is an example showing the usage of `take` and `filter`: + + scala> rna1.take(3) + res5: RNA1 = RNA1(A, U, G) + + scala> rna1.filter(_ != U) + res6: RNA1 = RNA1(A, G, G, C) + +### Dealing with map and friends ### + +However, transformation operations that return a collection with a +different element type always return an `IndexedSeq`. + +How should these +methods be adapted to RNA strands? The desired behavior would be to get +back an RNA strand when mapping bases to bases or appending two RNA strands +with `++`: + + scala> val rna = RNA(A, U, G, G, C) + rna: RNA = RNA(A, U, G, G, C) + + scala> rna map { case A => U case b => b } + res7: RNA = RNA(U, U, G, G, C) + + scala> rna ++ rna + res8: RNA = RNA(A, U, G, G, C, A, U, G, G, C) + +On the other hand, mapping bases to some other type over an RNA strand +cannot yield another RNA strand because the new elements have the +wrong type. It has to yield a sequence instead. In the same vein +appending elements that are not of type `Base` to an RNA strand can +yield a general sequence, but it cannot yield another RNA strand. + + scala> rna map Base.toInt + res2: IndexedSeq[Int] = Vector(0, 1, 2, 2, 3) + + scala> rna ++ List("missing", "data") + res3: IndexedSeq[java.lang.Object] = + Vector(A, U, G, G, C, missing, data) + +This is what you'd expect in the ideal case. But this is not what the +[`RNA1` class](#first-version-of-rna-strands-class) provides. In fact, all +examples will return instances of `Vector`, not just the last two. If you run +the first three commands above with instances of this class you obtain: + + scala> val rna1 = RNA1(A, U, G, G, C) + rna1: RNA1 = RNA1(A, U, G, G, C) + + scala> rna1 map { case A => U case b => b } + res0: IndexedSeq[Base] = Vector(U, U, G, G, C) + + scala> rna1 ++ rna1 + res1: IndexedSeq[Base] = Vector(A, U, G, G, C, A, U, G, G, C) + +So the result of `map` and `++` is never an RNA strand, even if the +element type of the generated collection is `Base`. To see how to do +better, it pays to have a close look at the signature of the `map` +method (or of `++`, which has a similar signature). The `map` method is +originally defined in class `scala.collection.IterableOps` with the +following signature: + + def map[B](f: A => B): CC[B] + +Here `A` is the type of elements of the collection, and `CC` is the type +constructor passed as a second parameter to the `IterableOps` trait. + +In our `RNA1` implementation, this `CC` type constructor is `IndexedSeq`, +this is why we always get a `Vector` as a result. + +### Second version of RNA strands class ### + + import scala.collection.{ View, mutable } + import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } + + final class RNA2 private (val groups: Array[Int], val length: Int) + extends IndexedSeq[Base] with IndexedSeqOps[Base, IndexedSeq, RNA2] { + + import RNA2._ + + def apply(idx: Int): Base = // as before + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before + override protected def newSpecificBuilder: mutable.Builder[Base, RNA2] = // as before + + // Overloading of `appended`, `prepended`, `appendedAll`, + // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2` + // when possible + def appended(base: Base): RNA2 = + fromSpecificIterable(new View.Append(this, base)) + def appendedAll(suffix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(this, suffix)) + def prepended(base: Base): RNA2 = + fromSpecificIterable(new View.Prepend(base, this)) + def prependedAll(prefix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(prefix, this)) + def map(f: Base => Base): RNA2 = + fromSpecificIterable(new View.Map(this, f)) + def flatMap(f: Base => IterableOnce[Base]): RNA2 = + fromSpecificIterable(new View.FlatMap(this, f)) + def concat(suffix: Iterable[Base]): RNA2 = + fromSpecificIterable(new View.Concat(this, suffix)) + } + +To address this shortcoming, you need to overload the methods that +return an `IndexedSeq[B]` for the case where `B` is known to be `Base`, +to return an `RNA2` instead. + +Compared to [class `RNA1`](#first-version-of-rna-strands-class) +we added overloads for methods `appended`, `appendedAll`, `prepended`, +`prependedAll`, `map` and `flatMap`. + +This implementation now behaves correctly, but we can still improve a few things. Since our +collection is strict, we could take advantage of the better performance offered by strict builders +in transformation operations. +Also, if we try to convert an `Iterable[Base]` into an `RNA2` it fails: + +~~~ +scala> val bases: Iterable[Base] = List(A, U, C, C) +bases: Iterable[Base] = List(A, U, C, C) + +scala> bases.to(RNA2) + ^ + error: type mismatch; + found : RNA2.type + required: scala.collection.Factory[Base,?] +~~~ + +### Final version of RNA strands class ### + +~~~ scala +import scala.collection.{ AbstractIterator, SpecificIterableFactory, StrictOptimizedSeqOps, View, mutable } +import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps } + +final class RNA private ( + val groups: Array[Int], + val length: Int +) extends IndexedSeq[Base] + with IndexedSeqOps[Base, IndexedSeq, RNA] + with StrictOptimizedSeqOps[Base, IndexedSeq, RNA] { rna => + + import RNA._ + + // Mandatory implementation of `apply` in `IndexedSeqOps` + def apply(idx: Int): Base = { + if (idx < 0 || length <= idx) + throw new IndexOutOfBoundsException + Base.fromInt(groups(idx / N) >> (idx % N * S) & M) + } + + // Mandatory implementation of `fromSpecificIterable` and + // `newSpecificBuilder`, from `IterableOps` + override protected def fromSpecificIterable(coll: Iterable[Base]): RNA = + RNA.fromSpecific(coll) + override protected def newSpecificBuilder: mutable.Builder[Base, RNA] = + RNA.newBuilder + + // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`, + // `map`, `flatMap` and `concat` to return an `RNA` when possible + def appended(base: Base): RNA = + (newSpecificBuilder ++= this += base).result() + def appendedAll(suffix: Iterable[Base]): RNA = + (newSpecificBuilder ++= this ++= suffix).result() + def prepended(base: Base): RNA = + (newSpecificBuilder += base ++= this).result() + def prependedAll(prefix: Iterable[Base]): RNA = + (newSpecificBuilder ++= prefix ++= this).result() + def map(f: Base => Base): RNA = { + var b = newSpecificBuilder + for (base <- this) { + b += f(base) + } + b.result() + } + def flatMap(f: Base => IterableOnce[Base]): RNA = { + var b = newSpecificBuilder + for (base <- this) { + b ++= f(base) + } + b.result() + } + def concat(suffix: IterableOnce[Base]): RNA = { + val b = newSpecificBuilder + b ++= this + b ++= suffix + b.result() + } + + // Optional re-implementation of iterator, + // to make it more efficient. + override def iterator: Iterator[Base] = new AbstractIterator[Base] { + private var i = 0 + private var b = 0 + def hasNext: Boolean = i < rna.length + def next(): Base = { + b = if (i % N == 0) groups(i / N) else b >>> S + i += 1 + Base.fromInt(b & M) + } + } + +} + +object RNA extends SpecificIterableFactory[Base, RNA] { + + private val S = 2 // number of bits in group + private val M = (1 << S) - 1 // bitmask to isolate a group + private val N = 32 / S // number of groups in an Int + + def fromSeq(buf: collection.Seq[Base]): RNA = { + val groups = new Array[Int]((buf.length + N - 1) / N) + for (i <- 0 until buf.length) + groups(i / N) |= Base.toInt(buf(i)) << (i % N * S) + new RNA(groups, buf.length) + } + + // Mandatory factory methods: `empty`, `newBuilder` + // and `fromSpecific` + def empty: RNA = fromSeq(Seq.empty) + + def newBuilder: mutable.Builder[Base, RNA] = + mutable.ArrayBuffer.newBuilder[Base].mapResult(fromSeq) + + def fromSpecific(it: IterableOnce[Base]): RNA = it match { + case seq: collection.Seq[Base] => fromSeq(seq) + case _ => fromSeq(mutable.ArrayBuffer.from(it)) + } +} +~~~ + +The final [`RNA` class](#final-version-of-rna-strands-class): + +- extends the `StrictOptimizedSeqOps` trait, which overrides all transformation + operations to take advantage of strict builders, +- uses a strict mode for overloads of transformation operations that return + an `RNA`, +- has a companion object that extends `SpecificIterableFactory[Base, RNA]`, which makes + it possible to use it as a parameter of a `to` call (to convert any collection + of bases to an `RNA`, e.g. `List(U, A, G, C).to(RNA)`), +- moves the `newSpecificBuilder` and `fromSpecificIterable` implementations + to the companion object. + +The discussion so far centered on the minimal amount of definitions +needed to define new sequences with methods that obey certain +types. But in practice you might also want to add new functionality to +your sequences or to override existing methods for better +efficiency. An example of this is the overridden `iterator` method in +class `RNA`. `iterator` is an important method in its own right because it +implements loops over collections. Furthermore, many other collection +methods are implemented in terms of `iterator`. So it makes sense to +invest some effort optimizing the method's implementation. The +standard implementation of `iterator` in `IndexedSeq` will simply select +every `i`'th element of the collection using `apply`, where `i` ranges from +0 to the collection's length minus one. So this standard +implementation selects an array element and unpacks a base from it +once for every element in an RNA strand. The overriding `iterator` in +class `RNA` is smarter than that. For every selected array element it +immediately applies the given function to all bases contained in +it. So the effort for array selection and bit unpacking is much +reduced. + +## Prefix map ## + +As a third example you'll learn how to integrate a new kind of mutable map +into the collection framework. The idea is to implement a mutable map +with `String` as the type of keys by a "Patricia trie". The term +*Patricia* is in fact an abbreviation for "Practical Algorithm to +Retrieve Information Coded in Alphanumeric" and *trie* comes from +re*trie*val (a trie is also called a radix tree or prefix tree). +The idea is to store a set or a map as a tree where subsequent +characters in a search key +uniquely determine a path through the tree. For instance a Patricia trie +storing the strings "abc", "abd", "al", "all" and "xy" would look +like this: + +A sample patricia trie: + + +To find the node corresponding to the string "abc" in this trie, +simply follow the subtree labeled "a", proceed from there to the +subtree labelled "b", to finally reach its subtree labelled "c". If +the Patricia trie is used as a map, the value that's associated with a +key is stored in the nodes that can be reached by the key. If it is a +set, you simply store a marker saying that the node is present in the +set. + +Patricia tries support very efficient lookups and updates. Another +nice feature is that they support selecting a subcollection by giving +a prefix. For instance, in the patricia tree above you can obtain the +sub-collection of all keys that start with an "a" simply by following +the "a" link from the root of the tree. + +Based on these ideas we will now walk you through the implementation +of a map that's implemented as a Patricia trie. We call the map a +`PrefixMap`, which means that it provides a method `withPrefix` that +selects a submap of all keys starting with a given prefix. We'll first +define a prefix map with the keys shown in the running example: + + scala> val m = PrefixMap("abc" -> 0, "abd" -> 1, "al" -> 2, + "all" -> 3, "xy" -> 4) + m: PrefixMap[Int] = PrefixMap((abc,0), (abd,1), (al,2), (all,3), (xy,4)) + +Then calling `withPrefix` on `m` will yield another prefix map: + + scala> m withPrefix "a" + res14: PrefixMap[Int] = PrefixMap((bc,0), (bd,1), (l,2), (ll,3)) + +### Patricia trie implementation ### + +~~~ scala +import scala.collection._ +import scala.collection.mutable.{ GrowableBuilder, Builder } + +class PrefixMap[A] + extends mutable.Map[String, A] + with mutable.MapOps[String, A, mutable.Map, PrefixMap[A]] + with StrictOptimizedIterableOps[(String, A), mutable.Iterable, PrefixMap[A]] { + + private var suffixes: immutable.Map[Char, PrefixMap[A]] = immutable.Map.empty + private var value: Option[A] = None + + def get(s: String): Option[A] = + if (s.isEmpty) value + else suffixes get (s(0)) flatMap (_.get(s substring 1)) + + def withPrefix(s: String): PrefixMap[A] = + if (s.isEmpty) this + else { + val leading = s(0) + suffixes get leading match { + case None => + suffixes = suffixes + (leading -> empty) + case _ => + } + suffixes(leading) withPrefix (s substring 1) + } + + def iterator: Iterator[(String, A)] = + (for (v <- value.iterator) yield ("", v)) ++ + (for ((chr, m) <- suffixes.iterator; + (s, v) <- m.iterator) yield (chr +: s, v)) + + def addOne(kv: (String, A)): this.type = { + withPrefix(kv._1).value = Some(kv._2) + this + } + + def subtractOne(s: String): this.type = { + if (s.isEmpty) { val prev = value; value = None; prev } + else suffixes get (s(0)) flatMap (_.remove(s substring 1)) + this + } + + // Overloading of transformation methods that should return a PrefixMap + def map[B](f: ((String, A)) => (String, B)): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + for (kv <- this) { + b += f(kv) + } + b.result() + } + def flatMap[B](f: ((String, A)) => IterableOnce[(String, B)]): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + for (kv <- this) { + b ++= f(kv) + } + b.result() + } + + // Override `concat` and `empty` methods to refine their return type + override def concat[B >: A](suffix: Iterable[(String, B)]): PrefixMap[B] = { + val b = PrefixMap.newBuilder[B] + b ++= this + b ++= suffix + b.result() + } + override def empty: PrefixMap[A] = new PrefixMap + + // Members declared in scala.collection.mutable.Clearable + def clear(): Unit = suffixes = immutable.Map.empty + // Members declared in scala.collection.IterableOps + override protected def fromSpecificIterable(coll: Iterable[(String, A)]): PrefixMap[A] = PrefixMap.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(String, A), PrefixMap[A]] = PrefixMap.newBuilder +} + +object PrefixMap { + def empty[A] = new PrefixMap[A] + + def from[A](source: IterableOnce[(String, A)]): PrefixMap[A] = + source match { + case pm: PrefixMap[A] => pm + case _ => (newBuilder ++= source).result() + } + + def apply[A](kvs: (String, A)*): PrefixMap[A] = from(kvs) + + def newBuilder[A]: mutable.Builder[(String, A), PrefixMap[A]] = + new mutable.GrowableBuilder[(String, A), PrefixMap[A]](empty) + + implicit def toFactory[A](self: this.type): Factory[(String, A), PrefixMap[A]] = + new Factory[(String, A), PrefixMap[A]] { + def fromSpecific(it: IterableOnce[(String, A)]): PrefixMap[A] = self.from(it) + def newBuilder: mutable.Builder[(String, A), PrefixMap[A]] = self.newBuilder + } + +} +~~~ + +The previous listing shows the definition of `PrefixMap`. The map has +keys of type `String` and the values are of parametric type `A`. It extends +`mutable.Map[String, A]` and `mutable.MapOps[String, A, mutable.Map, PrefixMap[A]]`. +You have seen this pattern already for sequences in the +RNA strand example; then as now inheriting an implementation class +such as `MapOps` serves to get the right result type for +transformations such as `filter`. + +A prefix map node has two mutable fields: `suffixes` and `value`. The +`value` field contains an optional value that's associated with the +node. It is initialized to `None`. The `suffixes` field contains a map +from characters to `PrefixMap` values. It is initialized to the empty +map. + +You might ask why we picked an immutable map as the implementation +type for `suffixes`? Would not a mutable map have been more standard, +since `PrefixMap` as a whole is also mutable? The answer is that +immutable maps that contain only a few elements are very efficient in +both space and execution time. For instance, maps that contain fewer +than 5 elements are represented as a single object. By contrast, the +standard mutable map is a `HashMap`, which typically occupies around 80 +bytes, even if it is empty. So if small collections are common, it's +better to pick immutable over mutable. In the case of Patricia tries, +we'd expect that most nodes except the ones at the very top of the +tree would contain only a few successors. So storing these successors +in an immutable map is likely to be more efficient. + +Now have a look at the first method that needs to be implemented for a +map: `get`. The algorithm is as follows: To get the value associated +with the empty string in a prefix map, simply select the optional +`value` stored in the root of the tree (the current map). +Otherwise, if the key string is +not empty, try to select the submap corresponding to the first +character of the string. If that yields a map, follow up by looking up +the remainder of the key string after its first character in that +map. If the selection fails, the key is not stored in the map, so +return with `None`. The combined selection over an option value `opt` is +elegantly expressed using `opt.flatMap(x => f(x))`. When applied to an +optional value that is `None`, it returns `None`. Otherwise `opt` is +`Some(x)` and the function `f` is applied to the encapsulated value `x`, +yielding a new option, which is returned by the flatmap. + +The next two methods to implement for a mutable map are `addOne` and `subtractOne`. + +The `subtractOne` method is very similar to `get`, except that before returning +any associated value, the field containing that value is set to +`None`. The `addOne` method first calls `withPrefix` to navigate to the tree +node that needs to be updated, then sets the `value` field of that node +to the given value. The `withPrefix` method navigates through the tree, +creating sub-maps as necessary if some prefix of characters is not yet +contained as a path in the tree. + +The last abstract method to implement for a mutable map is +`iterator`. This method needs to produce an iterator that yields all +key/value pairs stored in the map. For any given prefix map this +iterator is composed of the following parts: First, if the map +contains a defined value, `Some(x)`, in the `value` field at its root, +then `("", x)` is the first element returned from the +iterator. Furthermore, the iterator needs to traverse the iterators of +all submaps stored in the `suffixes` field, but it needs to add a +character in front of every key string returned by those +iterators. More precisely, if `m` is the submap reached from the root +through a character `chr`, and `(s, v)` is an element returned from +`m.iterator`, then the root's iterator will return `(chr +: s, v)` +instead. This logic is implemented quite concisely as a concatenation +of two `for` expressions in the implementation of the `iterator` method in +`PrefixMap`. The first `for` expression iterates over `value.iterator`. This +makes use of the fact that `Option` values define an iterator method +that returns either no element, if the option value is `None`, or +exactly one element `x`, if the option value is `Some(x)`. + +However, in all these cases, to build the right kind of collection +you need to start with an empty collection of that kind. This is +provided by the `empty` method, which is the last method defined in +`PrefixMap`. This method simply returns a fresh `PrefixMap`. + +We'll now turn to the companion object `PrefixMap`. In fact it is not +strictly necessary to define this companion object, as class `PrefixMap` +can stand well on its own. The main purpose of object `PrefixMap` is to +define some convenience factory methods. It also defines an implicit +conversion to `Factory` for a better interoperability with other +collections. This conversion is triggered when one writes, for instance, +`List("foo" -> 3).to(PrefixMap)`. The `to` operation takes a `Factory` +as parameter but the `PrefixMap` companion object does not extend `Factory` (and it +can not because a `Factory` fixes the type of collection elements, +whereas `PrefixMap` has a polymorphic type of values). + +The two convenience methods are `empty` and `apply`. The same methods are +present for all other collections in Scala's collection framework so +it makes sense to define them here, too. With the two methods, you can +write `PrefixMap` literals like you do for any other collection: + + scala> PrefixMap("hello" -> 5, "hi" -> 2) + res0: PrefixMap[Int] = PrefixMap(hello -> 5, hi -> 2) + + scala> res0 += "foo" -> 3 + res1: res0.type = PrefixMap(hello -> 5, hi -> 2, foo -> 3) + +## Summary ## + +To summarize, if you want to fully integrate a new collection class +into the framework you need to pay attention to the following points: + +1. Decide whether the collection should be mutable or immutable. +2. Pick the right base traits for the collection. +3. Inherit from the right implementation trait to implement most + collection operations. +4. Overload desired operations that do not return, by default, a + collection as specific as they could. A complete list of such + operations is given as an appendix. + +You have now seen how Scala's collections are built and how you can +add new kinds of collections. Because of Scala's rich support for +abstraction, each new collection type has a large number of +methods without having to reimplement them all over again. + +### Acknowledgement ### + +These pages contain material adapted from the 2nd edition of +[Programming in Scala](http://www.artima.com/shop/programming_in_scala) by +Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its +publication. + +## Appendix: Methods to overload to support the “same result type” principle ## + +You want to add overloads to specialize transformation operations such that they return a more specific result type. Examples are: +- `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), +- `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), +- `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a +`SortedSet` (instead of a `Set`). + +Typically, this happens when the collection fixes some type parameter of its template trait. For instance in +the case of the `RNA` collection type, we fix the element type to `Base`, and in the case of the `PrefixMap[A]` +collection type, we fix the type of keys to `String`. + +The following table lists transformation operations that might return an undesirably wide type. You might want to overload +these operations to return a more specific type. + + Collection | Operations +---------------|-------------- +`Iterable` | `map`, `flatMap`, `collect`, `scanLeft`, `scanRight`, `groupMap`, `concat`, `zip`, `zipAll`, `unzip` +`Seq` | `prepended`, `appended`, `prependedAll`, `appendedAll`, `padTo`, `patch` +`immutable.Seq`| `updated` +`SortedSet` | `map`, `flatMap`, `collect`, `zip` +`Map` | `map`, `flatMap`, `collect`, `concat` +`immutable.Map`| `updated`, `transform` +`SortedMap` | `map`, `flatMap`, `collect`, `concat` +`immutable.SortedMap` | `updated` + +## Appendix: Cross-building custom collections ## + +Since the new internal API of the Scala 2.13 collections is very different from the previous +collections API, authors of custom collection types should use separate source directories +(per Scala version) to define them. + +With sbt you can achieve this by adding the following setting to your project: + +~~~ scala +// Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer +// and a `src/main/scala-2.13-` source directory for Scala version older than 2.13 +unmanagedSourceDirectories in Compile += { + val sourceDir = (sourceDirectory in Compile).value + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+" + case _ => sourceDir / "scala-2.13-" + } +} +~~~ + +And then you can define a Scala 2.13 compatible implementation of your collection +in the `src/main/scala-2.13+` source directory, and an implementation for the +previous Scala versions in the `src/main/scala-2.13-` source directory. + +You can see how this has been put in practice in +[scalacheck](https://github.com/rickynils/scalacheck/pull/411) and +[scalaz](https://github.com/scalaz/scalaz/pull/1730). From 72f377c163f7acd4b32fbf11ca6e7eeb12270424 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 7 Jun 2018 21:33:56 -0700 Subject: [PATCH 0218/3174] upgrade nokogiri, because security GitHub's "vulnerability alerts" feature recommended this change, at https://github.com/scala/docs.scala-lang/network/dependencies --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 10d4ab53a1..a2f8d34ff4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -53,7 +53,7 @@ GEM mercenary (0.3.6) mini_portile2 (2.3.0) minitest (5.10.3) - nokogiri (1.8.1) + nokogiri (1.8.2) mini_portile2 (~> 2.3.0) parallel (1.12.0) pathutil (0.14.0) From aedff1a90597b65c7f9d2daceaa468cba5b3d4d1 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 13:47:59 +0200 Subject: [PATCH 0219/3174] May 2018 SIP Meeting Berlin --- _sips/minutes/2018-5-18 | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 _sips/minutes/2018-5-18 diff --git a/_sips/minutes/2018-5-18 b/_sips/minutes/2018-5-18 new file mode 100644 index 0000000000..45f3a9b9d2 --- /dev/null +++ b/_sips/minutes/2018-5-18 @@ -0,0 +1,80 @@ +--- +layout: sips +title: SIP Meeting Minutes - 18th May 2018 + +partof: minutes +--- + +# Minutes + +Open discusion about SIP role and transition with given evolution of Scala language, from Scala 2 to Scala 3. + +Jorge Vicente Cantero was the Process Lead and Darja Jovanovic was the secretary. + + +## Date and Location +The meeting took place on 18th May 2018 in Zalando offices in Berlin, Germany day after ScalaDays 2018 finished. + +Minutes were taken by Darja Jovanovic. + +## Attendees + +* Martin Odersky ([@odersky](https://github.com/odersky)), EPFL +* Jorge Vicente Cantero ([@jvican](https://github.com/jvican)), Process Lead +* Seth Tisue ([@SethTisue](https://github.com/SethTisue)), Lightbend +* Heather Miller ([@heathermiller](https://github.com/heathermiller)), Scala Center +* Sébastien Doeraene ([@sjrd](https://github.com/sjrd)), EPFL +* Adriaan Moors ([@adriaanm](https://github.com/adriaanm)), Lightbend +* Miles Sabin ([@milessabin](https://github.com/milessabin)) + + +## Not present + + + +## Proceedings +### Opening Remarks + +Quorum was not met, but the meeting still took place in a form of an open discussion. + +The meeting was devoted to discussing how we would handle the approval of Scala 3 changes into the specification and how we would organize during the next year, given that Scala 3 will be feature freeze by then. + +Topics discussed: + +1. SIP Committee role in the upcoming Scala 3 release. + +All present agreed that SIP Committee should continue its mandate in approving the Scala 3 changes. + +2. SIP Committee role in Scala 2 + +SIP Committee will focus on Scala 3 changes and creating the spec, **Martin** [YouTube time: 6'54''](https://youtu.be/q2LVmTe9qmU?t=414), Scala 2 SIP proposals will continue as before, but in a slower paste. + +3. How to structure and organise the workflow + +Given the short time and amount of decisions that need to be made, the Committee proposed and agreed about the following + +*Structure* +a) Have a **list of changes**, separated in batches that would be decided within the next year, meeting once a month +b) **Plan** should be consolidated between the Committee members through a Google doc +c) **Public comments** - each batch should be published for a month before discussing on the Contributors thread in order to have community involved, share their opinion and contribute in the proposed changes. The discussions should be in a month time frame, and clearly stated at the beginning of the thread + +*Organisation* +**Jorge** will be in charge of posting the monthly batches on contributors thread and, depending on the subject, one of the Committee Members or a contributor will follow the conversations, answer questions and finally summarize the discussion to be submitted to the Committee in order to make inclusive decisions. +The first batch should be the removals as per list already prepared for 2.14 release. + +The above mentioned structure and organisation was gathered throughout the meeting, here are the snippets: + +- **Adriaan** suggests the batches, to be able to move faster [YouTube time: 5'51''](https://youtu.be/q2LVmTe9qmU?t=351) and gives a reason why [YouTube time: 8'25''](https://youtu.be/q2LVmTe9qmU?t=505). +- **Seth** suggests to put the changes up for public comment [YouTube time: 7.12](https://youtu.be/q2LVmTe9qmU?t=432) +- At [YouTube time: 24'04''](https://youtu.be/q2LVmTe9qmU?t=1444) **Martin** suggests a list of changes that needs to be considered +- **Heather** lays down the structure/organisation idea [YouTube time: 13'51''](https://youtu.be/q2LVmTe9qmU?t=824) +- Between [YouTube time: 19'38'' and 24'](https://youtu.be/q2LVmTe9qmU?t=1178) the Committee discusses and agrees on the next steps: 1. Batches; 2. Plan; 3. Public comments on Contributors + +Other: spec, quorum +**Heather** bings up a question about Scala spec [YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. + +**Miles** [YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525) asks PLEASE ADD + +**Martin** [YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279 ) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. + +**Conclusion** The first batch should be agreed upon, posted on the Contributors thread for public comments. Such discussion should be summaraized and included in the next meeting (22nd June 2018, after ScalaDays NewYork). From ce89a14ee4b59feedd9a331d6e4daca70855aba7 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 13:51:45 +0200 Subject: [PATCH 0220/3174] Update 2018-5-18 --- _sips/minutes/2018-5-18 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sips/minutes/2018-5-18 b/_sips/minutes/2018-5-18 index 45f3a9b9d2..3da66ed325 100644 --- a/_sips/minutes/2018-5-18 +++ b/_sips/minutes/2018-5-18 @@ -26,7 +26,7 @@ Minutes were taken by Darja Jovanovic. * Sébastien Doeraene ([@sjrd](https://github.com/sjrd)), EPFL * Adriaan Moors ([@adriaanm](https://github.com/adriaanm)), Lightbend * Miles Sabin ([@milessabin](https://github.com/milessabin)) - +* Darja Jovanovic ([@darjutak](https://github.com/darjutak) ## Not present From 495128a7b069d70a0b7cafc8100f2c87cfbd2dd5 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 13:53:34 +0200 Subject: [PATCH 0221/3174] Rename 2018-5-18 to 2018-5-18.md --- _sips/minutes/{2018-5-18 => 2018-5-18.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _sips/minutes/{2018-5-18 => 2018-5-18.md} (100%) diff --git a/_sips/minutes/2018-5-18 b/_sips/minutes/2018-5-18.md similarity index 100% rename from _sips/minutes/2018-5-18 rename to _sips/minutes/2018-5-18.md From 85f52cb474739e0fb3a203090cb14204364ce2d6 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:01:16 +0200 Subject: [PATCH 0222/3174] Update 2018-5-18.md --- _sips/minutes/2018-5-18.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/_sips/minutes/2018-5-18.md b/_sips/minutes/2018-5-18.md index 3da66ed325..66fea570e6 100644 --- a/_sips/minutes/2018-5-18.md +++ b/_sips/minutes/2018-5-18.md @@ -25,11 +25,14 @@ Minutes were taken by Darja Jovanovic. * Heather Miller ([@heathermiller](https://github.com/heathermiller)), Scala Center * Sébastien Doeraene ([@sjrd](https://github.com/sjrd)), EPFL * Adriaan Moors ([@adriaanm](https://github.com/adriaanm)), Lightbend -* Miles Sabin ([@milessabin](https://github.com/milessabin)) -* Darja Jovanovic ([@darjutak](https://github.com/darjutak) +* Miles Sabin ([@milessabin](https://github.com/milessabin)), Independent +* Darja Jovanovic ([@darjutak](https://github.com/darjutak)), Scala Center ## Not present +* Iulian Dragos ([@dragos](https://github.com/dragos)), Triplequote +* Eugene Burmako ([@xeno-by](https://github.com/xeno-by)), Twitter +* Josh Suereth ([@jsuereth](https://github.com/jsuereth)), Independent ## Proceedings @@ -47,18 +50,20 @@ All present agreed that SIP Committee should continue its mandate in approving t 2. SIP Committee role in Scala 2 -SIP Committee will focus on Scala 3 changes and creating the spec, **Martin** [YouTube time: 6'54''](https://youtu.be/q2LVmTe9qmU?t=414), Scala 2 SIP proposals will continue as before, but in a slower paste. +SIP Committee will focus on Scala 3 changes and creating the spec, **Martin** [YouTube time: 6'54''](https://youtu.be/q2LVmTe9qmU?t=414), Scala 2 SIP proposals will continue as before, but at a slower pace. 3. How to structure and organise the workflow Given the short time and amount of decisions that need to be made, the Committee proposed and agreed about the following *Structure* + a) Have a **list of changes**, separated in batches that would be decided within the next year, meeting once a month -b) **Plan** should be consolidated between the Committee members through a Google doc +b) **Plan** should be consolidated between the Committee members using a shared a Google doc c) **Public comments** - each batch should be published for a month before discussing on the Contributors thread in order to have community involved, share their opinion and contribute in the proposed changes. The discussions should be in a month time frame, and clearly stated at the beginning of the thread *Organisation* + **Jorge** will be in charge of posting the monthly batches on contributors thread and, depending on the subject, one of the Committee Members or a contributor will follow the conversations, answer questions and finally summarize the discussion to be submitted to the Committee in order to make inclusive decisions. The first batch should be the removals as per list already prepared for 2.14 release. From 4c3869ed074c51b3635cb4a896dd93aa726c22b7 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:02:02 +0200 Subject: [PATCH 0223/3174] Rename 2018-5-18.md to 2018-06-18-sup-minutes.md --- _sips/minutes/{2018-5-18.md => 2018-06-18-sup-minutes.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _sips/minutes/{2018-5-18.md => 2018-06-18-sup-minutes.md} (100%) diff --git a/_sips/minutes/2018-5-18.md b/_sips/minutes/2018-06-18-sup-minutes.md similarity index 100% rename from _sips/minutes/2018-5-18.md rename to _sips/minutes/2018-06-18-sup-minutes.md From 915b1f4174d41ffa0c754c4ab16038aa2d827e82 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:03:25 +0200 Subject: [PATCH 0224/3174] Update 2018-06-18-sup-minutes.md --- _sips/minutes/2018-06-18-sup-minutes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_sips/minutes/2018-06-18-sup-minutes.md b/_sips/minutes/2018-06-18-sup-minutes.md index 66fea570e6..b34be7273e 100644 --- a/_sips/minutes/2018-06-18-sup-minutes.md +++ b/_sips/minutes/2018-06-18-sup-minutes.md @@ -75,7 +75,8 @@ The above mentioned structure and organisation was gathered throughout the meeti - **Heather** lays down the structure/organisation idea [YouTube time: 13'51''](https://youtu.be/q2LVmTe9qmU?t=824) - Between [YouTube time: 19'38'' and 24'](https://youtu.be/q2LVmTe9qmU?t=1178) the Committee discusses and agrees on the next steps: 1. Batches; 2. Plan; 3. Public comments on Contributors -Other: spec, quorum +4. Other: spec, quorum + **Heather** bings up a question about Scala spec [YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. **Miles** [YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525) asks PLEASE ADD From f7213dfafd3fad11b2e29e11639b650a7f800acb Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:07:25 +0200 Subject: [PATCH 0225/3174] Update 2018-06-18-sup-minutes.md --- _sips/minutes/2018-06-18-sup-minutes.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/_sips/minutes/2018-06-18-sup-minutes.md b/_sips/minutes/2018-06-18-sup-minutes.md index b34be7273e..25f9b6e93b 100644 --- a/_sips/minutes/2018-06-18-sup-minutes.md +++ b/_sips/minutes/2018-06-18-sup-minutes.md @@ -13,7 +13,10 @@ Jorge Vicente Cantero was the Process Lead and Darja Jovanovic was the secretary ## Date and Location -The meeting took place on 18th May 2018 in Zalando offices in Berlin, Germany day after ScalaDays 2018 finished. +The meeting took place on 18th May 2018 in Zalando offices in Berlin at 5 PM CET, Germany day after ScalaDays 2018 finished. +All the attendees were in the same room and it was broadcasted via Google HangOuts. + +[Watch on Scala Center YouTube channel](https://youtu.be/q2LVmTe9qmU?t=3) Minutes were taken by Darja Jovanovic. From 72528edbbfc009591896863c234be3accbc7b408 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:09:34 +0200 Subject: [PATCH 0226/3174] Update 2018-06-18-sup-minutes.md --- _sips/minutes/2018-06-18-sup-minutes.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_sips/minutes/2018-06-18-sup-minutes.md b/_sips/minutes/2018-06-18-sup-minutes.md index 25f9b6e93b..48aaba4e70 100644 --- a/_sips/minutes/2018-06-18-sup-minutes.md +++ b/_sips/minutes/2018-06-18-sup-minutes.md @@ -53,7 +53,7 @@ All present agreed that SIP Committee should continue its mandate in approving t 2. SIP Committee role in Scala 2 -SIP Committee will focus on Scala 3 changes and creating the spec, **Martin** [YouTube time: 6'54''](https://youtu.be/q2LVmTe9qmU?t=414), Scala 2 SIP proposals will continue as before, but at a slower pace. +SIP Committee will focus on Scala 3 changes and creating the spec, **Martin** ([YouTube time: 6'54''](https://youtu.be/q2LVmTe9qmU?t=414)), Scala 2 SIP proposals will continue as before, but at a slower pace. 3. How to structure and organise the workflow @@ -72,18 +72,18 @@ The first batch should be the removals as per list already prepared for 2.14 rel The above mentioned structure and organisation was gathered throughout the meeting, here are the snippets: -- **Adriaan** suggests the batches, to be able to move faster [YouTube time: 5'51''](https://youtu.be/q2LVmTe9qmU?t=351) and gives a reason why [YouTube time: 8'25''](https://youtu.be/q2LVmTe9qmU?t=505). -- **Seth** suggests to put the changes up for public comment [YouTube time: 7.12](https://youtu.be/q2LVmTe9qmU?t=432) -- At [YouTube time: 24'04''](https://youtu.be/q2LVmTe9qmU?t=1444) **Martin** suggests a list of changes that needs to be considered -- **Heather** lays down the structure/organisation idea [YouTube time: 13'51''](https://youtu.be/q2LVmTe9qmU?t=824) +- **Adriaan** suggests the batches, to be able to move faster ([YouTube time: 5'51''](https://youtu.be/q2LVmTe9qmU?t=351)) and gives a reason why ([YouTube time: 8'25''](https://youtu.be/q2LVmTe9qmU?t=505)). +- **Seth** suggests to put the changes up for public comment ([YouTube time: 7.12](https://youtu.be/q2LVmTe9qmU?t=432)) +- At ([YouTube time: 24'04''](https://youtu.be/q2LVmTe9qmU?t=1444)) **Martin** suggests a list of changes that needs to be considered +- **Heather** lays down the structure/organisation idea ([YouTube time: 13'51''](https://youtu.be/q2LVmTe9qmU?t=824)) - Between [YouTube time: 19'38'' and 24'](https://youtu.be/q2LVmTe9qmU?t=1178) the Committee discusses and agrees on the next steps: 1. Batches; 2. Plan; 3. Public comments on Contributors 4. Other: spec, quorum -**Heather** bings up a question about Scala spec [YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. +**Heather** bings up a question about Scala spec ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. -**Miles** [YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525) asks PLEASE ADD +**Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525)) asks PLEASE ADD -**Martin** [YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279 ) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. +**Martin** ([YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279)) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. **Conclusion** The first batch should be agreed upon, posted on the Contributors thread for public comments. Such discussion should be summaraized and included in the next meeting (22nd June 2018, after ScalaDays NewYork). From 7cccddc971411414e10c8ad8adb2d62b99dc9170 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:14:07 +0200 Subject: [PATCH 0227/3174] Rename 2018-06-18-sup-minutes.md to 2018-06-18-sip-minutes.md --- .../{2018-06-18-sup-minutes.md => 2018-06-18-sip-minutes.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _sips/minutes/{2018-06-18-sup-minutes.md => 2018-06-18-sip-minutes.md} (100%) diff --git a/_sips/minutes/2018-06-18-sup-minutes.md b/_sips/minutes/2018-06-18-sip-minutes.md similarity index 100% rename from _sips/minutes/2018-06-18-sup-minutes.md rename to _sips/minutes/2018-06-18-sip-minutes.md From 4b8ee463a3bebf9b2759266c16c4d322e7aec18a Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:26:20 +0200 Subject: [PATCH 0228/3174] Update 2018-06-18-sip-minutes.md --- _sips/minutes/2018-06-18-sip-minutes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sips/minutes/2018-06-18-sip-minutes.md b/_sips/minutes/2018-06-18-sip-minutes.md index 48aaba4e70..93ef43dbff 100644 --- a/_sips/minutes/2018-06-18-sip-minutes.md +++ b/_sips/minutes/2018-06-18-sip-minutes.md @@ -7,7 +7,7 @@ partof: minutes # Minutes -Open discusion about SIP role and transition with given evolution of Scala language, from Scala 2 to Scala 3. +Open discusion about SIP role and transition with given evolution of Scala language, from Scala 2 to Scala 3. The conversation was prompted due to the wake of Martin Odersky's keynote at Scala Days, Berlin 2018 introducing the future of Scala - Scala 3 (link to the key note will be added once published by the organisers). Jorge Vicente Cantero was the Process Lead and Darja Jovanovic was the secretary. From 1e88d537216f923711e63c9fb2979baeade52587 Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Tue, 12 Jun 2018 17:06:09 +0200 Subject: [PATCH 0229/3174] Update 2018-06-18-sip-minutes.md --- _sips/minutes/2018-06-18-sip-minutes.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/_sips/minutes/2018-06-18-sip-minutes.md b/_sips/minutes/2018-06-18-sip-minutes.md index 93ef43dbff..d8f69eb48d 100644 --- a/_sips/minutes/2018-06-18-sip-minutes.md +++ b/_sips/minutes/2018-06-18-sip-minutes.md @@ -43,7 +43,7 @@ Minutes were taken by Darja Jovanovic. Quorum was not met, but the meeting still took place in a form of an open discussion. -The meeting was devoted to discussing how we would handle the approval of Scala 3 changes into the specification and how we would organize during the next year, given that Scala 3 will be feature freeze by then. +The meeting was devoted to discussing how SIP Committee should handle the approval of Scala 3 changes into the specification and how it would organize during the next year, given that Scala 3 will be feature freeze by then. Topics discussed: @@ -61,13 +61,13 @@ Given the short time and amount of decisions that need to be made, the Committee *Structure* -a) Have a **list of changes**, separated in batches that would be decided within the next year, meeting once a month -b) **Plan** should be consolidated between the Committee members using a shared a Google doc -c) **Public comments** - each batch should be published for a month before discussing on the Contributors thread in order to have community involved, share their opinion and contribute in the proposed changes. The discussions should be in a month time frame, and clearly stated at the beginning of the thread +a) Have a **list of changes**, grouped in batches that would be decided within the next year, meeting once a month +b) **Plan** - full and strucutured list of changes that need to be implemented consolidated between the Committee members using a shared a Google doc +c) **Public comments** - each batch should be published on the Contributors thread, for a month at a time in order to have community involved, share their opinion and contribute. Advise was proposed - each thread should clearly point out start and end date of collecting the comments/suggestions. *Organisation* -**Jorge** will be in charge of posting the monthly batches on contributors thread and, depending on the subject, one of the Committee Members or a contributor will follow the conversations, answer questions and finally summarize the discussion to be submitted to the Committee in order to make inclusive decisions. +**Jorge** will be in charge of posting the monthly batches on contributors thread. One of the Committee Members (SIP reviewer) or SIP author will be assigned/volunteer to follow the conversations, answer questions and finally summarize the discussion to be submitted to the Committee in order to make inclusive decision. The first batch should be the removals as per list already prepared for 2.14 release. The above mentioned structure and organisation was gathered throughout the meeting, here are the snippets: @@ -80,9 +80,9 @@ The above mentioned structure and organisation was gathered throughout the meeti 4. Other: spec, quorum -**Heather** bings up a question about Scala spec ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. +**Heather** bings up an important question "What about Scala spec" ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. -**Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525)) asks PLEASE ADD +**Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525)) states that SIP proposals should be directly linked to specification changes which will save a lot of time and effort. **Martin** ([YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279)) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. From a7fbbaab613498fdaa8c07fb2656966a4fc66dfb Mon Sep 17 00:00:00 2001 From: darjutak <31061184+darjutak@users.noreply.github.com> Date: Wed, 13 Jun 2018 10:41:03 +0200 Subject: [PATCH 0230/3174] Update 2018-06-18-sip-minutes.md --- _sips/minutes/2018-06-18-sip-minutes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_sips/minutes/2018-06-18-sip-minutes.md b/_sips/minutes/2018-06-18-sip-minutes.md index d8f69eb48d..3f4c390f78 100644 --- a/_sips/minutes/2018-06-18-sip-minutes.md +++ b/_sips/minutes/2018-06-18-sip-minutes.md @@ -7,7 +7,7 @@ partof: minutes # Minutes -Open discusion about SIP role and transition with given evolution of Scala language, from Scala 2 to Scala 3. The conversation was prompted due to the wake of Martin Odersky's keynote at Scala Days, Berlin 2018 introducing the future of Scala - Scala 3 (link to the key note will be added once published by the organisers). +Open discussion about SIP role and transition with given evolution of Scala language, from Scala 2 to Scala 3. The conversation was prompted due to the wake of Martin Odersky's keynote at Scala Days, Berlin 2018 introducing the future of Scala - Scala 3 (link to the key note will be added once published by the organisers). Jorge Vicente Cantero was the Process Lead and Darja Jovanovic was the secretary. @@ -82,7 +82,7 @@ The above mentioned structure and organisation was gathered throughout the meeti **Heather** bings up an important question "What about Scala spec" ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. -**Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525)) states that SIP proposals should be directly linked to specification changes which will save a lot of time and effort. +**Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525))suggested that SIP proposals should include draft specification changes to save time and effort pulling the eventual spec update together. **Martin** ([YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279)) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. From d8949a957441347bee80324222b8156b04f12c52 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 13 Jun 2018 11:49:18 +0200 Subject: [PATCH 0231/3174] Fix minutes date --- .../{2018-06-18-sip-minutes.md => 2018-05-18-sip-minutes.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _sips/minutes/{2018-06-18-sip-minutes.md => 2018-05-18-sip-minutes.md} (100%) diff --git a/_sips/minutes/2018-06-18-sip-minutes.md b/_sips/minutes/2018-05-18-sip-minutes.md similarity index 100% rename from _sips/minutes/2018-06-18-sip-minutes.md rename to _sips/minutes/2018-05-18-sip-minutes.md From 6a4165565a1006956734fe02971b0ee3b2502055 Mon Sep 17 00:00:00 2001 From: pacom20003 Date: Thu, 14 Jun 2018 16:43:01 -0400 Subject: [PATCH 0232/3174] Simple gramar fix --- .../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 6b0d28940d..74bfff8b5b 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 @@ -62,7 +62,7 @@ object Main extends App { } ``` -Note: IntelliJ has its own implementation the Scala compiler, and sometimes your +Note: IntelliJ has its own implementation of the Scala compiler, and sometimes your code is correct even though IntelliJ indicates otherwise. You can always check to see if sbt can run your project on the command line. From 07e325985066e97226482519aa4ed30b98a6fc1f Mon Sep 17 00:00:00 2001 From: bogamedia Date: Sun, 17 Jun 2018 13:50:21 -0600 Subject: [PATCH 0233/3174] Update getting-started-with-scala-in-intellij.md --- .../getting-started-with-scala-in-intellij.md | 3 ++- 1 file changed, 2 insertions(+), 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 ea7027178d..6a555ba411 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 @@ -55,7 +55,8 @@ A good way to try out code samples is with Scala Worksheets 1. In the project pane on the left, right click `src` and select **New** => **Scala Worksheet**. -1. Enter the following code into the worksheet: +2. Name your new Scala worksheet "Mathematician". +3. Enter the following code into the worksheet: ``` def square(x: Int) = x * x From 3de1c10c81c53e127a42d98773abaa2c07bd502f Mon Sep 17 00:00:00 2001 From: ajaysunilsharma Date: Wed, 20 Jun 2018 07:06:02 +0530 Subject: [PATCH 0234/3174] Update for page for-comprehensions in Scala Tour Page mentions guard filters out users who are in their 20s but the guard is actually filtering out those users who are not in their 20s. --- _tour/for-comprehensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/for-comprehensions.md b/_tour/for-comprehensions.md index 1a2a73dfbb..d8881cb326 100644 --- a/_tour/for-comprehensions.md +++ b/_tour/for-comprehensions.md @@ -30,7 +30,7 @@ val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30) twentySomethings.foreach(name => println(name)) // prints Travis Dennis ``` -The `for` loop used with a `yield` statement actually creates a `List`. Because we said `yield user.name`, it's a `List[String]`. `user <- userBase` is our generator and `if (user.age >=20 && user.age < 30)` is a guard that filters out users who are in their 20s. +The `for` loop used with a `yield` statement actually creates a `List`. Because we said `yield user.name`, it's a `List[String]`. `user <- userBase` is our generator and `if (user.age >=20 && user.age < 30)` is a guard that filters out users who are not in their 20s. Here is a more complicated example using two generators. It computes all pairs of numbers between `0` and `n-1` whose sum is equal to a given value `v`: From 8bcfe7133c5b63a85c0b72a063ee64a68dd237aa Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Tue, 26 Jun 2018 11:00:54 +0200 Subject: [PATCH 0235/3174] Be clearer around indentation Add an extra level of indentation for demonstration purposes, and clarify language --- _style/indentation.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/_style/indentation.md b/_style/indentation.md index c378957e17..247c07bb05 100644 --- a/_style/indentation.md +++ b/_style/indentation.md @@ -11,19 +11,25 @@ previous-page: overview next-page: naming-conventions --- -Indentation should follow the "2-space convention". Thus, instead of +Each level of indentation is 2 spaces. Tabs are not used. Thus, instead of indenting like this: // wrong! class Foo { - def bar = ... + def fourspaces = { + val x = 4 + .. + } } You should indent like this: // right! class Foo { - def bar = .. + def twospaces = { + val x = 2 + .. + } } The Scala language encourages a startling amount of nested scopes and From 42941be7798d4e0d72d997a30f45706993f9da56 Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Tue, 26 Jun 2018 14:39:27 +0200 Subject: [PATCH 0236/3174] More descriptive SIP channel link title --- _layouts/sips.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_layouts/sips.html b/_layouts/sips.html index 6c26e24cec..00d1d6c2e7 100644 --- a/_layouts/sips.html +++ b/_layouts/sips.html @@ -31,7 +31,7 @@
    Next meeting:
    From 03cb83dbbf3babb406ec511d6ba3bea6fb9a19a1 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 26 Jun 2018 10:06:09 -0400 Subject: [PATCH 0237/3174] correction: Youtube -> YouTube --- _layouts/sips.html | 2 +- learn.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_layouts/sips.html b/_layouts/sips.html index 00d1d6c2e7..c2f2af3a41 100644 --- a/_layouts/sips.html +++ b/_layouts/sips.html @@ -31,7 +31,7 @@
    Next meeting:
    diff --git a/learn.md b/learn.md index a2d69833df..3ec8a4909a 100644 --- a/learn.md +++ b/learn.md @@ -34,11 +34,11 @@ you get a certificate of completion from Coursera on the paid version. You can l ## Dr.Mark C Lewis's Lectures from Trinity University - * [Dr.Mark C Lewis](http://www.cs.trinity.edu/~mlewis/) from Trinity University, San Antonio, TX, teaches programming courses using the Scala language. Course videos are available in Youtube for free. Some of the courses below. + * [Dr.Mark C Lewis](http://www.cs.trinity.edu/~mlewis/) from Trinity University, San Antonio, TX, teaches programming courses using the Scala language. Course videos are available in YouTube for free. Some of the courses below. * [Introduction to Programming and Problem Solving Using Scala](https://www.youtube.com/playlist?list=PLLMXbkbDbVt9MIJ9DV4ps-_trOzWtphYO) * [Object-Orientation, Abstraction, and Data Structures Using Scala](https://www.youtube.com/playlist?list=PLLMXbkbDbVt8JLumqKj-3BlHmEXPIfR42) - You can visit his [Youtube channel](https://www.youtube.com/user/DrMarkCLewis/featured) for more videos. + You can visit his [YouTube channel](https://www.youtube.com/user/DrMarkCLewis/featured) for more videos. ## Try Scala In Your Browser! From 3460aee7bb69979945aa47b6483d95cf7fde7a2d Mon Sep 17 00:00:00 2001 From: Seph Lietz Date: Wed, 27 Jun 2018 21:40:29 -0500 Subject: [PATCH 0238/3174] Scala Compiler Options minor copy edits --- _overviews/compiler-options/index.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/_overviews/compiler-options/index.md b/_overviews/compiler-options/index.md index 69e2338a82..aa228ba67d 100644 --- a/_overviews/compiler-options/index.md +++ b/_overviews/compiler-options/index.md @@ -27,21 +27,21 @@ discourse: true ## Introduction -Scala compiler `scalac` offers various **compiler options**, also referred as **compiler flags**, to change how to compile your program. +Scala compiler `scalac` offers various **compiler options**, also referred to as **compiler flags**, to change how to compile your program. -Nowadays, most people are not running scalac from the command line. -Instead, they use sbt, IDE, and other tools as their interface to the compiler. -Therefore they may not even have scalac installed, and won't think to do `man scalac`. +Nowadays, most people are not running `scalac` from the command line. +Instead, they use sbt, an IDE, and other tools as their interface to the compiler. +Therefore they may not even have `scalac` installed, and won't think to do `man scalac`. -This page come to the rescue for the people to find... +This page comes to the rescue for the people to find… -* What compiler options scalac offers -* How to use compiler option +* What compiler options `scalac` offers +* How to use compiler options ## How to use compiler options -### Use compiler option with scalac +### Use compiler options with scalac ```bash scalac [ ] @@ -51,7 +51,7 @@ E.g. `scalac -encoding utf8 -Xfatal-warnings Hello.scala` -### Use compiler option with sbt +### Use compiler options with sbt @@ -182,4 +182,4 @@ scalacOptions ++= Seq(
    all
    matches all phases
    - \ No newline at end of file + From db7efadc0a39e5496bb3035746ab2d80103de30e Mon Sep 17 00:00:00 2001 From: som-snytt Date: Sat, 30 Jun 2018 04:00:31 -0700 Subject: [PATCH 0239/3174] Sip/underscoreless (#1090) --- _sips/sips/2018-05-26-case-if.md | 40 +++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/_sips/sips/2018-05-26-case-if.md b/_sips/sips/2018-05-26-case-if.md index f246fcfe6c..b9e6200671 100644 --- a/_sips/sips/2018-05-26-case-if.md +++ b/_sips/sips/2018-05-26-case-if.md @@ -14,9 +14,10 @@ redirect_from: /sips/pending/case-if.html ## History -| Date | Version | -|---------------|---------------| -| May 26th 2018 | Initial Draft | +| Date | Version | +|---------------|----------------| +| May 26th 2018 | Initial Draft | +| May 28th 2018 | Underscoreless | ## Motivation @@ -34,18 +35,46 @@ We propose to go underscoreless, pace the famous consultancy. If we can't have SIP-12 then we can have tidy syntax for `if-then` in `case` blocks. +Since `Scala <3` abhors two ways of doing a thing, we eliminate underscore +as a pattern. Underscore as a subpattern, that is, as a `pattern2`, is patterned +after placeholder syntax in expressions, just as constructor patterns are patterned +after constructor invocations. We read `C(_)` and `case C(_) =>` to mean construction +of `C` with an argument unspecified. Similarly, just as placeholder syntax is +restricted, so that an underscore is never an `Expr`, pattern syntax must disallow +underscore as a `Pattern` production. + +In fact, underscore never quite functioned that way, since the definition + + val _ = 42 + +has always incorrectly introduced a variable named `_`. + +Suggestions have surfaced that this syntax should mean something entirely different, +namely, the introduction of a freshly named variable which cannot be named in +source code, but induces the evaluation of the RHS of the definition, and which +can be accessed implicitly if defined as an implicit value. + +However that may be, underscore must first be disallowed as a `Pattern`. + +The only way to coherently define a `case` for which no pattern is applied is to omit +the pattern. And in the absence of alternative semantics, `val _` is not meaningful. +Underscore on the RHS of `var` definitions has already been deprecated, and it is +expected that that syntax will also be removed. + ## Syntax In lieu of 42 match { case _ if now isAfter midnight => nothingGoodHappens() + case _ => () } we write 42 match { case if now isAfter midnight => nothingGoodHappens() + case => () } The syntax accepts either a pattern with optional guard, or a guard with no pattern: @@ -53,11 +82,6 @@ The syntax accepts either a pattern with optional guard, or a guard with no patt CaseClause ::= ‘case’ (Pattern [Guard] | Guard) ‘=>’ Block Guard ::= ‘if’ PostfixExpr -A guard with no pattern is taken as though the pattern were an underscore, which matches -any value. - -This modest proposal eschews dispensing with the pattern altogether, `case =>`. - ## Further Justifications In a respected online [forum][2] which brooks no fools, [Mulliganaceous][3] has posted From 5ac9c209ec572f1be183ce8e6c55d2f2cd9d9f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sakib=20Had=C5=BEiavdi=C4=87?= Date: Sat, 7 Jul 2018 12:52:20 +0200 Subject: [PATCH 0240/3174] Added contributors widget (#1098) Fixes #44 Following [this answer](https://stackoverflow.com/a/19200303/4496364) I managed to get this via Github API: ![](https://upload.cc/i1/2018/07/04/n4zkhJ.png) I roughly followed Mozilla's [docs page](https://developer.mozilla.org/en-US/docs/Web/HTML) design and their contributors listing. Some users don't have the "author" field. Probably deleted their profile? So, the fallback is `commit.commit.committer.name` which is, I suppose, always present because of Git... Also, if the author isn't present, image icon is generated with https://github.com/identicons. Example here is Ghildiyal user. Currently, I added this to tour only. IDK did you guys intend to put these on each page? If so, there could be some problems with getting page URL from Github. IDK if all of them follow same pattern as "tours".. --- _includes/contributors-list.html | 4 ++ _includes/inner-page-main-content.html | 2 + _layouts/cheatsheet.html | 2 + _layouts/glossary.html | 2 + _layouts/multipage-overview.html | 2 + _layouts/singlepage-overview.html | 2 + _layouts/style-guide.html | 2 + _layouts/tour.html | 2 + _sass/layout/content-contributors.scss | 22 +++++++ resources/css/style.scss | 3 +- resources/js/functions.js | 83 +++++++++++++++++++++++++- 11 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 _includes/contributors-list.html create mode 100644 _sass/layout/content-contributors.scss diff --git a/_includes/contributors-list.html b/_includes/contributors-list.html new file mode 100644 index 0000000000..0feecc424e --- /dev/null +++ b/_includes/contributors-list.html @@ -0,0 +1,4 @@ +
    +

    Contributors to this page:

    +
    +
    diff --git a/_includes/inner-page-main-content.html b/_includes/inner-page-main-content.html index 9587a304cb..78a954b5ae 100644 --- a/_includes/inner-page-main-content.html +++ b/_includes/inner-page-main-content.html @@ -3,6 +3,8 @@
    {{content}} + + {% include contributors-list.html %}
    diff --git a/_layouts/cheatsheet.html b/_layouts/cheatsheet.html index 6dacd54d46..471a120c4f 100644 --- a/_layouts/cheatsheet.html +++ b/_layouts/cheatsheet.html @@ -30,6 +30,8 @@ {% endfor %} {% endif %} + + {% include contributors-list.html %}
    diff --git a/_layouts/glossary.html b/_layouts/glossary.html index ea5d5dde0f..e65a189e23 100644 --- a/_layouts/glossary.html +++ b/_layouts/glossary.html @@ -8,6 +8,8 @@
    {{content}} + + {% include contributors-list.html %}
    diff --git a/_layouts/multipage-overview.html b/_layouts/multipage-overview.html index cf7c0b5a32..a98e6742e3 100644 --- a/_layouts/multipage-overview.html +++ b/_layouts/multipage-overview.html @@ -9,6 +9,8 @@
    {{content}} + + {% include contributors-list.html %}
    diff --git a/_layouts/singlepage-overview.html b/_layouts/singlepage-overview.html index 87c3279b92..72cabad3fd 100644 --- a/_layouts/singlepage-overview.html +++ b/_layouts/singlepage-overview.html @@ -8,6 +8,8 @@
    {{content}} + + {% include contributors-list.html %}
    diff --git a/_layouts/style-guide.html b/_layouts/style-guide.html index 8028663a43..ecc9a53bf2 100644 --- a/_layouts/style-guide.html +++ b/_layouts/style-guide.html @@ -9,6 +9,8 @@
    {{content}} + + {% include contributors-list.html %}
    diff --git a/_layouts/tour.html b/_layouts/tour.html index a7f96b55c1..9369547dd7 100644 --- a/_layouts/tour.html +++ b/_layouts/tour.html @@ -20,6 +20,8 @@ next {% endif %} + + {% include contributors-list.html %} diff --git a/_sass/layout/content-contributors.scss b/_sass/layout/content-contributors.scss new file mode 100644 index 0000000000..ebf6f00b98 --- /dev/null +++ b/_sass/layout/content-contributors.scss @@ -0,0 +1,22 @@ +.content-contributors { + .contributors-container { + display: flex; + flex-wrap: wrap; + align-items: center; + div { + margin: 5px; + a { + vertical-align: middle; + padding: 3px; + text-decoration: none; + } + img { + vertical-align: middle; + width: 35px; + height: 35px; + margin-bottom: 0; + border-radius: 7px; + } + } + } +} diff --git a/resources/css/style.scss b/resources/css/style.scss index d6ce6e6aa6..7d297f71ea 100755 --- a/resources/css/style.scss +++ b/resources/css/style.scss @@ -54,7 +54,8 @@ @import 'layout/books'; @import 'layout/training-events'; @import 'layout/blog'; -@import 'layout/download'; // COMPONENTS +@import 'layout/download'; +@import 'layout/content-contributors'; // COMPONENTS //------------------------------------------------ //------------------------------------------------ @import 'components/buttons'; diff --git a/resources/js/functions.js b/resources/js/functions.js index d7e85b0646..ed94b16a9f 100644 --- a/resources/js/functions.js +++ b/resources/js/functions.js @@ -521,4 +521,85 @@ $(document).ready(function(){ $("html, body").animate({ scrollTop: 0 }, 600); return false; }); -}); \ No newline at end of file +}); + +//Contributors widget +// see https://stackoverflow.com/a/19200303/4496364 +$(document).ready(function () { + let githubApiUrl = 'https://api.github.com/repos/scala/docs.scala-lang/commits'; + let identiconsUrl = 'https://github.com/identicons'; + /* - we need to transform "/tour/basics.html" to "_ba/tour/basics.md" + * - 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', + 'plugins', 'quasiquotes', 'reflection', + 'repl', 'scaladoc', 'tutorials' + ]; + + let thisPageUrl = window.location.pathname; + // chop off beginning slash and ending .html + thisPageUrl = thisPageUrl.substring(1, thisPageUrl.lastIndexOf('.')); + let isRootFile = rootFiles.some(rf => thisPageUrl.startsWith(rf)); + let isInOverviewsFolder = overviewsFolders.some(of => thisPageUrl.startsWith(of)); + if(isRootFile) { + thisPageUrl = thisPageUrl + '.md'; + } else if(isInOverviewsFolder) { + thisPageUrl = '_overviews/'+ thisPageUrl + '.md'; + } else { + thisPageUrl = '_' + thisPageUrl + '.md'; + } + + let url = githubApiUrl + '?path=' + thisPageUrl; + $.get(url, function (data, status) { + if(!data || data.length < 1) { + $('.content-contributors').html(''); // clear content + return false; // break + } + let contributorsUnique = []; + data.forEach(commit => { + // add if not already in array + let addedToList = contributorsUnique.find(c => { + let matches = c.authorName == commit.commit.author.name; + if (!matches && commit.author) { + matches = c.authorName == commit.author.login; + } + return matches; + }); + + if (!addedToList) { + // first set fallback properties + let authorName = commit.commit.author.name; + let authorLink = ''; + let authorImageLink = identiconsUrl + '/' + commit.commit.author.name + '.png'; + // if author present, fill these preferably + if (commit.author) { + authorName = commit.author.login; + authorLink = commit.author.html_url; + authorImageLink = commit.author.avatar_url; + } + contributorsUnique.push({ + 'authorName': authorName, + 'authorLink': authorLink, + 'authorImageLink': authorImageLink + }); + } + }); + + let contributorsHtml = ''; + contributorsUnique.forEach(contributor => { + let contributorHtml = '
    '; + contributorHtml += ''; + if (contributor.authorLink) + contributorHtml += '' + contributor.authorName + ''; + else + contributorHtml += '' + contributor.authorName + ''; + contributorHtml += '
    '; + contributorsHtml += contributorHtml; + }); + $('#contributors').html(contributorsHtml); + }); +}); From ae2e753b111af2c9e5cbe5f4ad58bb188a085674 Mon Sep 17 00:00:00 2001 From: Pavel Date: Mon, 9 Jul 2018 12:32:10 +0300 Subject: [PATCH 0241/3174] Add Algolia search for documentation. Need test in prod. (#1096) * Add Algolia search for documentation. Need test in prod. * add full width on mobile screen --- _includes/footer.html | 11 +++++++++++ _includes/headertop.html | 3 +++ _layouts/inner-page-parent.html | 22 +++++++++++++++------- _sass/components/search.scss | 12 ++++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/_includes/footer.html b/_includes/footer.html index 4767f2e7ab..7171b3c1f5 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -95,6 +95,17 @@ }); {% endif %} + + + + diff --git a/_includes/headertop.html b/_includes/headertop.html index bf2150c17b..383d5eacfa 100644 --- a/_includes/headertop.html +++ b/_includes/headertop.html @@ -23,3 +23,6 @@ + + + diff --git a/_layouts/inner-page-parent.html b/_layouts/inner-page-parent.html index 8940ae4e54..3ed25753ca 100644 --- a/_layouts/inner-page-parent.html +++ b/_layouts/inner-page-parent.html @@ -1,6 +1,4 @@ - -{% include headertop.html %} -{% include headerbottom.html %} + {% include headertop.html %} {% include headerbottom.html %} @@ -11,13 +9,23 @@
    -

    {{page.title}}

    +
    + +

    {{page.title}}

    +
    + + + +
    +
    +
    - {% comment %}Specific content from child layouts{% endcomment %} - {{content}} + {% comment %}Specific content from child layouts{% endcomment %} {{content}} -{% include footer.html %} +{% include footer.html %} \ No newline at end of file diff --git a/_sass/components/search.scss b/_sass/components/search.scss index 6bccdd20b8..de18915531 100755 --- a/_sass/components/search.scss +++ b/_sass/components/search.scss @@ -4,7 +4,19 @@ .search-container { position: relative; + margin-top: 20px; + margin-bottom: 20px; + + .algolia-autocomplete { + width: 100%; + } + @media screen and (min-width: 768px) { + margin: 0; + margin-top: -20px; + float: right; + width: 24%; + } .icon-search { position: absolute; left: 14px; From 8edfca2f94895463ecfca98a3088ca3e4d9f3593 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Mon, 9 Jul 2018 11:34:36 +0200 Subject: [PATCH 0242/3174] Update favicon and add it for various platforms (#1092) --- _includes/headertop.html | 7 ++++ resources/android-chrome-192x192.png | Bin 0 -> 5913 bytes resources/android-chrome-512x512.png | Bin 0 -> 15386 bytes resources/apple-touch-icon.png | Bin 0 -> 4933 bytes resources/browserconfig.xml | 9 +++++ resources/favicon-16x16.png | Bin 0 -> 995 bytes resources/favicon-32x32.png | Bin 0 -> 1609 bytes resources/favicon.ico | Bin 570 -> 15086 bytes resources/mstile-150x150.png | Bin 0 -> 4442 bytes resources/safari-pinned-tab.svg | 54 +++++++++++++++++++++++++++ resources/site.webmanifest | 19 ++++++++++ 11 files changed, 89 insertions(+) create mode 100644 resources/android-chrome-192x192.png create mode 100644 resources/android-chrome-512x512.png create mode 100644 resources/apple-touch-icon.png create mode 100644 resources/browserconfig.xml create mode 100644 resources/favicon-16x16.png create mode 100644 resources/favicon-32x32.png create mode 100644 resources/mstile-150x150.png create mode 100644 resources/safari-pinned-tab.svg create mode 100644 resources/site.webmanifest diff --git a/_includes/headertop.html b/_includes/headertop.html index 383d5eacfa..e39ab97d51 100644 --- a/_includes/headertop.html +++ b/_includes/headertop.html @@ -10,6 +10,13 @@ + + + + + + + diff --git a/resources/android-chrome-192x192.png b/resources/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..60d23b724712e81e28aaed8c6e1d0981c24f28e0 GIT binary patch literal 5913 zcmb`Lc|26{yT{KMTb72#GPWT?5>X8zg)CVb85P+XOZE{l*_yFsFOn@GC6O?Mu}_wS zL}fP^Yql6mmTdQQ|NGt7>;84`>wM4op7TAg=Q+ zK~X_fL)vhchgrbEBTP+EkjqFxP~+&mi4o7GVaYcTAIYwdeaXqrJtDo?!<81|+Z_C90@@7JQ>faJ&I6mceNYvvH zv(i1ePz_yW3>Cx+lVN6C9J~&MSkre464aS~lPub!6J-8-n{^2xkd@XJvca-#cgoay-pw+5*4qdKMk=Ygphsyz9wfL za+PuJjzZT@a$IKmq>K|845vUTY6J-i#4Z^^R`?(q4PlPflKDyDyfMyM&ndkrK}Ihf zr{23EX_zUb!*NrKtq@7;O#iJy5^d(x8-H9k@1fSKU9wQ?+6sicabYcwH2hOX2*SCB zvPy4`krUlS^tVQ15q8fO^f#o?Uq*ejnuN?=ueK+ATeh>FPhJcF6e)5TF7gxj%ITHZ zFTW}BRPtYB7GI`1%K@3>Q(lu1qYl3ON8yhJX0voMU1*t7z@UF8#Bo2av; z7lBKfI^|oVul==|SAY@vk>HvIVVtZI?>K!+P?2yG`~q6}+)&o%x*THvhk<5i67x`~ z^3=cF?6%|G84Oi+kocFU-Dl`dv{m5v6#;F5`mJPl}#fsil zsc|j`V6t{5&-kpB!Nv9wk?gw`)8=ZkTX0{HM%s0rEnr;B}0!k^w7#4P{72uU@>Q-XIup1Um8fDR^{lBjH ze_cR#1{djnfbXHSC%Wuu?37Yy*Fk8`;5Ck$-0Kl$Dxc1|x9qCS_M@A-ey0zr$z0Iy z%p?tIJ)EAP#yX0&eo#FM4{cgqI?0UCy5Bt~c_aB)sFePte*H@|d>aeyteo~eEHm376D;LI4u<S3CezoaGXvdOqcW?Nceghag|)8r zbz!n?1z^fc`%|~vvy2~UxVjsL=)6PZ_E<^zQ5*{!i#az6-;egR%lvZaexcu)uU+xR zx_moUWTkj04w03PbVu#xKo)^L1RYcFHC8sFE zrPnjeeH9;Qc?(^08(U4$S=L#{PYC=C#^-fRV}?9V3OfR$;n?hpPCzvnx}rW zztV4Ibdmo=cVz2xdEY|&yFvrS@LEz@6T0z?nB>poj?9m8n-7coX=^0zEp0S9zvN*c z7t{l|P5s5-qTYeUx(Z3pFnOlmxR`dHWNU=lD0DUv8W~A8kDFW9?y=oN4=yPi9A--x zldAb}ejmTR{=gid13`Y{3D=$F#7X+J1ctf0$H@7`+qaqXnYPpqe9g}sZdFKgoBQZ| z5>Y@~jQB>8$E6 zj#xk#I#@3XWl=W#H`(@;y3It7RBuRZUChFFv4jAf$+JmGu%A;AUti#l*t$?%juy+rP8@4_a z(8etq_pCmbvG2M0F~K5`@w-=o+#rt^xgQI12f0J0iN?7DhOPFzAxRh^THS`Mut4E( z4CRO)+H+<{f!@V7{@zZuC>Ar0Xp4aHehkhLc_r(4Tv>djB+@AI${!Dhlcfs}n6z!* z^f3cF-`!XU3wN-{9X|T0l{kJ;=#{WNKFs@x-^M&ka5Bj!; z1b3E8n3fY5wg$BPb-?)b-V8A19C`I)4lOw1A+e6mWt3&V_iG`vJ&FoWl#ZkwfJ*8m zwj2=T9W@@Bm=n{m5M;!RRLdhYn0(2$pnN-RCr-bIw+Rrx!Pun8`~%QobBWqrxHBz7 zlc5UIZi z-=}b8Wj@T~pd06TK>Dp^0-Rzy-T3OGs7rJJboDFpi7yMs_ZM@!+wLt!^Og)xIw&qd zh_Va!_X;U4m+ANZmc+01^Uhsa=jZpze05&qTqMR7f)B0j$0K(H6(Ce-Jya!DHtjgW zGv$qp8NrW{_IL9s?J@N$HL4+J=^1R7tD+#IS~;LIaa_!mDVgSC8#8)p#vK`~(&JZ3 z8s{=ja^Q}UFOIogX5YWG!a;%!#)R^hU_(kHMJUlsx3he|xDZ3cHhGdT@jFPl2`qIx zoi$hrn$yt>o(iyEuG%T_h`Aiu^Ow=8v^PJZrs7s7(6E_x(gyr3G5l@@A-*OroIQSz z6;{H`@zr75Oa|&Ii$UMhR~3=?c-{#0Oi#`p2@FlPzajW_wFgATy0i7BAZ_M*_^y5E zr4WJ;XAu-defd?l;zQ&TyAfoR@PX|ukJ0HighDDp3ho|qbt#vx^v2@LB)%jVU%rxt z)QpLhKBnciNa(;yu;?V?7@$jVuIj0_n%PxKKJf60Vs%OMav=}7M*iu@7v|ok-*kgI z3V%+RF>-toXPa_n<+1;|;m~E~Prw!VexU=eXocVuH_Uaem5UC*s~@0R8-TidCIO-G z?*A~*?GObaKOle<$$_5oa-ExHIQa3>5tnFzJ0>EJpOtOe!TvymJ4hX7Kh;>Az$3oM325Mxmy(R&#W_Opjau z-uYp|&zIUg`GG5K{pfO8!L$0Dcibb@(4nGzt<7!Pz8;k=8?qvamDo8J_+rTF zcQDmq1n=edkuRGqIP*c|vC`c}K4Wvh)}-G<7q``uPx#i4O*-W1SN!P+T+yq6?MP5L zqnf}JY7MtzP$cwPlRlf9D@JXQ=4SoB9+mj34C|*aaW@3~sVh?=o&#KnrN-5QDPxQd z1h(YCb@O@iE{~#1WBQlI6Cc)yZ0Kf{7jvpw`u|bQTg^WfjNEYni8ldZ_obsNC0Max z$YRd4B|~NMxqov^WqO5AXRupz#jM-`jS9M0mJ8aM+clh2VlmH zFmt9iMu%3yf?hnOo3$~#Zfw_+eo@zW0BibSb3`392+_cXXzjDXb>Y=z9_aaaBkSkX%b%N?1VX(GNWh0*1?!4_l zxS_?nRl^(~*{9Vmm|E!sO8oVUAXdGInbS%>pC$0JMmMFakZiA;I>TGS28tbH#$`A6 zD_6CG&Ckpq=4?XKDQvTw;8R=*q18C&~U!UHL}y z6@@EOyX8LO#^v1U4hzXmp?4!~PALb_K3UsST3$aux}t{6*rPA^A6PLbbP8zvLGriW ztGMdmCKnTl!kT|ib;6oo2T8+lV|W>FB9vOW6!Cc=Pi{%#oK^N*TYI>ce4z2CTQpxX z_u9Abs(QNOZy6>Mu9FV4S(1n-LhT6l!EV#+BW>us(GaM=#r7!pHpmKZqI7=i-sbbu zq>hw1TZg%K1;%dgH{DN~XkK=eDO1s8VUuF`r|i|r?$oOotjjz+uxL+!qim%PRQ8dO zX69m(cgxqR$NIhxnx*Iyw8iF#~%GhDc%x+Ko^6RF=)S+&|!Jnrc z6zQ*x>!|p=a~L;h@YK-V@tR6;#~xRk))}&QW4X^n6^(IG}Nu&!#r!mc@L?vBOUL zP0=I37+}Ekf!D8>Z%_N@i+wf7EbMjhmUDb0=V+_$s5f8Hw#{0xW@brBY2t(06SA7C zq`k;@;LmSY*fuj_p0hlVD7 zm;IP^RGw zqc;O4jpzuv0$oX|gR4QDC2g+pej3M<9i(Nj^ycqZJ&C97g61#q?s%+)=mw`P?xvY( zFTZH%7068sJE=#)=4<8?hM0s1!(+5uIsusQI>J|FuZG_UHIH9)N7F6|UFUHr`q}y~< zeef~<=BI0vgWN61GXs+ija>t7=jjEBY`vcwLnrX@d&p-QWN8NF#UJb7J1)l72OV5p za)~?x(@Z6H3gmw2c+H~dRZl(I>3cW0-q5B|i1ozwd_A>r!9{gJ{nxWi5#Pd4TL(P8 zZ+j6-l(o)mY`-qGa$SZYzc#=myzAWi`QJlqv-UI&-1_{dsg@Pgy+}Er*&`13Cj^dQ zvY?pT3vKgY`J_fZqbn1TJ=vn1&jl~tgt@aU+2`_P%LT*ot2Y-?W!qSqHU9B{!vr*# zS(=vjC48A2_5PP0A+RS^NbKry_ND;qSpL{!E&7F=Pf6@M!txnRlU3($Rpf`^UjIL_ z!9TuGiX)nzHv(6y%zQiCP@Eb>kx(YEFF{WOoEjD7|CJ27&d_hul!?9vUSD+)5u$HA1bz*3;B=!17c=GEfQ}G49LJ&z5n7OYRGU zZn;m;c<8I-<0~*?1wlajJ3nY@hUHa>f$weOP=~J6W(jDXWARIoM zGDtBb-=9TUWj4jb{|b>?ZFM@+M-vgWZ*~Nfm4hu_LWKr0}mH;oAvP|gm8NUv9@_~d+++Xowb)%4&Nq zenBOvhbEQa?6c4qap4+EVf*7uO$CaeSA7sqT9xaT6-yeWOXZWi^C$y)#&>wlVQaPK z-5}2OT!$P-1SAo9^@-twaKkMsYi(JzSQsCpCfEOH!bdPs*9Q`$kpc#=uq)}OWA5i@ z@8_h7z3&8ezp zCTD;KW`VcN{V?_cVz~R>&aNI#Vtx;CPGYV&KP&*?v!>TMSbgrCKHX{D^;Lfs13)F% z<+1E=3Ao`i9w=N)n{ctk5h_t}ORQ_C?@Q~~R^e8bF2eO(19@PPpWAO;3-ug)1fZ{j K)-KVq3;QqFp7Bor literal 0 HcmV?d00001 diff --git a/resources/android-chrome-512x512.png b/resources/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..f48239dbad0ecf5891c694a3d50fb1423f4ead84 GIT binary patch literal 15386 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 literal 0 HcmV?d00001 diff --git a/resources/browserconfig.xml b/resources/browserconfig.xml new file mode 100644 index 0000000000..6c3340f024 --- /dev/null +++ b/resources/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #2d89ef + + + diff --git a/resources/favicon-16x16.png b/resources/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..8586591f41cfe9cf15bbb19a732a34c7005a30c0 GIT binary patch literal 995 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>(kw69ASaS1B@`vf zH&aCd=qX_6{r~^}1^eCqz`zYI3GxF)6gI%ZC!i5DqsXqfVcLc>&wuqy?J1nxY_s6* z-=5+N&;GVdEi8TgyW6_&+@HyRem{tx@cs4O6RVm66`A!tOqE34t{(uJ$(ZEr?owpN z#~T6Uu$OrHy0SlF6Be;naC5)81SoXW)5S4F;&O6A1G8Hpr<Df8XZWh)! zaBAt|)ywD4m@;Ql)&bs&Nf{|QLi47{iLE-uY;0m8lH#*MQ$M2NB+rR+C(d}CG<*J- zor{AbDkAFX6SXHt)uXvNnOR+2a&z9k`OM9A*m>bQfnttAAAW9bPPg)vlQ(mR9JqS+ z?%~U)Zy&$jFZd|9-8f8yaN4Aam!<$wB&=hGktW@T=@WNu+)VeiQz%)$yT z4JLlmFf(GPG_o4 z1+`k%Qbin;>S(Q~BXvWNMX`uw6Gc>P9kCTlX9}Xd=r4ctXQyw@yJy}z=iKvs-#K5# z+LlsDToM3)YKb((Lyyk91TT1+YIn9kH!Cy38UetmJ>=JE-ZMdGWV{uC!XN;Ob^tI5 ze--@-Kt2w@v(*3?zX5=gTX`XF0RWySW0xhEVZwbq_CSvn@R1d4+JH{niK7j{JTrq_ zBMpf0rQXwHS5?9@bNIu0jO{%OCjT!sY``FZZ35OtuI~aGDV0qh)QS6b;-fO|ZH?&E z9R3$Vwkv=MDZorfM?vxlqmdTT$&iSJNr^$I?_tABMhp^o_G!gk8qxdYQZeUH5I2-c zj74VnLMxN_x2lEb6oS2C4pb)7p8-pt5j{PFiL(t9f{{jCNGB~}kl(BK&@glDkRF3z zT2#XSTA~>+?`XolPz2bqN*XYz!@4!1D@tK~FmEU72Qfq9Ayi_oR@|c%-NMo9su@Q0 zGTs5qzbKHE6~Ihl(V#x_s6-uwV4%#;=JqZPvubm1bnEq(9Srcoh)x)tycJ3@u}KpEjW-PMY3;i6`h@T@{`M8+)< zbGGmiCx>D4rN99>{OE9$bE!nDFJ-MiW0%MeZW`RWm45UbE_1t(T_Fi*SEDy^^qvlT z`}VDE_X^!CPq=-!UCmv3ZsYz5{Zjd1=z4&nRU#bf?ejXfs z`S+Xfi6LpF&xkZ^Voc2~yFWRmo-JK|uzONoclvzm@YG{@C1Fq$4uj~4=WoW;1huPf zU`kR_Ufb9=`I} zd}Y7IF0)pIUu!Q9uwL0O-xm~9Wy~0D=>K%|R>h^uEeE_U9>=SuubOuq{K#>3>-F}; z?G5dk$=1oCAmBJ6KUUfhGr}@b*2AVQk z8=CC0@20MHEkyC)(DVmy3qtbVN)`o)wdyZ zLHMRW`(7fYaVsN9=MFn<)y8e3&(FW&s8(ILm^U<_NOnHjT*CUJMJ5Syq+WX1KJnxF zUdQ>oSHFyz+vHnscwGOs{6KYSS^m=(O;hxog_R+$ahCp*^rw$UpKw^=#_7%7J#C?0 zS?!YAl0ysH*z8A%vGFUCzKV`8XC&rZvjtdGi>Dm_UaiSmw;?OXmAyXG)K#!sP~{j3 zYuYyb1o6*%y8Jl+=b}j|-Dil~;nbvVbBa4X&7EO%ZpwfTXmL%b5)V;o<|SxxqhX#= zr&ZuuBaRQ!=14y%$ljRlTD#@n3y#_MmcfGL!h{reeA;Jd?xu}vT^lk`_m0a0m31~-O&yD8JW`46z dM^R)=lnOlKFx}&e3}3?*z+$$UPApno{0}O%I9>n% literal 0 HcmV?d00001 diff --git a/resources/favicon.ico b/resources/favicon.ico index 8c40f32b075795be79aa51e266025d6aae6ab14c..a89bfc3cba8314942e0a8b3a5a4a287020830973 100644 GIT binary patch literal 15086 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 diff --git a/resources/mstile-150x150.png b/resources/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..5a826017cf27815b586f54b416780a963968668d GIT binary patch literal 4442 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 o)Woa4H+`@^?xA%1JC0hQRq> + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/resources/site.webmanifest b/resources/site.webmanifest new file mode 100644 index 0000000000..066bd7a362 --- /dev/null +++ b/resources/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/resources/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/resources/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} From ddd3d65b225ec930238e2dbd245b397b52a78006 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 9 Jul 2018 14:29:27 -0700 Subject: [PATCH 0243/3174] tiny formatting fix --- _overviews/plugins/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md index 16a44644ba..3b11e43164 100644 --- a/_overviews/plugins/index.md +++ b/_overviews/plugins/index.md @@ -5,7 +5,7 @@ title: Scala Compiler Plugins discourse: true --- -**Lex Spoon (2008)** +**Lex Spoon (2008)** **Seth Tisue (2018)** ## Introduction From 0b0edeec96045239414999ab7bd1cb362c85e49a Mon Sep 17 00:00:00 2001 From: Roman Filonenko Date: Thu, 12 Jul 2018 14:35:06 +0200 Subject: [PATCH 0244/3174] add implicit keyword to the Modifiers section #1075 --- _style/declarations.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_style/declarations.md b/_style/declarations.md index f039b56595..ca6c389d5c 100644 --- a/_style/declarations.md +++ b/_style/declarations.md @@ -116,8 +116,9 @@ applicable): 1. Annotations, *each on their own line* 2. Override modifier (`override`) 3. Access modifier (`protected`, `private`) -4. Final modifier (`final`) -5. `def` +4. Implicit modifier (`implicit`) +5. Final modifier (`final`) +6. `def` From 163b725ce841fa624d1b697d14ad33e6c47c210b Mon Sep 17 00:00:00 2001 From: Jatin Gupta Date: Sun, 15 Jul 2018 22:35:34 -0700 Subject: [PATCH 0245/3174] Update documentation since deprecation now takes two arguments --- _tour/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/annotations.md b/_tour/annotations.md index 32220d90a6..f88ba840cc 100644 --- a/_tour/annotations.md +++ b/_tour/annotations.md @@ -16,7 +16,7 @@ redirect_from: "/tutorials/tour/annotations.html" Annotations associate meta-information with definitions. For example, the annotation `@deprecated` before a method causes the compiler to print a warning if the method is used. ``` object DeprecationDemo extends App { - @deprecated + @deprecated("deprecation message e.g. - this method will be removed", "next release in which method will be deprecated e.g. ExampleLib 2.0") def hello = "hola" hello From 0e3e8669c6e9612bd849a07c6ed5193c7acb39dc Mon Sep 17 00:00:00 2001 From: Jatin Gupta Date: Mon, 16 Jul 2018 10:20:21 -0700 Subject: [PATCH 0246/3174] Keep character count under 60 --- _tour/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/annotations.md b/_tour/annotations.md index f88ba840cc..b486d7b806 100644 --- a/_tour/annotations.md +++ b/_tour/annotations.md @@ -16,7 +16,7 @@ redirect_from: "/tutorials/tour/annotations.html" Annotations associate meta-information with definitions. For example, the annotation `@deprecated` before a method causes the compiler to print a warning if the method is used. ``` object DeprecationDemo extends App { - @deprecated("deprecation message e.g. - this method will be removed", "next release in which method will be deprecated e.g. ExampleLib 2.0") + @deprecated("deprecation message", "release # which deprecates method") def hello = "hola" hello From 5a6710b8a56b85ccf7b6e95e054dfbe1ec988fd8 Mon Sep 17 00:00:00 2001 From: Philippus Date: Wed, 18 Jul 2018 18:48:21 +0200 Subject: [PATCH 0247/3174] Use jQuery from CDN, fall back to local if needed, closes #1074 --- _includes/footer.html | 3 ++- scripts/jquery-3.1.1.min.js | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 scripts/jquery-3.1.1.min.js diff --git a/_includes/footer.html b/_includes/footer.html index 7171b3c1f5..6fba4fd292 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -21,7 +21,8 @@ - + + diff --git a/scripts/jquery-3.1.1.min.js b/scripts/jquery-3.1.1.min.js new file mode 100644 index 0000000000..4c5be4c0fb --- /dev/null +++ b/scripts/jquery-3.1.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R), +a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)), +void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" - diff --git a/_sass/layout/toc.scss b/_sass/layout/toc.scss index c4d9556079..7ac4716277 100644 --- a/_sass/layout/toc.scss +++ b/_sass/layout/toc.scss @@ -3,6 +3,14 @@ //------------------------------------------------ .sidebar-toc-wrapper { + position: -webkit-sticky; + position: sticky; + top: 0; + + @include bp(large) { + position: relative; + } + @include bp(medium) { display: none; } diff --git a/resources/js/functions.js b/resources/js/functions.js index ff9d0f7676..9e9fd92070 100644 --- a/resources/js/functions.js +++ b/resources/js/functions.js @@ -304,27 +304,9 @@ $(document).ready(function() { autoId: true, numerate: false }); - toggleStickyToc(); } }); -$(window).resize(function() { - toggleStickyToc(); -}); - -var toggleStickyToc = function() { - if ($("#sidebar-toc").length) { - if ($(window).width() <= 992) { - $(".sidebar-toc-wrapper").unstick(); - } else { - $(".sidebar-toc-wrapper").sticky({ - topSpacing: 0, - bottomSpacing: 500 - }); - } - } -} - // Language dropdown function DropDown(el) { this.dd = el; diff --git a/resources/js/vendor/jquery.sticky.js b/resources/js/vendor/jquery.sticky.js deleted file mode 100644 index f50486f357..0000000000 --- a/resources/js/vendor/jquery.sticky.js +++ /dev/null @@ -1,287 +0,0 @@ -// Sticky Plugin v1.0.4 for jQuery -// ============= -// Author: Anthony Garand -// Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk) -// Improvements by Leonardo C. Daronco (daronco) -// Created: 02/14/2011 -// Date: 07/20/2015 -// Website: http://stickyjs.com/ -// Description: Makes an element on the page stick on the screen as you scroll -// It will only set the 'top' and 'position' of your element, you -// might need to adjust the width in some cases. - -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], factory); - } else if (typeof module === 'object' && module.exports) { - // Node/CommonJS - module.exports = factory(require('jquery')); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - var slice = Array.prototype.slice; // save ref to original slice() - var splice = Array.prototype.splice; // save ref to original slice() - - var defaults = { - topSpacing: 0, - bottomSpacing: 0, - className: 'is-sticky', - wrapperClassName: 'sticky-wrapper', - center: false, - getWidthFrom: '', - widthFromWrapper: true, // works only when .getWidthFrom is empty - responsiveWidth: false, - zIndex: 'auto' - }, - $window = $(window), - $document = $(document), - sticked = [], - windowHeight = $window.height(), - scroller = function() { - var scrollTop = $window.scrollTop(), - documentHeight = $document.height(), - dwh = documentHeight - windowHeight, - extra = (scrollTop > dwh) ? dwh - scrollTop : 0; - - for (var i = 0, l = sticked.length; i < l; i++) { - var s = sticked[i], - elementTop = s.stickyWrapper.offset().top, - etse = elementTop - s.topSpacing - extra; - - //update height in case of dynamic content - s.stickyWrapper.css('height', s.stickyElement.outerHeight()); - - if (scrollTop <= etse) { - if (s.currentTop !== null) { - s.stickyElement - .css({ - 'width': '', - 'position': '', - 'top': '', - 'z-index': '' - }); - s.stickyElement.parent().removeClass(s.className); - s.stickyElement.trigger('sticky-end', [s]); - s.currentTop = null; - } - } - else { - var newTop = documentHeight - s.stickyElement.outerHeight() - - s.topSpacing - s.bottomSpacing - scrollTop - extra; - if (newTop < 0) { - newTop = newTop + s.topSpacing; - } else { - newTop = s.topSpacing; - } - if (s.currentTop !== newTop) { - var newWidth; - if (s.getWidthFrom) { - newWidth = $(s.getWidthFrom).width() || null; - } else if (s.widthFromWrapper) { - newWidth = s.stickyWrapper.width(); - } - if (newWidth == null) { - newWidth = s.stickyElement.width(); - } - s.stickyElement - .css('width', newWidth) - .css('position', 'fixed') - .css('top', newTop) - .css('z-index', s.zIndex); - - s.stickyElement.parent().addClass(s.className); - - if (s.currentTop === null) { - s.stickyElement.trigger('sticky-start', [s]); - } else { - // sticky is started but it have to be repositioned - s.stickyElement.trigger('sticky-update', [s]); - } - - if (s.currentTop === s.topSpacing && s.currentTop > newTop || s.currentTop === null && newTop < s.topSpacing) { - // just reached bottom || just started to stick but bottom is already reached - s.stickyElement.trigger('sticky-bottom-reached', [s]); - } else if(s.currentTop !== null && newTop === s.topSpacing && s.currentTop < newTop) { - // sticky is started && sticked at topSpacing && overflowing from top just finished - s.stickyElement.trigger('sticky-bottom-unreached', [s]); - } - - s.currentTop = newTop; - } - - // Check if sticky has reached end of container and stop sticking - var stickyWrapperContainer = s.stickyWrapper.parent(); - var unstick = (s.stickyElement.offset().top + s.stickyElement.outerHeight() >= stickyWrapperContainer.offset().top + stickyWrapperContainer.outerHeight()) && (s.stickyElement.offset().top <= s.topSpacing); - - if( unstick ) { - s.stickyElement - .css('position', 'absolute') - .css('top', '') - .css('bottom', 0) - .css('z-index', ''); - } else { - s.stickyElement - .css('position', 'fixed') - .css('top', newTop) - .css('bottom', '') - .css('z-index', s.zIndex); - } - } - } - }, - resizer = function() { - windowHeight = $window.height(); - - for (var i = 0, l = sticked.length; i < l; i++) { - var s = sticked[i]; - var newWidth = null; - if (s.getWidthFrom) { - if (s.responsiveWidth) { - newWidth = $(s.getWidthFrom).width(); - } - } else if(s.widthFromWrapper) { - newWidth = s.stickyWrapper.width(); - } - if (newWidth != null) { - s.stickyElement.css('width', newWidth); - } - } - }, - methods = { - init: function(options) { - return this.each(function() { - var o = $.extend({}, defaults, options); - var stickyElement = $(this); - - var stickyId = stickyElement.attr('id'); - var wrapperId = stickyId ? stickyId + '-' + defaults.wrapperClassName : defaults.wrapperClassName; - var wrapper = $('
    ') - .attr('id', wrapperId) - .addClass(o.wrapperClassName); - - stickyElement.wrapAll(function() { - if ($(this).parent("#" + wrapperId).length == 0) { - return wrapper; - } -}); - - var stickyWrapper = stickyElement.parent(); - - if (o.center) { - stickyWrapper.css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"}); - } - - if (stickyElement.css("float") === "right") { - stickyElement.css({"float":"none"}).parent().css({"float":"right"}); - } - - o.stickyElement = stickyElement; - o.stickyWrapper = stickyWrapper; - o.currentTop = null; - - sticked.push(o); - - methods.setWrapperHeight(this); - methods.setupChangeListeners(this); - }); - }, - - setWrapperHeight: function(stickyElement) { - var element = $(stickyElement); - var stickyWrapper = element.parent(); - if (stickyWrapper) { - stickyWrapper.css('height', element.outerHeight()); - } - }, - - setupChangeListeners: function(stickyElement) { - if (window.MutationObserver) { - var mutationObserver = new window.MutationObserver(function(mutations) { - if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) { - methods.setWrapperHeight(stickyElement); - } - }); - mutationObserver.observe(stickyElement, {subtree: true, childList: true}); - } else { - if (window.addEventListener) { - stickyElement.addEventListener('DOMNodeInserted', function() { - methods.setWrapperHeight(stickyElement); - }, false); - stickyElement.addEventListener('DOMNodeRemoved', function() { - methods.setWrapperHeight(stickyElement); - }, false); - } else if (window.attachEvent) { - stickyElement.attachEvent('onDOMNodeInserted', function() { - methods.setWrapperHeight(stickyElement); - }); - stickyElement.attachEvent('onDOMNodeRemoved', function() { - methods.setWrapperHeight(stickyElement); - }); - } - } - }, - update: scroller, - unstick: function(options) { - return this.each(function() { - var that = this; - var unstickyElement = $(that); - - var removeIdx = -1; - var i = sticked.length; - while (i-- > 0) { - if (sticked[i].stickyElement.get(0) === that) { - splice.call(sticked,i,1); - removeIdx = i; - } - } - if(removeIdx !== -1) { - unstickyElement.unwrap(); - unstickyElement - .css({ - 'width': '', - 'position': '', - 'top': '', - 'float': '', - 'z-index': '' - }) - ; - } - }); - } - }; - - // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): - if (window.addEventListener) { - window.addEventListener('scroll', scroller, false); - window.addEventListener('resize', resizer, false); - } else if (window.attachEvent) { - window.attachEvent('onscroll', scroller); - window.attachEvent('onresize', resizer); - } - - $.fn.sticky = function(method) { - if (methods[method]) { - return methods[method].apply(this, slice.call(arguments, 1)); - } else if (typeof method === 'object' || !method ) { - return methods.init.apply( this, arguments ); - } else { - $.error('Method ' + method + ' does not exist on jQuery.sticky'); - } - }; - - $.fn.unstick = function(method) { - if (methods[method]) { - return methods[method].apply(this, slice.call(arguments, 1)); - } else if (typeof method === 'object' || !method ) { - return methods.unstick.apply( this, arguments ); - } else { - $.error('Method ' + method + ' does not exist on jQuery.sticky'); - } - }; - $(function() { - setTimeout(scroller, 0); - }); -})); From 022d3a49b9e677a60e5cefed38365dc667e4cb28 Mon Sep 17 00:00:00 2001 From: Sam Zaydel Date: Mon, 18 Mar 2019 07:03:59 -0700 Subject: [PATCH 0538/3174] Extra 'not' in sentence in Trait Traversable --- _overviews/FAQ/collections.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/FAQ/collections.md b/_overviews/FAQ/collections.md index 65f9f3d5a1..b044191727 100644 --- a/_overviews/FAQ/collections.md +++ b/_overviews/FAQ/collections.md @@ -171,8 +171,8 @@ Traversible objects can be finite or infinite. An example of an infinite traversable object is the stream of natural numbers `Stream.from(0)`. The method `hasDefiniteSize` indicates whether a collection is possibly infinite. If `hasDefiniteSize` returns true, the collection is certainly finite. If it -returns false, the collection has not been not fully elaborated yet, so it -might be infinite or finite. +returns false, the collection has not been fully elaborated yet, so it might +be infinite or finite. This class defines methods which can be efficiently implemented in terms of `foreach` (over 40 of them). From 152516a1b3198f810fee43622040a7d1b444b5eb Mon Sep 17 00:00:00 2001 From: Xztty Date: Thu, 21 Mar 2019 14:14:01 +0800 Subject: [PATCH 0539/3174] replace JavaConversions to JavaConverters from scala 2.12.0 the JavaConversions is marked as deprecated class. And it's recommended to use JavaConverters --- ...ersions-between-java-and-scala-collections.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md b/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md index af302dd49f..9b8e44daf0 100644 --- a/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md +++ b/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md @@ -25,20 +25,20 @@ language: zh-cn mutable.Map <=> java.util.Map mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap -使用这些转换很简单,只需从JavaConversions对象中import它们即可。 +使用这些转换很简单,只需从JavaConverters对象中import它们即可。 - scala> import collection.JavaConversions._ - import collection.Java.Conversions._ + scala> import collection.JavaConverters._ + import collection.JavaConverters._ -import之后,就可以在Scala容器和与之对应的Java容器之间进行隐式转换了 +import之后,通过扩展方法 asScala 和 asJava 就可以在Scala容器和与之对应的Java容器之间进行隐式转换了 scala> import collection.mutable._ import collection.mutable._ - scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3) + scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] - scala> val buf: Seq[Int] = jul + scala> val buf: Seq[Int] = jul.asScala buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) - scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2) + scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava m: java.util.Map[String, Int] = {hello=2, abc=1} 在Scala内部,这些转换是通过一系列“包装”对象完成的,这些对象会将相应的方法调用转发至底层的容器对象。所以容器不会在Java和Scala之间拷贝来拷贝去。一个值得注意的特性是,如果你将一个Java容器转换成其对应的Scala容器,然后再将其转换回同样的Java容器,最终得到的是一个和一开始完全相同的容器对象(译注:这里的相同意味着这两个对象实际上是指向同一片内存区域的引用,容器转换过程中没有任何的拷贝发生)。 @@ -52,7 +52,7 @@ import之后,就可以在Scala容器和与之对应的Java容器之间进行 因为Java并未区分可变容器不可变容器类型,所以,虽然能将`scala.immutable.List`转换成`java.util.List`,但所有的修改操作都会抛出“UnsupportedOperationException”。参见下例: - scala> jul = List(1, 2, 3) + scala> jul = List(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] scala> jul.add(7) java.lang.UnsupportedOperationException From 06464d4f919912051141a055c3ba5ece6c7bf99f Mon Sep 17 00:00:00 2001 From: salim7 Date: Tue, 26 Mar 2019 10:49:15 +0100 Subject: [PATCH 0540/3174] Fixed Typo --- .../parallel-collections/conversions.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/_overviews/parallel-collections/conversions.md b/_overviews/parallel-collections/conversions.md index 9997c5539a..f4d42d446c 100644 --- a/_overviews/parallel-collections/conversions.md +++ b/_overviews/parallel-collections/conversions.md @@ -66,16 +66,16 @@ into a `ParX` collection. Here is a summary of all conversion methods: -| Method | Return Type | -| -------------- | -------------- | -| `toArray` | `Array` | -| `toList` | `List` | -| `toIndexedSeq` | `IndexedSeq` | -| `toStream` | `Stream` | -| `toIterator` | `Iterator` | -| `toBuffer` | `Buffer` | -| `toTraversable`| `GenTraverable`| -| `toIterable` | `ParIterable` | -| `toSeq` | `ParSeq` | -| `toSet` | `ParSet` | -| `toMap` | `ParMap` | +| Method | Return Type | +| -------------- | --------------- | +| `toArray` | `Array` | +| `toList` | `List` | +| `toIndexedSeq` | `IndexedSeq` | +| `toStream` | `Stream` | +| `toIterator` | `Iterator` | +| `toBuffer` | `Buffer` | +| `toTraversable`| `GenTraversable`| +| `toIterable` | `ParIterable` | +| `toSeq` | `ParSeq` | +| `toSet` | `ParSet` | +| `toMap` | `ParMap` | From 6420a94d859c84fdabc3f2b95aab5b73de6d8a49 Mon Sep 17 00:00:00 2001 From: Long Sun Date: Tue, 26 Mar 2019 14:20:49 +0800 Subject: [PATCH 0541/3174] Fix typo --- _zh-cn/tour/basics.md | 2 +- _zh-cn/tour/classes.md | 2 +- _zh-cn/tour/unified-types.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_zh-cn/tour/basics.md b/_zh-cn/tour/basics.md index b63a482e41..82ac4a3f27 100644 --- a/_zh-cn/tour/basics.md +++ b/_zh-cn/tour/basics.md @@ -25,7 +25,7 @@ previous-page: tour-of-scala 这是一种简单的、零设置的方法来实践Scala的代码片段。 -这篇文档中的大部分代码示例与 ScalaFiddle 进行了集成,可以通过点击 “Run” 按钮即来直接运行 Scale 代码。 +这篇文档中的大部分代码示例与 ScalaFiddle 进行了集成,可以通过点击 “Run” 按钮即来直接运行 Scala 代码。 ## 表达式 diff --git a/_zh-cn/tour/classes.md b/_zh-cn/tour/classes.md index 1f6026a3aa..e916677681 100644 --- a/_zh-cn/tour/classes.md +++ b/_zh-cn/tour/classes.md @@ -95,7 +95,7 @@ point1.y = 101 // prints the warning ``` 在这个版本的`Point`类中,数据存在私有变量`_x`和`_y`中。`def x`和`def y`方法用于访问私有数据。`def x_=`和`def y_=`是为了验证和给`_x`和`_y`赋值。注意下对于setter方法的特殊语法:这个方法在getter方法的后面加上`_=`,后面跟着参数。 -主构造方法中带有`val`和`var`的参数时公有的。然而由于`val`是不可变的,所以不能像下面这样去使用。 +主构造方法中带有`val`和`var`的参数是公有的。然而由于`val`是不可变的,所以不能像下面这样去使用。 ``` class Point(val x: Int, val y: Int) val point = new Point(1, 2) diff --git a/_zh-cn/tour/unified-types.md b/_zh-cn/tour/unified-types.md index 4ddd6d01ac..d5bacaa87d 100644 --- a/_zh-cn/tour/unified-types.md +++ b/_zh-cn/tour/unified-types.md @@ -42,7 +42,7 @@ val list: List[Any] = List( list.foreach(element => println(element)) ``` -这里定义了一个类型`List`的变量`list`。这个列表里由多种类型进行初始化,但是它们都是`scala.Any`的实例,所以可以把它们加入到列表中。 +这里定义了一个类型`List`的变量`list`。这个列表里由多种类型进行初始化,但是它们都是`scala.Any`的实例,所以可以把它们加入到列表中。 下面是程序的输出: From 7166149b60df844d95da092ccb18c78a08b39552 Mon Sep 17 00:00:00 2001 From: Salim D Date: Tue, 26 Mar 2019 12:25:59 +0100 Subject: [PATCH 0542/3174] Fixed Typo in Japanese Translation --- .../parallel-collections/conversions.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/_ja/overviews/parallel-collections/conversions.md b/_ja/overviews/parallel-collections/conversions.md index 73345f4fd9..636f6885b4 100644 --- a/_ja/overviews/parallel-collections/conversions.md +++ b/_ja/overviews/parallel-collections/conversions.md @@ -47,16 +47,16 @@ language: ja 以下の表に全ての変換をまとめる: -| メソッド | 戻り値の型 | -| -------------- | -------------- | -| `toArray` | `Array` | -| `toList` | `List` | -| `toIndexedSeq` | `IndexedSeq` | -| `toStream` | `Stream` | -| `toIterator` | `Iterator` | -| `toBuffer` | `Buffer` | -| `toTraversable`| `GenTraverable`| -| `toIterable` | `ParIterable` | -| `toSeq` | `ParSeq` | -| `toSet` | `ParSet` | -| `toMap` | `ParMap` | +| メソッド | 戻り値の型 | +| -------------- | --------------- | +| `toArray` | `Array` | +| `toList` | `List` | +| `toIndexedSeq` | `IndexedSeq` | +| `toStream` | `Stream` | +| `toIterator` | `Iterator` | +| `toBuffer` | `Buffer` | +| `toTraversable`| `GenTraversable`| +| `toIterable` | `ParIterable` | +| `toSeq` | `ParSeq` | +| `toSet` | `ParSet` | +| `toMap` | `ParMap` | From e56e2f3c57e2d8552ea1b0804f7480d48aecd6b5 Mon Sep 17 00:00:00 2001 From: Salim D Date: Tue, 26 Mar 2019 12:27:00 +0100 Subject: [PATCH 0543/3174] Fixed Typo in Chinese Translation --- _zh-cn/overviews/parallel-collections/conversions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/overviews/parallel-collections/conversions.md b/_zh-cn/overviews/parallel-collections/conversions.md index 788ca55630..6f13fd3491 100644 --- a/_zh-cn/overviews/parallel-collections/conversions.md +++ b/_zh-cn/overviews/parallel-collections/conversions.md @@ -46,7 +46,7 @@ language: zh-cn |toStream | Stream | |toIterator | Iterator | |toBuffer | Buffer | -|toTraversable | GenTraverable | +|toTraversable | GenTraversable | |toIterable | ParIterable | |toSeq | ParSeq | |toSet | ParSet | From 86fe85797f87dbf547487d6236d1ead6e2c97abb Mon Sep 17 00:00:00 2001 From: Salim D Date: Tue, 26 Mar 2019 12:27:56 +0100 Subject: [PATCH 0544/3174] Fixed Typo in Spanish Translation --- .../parallel-collections/conversions.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/_es/overviews/parallel-collections/conversions.md b/_es/overviews/parallel-collections/conversions.md index 8461a2f9aa..ec836d0338 100644 --- a/_es/overviews/parallel-collections/conversions.md +++ b/_es/overviews/parallel-collections/conversions.md @@ -61,16 +61,16 @@ en una colección `ParX` A continuación se muestra un resumen de todos los métodos de conversión: -| método | Tipo de Retorno| -| -------------- | -------------- | -| `toArray` | `Array` | -| `toList` | `List` | -| `toIndexedSeq` | `IndexedSeq` | -| `toStream` | `Stream` | -| `toIterator` | `Iterator` | -| `toBuffer` | `Buffer` | -| `toTraversable`| `GenTraverable`| -| `toIterable` | `ParIterable` | -| `toSeq` | `ParSeq` | -| `toSet` | `ParSet` | -| `toMap` | `ParMap` | +| método | Tipo de Retorno | +| -------------- | --------------- | +| `toArray` | `Array` | +| `toList` | `List` | +| `toIndexedSeq` | `IndexedSeq` | +| `toStream` | `Stream` | +| `toIterator` | `Iterator` | +| `toBuffer` | `Buffer` | +| `toTraversable`| `GenTraversable`| +| `toIterable` | `ParIterable` | +| `toSeq` | `ParSeq` | +| `toSet` | `ParSet` | +| `toMap` | `ParMap` | From 2f5d77fb3657919a3aa0bc7b04e7ee00b3a49d19 Mon Sep 17 00:00:00 2001 From: Salim D Date: Tue, 26 Mar 2019 12:29:18 +0100 Subject: [PATCH 0545/3174] Fixed Typo in Russian Translation --- .../parallel-collections/conversions.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/_ru/overviews/parallel-collections/conversions.md b/_ru/overviews/parallel-collections/conversions.md index 8579774ec9..114f2d8986 100644 --- a/_ru/overviews/parallel-collections/conversions.md +++ b/_ru/overviews/parallel-collections/conversions.md @@ -38,16 +38,16 @@ num: 3 Ниже приведена сводная таблица всех методов преобразования: -| Метод | Тип возвращаемого значения | -| -------------- | -------------------------- | -| `toArray` | `Array` | -| `toList` | `List` | -| `toIndexedSeq` | `IndexedSeq` | -| `toStream` | `Stream` | -| `toIterator` | `Iterator` | -| `toBuffer` | `Buffer` | -| `toTraversable`| `GenTraverable` | -| `toIterable` | `ParIterable` | -| `toSeq` | `ParSeq` | -| `toSet` | `ParSet` | -| `toMap` | `ParMap` | +| Метод | Тип возвращаемого значения | +| -------------- | --------------------------- | +| `toArray` | `Array` | +| `toList` | `List` | +| `toIndexedSeq` | `IndexedSeq` | +| `toStream` | `Stream` | +| `toIterator` | `Iterator` | +| `toBuffer` | `Buffer` | +| `toTraversable`| `GenTraversable` | +| `toIterable` | `ParIterable` | +| `toSeq` | `ParSeq` | +| `toSet` | `ParSet` | +| `toMap` | `ParMap` | From 16d636c1509d374a328c58518c282ba04fb52c63 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 8 Apr 2019 08:36:19 +0000 Subject: [PATCH 0546/3174] add RC1 Scaladoc --- api/all.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/all.md b/api/all.md index d629074504..50c5bea6bc 100644 --- a/api/all.md +++ b/api/all.md @@ -5,6 +5,7 @@ includeTOC: true --- ## Latest releases + * Scala 2.12.8 * [Library API](https://www.scala-lang.org/api/2.12.8/) * [Compiler API](https://www.scala-lang.org/api/2.12.8/scala-compiler/scala/) @@ -25,6 +26,13 @@ includeTOC: true * [Continuations API](https://www.scala-lang.org/files/archive/api/2.11.12/scala-continuations-library/#scala.util.continuations.package) * [Scala 2.10.7](https://www.scala-lang.org/api/2.10.7/) +## Prereleases + +* Scala 2.13.0-RC1 + * [Library API](https://www.scala-lang.org/api/2.13.0-RC1/) + * [Compiler API](https://www.scala-lang.org/api/2.13.0-RC1/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.0-RC1/scala-reflect/scala/reflect/) + ## Nightly builds * Scala 2.13.x From 151a87ec0d501fe70702cd1193597e8ac5fa1232 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 9 Apr 2019 13:38:35 +0200 Subject: [PATCH 0547/3174] Adapt architecture of collections to latest 2.13 changes --- .../architecture-of-scala-213-collections.md | 33 ++-- .../core/custom-collection-operations.md | 2 +- _overviews/core/custom-collections.md | 166 ++++++++++-------- 3 files changed, 105 insertions(+), 96 deletions(-) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index 5144b83f45..557c8c0258 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -280,13 +280,13 @@ implementations of `filter` and `map`: trait IterableOps[+A, +CC[_], +C] { def filter(pred: A => Boolean): C = - fromSpecificIterable(new View.Filter(this, pred)) + fromSpecific(new View.Filter(this, pred)) def map[B](f: A => B): CC[B] = - fromIterable(new View.Map(this, f)) + from(new View.Map(this, f)) - protected def fromSpecificIterable(coll: Iterable[A]): C - protected def fromIterable[E](it: Iterable[E]): CC[E] + protected def fromSpecific(coll: IterableOnce[A]): C + protected def from[E](it: IterableOnce[E]): CC[E] } ~~~ @@ -294,25 +294,25 @@ Let’s detail the implementation of `filter`, step by step: - the instantiation of `View.Filter` creates a (non-strict) `View` that filters the elements of the underlying collection ; -- the call to `fromSpecificIterable` turns the `View` into a concrete - collection `C`. The implementation of `fromSpecificIterable` is left to +- the call to `fromSpecific` turns the `View` into a concrete + collection `C`. The implementation of `fromSpecific` is left to concrete collections: they can decide to evaluate in a strict or non-strict way the elements resulting from the operation. The implementation of `map` is similar, excepted that instead of using -`fromSpecificIterable` it uses `fromIterable` which takes as parameter an +`fromSpecific` it uses `from` which takes as parameter an iterable whose element type `E` is arbitrary. -Actually, `fromIterable` is not abstract in `IterableOps`: it delegates to an -`iterableFactory` member (which is abstract): +Actually, the `from` operation is not defined directly in `IterableOps` but is accessed via +an (abstract) `iterableFactory` member: ~~~ scala trait IterableOps[+A, +CC[_], +C] { - protected def fromIterable[E](it: Iterable[E]): CC[E] = - iterableFactory.from(it) - def iterableFactory: IterableFactory[CC] + + def map[B](f: A => B): CC[B] = + iterableFactory.from(new View.Map(this, f)) } ~~~ @@ -336,12 +336,9 @@ trait MapOps[K, +V, +CC[_, _], +C] extends IterableOps[(K, V), Iterable, C] { def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = - mapFromIterable(new View.Map(this, f)) - - // Similar to fromIterable, but returns a Map collection type - protected def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): CC[K2, V2] = - mapFactory.from(it) + mapFactory.from(new View.Map(this, f)) + // Similar to iterableFactory, but for Map collection types def mapFactory: MapFactory[CC] } @@ -387,7 +384,7 @@ type of elements. The following code shows the relevant parts of `IterableOps` a ~~~ scala trait IterableOps[+A, +CC[_], +C] { def iterableFactory: IterableFactory[CC] - protected def fromSpecificIterable(coll: Iterable[A]): C + protected def fromSpecific(coll: IterableOnce[A]): C protected def newSpecificBuilder: Builder[A, C] } diff --git a/_overviews/core/custom-collection-operations.md b/_overviews/core/custom-collection-operations.md index 29b3e9dd77..87b2f863ae 100644 --- a/_overviews/core/custom-collection-operations.md +++ b/_overviews/core/custom-collection-operations.md @@ -279,7 +279,7 @@ trait BuildFrom[-From, -A, +C] { /** @return a collection of type `C` containing the same elements * (of type `A`) as the source collection `it`. */ - def fromSpecificIterable(from: From)(it: Iterable[A]): C + def fromSpecific(from: From)(it: IterableOnce[A]): C /** @return a Builder for the collection type `C`, containing * elements of type `A`. diff --git a/_overviews/core/custom-collections.md b/_overviews/core/custom-collections.md index b73685ee68..d673110cea 100644 --- a/_overviews/core/custom-collections.md +++ b/_overviews/core/custom-collections.md @@ -72,6 +72,8 @@ class Capped1[A] private (val capacity: Int, val length: Int, offset: Int, elems elem } } + + override def className = "Capped1" } ~~~ @@ -101,6 +103,9 @@ to implement `iterator` to make the generic collection operations (such as `foldLeft`, `count`, etc.) work on `Capped` collections. Here we implement it by using indexed access. +Last, we override `className` to return the name of the collection, +“Capped1”. This name is used by the `toString` operation. + Here are some interactions with the `Capped1` collection: ~~~ scala @@ -165,7 +170,11 @@ class Capped2[A] private (val capacity: Int, val length: Int, offset: Int, elems def iterator: Iterator[A] = // as before + override def className = "Capped2" override val iterableFactory: IterableFactory[Capped2] = new Capped2Factory(capacity) + override protected def fromSpecific(coll: IterableOnce[A]): Capped2[A] = iterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, Capped2[A]] = iterableFactory.newBuilder + override def empty: Capped2[A] = iterableFactory.empty } @@ -199,14 +208,22 @@ type of methods like `map`, `flatMap` or `concat` is defined by the second type parameter passed to class `IterableOps`, i.e., in class `Capped2`, it is `Capped2` itself. -To construct a `Capped2`, the `fromSpecificIterable` and -`newSpecificBuilder` implementations inherited from `immutable.Iterable` -delegate to the `iterableFactory` member, which is overridden here to -return an instance of `Capped2Factory`. This class -provides convenient factory methods to build collections. Eventually, -these methods delegate to `empty`, which builds an empty `Capped2` -instance, and `newBuilder`, which uses the `appended` operation -to grow a `Capped2` collection. +Operations returning `Capped2[A]` collections are implemented in `IterableOps` +in terms of the `fromSpecific` and `newSpecificBuilder` operations. The +`immutable.Iterable[A]` parent class implements the `fromSpecific` and +`newSpecificBuilder` such that they only return `immutable.Iterable[A]` +collections instead of the expected `Capped2[A]` collections. Consequently, +we override the `fromSpecific` and `newSpecificBuilder` operations to +make them return a `Capped2[A]` collection. Another inherited operation +returning a too general type is `empty`. We override it to return a +`Capped2[A]` collection too. All these overrides simply forward to the +collection factory referred to by the `iterableFactory` member, whose value +is an instance of class `Capped2Factory`. + +The `Capped2Factory` class provides convenient factory methods to build +collections. Eventually, these methods delegate to the `empty` operation, +which builds an empty `Capped2` instance, and `newBuilder`, which uses the +`appended` operation to grow a `Capped2` collection. With the refined implementation of the [`Capped2` class](#second-version-of-capped-class), the transformation operations work now as expected, and the @@ -233,9 +250,15 @@ res4: Capped2[Int] = Capped2(2, 3, 4, 5) ~~~ This implementation now behaves correctly, but we can still improve -a few things. Since our collection is strict, we can take advantage -of the better performance offered by -strict implementations of transformation operations. +a few things: + +- since our collection is strict, we can take advantage + of the better performance offered by + strict implementations of transformation operations, +- since our `fromSpecific`, `newSpecificBuilder` and `empty` + operation just forward to the `iterableFactory` member, + we can use the `IterableFactoryDefaults` trait that provides + such implementations. ### Final version of `Capped` class ### @@ -245,6 +268,7 @@ import scala.collection._ final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, elems: Array[Any]) extends immutable.Iterable[A] with IterableOps[A, Capped, Capped[A]] + with IterableFactoryDefaults[A, Capped] with StrictOptimizedIterableOps[A, Capped, Capped[A]] { self => def this(capacity: Int) = @@ -277,6 +301,8 @@ final class Capped[A] private (val capacity: Int, val length: Int, offset: Int, override def knownSize: Int = length + override def className = "Capped" + override val iterableFactory: IterableFactory[Capped] = new CappedFactory(capacity) } @@ -303,6 +329,9 @@ That is it. The final [`Capped` class](#final-version-of-capped-class): - extends the `StrictOptimizedIterableOps` trait, which overrides all transformation operations to take advantage of strict builders, +- extends the `IterableFactoryDefaults` trait, which overrides the + `fromSpecific`, `newSpecificBuilder` and `empty` operations to forward + to the `iterableFactory`, - overrides a few operations for performance: the `view` now uses indexed access, and the `iterator` delegates to the view. The `knownSize` operation is also overridden because the size is always @@ -371,10 +400,12 @@ representation. Base.fromInt(groups(idx / N) >> (idx % N * S) & M) } - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 = - fromSeq(coll.toSeq) + override protected def fromSpecific(coll: IterableOnce[Base]): RNA1 = + fromSeq(coll.iterator.toSeq) override protected def newSpecificBuilder: mutable.Builder[Base, RNA1] = iterableFactory.newBuilder[Base].mapResult(fromSeq) + override def empty: RNA1 = fromSeq(Seq.empty) + override def className = "RNA1" } object RNA1 { @@ -422,7 +453,7 @@ abstract methods: We also override the following members used by transformation operations such as `filter` and `take`: -- `fromSpecificIterable`, implemented by the `fromSeq` method of the `RNA1` +- `fromSpecific`, implemented by the `fromSeq` method of the `RNA1` companion object, - `newSpecificBuilder`, implemented by using the default `IndexedSeq` builder and transforming its result into an `RNA1` with the `mapResult` method. @@ -554,26 +585,28 @@ this is why we always get a `Vector` as a result. import RNA2._ def apply(idx: Int): Base = // as before - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before + override protected def fromSpecific(coll: IterableOnce[Base]): RNA2 = // as before override protected def newSpecificBuilder: mutable.Builder[Base, RNA2] = // as before // Overloading of `appended`, `prepended`, `appendedAll`, // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2` // when possible + def concat(suffix: IterableOnce[Base]): RNA2 = + fromSpecific(iterator ++ suffix.iterator) + // symbolic alias for `concat` + @inline final def ++ (suffix: IterableOnce[Base]): RNA2 = concat(suffix) def appended(base: Base): RNA2 = - fromSpecificIterable(new View.Append(this, base)) - def appendedAll(suffix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(this, suffix)) + fromSpecific(new View.Append(this, base)) + def appendedAll(suffix: IterableOnce[Base]): RNA2 = + concat(suffix) def prepended(base: Base): RNA2 = - fromSpecificIterable(new View.Prepend(base, this)) - def prependedAll(prefix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(prefix, this)) + fromSpecific(new View.Prepend(base, this)) + def prependedAll(prefix: IterableOnce[Base]): RNA2 = + fromSpecific(prefix.iterator ++ iterator) def map(f: Base => Base): RNA2 = - fromSpecificIterable(new View.Map(this, f)) + fromSpecific(new View.Map(this, f)) def flatMap(f: Base => IterableOnce[Base]): RNA2 = - fromSpecificIterable(new View.FlatMap(this, f)) - def concat(suffix: Iterable[Base]): RNA2 = - fromSpecificIterable(new View.Concat(this, suffix)) + fromSpecific(new View.FlatMap(this, f)) } To address this shortcoming, you need to overload the methods that @@ -581,7 +614,7 @@ return an `IndexedSeq[B]` for the case where `B` is known to be `Base`, to return an `RNA2` instead. Compared to [class `RNA1`](#first-version-of-rna-strands-class) -we added overloads for methods `appended`, `appendedAll`, `prepended`, +we added overloads for methods `concat`, `appended`, `appendedAll`, `prepended`, `prependedAll`, `map` and `flatMap`. This implementation now behaves correctly, but we can still improve a few things. Since our @@ -622,43 +655,31 @@ final class RNA private ( Base.fromInt(groups(idx / N) >> (idx % N * S) & M) } - // Mandatory implementation of `fromSpecificIterable` and - // `newSpecificBuilder`, from `IterableOps` - override protected def fromSpecificIterable(coll: Iterable[Base]): RNA = + // Mandatory overrides of `fromSpecific`, `newSpecificBuilder`, + // and `empty`, from `IterableOps` + override protected def fromSpecific(coll: IterableOnce[Base]): RNA = RNA.fromSpecific(coll) override protected def newSpecificBuilder: mutable.Builder[Base, RNA] = RNA.newBuilder + override def empty: RNA = RNA.empty // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`, // `map`, `flatMap` and `concat` to return an `RNA` when possible + def concat(suffix: IterableOnce[Base]): RNA = + strictOptimizedConcat(suffix, newSpecificBuilder) + @inline final def ++ (suffix: IterableOnce[Base]): RNA = concat(suffix) def appended(base: Base): RNA = (newSpecificBuilder ++= this += base).result() def appendedAll(suffix: Iterable[Base]): RNA = - (newSpecificBuilder ++= this ++= suffix).result() + strictOptimizedConcat(suffix, newSpecificBuilder) def prepended(base: Base): RNA = (newSpecificBuilder += base ++= this).result() def prependedAll(prefix: Iterable[Base]): RNA = (newSpecificBuilder ++= prefix ++= this).result() - def map(f: Base => Base): RNA = { - var b = newSpecificBuilder - for (base <- this) { - b += f(base) - } - b.result() - } - def flatMap(f: Base => IterableOnce[Base]): RNA = { - var b = newSpecificBuilder - for (base <- this) { - b ++= f(base) - } - b.result() - } - def concat(suffix: IterableOnce[Base]): RNA = { - val b = newSpecificBuilder - b ++= this - b ++= suffix - b.result() - } + def map(f: Base => Base): RNA = + strictOptimizedMap(newSpecificBuilder, f) + def flatMap(f: Base => IterableOnce[Base]): RNA = + strictOptimizedFlatMap(newSpecificBuilder, f) // Optional re-implementation of iterator, // to make it more efficient. @@ -673,6 +694,7 @@ final class RNA private ( } } + override def className = "RNA" } object RNA extends SpecificIterableFactory[Base, RNA] { @@ -706,12 +728,13 @@ The final [`RNA` class](#final-version-of-rna-strands-class): - extends the `StrictOptimizedSeqOps` trait, which overrides all transformation operations to take advantage of strict builders, -- uses a strict mode for overloads of transformation operations that return - an `RNA`, +- uses utility operations provided by the `StrictOptimizedSeqOps` trait such as + `strictOptimizedConcat` to implement overload of transformation operations that + return an `RNA` collection, - has a companion object that extends `SpecificIterableFactory[Base, RNA]`, which makes it possible to use it as a parameter of a `to` call (to convert any collection of bases to an `RNA`, e.g. `List(U, A, G, C).to(RNA)`), -- moves the `newSpecificBuilder` and `fromSpecificIterable` implementations +- moves the `newSpecificBuilder` and `fromSpecific` implementations to the companion object. The discussion so far centered on the minimal amount of definitions @@ -826,35 +849,23 @@ class PrefixMap[A] } // Overloading of transformation methods that should return a PrefixMap - def map[B](f: ((String, A)) => (String, B)): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - for (kv <- this) { - b += f(kv) - } - b.result() - } - def flatMap[B](f: ((String, A)) => IterableOnce[(String, B)]): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - for (kv <- this) { - b ++= f(kv) - } - b.result() - } + def map[B](f: ((String, A)) => (String, B)): PrefixMap[B] = + strictOptimizedMap(PrefixMap.newBuilder, f) + def flatMap[B](f: ((String, A)) => IterableOnce[(String, B)]): PrefixMap[B] = + strictOptimizedFlatMap(PrefixMap.newBuilder, f) // Override `concat` and `empty` methods to refine their return type - override def concat[B >: A](suffix: Iterable[(String, B)]): PrefixMap[B] = { - val b = PrefixMap.newBuilder[B] - b ++= this - b ++= suffix - b.result() - } + override def concat[B >: A](suffix: IterableOnce[(String, B)]): PrefixMap[B] = + strictOptimizedConcat(suffix, PrefixMap.newBuilder) override def empty: PrefixMap[A] = new PrefixMap // Members declared in scala.collection.mutable.Clearable - def clear(): Unit = suffixes = immutable.Map.empty + override def clear(): Unit = suffixes = immutable.Map.empty // Members declared in scala.collection.IterableOps - override protected def fromSpecificIterable(coll: Iterable[(String, A)]): PrefixMap[A] = PrefixMap.from(coll) + override protected def fromSpecific(coll: IterableOnce[(String, A)]): PrefixMap[A] = PrefixMap.from(coll) override protected def newSpecificBuilder: mutable.Builder[(String, A), PrefixMap[A]] = PrefixMap.newBuilder + + override def className = "PrefixMap" } object PrefixMap { @@ -871,6 +882,8 @@ object PrefixMap { def newBuilder[A]: mutable.Builder[(String, A), PrefixMap[A]] = new mutable.GrowableBuilder[(String, A), PrefixMap[A]](empty) + import scala.language.implicitConversions + implicit def toFactory[A](self: this.type): Factory[(String, A), PrefixMap[A]] = new Factory[(String, A), PrefixMap[A]] { def fromSpecific(it: IterableOnce[(String, A)]): PrefixMap[A] = self.from(it) @@ -953,8 +966,7 @@ exactly one element `x`, if the option value is `Some(x)`. However, in all these cases, to build the right kind of collection you need to start with an empty collection of that kind. This is -provided by the `empty` method, which is the last method defined in -`PrefixMap`. This method simply returns a fresh `PrefixMap`. +provided by the `empty` method, which simply returns a fresh `PrefixMap`. We'll now turn to the companion object `PrefixMap`. In fact it is not strictly necessary to define this companion object, as class `PrefixMap` From e6c3ab621a841d3ec0d2f96fa7ced062c5a8563d Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 9 Apr 2019 13:40:10 +0200 Subject: [PATCH 0548/3174] Credit book Programming in Scala --- _overviews/core/architecture-of-scala-213-collections.md | 7 +++++++ _overviews/core/custom-collections.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/_overviews/core/architecture-of-scala-213-collections.md b/_overviews/core/architecture-of-scala-213-collections.md index 557c8c0258..ad4fede7b7 100644 --- a/_overviews/core/architecture-of-scala-213-collections.md +++ b/_overviews/core/architecture-of-scala-213-collections.md @@ -425,3 +425,10 @@ This document explains that: You now have all the required knowledge to implement [custom collection types]({{ site.baseurl }}/overviews/core/custom-collections.html). + +### Acknowledgement ### + +This page contains material adapted from the book +[Programming in Scala](http://www.artima.com/shop/programming_in_scala) by +Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its +publication. diff --git a/_overviews/core/custom-collections.md b/_overviews/core/custom-collections.md index d673110cea..65941555ce 100644 --- a/_overviews/core/custom-collections.md +++ b/_overviews/core/custom-collections.md @@ -1010,7 +1010,7 @@ methods without having to reimplement them all over again. ### Acknowledgement ### -These pages contain material adapted from the 2nd edition of +This page contains material adapted from the book [Programming in Scala](http://www.artima.com/shop/programming_in_scala) by Odersky, Spoon and Venners. We thank Artima for graciously agreeing to its publication. From cfa0b2f9be2286f4c1c9bff29649819d8a275883 Mon Sep 17 00:00:00 2001 From: matko-CT Date: Wed, 10 Apr 2019 11:02:19 +0200 Subject: [PATCH 0549/3174] typo underly to underlie --- _overviews/collections/concrete-immutable-collection-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections/concrete-immutable-collection-classes.md b/_overviews/collections/concrete-immutable-collection-classes.md index 78ca9d0857..64bfb62655 100644 --- a/_overviews/collections/concrete-immutable-collection-classes.md +++ b/_overviews/collections/concrete-immutable-collection-classes.md @@ -152,7 +152,7 @@ Ranges are represented in constant space, because they can be defined by just th Hash tries are a standard way to implement immutable sets and maps efficiently. They are supported by class [immutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/HashMap.html). Their representation is similar to vectors in that they are also trees where every node has 32 elements or 32 subtrees. But the selection of these keys is now done based on hash code. For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level. -Hash tries strike a nice balance between reasonably fast lookups and reasonably efficient functional insertions (`+`) and deletions (`-`). That's why they underly Scala's default implementations of immutable maps and sets. In fact, Scala has a further optimization for immutable sets and maps that contain less than five elements. Sets and maps with one to four elements are stored as single objects that just contain the elements (or key/value pairs in the case of a map) as fields. The empty immutable set and the empty immutable map is in each case a single object - there's no need to duplicate storage for those because an empty immutable set or map will always stay empty. +Hash tries strike a nice balance between reasonably fast lookups and reasonably efficient functional insertions (`+`) and deletions (`-`). That's why they underlie Scala's default implementations of immutable maps and sets. In fact, Scala has a further optimization for immutable sets and maps that contain less than five elements. Sets and maps with one to four elements are stored as single objects that just contain the elements (or key/value pairs in the case of a map) as fields. The empty immutable set and the empty immutable map is in each case a single object - there's no need to duplicate storage for those because an empty immutable set or map will always stay empty. ## Red-Black Trees From 905395328bfe249feaef59f74950dc462af448f1 Mon Sep 17 00:00:00 2001 From: fmc Date: Wed, 10 Apr 2019 16:36:45 -0400 Subject: [PATCH 0550/3174] [chore] Fix some spelling and grammar errors --- _overviews/macros/typeproviders.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/macros/typeproviders.md b/_overviews/macros/typeproviders.md index db886a9c4b..f6fb1615b3 100644 --- a/_overviews/macros/typeproviders.md +++ b/_overviews/macros/typeproviders.md @@ -35,7 +35,7 @@ concrete examples. Slides and accompanying code can be found at [https://github. ## Introduction Type providers are a strongly-typed type-bridging mechanism, which enables information-rich programming in F# 3.0. -A type provider is a compile-time facility, which is capable of generating definitions and their implementations +A type provider is a compile-time facility which is capable of generating definitions and their implementations based on static parameters describing datasources. Type providers can operate in two modes: non-erased and erased. The former is similar to textual code generation in the sense that every generated type becomes bytecode, while in the latter case generated types only manifest themselves during type checking, but before bytecode generation @@ -70,7 +70,7 @@ takes a connection string and generates a module that encapsulates the given dat new Db {} } -It is true that noone outside the macro expansion block would be able to refer to the `Coffee` class directly, +It is true that no one outside the macro expansion block would be able to refer to the `Coffee` class directly, however if we inspect the type of `db`, we will find something fascinating. scala> val db = h2db("jdbc:h2:coffees.h2.db") From 1077b0ac26a89b64deaa6121ff30869933c7da84 Mon Sep 17 00:00:00 2001 From: Kshitij Date: Sun, 14 Apr 2019 18:16:19 +0530 Subject: [PATCH 0551/3174] Fix reverseSort to first sort and then reverse --- _overviews/FAQ/finding-implicits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/FAQ/finding-implicits.md b/_overviews/FAQ/finding-implicits.md index c12d7b2748..015216f28c 100644 --- a/_overviews/FAQ/finding-implicits.md +++ b/_overviews/FAQ/finding-implicits.md @@ -124,7 +124,7 @@ Context bounds are more useful when you just need to _pass_ them to other methods that use them. For example, the method `sorted` on `Seq` needs an implicit `Ordering`. To create a method `reverseSort`, one could write: - def reverseSort[T : Ordering](seq: Seq[T]) = seq.reverse.sorted + def reverseSort[T : Ordering](seq: Seq[T]) = seq.sorted.reverse Because `Ordering[T]` was implicitly passed to `reverseSort`, it can then pass it implicitly to `sorted`. From 6307ea383f3122ce8faccd65434b60d38598885c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 16 Apr 2019 13:56:53 -0700 Subject: [PATCH 0552/3174] JDK 12 is out --- _overviews/jdk-compatibility/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_overviews/jdk-compatibility/overview.md b/_overviews/jdk-compatibility/overview.md index 477a039c86..b776a87a6b 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -56,9 +56,9 @@ To help with testing on JDK 11, see [scala/scala-dev#559](https://github.com/sca ## JDK 12 compatibility notes -As of February 2019, JDK 12 is not in full release, but early-access builds are available. Note that even the final JDK 12 release will not be an LTS release, so the remarks above about non-LTS releases apply. +JDK 12 was released in March 2019. But it is not an LTS release, so the remarks above about non-LTS releases apply. -Scala has not yet been extensively tested on JDK 12. +Scala has not been extensively tested on JDK 12. However, the Scala 2.12 community build is [up and running](https://scala-ci.typesafe.com/view/scala-2.12.x/job/scala-2.12.x-jdk12-integrate-community-build/) on an early-access JDK 12 build, and most projects are green. @@ -67,7 +67,7 @@ Two significant known issues with Scala 2.12.8 on JDK 12 are: * the `-release` flag doesn't work ([scala/bug#11403](https://github.com/scala/bug/issues/11403)) * the optimizer doesn't work ([scala/bug#11372](https://github.com/scala/bug/issues/11372)) -Both issues have already been fixed. The fixes will be included in [Scala 2.12.9](https://github.com/scala/scala/milestone/77). A release date for 2.12.9 has not been set. In the meantime, consider using a [Scala nightly build](https://stackoverflow.com/questions/40622878/how-do-i-tell-sbt-to-use-a-nightly-build-of-scala-2-12-or-2-13) to test the fixes. +Both issues have already been fixed. The fixes will be included in [Scala 2.12.9](https://github.com/scala/scala/milestone/77). 2.12.9 is tentatively planned for release in June 2019. In the meantime, consider using a [Scala nightly build](https://stackoverflow.com/questions/40622878/how-do-i-tell-sbt-to-use-a-nightly-build-of-scala-2-12-or-2-13) to test the fixes. In other respects, so far it appears that 12 is similar to 11 with respect to Scala compatibility. From ff6580c6247ee091b4805335a67480f2153c3bec Mon Sep 17 00:00:00 2001 From: Bert Kellerman Date: Thu, 18 Apr 2019 08:49:07 -0700 Subject: [PATCH 0553/3174] Update pattern-matching.md --- _tour/pattern-matching.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index 5a6d4969c4..b5f9e37d46 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -65,8 +65,8 @@ case class VoiceRecording(contactName: String, link: String) extends Notificatio ``` def showNotification(notification: Notification): String = { notification match { - case Email(email, title, _) => - s"You got an email from $email with title: $title" + case Email(sender, title, _) => + s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" case VoiceRecording(name, link) => @@ -80,7 +80,7 @@ println(showNotification(someSms)) // prints You got an SMS from 12345! Message println(showNotification(someVoiceRecording)) // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123 ``` -The function `showNotification` takes as a parameter the abstract type `Notification` and matches on the type of `Notification` (i.e. it figures out whether it's an `Email`, `SMS`, or `VoiceRecording`). In the `case Email(email, title, _)` the fields `email` and `title` are used in the return value but the `body` field is ignored with `_`. +The function `showNotification` takes as a parameter the abstract type `Notification` and matches on the type of `Notification` (i.e. it figures out whether it's an `Email`, `SMS`, or `VoiceRecording`). In the `case Email(sender, title, _)` the fields `sender` and `title` are used in the return value but the `body` field is ignored with `_`. ## Pattern guards Pattern guards are simply boolean expressions which are used to make cases more specific. Just add `if ` after the pattern. @@ -88,7 +88,7 @@ Pattern guards are simply boolean expressions which are used to make cases more def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = { notification match { - case Email(email, _, _) if importantPeopleInfo.contains(email) => + case Email(sender, _, _) if importantPeopleInfo.contains(sender) => "You got an email from special someone!" case SMS(number, _) if importantPeopleInfo.contains(number) => "You got an SMS from special someone!" @@ -110,7 +110,7 @@ println(showImportantNotification(importantEmail, importantPeopleInfo)) println(showImportantNotification(importantSms, importantPeopleInfo)) ``` -In the `case Email(email, _, _) if importantPeopleInfo.contains(email)`, the pattern is matched only if the `email` is in the list of important people. +In the `case Email(sender, _, _) if importantPeopleInfo.contains(sender)`, the pattern is matched only if the `sender` is in the list of important people. ## Matching on type only You can match on the type like so: From 03df61186b2d78c3fa26cb6482c9f024030593da Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 22 Apr 2019 19:54:50 -0700 Subject: [PATCH 0554/3174] standardize CoC let's only have the text in one place --- CODE_OF_CONDUCT.md | 81 +++------------------------------------------- 1 file changed, 5 insertions(+), 76 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 948de8e719..0511f2126d 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,78 +1,7 @@ -## Scala Code of Conduct +all repositories in these organizations: -We are committed to providing a friendly, safe and welcoming environment for -all, regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, body size, race, ethnicity, -age, religion, nationality, or other such characteristics. +* [scala](https://github.com/scala) +* [scalacenter](https://github.com/scalacenter) +* [lampepfl](https://github.com/lampepfl) -### Our Standards - -**Whether you’re a regular contributor or a newcomer, we care about making this community a welcoming and safe place for you and we’ve got your back.** - -As a member of the community, you agree to the following: - -**Encouraged:** - -- Be kind and courteous. -- Respect differences of opinion and remember that every design or implementation choice carries a trade-off and numerous costs. There is seldom a single right answer. -- Remember that everyone was new to Scala at some point. We want to encourage newcomers to join our community and learn the Scala language and ecosystem. Assume competence. -- Show empathy towards other community members. - -**Discouraged:** - -- Keep unstructured critique to a minimum. We encourage sharing ideas and perspectives, so please ensure that your feedback is constructive and relevant. If you have solid ideas you want to experiment with, make a fork and see how it works. -- Avoid aggressive and micro-aggressive behavior, such as unconstructive criticism, providing corrections that do not improve the conversation (sometimes referred to as "well actually"s), repeatedly interrupting or talking over someone else, feigning surprise at someone’s lack of knowledge or awareness about a topic, or subtle prejudice (for example, comments like “That’s so easy my grandmother could do it.”). For more examples of this kind of behavior, [see the Recurse Center's user manual](https://www.recurse.com/manual#sec-environment). -- We will exclude you from interaction if you insult, demean or harass anyone. The term “Harassment” includes “Unacceptable Behavior” described in the [Citizen Code of Conduct](http://citizencodeofconduct.org/). **In particular, we don’t tolerate behavior that excludes people in socially marginalized groups.** -- Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member's behavior, please contact one of the [moderators](https://contributors.scala-lang.org/about) or any member of the [Scala Center](http://scala.epfl.ch/) immediately. -- Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. - -### Moderation - -These are the policies for upholding our community’s standards of conduct. If -you feel that a thread needs moderation, please contact anyone on the -[moderation team](https://contributors.scala-lang.org/about), or any employee of -the [Scala Center](https://scala.epfl.ch/). - -- Remarks that violate the above code of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) -- Moderators will warn users who make remarks inconsistent with the above code of conduct. -- If the warning is unheeded, the user will be “kicked,” i.e., kicked out of the communication channel to cool off. -- If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. -- Moderators may choose at their discretion to un-ban the user if it was a first offense and they if they make suitable amends with the offended party. -- If you think a ban is unjustified, please take it up with that moderator, or with a different moderator, in private. Complaints about bans in-channel are not allowed. -- Moderators are held to a higher standard than other community members. If a moderator acts inappropriately, they should expect less leeway than others. - -In the Scala community we strive to go the extra step to look out for each -other. Don’t just aim to be technically unimpeachable; try to be your best self. -In particular, avoid exacerbating offensive or sensitive issues, particularly if -they’re off-topic; this all too often leads to unnecessary fights, hurt -feelings, and damaged trust; worse, it can drive people away from the community -entirely. - -If someone takes issue with something you said or did, resist the urge to be -defensive. Rather, stop the offending behavior, apologize, and be sensitive -thereafter. Even if you feel you were misinterpreted or unfairly accused, -chances are good there was something you could’ve communicated better — remember -that it’s your responsibility to make your fellow Scala developers comfortable. -We are all here first and foremost because we want to talk about cool -technology, and everyone wants to get along in doing so. People are generally -eager to assume good intent and forgive. - -### Domain - -The enforcement policies listed above apply to all official Scala channels: -mailing lists, GitHub repositories and Gitter channels under scala and -scalacenter, Discourse, and Scala Center venues and hackathons. For other -projects adopting the Scala Code of Conduct, please contact the maintainers of -those projects for enforcement. If you wish to use this code of conduct for your -own project, consider explicitly mentioning your moderation policy or making a -copy with your own moderation policy so as to avoid confusion. - -### Credits - -Adapted from and/or inspired by multiple successful Codes of Conduct, including: - -* [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html) -* [The Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) -* [The Contributor Covenant v1.4.0](http://contributor-covenant.org/version/1/4/) -* [The Recurse Center's User Manual](https://www.recurse.com/manual#sec-environment) -* [The 18F Code of Conduct](https://18f.gsa.gov/code-of-conduct/) \ No newline at end of file +are covered by the Scala Code of Conduct: https://scala-lang.org/conduct/ From e1156e6a824aa59a127e02b12ad09705b069a43e Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 26 Apr 2019 11:23:17 +0200 Subject: [PATCH 0555/3174] Copy the strawman FAQ to collections-migration-213 --- _data/overviews.yml | 5 + _overviews/core/collections-migration-213.md | 330 +++++++++++++++++++ 2 files changed, 335 insertions(+) create mode 100644 _overviews/core/collections-migration-213.md diff --git a/_data/overviews.yml b/_data/overviews.yml index 8318194013..0b5470023e 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -82,6 +82,11 @@ url: "collections-2.13/creating-collections-from-scratch.html" - title: Conversions Between Java and Scala Collections url: "collections-2.13/conversions-between-java-and-scala-collections.html" + - title: Migrating a Project to Scala 2.13's Collections + icon: sitemap + url: "core/collections-migration-213.html" + description: "This page describes the main changes for collection users that migrate to Scala + 2.13 and shows how to cross-build projects with Scala 2.11 / 2.12 and 2.13." - title: The Architecture of Scala 2.13’s Collections icon: sitemap url: "core/architecture-of-scala-213-collections.html" diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md new file mode 100644 index 0000000000..64ad70dc07 --- /dev/null +++ b/_overviews/core/collections-migration-213.md @@ -0,0 +1,330 @@ +--- +layout: singlepage-overview +title: Migrating a Project to Scala 2.13's Collections +permalink: /overviews/core/:title.html +--- + +This document describes the main changes for collection users that migrate to Scala 2.13 and shows +how to cross-build projects with Scala 2.11 / 2.12 and 2.13. + +For an in-depth overview of the Scala 2.13 collections library, see the [collections guide]({{ site.baseurl }}/overviews/collections-2.13/introduction.html). The implementation details of the 2.13 collections are explained in the document [the architecture of Scala collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html). + +## What are the major changes? + +See the list at the top of the [2.13.0-M4 release notes](https://github.com/scala/scala/releases/tag/v2.13.0-M4). + +## What are the breaking changes? + +The following table summarizes the breaking changes: + +| Description | Old Code | New Code | Automatic Migration Rule | +| ----------- | -------- | -------- | ------------------------ | +| Method `to[C[_]]` has been removed (it might be reintroduced but deprecated, though) | `xs.to[List]` | `xs.to(List)` | `NewCollections`, `CrossCompat` | +| `mutable.Map` no longer have an `updated` method | `mutable.Map(1 -> 2).updated(1, 3)` | `mutable.Map(1 -> 2).clone() += 1 -> 3` | `NewCollections`, `CrossCompat` | +| `mapValues` and `filterKeys` now return a `MapView` instead of a `Map` | `kvs.mapValues(f)` | `kvs.mapValues(f).toMap` | `RoughlyMapValues` | +| `Iterable` no longer has a `sameElements` operation | `xs1.sameElements(xs2)` | `xs1.iterator.sameElements(xs2)` | `NewCollections`, `CrossCompat` | +| `collection.breakOut` no longer exists | `val xs: List[Int] = ys.map(f)(collection.breakOut)` | `val xs = ys.iterator.map(f).to(List)` | `NewCollections` | +| `zip` on `Map[K, V]` now returns an `Iterable` | `map.zip(iterable)` | `map.zip(iterable).toMap` | `Experimental` | +| `ArrayBuilder.make` does not accept parens anymore | `ArrayBuilder.make[Int]()` | `ArrayBuilder.make[Int]` | `NewCollections`, `CrossCompat` | + +The “Automatic Migration Rule” column gives the name of the migration rule that can be used to automatically update old code to the new expected form. See https://github.com/scala/scala-collection-compat/ for more +details on how to use it. + +Some classes have been removed, made private or have no equivalent in the new design: + +- `ArrayStack`, +- `mutable.FlatHashTable`, +- `mutable.HashTable`, +- `History`, +- `Immutable`, +- `IndexedSeqOptimized`, +- `LazyBuilder`, +- `mutable.LinearSeq`, +- `LinkedEntry`, +- `MapBuilder`, +- `Mutable`, +- `MutableList`, +- `Publisher`, +- `ResizableArray`, +- `RevertibleHistory`, +- `SeqForwarder`, +- `SetBuilder`, +- `Sizing`, +- `SliceInterval`, +- `StackBuilder`, +- `StreamView`, +- `Subscriber`, +- `Undoable`, +- `WrappedArrayBuilder`. + +Other notable changes are: + + - `Iterable.partition` invokes `iterator` twice on non-strict collections and assumes it gets two iterators over the same elements. Strict subclasses override `partition` do perform only a single traversal + - `scala.Seq[+A]` is now `scala.collection.immutable.Seq[A]` (this also affects varargs methods). + - Equality between collections is not anymore defined at the level of `Iterable`. It is defined separately in the `Set`, `Seq` and `Map` branches. Another consequence is that `Iterable` does not anymore have a `canEqual` method. + - The new collections makes more use of overloading. You can find more information about the motivation + behind this choice [here](http://scala-lang.org/blog/2017/05/30/tribulations-canbuildfrom.html). For instance, `Map.map` is overloaded: + + scala> Map(1 -> "a").map + def map[B](f: ((Int, String)) => B): scala.collection.immutable.Iterable[B] + def map[K2, V2](f: ((Int, String)) => (K2, V2)): scala.collection.immutable.Map[K2,V2] + + Type inference has been improved so that `Map(1 -> "a").map(x => (x._1 + 1, x._2))` works, the compiler can infer the parameter type for the function literal. However, using a method reference in 2.13.0-M4 (improvement are on the way for 2.13.0) does not work, and an explicit eta-expansion is necessary: + + scala> def f(t: (Int, String)) = (t._1 + 1, t._2) + scala> Map(1 -> "a").map(f) + ^ + error: missing argument list for method f + Unapplied methods are only converted to functions when a function type is expected. + You can make this conversion explicit by writing `f _` or `f(_)` instead of `f`. + scala> Map(1 -> "a").map(f _) + res10: scala.collection.immutable.Map[Int,String] = ChampHashMap(2 -> a) + - `View`s have been completely redesigned and we expect their usage to have a more predictable evaluation model. + You can read more about the new design [here](http://scala-lang.org/blog/2017/11/28/view-based-collections.html). + - `mutable.ArraySeq` (which wraps an `Array[AnyRef]` in 2.12, meaning that primitives were boxed in the array) can now wrap boxed and unboxed arrays. `mutable.ArraySeq` in 2.13 is in fact equivalent to `WrappedArray` in 2.12, there are specialized subclasses for primitive arrays. Note that a `mutable.ArraySeq` can be used either way for primitive arrays (TODO: document how). `WrappedArray` is deprecated. + - There is no “default” `Factory` (previously known as `[A, C] => CanBuildFrom[Nothing, A, C]`): use `Factory[A, Vector[A]]` explicitly instead. + +## Breaking changes with old syntax still supported + +The following table lists the changes that continue to work with a deprecation warning. + +| Description | Old Code | New Code | Automatic Migration Rule | +| ----------- | -------- | -------- | ------------------------ | +| `collection.Set/Map` no longer have `+` and `-` operations | `xs + 1 - 2` | `xs ++ Set(1) -- Set(2)` | `Experimental` | +| `collection.Map` no longer have `--` operation | `map -- keys` | `map.to(immutable.Map) -- keys` | | +| `immutable.Set/Map`: the `+` operation no longer has an overload accepting multiple values | `Set(1) + (2, 3)` | `Set(1) + 2 + 3` | `NewCollections`, `CrossCompat` | +| `mutable.Set/Map` no longer have a `+` operation | `mutable.Set(1) + 2` | `mutable.Set(1).clone() += 2` | `NewCollections`, `CrossCompat` | +| `SortedSet`: the `to`, `until` and `from` methods are now called `rangeTo`, `rangeUntil` and `rangeFrom`, respectively | `xs.until(42)` | `xs.rangeUntil(42)` | | +| `Traversable` and `TraversableOnce` are replaced with `Iterable` and `IterableOnce`, respectively | `def f(xs: Traversable[Int]): Unit` | `def f(xs: Iterable[Int]): Unit` | `NewCollections`, `CrossCompat` | +| `Stream` is replaced with `LazyList` | `Stream.from(1)` | `LazyList.from(1)` | `RoughlyStreamToLazyList` | +| `Seq#union` is replaced with `concat` | `xs.union(ys)` | `xs.concat(ys)` | | +| `Stream#append` is replaced with `lazyAppendAll` | `xs.append(ys)` | `xs.lazyAppendedAll(ys)` | `NewCollections`, `CrossCompat` | +| `IterableOnce#toIterator` is replaced with `IterableOnce#iterator` | `xs.toIterator` | `xs.iterator` | `NewCollections`, `CrossCompat` | +| `copyToBuffer` has been deprecated | `xs.copyToBuffer(buffer)` | `buffer ++= xs` | `NewCollections`, `CrossCompat` | +| `TupleNZipped` has been replaced with `LazyZipN` | `(xs, ys).zipped` | `xs.lazyZip(ys)` | `NewCollections` | +| `retain` has been renamed to `filterInPlace` | `xs.retain(f)` | `xs.filterInPlace(f.tupled)` | `NewCollections` | +| `:/` and `/:` operators have been deprecated | `(xs :\ y)(f)` | `xs.foldRight(y)(f)` | `NewCollections`, `CrossCompat` | +| `companion` operation has been renamed to `iterableFactory` | `xs.companion` | `xs.iterableFactory` | | + +## Deprecated things in 2.12 that have been removed in 2.13 + +- `collection.convert.JavaConversions`. Use `collection.convert.JavaConverters` instead ; +- `collection.mutable.MutableList` (was not deprecated in 2.12 but was considered to be an implementation detail for implementing other collections). Use an `ArrayDeque` instead, or a `List` and a `var` ; +- `collection.immutable.Stack`. Use a `List` instead ; +- `StackProxy`, `MapProxy`, `SetProxy`, `SeqProxy`, etc. No replacement ; +- `SynchronizedMap`, `SynchronizedBuffer`, etc. Use `java.util.concurrent` instead ; + +## Are there new collection types? + +`scala.collection.immutable.ArraySeq` is an immutable sequence backed by an array. It is used to pass varargs parameters. + +The [`scala-collection-contrib`](https://github.com/scala/scala-collection-contrib) module provides decorators enriching the collections with new operations. You can +think of this artifact as an incubator: if we get evidence that these operations should be part of the core, +we might eventually move them. + +The following collections are provided: + +- `MultiSet` (both mutable and immutable) +- `SortedMultiSet` (both mutable and immutable) +- `MultiDict` (both mutable and immutable) +- `SortedMultiDict` (both mutable and immutable) + +## Are there new operations on collections? + +The following new partitioning operations are available: + +~~~ scala +def groupMap[K, B](key: A => K)(f: A => B): Map[K, CC[B]] // (Where `CC` can be `List`, for instance) +def groupMapReduce[K, B](key: A => K)(f: A => B)(g: (B, B) => B): Map[K, B] +~~~ + +`groupMap` is equivalent to `groupBy(key).mapValues(_.map(f))`. + +`groupMapReduce` is equivalent to `groupBy(key).mapValues(_.map(f).reduce(g))`. + +Mutable collections now have transformation operations that modify the collection in place: + +~~~ scala +def mapInPlace(f: A => A): this.type +def flatMapInPlace(f: A => IterableOnce[A]): this.type +def filterInPlace(p: A => Boolean): this.type +def patchInPlace(from: Int, patch: scala.collection.Seq[A], replaced: Int): this.type +~~~ + +Another new operation is `distinctBy`: + +~~~ scala +def distinctBy[B](f: A => B): C // (Where `C` can be `List[Int]`, for instance) +~~~ + +Last, additional operations are provided by the `scala-collection-contrib` module. You can +think of this artifact as an incubator: if we get evidence that these operations should be part of the core, +we might eventually move them. + +The new operations are provided via an implicit enrichment. You need to add the following import to make them +available: + +~~~ scala +import strawman.collection.decorators._ +~~~ + +The following operations are provided: + +- `Seq` + - `intersperse` +- `Map` + - `zipByKey` / `join` / `zipByKeyWith` + - `mergeByKey` / `fullOuterJoin` / `mergeByKeyWith` / `leftOuterJoin` / `rightOuterJoin` + +## Are there new implementations of existing collection types (changes in performance characteristics)? + +The default `Set` and `Map` are backed by a `ChampHashSet` and a `ChampHashMap`, respectively. The performance characteristics are the same but the +operation implementations are faster. These data structures also have a lower memory footprint. + +`mutable.Queue` and `mutable.Stack` now use `mutable.ArrayDeque`. This data structure supports constant time index access, and amortized constant time +insert and remove operations. + +## How do I cross-build my project against Scala 2.12 and Scala 2.13? + +Most usages of collections are compatible and can cross-compile 2.12 and 2.13 (at the cost of some warnings, sometimes). + +If you cannot get your code to cross-compile, there are various solutions: + - You can maintain a separate branch with the changes for 2.13 and publish releases for 2.13 from this branch. + - You can put source files that don't cross-compile in separate directories and configure sbt to assemble the sources according to the Scala version (see also the examples below): + + // Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer + // and a `src/main/scala-2.13-` source directory for Scala version older than 2.13 + unmanagedSourceDirectories in Compile += { + val sourceDir = (sourceDirectory in Compile).value + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+" + case _ => sourceDir / "scala-2.13-" + } + } + + - You can use the [`scala-collection-compat`](https://github.com/scala/scala-collection-compat) library, which makes some of 2.13's APIs available to 2.11 and 2.12. This solution does not always work, for example if your library implements custom collection types. + +Note that the `scala-collection-compat` library has not fully stabilized yet. We expect that new, binary incompatible versions of this library will be published (for 2.11, 2.12) until Scala 2.13 is getting close to its final state. Therefore you might want to avoid adding a dependency on that library to your 2.11 / 2.12 artifacts for the time being. + +Examples of libraries that cross-compile with separate source directories: + - https://github.com/scala/scala-parser-combinators/pull/152 + - https://github.com/scala/scala-xml/pull/222 + - Some other examples are listed here: https://github.com/scala/community-builds/issues/710 + +# Collection Implementers + +## `CanBuildFrom` no longer exists - what were its uses and how can they be replaced? + +`CanBuildFrom` was used to: + - generically implement transformation operations whose return type could + vary according to the type of collection elements (ie mapping a `Char` to a `Char` in a `String` + returns a `String`, but mapping a `Char` to an `Int` returns a `IndexedSeq[Int]`), + - abstract over the arity of collection type constructors (ie `List[_]` vs `Map[_, _]`), + - abstract over implicit parameters required to perform a transformation operations (ie mapping an `A` to a `B` in `SortedSet[A]` + requires an implicit `Ordering[B]` to return a `SortedSet[B]`), + - provide type-driven builders to implement generic transformation methods (eg `Future.traverse`). + +The first three points are now handled using overloading. This means that `Map[K, V]` has two overloads of `map`, +one that takes a `(K, V) => (K', V')` mapping function and returns a `Map[K', V']`, and one that takes a +`(K, V) => A` mapping function and returns an `Iterable[A]`. + +You can find more information about the design [here](http://scala-lang.org/blog/2017/05/30/tribulations-canbuildfrom.html). + +To address the last point, there is a `BuildFrom` typeclass that works exactly like the former `CanBuildFrom`. See the next section +for examples of use. + +## How can I write generic extension methods? + +Depending on the level of desired genericity, several solutions can apply, with different complexity. + +### Write an operation that can consume any collection + +Take an `IterableOnce[A]` as parameter, or an `Iterable[A]` if you need more than one +traversals: + +~~~ scala +implicit class SumByOperation[A](coll: IterableOnce[A]) { + def sumBy[B](f: A => B)(implicit num: Numeric[B]): B = { + val it = coll.iterator + var result = f(it.next()) + while (it.hasNext()) { + result = num.plus(result, it.next()) + } + result + } +} +~~~ + +### Write an operation that returns another collection + +Use `BuildFrom`: + +~~~ scala +def optionSequence[CC[X] <: Iterable[X], A, To](xs: CC[Option[A]])(implicit bf: BuildFrom[CC[Option[A]], A, To]): Option[To] = + xs.foldLeft[Option[Builder[A, To]]](Some(bf.newBuilder(xs))) { + case (Some(builder), Some(a)) => Some(builder += a) + case _ => None + }.map(_.result()) +~~~ + +The `optionSequence` operation can be used on any collection (but not on an `Array` or a `String`): + +~~~ +scala> optionSequence(List[Option[Int]](Some(1), Some(2), Some(3))) +res1: Option[List[Int]] = Some(List(1, 2, 3)) + +scala> optionSequence(Set[Option[(Int, String)]](Some(1 -> "foo"), Some(2 -> "bar")))(TreeMap) // Force the result type +res4: Option[scala.collection.immutable.TreeMap[Int,String]] = Some(TreeMap(1 -> foo, 2 -> bar)) +~~~ + +### Write an operation that can also be applied to a `View`, an `Array` or `String` + +For more advanced cases, or if your operation should also work with `Array`s, `String`s and `View`s, +the pattern given in the previous section is not enough. + +The [`scala-collection-contrib`](https://github.com/scala/scala-collection-contrib) module +provides a more advanced machinery that handles that: + +~~~ scala +class IntersperseOperation[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { + def intersperse[B >: seq.A, That](sep: B)(implicit bf: BuildFrom[C, B, That]): That = + bf.fromSpecificIterable(coll)(new View.Intersperse(seq(coll), sep)) // (Assume that there is a `View.Intersperse` implemented somewhere) +} + +implicit def IntersperseOperation[C](coll: C)(implicit seq: HasSeqOps[C]): SeqDecorator[C, seq.type] = + new IntersperseOperation(coll)(seq) +~~~ + +This pattern makes the `intersperse` operation available to any `Seq` _like_ type (eg. a `SeqView`, an `Array` or a `String`). + +## How do I integrate my collection in the new design? + +See the [online documentation](https://docs.scala-lang.org/overviews/core/custom-collections.html) + +The API of the template traits has changed: +- they used to be suffixed by “Like” (e.g. `SeqLike`), whereas they are now suffixed by “Ops” (e.g. `SeqOps`), +- they used to abstract over the collection type of transformation operations, they now abstract over both + the collection type and the collection type constructor: `SeqLike[+A, +Repr]` has been replaced with + `SeqOps[+A, +CC[_], +C]`. + +## Which methods should I overload to support the “same result type” principle? + +You want to add overloads to specialize a transformation operations such that they return a more specific result. Examples are: +- `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), +- `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), +- `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a +`SortedSet` (instead of a `Set`). + +The following table lists transformation operations that might return a too wide type. You might want to overload +these operations to return a more specific type. + + Collection | Operations +---------------|-------------- +`Iterable` | `map`, `flatMap`, `collect`, `scanLeft`, `scanRight`, `groupMap`, `concat`, `zip`, `zipWithIndex`, `zipAll`, `unzip` +`Seq` | `prepended`, `appended`, `prependedAll`, `appendedAll`, `padTo`, `patch` +`immutable.Seq`| `updated` +`SortedSet` | `map`, `flatMap`, `collect`, `zip` +`Map` | `map`, `flatMap`, `collect`, `concat` +`immutable.Map`| `updated`, `transform` +`SortedMap` | `map`, `flatMap`, `collect`, `concat` +`immutable.SortedMap` | `updated` From fb973a8c3c8dd25f2eaf29151a5c6a34b7bbb6c9 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 26 Apr 2019 11:26:07 +0200 Subject: [PATCH 0556/3174] minor typos --- _overviews/core/collections-migration-213.md | 52 ++++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 64ad70dc07..0e130c677a 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -27,35 +27,35 @@ The following table summarizes the breaking changes: | `zip` on `Map[K, V]` now returns an `Iterable` | `map.zip(iterable)` | `map.zip(iterable).toMap` | `Experimental` | | `ArrayBuilder.make` does not accept parens anymore | `ArrayBuilder.make[Int]()` | `ArrayBuilder.make[Int]` | `NewCollections`, `CrossCompat` | -The “Automatic Migration Rule” column gives the name of the migration rule that can be used to automatically update old code to the new expected form. See https://github.com/scala/scala-collection-compat/ for more +The “Automatic Migration Rule” column gives the name of the migration rule that can be used to automatically update old code to the new expected form. See [scala-collection-compat](https://github.com/scala/scala-collection-compat) for more details on how to use it. Some classes have been removed, made private or have no equivalent in the new design: -- `ArrayStack`, -- `mutable.FlatHashTable`, -- `mutable.HashTable`, -- `History`, -- `Immutable`, -- `IndexedSeqOptimized`, -- `LazyBuilder`, -- `mutable.LinearSeq`, -- `LinkedEntry`, -- `MapBuilder`, -- `Mutable`, -- `MutableList`, -- `Publisher`, -- `ResizableArray`, -- `RevertibleHistory`, -- `SeqForwarder`, -- `SetBuilder`, -- `Sizing`, -- `SliceInterval`, -- `StackBuilder`, -- `StreamView`, -- `Subscriber`, -- `Undoable`, -- `WrappedArrayBuilder`. +- `ArrayStack` +- `mutable.FlatHashTable` +- `mutable.HashTable` +- `History` +- `Immutable` +- `IndexedSeqOptimized` +- `LazyBuilder` +- `mutable.LinearSeq` +- `LinkedEntry` +- `MapBuilder` +- `Mutable` +- `MutableList` +- `Publisher` +- `ResizableArray` +- `RevertibleHistory` +- `SeqForwarder` +- `SetBuilder` +- `Sizing` +- `SliceInterval` +- `StackBuilder` +- `StreamView` +- `Subscriber` +- `Undoable` +- `WrappedArrayBuilder` Other notable changes are: @@ -299,7 +299,7 @@ This pattern makes the `intersperse` operation available to any `Seq` _like_ typ ## How do I integrate my collection in the new design? -See the [online documentation](https://docs.scala-lang.org/overviews/core/custom-collections.html) +See the [online documentation]({{ site.baseurl }}/overviews/core/custom-collections.html) The API of the template traits has changed: - they used to be suffixed by “Like” (e.g. `SeqLike`), whereas they are now suffixed by “Ops” (e.g. `SeqOps`), From a68cd1b802acf5c1df0f7e9b5cbb78d0223c9ef4 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 29 Apr 2019 11:59:00 +0200 Subject: [PATCH 0557/3174] review feedback --- _overviews/core/collections-migration-213.md | 188 +++++-------------- 1 file changed, 44 insertions(+), 144 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 0e130c677a..10bcb21dbf 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -9,26 +9,39 @@ how to cross-build projects with Scala 2.11 / 2.12 and 2.13. For an in-depth overview of the Scala 2.13 collections library, see the [collections guide]({{ site.baseurl }}/overviews/collections-2.13/introduction.html). The implementation details of the 2.13 collections are explained in the document [the architecture of Scala collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html). -## What are the major changes? - -See the list at the top of the [2.13.0-M4 release notes](https://github.com/scala/scala/releases/tag/v2.13.0-M4). +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. + - 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)). + - New collection types: + - `immutable.ArraySeq` is an effectively immutable sequence that wraps an array + - `immutable.LazyList` is a linked list that is lazy in its state, i.e., whether it's empty or non-empty. This allows creating a `LazyList` without evaluating the `head` element. `immutable.Stream`, which has a strict `head` and a lazy `tail`, is deprecated. + - Deprecated collections were removed (`MutableList`, `immutable.Stack`, others) + - Parallel collections are now in a separate hierarchy in a [separate module](https://github.com/scala/scala-parallel-collections). + - The `scala.jdk.StreamConverters` object provides extension methods to create (sequential or parallel) Java 8 streams for Scala collections. + - `scala.Seq` is now an alias for `scala.collection.immutable.Seq` (no longer `scala.collection.Seq`). Note that this also changes the type of Scala varargs methods. + +## Tools for migrating and cross-building + +The [scala-collection-compat](https://github.com/scala/scala-collection-compat) is a library released for 2.11, 2.12 and 2.13 that provides some of the new APIs from Scala 2.13 for the older versions. This simplifies cross-building projects. + +The module also provides [migratrion rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. ## What are the breaking changes? -The following table summarizes the breaking changes: +The following table summarizes the breaking changes. The "Automatic Migration Rule" column gives the name of the migration rule that can be used to automatically update old code to the new expected form. | Description | Old Code | New Code | Automatic Migration Rule | | ----------- | -------- | -------- | ------------------------ | -| Method `to[C[_]]` has been removed (it might be reintroduced but deprecated, though) | `xs.to[List]` | `xs.to(List)` | `NewCollections`, `CrossCompat` | -| `mutable.Map` no longer have an `updated` method | `mutable.Map(1 -> 2).updated(1, 3)` | `mutable.Map(1 -> 2).clone() += 1 -> 3` | `NewCollections`, `CrossCompat` | +| Method `to[C[_]]` has been removed (it might be reintroduced but deprecated, though) | `xs.to[List]` | `xs.to(List)` | `Collection213Upgrade`, `Collections213CrossCompat` | | `mapValues` and `filterKeys` now return a `MapView` instead of a `Map` | `kvs.mapValues(f)` | `kvs.mapValues(f).toMap` | `RoughlyMapValues` | -| `Iterable` no longer has a `sameElements` operation | `xs1.sameElements(xs2)` | `xs1.iterator.sameElements(xs2)` | `NewCollections`, `CrossCompat` | -| `collection.breakOut` no longer exists | `val xs: List[Int] = ys.map(f)(collection.breakOut)` | `val xs = ys.iterator.map(f).to(List)` | `NewCollections` | -| `zip` on `Map[K, V]` now returns an `Iterable` | `map.zip(iterable)` | `map.zip(iterable).toMap` | `Experimental` | -| `ArrayBuilder.make` does not accept parens anymore | `ArrayBuilder.make[Int]()` | `ArrayBuilder.make[Int]` | `NewCollections`, `CrossCompat` | - -The “Automatic Migration Rule” column gives the name of the migration rule that can be used to automatically update old code to the new expected form. See [scala-collection-compat](https://github.com/scala/scala-collection-compat) for more -details on how to use it. +| `Iterable` no longer has a `sameElements` operation | `xs1.sameElements(xs2)` | `xs1.iterator.sameElements(xs2)` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `collection.breakOut` no longer exists | `val xs: List[Int] = ys.map(f)(collection.breakOut)` | `val xs = ys.iterator.map(f).to(List)` | `Collection213Upgrade` | +| `zip` on `Map[K, V]` now returns an `Iterable` | `map.zip(iterable)` | `map.zip(iterable).toMap` | `Collection213Experimental` | +| `ArrayBuilder.make` does not accept parens anymore | `ArrayBuilder.make[Int]()` | `ArrayBuilder.make[Int]` | `Collection213Upgrade`, `Collections213CrossCompat` | Some classes have been removed, made private or have no equivalent in the new design: @@ -82,7 +95,7 @@ Other notable changes are: - `View`s have been completely redesigned and we expect their usage to have a more predictable evaluation model. You can read more about the new design [here](http://scala-lang.org/blog/2017/11/28/view-based-collections.html). - `mutable.ArraySeq` (which wraps an `Array[AnyRef]` in 2.12, meaning that primitives were boxed in the array) can now wrap boxed and unboxed arrays. `mutable.ArraySeq` in 2.13 is in fact equivalent to `WrappedArray` in 2.12, there are specialized subclasses for primitive arrays. Note that a `mutable.ArraySeq` can be used either way for primitive arrays (TODO: document how). `WrappedArray` is deprecated. - - There is no “default” `Factory` (previously known as `[A, C] => CanBuildFrom[Nothing, A, C]`): use `Factory[A, Vector[A]]` explicitly instead. + - There is no "default" `Factory` (previously known as `[A, C] => CanBuildFrom[Nothing, A, C]`): use `Factory[A, Vector[A]]` explicitly instead. ## Breaking changes with old syntax still supported @@ -90,20 +103,21 @@ The following table lists the changes that continue to work with a deprecation w | Description | Old Code | New Code | Automatic Migration Rule | | ----------- | -------- | -------- | ------------------------ | -| `collection.Set/Map` no longer have `+` and `-` operations | `xs + 1 - 2` | `xs ++ Set(1) -- Set(2)` | `Experimental` | +| `collection.Set/Map` no longer have `+` and `-` operations | `xs + 1 - 2` | `xs ++ Set(1) -- Set(2)` | `Collection213Experimental` | | `collection.Map` no longer have `--` operation | `map -- keys` | `map.to(immutable.Map) -- keys` | | -| `immutable.Set/Map`: the `+` operation no longer has an overload accepting multiple values | `Set(1) + (2, 3)` | `Set(1) + 2 + 3` | `NewCollections`, `CrossCompat` | -| `mutable.Set/Map` no longer have a `+` operation | `mutable.Set(1) + 2` | `mutable.Set(1).clone() += 2` | `NewCollections`, `CrossCompat` | +| `immutable.Set/Map`: the `+` operation no longer has an overload accepting multiple values | `Set(1) + (2, 3)` | `Set(1) + 2 + 3` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `mutable.Map` no longer have an `updated` method | `mutable.Map(1 -> 2).updated(1, 3)` | `mutable.Map(1 -> 2).clone() += 1 -> 3` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `mutable.Set/Map` no longer have a `+` operation | `mutable.Set(1) + 2` | `mutable.Set(1).clone() += 2` | `Collection213Upgrade`, `Collections213CrossCompat` | | `SortedSet`: the `to`, `until` and `from` methods are now called `rangeTo`, `rangeUntil` and `rangeFrom`, respectively | `xs.until(42)` | `xs.rangeUntil(42)` | | -| `Traversable` and `TraversableOnce` are replaced with `Iterable` and `IterableOnce`, respectively | `def f(xs: Traversable[Int]): Unit` | `def f(xs: Iterable[Int]): Unit` | `NewCollections`, `CrossCompat` | -| `Stream` is replaced with `LazyList` | `Stream.from(1)` | `LazyList.from(1)` | `RoughlyStreamToLazyList` | +| `Traversable` and `TraversableOnce` are replaced with `Iterable` and `IterableOnce`, respectively | `def f(xs: Traversable[Int]): Unit` | `def f(xs: Iterable[Int]): Unit` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `Stream` is replaced with `LazyList` | `Stream.from(1)` | `LazyList.from(1)` | `Collection213Roughly` | | `Seq#union` is replaced with `concat` | `xs.union(ys)` | `xs.concat(ys)` | | -| `Stream#append` is replaced with `lazyAppendAll` | `xs.append(ys)` | `xs.lazyAppendedAll(ys)` | `NewCollections`, `CrossCompat` | -| `IterableOnce#toIterator` is replaced with `IterableOnce#iterator` | `xs.toIterator` | `xs.iterator` | `NewCollections`, `CrossCompat` | -| `copyToBuffer` has been deprecated | `xs.copyToBuffer(buffer)` | `buffer ++= xs` | `NewCollections`, `CrossCompat` | -| `TupleNZipped` has been replaced with `LazyZipN` | `(xs, ys).zipped` | `xs.lazyZip(ys)` | `NewCollections` | -| `retain` has been renamed to `filterInPlace` | `xs.retain(f)` | `xs.filterInPlace(f.tupled)` | `NewCollections` | -| `:/` and `/:` operators have been deprecated | `(xs :\ y)(f)` | `xs.foldRight(y)(f)` | `NewCollections`, `CrossCompat` | +| `Stream#append` is replaced with `lazyAppendAll` | `xs.append(ys)` | `xs.lazyAppendedAll(ys)` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `IterableOnce#toIterator` is replaced with `IterableOnce#iterator` | `xs.toIterator` | `xs.iterator` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `copyToBuffer` has been deprecated | `xs.copyToBuffer(buffer)` | `buffer ++= xs` | `Collection213Upgrade`, `Collections213CrossCompat` | +| `TupleNZipped` has been replaced with `LazyZipN` | `(xs, ys).zipped` | `xs.lazyZip(ys)` | `Collection213Upgrade` | +| `retain` has been renamed to `filterInPlace` | `xs.retain(f)` | `xs.filterInPlace(f.tupled)` | `Collection213Upgrade` | +| `:/` and `/:` operators have been deprecated | `(xs :\ y)(f)` | `xs.foldRight(y)(f)` | `Collection213Upgrade`, `Collections213CrossCompat` | | `companion` operation has been renamed to `iterableFactory` | `xs.companion` | `xs.iterableFactory` | | ## Deprecated things in 2.12 that have been removed in 2.13 @@ -189,6 +203,7 @@ insert and remove operations. Most usages of collections are compatible and can cross-compile 2.12 and 2.13 (at the cost of some warnings, sometimes). If you cannot get your code to cross-compile, there are various solutions: + - You can use the [`scala-collection-compat`](https://github.com/scala/scala-collection-compat) library, which makes some of 2.13's APIs available to 2.11 and 2.12. This solution does not always work, for example if your library implements custom collection types. - You can maintain a separate branch with the changes for 2.13 and publish releases for 2.13 from this branch. - You can put source files that don't cross-compile in separate directories and configure sbt to assemble the sources according to the Scala version (see also the examples below): @@ -202,10 +217,6 @@ If you cannot get your code to cross-compile, there are various solutions: } } - - You can use the [`scala-collection-compat`](https://github.com/scala/scala-collection-compat) library, which makes some of 2.13's APIs available to 2.11 and 2.12. This solution does not always work, for example if your library implements custom collection types. - -Note that the `scala-collection-compat` library has not fully stabilized yet. We expect that new, binary incompatible versions of this library will be published (for 2.11, 2.12) until Scala 2.13 is getting close to its final state. Therefore you might want to avoid adding a dependency on that library to your 2.11 / 2.12 artifacts for the time being. - Examples of libraries that cross-compile with separate source directories: - https://github.com/scala/scala-parser-combinators/pull/152 - https://github.com/scala/scala-xml/pull/222 @@ -213,118 +224,7 @@ Examples of libraries that cross-compile with separate source directories: # Collection Implementers -## `CanBuildFrom` no longer exists - what were its uses and how can they be replaced? - -`CanBuildFrom` was used to: - - generically implement transformation operations whose return type could - vary according to the type of collection elements (ie mapping a `Char` to a `Char` in a `String` - returns a `String`, but mapping a `Char` to an `Int` returns a `IndexedSeq[Int]`), - - abstract over the arity of collection type constructors (ie `List[_]` vs `Map[_, _]`), - - abstract over implicit parameters required to perform a transformation operations (ie mapping an `A` to a `B` in `SortedSet[A]` - requires an implicit `Ordering[B]` to return a `SortedSet[B]`), - - provide type-driven builders to implement generic transformation methods (eg `Future.traverse`). - -The first three points are now handled using overloading. This means that `Map[K, V]` has two overloads of `map`, -one that takes a `(K, V) => (K', V')` mapping function and returns a `Map[K', V']`, and one that takes a -`(K, V) => A` mapping function and returns an `Iterable[A]`. - -You can find more information about the design [here](http://scala-lang.org/blog/2017/05/30/tribulations-canbuildfrom.html). - -To address the last point, there is a `BuildFrom` typeclass that works exactly like the former `CanBuildFrom`. See the next section -for examples of use. - -## How can I write generic extension methods? - -Depending on the level of desired genericity, several solutions can apply, with different complexity. - -### Write an operation that can consume any collection - -Take an `IterableOnce[A]` as parameter, or an `Iterable[A]` if you need more than one -traversals: - -~~~ scala -implicit class SumByOperation[A](coll: IterableOnce[A]) { - def sumBy[B](f: A => B)(implicit num: Numeric[B]): B = { - val it = coll.iterator - var result = f(it.next()) - while (it.hasNext()) { - result = num.plus(result, it.next()) - } - result - } -} -~~~ - -### Write an operation that returns another collection - -Use `BuildFrom`: - -~~~ scala -def optionSequence[CC[X] <: Iterable[X], A, To](xs: CC[Option[A]])(implicit bf: BuildFrom[CC[Option[A]], A, To]): Option[To] = - xs.foldLeft[Option[Builder[A, To]]](Some(bf.newBuilder(xs))) { - case (Some(builder), Some(a)) => Some(builder += a) - case _ => None - }.map(_.result()) -~~~ - -The `optionSequence` operation can be used on any collection (but not on an `Array` or a `String`): - -~~~ -scala> optionSequence(List[Option[Int]](Some(1), Some(2), Some(3))) -res1: Option[List[Int]] = Some(List(1, 2, 3)) - -scala> optionSequence(Set[Option[(Int, String)]](Some(1 -> "foo"), Some(2 -> "bar")))(TreeMap) // Force the result type -res4: Option[scala.collection.immutable.TreeMap[Int,String]] = Some(TreeMap(1 -> foo, 2 -> bar)) -~~~ - -### Write an operation that can also be applied to a `View`, an `Array` or `String` - -For more advanced cases, or if your operation should also work with `Array`s, `String`s and `View`s, -the pattern given in the previous section is not enough. - -The [`scala-collection-contrib`](https://github.com/scala/scala-collection-contrib) module -provides a more advanced machinery that handles that: - -~~~ scala -class IntersperseOperation[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { - def intersperse[B >: seq.A, That](sep: B)(implicit bf: BuildFrom[C, B, That]): That = - bf.fromSpecificIterable(coll)(new View.Intersperse(seq(coll), sep)) // (Assume that there is a `View.Intersperse` implemented somewhere) -} - -implicit def IntersperseOperation[C](coll: C)(implicit seq: HasSeqOps[C]): SeqDecorator[C, seq.type] = - new IntersperseOperation(coll)(seq) -~~~ - -This pattern makes the `intersperse` operation available to any `Seq` _like_ type (eg. a `SeqView`, an `Array` or a `String`). - -## How do I integrate my collection in the new design? - -See the [online documentation]({{ site.baseurl }}/overviews/core/custom-collections.html) - -The API of the template traits has changed: -- they used to be suffixed by “Like” (e.g. `SeqLike`), whereas they are now suffixed by “Ops” (e.g. `SeqOps`), -- they used to abstract over the collection type of transformation operations, they now abstract over both - the collection type and the collection type constructor: `SeqLike[+A, +Repr]` has been replaced with - `SeqOps[+A, +CC[_], +C]`. - -## Which methods should I overload to support the “same result type” principle? - -You want to add overloads to specialize a transformation operations such that they return a more specific result. Examples are: -- `map`, on `StringOps`, when the mapping function returns a `Char`, should return a `String` (instead of an `IndexedSeq`), -- `map`, on `Map`, when the mapping function returns a pair, should return a `Map` (instead of an `Iterable`), -- `map`, on `SortedSet`, when an implicit `Ordering` is available for the resulting element type, should return a -`SortedSet` (instead of a `Set`). - -The following table lists transformation operations that might return a too wide type. You might want to overload -these operations to return a more specific type. - - Collection | Operations ----------------|-------------- -`Iterable` | `map`, `flatMap`, `collect`, `scanLeft`, `scanRight`, `groupMap`, `concat`, `zip`, `zipWithIndex`, `zipAll`, `unzip` -`Seq` | `prepended`, `appended`, `prependedAll`, `appendedAll`, `padTo`, `patch` -`immutable.Seq`| `updated` -`SortedSet` | `map`, `flatMap`, `collect`, `zip` -`Map` | `map`, `flatMap`, `collect`, `concat` -`immutable.Map`| `updated`, `transform` -`SortedMap` | `map`, `flatMap`, `collect`, `concat` -`immutable.SortedMap` | `updated` +To learn about differences when implementing custom collection types or operations, see the following documents: + - [The architecture of Scala collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html) + - [Implementing custom collections]({{ site.baseurl }}/overviews/core/custom-collections.html) + - [Adding custom collection operations]({{ site.baseurl }}/overviews/core/custom-collection-operations.html) \ No newline at end of file From a0fd98a7a236e213261d411daf010ed0cbdb43a3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 29 Apr 2019 12:02:37 +0200 Subject: [PATCH 0558/3174] review feedback --- _overviews/core/collections-migration-213.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 10bcb21dbf..10f9d75e52 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -165,10 +165,11 @@ def filterInPlace(p: A => Boolean): this.type def patchInPlace(from: Int, patch: scala.collection.Seq[A], replaced: Int): this.type ~~~ -Another new operation is `distinctBy`: +Other new operations are `distinctBy` and `partitionMap` ~~~ scala -def distinctBy[B](f: A => B): C // (Where `C` can be `List[Int]`, for instance) +def distinctBy[B](f: A => B): C // `C` can be `List[Int]`, for instance +def partitionMap[A1, A2](f: A => Either[A1, A2]): (CC[A1], CC[A2]) // `CC` can be `List`, for instance ~~~ Last, additional operations are provided by the `scala-collection-contrib` module. You can From ba9ba4ad39cf0ebe08a8ab3e6e472ce93a6b488b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 29 Apr 2019 14:11:19 +0200 Subject: [PATCH 0559/3174] allow scrolling tables --- _overviews/core/collections-migration-213.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 10f9d75e52..f58bad8e9f 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -34,6 +34,8 @@ The module also provides [migratrion rules](https://github.com/scala/scala-colle The following table summarizes the breaking changes. The "Automatic Migration Rule" column gives the name of the migration rule that can be used to automatically update old code to the new expected form. +
    + | Description | Old Code | New Code | Automatic Migration Rule | | ----------- | -------- | -------- | ------------------------ | | Method `to[C[_]]` has been removed (it might be reintroduced but deprecated, though) | `xs.to[List]` | `xs.to(List)` | `Collection213Upgrade`, `Collections213CrossCompat` | @@ -43,6 +45,8 @@ The following table summarizes the breaking changes. The "Automatic Migration Ru | `zip` on `Map[K, V]` now returns an `Iterable` | `map.zip(iterable)` | `map.zip(iterable).toMap` | `Collection213Experimental` | | `ArrayBuilder.make` does not accept parens anymore | `ArrayBuilder.make[Int]()` | `ArrayBuilder.make[Int]` | `Collection213Upgrade`, `Collections213CrossCompat` | +
    + Some classes have been removed, made private or have no equivalent in the new design: - `ArrayStack` @@ -101,6 +105,8 @@ Other notable changes are: The following table lists the changes that continue to work with a deprecation warning. +
    + | Description | Old Code | New Code | Automatic Migration Rule | | ----------- | -------- | -------- | ------------------------ | | `collection.Set/Map` no longer have `+` and `-` operations | `xs + 1 - 2` | `xs ++ Set(1) -- Set(2)` | `Collection213Experimental` | @@ -119,7 +125,9 @@ The following table lists the changes that continue to work with a deprecation w | `retain` has been renamed to `filterInPlace` | `xs.retain(f)` | `xs.filterInPlace(f.tupled)` | `Collection213Upgrade` | | `:/` and `/:` operators have been deprecated | `(xs :\ y)(f)` | `xs.foldRight(y)(f)` | `Collection213Upgrade`, `Collections213CrossCompat` | | `companion` operation has been renamed to `iterableFactory` | `xs.companion` | `xs.iterableFactory` | | - + +
    + ## Deprecated things in 2.12 that have been removed in 2.13 - `collection.convert.JavaConversions`. Use `collection.convert.JavaConverters` instead ; From db7c58b57daf28e874b4fe01c0b2df3168aa875c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 30 Apr 2019 18:09:44 +0200 Subject: [PATCH 0560/3174] Fix the sentence that says how SIP committee members are elected. This is not a change of the actual process. We've always done it that way (or least as far as I've been in the committee). --- _sips/sip-submission.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_sips/sip-submission.md b/_sips/sip-submission.md index b40800b5d0..c30a4ae96c 100644 --- a/_sips/sip-submission.md +++ b/_sips/sip-submission.md @@ -190,8 +190,9 @@ Committee members should be either individuals responsible for a specific part of the Scala codebase, committers or contributors of the Scala compiler. Exceptionally, members may also be important representatives of the community with a high technical knowledge to understand the implications of every proposal -and participate into the discussions. The members are elected by the Process -Lead based on their expertise and implication in the community. +and participate into the discussions. New members are elected by existing +members of the SIP Committee, based on their expertise and involvement in the +community. The current committee members are: From ff6a56bab84958abc40fc5fb6cd86efb57e2f147 Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Wed, 1 May 2019 12:57:26 -0300 Subject: [PATCH 0561/3174] Update basics.md --- _es/tour/basics.md | 288 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index bd86428a9b..78464b51d1 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -7,3 +7,291 @@ discourse: false partof: scala-tour language: es --- + +# Scala básico + + +## Expresiones + +En Scala todo es una expresión (cada sentencia "devuelve" un valor). + +```scala +1 + 1 +``` + +Se puede ver el resultado de evaluar expresiones usando println. + +```scala +println(1) // 1 +println(1 + 1) // 2 +println("Hello!") // Hello! +println("Hello," + " world!") // Hello, world! +``` + +## Valores + +Se puede nombrar el resultado de expresiones con la palabra clave *val*. + +```scala +val x = 1 + 1 +println(x) // 2 +``` + +Los resultados con nombre, como x en el ejemplo, son llamados *valores*. Referenciar un valor no lo vuelve a computar. + +Los valores no pueden ser reasignados. + +```scala +x = 3 // This does not compile. +``` + +Los tipos de los valores pueden ser inferidos, pero tambien se pueden anotar explicitamente de la siguiente forma: + +```scala +val x: Int = 1 + 1 +``` + +Noten como la declaración de tipo Int va después del identificador. + +## Variables + +Las variables son como los valores, excepto que no es posible re-asignarlos. Las variables se definen con la palabra clave *var*. + +```scala +var x = 1 + 1 +x = 3 // This compiles because "x" is declared with the "var" keyword. +println(x * x) // 9 +``` + +Igual que con los valores, si queremos se puede especificar el tipo: + +```scala +var x: Int = 1 + 1 +``` + +## Bloques + +Se pueden combinar expresiones rodeándolas con { y } . A esto le llamamos un *bloque*. + +El resultado de la ultima expresión del bloque es también el resultado total del bloque. + +```scala +println({ + val x = 1 + 1 + x + 1 +}) // 3 +``` + +## Funciones + +Las funciones son expresiones que reciben parámetros. + +Se pueden definir funciones anónimas, por ejemplo, una que retorne x + 1 para x entero: + +```scala +(x: Int) => x + 1 +``` + +A la izquierda de => esta la lista de parámetros. A la derecha esta el cuerpo de la función + +También podemos asignarle un nombre a la función. + +```scala +val addOne = (x: Int) => x + 1 +println(addOne(1)) // 2 +``` + +Las funciones pueden tomar muchos parámetros. + +```scala +val add = (x: Int, y: Int) => x + y +println(add(1, 2)) // 3 +``` + +O ninguno. + +```scala +val getTheAnswer = () => 42 +println(getTheAnswer()) // 42 +``` + + +## Métodos + +Los métodos se parecen y se comportan de forma muy similar a las funciones, pero hay un par de diferencias clave entre ellos. +Los métodos se definen con la palabra clave *def*, seguida por un nombre, una lista de parámetros, un tipo de retorno (opcional pero recomendado), y el cuerpo del método. + +```scala +def add(x: Int, y: Int): Int = x + y +println(add(1, 2)) // 3 +``` + +Notar como el tipo de retorno es declarado después de la lista de parámetros y con dos puntos. + +Los métodos pueden tener mutiles listas de parámetros. + +```scala +def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier +println(addThenMultiply(1, 2)(3)) // 9 +``` + +O ninguna. + +```scala +def name: String = System.getProperty("user.name") +println("Hello, " + name + "!") +``` + +Hay otras diferencias, pero para simplificar, podemos pensar que son similares a las funciones. + +Los métodos también pueden tener expresiones de varias lineas. + +```scala +def getSquareString(input: Double): String = { + val square = input * input + square.toString +} +``` + +La ultima expresión en el cuerpo del método es el valor de retorno del mismo. +(Scala tiene la palabra clave *return* pero no se usa y no hace lo que uds. piensan que hace) + +## Clases + +Se puede definir clases con la palabra clave *class* seguida del nombre y los parámetros del constructor. + +```scala +class Greeter(prefix: String, suffix: String) { + def greet(name: String): Unit = + println(prefix + name + suffix) +} +``` + +El tipo de retorno del método greet es Unit, que dice que no hay nada significativo que retornar. Se usa de forma similar al void de Java y C (con la diferencia de que como toda expresión en Scala debe retornar un valor, existe un valor singleton para el tipo Unit que se escribe `()` y no lleva información ) + +Puedes crear una instancia de una clase con la palabra clave *new*. + +```scala +val greeter = new Greeter("Hello, ", "!") +greeter.greet("Scala developer") // Hello, Scala developer! +``` + +Mas adelante, cubriremos las clases en profundidad. + +## Case Classes + +Scala tiene un tipo especial de clases llamadas "case" classes. Por defecto, las case classes son inmutables y son comparadas por valor. +Las case classes se definen usando las palabras clave *case class*. + +```scala +case class Point(x: Int, y: Int) +``` + +Se pueden instanciar sin necesidad de usar la palabra clave new. + +```scala +val point = Point(1, 2) +val anotherPoint = Point(1, 2) +val yetAnotherPoint = Point(2, 2) +``` + +Y son comparadas por valor. + +```scala +if (point == anotherPoint) { + println(point + " and " + anotherPoint + " are the same.") +} else { + println(point + " and " + anotherPoint + " are different.") +} // Point(1,2) and Point(1,2) are the same. + +if (point == yetAnotherPoint) { + println(point + " and " + yetAnotherPoint + " are the same.") +} else { + println(point + " and " + yetAnotherPoint + " are different.") +} // Point(1,2) and Point(2,2) are different. +``` + +Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Las cubriremos en profundidad mas adelante. + +## Objetos + +Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como singleton de sus propias clases + +Puedes definir objectos con la palabra clave *object*. + +```scala +object IdFactory { + private var counter = 0 + def create(): Int = { + counter += 1 + counter + } +} +``` + +Para acceder al objeto, lo referencias por su nombre. + +```scala +val newId: Int = IdFactory.create() +println(newId) // 1 +val newerId: Int = IdFactory.create() +println(newerId) // 2 +``` + +Mas adelante, cubriremos los objetos en profundidad. + +## Traits + +Los traits son tipos que contienen campos y métodos. Se pueden combinar múltiples traits. + +Los traits se definen con la palabra clave *trait*. + +```scala +trait Greeter { + def greet(name: String): Unit +} +``` + +Los traits pueden también tener implementación por defecto. + +```scala +trait Greeter { + def greet(name: String): Unit = + println("Hello, " + name + "!") +} +``` + +También puedes extender traits con la palabra clave *extends* y sobrescribir una implementación con la palabra clave *override* . + +```scala +class DefaultGreeter extends Greeter + +class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { + override def greet(name: String): Unit = { + println(prefix + name + postfix) + } +} + +val greeter = new DefaultGreeter() +greeter.greet("Scala developer") // Hello, Scala developer! + +val customGreeter = new CustomizableGreeter("How are you, ", "?") +customGreeter.greet("Scala developer") // How are you, Scala developer? +``` + +Aquí, DefaultGreeter extiende un solo trait, pero puede extender múltiples traits. + +Mas adelante, cubriremos los traits en profundidad. + +## Metodo principal (Main Method) + +El metodo principal (main) es el punto de entrada de un programa. La maquina virtual de java (JVM) requiere que el método principal sea llamado `main` y que tome un solo argumento: un arrray de Strings. + +Usando un objeto, puedes definir el método principal de la siguiente forma: + +```scala +object Main { + def main(args: Array[String]): Unit = + println("Hello, Scala developer!") +} +``` From bf99da257277f91cd6ba36954558c359d16594a4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Thu, 2 May 2019 07:53:05 +0100 Subject: [PATCH 0562/3174] Linkify the Oracle LTS support URL --- _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 b776a87a6b..117e52b90b 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -27,7 +27,7 @@ This table shows the first Scala release in each series that works with each JVM We recommend using Java 8 for *compiling* Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to *run* your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9. The Scala compiler does usually need updates to run properly on newer versions of the JVM, so make sure to use the appropriate JVM when compiling your code. -We try to provide experimental support for running the Scala compiler on LTS versions of Java ("Long Term Support"; see http://www.oracle.com/technetwork/java/eol-135779.html), and to the extent possible will include the current LTS Java version in our CI matrix and the community build. We will not, a priori, consider non-LTS Java versions. Compiler bugs related to Java versions other than the supported one (Java 8), will be scheduled with lower priority, and will not be considered release blockers. Lightbend does offer commercial support for faster resolution of issues like this. +We try to provide experimental support for running the Scala compiler on LTS versions of Java ("Long Term Support"; see ), and to the extent possible will include the current LTS Java version in our CI matrix and the community build. We will not, a priori, consider non-LTS Java versions. Compiler bugs related to Java versions other than the supported one (Java 8), will be scheduled with lower priority, and will not be considered release blockers. Lightbend does offer commercial support for faster resolution of issues like this. Scala code compiled on Java 8 should run without problems in later JVMs, and we will give higher priority to bugs that break this property. For example, in the 2.13.x series we intend to provide support for JPMS module access checks, to allow ensuring your code won't incur `LinkageErrors` due to module access violations. From 9263c69c11ed51379e47b277db50901a8bdca563 Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Sat, 4 May 2019 14:36:31 -0300 Subject: [PATCH 0563/3174] fix formatting and scalafiddle --- _es/tour/basics.md | 138 +++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 55 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index 78464b51d1..24819b1d86 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -6,58 +6,77 @@ discourse: false partof: scala-tour language: es + +num: 2 +next-page: unified-types +previous-page: tour-of-scala --- -# Scala básico +En esta página, cubriremos lo básico de Scala. + +## Probando Scala en el navegador + +Puedes ejecutar Scala en tu navegador con ScalaFiddle. + +1. Ve a [https://scalafiddle.io](https://scalafiddle.io). +2. Pega `println("Hello, world!")` en el panel izquierdo. +3. Presiona el botón de "Run". El resultado aparece en el panel de la derecha. +Esta es una forma simple y con cero configuración de experimentar con piezas de código en Scala. + +Many of the code examples in this documentation are also integrated with ScalaFiddle, so you +can directly experiment with them simply by clicking the Run-button. +Muchos de los ejemplos de código en esta documentación están integrados también con ScalaFiddle, para que puedas experimentar directamente con ellos simplemente presionando el botón de "Run". ## Expresiones En Scala todo es una expresión (cada sentencia "devuelve" un valor). -```scala +```tut 1 + 1 ``` -Se puede ver el resultado de evaluar expresiones usando println. +Se puede ver el resultado de evaluar expresiones usando `println`. -```scala +{% scalafiddle %} +```tut println(1) // 1 println(1 + 1) // 2 println("Hello!") // Hello! println("Hello," + " world!") // Hello, world! ``` +{% endscalafiddle %} ## Valores -Se puede nombrar el resultado de expresiones con la palabra clave *val*. +Se puede nombrar el resultado de expresiones con la palabra clave `val`. -```scala +```tut val x = 1 + 1 println(x) // 2 ``` -Los resultados con nombre, como x en el ejemplo, son llamados *valores*. Referenciar un valor no lo vuelve a computar. +Los resultados con nombre, como `x` en el ejemplo, son llamados valores. Referenciar un valor no lo vuelve a computar. Los valores no pueden ser reasignados. -```scala +```tut:fail x = 3 // This does not compile. ``` -Los tipos de los valores pueden ser inferidos, pero tambien se pueden anotar explicitamente de la siguiente forma: +Los tipos de los valores pueden ser inferidos, pero también se pueden anotar explicitamente de la siguiente forma: -```scala +```tut val x: Int = 1 + 1 ``` -Noten como la declaración de tipo Int va después del identificador. +Noten como la declaración de tipo `Int` va después del identificador `x`. También necesitas un `:`. ## Variables -Las variables son como los valores, excepto que no es posible re-asignarlos. Las variables se definen con la palabra clave *var*. +Las variables son como los valores, excepto que no es posible re-asignarlos. Las variables se definen con la palabra clave `var`. -```scala +```tut var x = 1 + 1 x = 3 // This compiles because "x" is declared with the "var" keyword. println(x * x) // 9 @@ -65,17 +84,17 @@ println(x * x) // 9 Igual que con los valores, si queremos se puede especificar el tipo: -```scala +```tut var x: Int = 1 + 1 ``` ## Bloques -Se pueden combinar expresiones rodeándolas con { y } . A esto le llamamos un *bloque*. +Se pueden combinar expresiones rodeándolas con `{}` . A esto le llamamos un bloque. El resultado de la ultima expresión del bloque es también el resultado total del bloque. -```scala +```tut println({ val x = 1 + 1 x + 1 @@ -88,7 +107,7 @@ Las funciones son expresiones que reciben parámetros. Se pueden definir funciones anónimas, por ejemplo, una que retorne x + 1 para x entero: -```scala +```tut (x: Int) => x + 1 ``` @@ -96,48 +115,56 @@ A la izquierda de => esta la lista de parámetros. A la derecha esta el cuerpo d También podemos asignarle un nombre a la función. -```scala +{% scalafiddle %} +```tut val addOne = (x: Int) => x + 1 println(addOne(1)) // 2 ``` +{% endscalafiddle %} Las funciones pueden tomar muchos parámetros. -```scala +{% scalafiddle %} +```tut val add = (x: Int, y: Int) => x + y println(add(1, 2)) // 3 ``` +{% endscalafiddle %} O ninguno. -```scala +```tut val getTheAnswer = () => 42 println(getTheAnswer()) // 42 ``` - ## Métodos Los métodos se parecen y se comportan de forma muy similar a las funciones, pero hay un par de diferencias clave entre ellos. -Los métodos se definen con la palabra clave *def*, seguida por un nombre, una lista de parámetros, un tipo de retorno (opcional pero recomendado), y el cuerpo del método. -```scala +Los métodos se definen con la palabra clave `def`, seguida por un nombre, una lista de parámetros, un tipo de retorno, y el cuerpo del método. + +{% scalafiddle %} +```tut def add(x: Int, y: Int): Int = x + y println(add(1, 2)) // 3 ``` +{% endscalafiddle %} -Notar como el tipo de retorno es declarado después de la lista de parámetros y con dos puntos. +Notar como el tipo de retorno es declarado _después_ de la lista de parámetros y con dos puntos `: Int`. Los métodos pueden tener mutiles listas de parámetros. -```scala +{% scalafiddle %} +```tut def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier println(addThenMultiply(1, 2)(3)) // 9 ``` +{% endscalafiddle %} -O ninguna. +O ninguna lista de parametros. -```scala +```tut def name: String = System.getProperty("user.name") println("Hello, " + name + "!") ``` @@ -146,7 +173,7 @@ Hay otras diferencias, pero para simplificar, podemos pensar que son similares a Los métodos también pueden tener expresiones de varias lineas. -```scala +```tut def getSquareString(input: Double): String = { val square = input * input square.toString @@ -154,42 +181,42 @@ def getSquareString(input: Double): String = { ``` La ultima expresión en el cuerpo del método es el valor de retorno del mismo. -(Scala tiene la palabra clave *return* pero no se usa y no hace lo que uds. piensan que hace) +(Scala tiene la palabra clave `return` pero raramente se usa) ## Clases -Se puede definir clases con la palabra clave *class* seguida del nombre y los parámetros del constructor. +Se puede definir clases con la palabra clave `class` seguida del nombre y los parámetros del constructor. -```scala +```tut class Greeter(prefix: String, suffix: String) { def greet(name: String): Unit = println(prefix + name + suffix) } ``` -El tipo de retorno del método greet es Unit, que dice que no hay nada significativo que retornar. Se usa de forma similar al void de Java y C (con la diferencia de que como toda expresión en Scala debe retornar un valor, existe un valor singleton para el tipo Unit que se escribe `()` y no lleva información ) +El tipo de retorno del método `greet` es `Unit`, que dice que no hay nada significativo que retornar. Se usa de forma similar al `void` de Java y C (Con la diferencia de que como toda expresión en Scala debe retornar un valor, existe un valor singleton para el tipo Unit que se escribe () y no lleva información ) Puedes crear una instancia de una clase con la palabra clave *new*. -```scala +```tut val greeter = new Greeter("Hello, ", "!") greeter.greet("Scala developer") // Hello, Scala developer! ``` -Mas adelante, cubriremos las clases en profundidad. +Cubriremos las clases en profundidad [mas adelante](classes.html). ## Case Classes Scala tiene un tipo especial de clases llamadas "case" classes. Por defecto, las case classes son inmutables y son comparadas por valor. -Las case classes se definen usando las palabras clave *case class*. +Las case classes se definen usando las palabras clave `case class`. -```scala +```tut case class Point(x: Int, y: Int) ``` -Se pueden instanciar sin necesidad de usar la palabra clave new. +Se pueden instanciar sin necesidad de usar la palabra clave `new`. -```scala +```tut val point = Point(1, 2) val anotherPoint = Point(1, 2) val yetAnotherPoint = Point(2, 2) @@ -197,7 +224,7 @@ val yetAnotherPoint = Point(2, 2) Y son comparadas por valor. -```scala +```tut if (point == anotherPoint) { println(point + " and " + anotherPoint + " are the same.") } else { @@ -211,15 +238,15 @@ if (point == yetAnotherPoint) { } // Point(1,2) and Point(2,2) are different. ``` -Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Las cubriremos en profundidad mas adelante. +Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Las cubriremos en profundidad [mas adelante](case-classes.html). ## Objetos Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como singleton de sus propias clases -Puedes definir objectos con la palabra clave *object*. +Puedes definir objectos con la palabra clave `object`. -```scala +```tut object IdFactory { private var counter = 0 def create(): Int = { @@ -231,22 +258,22 @@ object IdFactory { Para acceder al objeto, lo referencias por su nombre. -```scala +```tut val newId: Int = IdFactory.create() println(newId) // 1 val newerId: Int = IdFactory.create() println(newerId) // 2 ``` -Mas adelante, cubriremos los objetos en profundidad. +Cubriremos los objetos en profundidad [mas adelante](singleton-objects.html). ## Traits Los traits son tipos que contienen campos y métodos. Se pueden combinar múltiples traits. -Los traits se definen con la palabra clave *trait*. +Los traits se definen con la palabra clave `trait`. -```scala +```tut trait Greeter { def greet(name: String): Unit } @@ -254,16 +281,16 @@ trait Greeter { Los traits pueden también tener implementación por defecto. -```scala +{% scalafiddle %} +```tut trait Greeter { def greet(name: String): Unit = println("Hello, " + name + "!") } -``` -También puedes extender traits con la palabra clave *extends* y sobrescribir una implementación con la palabra clave *override* . +También puedes extender traits con la palabra clave `extends` y sobrescribir una implementación con la palabra clave `override` . -```scala +```tut class DefaultGreeter extends Greeter class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { @@ -278,18 +305,19 @@ greeter.greet("Scala developer") // Hello, Scala developer! val customGreeter = new CustomizableGreeter("How are you, ", "?") customGreeter.greet("Scala developer") // How are you, Scala developer? ``` +{% endscalafiddle %} -Aquí, DefaultGreeter extiende un solo trait, pero puede extender múltiples traits. +Aquí, `DefaultGreeter` extiende un solo trait, pero puede extender múltiples traits. -Mas adelante, cubriremos los traits en profundidad. +Cubriremos los traits en profundidad [mas adelante](traits.html). -## Metodo principal (Main Method) +## Método principal (Main Method) -El metodo principal (main) es el punto de entrada de un programa. La maquina virtual de java (JVM) requiere que el método principal sea llamado `main` y que tome un solo argumento: un arrray de Strings. +El método principal (main) es el punto de entrada de un programa. La maquina virtual de java (JVM) requiere que el método principal sea llamado `main` y que tome un solo argumento: un arrray de Strings. Usando un objeto, puedes definir el método principal de la siguiente forma: -```scala +```tut object Main { def main(args: Array[String]): Unit = println("Hello, Scala developer!") From 0ff8f50cacaf22ceaca3102251d035689f5e54ac Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Sat, 4 May 2019 23:14:13 -0300 Subject: [PATCH 0564/3174] add missing closing quotes --- _es/tour/basics.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index 24819b1d86..2b613c7bec 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -287,6 +287,7 @@ trait Greeter { def greet(name: String): Unit = println("Hello, " + name + "!") } +``` También puedes extender traits con la palabra clave `extends` y sobrescribir una implementación con la palabra clave `override` . From 16c153cc515aa141f37e39305c01aefd961e6089 Mon Sep 17 00:00:00 2001 From: "Diego E. Alonso Blas" Date: Sun, 5 May 2019 23:59:11 -0300 Subject: [PATCH 0565/3174] Apply suggestions from code review Co-Authored-By: gclaramunt --- _es/tour/basics.md | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index 2b613c7bec..c8f45e7c5a 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -19,14 +19,14 @@ En esta página, cubriremos lo básico de Scala. Puedes ejecutar Scala en tu navegador con ScalaFiddle. 1. Ve a [https://scalafiddle.io](https://scalafiddle.io). -2. Pega `println("Hello, world!")` en el panel izquierdo. -3. Presiona el botón de "Run". El resultado aparece en el panel de la derecha. +2. Escribe `println("Hello, world!")` en el panel a la izquierda. +3. Presiona el botón "Run". En el panel de la derecha aparecerá el resultado. -Esta es una forma simple y con cero configuración de experimentar con piezas de código en Scala. +Así, de manera fácil y sin preparación, puedes probar fragmentos de código Scala. Many of the code examples in this documentation are also integrated with ScalaFiddle, so you can directly experiment with them simply by clicking the Run-button. -Muchos de los ejemplos de código en esta documentación están integrados también con ScalaFiddle, para que puedas experimentar directamente con ellos simplemente presionando el botón de "Run". +Muchos ejemplos de código en esta documentación están integrados con ScalaFiddle, y así puedes probarlos directamente solo con pulsar el botón "Run". ## Expresiones @@ -49,7 +49,7 @@ println("Hello," + " world!") // Hello, world! ## Valores -Se puede nombrar el resultado de expresiones con la palabra clave `val`. +Se puede dar un nombre al resultado de una expresión usando la palabra reservada `val`. ```tut val x = 1 + 1 @@ -74,7 +74,7 @@ Noten como la declaración de tipo `Int` va después del identificador `x`. Tamb ## Variables -Las variables son como los valores, excepto que no es posible re-asignarlos. Las variables se definen con la palabra clave `var`. +Una variable es como un valor, excepto que a una variable se le puede re-asignar un valor después de declararla. Una variable se declara con la palabra reservada `var`. ```tut var x = 1 + 1 @@ -82,7 +82,7 @@ x = 3 // This compiles because "x" is declared with the "var" keyword. println(x * x) // 9 ``` -Igual que con los valores, si queremos se puede especificar el tipo: +Como con los valores, si se quiere se puede especificar el tipo de una variable mutable: ```tut var x: Int = 1 + 1 @@ -103,7 +103,7 @@ println({ ## Funciones -Las funciones son expresiones que reciben parámetros. +Una función es una expresión que acepta parámetros. Se pueden definir funciones anónimas, por ejemplo, una que retorne x + 1 para x entero: @@ -111,7 +111,7 @@ Se pueden definir funciones anónimas, por ejemplo, una que retorne x + 1 para x (x: Int) => x + 1 ``` -A la izquierda de => esta la lista de parámetros. A la derecha esta el cuerpo de la función +La lista de parámetros de la función está a la izquierda de la flecha `=>`, y a su derecha está el cuerpo de la función. También podemos asignarle un nombre a la función. @@ -140,9 +140,9 @@ println(getTheAnswer()) // 42 ## Métodos -Los métodos se parecen y se comportan de forma muy similar a las funciones, pero hay un par de diferencias clave entre ellos. +Los métodos se parecen y comportan casi como a las funciones, pero se diferencian en dos aspectos clave: -Los métodos se definen con la palabra clave `def`, seguida por un nombre, una lista de parámetros, un tipo de retorno, y el cuerpo del método. +Un método se define con la palabra reservada `def`, seguida por el nombre del método, la lista de parámetros, el tipo de valores que el método devuelve, y el cuerpo del método. {% scalafiddle %} ```tut @@ -151,9 +151,9 @@ println(add(1, 2)) // 3 ``` {% endscalafiddle %} -Notar como el tipo de retorno es declarado _después_ de la lista de parámetros y con dos puntos `: Int`. +Observe que el tipo de retorno se declara _después_ de la lista de parámetros, y separado con dos puntos, e.g. `: Int`. -Los métodos pueden tener mutiles listas de parámetros. +Un método puede tener varias listas de parámetros {% scalafiddle %} ```tut @@ -181,11 +181,11 @@ def getSquareString(input: Double): String = { ``` La ultima expresión en el cuerpo del método es el valor de retorno del mismo. -(Scala tiene la palabra clave `return` pero raramente se usa) +(Scala tiene una palabra reservada `return`, pero se usa raramente, y no se aconseja usarla) ## Clases -Se puede definir clases con la palabra clave `class` seguida del nombre y los parámetros del constructor. +Una clase se define con la palabra reservada `class`, seguida del nombre, y la lista de parámetros del constructor. ```tut class Greeter(prefix: String, suffix: String) { @@ -194,27 +194,27 @@ class Greeter(prefix: String, suffix: String) { } ``` -El tipo de retorno del método `greet` es `Unit`, que dice que no hay nada significativo que retornar. Se usa de forma similar al `void` de Java y C (Con la diferencia de que como toda expresión en Scala debe retornar un valor, existe un valor singleton para el tipo Unit que se escribe () y no lleva información ) +El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que, dado que en Scala toda expresión debe devuelvor un valor, se usa un tipo `Unit`, con un solo valor, que se escribe `()` y no lleva información. -Puedes crear una instancia de una clase con la palabra clave *new*. +Se puede crear una instancia de una clase con la palabra reservada *new*. ```tut val greeter = new Greeter("Hello, ", "!") greeter.greet("Scala developer") // Hello, Scala developer! ``` -Cubriremos las clases en profundidad [mas adelante](classes.html). +Las clases se tratan en profundidad [mas adelante](classes.html). ## Case Classes -Scala tiene un tipo especial de clases llamadas "case" classes. Por defecto, las case classes son inmutables y son comparadas por valor. -Las case classes se definen usando las palabras clave `case class`. +Hay un tipo especial de clases en Scala, las llamadas "case" classes. Por defecto, las instancias de una case class son inmutables, y se comparan con otras solo por los valores que contienen en cada campo. +Una case class se define con las palabras reservadas `case class`: ```tut case class Point(x: Int, y: Int) ``` -Se pueden instanciar sin necesidad de usar la palabra clave `new`. +Se puede crear una instancia de una `case class`, sin usar la palabra reservada `new`. ```tut val point = Point(1, 2) @@ -238,7 +238,7 @@ if (point == yetAnotherPoint) { } // Point(1,2) and Point(2,2) are different. ``` -Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Las cubriremos en profundidad [mas adelante](case-classes.html). +Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Se tratan con más detalle [mas adelante](case-classes.html). ## Objetos @@ -271,7 +271,7 @@ Cubriremos los objetos en profundidad [mas adelante](singleton-objects.html). Los traits son tipos que contienen campos y métodos. Se pueden combinar múltiples traits. -Los traits se definen con la palabra clave `trait`. +Un trait se define usando la palabra reservada `trait`. ```tut trait Greeter { @@ -310,11 +310,11 @@ customGreeter.greet("Scala developer") // How are you, Scala developer? Aquí, `DefaultGreeter` extiende un solo trait, pero puede extender múltiples traits. -Cubriremos los traits en profundidad [mas adelante](traits.html). +Los `traits` se tratan con detalle [en otra página](traits.html). ## Método principal (Main Method) -El método principal (main) es el punto de entrada de un programa. La maquina virtual de java (JVM) requiere que el método principal sea llamado `main` y que tome un solo argumento: un arrray de Strings. +El método principal (main) es el punto donde comienza la ejecución de un programa en Scala. La máquina virtual de java (_Java Virtual Machine_ or JVM) requiere, para ejecutar un código Scala, que éste tenga un método principal llamado `main` cuyo único parámetro sea un arrray de Strings. Usando un objeto, puedes definir el método principal de la siguiente forma: From 6de4ca5c19c03f0d597798b58a6efe86fdb5c376 Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Mon, 6 May 2019 00:07:54 -0300 Subject: [PATCH 0566/3174] review comments --- _es/tour/basics.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index c8f45e7c5a..4147f63df1 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -24,13 +24,11 @@ Puedes ejecutar Scala en tu navegador con ScalaFiddle. Así, de manera fácil y sin preparación, puedes probar fragmentos de código Scala. -Many of the code examples in this documentation are also integrated with ScalaFiddle, so you -can directly experiment with them simply by clicking the Run-button. Muchos ejemplos de código en esta documentación están integrados con ScalaFiddle, y así puedes probarlos directamente solo con pulsar el botón "Run". ## Expresiones -En Scala todo es una expresión (cada sentencia "devuelve" un valor). +Las expresiones son sentencias computables. ```tut 1 + 1 @@ -105,7 +103,7 @@ println({ Una función es una expresión que acepta parámetros. -Se pueden definir funciones anónimas, por ejemplo, una que retorne x + 1 para x entero: +Una función se puede declarar anónima, sin nombre. Por ejemplo, ésta es una función que acepta un número entero `x`, y devuelve el resultado de incrementarlo `x+1`: ```tut (x: Int) => x + 1 @@ -244,7 +242,7 @@ Hay mucho mas sobre las case classes que queremos presentar, y estamos convencid Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como singleton de sus propias clases -Puedes definir objectos con la palabra clave `object`. +Un objeto se define usando la palabra reservada `object`. ```tut object IdFactory { From 0e2289195e42a1fbaa136d6bcf010510e360a485 Mon Sep 17 00:00:00 2001 From: Ignasi Marimon-Clos Date: Mon, 6 May 2019 11:08:38 -0300 Subject: [PATCH 0567/3174] Apply suggestions from code review Co-Authored-By: gclaramunt --- _es/tour/basics.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index 4147f63df1..c8155a77f8 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -12,7 +12,7 @@ next-page: unified-types previous-page: tour-of-scala --- -En esta página, cubriremos lo básico de Scala. +En esta página, practicaremos conceptos básicos de Scala. ## Probando Scala en el navegador @@ -59,10 +59,10 @@ Los resultados con nombre, como `x` en el ejemplo, son llamados valores. Referen Los valores no pueden ser reasignados. ```tut:fail -x = 3 // This does not compile. +x = 3 // Producirá un error de compilación. ``` -Los tipos de los valores pueden ser inferidos, pero también se pueden anotar explicitamente de la siguiente forma: +Los tipos de los valores pueden ser inferidos, pero también se pueden anotar explícitamente de la siguiente forma: ```tut val x: Int = 1 + 1 @@ -90,7 +90,7 @@ var x: Int = 1 + 1 Se pueden combinar expresiones rodeándolas con `{}` . A esto le llamamos un bloque. -El resultado de la ultima expresión del bloque es también el resultado total del bloque. +El resultado de la última expresión del bloque es también el resultado total del bloque. ```tut println({ @@ -120,7 +120,7 @@ println(addOne(1)) // 2 ``` {% endscalafiddle %} -Las funciones pueden tomar muchos parámetros. +Las funciones pueden tomar varios parámetros. {% scalafiddle %} ```tut @@ -149,9 +149,9 @@ println(add(1, 2)) // 3 ``` {% endscalafiddle %} -Observe que el tipo de retorno se declara _después_ de la lista de parámetros, y separado con dos puntos, e.g. `: Int`. +Observe que el tipo de retorno se declara _después_ de la lista de parámetros, y separado con dos puntos, p.ej. `: Int`. -Un método puede tener varias listas de parámetros +Un método puede tener varias listas de parámetros. {% scalafiddle %} ```tut @@ -179,7 +179,7 @@ def getSquareString(input: Double): String = { ``` La ultima expresión en el cuerpo del método es el valor de retorno del mismo. -(Scala tiene una palabra reservada `return`, pero se usa raramente, y no se aconseja usarla) +(Scala tiene una palabra reservada `return`, pero se usa raramente y no se aconseja usarla) ## Clases @@ -192,7 +192,7 @@ class Greeter(prefix: String, suffix: String) { } ``` -El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que, dado que en Scala toda expresión debe devuelvor un valor, se usa un tipo `Unit`, con un solo valor, que se escribe `()` y no lleva información. +El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que en Scala toda expresión debe devolver un valor. Se usa un tipo `Unit` que tiene con un solo valor que se escribe `()` y no lleva información. Se puede crear una instancia de una clase con la palabra reservada *new*. @@ -201,7 +201,7 @@ val greeter = new Greeter("Hello, ", "!") greeter.greet("Scala developer") // Hello, Scala developer! ``` -Las clases se tratan en profundidad [mas adelante](classes.html). +Las clases se tratan en profundidad [más adelante](classes.html). ## Case Classes @@ -236,11 +236,11 @@ if (point == yetAnotherPoint) { } // Point(1,2) and Point(2,2) are different. ``` -Hay mucho mas sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Se tratan con más detalle [mas adelante](case-classes.html). +Hay mucho más sobre las case classes que queremos presentar, y estamos convencidos de que te vas a enamorar de ellas. Se tratan con más detalle [mas adelante](case-classes.html). ## Objetos -Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como singleton de sus propias clases +Los objetos son instancias de una sola clase de su propia definición. Puedes pensar en ellos como _singleton_ de sus propias clases. Un objeto se define usando la palabra reservada `object`. @@ -263,7 +263,7 @@ val newerId: Int = IdFactory.create() println(newerId) // 2 ``` -Cubriremos los objetos en profundidad [mas adelante](singleton-objects.html). +Cubriremos los objetos en profundidad [más adelante](singleton-objects.html). ## Traits @@ -287,7 +287,7 @@ trait Greeter { } ``` -También puedes extender traits con la palabra clave `extends` y sobrescribir una implementación con la palabra clave `override` . +También puedes extender traits con la palabra clave `extends` y sobrescribir una implementación con la palabra clave `override`. ```tut class DefaultGreeter extends Greeter From d17ca9078857b64ecb9f0e7479ddc9389bb8f1bc Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Mon, 6 May 2019 13:46:57 -0300 Subject: [PATCH 0568/3174] Apply suggestions from code review Co-Authored-By: gclaramunt --- _es/tour/basics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index c8155a77f8..d472a60ddf 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -62,7 +62,7 @@ Los valores no pueden ser reasignados. x = 3 // Producirá un error de compilación. ``` -Los tipos de los valores pueden ser inferidos, pero también se pueden anotar explícitamente de la siguiente forma: +Scala es capaz de inferir el tipo de un valor. Aun asi, también se puede indicar el tipo usando una anotación: ```tut val x: Int = 1 + 1 @@ -103,7 +103,7 @@ println({ Una función es una expresión que acepta parámetros. -Una función se puede declarar anónima, sin nombre. Por ejemplo, ésta es una función que acepta un número entero `x`, y devuelve el resultado de incrementarlo `x+1`: +Una función se puede declarar anónima, sin nombre. Por ejemplo, ésta es una función que acepta un número entero `x`, y devuelve el resultado de incrementarlo: ```tut (x: Int) => x + 1 @@ -192,7 +192,7 @@ class Greeter(prefix: String, suffix: String) { } ``` -El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que en Scala toda expresión debe devolver un valor. Se usa un tipo `Unit` que tiene con un solo valor que se escribe `()` y no lleva información. +El método `greet` tiene un tipo de retorno `Unit`, que indica que el método no tiene nada significativo que devolver. Esto es similar al tipo `void` en C, C++, o Java. La diferencia con estos lenguajes es que en Scala toda expresión debe devolver un valor. Por ello, se usa un tipo `Unit` que tiene con un solo valor que se escribe `()` y no lleva información. Se puede crear una instancia de una clase con la palabra reservada *new*. @@ -277,7 +277,7 @@ trait Greeter { } ``` -Los traits pueden también tener implementación por defecto. +Un `trait` también puede definit un método, o un valor, con una implementación por defecto. {% scalafiddle %} ```tut @@ -287,7 +287,7 @@ trait Greeter { } ``` -También puedes extender traits con la palabra clave `extends` y sobrescribir una implementación con la palabra clave `override`. +Un `trait` también puede extender otros traits, usando la palabra clave `extends`. Asimismo, en un `trait` se puede redefinir la implementación de un método heredado, usando la palabra reservada `override`. ```tut class DefaultGreeter extends Greeter From e70979eafa06e361b5353b6f91898c3fc80e1e72 Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Mon, 6 May 2019 15:27:47 -0300 Subject: [PATCH 0569/3174] spellcheck --- _es/tour/basics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_es/tour/basics.md b/_es/tour/basics.md index d472a60ddf..80977f061b 100644 --- a/_es/tour/basics.md +++ b/_es/tour/basics.md @@ -59,16 +59,16 @@ Los resultados con nombre, como `x` en el ejemplo, son llamados valores. Referen Los valores no pueden ser reasignados. ```tut:fail -x = 3 // Producirá un error de compilación. +x = 3 // This does not compile. ``` -Scala es capaz de inferir el tipo de un valor. Aun asi, también se puede indicar el tipo usando una anotación: +Scala es capaz de inferir el tipo de un valor. Aun así, también se puede indicar el tipo usando una anotación: ```tut val x: Int = 1 + 1 ``` -Noten como la declaración de tipo `Int` va después del identificador `x`. También necesitas un `:`. +Nótese que la anotación del tipo `Int` sigue al identificador `x` de la variable, separado por dos puntos `:`. ## Variables @@ -160,7 +160,7 @@ println(addThenMultiply(1, 2)(3)) // 9 ``` {% endscalafiddle %} -O ninguna lista de parametros. +O ninguna lista de parámetros. ```tut def name: String = System.getProperty("user.name") @@ -277,7 +277,7 @@ trait Greeter { } ``` -Un `trait` también puede definit un método, o un valor, con una implementación por defecto. +Un `trait` también puede definir un método, o un valor, con una implementación por defecto. {% scalafiddle %} ```tut From 9fd83799523ca0a3e56dbb8e2fef9f6076c9f858 Mon Sep 17 00:00:00 2001 From: Gabriel Claramunt Date: Tue, 7 May 2019 19:25:08 -0300 Subject: [PATCH 0570/3174] change next page link to target basics (#1325) --- _es/tour/tour-of-scala.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_es/tour/tour-of-scala.md b/_es/tour/tour-of-scala.md index 445b894c8d..14ef79cebc 100644 --- a/_es/tour/tour-of-scala.md +++ b/_es/tour/tour-of-scala.md @@ -9,7 +9,8 @@ partof: scala-tour num: 1 language: es -next-page: abstract-type-members +next-page: basics + --- Scala es un lenguaje de programación moderno multi-paradigma diseñado para expresar patrones de programación comunes de una forma concisa, elegante, y de tipado seguro. Integra fácilmente características de lenguajes orientados a objetos y funcionales. From 2d8f8e533e48b462680cf1e398d547721ed7c80f Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 10 May 2019 16:01:10 -0400 Subject: [PATCH 0571/3174] Add guidance on how to migrate scala.Seq --- _overviews/core/collections-migration-213.md | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index f58bad8e9f..7b8aed0c6f 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -10,6 +10,7 @@ how to cross-build projects with Scala 2.11 / 2.12 and 2.13. For an in-depth overview of the Scala 2.13 collections library, see the [collections guide]({{ site.baseurl }}/overviews/collections-2.13/introduction.html). The implementation details of the 2.13 collections are explained in the document [the architecture of Scala collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html). The most important changes in the Scala 2.13 collections library are: + - `scala.Seq[+A]` is now an alias for `scala.collection.immutable.Seq[A]` (instead of `scala.collection.Seq[A]`). Note that this also changes the type of Scala varargs methods. - 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. @@ -22,7 +23,6 @@ The most important changes in the Scala 2.13 collections library are: - Deprecated collections were removed (`MutableList`, `immutable.Stack`, others) - Parallel collections are now in a separate hierarchy in a [separate module](https://github.com/scala/scala-parallel-collections). - The `scala.jdk.StreamConverters` object provides extension methods to create (sequential or parallel) Java 8 streams for Scala collections. - - `scala.Seq` is now an alias for `scala.collection.immutable.Seq` (no longer `scala.collection.Seq`). Note that this also changes the type of Scala varargs methods. ## Tools for migrating and cross-building @@ -30,6 +30,31 @@ The [scala-collection-compat](https://github.com/scala/scala-collection-compat) The module also provides [migratrion rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. +## scala.Seq migration + +In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]`, instead of `scala.collection.Seq[A]`. This change requires some planning depending on how your code is going to be used. + +If you're making an application, and simply migrating Scala 2.12 code base to 2.13, it might be ok to keep using `scala.Seq` in your code. + +If you're making a library intended to be used by other programmers, then using `scala.Seq` or vararg is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. + +- if you cross build with Scala 2.12 and want to maintain the API semantics for 2.13 version of your library, or +- if your library users frequently uses mutable collections such as `Array` + +you can import `scala.collection.Seq` ("CSeq") explicitly in your code. + +~~~ scala +import scala.collection.Seq +~~~ + +In the future when your API is able to break the source compatibility, it might also make sense to migrate towards the `scala.collection.immutable.Seq` ("ISeq") for both Scala 2.12 and Scala 2.13. + +~~~ scala +import scala.collection.immutable.Seq +~~~ + +Note that in Scala 2.13 the sequence passed into a vararg as `orderFood(xs: _*)` must also be immutable. This is because the sequence passed into a vararg must conform to`scala.Seq` acoording to [Specification](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications). Thus if your API exposes varargs, it will be an unavoidable breaking change. This might affect Java interoperability. + ## What are the breaking changes? The following table summarizes the breaking changes. The "Automatic Migration Rule" column gives the name of the migration rule that can be used to automatically update old code to the new expected form. @@ -77,7 +102,6 @@ Some classes have been removed, made private or have no equivalent in the new de Other notable changes are: - `Iterable.partition` invokes `iterator` twice on non-strict collections and assumes it gets two iterators over the same elements. Strict subclasses override `partition` do perform only a single traversal - - `scala.Seq[+A]` is now `scala.collection.immutable.Seq[A]` (this also affects varargs methods). - Equality between collections is not anymore defined at the level of `Iterable`. It is defined separately in the `Set`, `Seq` and `Map` branches. Another consequence is that `Iterable` does not anymore have a `canEqual` method. - The new collections makes more use of overloading. You can find more information about the motivation behind this choice [here](http://scala-lang.org/blog/2017/05/30/tribulations-canbuildfrom.html). For instance, `Map.map` is overloaded: From 8178166fd0c7b3e6e7b5dfb025b76c469279aba1 Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Fri, 10 May 2019 17:28:00 -0400 Subject: [PATCH 0572/3174] Update _overviews/core/collections-migration-213.md Co-Authored-By: Dale Wijnand <344610+dwijnand@users.noreply.github.com> --- _overviews/core/collections-migration-213.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 7b8aed0c6f..e04c036d61 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -53,7 +53,7 @@ In the future when your API is able to break the source compatibility, it might import scala.collection.immutable.Seq ~~~ -Note that in Scala 2.13 the sequence passed into a vararg as `orderFood(xs: _*)` must also be immutable. This is because the sequence passed into a vararg must conform to`scala.Seq` acoording to [Specification](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications). Thus if your API exposes varargs, it will be an unavoidable breaking change. This might affect Java interoperability. +Note that in Scala 2.13 the sequence passed into as a varargs as `orderFood(xs: _*)` must also be immutable. This is because the sequence passed in as a varargs must conform to `scala.Seq` according to [SLS 6.6](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications). Thus, if your API exposes varargs it will be an unavoidable breaking change. This might affect Java interoperability. ## What are the breaking changes? @@ -260,4 +260,4 @@ Examples of libraries that cross-compile with separate source directories: To learn about differences when implementing custom collection types or operations, see the following documents: - [The architecture of Scala collections]({{ site.baseurl }}/overviews/core/architecture-of-scala-213-collections.html) - [Implementing custom collections]({{ site.baseurl }}/overviews/core/custom-collections.html) - - [Adding custom collection operations]({{ site.baseurl }}/overviews/core/custom-collection-operations.html) \ No newline at end of file + - [Adding custom collection operations]({{ site.baseurl }}/overviews/core/custom-collection-operations.html) From 54b38f7ee2ac71384741e7b2318eaa0f4f09d186 Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Fri, 10 May 2019 17:32:25 -0400 Subject: [PATCH 0573/3174] Update _overviews/core/collections-migration-213.md Co-Authored-By: Dale Wijnand <344610+dwijnand@users.noreply.github.com> --- _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 e04c036d61..ac2be9d9d3 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -34,7 +34,7 @@ The module also provides [migratrion rules](https://github.com/scala/scala-colle In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]`, instead of `scala.collection.Seq[A]`. This change requires some planning depending on how your code is going to be used. -If you're making an application, and simply migrating Scala 2.12 code base to 2.13, it might be ok to keep using `scala.Seq` in your code. +If you're making an application, and simply migrating a Scala 2.12 code base to 2.13, it might be ok to keep using `scala.Seq` in your code. If you're making a library intended to be used by other programmers, then using `scala.Seq` or vararg is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. From 6c566237690ef8948d619fea97ab91e96cbc18fc Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Fri, 10 May 2019 17:32:39 -0400 Subject: [PATCH 0574/3174] Update _overviews/core/collections-migration-213.md Co-Authored-By: Dale Wijnand <344610+dwijnand@users.noreply.github.com> --- _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 ac2be9d9d3..7b4a59f124 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -36,7 +36,7 @@ In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A] If you're making an application, and simply migrating a Scala 2.12 code base to 2.13, it might be ok to keep using `scala.Seq` in your code. -If you're making a library intended to be used by other programmers, then using `scala.Seq` or vararg is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. +If you're making a library intended to be used by other programmers, then using `scala.Seq` or varargs is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. - if you cross build with Scala 2.12 and want to maintain the API semantics for 2.13 version of your library, or - if your library users frequently uses mutable collections such as `Array` From 66fb063a96e63630e709257e807219d53a6d5ef1 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Thu, 16 May 2019 22:52:32 -0400 Subject: [PATCH 0575/3174] Add redirect for partest-guide (#1329) https://github.com/scala/scala-partest --- _overviews/tutorials/partest-guide.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 _overviews/tutorials/partest-guide.md diff --git a/_overviews/tutorials/partest-guide.md b/_overviews/tutorials/partest-guide.md new file mode 100644 index 0000000000..36fa8c74c7 --- /dev/null +++ b/_overviews/tutorials/partest-guide.md @@ -0,0 +1,6 @@ +--- +layout: inner-page-no-masthead +sitemap: false +permalink: /tutorials/partest-guide.html +redirect_to: https://github.com/scala/scala-partest +--- From 017fef76e43a45fcd01d42f5a6558c0b48e23f31 Mon Sep 17 00:00:00 2001 From: Suyash Date: Sat, 18 May 2019 08:44:57 +0400 Subject: [PATCH 0576/3174] Update getting-started-with-scala-in-intellij.md updating doc for adding scala framework support addition which was missing earlier --- .../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 f6cd28b50a..b6517c06bd 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 @@ -36,7 +36,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**. +**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 donload button, or select the library path manually. 1. Name the class `Hello` and change the **Kind** to `object`. 1. Change the code in the class to the following: From 8025fe3685a7a66c8f329c4ffa746fbc880ad0f0 Mon Sep 17 00:00:00 2001 From: Suyash Date: Sun, 19 May 2019 11:56:00 +0400 Subject: [PATCH 0577/3174] Update getting-started-with-scala-in-intellij.md Fixing typo. --- .../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 b6517c06bd..730f2e7f36 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 @@ -36,7 +36,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 donload 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. 1. Name the class `Hello` and change the **Kind** to `object`. 1. Change the code in the class to the following: From 9afd159f5556ad9a772e8a264e000d30d910c168 Mon Sep 17 00:00:00 2001 From: Akhtyam Sakaev <3930435+asakaev@users.noreply.github.com> Date: Sat, 18 May 2019 01:38:15 +0300 Subject: [PATCH 0578/3174] refine pattern-matching.md --- _tour/pattern-matching.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index b5f9e37d46..20ca742c70 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -28,19 +28,19 @@ x match { case 0 => "zero" case 1 => "one" case 2 => "two" - case _ => "many" + case _ => "other" } ``` -The `val x` above is a random integer between 0 and 10. `x` becomes the left operand of the `match` operator and on the right is an expression with four cases. The last case `_` is a "catch all" case for any number greater than 2. Cases are also called _alternatives_. +The `val x` above is a random integer between 0 and 10. `x` becomes the left operand of the `match` operator and on the right is an expression with four cases. The last case `_` is a "catch all" case for any other possible `Int` values. Cases are also called _alternatives_. Match expressions have a value. ```tut def matchTest(x: Int): String = x match { case 1 => "one" case 2 => "two" - case _ => "many" + case _ => "other" } -matchTest(3) // many +matchTest(3) // other matchTest(1) // one ``` This match expression has a type String because all of the cases return String. Therefore, the function `matchTest` returns a String. From 2b4de2d746a2ffb8547298897d585c94b711f508 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 20 May 2019 18:17:11 -0400 Subject: [PATCH 0579/3174] reflect review comments --- _overviews/core/collections-migration-213.md | 66 ++++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 7b4a59f124..f877849115 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -32,29 +32,83 @@ The module also provides [migratrion rules](https://github.com/scala/scala-colle ## scala.Seq migration -In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]`, instead of `scala.collection.Seq[A]`. This change requires some planning depending on how your code is going to be used. - -If you're making an application, and simply migrating a Scala 2.12 code base to 2.13, it might be ok to keep using `scala.Seq` in your code. +In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]` ("ISeq"), instead of `scala.collection.Seq[A]` ("CSeq"). This change requires some planning depending on how your code is going to be used. If you're making a library intended to be used by other programmers, then using `scala.Seq` or varargs is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. - if you cross build with Scala 2.12 and want to maintain the API semantics for 2.13 version of your library, or - if your library users frequently uses mutable collections such as `Array` -you can import `scala.collection.Seq` ("CSeq") explicitly in your code. +you can import collection Seq explicitly in your code. ~~~ scala import scala.collection.Seq + +object FoodToGo { + def orderFood(order: Seq[Order]): Seq[Food] +} +~~~ + +Note that this might still break the source compatibility if `scala.Seq` (or just `Seq`) appears in the source code. + +~~~ scala +val food: Seq[Food] = FoodToGo.orderFood(order) // won't compile ~~~ -In the future when your API is able to break the source compatibility, it might also make sense to migrate towards the `scala.collection.immutable.Seq` ("ISeq") for both Scala 2.12 and Scala 2.13. +Since `Seq`, an alias for ISeq in 2.13, is narrower than CSeq, the above code will no longer compile. One workaround would be to ask your users to add `toSeq`, which returns ISeq. ~~~ scala -import scala.collection.immutable.Seq +val food: Seq[Food] = FoodToGo.orderFood(order).toSeq // add .toSeq ~~~ +Another workaround might be to accept CSeq, but return ISeq. + +~~~ scala +import scala.collection.{ Seq => CSeq } +import scala.collection.immutable.{ Seq => ISeq } + +object FoodToGo { + def orderFood(order: CSeq[Order]): ISeq[Food] +} +~~~ + +In the future when your API is able to break the source compatibility, it might also make sense to migrate towards ISeq for both Scala 2.12 and Scala 2.13. + +~~~ scala +import scala.collection.immutable.{ Seq => ISeq } + +object FoodToGo { + def orderFood(order: ISeq[Order]): ISeq[Food] +} +~~~ + +Similarly, if you're making an end-user application, unifying to CSeq might be the easier and safer initial path especially for a larger and complex code base. Switching to ISeq will be a more advanced refactoring. + Note that in Scala 2.13 the sequence passed into as a varargs as `orderFood(xs: _*)` must also be immutable. This is because the sequence passed in as a varargs must conform to `scala.Seq` according to [SLS 6.6](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications). Thus, if your API exposes varargs it will be an unavoidable breaking change. This might affect Java interoperability. +### Masking scala.Seq + +To use the compiler to bad the use of plain `Seq`, you can declare your own `Seq` to mask `scala.Seq`. + +~~~ scala +package example + +import scala.annotation.compileTimeOnly + +/** + * In Scala 2.13, scala.Seq moved from scala.collection.Seq to scala.collection.immutable.Seq. + * In this code base, we'll require you to name ISeq or CSeq. + * + * import scala.collection.{ Seq => CSeq } + * import scala.collection.immutable.{ Seq => ISeq } + * + * This Seq trait is a dummy type to prevent the use of `Seq`. + */ +@compileTimeOnly("Use ISeq or CSeq") private[example] trait Seq[A1, F1[A2], A3] +~~~ + +This might be useful during the transition period where you have to remember to import CSeq. + ## What are the breaking changes? The following table summarizes the breaking changes. The "Automatic Migration Rule" column gives the name of the migration rule that can be used to automatically update old code to the new expected form. From cc9b455f6d43d30aa67220e33dc598b381ad3f07 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 20 May 2019 18:23:35 -0400 Subject: [PATCH 0580/3174] scala.IndexedSeq too --- _overviews/core/collections-migration-213.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index f877849115..730ddb34b9 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -11,6 +11,7 @@ For an in-depth overview of the Scala 2.13 collections library, see the [collect The most important changes in the Scala 2.13 collections library are: - `scala.Seq[+A]` is now an alias for `scala.collection.immutable.Seq[A]` (instead of `scala.collection.Seq[A]`). Note that this also changes the type of Scala varargs methods. + - `scala.IndexedSeq[+A]` is now an alias for `scala.collection.immutable.IndexedSeq[A]` (instead of `scala.collection.IndexedSeq[A]`). - 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. @@ -30,11 +31,11 @@ The [scala-collection-compat](https://github.com/scala/scala-collection-compat) The module also provides [migratrion rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. -## scala.Seq migration +## scala.Seq and scala.IndexedSeq migration -In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]` ("ISeq"), instead of `scala.collection.Seq[A]` ("CSeq"). This change requires some planning depending on how your code is going to be used. +In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]` ("ISeq"), instead of `scala.collection.Seq[A]` ("CSeq"). Similarly, `scala.IndexedSeq[+A]` is an alias for `scala.collection.immutable.IndexedSeq[A]`. These changes require some planning depending on how your code is going to be used. -If you're making a library intended to be used by other programmers, then using `scala.Seq` or varargs is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. +If you're making a library intended to be used by other programmers, then using `scala.Seq`, `scala.IndexedSeq`, or vararg is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. - if you cross build with Scala 2.12 and want to maintain the API semantics for 2.13 version of your library, or - if your library users frequently uses mutable collections such as `Array` @@ -105,6 +106,17 @@ import scala.annotation.compileTimeOnly * This Seq trait is a dummy type to prevent the use of `Seq`. */ @compileTimeOnly("Use ISeq or CSeq") private[example] trait Seq[A1, F1[A2], A3] + +/** + * In Scala 2.13, scala.IndexedSeq moved from scala.collection.IndexedSeq to scala.collection.immutable.IndexedSeq. + * In this code base, we'll require you to name ISeq or CSeq. + * + * import scala.collection.{ IndexedSeq => CIndexedSeq } + * import scala.collection.immutable.{ IndexedSeq => IIndexedSeq } + * + * This IndexedSeq trait is a dummy type to prevent the use of `IndexedSeq`. + */ +@compileTimeOnly("Use IIndexedSeq or CIndexedSeq") private[example] trait IndexedSeq[A1, F1[A2], A3] ~~~ This might be useful during the transition period where you have to remember to import CSeq. From a0a7b9babd80592fe1ae8d01e190f6ddabe0fe11 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 20 May 2019 19:36:39 -0700 Subject: [PATCH 0581/3174] RC2 is here --- api/all.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/all.md b/api/all.md index 50c5bea6bc..d2caf5f5a7 100644 --- a/api/all.md +++ b/api/all.md @@ -28,10 +28,10 @@ includeTOC: true ## Prereleases -* Scala 2.13.0-RC1 - * [Library API](https://www.scala-lang.org/api/2.13.0-RC1/) - * [Compiler API](https://www.scala-lang.org/api/2.13.0-RC1/scala-compiler/scala/) - * [Reflection API](https://www.scala-lang.org/api/2.13.0-RC1/scala-reflect/scala/reflect/) +* Scala 2.13.0-RC2 + * [Library API](https://www.scala-lang.org/api/2.13.0-RC2/) + * [Compiler API](https://www.scala-lang.org/api/2.13.0-RC2/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.0-RC2/scala-reflect/scala/reflect/) ## Nightly builds From e498da2ff78db946b41270999cb327177c150356 Mon Sep 17 00:00:00 2001 From: Noah Rosamilia Date: Tue, 21 May 2019 10:22:10 -0400 Subject: [PATCH 0582/3174] Fix typo in implicit-parameters.md --- _tour/implicit-parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/implicit-parameters.md b/_tour/implicit-parameters.md index 43befb04e7..5f2c181491 100644 --- a/_tour/implicit-parameters.md +++ b/_tour/implicit-parameters.md @@ -56,7 +56,7 @@ object ImplicitTest { To show how implicit parameters work, we first define monoids `stringMonoid` and `intMonoid` for strings and integers, respectively. The `implicit` keyword indicates that the corresponding object can be used implicitly. -The method `sum` takes a `List[A]` and returns an `A`, which takes the initial `A` from `unit`, and combines each next `A` in the list to that with the `add` method. Making the parameter `m` implicit here means we only have to provide the `xs` parameter when we call the method if Scala can find a an implict `Monoid[A]` to use for the implicit `m` parameter. +The method `sum` takes a `List[A]` and returns an `A`, which takes the initial `A` from `unit`, and combines each next `A` in the list to that with the `add` method. Making the parameter `m` implicit here means we only have to provide the `xs` parameter when we call the method if Scala can find an implict `Monoid[A]` to use for the implicit `m` parameter. In our `main` method we call `sum` twice, and only provide the `xs` parameter. Scala will now look for an implicit in the scope mentioned above. The first call to `sum` passes a `List[Int]` for `xs`, which means that `A` is `Int`. The implicit parameter list with `m` is left out, so Scala will look for an implicit of type `Monoid[Int]`. The first lookup rule reads From 182cc3f73799e5537404593b20f43aa81340334c Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Tue, 21 May 2019 21:03:08 +0200 Subject: [PATCH 0583/3174] Fix typo --- _tour/implicit-parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/implicit-parameters.md b/_tour/implicit-parameters.md index 5f2c181491..aeb43361b4 100644 --- a/_tour/implicit-parameters.md +++ b/_tour/implicit-parameters.md @@ -56,7 +56,7 @@ object ImplicitTest { To show how implicit parameters work, we first define monoids `stringMonoid` and `intMonoid` for strings and integers, respectively. The `implicit` keyword indicates that the corresponding object can be used implicitly. -The method `sum` takes a `List[A]` and returns an `A`, which takes the initial `A` from `unit`, and combines each next `A` in the list to that with the `add` method. Making the parameter `m` implicit here means we only have to provide the `xs` parameter when we call the method if Scala can find an implict `Monoid[A]` to use for the implicit `m` parameter. +The method `sum` takes a `List[A]` and returns an `A`, which takes the initial `A` from `unit`, and combines each next `A` in the list to that with the `add` method. Making the parameter `m` implicit here means we only have to provide the `xs` parameter when we call the method if Scala can find an implicit `Monoid[A]` to use for the implicit `m` parameter. In our `main` method we call `sum` twice, and only provide the `xs` parameter. Scala will now look for an implicit in the scope mentioned above. The first call to `sum` passes a `List[Int]` for `xs`, which means that `A` is `Int`. The implicit parameter list with `m` is left out, so Scala will look for an implicit of type `Monoid[Int]`. The first lookup rule reads From 83173abf49f8dc02217c25b8564c0ce609ff0f74 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 21 May 2019 09:55:08 +0100 Subject: [PATCH 0584/3174] Tweak Seq migration guide --- _overviews/core/collections-migration-213.md | 117 +++++++++++++------ 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 730ddb34b9..71b9cbf815 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -31,65 +31,106 @@ The [scala-collection-compat](https://github.com/scala/scala-collection-compat) The module also provides [migratrion rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. -## scala.Seq and scala.IndexedSeq migration +## scala.Seq, varargs and scala.IndexedSeq migration -In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]` ("ISeq"), instead of `scala.collection.Seq[A]` ("CSeq"). Similarly, `scala.IndexedSeq[+A]` is an alias for `scala.collection.immutable.IndexedSeq[A]`. These changes require some planning depending on how your code is going to be used. +In Scala 2.13 `scala.Seq[+A]` is an alias for `scala.collection.immutable.Seq[A]`, instead of `scala.collection.Seq[A]`, and `scala.IndexedSeq[+A]` is an alias for `scala.collection.immutable.IndexedSeq[A]`. These changes require some planning depending on how your code is going to be used. -If you're making a library intended to be used by other programmers, then using `scala.Seq`, `scala.IndexedSeq`, or vararg is going to be a breaking change in the API semantics. For example, if there was a function `def orderFood(order: Seq[Order]): Seq[Food]`, previously the library user would have been able to pass in an array of `Order`, but it won't work for 2.13. +The change in definition of `scala.Seq` also has the effect of making the type of varargs parameters immutable sequences, due to [SLS 6.6][], so in +a method such as `orderFood(xs: _*)` the varargs parameter `xs` must be an immutable sequence. -- if you cross build with Scala 2.12 and want to maintain the API semantics for 2.13 version of your library, or -- if your library users frequently uses mutable collections such as `Array` +[SLS 6.6]: https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications -you can import collection Seq explicitly in your code. +Therefore any method signature in Scala 2.13 which includes `scala.Seq`, varargs, or `scala.IndexedSeq` is going +to have a breaking change in API semantics (as the immutable sequence types require more — immutability — than the +not-immutable types). For example, users of a method like `def orderFood(order: Seq[Order]): Seq[Food]` would +previously have been able to pass in an `ArrayBuffer` of `Order`, but cannot in 2.13. + +### Migrating varargs + +The change for varargs is unavoidable, as you cannot change the type used at definition site. The options +available for migrating the usage sites are the following: + +- change the value to already be an immutable sequence, which allows for direct varargs usage: `xs: _*`, +- change the value to be an immutable sequence on the fly by calling `.toSeq`: `xs.toSeq: _*`, which will only + copy data if the sequence wasn't already immutable +- use `scala.collection.immutable.ArraySeq.unsafeWrapArray` to wrap your array and avoid copying, but see its + scaladoc + +### Option 1: migrate back to scala.collection.Seq + +The first, in some ways simplest, migration strategy for all non-varargs usages of `scala.Seq` is to replace +them with `scala.collection.Seq` (and require users to call `.toSeq` or `unsafeWrapArray` when passing such +sequences to varargs methods). + +We recommend using `import scala.collection`/`import scala.collection.immutable` and +`collection.Seq`/`immutable.Seq`. + +We recommend against using `import scala.collection.Seq`, which shadows the automatically imported `scala.Seq`, +because even if it's a oneline change it causes name confusion. For code generation or macros the safest option +is using the fully-qualified `_root_.scala.collection.Seq`. + +As an example, the migration would look something like this: ~~~ scala -import scala.collection.Seq +import scala.collection object FoodToGo { - def orderFood(order: Seq[Order]): Seq[Food] + def orderFood(order: collection.Seq[Order]): collection.Seq[Food] } ~~~ -Note that this might still break the source compatibility if `scala.Seq` (or just `Seq`) appears in the source code. +However users of this code in Scala 2.13 would also have to migrate, as the result type is source-incompatible +with any `scala.Seq` (or just `Seq`) usage in their code: ~~~ scala val food: Seq[Food] = FoodToGo.orderFood(order) // won't compile ~~~ -Since `Seq`, an alias for ISeq in 2.13, is narrower than CSeq, the above code will no longer compile. One workaround would be to ask your users to add `toSeq`, which returns ISeq. +The simplest workaround is to ask your users to call `.toSeq` on the result which will return an immutable Seq, +and only copy data if the sequence wasn't immutable: ~~~ scala val food: Seq[Food] = FoodToGo.orderFood(order).toSeq // add .toSeq ~~~ -Another workaround might be to accept CSeq, but return ISeq. +### Option 2: use scala.collection.Seq for parameters and scala.collection.immutable.Seq for result types + +The second, intermediate, migration strategy would be to change all methods to accept not-immutable Seq but +return immutable Seq, following the [robustness principle][] (also known as "Postel's law"): + +[robustness principle]: https://en.wikipedia.org/wiki/Robustness_principle ~~~ scala -import scala.collection.{ Seq => CSeq } -import scala.collection.immutable.{ Seq => ISeq } +import scala.collection +import scala.collection.immutable object FoodToGo { - def orderFood(order: CSeq[Order]): ISeq[Food] + def orderFood(order: collection.Seq[Order]): immutable.Seq[Food] } ~~~ -In the future when your API is able to break the source compatibility, it might also make sense to migrate towards ISeq for both Scala 2.12 and Scala 2.13. +### Option 3: use immutable sequences + +The third migration strategy is to change your API to use immutable sequences for both parameter and result +types. When cross-building your library for Scala 2.12 and 2.13 this could either mean: + +- continuing to use `scala.Seq` which means it stays source and binary-compatible in 2.12, but would have to + have immutable sequence semantics (but that might already be the case). +- switch to explicitly using immutable Seq in both Scala 2.12 and 2.13, which means breaking source, binary and + (possibly) semantic compatibility in 2.12: ~~~ scala -import scala.collection.immutable.{ Seq => ISeq } +import scala.collection.immutable object FoodToGo { - def orderFood(order: ISeq[Order]): ISeq[Food] + def orderFood(order: immutable.Seq[Order]): immutable.Seq[Food] } ~~~ -Similarly, if you're making an end-user application, unifying to CSeq might be the easier and safer initial path especially for a larger and complex code base. Switching to ISeq will be a more advanced refactoring. - -Note that in Scala 2.13 the sequence passed into as a varargs as `orderFood(xs: _*)` must also be immutable. This is because the sequence passed in as a varargs must conform to `scala.Seq` according to [SLS 6.6](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications). Thus, if your API exposes varargs it will be an unavoidable breaking change. This might affect Java interoperability. - -### Masking scala.Seq +### Shadowing scala.Seq and scala.IndexedSeq -To use the compiler to bad the use of plain `Seq`, you can declare your own `Seq` to mask `scala.Seq`. +You maybe be interested in entirely banning plain `Seq` usage. You can use the compiler to do so by declaring +your own package-level (and package private) `Seq` type which will mask `scala.Seq`. ~~~ scala package example @@ -97,29 +138,33 @@ package example import scala.annotation.compileTimeOnly /** - * In Scala 2.13, scala.Seq moved from scala.collection.Seq to scala.collection.immutable.Seq. - * In this code base, we'll require you to name ISeq or CSeq. + * In Scala 2.13, `scala.Seq` changed from aliasing `scala.collection.Seq` to aliasing + * `scala.collection.immutable.Seq`. In this code base usage of unqualified `Seq` is banned: use + * `immutable.Seq` or `collection.Seq` instead. * - * import scala.collection.{ Seq => CSeq } - * import scala.collection.immutable.{ Seq => ISeq } + * import scala.collection + * import scala.collection.immutable * - * This Seq trait is a dummy type to prevent the use of `Seq`. + * This `Seq` trait is a dummy type to prevent the use of `Seq`. */ -@compileTimeOnly("Use ISeq or CSeq") private[example] trait Seq[A1, F1[A2], A3] +@compileTimeOnly("Use immutable.Seq or collection.Seq") +private[example] trait Seq[A1] /** - * In Scala 2.13, scala.IndexedSeq moved from scala.collection.IndexedSeq to scala.collection.immutable.IndexedSeq. - * In this code base, we'll require you to name ISeq or CSeq. + * In Scala 2.13, `scala.IndexedSeq` changed from aliasing `scala.collection.IndexedSeq` to aliasing + * `scala.collection.immutable.IndexedSeq`. In this code base usage of unqualified `IndexedSeq` is + * banned: use `immutable.IndexedSeq` or `collection.IndexedSeq`. * - * import scala.collection.{ IndexedSeq => CIndexedSeq } - * import scala.collection.immutable.{ IndexedSeq => IIndexedSeq } + * import scala.collection + * import scala.collection.immutable * - * This IndexedSeq trait is a dummy type to prevent the use of `IndexedSeq`. + * This `IndexedSeq` trait is a dummy type to prevent the use of `IndexedSeq`. */ -@compileTimeOnly("Use IIndexedSeq or CIndexedSeq") private[example] trait IndexedSeq[A1, F1[A2], A3] +@compileTimeOnly("Use immutable.IndexedSeq or collection.IndexedSeq") +private[example] trait IndexedSeq[A1] ~~~ -This might be useful during the transition period where you have to remember to import CSeq. +This might be useful during the migration to catch usages of unqualified `Seq` and `IndexedSeq`. ## What are the breaking changes? From a527db979319fd7689897661d5443ca81514c280 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 23 May 2019 11:33:21 +0000 Subject: [PATCH 0585/3174] Bump nokogiri from 1.8.4 to 1.8.5 Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.8.4 to 1.8.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.8.4...v1.8.5) --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4157511c7d..de18a3160a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -61,7 +61,7 @@ GEM mercenary (0.3.6) mini_portile2 (2.3.0) minitest (5.11.3) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) parallel (1.12.1) pathutil (0.16.1) From 3b4357de9f9569257d793330cbf5b49d9caea9e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 23 May 2019 11:33:47 +0000 Subject: [PATCH 0586/3174] Bump jekyll from 3.8.3 to 3.8.5 Bumps [jekyll](https://github.com/jekyll/jekyll) from 3.8.3 to 3.8.5. - [Release notes](https://github.com/jekyll/jekyll/releases) - [Changelog](https://github.com/jekyll/jekyll/blob/master/History.markdown) - [Commits](https://github.com/jekyll/jekyll/compare/v3.8.3...v3.8.5) --- Gemfile.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4157511c7d..16afcdf020 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,18 +6,18 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.5.2) + addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) colorator (1.1.0) colorize (0.8.1) - concurrent-ruby (1.0.5) + concurrent-ruby (1.1.5) em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) ethon (0.11.0) ffi (>= 1.3.0) eventmachine (1.2.7) - ffi (1.9.25) + ffi (1.11.1) forwardable-extended (2.6.0) html-proofer (3.9.1) activesupport (>= 4.2, < 6.0) @@ -31,7 +31,7 @@ GEM http_parser.rb (0.6.0) i18n (0.9.5) concurrent-ruby (~> 1.0) - jekyll (3.8.3) + jekyll (3.8.5) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) @@ -50,10 +50,10 @@ GEM sass (~> 3.4) jekyll-scalafiddle (1.0.1) jekyll (~> 3.0) - jekyll-watch (2.0.0) + jekyll-watch (2.2.1) listen (~> 3.0) kramdown (1.17.0) - liquid (4.0.0) + liquid (4.0.3) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -64,16 +64,16 @@ GEM nokogiri (1.8.4) mini_portile2 (~> 2.3.0) parallel (1.12.1) - pathutil (0.16.1) + pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (3.0.2) + public_suffix (3.0.3) rb-fsevent (0.10.3) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - rouge (3.1.1) + rb-inotify (0.10.0) + ffi (~> 1.0) + rouge (3.3.0) ruby_dep (1.5.0) - safe_yaml (1.0.4) - sass (3.5.7) + safe_yaml (1.0.5) + sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) From debd78f1d8d123c3b9da4c89027638728fbc42c2 Mon Sep 17 00:00:00 2001 From: Filipe Regadas Date: Mon, 27 May 2019 18:29:35 -0400 Subject: [PATCH 0587/3174] Fix invalid universe import --- _overviews/quasiquotes/lifting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/quasiquotes/lifting.md b/_overviews/quasiquotes/lifting.md index 2c6126a789..c28082b716 100644 --- a/_overviews/quasiquotes/lifting.md +++ b/_overviews/quasiquotes/lifting.md @@ -49,7 +49,7 @@ To define tree representation for your own data type just provide an implicit in package points - import scala.universe._ + import scala.reflect.runtime.universe._ case class Point(x: Int, y: Int) object Point { From 5e5b22979ca2a1c431588c79f6cc73267858b655 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Thu, 30 May 2019 17:14:15 +0800 Subject: [PATCH 0588/3174] Fix Chinese Simple(zh_CN) version of issue#1339, which is refining pattern matching. --- _zh-cn/tour/pattern-matching.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_zh-cn/tour/pattern-matching.md b/_zh-cn/tour/pattern-matching.md index 8f03480ac6..c9727b304d 100644 --- a/_zh-cn/tour/pattern-matching.md +++ b/_zh-cn/tour/pattern-matching.md @@ -28,19 +28,19 @@ x match { case 0 => "zero" case 1 => "one" case 2 => "two" - case _ => "many" + case _ => "other" } ``` -上述代码中的`val x`是一个0到10之间的随机整数,将它放在`match`运算符的左侧对其进行模式匹配,`match`的右侧是包含4条`case`的表达式,其中最后一个`case _`表示匹配其余所有情况,在这里即是`x`大于2的情况。 +上述代码中的`val x`是一个0到10之间的随机整数,将它放在`match`运算符的左侧对其进行模式匹配,`match`的右侧是包含4条`case`的表达式,其中最后一个`case _`表示匹配其余所有情况,在这里就是其他可能的整型值。 `match`表达式具有一个结果值 ```tut def matchTest(x: Int): String = x match { case 1 => "one" case 2 => "two" - case _ => "many" + case _ => "other" } -matchTest(3) // many +matchTest(3) // other matchTest(1) // one ``` 这个`match`表达式是String类型的,因为所有的情况(case)均返回String,所以`matchTest`函数的返回值是String类型。 From 099fe2fcd30d42e296cf504ee5687582755f9bf0 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Fri, 31 May 2019 12:46:00 +0800 Subject: [PATCH 0589/3174] Fix Chinese Simple(zh_CN) version of issue#1339, based on commit https://github.com/scala/docs.scala-lang/commit/ff6580c6247ee091b4805335a67480f2153c3bec. --- _zh-cn/tour/pattern-matching.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_zh-cn/tour/pattern-matching.md b/_zh-cn/tour/pattern-matching.md index c9727b304d..7ea9fec48e 100644 --- a/_zh-cn/tour/pattern-matching.md +++ b/_zh-cn/tour/pattern-matching.md @@ -66,8 +66,8 @@ case class VoiceRecording(contactName: String, link: String) extends Notificatio ``` def showNotification(notification: Notification): String = { notification match { - case Email(email, title, _) => - s"You got an email from $email with title: $title" + case Email(sender, title, _) => + s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" case VoiceRecording(name, link) => @@ -81,7 +81,7 @@ println(showNotification(someSms)) // prints You got an SMS from 12345! Message println(showNotification(someVoiceRecording)) // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123 ``` -`showNotification`函数接受一个抽象类`Notification`对象作为输入参数,然后匹配其具体类型。(也就是判断它是一个`Email`,`SMS`,还是`VoiceRecording`)。在`case Email(email, title, _)`中,对象的`email`和`title`属性在返回值中被使用,而`body`属性则被忽略,故使用`_`代替。 +`showNotification`函数接受一个抽象类`Notification`对象作为输入参数,然后匹配其具体类型。(也就是判断它是一个`Email`,`SMS`,还是`VoiceRecording`)。在`case Email(sender, title, _)`中,对象的`sender`和`title`属性在返回值中被使用,而`body`属性则被忽略,故使用`_`代替。 ## 模式守卫(Pattern gaurds) 为了让匹配更加具体,可以使用模式守卫,也就是在模式后面加上`if `。 @@ -89,7 +89,7 @@ println(showNotification(someVoiceRecording)) // you received a Voice Recording def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = { notification match { - case Email(email, _, _) if importantPeopleInfo.contains(email) => + case Email(sender, _, _) if importantPeopleInfo.contains(sender) => "You got an email from special someone!" case SMS(number, _) if importantPeopleInfo.contains(number) => "You got an SMS from special someone!" @@ -111,7 +111,7 @@ println(showImportantNotification(importantEmail, importantPeopleInfo)) println(showImportantNotification(importantSms, importantPeopleInfo)) ``` -在`case Email(email, _, _) if importantPeopleInfo.contains(email)`中,除了要求`notification`是`Email`类型外,还需要`email`在重要人物列表`importantPeopleInfo`中,才会匹配到该模式。 +在`case Email(sender, _, _) if importantPeopleInfo.contains(sender)`中,除了要求`notification`是`Email`类型外,还需要`sender`在重要人物列表`importantPeopleInfo`中,才会匹配到该模式。 ## 仅匹配类型 From 1c7b5b6f9f7e7fea1b26206759215dd1a7491862 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 31 May 2019 22:01:55 +0200 Subject: [PATCH 0590/3174] hello Scala 2.13.0-RC3 --- api/all.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/all.md b/api/all.md index d2caf5f5a7..77ecd28618 100644 --- a/api/all.md +++ b/api/all.md @@ -28,10 +28,10 @@ includeTOC: true ## Prereleases -* Scala 2.13.0-RC2 - * [Library API](https://www.scala-lang.org/api/2.13.0-RC2/) - * [Compiler API](https://www.scala-lang.org/api/2.13.0-RC2/scala-compiler/scala/) - * [Reflection API](https://www.scala-lang.org/api/2.13.0-RC2/scala-reflect/scala/reflect/) +* Scala 2.13.0-RC3 + * [Library API](https://www.scala-lang.org/api/2.13.0-RC3/) + * [Compiler API](https://www.scala-lang.org/api/2.13.0-RC3/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.0-RC3/scala-reflect/scala/reflect/) ## Nightly builds From 0e3b437e0a73d31900a8c702ac28e6454cde63e2 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Sun, 2 Jun 2019 11:16:32 +0800 Subject: [PATCH 0591/3174] Fix Chinese Simple(zh_CN) version of issue#1339, based on commit https://github.com/scala/docs.scala-lang/commit/55ed64e205d80298f59a6724bd7c44a26ec6e0e7 (Fix: should extend NotUniversal trait) --- _zh-cn/overviews/core/value-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/overviews/core/value-classes.md b/_zh-cn/overviews/core/value-classes.md index 85014abdb8..b731b9da0e 100644 --- a/_zh-cn/overviews/core/value-classes.md +++ b/_zh-cn/overviews/core/value-classes.md @@ -226,7 +226,7 @@ value class不能将惰性val或val作为成员,也不能有嵌套类、trait value类不能继承non-universal trait,并且其本身不能被继承: trait NotUniversal - class Value(val x: Int) extends AnyVal with notUniversal + class Value(val x: Int) extends AnyVal with NotUniversal class Extend(x: Int) extends Value(x) Extend.scala:2: error: illegal inheritance; superclass AnyVal From 749a5dce75eb7a794e5eb075b6b4c36b435f9dd6 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Sun, 2 Jun 2019 12:05:38 +0800 Subject: [PATCH 0592/3174] Fix Chinese Simple(zh_CN) version of issue#1339, based on the latest commit of English originals. --- ...ions-between-java-and-scala-collections.md | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md b/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md index 9b8e44daf0..341dce3d87 100644 --- a/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md +++ b/_zh-cn/overviews/collections/conversions-between-java-and-scala-collections.md @@ -16,14 +16,15 @@ language: zh-cn 某些时候,你需要将一种容器类型转换成另外一种类型。例如,你可能想要像访问Scala容器一样访问某个Java容器,或者你可能想将一个Scala容器像Java容器一样传递给某个Java方法。在Scala中,这是很容易的,因为Scala提供了大量的方法来隐式转换所有主要的Java和Scala容器类型。其中提供了如下的双向类型转换: - Iterator <=> java.util.Iterator - Iterator <=> java.util.Enumeration - Iterable <=> java.lang.Iterable - Iterable <=> java.util.Collection - mutable.Buffer <=> java.util.List - mutable.Set <=> java.util.Set - mutable.Map <=> java.util.Map - mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap + + Iterator <=> java.util.Iterator + Iterator <=> java.util.Enumeration + Iterable <=> java.lang.Iterable + Iterable <=> java.util.Collection + mutable.Buffer <=> java.util.List + mutable.Set <=> java.util.Set + mutable.Map <=> java.util.Map + mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap 使用这些转换很简单,只需从JavaConverters对象中import它们即可。 @@ -34,26 +35,30 @@ import之后,通过扩展方法 asScala 和 asJava 就可以在Scala容器和 scala> import collection.mutable._ import collection.mutable._ + scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] + scala> val buf: Seq[Int] = jul.asScala buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) + scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava - m: java.util.Map[String, Int] = {hello=2, abc=1} + m: java.util.Map[String,Int] = {abc=1, hello=2} 在Scala内部,这些转换是通过一系列“包装”对象完成的,这些对象会将相应的方法调用转发至底层的容器对象。所以容器不会在Java和Scala之间拷贝来拷贝去。一个值得注意的特性是,如果你将一个Java容器转换成其对应的Scala容器,然后再将其转换回同样的Java容器,最终得到的是一个和一开始完全相同的容器对象(译注:这里的相同意味着这两个对象实际上是指向同一片内存区域的引用,容器转换过程中没有任何的拷贝发生)。 还有一些Scala容器类型可以转换成对应的Java类型,但是并没有将相应的Java类型转换成Scala类型的能力,它们是: - Seq => java.util.List - mutable.Seq => java.util.List - Set => java.util.Set - Map => java.util.Map + Seq => java.util.List + mutable.Seq => java.util.List + Set => java.util.Set + Map => java.util.Map 因为Java并未区分可变容器不可变容器类型,所以,虽然能将`scala.immutable.List`转换成`java.util.List`,但所有的修改操作都会抛出“UnsupportedOperationException”。参见下例: - scala> jul = List(1, 2, 3).asJava + scala> val jul = List(1, 2, 3).asJava jul: java.util.List[Int] = [1, 2, 3] + scala> jul.add(7) java.lang.UnsupportedOperationException - at java.util.AbstractList.add(AbstractList.java:131) + at java.util.AbstractList.add(AbstractList.java:148) From 2893df074cdf8372a0591cde341fe58c2d1414c8 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Sun, 2 Jun 2019 12:09:13 +0800 Subject: [PATCH 0593/3174] Typo in _overviews/collections/conversions-between-java-and-scala-collections.md . --- .../conversions-between-java-and-scala-collections.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections/conversions-between-java-and-scala-collections.md b/_overviews/collections/conversions-between-java-and-scala-collections.md index fb184cfac2..c476d4369c 100644 --- a/_overviews/collections/conversions-between-java-and-scala-collections.md +++ b/_overviews/collections/conversions-between-java-and-scala-collections.md @@ -46,7 +46,7 @@ This enables conversions between Scala collections and their corresponding Java scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava m: java.util.Map[String,Int] = {abc=1, hello=2} -Internally, these conversion work by setting up a "wrapper" object that forwards all operations to the underlying collection object. So collections are never copied when converting between Java and Scala. An interesting property is that if you do a round-trip conversion from, say a Java type to its corresponding Scala type, and back to the same Java type, you end up with the identical collection object you have started with. +Internally, these conversions work by setting up a "wrapper" object that forwards all operations to the underlying collection object. So collections are never copied when converting between Java and Scala. An interesting property is that if you do a round-trip conversion from, say a Java type to its corresponding Scala type, and back to the same Java type, you end up with the identical collection object you have started with. Certain other Scala collections can also be converted to Java, but do not have a conversion back to the original Scala type: From 4f7da4a9fa605139d8dcefc69fd011e5dd9c25ab Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Mon, 3 Jun 2019 10:32:39 +0800 Subject: [PATCH 0594/3174] Fix the contents layout of _zh-cn/overviews/collections/seqs.md . --- _zh-cn/overviews/collections/seqs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_zh-cn/overviews/collections/seqs.md b/_zh-cn/overviews/collections/seqs.md index c9640efd99..adee18c33f 100644 --- a/_zh-cn/overviews/collections/seqs.md +++ b/_zh-cn/overviews/collections/seqs.md @@ -27,7 +27,7 @@ language: zh-cn 如果一个序列是可变的,它提供了另一种更新序列中的元素的,但有副作用的update方法,Scala中常有这样的语法,如seq(idx) = elem。它只是seq.update(idx, elem)的简写,所以update 提供了方便的赋值语法。应注意update 和updated之间的差异。update 再原来基础上更改序列中的元素,并且仅适用于可变序列。而updated 适用于所有的序列,它总是返回一个新序列,而不会修改原序列。 -## Seq类的操作 +### Seq类的操作 | WHAT IT IS | WHAT IT DOES | |------------------ | -------------------| @@ -79,13 +79,13 @@ language: zh-cn 常用线性序列有 `scala.collection.immutable.List`和`scala.collection.immutable.Stream`。常用索引序列有 `scala.Array scala.collection.mutable.ArrayBuffer`。Vector 类提供一个在索引访问和线性访问之间有趣的折中。它同时具有高效的恒定时间的索引开销,和恒定时间的线性访问开销。正因为如此,对于混合访问模式,vector是一个很好的基础。后面将详细介绍vector。 -## 缓冲器 +### 缓冲器 Buffers是可变序列一个重要的种类。它们不仅允许更新现有的元素,而且允许元素的插入、移除和在buffer尾部高效地添加新元素。buffer 支持的主要新方法有:用于在尾部添加元素的 `+=` 和 `++=`;用于在前方添加元素的`+=: `和` ++=:` ;用于插入元素的 `insert`和`insertAll`;以及用于删除元素的` remove` 和 `-=`。如下表所示。 ListBuffer和ArrayBuffer是常用的buffer实现 。顾名思义,ListBuffer依赖列表(List),支持高效地将它的元素转换成列表。而ArrayBuffer依赖数组(Array),能快速地转换成数组。 -## Buffer类的操作 +#### Buffer类的操作 | WHAT IT IS | WHAT IT DOES | |--------------------- | -----------------------| From 1a3243214af43a3fe9a1c07b073b6a35b3b43941 Mon Sep 17 00:00:00 2001 From: Alexander Ronsse-Tucherov Date: Tue, 4 Jun 2019 17:40:55 -0700 Subject: [PATCH 0595/3174] Change "seemless" to "seamless" --- _overviews/tutorials/scala-for-java-programmers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/tutorials/scala-for-java-programmers.md b/_overviews/tutorials/scala-for-java-programmers.md index ada65a08f7..3ed8305c2a 100644 --- a/_overviews/tutorials/scala-for-java-programmers.md +++ b/_overviews/tutorials/scala-for-java-programmers.md @@ -99,7 +99,7 @@ French-speaking part of Switzerland use the same conventions.) Java's class libraries define powerful utility classes, such as `Date` and `DateFormat`. Since Scala interoperates -seemlessly with Java, there is no need to implement equivalent +seamlessly with Java, there is no need to implement equivalent classes in the Scala class library--we can simply import the classes of the corresponding Java packages: From 7b31ea8f5a8a44678761080566a557009b0d8c36 Mon Sep 17 00:00:00 2001 From: Changlin Li Date: Wed, 5 Jun 2019 21:05:27 -0400 Subject: [PATCH 0596/3174] Fix buggy Regex definition The original Regex definition doesn't fully match the `background-image` value. --- _tour/regular-expression-patterns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_tour/regular-expression-patterns.md b/_tour/regular-expression-patterns.md index ec07f9f368..2e0670879e 100644 --- a/_tour/regular-expression-patterns.md +++ b/_tour/regular-expression-patterns.md @@ -35,7 +35,7 @@ You can also search for groups of regular expressions using parentheses. ```tut import scala.util.matching.Regex -val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r +val keyValPattern: Regex = "([0-9a-zA-Z- ]+): ([0-9a-zA-Z-#()/. ]+)".r val input: String = """background-color: #A03300; @@ -53,7 +53,7 @@ for (patternMatch <- keyValPattern.findAllMatchIn(input)) Here we parse out the keys and values of a String. Each match has a group of sub-matches. Here is the output: ``` key: background-color value: #A03300 -key: background-image value: url(img +key: background-image value: url(img/header100.png) key: background-position value: top center key: background-repeat value: repeat-x key: background-size value: 2160px 108px From b3bd621d8e8ddda1b726aa8c473186dd996447ed Mon Sep 17 00:00:00 2001 From: cclaudiu81 Date: Fri, 7 Jun 2019 00:30:42 +0300 Subject: [PATCH 0597/3174] Update higher-order-functions.md enhanced doc on methods that take fns as args --- _tour/higher-order-functions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_tour/higher-order-functions.md b/_tour/higher-order-functions.md index efc8d37db2..d6d1681894 100644 --- a/_tour/higher-order-functions.md +++ b/_tour/higher-order-functions.md @@ -60,6 +60,8 @@ case class WeeklyWeatherForecast(temperatures: Seq[Double]) { ``` Here the method `convertCtoF` is passed to `forecastInFahrenheit`. This is possible because the compiler coerces `convertCtoF` to the function `x => convertCtoF(x)` (note: `x` will be a generated name which is guaranteed to be unique within its scope). + +In a pure Object Oriented world a good practice is to avoid exposing methods that are parameterized with functions that might escape the internal state of the objects. Leaking internal state might break the invariants of the object itself. ## Functions that accept functions One reason to use higher-order functions is to reduce redundant code. Let's say you wanted some methods that could raise someone's salaries by various factors. Without creating a higher-order function, From 6fefeb9bb018ff59592638d0ce2c8967845c39ca Mon Sep 17 00:00:00 2001 From: Red Liu Date: Sat, 8 Jun 2019 11:03:27 +0800 Subject: [PATCH 0598/3174] Fix translations of class for zh-cn --- _zh-cn/tour/classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/tour/classes.md b/_zh-cn/tour/classes.md index e916677681..4e7ee73bc9 100644 --- a/_zh-cn/tour/classes.md +++ b/_zh-cn/tour/classes.md @@ -19,7 +19,7 @@ prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-inter Scala中的类是用于创建对象的蓝图,其中包含了方法、常量、变量、类型、对象、特质、类,这些统称为成员。类型、对象和特质将在后面的文章中介绍。 ## 类定义 -一个最简的类的定义就是关键字`class`+标识符,类名必须是大写。 +一个最简的类的定义就是关键字`class`+标识符,类名首字母应大写。 ```tut class User @@ -69,7 +69,7 @@ println(point2.y) // prints 2 这样的做法在实践中有利于使得表达明确无误。 ## 私有成员和Getter/Setter语法 -成员默认是公有(`public`)的。使用`private`访问修饰符可以在函数外部隐藏它们。 +成员默认是公有(`public`)的。使用`private`访问修饰符可以在类外部隐藏它们。 ```tut class Point { private var _x = 0 From d7d2d9b5d3893e50c87c14565dec66f8fb7e8a51 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Sun, 9 Jun 2019 11:19:51 -0400 Subject: [PATCH 0599/3174] Remove feedback section from Scalameta post Gitter link is a 404 not found --- _sips/sips/2016-09-09-inline-meta.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/_sips/sips/2016-09-09-inline-meta.md b/_sips/sips/2016-09-09-inline-meta.md index 803d6dfc05..3aae1b3fed 100644 --- a/_sips/sips/2016-09-09-inline-meta.md +++ b/_sips/sips/2016-09-09-inline-meta.md @@ -26,9 +26,6 @@ We did our best to extensively evaluate the design space and comprehensively doc As a result, this is going to be a very long read. If you're just interested in getting a quick idea of the proposal, you can read just the ["Intuition"][Intuition] section. -If you have any questions, feedback or ideas regarding this document, use the link provided -in the ["Feedback"][FeedbackSection] section to join the public discussion. - ## Motivation Def macros and macro annotations have become an integral @@ -71,7 +68,6 @@ and coming up with a lightweight declaration syntax. In this document, we presen * [Out of scope](#out-of-scope) * [Conclusion](#conclusion) * [Credits](#credits) - * [Feedback](#feedback) ## Intuition @@ -983,12 +979,6 @@ Tamer Mohammed Abdul-Radi, David Dudson, Takeshi D. Itoh, Oleksandr Olgashko and The prototype of IntelliJ integration was developed by Mikhail Mutcianko. -## Feedback - -In order to centralize the discussion, post your feedback and ideas to [http://gitter.im/scalameta/sips][FeedbackWebsite]. -Once we submit this document as a full-fledged SIP, we will update this section to include the official discussion forum -mandated by the SIP process. - ## References 1. [Prototype of scalac integration][PrototypeScalac] @@ -1019,8 +1009,6 @@ mandated by the SIP process. [AnonymousTypeProviders]: http://docs.scala-lang.org/overviews/macros/typeproviders.html#anonymous-type-providers [ExtractorMacros]: https://docs.scala-lang.org/overviews/macros/extractors.html [AnnotationsTypecheck]: https://github.com/scalamacros/paradise/issues/75 -[FeedbackSection]: #feedback -[FeedbackWebsite]: http://gitter.im/scalameta/sips [AppendixInteraction]: https://gist.github.com/xeno-by/e26a904051a171e4bc8b9096630220a7 [AppendixExpansion]: https://gist.github.com/xeno-by/5dde62aedcc23afc85ecf4d795ac67c2 [AppendixMeta]: https://gist.github.com/xeno-by/9741ce7532cb30368b3753521bbfce4e From dbab980783ce676f59f616ad815e237ec417d12e Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Fri, 7 Jun 2019 08:50:51 -0400 Subject: [PATCH 0600/3174] Add generating Scaladoc --- _overviews/scaladoc/generate.md | 55 +++++++++++++++++++++++++++++++++ _overviews/scaladoc/overview.md | 5 +-- 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 _overviews/scaladoc/generate.md diff --git a/_overviews/scaladoc/generate.md b/_overviews/scaladoc/generate.md new file mode 100644 index 0000000000..a57e4cb0cb --- /dev/null +++ b/_overviews/scaladoc/generate.md @@ -0,0 +1,55 @@ +--- +layout: multipage-overview +title: Generating Scaladoc + +discourse: true + +partof: scaladoc +overview-name: Scaladoc + +num: 4 + +permalink: /overviews/scaladoc/:title.html +--- + +There are two ways to generate API documentation in HTML from your Scala code. Those options are: + +* use sbt to do it, +* use the scaladoc command-line tool. + +## Using sbt + +The easiest and most commonly used way to generate API documentation from your Scala code is with the build tool [sbt](https://www.scala-sbt.org). + +From the sbt console, run Scaladoc by simply running the `doc` task: + + > doc + [info] Main Scala API documentation to target/scala-2.12/api... + [info] model contains 1 documentable templates + [info] Main Scala API documentation successful. + [success] Total time: 20 s + +The HTML documentation will show up in the respective `target/` directory (or directories for builds with multiple projects) that sbt prints to the console output. + +For more information on using sbt on your system, see the [download instructions](https://www.scala-lang.org/download/) for [getting started with Scala and sbt on the command line]({{site.baseurl}}/getting-started-sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.html). + +For additional information about configuring Scaladoc in sbt, see the [Generate API documentation](https://www.scala-sbt.org/1.x/docs/Howto-Scaladoc.html) section of the sbt reference manual. + +## Using scaladoc command + +If you use Scala commands directly to start a console with `scala` or compile with `scalac`, then you should have a `scaladoc` command-line utility, as well. This is a more advanced and less commonly used method of generating Scaladoc. + + $ scaladoc src/main/scala/App.scala + model contains 1 documentable templates + +This will put the HTML in the current directory. This is probably not what you want. It's preferable to output to a subdirectory. To specify a different target directory, use the `-d` commmand-line option: + + $ scaladoc -d build/ src/main/scala/App.scala + +For more information on the `scaladoc` command and what other command-line options it supports, see the [scaladoc man page](https://www.scala-lang.org/files/archive/nightly/docs/manual/html/scaladoc.html). + +This command is harder to operate with more complex projects containing both multiple Scala source files and library dependencies. This is why using sbt (see above) is easier and better suited for generating Scaladoc. + +The Scaladoc command exists because it precedied the development of sbt, but also because it is useful to the Scala development team with studying bug reports for Scaladoc. + +More information on directly using the Scala commands, like `scaladoc`, is discussed at [your first lines of Scala](https://www.scala-lang.org/documentation/your-first-lines-of-scala.html). diff --git a/_overviews/scaladoc/overview.md b/_overviews/scaladoc/overview.md index efe893b729..b31aea8ef5 100644 --- a/_overviews/scaladoc/overview.md +++ b/_overviews/scaladoc/overview.md @@ -17,10 +17,11 @@ system that lives in the comments of Scala source code and which generates documentation related to the code structure within which it is written. It is based on other comment based documentation systems like Javadoc. -There are two flavors of Scaladoc documentation: +There are three aspects of Scaladoc documentation: - **[Using the Scaladoc interface]({{ site.baseurl }}/overviews/scaladoc/interface.html)** – how to navigate and use generated Scaladoc documentation to learn more about a library. - - **[Generating documentation for your library with Scaladoc]({{ site.baseurl }}/overviews/scaladoc/for-library-authors.html)** – how to use Scaladoc to generate documentation for your library. + - **[Scaladoc for Library Authors]({{ site.baseurl }}/overviews/scaladoc/for-library-authors.html)** – how to add Scaladoc comments to generate documentation for your library. + - **[Generating documentation for your library with Scaladoc]({{ site.baseurl }}/overviews/scaladoc/generate.html)** – how to use Scaladoc to generate documentation for your library. ### Contributing to Scaladoc From 7b46f87893a3267a6eac82fec10ae38526996ea6 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Sun, 9 Jun 2019 08:55:24 -0400 Subject: [PATCH 0601/3174] Fix typos and spellings on Scaladoc page --- _overviews/scaladoc/generate.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/scaladoc/generate.md b/_overviews/scaladoc/generate.md index a57e4cb0cb..d50b19c5b7 100644 --- a/_overviews/scaladoc/generate.md +++ b/_overviews/scaladoc/generate.md @@ -42,7 +42,7 @@ If you use Scala commands directly to start a console with `scala` or compile wi $ scaladoc src/main/scala/App.scala model contains 1 documentable templates -This will put the HTML in the current directory. This is probably not what you want. It's preferable to output to a subdirectory. To specify a different target directory, use the `-d` commmand-line option: +This will put the HTML in the current directory. This is probably not what you want. It's preferable to output to a subdirectory. To specify a different target directory, use the `-d` command-line option: $ scaladoc -d build/ src/main/scala/App.scala @@ -50,6 +50,6 @@ For more information on the `scaladoc` command and what other command-line optio This command is harder to operate with more complex projects containing both multiple Scala source files and library dependencies. This is why using sbt (see above) is easier and better suited for generating Scaladoc. -The Scaladoc command exists because it precedied the development of sbt, but also because it is useful to the Scala development team with studying bug reports for Scaladoc. +The Scaladoc command exists because it preceded the development of sbt, but also because it is useful to the Scala development team with studying bug reports for Scaladoc. More information on directly using the Scala commands, like `scaladoc`, is discussed at [your first lines of Scala](https://www.scala-lang.org/documentation/your-first-lines-of-scala.html). From af88f6563bbe4db334c8c7077bfca0146a8c5b14 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 9 Jun 2019 08:59:36 -0400 Subject: [PATCH 0602/3174] Avoid confusion about sbt on Scaladoc page --- _overviews/scaladoc/generate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scaladoc/generate.md b/_overviews/scaladoc/generate.md index d50b19c5b7..4c26f39a08 100644 --- a/_overviews/scaladoc/generate.md +++ b/_overviews/scaladoc/generate.md @@ -21,7 +21,7 @@ There are two ways to generate API documentation in HTML from your Scala code. The easiest and most commonly used way to generate API documentation from your Scala code is with the build tool [sbt](https://www.scala-sbt.org). -From the sbt console, run Scaladoc by simply running the `doc` task: +In the sbt shell, generate Scaladoc by running `doc`: > doc [info] Main Scala API documentation to target/scala-2.12/api... From dbbd5f0db67db746d0356b3d8caec835d7cc6fe7 Mon Sep 17 00:00:00 2001 From: Akhtyam Sakaev Date: Mon, 10 Jun 2019 03:36:03 +0300 Subject: [PATCH 0603/3174] Fix typo --- _includes/footer.html | 2 +- _overviews/FAQ/collections.md | 6 +++--- _overviews/FAQ/context-bounds.md | 2 +- _overviews/FAQ/finding-implicits.md | 2 +- _overviews/FAQ/finding-symbols.md | 2 +- .../collections/migrating-from-scala-27.md | 2 +- .../core/architecture-of-scala-collections.md | 4 ++-- .../binary-compatibility-of-scala-releases.md | 4 ++-- _overviews/core/collections-migration-213.md | 2 +- _overviews/core/futures.md | 6 +++--- _overviews/core/implicit-classes.md | 4 ++-- _overviews/macros/blackbox-whitebox.md | 2 +- _overviews/macros/changelog211.md | 4 ++-- .../parallel-collections/architecture.md | 6 +++--- _overviews/quasiquotes/definition-details.md | 8 +++---- _overviews/quasiquotes/expression-details.md | 2 +- _overviews/quasiquotes/intro.md | 4 ++-- _overviews/quasiquotes/terminology.md | 2 +- _overviews/quasiquotes/type-details.md | 4 ++-- ...inary-compatibility-for-library-authors.md | 10 ++++----- .../2016-09-20-sip-20th-september-minutes.md | 4 ++-- _sips/minutes/2016-11-29-sip-minutes.md | 2 +- _sips/minutes/2017-02-14-sip-minutes.md | 4 ++-- _sips/minutes/2017-05-08-sip-minutes.md | 4 ++-- _sips/minutes/2018-05-18-sip-minutes.md | 6 +++--- _sips/minutes/2018-08-30-sip-minutes.md | 6 +++--- _sips/sip-tutorial.md | 4 ++-- .../2010-01-22-named-and-default-arguments.md | 20 +++++++++--------- _sips/sips/2010-01-22-scala-2-8-arrays.md | 10 ++++----- _sips/sips/2011-10-13-uncluttering-control.md | 2 +- _sips/sips/2012-01-21-futures-promises.md | 8 +++---- ...-05-31-improved-lazy-val-initialization.md | 6 +++--- _sips/sips/2014-06-27-42.type.md | 4 ++-- _sips/sips/2016-01-11-static-members.md | 6 +++--- ...07-priority-based-infix-type-precedence.md | 2 +- _sips/sips/2017-09-20-opaque-types.md | 4 ++-- .../2018-07-31-interpolation-quote-escape.md | 8 +++---- _tour/automatic-closures.md | 2 +- _tour/traits.md | 2 +- contribute.md | 2 +- ...g-a-scala-project-with-intellij-and-sbt.md | 12 +++++------ ...ting-scala-with-sbt-on-the-command-line.md | 6 +++--- ...les-in-scala-impressions-and-statistics.md | 2 +- ...png => forward_backward_compatibility.png} | Bin 44 files changed, 102 insertions(+), 102 deletions(-) rename resources/images/library-author-guide/{fowards_backwards_compatibility.png => forward_backward_compatibility.png} (100%) diff --git a/_includes/footer.html b/_includes/footer.html index 6d233e5c8e..eb43f821b8 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -53,7 +53,7 @@ - + {% if page.layout == "sips"%} diff --git a/_overviews/FAQ/collections.md b/_overviews/FAQ/collections.md index b044191727..d78a2340a9 100644 --- a/_overviews/FAQ/collections.md +++ b/_overviews/FAQ/collections.md @@ -167,7 +167,7 @@ The operation is meant to traverse all elements of the collection, and apply the given operation f to each element. The application is done for its side effect only; in fact any function result of f is discarded by foreach. -Traversible objects can be finite or infinite. An example of an infinite +Traversable objects can be finite or infinite. An example of an infinite traversable object is the stream of natural numbers `Stream.from(0)`. The method `hasDefiniteSize` indicates whether a collection is possibly infinite. If `hasDefiniteSize` returns true, the collection is certainly finite. If it @@ -250,7 +250,7 @@ it. Also available are some traits with further refinements, such as * `LinearSeq` -- A trait for linear sequences, with efficient time for `isEmpty`, `head` and `tail`. * `immutable.LinearSeq` - * `immutable.List` -- An immutable, singlely-linked, list implementation. + * `immutable.List` -- An immutable, singly-linked, list implementation. * `immutable.Stream` -- A lazy-list. Its elements are only computed on-demand, but memoized (kept in memory) afterwards. It can be theoretically infinite. * `mutable.LinearSeq` * `mutable.DoublyLinkedList` -- A list with mutable `prev`, `head` (`elem`) and `tail` (`next`). @@ -343,7 +343,7 @@ it. Also available are some traits with further refinements, such as This was done to achieve maximum code reuse. The concrete *generic* implementation for classes with a certain structure (a traversable, a map, etc) is done in the Like classes. The classes intended for general consumption, -then, override selected methods that can be optmized. +then, override selected methods that can be optimized. * What the companion methods are for (e.g. List.companion)? diff --git a/_overviews/FAQ/context-bounds.md b/_overviews/FAQ/context-bounds.md index fa0beaaaa6..ad79c2990d 100644 --- a/_overviews/FAQ/context-bounds.md +++ b/_overviews/FAQ/context-bounds.md @@ -40,7 +40,7 @@ Another very common example in the library is a bit more complex: def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b) -Here, `implicitly` is used to retrive the implicit value we want, one of type +Here, `implicitly` is used to retrieve the implicit value we want, one of type `Ordering[A]`, which class defines the method `compare(a: A, b: A): Int`. We'll see another way of doing this below. diff --git a/_overviews/FAQ/finding-implicits.md b/_overviews/FAQ/finding-implicits.md index 015216f28c..69a1c4a49e 100644 --- a/_overviews/FAQ/finding-implicits.md +++ b/_overviews/FAQ/finding-implicits.md @@ -219,7 +219,7 @@ by a `t` that is not implicit, so no implicit `T` is in scope. The invocation of `f` was enabled by importing from `Y.X.`. But it is not convenient to require an import to access implicit values -providied by a package. +provided by a package. If an implicit value is not found in lexical scope, implicit search continues in implicit scope. diff --git a/_overviews/FAQ/finding-symbols.md b/_overviews/FAQ/finding-symbols.md index 0512856737..aca08ae12f 100644 --- a/_overviews/FAQ/finding-symbols.md +++ b/_overviews/FAQ/finding-symbols.md @@ -160,7 +160,7 @@ object of type that is receiving the method. For example, consider `"a" -> 1`. W to look for an implicit which works on `"a"`, and so it can take `String`, one of its supertypes (`AnyRef` or `Any`) or a type parameter. In this case, we find `implicit final class ArrowAssoc[A](private val self: A)` which makes this implicit -avaialable on all types. +available on all types. Other implicit conversions may be visible in your scope depending on imports, extended types or self-type annotations. See [Finding implicits](finding-implicits.html) for details. diff --git a/_overviews/collections/migrating-from-scala-27.md b/_overviews/collections/migrating-from-scala-27.md index c2c2bd9935..87f557ca4f 100644 --- a/_overviews/collections/migrating-from-scala-27.md +++ b/_overviews/collections/migrating-from-scala-27.md @@ -41,7 +41,7 @@ Generally, the old functionality of Scala 2.7 collections has been left in place There are two parts of the old libraries which have been replaced wholesale, and for which deprecation warnings were not feasible. -1. The previous `scala.collection.jcl` package is gone. This package tried to mimick some of the Java collection library design in Scala, but in doing so broke many symmetries. Most people who wanted Java collections bypassed `jcl` and used `java.util` directly. Scala 2.8 offers automatic conversion mechanisms between both collection libraries in the [JavaConversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html) object which replaces the `jcl` package. +1. The previous `scala.collection.jcl` package is gone. This package tried to mimic some of the Java collection library design in Scala, but in doing so broke many symmetries. Most people who wanted Java collections bypassed `jcl` and used `java.util` directly. Scala 2.8 offers automatic conversion mechanisms between both collection libraries in the [JavaConversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html) object which replaces the `jcl` package. 2. Projections have been generalized and cleaned up and are now available as views. It seems that projections were used rarely, so not much code should be affected by this change. So, if your code uses either `jcl` or projections there might be some minor rewriting to do. diff --git a/_overviews/core/architecture-of-scala-collections.md b/_overviews/core/architecture-of-scala-collections.md index 5cb894f1e9..3a2dcf6fb4 100644 --- a/_overviews/core/architecture-of-scala-collections.md +++ b/_overviews/core/architecture-of-scala-collections.md @@ -907,7 +907,7 @@ return with `None`. The combined selection over an option value `opt` is elegantly expressed using `opt.flatMap(x => f(x))`. When applied to an optional value that is `None`, it returns `None`. Otherwise `opt` is `Some(x)` and the function `f` is applied to the encapsulated value `x`, -yielding a new option, which is returned by the flatmap. +yielding a new option, which is returned by the flatMap. The next two methods to implement for a mutable map are `+=` and `-=`. In the implementation of `PrefixMap`, these are defined in terms of two @@ -948,7 +948,7 @@ using the map's `+=` method. For immutable maps, the non-destructive element addition method `+` is used instead of method `+=`. Sets work in the same way. -However, in all these cases, to build the right kind of colletion +However, in all these cases, to build the right kind of collection you need to start with an empty collection of that kind. This is provided by the `empty` method, which is the last method defined in `PrefixMap`. This method simply returns a fresh `PrefixMap`. diff --git a/_overviews/core/binary-compatibility-of-scala-releases.md b/_overviews/core/binary-compatibility-of-scala-releases.md index c12db85230..749a31f6cc 100644 --- a/_overviews/core/binary-compatibility-of-scala-releases.md +++ b/_overviews/core/binary-compatibility-of-scala-releases.md @@ -11,8 +11,8 @@ When two versions of Scala are binary compatible, it is safe to compile your pro We check binary compatibility automatically with [MiMa](https://github.com/lightbend/migration-manager). We strive to maintain a similar invariant for the `behavior` (as opposed to just linkage) of the standard library, but this is not checked mechanically (Scala is not a proof assistant so this is out of reach for its type system). -#### Forwards and Back -We distinguish forwards and backwards compatibility (think of these as properties of a sequence of versions, not of an individual version). Maintaining backwards compatibility means code compiled on an older version will link with code compiled with newer ones. Forwards compatibility allows you to compile on new versions and run on older ones. +#### Forward and Back +We distinguish forward and backward compatibility (think of these as properties of a sequence of versions, not of an individual version). Maintaining backwards compatibility means code compiled on an older version will link with code compiled with newer ones. Forward compatibility allows you to compile on new versions and run on older ones. Thus, backwards compatibility precludes the removal of (non-private) methods, as older versions could call them, not knowing they would be removed, whereas forwards compatibility disallows adding new (non-private) methods, because newer programs may come to depend on them, which would prevent them from running on older versions (private methods are exempted here as well, as their definition and call sites must be in the same compilation unit). diff --git a/_overviews/core/collections-migration-213.md b/_overviews/core/collections-migration-213.md index 71b9cbf815..f2b33ae434 100644 --- a/_overviews/core/collections-migration-213.md +++ b/_overviews/core/collections-migration-213.md @@ -29,7 +29,7 @@ The most important changes in the Scala 2.13 collections library are: The [scala-collection-compat](https://github.com/scala/scala-collection-compat) is a library released for 2.11, 2.12 and 2.13 that provides some of the new APIs from Scala 2.13 for the older versions. This simplifies cross-building projects. -The module also provides [migratrion rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. +The module also provides [migration rules](https://github.com/scala/scala-collection-compat#migration-tool) for [scalafix](https://scalacenter.github.io/scalafix/docs/users/installation.html) that can update a project's source code to work with the 2.13 collections library. ## scala.Seq, varargs and scala.IndexedSeq migration diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index c753fca53d..a0eea92daf 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -665,16 +665,16 @@ multiple `andThen` calls are ordered, as in the following example which stores the recent posts from a social network to a mutable set and then renders all the posts to the screen: - val allposts = mutable.Set[String]() + val allPosts = mutable.Set[String]() Future { session.getRecentPosts } andThen { - case Success(posts) => allposts ++= posts + case Success(posts) => allPosts ++= posts } andThen { case _ => clearAll() - for (post <- allposts) render(post) + for (post <- allPosts) render(post) } In summary, the combinators on futures are purely functional. diff --git a/_overviews/core/implicit-classes.md b/_overviews/core/implicit-classes.md index 9b3d819d87..501724cdb4 100644 --- a/_overviews/core/implicit-classes.md +++ b/_overviews/core/implicit-classes.md @@ -72,8 +72,8 @@ Implicit classes have the following restrictions: implicit class RichDate(date: java.util.Date) // OK! - implicit class Indexer[T](collecton: Seq[T], index: Int) // BAD! - implicit class Indexer[T](collecton: Seq[T])(implicit index: Index) // OK! + implicit class Indexer[T](collection: Seq[T], index: Int) // BAD! + implicit class Indexer[T](collection: Seq[T])(implicit index: Index) // OK! While it's possible to create an implicit class with more than one non-implicit argument, such classes diff --git a/_overviews/macros/blackbox-whitebox.md b/_overviews/macros/blackbox-whitebox.md index aade9367f2..f243e4ac74 100644 --- a/_overviews/macros/blackbox-whitebox.md +++ b/_overviews/macros/blackbox-whitebox.md @@ -29,7 +29,7 @@ In fact, macros became an important part of our ecosystem so quickly that just a Macro flavors are plentiful, so we decided to carefully examine them to figure out which ones should be put in the standard. This entails answering a few important questions. Why are macros working so well? Why do people use them? Our hypothesis is that this happens because the hard to comprehend notion of metaprogramming expressed in def macros piggybacks on the familiar concept of a typed method call. Thanks to that, the code that users write can absorb more meaning without becoming bloated or losing -compehensibility. +comprehensibility. ## Blackbox and whitebox macros diff --git a/_overviews/macros/changelog211.md b/_overviews/macros/changelog211.md index 0b91acfb4c..c4753e56ea 100644 --- a/_overviews/macros/changelog211.md +++ b/_overviews/macros/changelog211.md @@ -60,7 +60,7 @@ Quasiquotes is the single most impressive upgrade for reflection and macros in S 16) **[knownDirectSubclasses is deemed to be officially broken](https://issues.scala-lang.org/browse/SI-7046)**. A lot of users who tried to traverse sealed hierarchies of classes have noticed that `ClassSymbol.knownDirectSubclasses` only works if invocations of their macros come after the definitions of those hierarchies in Scala's compilation order. For instance, if a sealed hierarchy is defined in the bottom of a source file, and a macro application is written in the top of the file, then knownDirectSubclasses will return an empty list. This is an issue that is deeply rooted in Scala's internal architecture, and we can't provide a fix for it in the near future. -17) **showCode**. Along with `Tree.toString` that prints Scala-ish source code and `showRaw(tree)` that prints internal structures of trees, we now have `showCode` that prints compileable Scala source code corresponding to the provided tree, courtesy of Vladimir Nikolaev, who's done an amazing work of bringing this to life. We plan to eventually replace `Tree.toString` with `showCode`, but in Scala 2.11.0 these are two different methods. +17) **showCode**. Along with `Tree.toString` that prints Scala-ish source code and `showRaw(tree)` that prints internal structures of trees, we now have `showCode` that prints compilable Scala source code corresponding to the provided tree, courtesy of Vladimir Nikolaev, who's done an amazing work of bringing this to life. We plan to eventually replace `Tree.toString` with `showCode`, but in Scala 2.11.0 these are two different methods. 18) **[It is now possible to typecheck in type and pattern modes](https://issues.scala-lang.org/browse/SI-6814)**. A very convenient `Context.typeCheck` and `ToolBox.typeCheck` functionality of Scala 2.10.x had a significant inconvenience - it only worked for expressions, and typechecking something as a type or as a pattern required building dummy expressions. Now `typeCheck` has the mode parameter that take case of that difficulty. @@ -170,7 +170,7 @@ Quasiquotes is the single most impressive upgrade for reflection and macros in S // provides a source compatibility stub // in Scala 2.10.x, it will make `import compat._` compile just fine, // even though `c.universe` doesn't have `compat` - // in Scala 2.11.0, it will be ignored, becase `import c.universe._` + // in Scala 2.11.0, it will be ignored, because `import c.universe._` // brings its own `compat` in scope and that one takes precedence private object HasCompat { val compat = ??? }; import HasCompat._ diff --git a/_overviews/parallel-collections/architecture.md b/_overviews/parallel-collections/architecture.md index d5173e915f..487c6deac9 100644 --- a/_overviews/parallel-collections/architecture.md +++ b/_overviews/parallel-collections/architecture.md @@ -37,7 +37,7 @@ terms of two core abstractions-- `Splitter`s and `Combiner`s. ### Splitters The job of a `Splitter`, as its name suggests, is to split a parallel -collection into a non-trival partition of its elements. The basic idea is to +collection into a non-trivial partition of its elements. The basic idea is to split the collection into smaller parts until they are small enough to be operated on sequentially. @@ -55,7 +55,7 @@ subsets of elements of the whole parallel collection. And similar to normal `Iterator`s, a `Splitter` is invalidated after its `split` method is invoked. In general, collections are partitioned using `Splitter`s into subsets of -roughly the same size. In cases where more arbitrarily-sized partions are +roughly the same size. In cases where more arbitrarily-sized partitions are required, in particular on parallel sequences, a `PreciseSplitter` is used, which inherits `Splitter` and additionally implements a precise split method, `psplit`. @@ -82,7 +82,7 @@ and the type of the resulting collection, respectively. _Note:_ Given two `Combiner`s, `c1` and `c2` where `c1 eq c2` is `true` (meaning they're the same `Combiner`), invoking `c1.combine(c2)` always does -nothing and simpy returns the receiving `Combiner`, `c1`. +nothing and simply returns the receiving `Combiner`, `c1`. ## Hierarchy diff --git a/_overviews/quasiquotes/definition-details.md b/_overviews/quasiquotes/definition-details.md index d859b6d136..7d3c38e3cc 100644 --- a/_overviews/quasiquotes/definition-details.md +++ b/_overviews/quasiquotes/definition-details.md @@ -216,7 +216,7 @@ Abstract type definitions have the following shape: low: universe.Tree = high: universe.Tree = List[T] -Whenever one of the bounds isn\'t available, it gets represented as an [empty tree](expression-details.html#empty). Here each of the type arguments is a type definition itself. +Whenever one of the bounds isn't available, it gets represented as an [empty tree](expression-details.html#empty). Here each of the type arguments is a type definition itself. Another form of type definition is a type alias: @@ -259,7 +259,7 @@ Alternatively you can also deconstruct arguments, separating implicit and non-im implparams: List[universe.ValDef] = List(implicit val y: Int = _) body: universe.Tree = x.$plus(y) -This way of handling parameters will still work if the method doesn\'t have any implicit parameters and `implparams` will get extracted as an empty list: +This way of handling parameters will still work if the method doesn't have any implicit parameters and `implparams` will get extracted as an empty list: scala> val q"def g(...$paramss)(implicit ..$implparams) = $rhs" = q"def g(x: Int)(y: Int) = x + y" @@ -344,7 +344,7 @@ Packages are a fundamental primitive to organize source code. You can express th } }) -Quasiquotes don\'t support the inline package definition syntax that is usually used in the header of the source file (but it's equivalent to the supported one in terms of ASTs). +Quasiquotes don't support the inline package definition syntax that is usually used in the header of the source file (but it's equivalent to the supported one in terms of ASTs). ## Package Object Definition @@ -352,7 +352,7 @@ Package objects are a cross between packages and object: q"package object $tname extends { ..$earlydefns } with ..$parents { $self => ..$stats }" -All of the handling properties are equivalent to those of objects apart from the fact that they don\'t have [modifiers](#modifiers). +All of the handling properties are equivalent to those of objects apart from the fact that they don't have [modifiers](#modifiers). Even though package and regular objects seem to be quite similar syntactically, they don't match one another: diff --git a/_overviews/quasiquotes/expression-details.md b/_overviews/quasiquotes/expression-details.md index 371b7508dc..19cbc5ee67 100644 --- a/_overviews/quasiquotes/expression-details.md +++ b/_overviews/quasiquotes/expression-details.md @@ -290,7 +290,7 @@ At the moment, tuples are only supported up to an arity of 22, but this is just scala> val `tuple 23 supported?` = definitions.TupleClass(23) != NoSymbol tuple 23 supported?: Boolean = false -Despited the fact that `Tuple1` class exists there is no built-in syntax for it. Single parens around expression do not change its meaning: +Despite the fact that `Tuple1` class exists there is no built-in syntax for it. Single parens around expression do not change its meaning: scala> val inparens = q"(a)" inparens: universe.Ident = a diff --git a/_overviews/quasiquotes/intro.md b/_overviews/quasiquotes/intro.md index fbebb00f77..274a0d936f 100644 --- a/_overviews/quasiquotes/intro.md +++ b/_overviews/quasiquotes/intro.md @@ -73,7 +73,7 @@ Each of these contexts is covered by a separate interpolator: tq | [types]({{ site.baseurl }}/overviews/quasiquotes/syntax-summary.html#types) pq | [patterns]({{ site.baseurl }}/overviews/quasiquotes/syntax-summary.html#patterns) -Syntactical similarity between different contexts doesn\'t imply similarity between underlying trees: +Syntactical similarity between different contexts doesn't imply similarity between underlying trees: scala> println(q"List[Int]" equalsStructure tq"List[Int]") false @@ -110,7 +110,7 @@ Unquote splicing is a way to unquote a variable number of elements: scala> val fab = q"f(..$ab)" fab: universe.Tree = f(a, b) -Dots before the unquotee annotate indicate a degree of flattenning and are called a *splicing rank*. `..$` expects the argument to be an `Iterable[Tree]` and `...$` expects an `Iterable[Iterable[Tree]]`. +Dots before the unquotee annotate indicate a degree of flattening and are called a *splicing rank*. `..$` expects the argument to be an `Iterable[Tree]` and `...$` expects an `Iterable[Iterable[Tree]]`. Splicing can easily be combined with regular unquotation: diff --git a/_overviews/quasiquotes/terminology.md b/_overviews/quasiquotes/terminology.md index d528551c4c..3b153a2274 100644 --- a/_overviews/quasiquotes/terminology.md +++ b/_overviews/quasiquotes/terminology.md @@ -19,6 +19,6 @@ permalink: /overviews/quasiquotes/:title.html * **Tree deconstruction** refers to usages of quasiquotes as patterns to structurally tear apart trees. * **Unquoting** is a way of either putting things in or extracting things out of quasiquotes. Can be performed with `$` syntax within a quasiquote. * **Unquote splicing** (or just splicing) is another form of unquoting that flattens contents of the unquotee into a tree. Can be performed with either `..$` or `...$` syntax. -* **Rank** is a degree of flattenning of unquotee: `rank($) == 0`, `rank(..$) == 1`, `rank(...$) == 2`. +* **Rank** is a degree of flattening of unquotee: `rank($) == 0`, `rank(..$) == 1`, `rank(...$) == 2`. * [**Lifting**](lifting.html) is a way to unquote non-tree values and transform them into trees with the help of the `Liftable` typeclass. * [**Unlifting**](unlifting.html) is a way to unquote non-tree values out of quasiquote patterns with the help of the `Unliftable` typeclass. diff --git a/_overviews/quasiquotes/type-details.md b/_overviews/quasiquotes/type-details.md index b9d6929f22..9258d5928e 100644 --- a/_overviews/quasiquotes/type-details.md +++ b/_overviews/quasiquotes/type-details.md @@ -92,7 +92,7 @@ Lastly and [similarly to expressions](expression-details.html#super-and-this) on ## Applied Type -Instantiations of parametized types can be expressed with the help of applied types (type-level equivalent of type application): +Instantiations of parameterized types can be expressed with the help of applied types (type-level equivalent of type application): scala> val applied = tq"Foo[A, B]" applied: universe.Tree = Foo[A, B] @@ -151,7 +151,7 @@ Existential types consist of a type tree and a list of definitions: tpt: universe.Tree = List[T] defns: List[universe.MemberDef] = List(type T) -Alternatively there is also an underscrore notation: +Alternatively there is also an underscore notation: scala> val tq"$tpt forSome { ..$defns }" = tq"List[_]" tpt: universe.Tree = List[_$1] diff --git a/_overviews/tutorials/binary-compatibility-for-library-authors.md b/_overviews/tutorials/binary-compatibility-for-library-authors.md index d8cf3002da..655317c95d 100644 --- a/_overviews/tutorials/binary-compatibility-for-library-authors.md +++ b/_overviews/tutorials/binary-compatibility-for-library-authors.md @@ -79,23 +79,23 @@ Two library versions are **Binary Compatible** with each other if the compiled b ### Relationship between source and binary compatibility While breaking source compatibility often results in binary incompatibilities as well, they are actually orthogonal -- breaking one does not imply breaking the other. -#### Forwards and Backwards Compatibility +#### Forward and Backward Compatibility There are two "directions" when we describe compatibility of a library release: -**Backwards Compatible** means that a newer library version can be used in an environment where an older version is expected. When talking about binary and source compatibility, +**Backward Compatible** means that a newer library version can be used in an environment where an older version is expected. When talking about binary and source compatibility, this is the common and implied direction. -**Forwards Compatible** means that an older library can be used in an environment where a newer version is expected. +**Forward Compatible** means that an older library can be used in an environment where a newer version is expected. Forward compatibility is generally not upheld for libraries. Let's look at an example where library `A v1.0.0` is compiled with library `C v1.1.0`. -![Forwards and Backwards Compatibility]({{ site.baseurl }}/resources/images/library-author-guide/fowards_backwards_compatibility.png){: style="width: 65%; margin: auto; display: block"} +![Forward and Backward Compatibility]({{ site.baseurl }}/resources/images/library-author-guide/forward_backward_compatibility.png){: style="width: 65%; margin: auto; display: block"} `C v1.1.0 ` is **Forwards Binary Compatible** with `v1.0.0` if we can use `v1.0.0`'s JAR at runtime instead of `v1.1.0`'s JAR without any linkage errors. -`C v1.2.0 ` is **Backwards Binary Compatible** with `v1.1.0` if we can use `v1.2.0`'s JAR at runtime instead of `v1.1.0`'s JAR without any linkage errors. +`C v1.2.0 ` is **Backward Binary Compatible** with `v1.1.0` if we can use `v1.2.0`'s JAR at runtime instead of `v1.1.0`'s JAR without any linkage errors. ## Why binary compatibility matters diff --git a/_sips/minutes/2016-09-20-sip-20th-september-minutes.md b/_sips/minutes/2016-09-20-sip-20th-september-minutes.md index fe5bd46fe5..584975a64d 100644 --- a/_sips/minutes/2016-09-20-sip-20th-september-minutes.md +++ b/_sips/minutes/2016-09-20-sip-20th-september-minutes.md @@ -154,12 +154,12 @@ issue, two things are required: The second option is not feasible because unsigned numbers are AnyVals, and they can only extend `Object`. Working around this in the backend is, in Sébastien's opinion, not an exciting adventure to embark on: a lot of patches and quirky -fixes are required in the compiler. Sébastien, recognizing his unability to fix +fixes are required in the compiler. Sébastien, recognizing his inability to fix the issue, recommends to reject the proposal. Josh needs to leave. Eugene wonders if these problems are only JVM-specific. Sébastien replies that both yes and no, and he confirms that unsigned integers -will be implemented in Scalajs alone, so the implementation won't be +will be implemented in Scala.js alone, so the implementation won't be platform-independent. Eugene is interested in knowing if there will be any code duplication in the implementation, and Sébastien doesn't think so, since Scala Native implements unsigned integer in a different way. diff --git a/_sips/minutes/2016-11-29-sip-minutes.md b/_sips/minutes/2016-11-29-sip-minutes.md index a3736d79a0..c970ddb730 100644 --- a/_sips/minutes/2016-11-29-sip-minutes.md +++ b/_sips/minutes/2016-11-29-sip-minutes.md @@ -66,7 +66,7 @@ The main motivation is to prepare for inline. Inline won't work very well withou ### [SIP-NN:Static](https://github.com/scala/docs.scala-lang/pull/491/files) -Iulian says too much code is generated by annotations. We could solve name clashes the way ScalaJS does by specifying the exported name. How can we wake code generation predictable without looking at annotations? How do we emit public static field without accessors? Having everything emitted as static and object where possible is going to simplify reasoning about how things are initialized. +Iulian says too much code is generated by annotations. We could solve name clashes the way Scala.js does by specifying the exported name. How can we wake code generation predictable without looking at annotations? How do we emit public static field without accessors? Having everything emitted as static and object where possible is going to simplify reasoning about how things are initialized. How should a user decide when to use static? It is platform-dependent. diff --git a/_sips/minutes/2017-02-14-sip-minutes.md b/_sips/minutes/2017-02-14-sip-minutes.md index a1d8785ba0..ac54f216d3 100644 --- a/_sips/minutes/2017-02-14-sip-minutes.md +++ b/_sips/minutes/2017-02-14-sip-minutes.md @@ -147,7 +147,7 @@ The current SIP tries to make it behave as expected by the users in common cases **Jorge** We have to pass here both on this proposal as is right now but I think this could be dangerous in the case where we don't have an implementation for Scalac because maybe the details change and assume something in Scalac that the SIP is not able to predict or guard against it. Let's wait until next month and I will double check whether this is possible or not. Then I will get in touch with the Lightbend team to see whether this can be implemented or not. We'll decide in a month whether it should be accepted. -**Sébastien** ScalaJS already implemented it under another name but it's supposed to be conservative with respect to the aesthetic SIP in the sense that things that are allowed now with @jsstatic will also be allowed with @static. @static might open up a little bit more. +**Sébastien** Scala.js already implemented it under another name but it's supposed to be conservative with respect to the aesthetic SIP in the sense that things that are allowed now with @jsstatic will also be allowed with @static. @static might open up a little bit more. **Conclusion** The static SIP proposal has to be implemented in Scala, as it's already present in Dotty. Triplequote (Iulian Dragos and Mirco Dotta) has offered to provide an implementation targeting 2.12.3. @@ -221,7 +221,7 @@ There are multiple use cases covered by this SIP. I think the two most important **Martin** If you don't emit a Scala signature then you can't have a co- or contravariant type parameter because they are only expressed in Scala signatures, in Java it's not there. I don't see how that follows from the current proposal. Also, isn't it platform dependent? -**Sébastien** We do have a Java signature. Scala-JS doesn't disable classfile emission. When you say quickly compile, it uses the classfiles to quickly compile. when you use macros, it will extend from those classfiles. When you use an IDE it reduces the classfiles to identify things. When you use sbt, it uses classfiles to detect the changes. However, they aren't used by the ScalaJS linker. +**Sébastien** We do have a Java signature. Scala.js doesn't disable classfile emission. When you say quickly compile, it uses the classfiles to quickly compile. when you use macros, it will extend from those classfiles. When you use an IDE it reduces the classfiles to identify things. When you use sbt, it uses classfiles to detect the changes. However, they aren't used by the Scala.js linker. **Seth** Does this need to be part of the compiler or can it move forward as a plugin or just as a check performed in MiMa? MiMa just compares two different APIs. Can it have this other job as well: seeing if it does anything outside of the boundaries. diff --git a/_sips/minutes/2017-05-08-sip-minutes.md b/_sips/minutes/2017-05-08-sip-minutes.md index e5d2e52ccf..752873ef1b 100644 --- a/_sips/minutes/2017-05-08-sip-minutes.md +++ b/_sips/minutes/2017-05-08-sip-minutes.md @@ -47,12 +47,12 @@ Minutes were taken by Darja Jovanovic. Proposal aims to introduce new syntax from comprehension for monads to comonads. Martin is the reviewer. He asks others attendees for their opinion on this. Everyone had read the SIP. -**Eugene** referred to original proposal and wishes to see a better motivation for this language feature encouraging use of “plain English” to simplify the use of Scala as practice oriented language. He believes that it could be critical how this SIP can be improved. During the recent conference, organized by Facebook, he spoke with typescript guys that are developing idiomic solutions that would benefit typescript and javascript and allow community users to give their inputs. +**Eugene** referred to original proposal and wishes to see a better motivation for this language feature encouraging use of “plain English” to simplify the use of Scala as practice oriented language. He believes that it could be critical how this SIP can be improved. During the recent conference, organized by Facebook, he spoke with TypeScript guys that are developing idiomatic solutions that would benefit TypeScript and JavaScript and allow community users to give their inputs. Refers to the paper “Denotation” he linked in a proposal, that is not enough for Scala, but a good start. **Jorge** is getting back discussion on voting on this proposal and he mentioned that Josh insisted on more examples and suggestions on motivation of this SIP. -**Eugene** wanted to add more syntax (map and flatmap), but **Martin** opposed to that saying that Scala is quite serious program and needs more reason to add any additional syntax to it. **Martin** would like to see more widespread use of comonadic constructs and Libraries, and before doing that, he wouldn’t consider any further change. **Sebastian** agrees with Martin and says that he doesn’t really understand Josh’s and Eugene’s proposal. **Iulian** agrees that the proposal is quite complicated and he wonders how it can be useful. He believes that it is an interesting research direction, but that it needs more users feedbacks in aim to be included in the Scala, therefore questioning if the proposal should be numbered in the current form. Seth and Adriaan agree with Martin and Iulian. +**Eugene** wanted to add more syntax (map and flatMap), but **Martin** opposed to that saying that Scala is quite serious program and needs more reason to add any additional syntax to it. **Martin** would like to see more widespread use of comonadic constructs and Libraries, and before doing that, he wouldn’t consider any further change. **Sebastian** agrees with Martin and says that he doesn’t really understand Josh’s and Eugene’s proposal. **Iulian** agrees that the proposal is quite complicated and he wonders how it can be useful. He believes that it is an interesting research direction, but that it needs more users feedback in aim to be included in the Scala, therefore questioning if the proposal should be numbered in the current form. Seth and Adriaan agree with Martin and Iulian. **Conclusion** Proposal discarded unanimously. They will send the feedback to the author. diff --git a/_sips/minutes/2018-05-18-sip-minutes.md b/_sips/minutes/2018-05-18-sip-minutes.md index 3f4c390f78..b707f52f73 100644 --- a/_sips/minutes/2018-05-18-sip-minutes.md +++ b/_sips/minutes/2018-05-18-sip-minutes.md @@ -62,7 +62,7 @@ Given the short time and amount of decisions that need to be made, the Committee *Structure* a) Have a **list of changes**, grouped in batches that would be decided within the next year, meeting once a month -b) **Plan** - full and strucutured list of changes that need to be implemented consolidated between the Committee members using a shared a Google doc +b) **Plan** - full and structured list of changes that need to be implemented consolidated between the Committee members using a shared a Google doc c) **Public comments** - each batch should be published on the Contributors thread, for a month at a time in order to have community involved, share their opinion and contribute. Advise was proposed - each thread should clearly point out start and end date of collecting the comments/suggestions. *Organisation* @@ -80,10 +80,10 @@ The above mentioned structure and organisation was gathered throughout the meeti 4. Other: spec, quorum -**Heather** bings up an important question "What about Scala spec" ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. +**Heather** brings up an important question "What about Scala spec" ([YouTube time: 4'49''](https://youtu.be/q2LVmTe9qmU?t=289)) to which **Martin** responds within the next year we should know which features are included as a first priority but that spec should not be left for the last minute. **Miles** ([YouTube time: 8'45](https://youtu.be/q2LVmTe9qmU?t=525))suggested that SIP proposals should include draft specification changes to save time and effort pulling the eventual spec update together. **Martin** ([YouTube time: 37'59''](https://youtu.be/q2LVmTe9qmU?t=2279)) also raised a question about the decision making process, asking if it would be better to change to simple majority when it comes to voting. This was rejected by most of the Members and agreed it should be discussed in a different meeting or time. -**Conclusion** The first batch should be agreed upon, posted on the Contributors thread for public comments. Such discussion should be summaraized and included in the next meeting (22nd June 2018, after ScalaDays NewYork). +**Conclusion** The first batch should be agreed upon, posted on the Contributors thread for public comments. Such discussion should be summarized and included in the next meeting (22nd June 2018, after ScalaDays NewYork). diff --git a/_sips/minutes/2018-08-30-sip-minutes.md b/_sips/minutes/2018-08-30-sip-minutes.md index 30fbc4bc49..48bc21c12f 100644 --- a/_sips/minutes/2018-08-30-sip-minutes.md +++ b/_sips/minutes/2018-08-30-sip-minutes.md @@ -141,7 +141,7 @@ Comments + Interaction with nullary constructors. Currently `class Foo` is interpreted as `class Foo()`. Mutatis mutandis for case class `apply` methods. -**Martin** ([Youtube time: 11.37](https://youtu.be/gnlL4PlstFY?t=688)) mentiones that this proposal also came about due to New collection usecases that surfaced in recent work - showing that without a strict rule there is a high amount of "un-disciplined" use of (). But he agrees with Miles about merging the two proposals together. +**Martin** ([Youtube time: 11.37](https://youtu.be/gnlL4PlstFY?t=688)) mentioned that this proposal also came about due to New collection usecases that surfaced in recent work - showing that without a strict rule there is a high amount of "un-disciplined" use of (). But he agrees with Miles about merging the two proposals together. **Conclusion** **Jorge** takes the task to merge the proposals and extend the motivation. @@ -210,7 +210,7 @@ Discussion: **Josh** ([YouTube time: 27’16’’](https://youtu.be/gnlL4PlstFY?t=1636)) clarifies that in order to replace the libraries one would need a proof of concept, and currently there is none. -**Adriaan** ([YouTube time 30’](https://youtu.be/gnlL4PlstFY?t=1796)) summarises the discussion, pointing out that Committee needs to answer a question *will we support XML in some way* and *waht would be the most "Scala-like" way to do so* and *who will be maintaing it*. +**Adriaan** ([YouTube time 30’](https://youtu.be/gnlL4PlstFY?t=1796)) summarises the discussion, pointing out that Committee needs to answer a question *will we support XML in some way* and *what would be the most "Scala-like" way to do so* and *who will be maintaining it*. **Seth** ([YouTube time 35’57’’](https://youtu.be/gnlL4PlstFY?t=2157)) is under the impression that large portion of XML user base are the ones using it to do generation and rarer to be reading in XML using the existing Scala XML support and asks others to share their impressions. **Martin** re-phrases it as “using XML for pattern matching”. @@ -269,7 +269,7 @@ Counter Proposals - Multiple "def" keywords, one which would mean side-effecting function := for side effects -**Josh** concludes: big point to debate would the language consistency be worth the change to more verbose expresion. +**Josh** concludes: big point to debate would the language consistency be worth the change to more verbose expression. **Iulian** ([You/tube time: ]( https://youtu.be/gnlL4PlstFY?t=2928)) adds that 1. last 5 years Syntax procedure was anyway deprecated; 2. going forward we should consider Scala 3 in a light of next 15 years, now is the right moment to clean up the language and 3. this is “the easiest refactoring to automate the code base” that could be a “zero cost migration” diff --git a/_sips/sip-tutorial.md b/_sips/sip-tutorial.md index 680eee2d73..b5ed7e03ae 100644 --- a/_sips/sip-tutorial.md +++ b/_sips/sip-tutorial.md @@ -11,7 +11,7 @@ The process to submit is simple: * Fork the [Scala documentation repository](http://github.com/scala/docs.scala-lang) and clone it. * Create a new SIP file in the `sips/pending/_posts/`. Use the [S(L)IP template](https://github.com/scala/docs.scala-lang/blob/master/_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`. + * 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](http://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. * Create a link to your SIP in the "pending sips" section of `index.md`. @@ -21,7 +21,7 @@ The process to submit is simple: ## SIP Post Format ## -First, create a new SIP file in the `pending/_posts` directory. Make sure the new file follows the format: `YYYY-MM-dd-{title}.md`. Where: +First, create a new SIP file in the `pending/_posts` directory. Make sure the new file follows the format: `YYYY-MM-dd-{title}.md`. Where: * `YYYY` is the current year when the proposal originated. * `MM` is the current month (`01` = January, `12` = December) when the proposal originated. * `dd` is the day of the month when the proposal originated. diff --git a/_sips/sips/2010-01-22-named-and-default-arguments.md b/_sips/sips/2010-01-22-named-and-default-arguments.md index fecaed1b71..a3d5a96165 100644 --- a/_sips/sips/2010-01-22-named-and-default-arguments.md +++ b/_sips/sips/2010-01-22-named-and-default-arguments.md @@ -16,13 +16,13 @@ The second language feature discussed in this document, default arguments, in ge ## Named Arguments -In Scala 2.8, method arguments can be specified in _named style_ using the same syntax as variable assignments: +In Scala 2.8, method arguments can be specified in _named style_ using the same syntax as variable assignments: def f[T](a: Int, b: T) f(b = getT(), a = getInt()) -The argument expressions are evaluated in call-site order, so in the above example `getT()` is executed before `getInt()`f. Mixing named and positional arguments is allowed as long as the positional part forms a prefix of the argument list: +The argument expressions are evaluated in call-site order, so in the above example `getT()` is executed before `getInt()`f. Mixing named and positional arguments is allowed as long as the positional part forms a prefix of the argument list: f(0, b = "1") // valid f(b = "1", a = 0) // valid @@ -51,7 +51,7 @@ The following list shows how named arguments interfere with other language featu **By-Name Parameters** continue to work as expected when using named arguments. The expression is only (and repeatedly) evaluated when the body of the method accesses the parameter. -**Repeated Parameters** When an application uses named arguments, the repeated parameter has to be specified exactly once. Using the same parameter name multiple times is disallowed. +**Repeated Parameters** When an application uses named arguments, the repeated parameter has to be specified exactly once. Using the same parameter name multiple times is disallowed. **Functional values** A functional value in Scala is an instance of a class which implements a method called apply. One can use the parameter names of that apply method for a named application. For functional values whose static type is scala.FunctionN, the parameter names of that apply method can be used. @@ -68,17 +68,17 @@ The following list shows how named arguments interfere with other language featu val a: A = new B a.f(a = 1) // OK -**Overloading Resolution** When a method application refers to an overloaded method, first the set of applicable alternatives is determined and then the most specific alternative is chosen (see [1], Chapter 6.26.3). +**Overloading Resolution** When a method application refers to an overloaded method, first the set of applicable alternatives is determined and then the most specific alternative is chosen (see [1], Chapter 6.26.3). -The presence of named argument influences the set of applicable alternatives, the argument types have to be matched against the corresponding parameter types based on the names. In the following example, the second alternative is applicable: +The presence of named argument influences the set of applicable alternatives, the argument types have to be matched against the corresponding parameter types based on the names. In the following example, the second alternative is applicable: def f() // #1 def f(a: Int, b: String) // #2 f(b = "someString", a = 1) // using #2 -If multiple alternatives are applicable, the most specific one is determined. This process is independent of the argument names used in a specific application and only looks at the method signature (for a detailed description, see [1], Chapter 6.26.3). +If multiple alternatives are applicable, the most specific one is determined. This process is independent of the argument names used in a specific application and only looks at the method signature (for a detailed description, see [1], Chapter 6.26.3). -In the following example, both alternatives are applicable, but none of them is more specific than the other because the argument types are compared based on their position, not on the argument name: +In the following example, both alternatives are applicable, but none of them is more specific than the other because the argument types are compared based on their position, not on the argument name: def f(a: Int, b: String) // #1 def f(b: Object, a: Int) // #2 @@ -113,7 +113,7 @@ A default argument may be an arbitrary expression. Since the scope of a paramete // def f(a: Int = 0, b: Int = a + 1) // "error: not found: value a" f(10)() // returns 11 (not 1) -A special expected type is used for type-checking the default argument `expr` of a method parameter `”x: T = expr”`: it is obtained by replacing all occurrences of type parameters of the method (type parameters of the class for constructors) with the undefined type. This allows specifying default arguments for polymorphic methods and classes: +A special expected type is used for type-checking the default argument `expr` of a method parameter `”x: T = expr”`: it is obtained by replacing all occurrences of type parameters of the method (type parameters of the class for constructors) with the undefined type. This allows specifying default arguments for polymorphic methods and classes: def f[T](a: T = 1) = a f() // returns 1: Int @@ -157,7 +157,7 @@ During type-checking, the static type is used to determine whether a parameter h def f(a: String, b: Int = 1) // #2 f("str") // both are applicable, #1 is selected -**Case Classes** For every case class, a method named `”copy”` is now generated which allows to easily create modified copies of the class’s instances. The copy method takes the same type and value parameters as the primary constructor of the case class, and every parameter defaults to the corresponding constructor parameter. +**Case Classes** For every case class, a method named `”copy”` is now generated which allows to easily create modified copies of the class’s instances. The copy method takes the same type and value parameters as the primary constructor of the case class, and every parameter defaults to the corresponding constructor parameter. case class A[T](a: T, b: Int) { // def copy[T’](a’: T’ = a, b’: Int = b): A[T’] = @@ -215,4 +215,4 @@ For constructor defaults, these methods are added to the companion object of the // } ## References -1. Odersky, M. _The Scala Language Specification, Version 2.11_. Available online at [http://www.scala-lang.org/files/archive/spec/2.11/](http://www.scala-lang.org/files/archive/spec/2.11/) +1. Odersky, M. _The Scala Language Specification, Version 2.11_. Available online at [http://www.scala-lang.org/files/archive/spec/2.11/](http://www.scala-lang.org/files/archive/spec/2.11/) diff --git a/_sips/sips/2010-01-22-scala-2-8-arrays.md b/_sips/sips/2010-01-22-scala-2-8-arrays.md index 407dc19bf1..3411fa929c 100644 --- a/_sips/sips/2010-01-22-scala-2-8-arrays.md +++ b/_sips/sips/2010-01-22-scala-2-8-arrays.md @@ -26,8 +26,8 @@ First, there’s actually not a single array type representation in Java but nine different ones: One representation for arrays of reference type and another eight for arrays of each of the primitive types `byte`, `char`, `short`, `int`, `long`, `float`, `double`, and `boolean`. There is no common -type for these different representations which is more specific than just -`java.lang.Object`, even though there are some reflective methods to deal with +type for these different representations which is more specific than just +`java.lang.Object`, even though there are some reflective methods to deal with arrays of arbitrary type in `java.lang.reflect.Array`. Second, there’s no way to create an array of a generic type; only monomorphic array creations are allowed. Third, the only operations supported by arrays are indexing, updates, @@ -35,14 +35,14 @@ and get length. Contrast this with what we would like to have in Scala: Arrays should slot into the collections hierarchy, supporting the hundred or so methods that are -defined on sequences. And they should certainly be generic, so that one can +defined on sequences. And they should certainly be generic, so that one can create an `Array[T]` where `T` is a type variable. ### The Past How to combine these desirables with the representation restrictions imposed by Java interoperability and performance? There’s no easy answer, and I -believe we got it wrong the first time when we designed Scala. The Scala +believe we got it wrong the first time when we designed Scala. The Scala language up to 2.7.x “magically” wrapped and unwrapped arrays when required in a process called boxing and unboxing, similarly to what is done to treat primitive numeric types as objects. “Magically” means: the compiler generated @@ -89,7 +89,7 @@ proposal is that one would not normally refer to Scala native arrays in user code, just as one rarely referred to RichString in Scala. One would only rely on the implicit conversion to add the necessary methods and traits to Java arrays. Unfortunately, the String/RichString experience has shown that this is -also problematic. In par- ticular, in pre 2.8 versions of Scala, one had the +also problematic. In particular, in pre 2.8 versions of Scala, one had the non-intuitive property that "abc".reverse.reverse == "abc" //, yet diff --git a/_sips/sips/2011-10-13-uncluttering-control.md b/_sips/sips/2011-10-13-uncluttering-control.md index 5f4dea8d64..e1ceb5d790 100644 --- a/_sips/sips/2011-10-13-uncluttering-control.md +++ b/_sips/sips/2011-10-13-uncluttering-control.md @@ -71,7 +71,7 @@ For while loops: To write a `do-while` inside a `while` loop you will need braces, like this: - while (expression1) { do expression2 while epression3 } + while (expression1) { do expression2 while expression3 } 3. In Scala 2.11: Disallow diff --git a/_sips/sips/2012-01-21-futures-promises.md b/_sips/sips/2012-01-21-futures-promises.md index a1b8d43666..11983d2201 100644 --- a/_sips/sips/2012-01-21-futures-promises.md +++ b/_sips/sips/2012-01-21-futures-promises.md @@ -109,7 +109,7 @@ We do so by calling the method `getRecentPosts` which returns a `List[String]`: f onComplete { case Right(posts) => for (post <- posts) render(post) - case Left(t) => render("An error has occured: " + t.getMessage) + case Left(t) => render("An error has occurred: " + t.getMessage) } The `onComplete` method is general in the sense that it allows the @@ -387,16 +387,16 @@ multiple `andThen` calls are ordered, as in the following example which stores the recent posts from a social network to a mutable set and then renders all the posts to the screen: - val allposts = mutable.Set[String]() + val allPosts = mutable.Set[String]() Future { session.getRecentPosts } andThen { - case Success(posts) => allposts ++= posts + case Success(posts) => allPosts ++= posts } andThen { case _ => clearAll() - for (post <- allposts) render(post) + for (post <- allPosts) render(post) } In summary, the combinators on futures are purely functional. diff --git a/_sips/sips/2013-05-31-improved-lazy-val-initialization.md b/_sips/sips/2013-05-31-improved-lazy-val-initialization.md index b3fc711ced..2ff2dfee7c 100644 --- a/_sips/sips/2013-05-31-improved-lazy-val-initialization.md +++ b/_sips/sips/2013-05-31-improved-lazy-val-initialization.md @@ -529,7 +529,7 @@ Note that this class is extracted from other place in standard library that uses - it requires usage of `identityHashCode` that is stored for every object inside object header. - as global arrays are used to store monitors, seemingly unrelated things may create contention. This is addressed in detail in evaluation section. -Both absence of monitor expansion and usage of `idetityHashCode` interact with +Both absence of monitor expansion and usage of `identityHashCode` interact with each other, as both of them operate on the object header. \[[12][12]\] presents the complete graph of transitions between possible states of the object header. What can be seen from this transition graph is that in the contended case, @@ -679,7 +679,7 @@ For those wishing to reproduce the results, the benchmarking suite takes 90 minu The final result of those benchmarks is that amount proposed versions, the two that worth considering are (V4-general) and (V6). They both perform better than the current implementation in all the contended case. -Specifically, in the contended case, V6 is 2 times fater than V1, while V4-general is 4 times faster. +Specifically, in the contended case, V6 is 2 times faster than V1, while V4-general is 4 times faster. Unfortunately V4-general is 30% slower in the uncontended case than current implementation(V1), while V6 is in the same ballpark, being up to 5% slower or faster depending on the setup of the benchmark. Based on this, we propose V6 to be used as default in future versions of Scala. @@ -699,7 +699,7 @@ Both Dotty and released Scala 2.12 already implement "Elegant Local lazy vals". ### Unsafe ### The proposed version, V6 relies on `sun.misc.Unsafe` in order to implement it's behaviour. -While `sun.misc.Unsafe` will remain availabe in Java9 there's an intention to deprecate it and replace it with VarHandles.\[[20][20]\]. +While `sun.misc.Unsafe` will remain available in Java9 there's an intention to deprecate it and replace it with VarHandles.\[[20][20]\]. The proposed version V6 can be implemented with using functionality present in Var Handles. ## Acknowledgements ## diff --git a/_sips/sips/2014-06-27-42.type.md b/_sips/sips/2014-06-27-42.type.md index 0c4e208810..afe0aeaeae 100644 --- a/_sips/sips/2014-06-27-42.type.md +++ b/_sips/sips/2014-06-27-42.type.md @@ -455,7 +455,7 @@ applications which work with large datasets. ``` This SIP updates the specification to match the current implementation and then adds the further - refinement that an explict upper bound of `Singleton` indicates that a singleton type should be + refinement that an explicit upper bound of `Singleton` indicates that a singleton type should be inferred. Given, @@ -592,7 +592,7 @@ the singleton types). This is desirable, but due to value class restrictions, en primitive types (such as `Int`). If we implemented `ValueOf[A]` as an opaque type instead of a value class, then this boxing -would be ellided, and the `valueOf[A]` method would be compiled to an identity function. +would be elided, and the `valueOf[A]` method would be compiled to an identity function. ## Related Scala issues resolved by the literal types implementation diff --git a/_sips/sips/2016-01-11-static-members.md b/_sips/sips/2016-01-11-static-members.md index 9fff070f02..3d98d6f5fe 100644 --- a/_sips/sips/2016-01-11-static-members.md +++ b/_sips/sips/2016-01-11-static-members.md @@ -97,7 +97,7 @@ object O { } {% endhighlight %} -Under the proposed scheme users will be able to opt-in to have the field `f` defined in the inner object `I` emited as a static field. +Under the proposed scheme users will be able to opt-in to have the field `f` defined in the inner object `I` emitted as a static field. In case `O.d` is annotated with `@static` the field will be created as a static field `d` in `class O`. If not annotated, it will be created in the companion module with a static forwarder `d` in `class O`. @@ -109,7 +109,7 @@ The following rules ensure that methods can be correctly compiled into static me 2. The fields annotated with `@static` should precede any non-`@static` fields. This ensures that we do not introduce surprises for users in initialization order of this class. -3. The right hand side of a method or field annotated with `@static` can only refer to top-level classes, members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accesible. `super` is never accessible. +3. The right hand side of a method or field annotated with `@static` can only refer to top-level classes, members of globally accessible objects and `@static` members. In particular, for non-static objects `this` is not accessible. `super` is never accessible. 4. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` is not allowed to define term members with name `foo`. @@ -153,7 +153,7 @@ This means that no code precedes the `@static` field initialization which makes since fields are initialized in the order `as written`, similar to how normal fields are initialized. The `@static` proposal is similar to `@tailrec` in a sense that it fails compilation in the case where the user did not write code that follows the aforementioned rules. -These rules exist to enforce the unlikelyhood of an observable difference in semantics if `@static` annotations are dropped; +These rules exist to enforce the unlikelihood of an observable difference in semantics if `@static` annotations are dropped; The restrictions in this SIP make it hard to observe changes in initialization within the same object. It is still possible to observe those changes using multiple classes and side effects within initializers: diff --git a/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md b/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md index 95c73ab90d..8e2341c1eb 100644 --- a/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md +++ b/_sips/sips/2017-02-07-priority-based-infix-type-precedence.md @@ -104,7 +104,7 @@ val fails : 1 + 2 * 3 + 4 = 11 //left associative:(((1+2)*3)+4))) = 13 ``` #### Developer issues example -[This](http://stackoverflow.com/questions/23333882/scala-infix-type-aliasing-for-2-type-parameters) stackoverflow question demonstrate developers are 'surprised' by the difference in infix precedence, expecting infix type precedence to act the same as expression operations. +[This](http://stackoverflow.com/questions/23333882/scala-infix-type-aliasing-for-2-type-parameters) Stack Overflow question demonstrate developers are 'surprised' by the difference in infix precedence, expecting infix type precedence to act the same as expression operations. --- diff --git a/_sips/sips/2017-09-20-opaque-types.md b/_sips/sips/2017-09-20-opaque-types.md index 7c8d5e3444..bbd4a798d3 100644 --- a/_sips/sips/2017-09-20-opaque-types.md +++ b/_sips/sips/2017-09-20-opaque-types.md @@ -885,7 +885,7 @@ there will certainly be an impact on the bytecode produced (and possibly the runtime performance). By contrast, replacing `String` with `Digits` is guaranteed to have no -impact (all occurances of `Digits` are guaranteed to be erased to +impact (all occurrences of `Digits` are guaranteed to be erased to `String`). Aside from the ergonomics of calling the `fromString` and `asString` methods, there's no runtime impact versus using the underlying type. @@ -953,7 +953,7 @@ but it is *not* a `List[AnyVal]`. Since value classes do have a runtime representation, they do increase the size of runtime artifacts produced (whether a JAR file, a -javascript file, or something else). Their methods are also compiled +JavaScript file, or something else). Their methods are also compiled to multiple representations (i.e. they support both the boxed and unboxed forms via extensions methods). Again, this comes at a cost. diff --git a/_sips/sips/2018-07-31-interpolation-quote-escape.md b/_sips/sips/2018-07-31-interpolation-quote-escape.md index bd5658d618..a04703d2a9 100644 --- a/_sips/sips/2018-07-31-interpolation-quote-escape.md +++ b/_sips/sips/2018-07-31-interpolation-quote-escape.md @@ -21,7 +21,7 @@ rather passes the raw string to the interpolator, which then has the option to process escapes itself as it sees fit. That means there are no lexing rules that process the escape, and the sequence `\"` simply terminates the interpolation. -Interpolations have a different meta-charcter -- the `$` character -- which is +Interpolations have a different meta-character -- the `$` character -- which is treated specially. Interpolations use this escape to splice in arguments, and it can also be used to escape itself as the sequence `$$` to represent a literal `$` character. @@ -90,7 +90,7 @@ on the original ticket ## Implementation The implementation is simple to the point of being trivial: see -[the implementation][5] for the actual change in functonality and the rest of +[the implementation][5] for the actual change in functionality and the rest of that PR for the spec and test changes. ## Drawbacks @@ -101,12 +101,12 @@ the language. An argument could be made that this change makes that worse rather than better. Because it affects parsing, this change may affect syntax highlighters. Syntax -highlighters tend to already stuggle around "funky" strings and interpolations. +highlighters tend to already struggle around "funky" strings and interpolations. ## Alternatives More ambitious proposals around interpolations are possible, and have been -propsed in different forms before. [This PR][6] in particular shows more options +proposed in different forms before. [This PR][6] in particular shows more options around using `\` as a meta character in interpolations. It stranded somewhere between red tape, ambition and changing processes. diff --git a/_tour/automatic-closures.md b/_tour/automatic-closures.md index 37b82524ef..e65c7130af 100644 --- a/_tour/automatic-closures.md +++ b/_tour/automatic-closures.md @@ -7,7 +7,7 @@ discourse: true partof: scala-tour --- -Scala allows parameterless function names as parameters of methods. When such a method is called, the actual parameters for parameterless function names are not evaluated and a nullary function is passed instead which encapsulates the computation of the corresponding parameter (so-called *call-by-name* evalutation). +Scala allows parameterless function names as parameters of methods. When such a method is called, the actual parameters for parameterless function names are not evaluated and a nullary function is passed instead which encapsulates the computation of the corresponding parameter (so-called *call-by-name* evaluation). The following code demonstrates this mechanism: diff --git a/_tour/traits.md b/_tour/traits.md index 121255457d..37bf615c6c 100644 --- a/_tour/traits.md +++ b/_tour/traits.md @@ -45,7 +45,7 @@ trait Iterator[A] { class IntIterator(to: Int) extends Iterator[Int] { private var current = 0 override def hasNext: Boolean = current < to - override def next(): Int = { + override def next(): Int = { if (hasNext) { val t = current current += 1 diff --git a/contribute.md b/contribute.md index 9f4692f679..5f4c2b6850 100644 --- a/contribute.md +++ b/contribute.md @@ -79,7 +79,7 @@ If you have something you're thinking about contributing, or that you're thinkin ### 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-separarted-by-dashes.md`, and header: +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 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 74bfff8b5b..021aed1bbf 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 @@ -19,11 +19,11 @@ Started with Scala and sbt on the Command Line]({{site.baseurl}}/getting-started here to the section "Writing Scala code". 1. If you didn't create the project from the command line, open up IntelliJ and select "Create New Project" - * On the left panel, select Scala and on the right panel, select SBT + * On the left panel, select Scala and on the right panel, select sbt * Click **Next** - * Name the project "SBTExampleProject" + * Name the project "SbtExampleProject" 1. If you already created the project on the command line, open up IntelliJ, select *Import Project* and open the `build.sbt` file for your project -1. Make sure the **JDK Version** is 1.8 and the **SBT Version** is at least 0.13.13 +1. Make sure the **JDK version** is 1.8 and the **sbt version** is at least 0.13.13 1. Select **Use auto-import** so dependencies are automatically downloaded when available 1. Select **Finish** @@ -47,7 +47,7 @@ but here's a glance at what everything is for: ## Writing Scala code -1. On the **Project** panel on the left, expand `SBTExampleProject` => `src` +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**. @@ -68,9 +68,9 @@ to see if sbt can run your project on the command line. ## Running the project 1. From the **Run** menu, select **Edit configurations** -1. Click the **+** button and select **SBT Task**. +1. Click the **+** button and select **sbt Task**. 1. Name it `Run the program`. -1. In the **Tasks** field, type `~run`. The `~` causes SBT to rebuild and rerun the project +1. In the **Tasks** field, type `~run`. The `~` causes sbt to rebuild and rerun the project when you save changes to a file in the project. 1. Click **OK**. 1. On the **Run** menu. Click **Run 'Run the program'**. diff --git a/getting-started-sbt-track/testing-scala-with-sbt-on-the-command-line.md b/getting-started-sbt-track/testing-scala-with-sbt-on-the-command-line.md index 388f76a1de..ba38a030ee 100644 --- a/getting-started-sbt-track/testing-scala-with-sbt-on-the-command-line.md +++ b/getting-started-sbt-track/testing-scala-with-sbt-on-the-command-line.md @@ -20,9 +20,9 @@ We assume you know [how to create a Scala project with sbt](getting-started-with ``` sbt test -[info] Loading global plugins from /Users/travislee/.sbt/0.13/plugins -[info] Loading project definition from /Users/travislee/workspace/sandbox/my-something-project/project -[info] Set current project to scalatest-example (in build file:/Users/travislee/workspace/sandbox/my-something-project/) +[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. diff --git a/news/_posts/2012-12-12-functional-programming-principles-in-scala-impressions-and-statistics.md b/news/_posts/2012-12-12-functional-programming-principles-in-scala-impressions-and-statistics.md index 7735015903..60c52a7875 100644 --- a/news/_posts/2012-12-12-functional-programming-principles-in-scala-impressions-and-statistics.md +++ b/news/_posts/2012-12-12-functional-programming-principles-in-scala-impressions-and-statistics.md @@ -6,7 +6,7 @@ discourse: true ###### By Heather Miller and Martin Odersky
    - In this post, we discuss our experience giving the popular MOOC Functional Programming Principles in Scala, and provide some insight into who our course participants were, how, overall, students performed in the course, and how students felt about the course. We visualize a lot of these statistics in a number of interactive plots, and we go on to publicly release the data and the code to generate these plots within a fun Scala-based project aimed at allowing you to manipulate these statistics with functional programming in Scala, to generate HTML/Javascript for easily visualizing and sharing them. We encourage you to share what you find with us— we'll share a number of your plots in a follow-up post! + In this post, we discuss our experience giving the popular MOOC Functional Programming Principles in Scala, and provide some insight into who our course participants were, how, overall, students performed in the course, and how students felt about the course. We visualize a lot of these statistics in a number of interactive plots, and we go on to publicly release the data and the code to generate these plots within a fun Scala-based project aimed at allowing you to manipulate these statistics with functional programming in Scala, to generate HTML/JavaScript for easily visualizing and sharing them. We encourage you to share what you find with us— we'll share a number of your plots in a follow-up post!
    [_Functional Programming Principles in Scala_](https://www.coursera.org/course/progfun) is a [MOOC](http://en.wikipedia.org/wiki/Massive_open_online_course) given by [our research group](http://lamp.epfl.ch) at [EPFL](http://www.epfl.ch), whose first edition was recently completed on [Coursera](http://www.coursera.org). The certificates of completion for those who passed the course have been released, and in looking back as the dust settles— it was a great experience to have done a class like that which greatly exceeded our expectations in more than one dimension. diff --git a/resources/images/library-author-guide/fowards_backwards_compatibility.png b/resources/images/library-author-guide/forward_backward_compatibility.png similarity index 100% rename from resources/images/library-author-guide/fowards_backwards_compatibility.png rename to resources/images/library-author-guide/forward_backward_compatibility.png From 557caf9adb45b7b84b1072cc603964ffbee2a9c3 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 10 Jun 2019 15:43:32 +0200 Subject: [PATCH 0604/3174] Update representation of un-evaluated collections as per scala/scala#8029 --- .../concrete-immutable-collection-classes.md | 4 ++-- _overviews/collections-2.13/views.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_overviews/collections-2.13/concrete-immutable-collection-classes.md b/_overviews/collections-2.13/concrete-immutable-collection-classes.md index e3c8f68556..131295bf0f 100644 --- a/_overviews/collections-2.13/concrete-immutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-immutable-collection-classes.md @@ -25,7 +25,7 @@ A [LazyList](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/co Whereas lists are constructed with the `::` operator, lazy lists are constructed with the similar-looking `#::`. Here is a simple example of a lazy list containing the integers 1, 2, and 3: scala> val lazyList = 1 #:: 2 #:: 3 #:: LazyList.empty - lazyList: scala.collection.immutable.LazyList[Int] = LazyList(?) + lazyList: scala.collection.immutable.LazyList[Int] = LazyList() The head of this lazy list is 1, and the tail of it has 2 and 3. None of the elements are printed here, though, because the list hasn’t been computed yet! Lazy lists are specified to compute lazily, and the `toString` method of a lazy list is careful not to force any extra evaluation. @@ -40,7 +40,7 @@ This function is deceptively simple. The first element of the sequence is clearl Here are the first few elements of the Fibonacci sequence starting with two ones: scala> val fibs = fibFrom(1, 1).take(7) - fibs: scala.collection.immutable.LazyList[Int] = LazyList(?) + fibs: scala.collection.immutable.LazyList[Int] = LazyList() scala> fibs.toList res9: List[Int] = List(1, 1, 2, 3, 5, 8, 13) diff --git a/_overviews/collections-2.13/views.md b/_overviews/collections-2.13/views.md index a9ec4c3d25..61ebae3cef 100644 --- a/_overviews/collections-2.13/views.md +++ b/_overviews/collections-2.13/views.md @@ -46,20 +46,20 @@ In the last statement, the expression `v map (_ + 1)` constructs a new vector wh Let's do this sequence of operations again, one by one: scala> val vv = v.view - vv: scala.collection.IndexedSeqView[Int] = View(?) + vv: scala.collection.IndexedSeqView[Int] = IndexedSeqView() The application `v.view` gives you an `IndexedSeqView[Int]`, i.e. a lazily evaluated `IndexedSeq[Int]`. Like with `LazyList`, -the `toString` operation of views does not force the view elements, that’s why the content of `vv` is shown as `View(?)`. +the `toString` operation of views does not force the view elements, that’s why the content of `vv` is shown as `IndexedSeqView()`. Applying the first `map` to the view gives: scala> vv map (_ + 1) - res13: scala.collection.IndexedSeqView[Int] = View(?) + res13: scala.collection.IndexedSeqView[Int] = IndexedSeqView() The result of the `map` is another `IndexedSeqView[Int]` value. This is in essence a wrapper that *records* the fact that a `map` with function `(_ + 1)` needs to be applied on the vector `v`. It does not apply that map until the view is forced, however. Let's now apply the second `map` to the last result. scala> res13 map (_ * 2) - res14: scala.collection.IndexedSeqView[Int] = View(?) + res14: scala.collection.IndexedSeqView[Int] = IndexedSeqView() Finally, forcing the last result gives: From e56ed6502486f58935cb08f2a663535890d287b4 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 10 Jun 2019 22:34:04 +0200 Subject: [PATCH 0605/3174] update 2.13 collections intro --- _overviews/collections-2.13/introduction.md | 46 ++++++++++----------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/_overviews/collections-2.13/introduction.md b/_overviews/collections-2.13/introduction.md index 2f077f3383..a4ff432874 100644 --- a/_overviews/collections-2.13/introduction.md +++ b/_overviews/collections-2.13/introduction.md @@ -12,22 +12,15 @@ num: 1 permalink: /overviews/collections-2.13/:title.html --- -**Martin Odersky, and Lex Spoon** - -In the eyes of many, the new collections framework is the most significant -change in the Scala 2.8 release. Scala had collections before (and in fact the new -framework is largely compatible with them). But it's only 2.8 that -provides a common, uniform, and all-encompassing framework for -collection types. - -Even though the additions to collections are subtle at first glance, -the changes they can provoke in your programming style can be -profound. In fact, quite often it's as if you work on a higher-level -with the basic building blocks of a program being whole collections -instead of their elements. This new style of programming requires some -adaptation. Fortunately, the adaptation is helped by several nice -properties of the new Scala collections. They are easy to use, -concise, safe, fast, universal. +The collections framework is the heart of the Scala 2.13 standard +library. It provides a common, uniform, and all-encompassing +framework for collection types. This framework enables you to work +with data in memory at a high level, with the basic building blocks of +a program being whole collections, instead of individual elements. + +This style of programming requires some learning. Fortunately, +the adaptation is helped by several nice properties of the Scala +collections. They are easy to use, concise, safe, fast, universal. **Easy to use:** A small vocabulary of 20-50 methods is enough to solve most collection problems in a couple of operations. No @@ -40,7 +33,7 @@ collection updates is eliminated. **Concise:** You can achieve with a single word what used to take one or several loops. You can express functional operations with lightweight syntax and combine operations effortlessly, so that the result -feels like a custom algebra. +feels like a custom algebra. **Safe:** This one has to be experienced to sink in. The statically typed and functional nature of Scala's collections means @@ -59,10 +52,13 @@ libraries. As a result, using collections is typically quite efficient. You might be able to do a little bit better with carefully hand-tuned data structures and operations, but you might also do a lot worse by making some suboptimal implementation decisions along the -way. What's more, collections have been recently adapted to parallel -execution on multi-cores. Parallel collections support the same -operations as sequential ones, so no new operations need to be learned -and no code needs to be rewritten. You can turn a sequential collection into a +way. + +**Parallel**: The +[`scala-parallel-collections` module](https://index.scala-lang.org/scala/scala-parallel-collections/scala-parallel-collections) +provides parallel execution of collections operations across multiple cores. +Parallel collections generally support the same +operations as sequential ones. You can turn a sequential collection into a parallel one simply by invoking the `par` method. **Universal:** Collections provide the same operations on @@ -89,10 +85,10 @@ traditional collection processing (three loops for an array, because the intermediate results need to be buffered somewhere else). Once you have learned the basic collection vocabulary you will also find writing this code is much easier and safer than writing explicit -loops. Furthermore, the `partition` operation is quite fast, and can -be even faster on parallel collections on multi-cores. (Parallel -collections are available as a -[separate library](https://index.scala-lang.org/scala/scala-parallel-collections/scala-parallel-collections)) +loops. + +Furthermore, the `partition` operation is quite fast, and can +be even faster on parallel collections on multiple cores. This document provides an in depth discussion of the APIs of the Scala collections classes from a user perspective. It takes you on From c95cb8f2f4577e845853784f0cbc0d4ea09184c3 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Tue, 11 Jun 2019 10:14:11 +0800 Subject: [PATCH 0606/3174] Fix issue#1361, add space for markdown syntax enclosing . --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 3b638f3a46..ca50ce5486 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -195,7 +195,7 @@ Meta-programming software is software whose input is itself software. Compilers A _method_ is a function that is a member of some class, trait, or singleton object. * #### mixin -_Mixin_ is what a trait is called when it is being used in a mixin composition. In other words, in “`trait Hat`,” `Hat` is just a trait, but in “`new Cat extends AnyRef with Hat`,” `Hat` can be called a mixin. When used as a verb, “mix in” is two words. For example, you can _mix_ traits _in_to classes or other traits. +_Mixin_ is what a trait is called when it is being used in a mixin composition. In other words, in “`trait Hat`,” `Hat` is just a trait, but in “`new Cat extends AnyRef with Hat`,” `Hat` can be called a mixin. When used as a verb, “mix in” is two words. For example, you can _mix_ traits _in_ to classes or other traits. * #### mixin composition The process of mixing traits into classes or other traits. _Mixin composition_ differs from traditional multiple inheritance in that the type of the super reference is not known at the point the trait is defined, but rather is determined anew each time the trait is mixed into a class or other trait. From 4998f619855df3accd6d6409a42c0cc300148a48 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Tue, 11 Jun 2019 12:22:24 +0800 Subject: [PATCH 0607/3174] Fix issue#1363, remove - and space within defined. --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 3b638f3a46..ba2382b2ac 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -216,7 +216,7 @@ In Scala, every _operation_ is a method call. Methods may be invoked in _operato Functions may take zero to many _parameters_. Each parameter has a name and a type. The distinction between parameters and arguments is that arguments refer to the actual objects passed when a function is invoked. Parameters are the variables that refer to those passed arguments. * #### parameterless function -A function that takes no parameters, which is de- fined without any empty parentheses. Invocations of parameterless functions may not supply parentheses. This supports the [uniform access principle](#uniform-access-principle), which enables the `def` to be changed into a `val` without requiring a change to client code. +A function that takes no parameters, which is defined without any empty parentheses. Invocations of parameterless functions may not supply parentheses. This supports the [uniform access principle](#uniform-access-principle), which enables the `def` to be changed into a `val` without requiring a change to client code. * #### parameterless method A _parameterless method_ is a parameterless function that is a member of a class, trait, or singleton object. From 978b9b07ed0d981b7967cf0fe0bcdb81ddf0b27d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 10 Jun 2019 13:45:16 +0200 Subject: [PATCH 0608/3174] Scala 2.13 release --- _config.yml | 4 +-- .../concrete-immutable-collection-classes.md | 22 ++++++++-------- .../concrete-mutable-collection-classes.md | 22 ++++++++-------- _overviews/collections-2.13/iterators.md | 6 ++--- _overviews/collections-2.13/overview.md | 8 +++--- _overviews/collections-2.13/trait-iterable.md | 4 +-- _overviews/collections/arrays.md | 2 +- .../concrete-immutable-collection-classes.md | 20 +++++++------- .../concrete-mutable-collection-classes.md | 26 +++++++++---------- ...ions-between-java-and-scala-collections.md | 4 +-- _overviews/collections/iterators.md | 6 ++--- .../concrete-parallel-collections.md | 22 ++++++++-------- api/all.md | 6 +++++ 13 files changed, 79 insertions(+), 73 deletions(-) diff --git a/_config.yml b/_config.yml index 32288ccccc..e7564efd1a 100644 --- a/_config.yml +++ b/_config.yml @@ -15,8 +15,8 @@ keywords: - Document - Guide -scala-version: 2.12.8 -scala-213-version: 2.13.0-M5 +scala-version: 2.13.0 +scala-212-version: 2.12.8 collections: style: diff --git a/_overviews/collections-2.13/concrete-immutable-collection-classes.md b/_overviews/collections-2.13/concrete-immutable-collection-classes.md index e3c8f68556..af8ed0b95c 100644 --- a/_overviews/collections-2.13/concrete-immutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-immutable-collection-classes.md @@ -16,11 +16,11 @@ Scala provides many concrete immutable collection classes for you to choose from ## Lists -A [List](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/List.html) is a finite immutable sequence. They provide constant-time access to their first element as well as the rest of the list, and they have a constant-time cons operation for adding a new element to the front of the list. Many other operations take linear time. +A [List](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html) is a finite immutable sequence. They provide constant-time access to their first element as well as the rest of the list, and they have a constant-time cons operation for adding a new element to the front of the list. Many other operations take linear time. ## LazyLists -A [LazyList](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/LazyList.html) is like a list except that its elements are computed lazily. Because of this, a lazy list can be infinitely long. Only those elements requested are computed. Otherwise, lazy lists have the same performance characteristics as lists. +A [LazyList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/LazyList.html) is like a list except that its elements are computed lazily. Because of this, a lazy list can be infinitely long. Only those elements requested are computed. Otherwise, lazy lists have the same performance characteristics as lists. Whereas lists are constructed with the `::` operator, lazy lists are constructed with the similar-looking `#::`. Here is a simple example of a lazy list containing the integers 1, 2, and 3: @@ -48,7 +48,7 @@ Here are the first few elements of the Fibonacci sequence starting with two ones Lists are very efficient when the algorithm processing them is careful to only process their heads. Accessing, adding, and removing the head of a list takes only constant time, whereas accessing or modifying elements later in the list takes time linear in the depth into the list. -[ArraySeq](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/ArraySeq.html) is a +[ArraySeq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/ArraySeq.html) is a collection type (introduced in Scala 2.13) that addresses the inefficiency for random access on lists. ArraySeqs allow accessing any element of the collection in constant time. As a result, algorithms using ArraySeqs do not have to be careful about accessing just the head of the collection. They can access elements at arbitrary locations, @@ -87,7 +87,7 @@ We have seen in the previous sections that `List` and `ArraySeq` are efficient d use cases but they are also inefficient in other use cases: for instance, prepending an element is constant for `List`, but linear for `ArraySeq`, and, conversely, indexed access is constant for `ArraySeq` but linear for `List`. -[Vector](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Vector.html) is a collection type that provides good performance for all its operations. Vectors allow accessing any element of the sequence in "effectively" constant time. It's a larger constant than for access to the head of a List or for reading an element of an ArraySeq, but it's a constant nonetheless. As a result, algorithms using vectors do not have to be careful about accessing just the head of the sequence. They can access and modify elements at arbitrary locations, and thus they can be much more convenient to write. +[Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html) is a collection type that provides good performance for all its operations. Vectors allow accessing any element of the sequence in "effectively" constant time. It's a larger constant than for access to the head of a List or for reading an element of an ArraySeq, but it's a constant nonetheless. As a result, algorithms using vectors do not have to be careful about accessing just the head of the sequence. They can access and modify elements at arbitrary locations, and thus they can be much more convenient to write. Vectors are built and modified just like any other sequence. @@ -112,7 +112,7 @@ Because vectors strike a good balance between fast random selections and fast ra ## Immutable Queues -A [Queue](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Queue.html) is a first-in-first-out sequence. You enqueue an element onto a queue with `enqueue`, and dequeue an element with `dequeue`. These operations are constant time. +A [Queue](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Queue.html) is a first-in-first-out sequence. You enqueue an element onto a queue with `enqueue`, and dequeue an element with `dequeue`. These operations are constant time. Here's how you can create an empty immutable queue: @@ -140,7 +140,7 @@ Note that `dequeue` returns a pair consisting of the element removed and the res ## Ranges -A [Range](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Range.html) is an ordered sequence of integers that are equally spaced apart. For example, "1, 2, 3," is a range, as is "5, 8, 11, 14." To create a range in Scala, use the predefined methods `to` and `by`. +A [Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html) is an ordered sequence of integers that are equally spaced apart. For example, "1, 2, 3," is a range, as is "5, 8, 11, 14." To create a range in Scala, use the predefined methods `to` and `by`. scala> 1 to 3 res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3) @@ -156,7 +156,7 @@ Ranges are represented in constant space, because they can be defined by just th ## Compressed Hash-Array Mapped Prefix-trees -Hash tries are a standard way to implement immutable sets and maps efficiently. [Compressed Hash-Array Mapped Prefix-trees](https://github.com/msteindorfer/oopsla15-artifact/) are a design for hash tries on the JVM which improves locality and makes sure the trees remain in a canonical and compact representation. They are supported by class [immutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/HashMap.html). Their representation is similar to vectors in that they are also trees where every node has 32 elements or 32 subtrees. But the selection of these keys is now done based on hash code. For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level. +Hash tries are a standard way to implement immutable sets and maps efficiently. [Compressed Hash-Array Mapped Prefix-trees](https://github.com/msteindorfer/oopsla15-artifact/) are a design for hash tries on the JVM which improves locality and makes sure the trees remain in a canonical and compact representation. They are supported by class [immutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/HashMap.html). Their representation is similar to vectors in that they are also trees where every node has 32 elements or 32 subtrees. But the selection of these keys is now done based on hash code. For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level. Hash tries strike a nice balance between reasonably fast lookups and reasonably efficient functional insertions (`+`) and deletions (`-`). That's why they underly Scala's default implementations of immutable maps and sets. In fact, Scala has a further optimization for immutable sets and maps that contain less than five elements. Sets and maps with one to four elements are stored as single objects that just contain the elements (or key/value pairs in the case of a map) as fields. The empty immutable set and the empty immutable map is in each case a single object - there's no need to duplicate storage for those because an empty immutable set or map will always stay empty. @@ -164,7 +164,7 @@ Hash tries strike a nice balance between reasonably fast lookups and reasonably Red-black trees are a form of balanced binary tree where some nodes are designated "red" and others designated "black." Like any balanced binary tree, operations on them reliably complete in time logarithmic to the size of the tree. -Scala provides implementations of immutable sets and maps that use a red-black tree internally. Access them under the names [TreeSet](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/TreeSet.html) and [TreeMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/TreeMap.html). +Scala provides implementations of immutable sets and maps that use a red-black tree internally. Access them under the names [TreeSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeSet.html) and [TreeMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeMap.html). scala> scala.collection.immutable.TreeSet.empty[Int] @@ -176,7 +176,7 @@ Red-black trees are the standard implementation of `SortedSet` in Scala, because ## Immutable BitSets -A [BitSet](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/BitSet.html) represents a collection of small integers as the bits of a larger integer. For example, the bit set containing 3, 2, and 0 would be represented as the integer 1101 in binary, which is 13 in decimal. +A [BitSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/BitSet.html) represents a collection of small integers as the bits of a larger integer. For example, the bit set containing 3, 2, and 0 would be represented as the integer 1101 in binary, which is 13 in decimal. Internally, bit sets use an array of 64-bit `Long`s. The first `Long` in the array is for integers 0 through 63, the second is for 64 through 127, and so on. Thus, bit sets are very compact so long as the largest integer in the set is less than a few hundred or so. @@ -193,7 +193,7 @@ Operations on bit sets are very fast. Testing for inclusion takes constant time. ## VectorMaps -A [VectorMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/VectorMap.html) represents +A [VectorMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/VectorMap.html) represents a map using both a `Vector` of keys and a `HashMap`. It provides an iterator that returns all the entries in their insertion order. @@ -217,7 +217,7 @@ order of elements into account. ## ListMaps -A [ListMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/ListMap.html) represents a map as a linked list of key-value pairs. In general, operations on a list map might have to iterate through the entire list. Thus, operations on a list map take time linear in the size of the map. In fact there is little usage for list maps in Scala because standard immutable maps are almost always faster. The only possible exception to this is if the map is for some reason constructed in such a way that the first elements in the list are selected much more often than the other elements. +A [ListMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/ListMap.html) represents a map as a linked list of key-value pairs. In general, operations on a list map might have to iterate through the entire list. Thus, operations on a list map take time linear in the size of the map. In fact there is little usage for list maps in Scala because standard immutable maps are almost always faster. The only possible exception to this is if the map is for some reason constructed in such a way that the first elements in the list are selected much more often than the other elements. scala> val map = scala.collection.immutable.ListMap(1->"one", 2->"two") map: scala.collection.immutable.ListMap[Int,java.lang.String] = diff --git a/_overviews/collections-2.13/concrete-mutable-collection-classes.md b/_overviews/collections-2.13/concrete-mutable-collection-classes.md index bcf855ddc6..f2cf39eb41 100644 --- a/_overviews/collections-2.13/concrete-mutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-mutable-collection-classes.md @@ -16,7 +16,7 @@ You've now seen the most commonly used immutable collection classes that Scala p ## Array Buffers -An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/ArrayBuffer.html) buffer holds an array and a size. Most operations on an array buffer have the same speed as for an array, because the operations simply access and modify the underlying array. Additionally, array buffers can have data efficiently added to the end. Appending an item to an array buffer takes amortized constant time. Thus, array buffers are useful for efficiently building up a large collection whenever the new items are always added to the end. +An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayBuffer.html) buffer holds an array and a size. Most operations on an array buffer have the same speed as for an array, because the operations simply access and modify the underlying array. Additionally, array buffers can have data efficiently added to the end. Appending an item to an array buffer takes amortized constant time. Thus, array buffers are useful for efficiently building up a large collection whenever the new items are always added to the end. scala> val buf = scala.collection.mutable.ArrayBuffer.empty[Int] buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() @@ -29,7 +29,7 @@ An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scal ## List Buffers -A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/ListBuffer.html) is like an array buffer except that it uses a linked list internally instead of an array. If you plan to convert the buffer to a list once it is built up, use a list buffer instead of an array buffer. +A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ListBuffer.html) is like an array buffer except that it uses a linked list internally instead of an array. If you plan to convert the buffer to a list once it is built up, use a list buffer instead of an array buffer. scala> val buf = scala.collection.mutable.ListBuffer.empty[Int] buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() @@ -42,7 +42,7 @@ A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/ ## StringBuilders -Just like an array buffer is useful for building arrays, and a list buffer is useful for building lists, a [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/StringBuilder.html) is useful for building strings. String builders are so commonly used that they are already imported into the default namespace. Create them with a simple `new StringBuilder`, like this: +Just like an array buffer is useful for building arrays, and a list buffer is useful for building lists, a [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html) is useful for building strings. String builders are so commonly used that they are already imported into the default namespace. Create them with a simple `new StringBuilder`, like this: scala> val buf = new StringBuilder buf: StringBuilder = @@ -55,7 +55,7 @@ Just like an array buffer is useful for building arrays, and a list buffer is us ## ArrayDeque -An [ArrayDeque](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/ArrayDeque.html) +An [ArrayDeque](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayDeque.html) is a sequence that supports efficient addition of elements in the front and in the end. It internally uses a resizable array. @@ -81,7 +81,7 @@ Scala provides mutable queues in addition to immutable ones. You use a `mQueue` ## Stacks -You saw immutable stacks earlier. There is also a mutable version, supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/Stack.html). It works exactly the same as the immutable version except that modifications happen in place. +You saw immutable stacks earlier. There is also a mutable version, supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Stack.html). It works exactly the same as the immutable version except that modifications happen in place. scala> val stack = new scala.collection.mutable.Stack[Int] stack: scala.collection.mutable.Stack[Int] = Stack() @@ -104,13 +104,13 @@ You saw immutable stacks earlier. There is also a mutable version, supported by ## Mutable ArraySeqs -Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/ArraySeq.html). +Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArraySeq.html). You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({{ site.baseurl }}/overviews/collections/arrays.html). ## Hash Tables -A hash table stores its elements in an underlying array, placing each item at a position in the array determined by the hash code of that item. Adding an element to a hash table takes only constant time, so long as there isn't already another element in the array that has the same hash code. Hash tables are thus very fast so long as the objects placed in them have a good distribution of hash codes. As a result, the default mutable map and set types in Scala are based on hash tables. You can access them also directly under the names [mutable.HashSet](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/HashSet.html) and [mutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/HashMap.html). +A hash table stores its elements in an underlying array, placing each item at a position in the array determined by the hash code of that item. Adding an element to a hash table takes only constant time, so long as there isn't already another element in the array that has the same hash code. Hash tables are thus very fast so long as the objects placed in them have a good distribution of hash codes. As a result, the default mutable map and set types in Scala are based on hash tables. You can access them also directly under the names [mutable.HashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashSet.html) and [mutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashMap.html). Hash sets and maps are used just like any other set or map. Here are some simple examples: @@ -129,11 +129,11 @@ Iteration over a hash table is not guaranteed to occur in any particular order. ## Weak Hash Maps -A weak hash map is a special kind of hash map where the garbage collector does not follow links from the map to the keys stored in it. This means that a key and its associated value will disappear from the map if there is no other reference to that key. Weak hash maps are useful for tasks such as caching, where you want to re-use an expensive function's result if the function is called again on the same key. If keys and function results are stored in a regular hash map, the map could grow without bounds, and no key would ever become garbage. Using a weak hash map avoids this problem. As soon as a key object becomes unreachable, it's entry is removed from the weak hashmap. Weak hash maps in Scala are implemented by class [WeakHashMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/WeakHashMap.html) as a wrapper of an underlying Java implementation `java.util.WeakHashMap`. +A weak hash map is a special kind of hash map where the garbage collector does not follow links from the map to the keys stored in it. This means that a key and its associated value will disappear from the map if there is no other reference to that key. Weak hash maps are useful for tasks such as caching, where you want to re-use an expensive function's result if the function is called again on the same key. If keys and function results are stored in a regular hash map, the map could grow without bounds, and no key would ever become garbage. Using a weak hash map avoids this problem. As soon as a key object becomes unreachable, it's entry is removed from the weak hashmap. Weak hash maps in Scala are implemented by class [WeakHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/WeakHashMap.html) as a wrapper of an underlying Java implementation `java.util.WeakHashMap`. ## Concurrent Maps -A concurrent map can be accessed by several threads at once. In addition to the usual [Map](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Map.html) operations, it provides the following atomic operations: +A concurrent map can be accessed by several threads at once. In addition to the usual [Map](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Map.html) operations, it provides the following atomic operations: ### Operations in Class concurrent.Map @@ -144,11 +144,11 @@ A concurrent map can be accessed by several threads at once. In addition to the | `m.replace(k, old, new)` |Replaces value associated with key `k` to `new`, if it was previously bound to `old`. | | `m.replace (k, v)` |Replaces value associated with key `k` to `v`, if it was previously bound to some value.| -`concurrent.Map` is a trait in the Scala collections library. Currently, it has two implementations. The first one is Java's `java.util.concurrent.ConcurrentMap`, which can be converted automatically into a Scala map using the [standard Java/Scala collection conversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html). The second implementation is [TrieMap](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/concurrent/TrieMap.html), which is a lock-free implementation of a hash array mapped trie. +`concurrent.Map` is a trait in the Scala collections library. Currently, it has two implementations. The first one is Java's `java.util.concurrent.ConcurrentMap`, which can be converted automatically into a Scala map using the [standard Java/Scala collection conversions]({{ site.baseurl }}/overviews/collections/conversions-between-java-and-scala-collections.html). The second implementation is [TrieMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/concurrent/TrieMap.html), which is a lock-free implementation of a hash array mapped trie. ## Mutable Bitsets -A mutable bit of type [mutable.BitSet](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/BitSet.html) set is just like an immutable one, except that it is modified in place. Mutable bit sets are slightly more efficient at updating than immutable ones, because they don't have to copy around `Long`s that haven't changed. +A mutable bit of type [mutable.BitSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/BitSet.html) set is just like an immutable one, except that it is modified in place. Mutable bit sets are slightly more efficient at updating than immutable ones, because they don't have to copy around `Long`s that haven't changed. scala> val bits = scala.collection.mutable.BitSet.empty bits: scala.collection.mutable.BitSet = BitSet() diff --git a/_overviews/collections-2.13/iterators.md b/_overviews/collections-2.13/iterators.md index 55de58cb7e..6d71f2bd1b 100644 --- a/_overviews/collections-2.13/iterators.md +++ b/_overviews/collections-2.13/iterators.md @@ -12,7 +12,7 @@ num: 15 permalink: /overviews/collections-2.13/:title.html --- -An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator `it` are `next` and `hasNext`. A call to `it.next()` will return the next element of the iterator and advance the state of the iterator. Calling `next` again on the same iterator will then yield the element one beyond the one returned previously. If there are no more elements to return, a call to `next` will throw a `NoSuchElementException`. You can find out whether there are more elements to return using [Iterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterator.html)'s `hasNext` method. +An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator `it` are `next` and `hasNext`. A call to `it.next()` will return the next element of the iterator and advance the state of the iterator. Calling `next` again on the same iterator will then yield the element one beyond the one returned previously. If there are no more elements to return, a call to `next` will throw a `NoSuchElementException`. You can find out whether there are more elements to return using [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html)'s `hasNext` method. The most straightforward way to "step through" all the elements returned by an iterator `it` uses a while-loop: @@ -78,7 +78,7 @@ destructively modified by invoking arbitrary methods. This creates the illusion the elements twice, but the effect is achieved through internal buffering. As usual, the underlying iterator `it` cannot be used directly and must be discarded. -In summary, iterators behave like collections _if one never accesses an iterator again after invoking a method on it_. The Scala collection libraries make this explicit with an abstraction [IterableOnce](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/IterableOnce.html), which is a common superclass of [Iterable](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterable.html) and [Iterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterator.html). `IterableOnce[A]` only has two methods: `iterator: Iterator[A]` and `knownSize: Int`. If an `IterableOnce` object is in fact an `Iterator`, its `iterator` operation always returns itself, in its current state, but if it is an `Iterable`, its `iterator` operation always return a new `Iterator`. A common use case of `IterableOnce` is as an argument type for methods that can take either an iterator or a collection as argument. An example is the appending method `concat` in class `Iterable`. It takes an `IterableOnce` parameter, so you can append elements coming from either an iterator or a collection. +In summary, iterators behave like collections _if one never accesses an iterator again after invoking a method on it_. The Scala collection libraries make this explicit with an abstraction [IterableOnce](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IterableOnce.html), which is a common superclass of [Iterable](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) and [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html). `IterableOnce[A]` only has two methods: `iterator: Iterator[A]` and `knownSize: Int`. If an `IterableOnce` object is in fact an `Iterator`, its `iterator` operation always returns itself, in its current state, but if it is an `Iterable`, its `iterator` operation always return a new `Iterator`. A common use case of `IterableOnce` is as an argument type for methods that can take either an iterator or a collection as argument. An example is the appending method `concat` in class `Iterable`. It takes an `IterableOnce` parameter, so you can append elements coming from either an iterator or a collection. All operations on iterators are summarized below. @@ -189,7 +189,7 @@ Sometimes you want an iterator that can "look ahead", so that you can inspect th But looking at this code more closely, it's clear that this is wrong: The code will indeed skip leading empty strings, but it will also advance `it` past the first non-empty string! -The solution to this problem is to use a buffered iterator. Class [BufferedIterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterator.html), which provides one extra method, `head`. Calling `head` on a buffered iterator will return its first element but will not advance the iterator. Using a buffered iterator, skipping empty words can be written as follows. +The solution to this problem is to use a buffered iterator. Class [BufferedIterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html), which provides one extra method, `head`. Calling `head` on a buffered iterator will return its first element but will not advance the iterator. Using a buffered iterator, skipping empty words can be written as follows. def skipEmptyWords(it: BufferedIterator[String]) = while (it.head.isEmpty) { it.next() } diff --git a/_overviews/collections-2.13/overview.md b/_overviews/collections-2.13/overview.md index 79cb856cc3..a96995b662 100644 --- a/_overviews/collections-2.13/overview.md +++ b/_overviews/collections-2.13/overview.md @@ -40,10 +40,10 @@ mutable collection means you need to understand which code changes which collection when. A collection in package `scala.collection` can be either mutable or -immutable. For instance, [collection.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/IndexedSeq.html) -is a superclass of both [collection.immutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/IndexedSeq.html) +immutable. For instance, [collection.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IndexedSeq.html) +is a superclass of both [collection.immutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html) and -[collection.mutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/IndexedSeq.html) +[collection.mutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/IndexedSeq.html) Generally, the root collections in package `scala.collection` support transformation operations affecting the whole collection, the immutable @@ -92,7 +92,7 @@ can be accessed alternatively as // is always automatically imported Other types aliased are -[Iterable](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterator.html), [LazyList](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/LazyList.html), [Vector](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/mutable/StringBuilder.html), and [Range](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/immutable/Range.html). +[Iterable](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html), [LazyList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/LazyList.html), [Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html), and [Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html). The following figure shows all collections in package `scala.collection`. These are all high-level abstract classes or traits, which diff --git a/_overviews/collections-2.13/trait-iterable.md b/_overviews/collections-2.13/trait-iterable.md index 3ae2ecfb99..e306f39f16 100644 --- a/_overviews/collections-2.13/trait-iterable.md +++ b/_overviews/collections-2.13/trait-iterable.md @@ -64,7 +64,7 @@ Two more methods exist in `Iterable` that return iterators: `grouped` and `slidi | `xs grouped size` |An iterator that yields fixed-sized "chunks" of this collection.| | `xs sliding size` |An iterator that yields a sliding fixed-sized window of elements in this collection.| | **Addition:** | | -| `xs concat ys`
    (or `xs ++ ys`) |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [IterableOnce](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/IterableOnce.html) collection, i.e., either an [Iterable](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterable.html) or an [Iterator](http://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Iterator.html).| +| `xs concat ys`
    (or `xs ++ ys`) |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [IterableOnce](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IterableOnce.html) collection, i.e., either an [Iterable](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html) or an [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html).| | **Maps:** | | | `xs map f` |The collection obtained from applying the function f to every element in `xs`.| | `xs flatMap f` |The collection obtained from applying the collection-valued function `f` to every element in `xs` and concatenating the results.| @@ -141,7 +141,7 @@ Two more methods exist in `Iterable` that return iterators: `grouped` and `slidi | **Views:** | | | `xs.view` |Produces a view over `xs`.| -In the inheritance hierarchy below `Iterable` you find three traits: [Seq](https://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [SetOps](https://www.scala-lang.org/api/{{ site.scala-213-version }}/scala/collection/SetOps.html). +In the inheritance hierarchy below `Iterable` you find three traits: [Seq](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [SetOps](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/SetOps.html). For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. diff --git a/_overviews/collections/arrays.md b/_overviews/collections/arrays.md index 512df5e432..343ebb1c74 100644 --- a/_overviews/collections/arrays.md +++ b/_overviews/collections/arrays.md @@ -13,7 +13,7 @@ languages: [ja, zh-cn] permalink: /overviews/collections/:title.html --- -[Array](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/Array.html) is a special kind of collection in Scala. On the one hand, Scala arrays correspond one-to-one to Java arrays. That is, a Scala array `Array[Int]` is represented as a Java `int[]`, an `Array[Double]` is represented as a Java `double[]` and a `Array[String]` is represented as a Java `String[]`. But at the same time, Scala arrays offer much more than their Java analogues. First, Scala arrays can be _generic_. That is, you can have an `Array[T]`, where `T` is a type parameter or abstract type. Second, Scala arrays are compatible with Scala sequences - you can pass an `Array[T]` where a `Seq[T]` is required. Finally, Scala arrays also support all sequence operations. Here's an example of this in action: +[Array](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/Array.html) is a special kind of collection in Scala. On the one hand, Scala arrays correspond one-to-one to Java arrays. That is, a Scala array `Array[Int]` is represented as a Java `int[]`, an `Array[Double]` is represented as a Java `double[]` and a `Array[String]` is represented as a Java `String[]`. But at the same time, Scala arrays offer much more than their Java analogues. First, Scala arrays can be _generic_. That is, you can have an `Array[T]`, where `T` is a type parameter or abstract type. Second, Scala arrays are compatible with Scala sequences - you can pass an `Array[T]` where a `Seq[T]` is required. Finally, Scala arrays also support all sequence operations. Here's an example of this in action: scala> val a1 = Array(1, 2, 3) a1: Array[Int] = Array(1, 2, 3) diff --git a/_overviews/collections/concrete-immutable-collection-classes.md b/_overviews/collections/concrete-immutable-collection-classes.md index 64bfb62655..b0e16eceb7 100644 --- a/_overviews/collections/concrete-immutable-collection-classes.md +++ b/_overviews/collections/concrete-immutable-collection-classes.md @@ -17,7 +17,7 @@ Scala provides many concrete immutable collection classes for you to choose from ## Lists -A [List](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html) is a finite immutable sequence. They provide constant-time access to their first element as well as the rest of the list, and they have a constant-time cons operation for adding a new element to the front of the list. Many other operations take linear time. +A [List](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/List.html) is a finite immutable sequence. They provide constant-time access to their first element as well as the rest of the list, and they have a constant-time cons operation for adding a new element to the front of the list. Many other operations take linear time. Lists have always been the workhorse for Scala programming, so not much needs to be said about them here. The major change in 2.8 is that the `List` class together with its subclass `::` and its subobject `Nil` is now defined in package `scala.collection.immutable`, where it logically belongs. There are still aliases for `List`, `Nil`, and `::` in the `scala` package, so from a user perspective, lists can be accessed as before. @@ -25,7 +25,7 @@ Another change is that lists now integrate more closely into the collections fra ## Streams -A [Stream](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Stream.html) is like a list except that its elements are computed lazily. Because of this, a stream can be infinitely long. Only those elements requested are computed. Otherwise, streams have the same performance characteristics as lists. +A [Stream](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stream.html) is like a list except that its elements are computed lazily. Because of this, a stream can be infinitely long. Only those elements requested are computed. Otherwise, streams have the same performance characteristics as lists. Whereas lists are constructed with the `::` operator, streams are constructed with the similar-looking `#::`. Here is a simple example of a stream containing the integers 1, 2, and 3: @@ -52,7 +52,7 @@ Here are the first few elements of the Fibonacci sequence starting with two ones Lists are very efficient when the algorithm processing them is careful to only process their heads. Accessing, adding, and removing the head of a list takes only constant time, whereas accessing or modifying elements later in the list takes time linear in the depth into the list. -[Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html) is a collection type (introduced in Scala 2.8) that addresses the inefficiency for random access on lists. Vectors allow accessing any element of the list in "effectively" constant time. It's a larger constant than for access to the head of a list or for reading an element of an array, but it's a constant nonetheless. As a result, algorithms using vectors do not have to be careful about accessing just the head of the sequence. They can access and modify elements at arbitrary locations, and thus they can be much more convenient to write. +[Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html) is a collection type (introduced in Scala 2.8) that addresses the inefficiency for random access on lists. Vectors allow accessing any element of the list in "effectively" constant time. It's a larger constant than for access to the head of a list or for reading an element of an array, but it's a constant nonetheless. As a result, algorithms using vectors do not have to be careful about accessing just the head of the sequence. They can access and modify elements at arbitrary locations, and thus they can be much more convenient to write. Vectors are built and modified just like any other sequence. @@ -86,7 +86,7 @@ Because vectors strike a good balance between fast random selections and fast ra ## Immutable stacks -If you need a last-in-first-out sequence, you can use a [Stack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Stack.html). You push an element onto a stack with `push`, pop an element with `pop`, and peek at the top of the stack without removing it with `top`. All of these operations are constant time. +If you need a last-in-first-out sequence, you can use a [Stack](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stack.html). You push an element onto a stack with `push`, pop an element with `pop`, and peek at the top of the stack without removing it with `top`. All of these operations are constant time. Here are some simple operations performed on a stack: @@ -106,7 +106,7 @@ Immutable stacks are used rarely in Scala programs because their functionality i ## Immutable Queues -A [Queue](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Queue.html) is just like a stack except that it is first-in-first-out rather than last-in-first-out. +A [Queue](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Queue.html) is just like a stack except that it is first-in-first-out rather than last-in-first-out. Here's how you can create an empty immutable queue: @@ -134,7 +134,7 @@ Note that `dequeue` returns a pair consisting of the element removed and the res ## Ranges -A [Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html) is an ordered sequence of integers that are equally spaced apart. For example, "1, 2, 3," is a range, as is "5, 8, 11, 14." To create a range in Scala, use the predefined methods `to` and `by`. +A [Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html) is an ordered sequence of integers that are equally spaced apart. For example, "1, 2, 3," is a range, as is "5, 8, 11, 14." To create a range in Scala, use the predefined methods `to` and `by`. scala> 1 to 3 res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3) @@ -150,7 +150,7 @@ Ranges are represented in constant space, because they can be defined by just th ## Hash Tries -Hash tries are a standard way to implement immutable sets and maps efficiently. They are supported by class [immutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/HashMap.html). Their representation is similar to vectors in that they are also trees where every node has 32 elements or 32 subtrees. But the selection of these keys is now done based on hash code. For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level. +Hash tries are a standard way to implement immutable sets and maps efficiently. They are supported by class [immutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/HashMap.html). Their representation is similar to vectors in that they are also trees where every node has 32 elements or 32 subtrees. But the selection of these keys is now done based on hash code. For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level. Hash tries strike a nice balance between reasonably fast lookups and reasonably efficient functional insertions (`+`) and deletions (`-`). That's why they underlie Scala's default implementations of immutable maps and sets. In fact, Scala has a further optimization for immutable sets and maps that contain less than five elements. Sets and maps with one to four elements are stored as single objects that just contain the elements (or key/value pairs in the case of a map) as fields. The empty immutable set and the empty immutable map is in each case a single object - there's no need to duplicate storage for those because an empty immutable set or map will always stay empty. @@ -158,7 +158,7 @@ Hash tries strike a nice balance between reasonably fast lookups and reasonably Red-black trees are a form of balanced binary tree where some nodes are designated "red" and others designated "black." Like any balanced binary tree, operations on them reliably complete in time logarithmic to the size of the tree. -Scala provides implementations of immutable sets and maps that use a red-black tree internally. Access them under the names [TreeSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeSet.html) and [TreeMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeMap.html). +Scala provides implementations of immutable sets and maps that use a red-black tree internally. Access them under the names [TreeSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/TreeSet.html) and [TreeMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/TreeMap.html). scala> scala.collection.immutable.TreeSet.empty[Int] @@ -170,7 +170,7 @@ Red-black trees are the standard implementation of `SortedSet` in Scala, because ## Immutable BitSets -A [BitSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/BitSet.html) represents a collection of small integers as the bits of a larger integer. For example, the bit set containing 3, 2, and 0 would be represented as the integer 1101 in binary, which is 13 in decimal. +A [BitSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/BitSet.html) represents a collection of small integers as the bits of a larger integer. For example, the bit set containing 3, 2, and 0 would be represented as the integer 1101 in binary, which is 13 in decimal. Internally, bit sets use an array of 64-bit `Long`s. The first `Long` in the array is for integers 0 through 63, the second is for 64 through 127, and so on. Thus, bit sets are very compact so long as the largest integer in the set is less than a few hundred or so. @@ -187,7 +187,7 @@ Operations on bit sets are very fast. Testing for inclusion takes constant time. ## List Maps -A [ListMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/ListMap.html) represents a map as a linked list of key-value pairs. In general, operations on a list map might have to iterate through the entire list. Thus, operations on a list map take time linear in the size of the map. In fact there is little usage for list maps in Scala because standard immutable maps are almost always faster. The only possible exception to this is if the map is for some reason constructed in such a way that the first elements in the list are selected much more often than the other elements. +A [ListMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/ListMap.html) represents a map as a linked list of key-value pairs. In general, operations on a list map might have to iterate through the entire list. Thus, operations on a list map take time linear in the size of the map. In fact there is little usage for list maps in Scala because standard immutable maps are almost always faster. The only possible exception to this is if the map is for some reason constructed in such a way that the first elements in the list are selected much more often than the other elements. scala> val map = scala.collection.immutable.ListMap(1->"one", 2->"two") map: scala.collection.immutable.ListMap[Int,java.lang.String] = diff --git a/_overviews/collections/concrete-mutable-collection-classes.md b/_overviews/collections/concrete-mutable-collection-classes.md index f229dc818d..432eb6df9f 100644 --- a/_overviews/collections/concrete-mutable-collection-classes.md +++ b/_overviews/collections/concrete-mutable-collection-classes.md @@ -17,7 +17,7 @@ You've now seen the most commonly used immutable collection classes that Scala p ## Array Buffers -An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayBuffer.html) buffer holds an array and a size. Most operations on an array buffer have the same speed as for an array, because the operations simply access and modify the underlying array. Additionally, array buffers can have data efficiently added to the end. Appending an item to an array buffer takes amortized constant time. Thus, array buffers are useful for efficiently building up a large collection whenever the new items are always added to the end. +An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArrayBuffer.html) buffer holds an array and a size. Most operations on an array buffer have the same speed as for an array, because the operations simply access and modify the underlying array. Additionally, array buffers can have data efficiently added to the end. Appending an item to an array buffer takes amortized constant time. Thus, array buffers are useful for efficiently building up a large collection whenever the new items are always added to the end. scala> val buf = scala.collection.mutable.ArrayBuffer.empty[Int] buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() @@ -30,7 +30,7 @@ An [ArrayBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/co ## List Buffers -A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ListBuffer.html) is like an array buffer except that it uses a linked list internally instead of an array. If you plan to convert the buffer to a list once it is built up, use a list buffer instead of an array buffer. +A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ListBuffer.html) is like an array buffer except that it uses a linked list internally instead of an array. If you plan to convert the buffer to a list once it is built up, use a list buffer instead of an array buffer. scala> val buf = scala.collection.mutable.ListBuffer.empty[Int] buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() @@ -43,7 +43,7 @@ A [ListBuffer](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/coll ## StringBuilders -Just like an array buffer is useful for building arrays, and a list buffer is useful for building lists, a [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html) is useful for building strings. String builders are so commonly used that they are already imported into the default namespace. Create them with a simple `new StringBuilder`, like this: +Just like an array buffer is useful for building arrays, and a list buffer is useful for building lists, a [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/StringBuilder.html) is useful for building strings. String builders are so commonly used that they are already imported into the default namespace. Create them with a simple `new StringBuilder`, like this: scala> val buf = new StringBuilder buf: StringBuilder = @@ -56,15 +56,15 @@ Just like an array buffer is useful for building arrays, and a list buffer is us ## Linked Lists -Linked lists are mutable sequences that consist of nodes which are linked with next pointers. They are supported by class [LinkedList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/LinkedList.html). In most languages `null` would be picked as the empty linked list. That does not work for Scala collections, because even empty sequences must support all sequence methods. In particular `LinkedList.empty.isEmpty` should return `true` and not throw a `NullPointerException`. Empty linked lists are encoded instead in a special way: Their `next` field points back to the node itself. Like their immutable cousins, linked lists are best traversed sequentially. In addition linked lists make it easy to insert an element or linked list into another linked list. +Linked lists are mutable sequences that consist of nodes which are linked with next pointers. They are supported by class [LinkedList](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/LinkedList.html). In most languages `null` would be picked as the empty linked list. That does not work for Scala collections, because even empty sequences must support all sequence methods. In particular `LinkedList.empty.isEmpty` should return `true` and not throw a `NullPointerException`. Empty linked lists are encoded instead in a special way: Their `next` field points back to the node itself. Like their immutable cousins, linked lists are best traversed sequentially. In addition linked lists make it easy to insert an element or linked list into another linked list. ## Double Linked Lists -Double linked lists are like single linked lists, except that they have besides `next` another mutable field `prev` that points to the element preceding the current node. The main benefit of that additional link is that it makes element removal very fast. Double linked lists are supported by class [DoubleLinkedList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/DoubleLinkedList.html). +Double linked lists are like single linked lists, except that they have besides `next` another mutable field `prev` that points to the element preceding the current node. The main benefit of that additional link is that it makes element removal very fast. Double linked lists are supported by class [DoubleLinkedList](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/DoubleLinkedList.html). ## Mutable Lists -A [MutableList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/MutableList.html) consists of a single linked list together with a pointer that refers to the terminal empty node of that list. This makes list append a constant time operation because it avoids having to traverse the list in search for its terminal node. [MutableList](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/MutableList.html) is currently the standard implementation of [mutable.LinearSeq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/LinearSeq.html) in Scala. +A [MutableList](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/MutableList.html) consists of a single linked list together with a pointer that refers to the terminal empty node of that list. This makes list append a constant time operation because it avoids having to traverse the list in search for its terminal node. [MutableList](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/MutableList.html) is currently the standard implementation of [mutable.LinearSeq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/LinearSeq.html) in Scala. ## Queues @@ -85,13 +85,13 @@ Scala provides mutable queues in addition to immutable ones. You use a `mQueue` ## Array Sequences -Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArraySeq.html). +Array sequences are mutable sequences of fixed size which store their elements internally in an `Array[Object]`. They are implemented in Scala by class [ArraySeq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArraySeq.html). You would typically use an `ArraySeq` if you want an array for its performance characteristics, but you also want to create generic instances of the sequence where you do not know the type of the elements and you do not have a `ClassTag` to provide it at run-time. These issues are explained in the section on [arrays]({{ site.baseurl }}/overviews/collections/arrays.html). ## Stacks -You saw immutable stacks earlier. There is also a mutable version, supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Stack.html). It works exactly the same as the immutable version except that modifications happen in place. +You saw immutable stacks earlier. There is also a mutable version, supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/Stack.html). It works exactly the same as the immutable version except that modifications happen in place. scala> val stack = new scala.collection.mutable.Stack[Int] stack: scala.collection.mutable.Stack[Int] = Stack() @@ -114,11 +114,11 @@ You saw immutable stacks earlier. There is also a mutable version, supported by ## Array Stacks -[ArrayStack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayStack.html) is an alternative implementation of a mutable stack which is backed by an Array that gets re-sized as needed. It provides fast indexing and is generally slightly more efficient for most operations than a normal mutable stack. +[ArrayStack](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArrayStack.html) is an alternative implementation of a mutable stack which is backed by an Array that gets re-sized as needed. It provides fast indexing and is generally slightly more efficient for most operations than a normal mutable stack. ## Hash Tables -A hash table stores its elements in an underlying array, placing each item at a position in the array determined by the hash code of that item. Adding an element to a hash table takes only constant time, so long as there isn't already another element in the array that has the same hash code. Hash tables are thus very fast so long as the objects placed in them have a good distribution of hash codes. As a result, the default mutable map and set types in Scala are based on hash tables. You can access them also directly under the names [mutable.HashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashSet.html) and [mutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashMap.html). +A hash table stores its elements in an underlying array, placing each item at a position in the array determined by the hash code of that item. Adding an element to a hash table takes only constant time, so long as there isn't already another element in the array that has the same hash code. Hash tables are thus very fast so long as the objects placed in them have a good distribution of hash codes. As a result, the default mutable map and set types in Scala are based on hash tables. You can access them also directly under the names [mutable.HashSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/HashSet.html) and [mutable.HashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/HashMap.html). Hash sets and maps are used just like any other set or map. Here are some simple examples: @@ -137,11 +137,11 @@ Iteration over a hash table is not guaranteed to occur in any particular order. ## Weak Hash Maps -A weak hash map is a special kind of hash map where the garbage collector does not follow links from the map to the keys stored in it. This means that a key and its associated value will disappear from the map if there is no other reference to that key. Weak hash maps are useful for tasks such as caching, where you want to re-use an expensive function's result if the function is called again on the same key. If keys and function results are stored in a regular hash map, the map could grow without bounds, and no key would ever become garbage. Using a weak hash map avoids this problem. As soon as a key object becomes unreachable, it's entry is removed from the weak hashmap. Weak hash maps in Scala are implemented by class [WeakHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/WeakHashMap.html) as a wrapper of an underlying Java implementation `java.util.WeakHashMap`. +A weak hash map is a special kind of hash map where the garbage collector does not follow links from the map to the keys stored in it. This means that a key and its associated value will disappear from the map if there is no other reference to that key. Weak hash maps are useful for tasks such as caching, where you want to re-use an expensive function's result if the function is called again on the same key. If keys and function results are stored in a regular hash map, the map could grow without bounds, and no key would ever become garbage. Using a weak hash map avoids this problem. As soon as a key object becomes unreachable, it's entry is removed from the weak hashmap. Weak hash maps in Scala are implemented by class [WeakHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/WeakHashMap.html) as a wrapper of an underlying Java implementation `java.util.WeakHashMap`. ## Concurrent Maps -A concurrent map can be accessed by several threads at once. In addition to the usual [Map](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Map.html) operations, it provides the following atomic operations: +A concurrent map can be accessed by several threads at once. In addition to the usual [Map](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Map.html) operations, it provides the following atomic operations: ### Operations in class ConcurrentMap @@ -156,7 +156,7 @@ A concurrent map can be accessed by several threads at once. In addition to the ## Mutable Bitsets -A mutable bit of type [mutable.BitSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/BitSet.html) set is just like an immutable one, except that it is modified in place. Mutable bit sets are slightly more efficient at updating than immutable ones, because they don't have to copy around `Long`s that haven't changed. +A mutable bit of type [mutable.BitSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/BitSet.html) set is just like an immutable one, except that it is modified in place. Mutable bit sets are slightly more efficient at updating than immutable ones, because they don't have to copy around `Long`s that haven't changed. scala> val bits = scala.collection.mutable.BitSet.empty bits: scala.collection.mutable.BitSet = BitSet() diff --git a/_overviews/collections/conversions-between-java-and-scala-collections.md b/_overviews/collections/conversions-between-java-and-scala-collections.md index c476d4369c..7d1f3d150a 100644 --- a/_overviews/collections/conversions-between-java-and-scala-collections.md +++ b/_overviews/collections/conversions-between-java-and-scala-collections.md @@ -15,7 +15,7 @@ permalink: /overviews/collections/:title.html Like Scala, Java also has a rich collections library. There are many similarities between the two. For instance, both libraries know iterators, iterables, sets, maps, and sequences. But there are also important differences. In particular, the Scala libraries put much more emphasis on immutable collections, and provide many more operations that transform a collection into a new one. -Sometimes you might need to pass from one collection framework to the other. For instance, you might want to access an existing Java collection as if it were a Scala collection. Or you might want to pass one of Scala's collections to a Java method that expects its Java counterpart. It is quite easy to do this, because Scala offers implicit conversions between all the major collection types in the [JavaConverters](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConverters$.html) object. In particular, you will find bidirectional conversions between the following types. +Sometimes you might need to pass from one collection framework to the other. For instance, you might want to access an existing Java collection as if it were a Scala collection. Or you might want to pass one of Scala's collections to a Java method that expects its Java counterpart. It is quite easy to do this, because Scala offers implicit conversions between all the major collection types in the [JavaConverters](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/JavaConverters$.html) object. In particular, you will find bidirectional conversions between the following types. Iterator <=> java.util.Iterator @@ -27,7 +27,7 @@ Sometimes you might need to pass from one collection framework to the other. For mutable.Map <=> java.util.Map mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap -To enable these conversions, simply import them from the [JavaConverters](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/JavaConverters$.html) object: +To enable these conversions, simply import them from the [JavaConverters](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/JavaConverters$.html) object: scala> import collection.JavaConverters._ import collection.JavaConverters._ diff --git a/_overviews/collections/iterators.md b/_overviews/collections/iterators.md index e771513c0c..975824d498 100644 --- a/_overviews/collections/iterators.md +++ b/_overviews/collections/iterators.md @@ -13,7 +13,7 @@ languages: [ja, zh-cn] permalink: /overviews/collections/:title.html --- -An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator `it` are `next` and `hasNext`. A call to `it.next()` will return the next element of the iterator and advance the state of the iterator. Calling `next` again on the same iterator will then yield the element one beyond the one returned previously. If there are no more elements to return, a call to `next` will throw a `NoSuchElementException`. You can find out whether there are more elements to return using [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html)'s `hasNext` method. +An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator `it` are `next` and `hasNext`. A call to `it.next()` will return the next element of the iterator and advance the state of the iterator. Calling `next` again on the same iterator will then yield the element one beyond the one returned previously. If there are no more elements to return, a call to `next` will throw a `NoSuchElementException`. You can find out whether there are more elements to return using [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html)'s `hasNext` method. The most straightforward way to "step through" all the elements returned by an iterator `it` uses a while-loop: @@ -76,7 +76,7 @@ destructively modified by invoking arbitrary methods. This creates the illusion the elements twice, but the effect is achieved through internal buffering. As usual, the underlying iterator `it` cannot be used directly and must be discarded. -In summary, iterators behave like collections _if one never accesses an iterator again after invoking a method on it_. The Scala collection libraries make this explicit with an abstraction [TraversableOnce](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/TraversableOnce.html), which is a common superclass of [Traversable](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Traversable.html) and [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html). As the name implies, `TraversableOnce` objects can be traversed using `foreach` but the state of that object after the traversal is not specified. If the `TraversableOnce` object is in fact an `Iterator`, it will be at its end after the traversal, but if it is a `Traversable`, it will still exist as before. A common use case of `TraversableOnce` is as an argument type for methods that can take either an iterator or a traversable as argument. An example is the appending method `++` in class `Traversable`. It takes a `TraversableOnce` parameter, so you can append elements coming from either an iterator or a traversable collection. +In summary, iterators behave like collections _if one never accesses an iterator again after invoking a method on it_. The Scala collection libraries make this explicit with an abstraction [TraversableOnce](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/TraversableOnce.html), which is a common superclass of [Traversable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html) and [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html). As the name implies, `TraversableOnce` objects can be traversed using `foreach` but the state of that object after the traversal is not specified. If the `TraversableOnce` object is in fact an `Iterator`, it will be at its end after the traversal, but if it is a `Traversable`, it will still exist as before. A common use case of `TraversableOnce` is as an argument type for methods that can take either an iterator or a traversable as argument. An example is the appending method `++` in class `Traversable`. It takes a `TraversableOnce` parameter, so you can append elements coming from either an iterator or a traversable collection. All operations on iterators are summarized below. @@ -186,7 +186,7 @@ Sometimes you want an iterator that can "look ahead", so that you can inspect th But looking at this code more closely, it's clear that this is wrong: The code will indeed skip leading empty strings, but it will also advance `it` past the first non-empty string! -The solution to this problem is to use a buffered iterator. Class [BufferedIterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html), which provides one extra method, `head`. Calling `head` on a buffered iterator will return its first element but will not advance the iterator. Using a buffered iterator, skipping empty words can be written as follows. +The solution to this problem is to use a buffered iterator. Class [BufferedIterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/BufferedIterator.html) is a subclass of [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html), which provides one extra method, `head`. Calling `head` on a buffered iterator will return its first element but will not advance the iterator. Using a buffered iterator, skipping empty words can be written as follows. def skipEmptyWords(it: BufferedIterator[String]) = while (it.head.isEmpty) { it.next() } diff --git a/_overviews/parallel-collections/concrete-parallel-collections.md b/_overviews/parallel-collections/concrete-parallel-collections.md index d171a4968a..3c82e34930 100644 --- a/_overviews/parallel-collections/concrete-parallel-collections.md +++ b/_overviews/parallel-collections/concrete-parallel-collections.md @@ -15,7 +15,7 @@ permalink: /overviews/parallel-collections/:title.html ## Parallel Array -A [ParArray](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParArray.html) +A [ParArray](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParArray.html) sequence holds a linear, contiguous array of elements. This means that the elements can be accessed and updated efficiently by modifying the underlying array. Traversing the @@ -54,7 +54,7 @@ parallel array it was obtained from. ## Parallel Vector -A [ParVector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParVector.html) +A [ParVector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParVector.html) is an immutable sequence with a low-constant factor logarithmic access and update time. @@ -76,16 +76,16 @@ combiners will be combined using concatenation and transformer methods will become much more efficient. Parallel vector is a parallel counterpart of the sequential -[Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html), +[Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html), so conversion between the two takes constant time. ## Parallel Range -A [ParRange](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParRange.html) +A [ParRange](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParRange.html) is an ordered sequence of elements equally spaced apart. A parallel range is created in a similar way as the sequential -[Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html): +[Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html): scala> 1 to 3 par res0: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3) @@ -105,9 +105,9 @@ another using the `seq` and `par` methods. Parallel hash tables store their elements in an underlying array and place them in the position determined by the hash code of the respective element. Parallel mutable hash sets -([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParHashSet.html)) +([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParHashSet.html)) and parallel mutable hash maps -([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParHashMap.html)) +([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParHashMap.html)) are based on hash tables. scala> val phs = scala.collection.parallel.mutable.ParHashSet(1 until 2000: _*) @@ -142,9 +142,9 @@ versa. Parallel hash tries are a parallel counterpart of the immutable hash tries, which are used to represent immutable sets and maps efficiently. They are supported by classes -[immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParHashSet.html) +[immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParHashSet.html) and -[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/immutable/ParHashMap.html). +[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/immutable/ParHashMap.html). scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _*) phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69, 809, 629, 365, 138, 760, 101, 479,... @@ -165,9 +165,9 @@ by using the `seq` and `par` method in constant time. ## Parallel Concurrent Tries -A [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/concurrent/TrieMap.html) +A [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/concurrent/TrieMap.html) is a concurrent thread-safe map, whereas a -[mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParTrieMap.html) +[mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParTrieMap.html) is its parallel counterpart. While most concurrent data structures do not guarantee consistent traversal if the data structure is modified during traversal, Ctries guarantee that updates are only visible in the next iteration. This diff --git a/api/all.md b/api/all.md index 77ecd28618..7c655d88d0 100644 --- a/api/all.md +++ b/api/all.md @@ -6,6 +6,10 @@ includeTOC: true ## Latest releases +* Scala 2.13.0 + * [Library API](https://www.scala-lang.org/api/2.13.0/) + * [Compiler API](https://www.scala-lang.org/api/2.13.0/scala-compiler/scala/) + * [Reflection API](https://www.scala-lang.org/api/2.13.0/scala-reflect/scala/reflect/) * Scala 2.12.8 * [Library API](https://www.scala-lang.org/api/2.12.8/) * [Compiler API](https://www.scala-lang.org/api/2.12.8/scala-compiler/scala/) @@ -26,12 +30,14 @@ includeTOC: true * [Continuations API](https://www.scala-lang.org/files/archive/api/2.11.12/scala-continuations-library/#scala.util.continuations.package) * [Scala 2.10.7](https://www.scala-lang.org/api/2.10.7/) + ## Nightly builds From 7a3d45dd1ab648313aba06fe3b5ec5bbaed74f07 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 08:35:59 +0800 Subject: [PATCH 0609/3174] Fix#1368, fill a word for the syntax correctness. --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 1d4e421eea..472b2ebe3b 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -267,7 +267,7 @@ A property of functions that are independent of temporal context and have no sid A variable in a running Scala program always _refers_ to some object. Even if that variable is assigned to `null`, it conceptually refers to the `Null` object. At runtime, an object may be implemented by a Java object or a value of a primitive type, but Scala allows programmers to think at a higher level of abstraction about their code as they imagine it running. See also [reference](#reference). * #### refinement type -A type formed by supplying a base type a number of members inside curly braces. The members in the curly braces refine the types that are present in the base type. For example, the type of “animal that eats grass” is `Animal { type SuitableFood = Grass }`. +A type formed by supplying a base type with a number of members inside curly braces. The members in the curly braces refine the types that are present in the base type. For example, the type of “animal that eats grass” is `Animal { type SuitableFood = Grass }`. * #### result An expression in a Scala program yields a _result_. The result of every expression in Scala is an object. From 967cf14521537b389cfa449d17913c13ea74524c Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 08:44:57 +0800 Subject: [PATCH 0610/3174] Fix#1369, replace quote with italic underbars enclosing to make the term consistent with other terms. --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 1d4e421eea..6a36a9b3b5 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -276,7 +276,7 @@ An expression in a Scala program yields a _result_. The result of every expressi A method’s _result type_ is the type of the value that results from calling the method. (In Java, this concept is called the return type.) * #### return -A function in a Scala program `returns` a value. You can call this value the [result](#result) of the function. You can also say the function _results in_ the value. The result of every function in Scala is an object. +A function in a Scala program _returns_ a value. You can call this value the [result](#result) of the function. You can also say the function _results in_ the value. The result of every function in Scala is an object. * #### runtime The Java Virtual Machine, or [JVM](#jvm), that hosts a running Scala program. Runtime encompasses both the virtual machine, as defined by the Java Virtual Machine Specification, and the runtime libraries of the Java API and the standard Scala API. The phrase at run time (with a space between run and time) means when the program is running, and contrasts with compile time. From 7eb53d367d14abab588135ab4da159833e15ad85 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 09:20:49 +0800 Subject: [PATCH 0611/3174] Fix issue#1372, add the lost right of parentheses. --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 1d4e421eea..7cb6cdb063 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -291,7 +291,7 @@ A file containing top level definitions and statements, which can be run directl The value being matched on in a `match` expression. For example, in “`s match { case _ => }`”, the selector is `s`. * #### self type -A _self type_ of a trait is the assumed type of `this`, the receiver, to be used within the trait. Any concrete class that mixes in the trait must ensure that its type conforms to the trait’s self type. The most common use of self types is for dividing a large class into several traits (as described in Chapter 29 of [Programming in Scala](http://www.artima.com/shop/programming_in_scala). +A _self type_ of a trait is the assumed type of `this`, the receiver, to be used within the trait. Any concrete class that mixes in the trait must ensure that its type conforms to the trait’s self type. The most common use of self types is for dividing a large class into several traits (as described in Chapter 29 of [Programming in Scala](http://www.artima.com/shop/programming_in_scala)). * #### semi-structured data XML data is semi-structured. It is more structured than a flat binary file or text file, but it does not have the full structure of a programming language’s data structures. From 556c843c21b04034e1a3fba578b4e57707b81716 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 14:49:35 +0800 Subject: [PATCH 0612/3174] Fix issue#1374, remove bar and space between word 'between'. --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 1d4e421eea..165accc0db 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -381,7 +381,7 @@ See [unreachable](#unreachable). The result of any computation or expression in Scala is a _value_, and in Scala, every value is an object. The term value essentially means the image of an object in memory (on the JVM’s heap or stack). * #### value type -A _value type_ is any subclass of `AnyVal`, such as `Int`, `Double`, or `Unit`. This term has meaning at the level of Scala source code. At runtime, instances of value types that correspond to Java primitive types may be implemented in terms of primitive type values or instances of wrapper types, such as `java.lang.Integer`. Over the lifetime of a value type instance, the runtime may transform it back and forth be- tween primitive and wrapper types (_i.e._, to box and unbox it). +A _value type_ is any subclass of `AnyVal`, such as `Int`, `Double`, or `Unit`. This term has meaning at the level of Scala source code. At runtime, instances of value types that correspond to Java primitive types may be implemented in terms of primitive type values or instances of wrapper types, such as `java.lang.Integer`. Over the lifetime of a value type instance, the runtime may transform it back and forth between primitive and wrapper types (_i.e._, to box and unbox it). * #### variable A named entity that refers to an object. A variable is either a `val` or a `var`. Both `val`s and `var`s must be initialized when defined, but only `var`s can be later reassigned to refer to a different object. From 9ff917defe6b08e378fcf973448500b6488c66d3 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 15:29:48 +0800 Subject: [PATCH 0613/3174] Fix issue#1376, replace in with of for 'at that point of time' --- glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary/index.md b/glossary/index.md index 1d4e421eea..d0b9f78cba 100644 --- a/glossary/index.md +++ b/glossary/index.md @@ -372,7 +372,7 @@ A method’s _type signature_ comprises its name, the number, order, and types o The _uniform access principle_ states that variables and parameterless functions should be accessed using the same syntax. Scala supports this principle by not allowing parentheses to be placed at call sites of parameterless functions. As a result, a parameterless function definition can be changed to a `val`, or _vice versa_, without affecting client code. * #### unreachable -At the Scala level, objects can become _unreachable_, at which point the memory they occupy may be reclaimed by the runtime. Unreachable does not necessarily mean unreferenced. Reference types (instances of `AnyRef`) are implemented as objects that reside on the JVM’s heap. When an instance of a reference type becomes unreachable, it indeed becomes unreferenced, and is available for garbage collection. Value types (instances of `AnyVal`) are implemented as both primitive type values and as instances of Java wrapper types (such as `java.lang.Integer`), which reside on the heap. Value type instances can be boxed (converted from a primitive value to a wrapper object) and unboxed (converted from a wrapper object to a primitive value) throughout the lifetime of the variables that refer to them. If a value type instance currently represented as a wrapper object on the JVM’s heap becomes unreachable, it indeed becomes unreferenced, and is available for garbage collection. But if a value type currently represented as a primitive value becomes unreachable, then it does not become unreferenced, because it does not exist as an object on the JVM’s heap at that point in time. The runtime may reclaim memory occupied by unreachable objects, but if an Int, for example, is implemented at run time by a primitive Java int that occupies some memory in the stack frame of an executing method, then the memory for that object is “reclaimed” when the stack frame is popped as the method completes. Memory for reference types, such as `Strings`, may be reclaimed by the JVM’s garbage collector after they become unreachable. +At the Scala level, objects can become _unreachable_, at which point the memory they occupy may be reclaimed by the runtime. Unreachable does not necessarily mean unreferenced. Reference types (instances of `AnyRef`) are implemented as objects that reside on the JVM’s heap. When an instance of a reference type becomes unreachable, it indeed becomes unreferenced, and is available for garbage collection. Value types (instances of `AnyVal`) are implemented as both primitive type values and as instances of Java wrapper types (such as `java.lang.Integer`), which reside on the heap. Value type instances can be boxed (converted from a primitive value to a wrapper object) and unboxed (converted from a wrapper object to a primitive value) throughout the lifetime of the variables that refer to them. If a value type instance currently represented as a wrapper object on the JVM’s heap becomes unreachable, it indeed becomes unreferenced, and is available for garbage collection. But if a value type currently represented as a primitive value becomes unreachable, then it does not become unreferenced, because it does not exist as an object on the JVM’s heap at that point of time. The runtime may reclaim memory occupied by unreachable objects, but if an Int, for example, is implemented at run time by a primitive Java int that occupies some memory in the stack frame of an executing method, then the memory for that object is “reclaimed” when the stack frame is popped as the method completes. Memory for reference types, such as `Strings`, may be reclaimed by the JVM’s garbage collector after they become unreachable. * #### unreferenced See [unreachable](#unreachable). From c9cfb6e93ee0070f80c61f03eb2d5fd469bc97db Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 16:19:14 +0800 Subject: [PATCH 0614/3174] This is to add the skeleton of translatable glossary, and the fix of zh-cn for issue#1224. --- _config.yml | 3 + {glossary => _glossary}/index.md | 2 + _layouts/glossary.html | 22 +- _zh-cn/glossary/index.md | 397 +++++++++++++++++++++++++++++++ 4 files changed, 423 insertions(+), 1 deletion(-) rename {glossary => _glossary}/index.md (99%) create mode 100644 _zh-cn/glossary/index.md diff --git a/_config.yml b/_config.yml index e7564efd1a..320c7a9839 100644 --- a/_config.yml +++ b/_config.yml @@ -29,6 +29,9 @@ collections: tutorials: output: true permalink: /:collection/:path.html + glossary: + output: true + permalink: /:collection/:path.html sips: output: true permalink: /:collection/:path.html diff --git a/glossary/index.md b/_glossary/index.md similarity index 99% rename from glossary/index.md rename to _glossary/index.md index 1d4e421eea..95ef0df59f 100644 --- a/glossary/index.md +++ b/_glossary/index.md @@ -1,6 +1,8 @@ --- layout: glossary title: Glossary + +languages: [zh-cn] ---
    Glossary from the definitive book on Scala, Programming in Scala.
    diff --git a/_layouts/glossary.html b/_layouts/glossary.html index 62b50b0a39..59a14bf8f9 100644 --- a/_layouts/glossary.html +++ b/_layouts/glossary.html @@ -10,7 +10,27 @@
    {{content}}
    - + {% if page.languages %} + + {% elsif page.language %} + {% assign engPath = page.id | remove_first: "/" | remove_first: page.language | append: '.html' %} + {% assign engPg = site.glossary | first %} + + {% endif %} {% include contributors-list.html %} diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md new file mode 100644 index 0000000000..bc7aff3156 --- /dev/null +++ b/_zh-cn/glossary/index.md @@ -0,0 +1,397 @@ +--- +layout: glossary +title: Glossary + +language: zh-cn +--- + +
    该术语表摘自Scala权威书籍《Programming in Scala
    + +
    + + + +   +
    + +* #### 代数数据类型(algebraic data type) +通过提供若干个带有独立构造器的备选项来定义的类型。它一般通过模式匹配的方式来结构类型,在规约语言和函数式编程语言中常见到这个概念。Scala可通过案例类来模拟代数数据类型。 + +* #### 备选项(alternative) +match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。备选项的别名是 _案例_(_case_)。 + +* #### 注解(annotation) +注解一般出现在源码中,并附加到语法的某个部分。注解对于计算机来说都是可处理的,所以可以用来有效的增加Scala扩展。 + +* #### 匿名类(anonymous class) +匿名类是由Scala编译器根据一种new表达式生成的合成子类,这种new表达式由类名或特质名后面紧跟一对花括号组成。花括号内包含了匿名子类的构造体,可为空,不过一旦跟在new后面名称指向的特质或类包含了抽象成员,则这些抽象成员就必须在其匿名子类的构造体内具化,即在花括号内要实现这些成员。 + +* #### 匿名函数(anonymous function) +[函数字面量](#function-literal)的另一种叫法。 + +* #### 应用(apply) +方法、函数或闭包应用于参数,意思是说通过这些实参来调用方法、函数或闭包。 + +* #### 实参(argument) +在函数调用过程中实参被传给函数的各个参数,其中参数就是指向实参的变量,实参则是调用发生时被传入的对象。另外,应用程序都可以获取被传入单例对象的main方法且类型为`Array[String]`的实参(来自命令行)。 + +* #### 赋值(assign) +可把对象赋值给变量,之后,变量就会指向对象。 + +* #### 辅助构造器(auxiliary constructor) +在类定义体花括号里面定义的所有附加构造器,其形似名为`this`但无结果类型的方法定义。 + +* #### 块(block) +被花括号围起来的一个或多个表达式和声明。求值块的时候,块内所有表达式和声明会被顺序处理,然后会返回最后一个表达式的值作为其自身的值。块通常被用来作为构造体,诸如函数、[for表达式](#for-expression)、`while`循环以及其他任何需要把语句组织到一起的地方,都会用到块。更正式点说,块是一个只其副作用和结果值对外可见的封装构造体。因此,类或对象的花括号是不会形成块的,因其内部定义字段和方法均对外可见。这样的花括号形成的是模板。 + +* #### 绑定变量(bound variable) +表达式的绑定变量是定义和使用都在表达式内部的变量。例如,在函数字面量表达式`(x: Int) => (x, y)`里面,`x`和`y`都被用到了,但只有`x`被绑定了,因为它在表达式中被定义为一个`Int`变量,并且它也是表达式所描述函数的唯一实参。 + +* #### 传名参数(by-name parameter) +参数类型前面带有`=>`的参数,如`(x: => Int)`。传名参数对应的实参求值不在方法被调用前,而是在每次方法通过名称引用到参数的时候。参数若不是传名的,则定是传值的。 + +* #### 传值参数(by-value parameter) +参数类型前面不带`=>`的参数,如`(x: Int)`。传值参数对应的实参是在方法调用前被求值的。传值参数是相对传名参数而言的。 + +* #### 类(class) +通过关键字`class`来定义的类,可抽象可具体,且在实例化时可用类型和值对其进行参数化处理。比如`new Array[String](2)`,被实例化的类是`Array`,产生的值类型为`Array[String]`。带有类型参数的类被称为 _类型构造器_ ,也可说成是类型具有类属性,如:类型`Array[String]`具有的类属性是`Array`。 + +* #### 闭包(closure) +可以捕获自由变量,或者说"关闭"函数创建时可见变量的函数对象。 + +* #### 伴生类(companion class) +和定义在相同源文件中的单例对象共享同一个名称的类,这样的类就叫做那个单例对象的伴生类。 + +* #### 伴生对象(companion object) +和定义在相同源文件中的类共享同一个名称的单例对象。伴生对象和伴生类具备访问彼此私有成员的能力。另外,类不管被用在何处,其伴生对象中定义的任何隐式转换都在其作用域内。 + +* #### 逆变(contravariant) +逆变标注可应用于类或特质的类型参数上,把减号(-)置于类型参数前即可。标注为逆变后类或特质的子类型将逆向(向相反的方向)协变于类型标注的参数。比如,`Function1`的第一个类型参数就是逆变的,所以`Function1[Any, Any]`是`Function1[String, Any]`的子类。 + +* #### 协变(covariant) +协变标注可应用于类或特质的类型参数上,把加号(+)置于类型参数前即可。标注为协变后类或特质的子类型将正向(向相同的方向)协变于类型标注的参数。比如,`List`的类型参数是协变的,所以`List[String]`是`List[Any]`的子类。 + +* #### 柯里化(currying) +把函数写成多个参数列表的方式。例如:`def f(x: Int)(y: Int)`是一个带有两个参数列表的柯里化函数。应用柯里化函数时需传入若干个实参列表,像`f(3)(4)`这样。不过也可以写成柯里化函数的 _部分应用_(partial application),像`f(3)`这样。 + +* #### 声明(declare) +可以通过 _声明_ 抽象的字段、方法或类型来赋给实体一个名称,但是没有具体实现。声明和定义最关键的差异就是定义会为命名实体创建具体实现,而声明则不会。 + +* #### 定义(define) +在Scala程序中若提到 _定义_ 什么东西,就是说给它赋个名称并给出实现。可以定义的东西包括类、特质、单例对象、字段、方法、本地函数、本地变量等。由于提到定义常常会涉及到某种具体实现,故而抽象成员应为声明而非定义。 + +* #### 直接子类(direct subclass) +类是其 _直接子类_ 的直接超类。 + +* #### 直接超类(direct superclass) +从某个类直接衍生出类或特质,或者说在继承层级结构最接近自己的上层的某个类,这样的类就是直接超类。若类`Child`的可选的extends子句中含有类`Parent`,则`Parent`就是`Child`的直接超类。若`Child`的可选extends子句中含有特质,则特质的直接超类也是`Child`的直接超类。若`Child`没有extends子句,则`AnyRef`就是`Child`的直接超类。若类的直接超类带有类型参数,比如`Child extends Parent[String]`,`Child`的直接超类依旧是`Parent`,而不是`Parent[String]`。另一方面,`Parent[String]`应该叫做`Child`的直接超类型。参见[超类型](#supertype)了解更多关于类和类型间的区别。 + +* #### 相等性(equality) +在没有条件限制的情况下使用时,_相等性_ 就是`==`所表达的两个值之间的关系。参见[引用相等性](#reference-equality)。 + +* #### 存在类型(existential type) +存在类型包含未知类型变量的引用。比如:`Array[T] forSome { type T }`是个存在类型,是`T`的数组,而`T`是某个完全未知的类型,关于`T`唯一能够假定的是它是确定存在的。尽管这个假定很虚,但是至少意味着`Array[T] forSome { type T }`确实是个数组,而不是香蕉什么的东西。 + +* #### 表达式(expression) +任何能够得到结果的Scala代码,也可说成表达式求值为某个结果或结果为某个值。 + +* #### 过滤器(filter) +[for表达式](#for-expression)中的`if`及跟在其后的布尔表达式。在`for(i <- 1 to 10; if i % 2 == 0)`中,过滤器为"`if i % 2 == 0`"。`if`右边的值就是[过滤器表达式](#filter-expression),也称为守卫。 + +* #### 过滤器表达式(filter expression) +过滤器表达式就是[for表达式](#for-expression)里面跟在`if`后面的布尔表达式。`for( i <- 1 to 10 ; if i % 2 == 0)`的过滤器表达式为"`i % 2 == 0`"。 + +* #### 头等函数(first-class function) +Scala支持 _头等函数_ ,意味着可以通过函数字面量语法来表达函数。如:`(x: Int) => x + 1`,并且函数可由对象来表达,叫做[函数值](#function-value)。 + +* #### for推解式(for comprehension) +_for推解式_ 是[for表达式](#for-expression)的一种,一般用来创建新的集合。对`for`推解式的每次迭代,[yield](#yield)子句都会定义新集合的一个元素。比如:`for (i <- (0 until 2); j <- (2 until 4)) yield (i, j)`将返回集合`Vector((0,2), (0,3), (1,2), (1,3))`。 + +* #### for表达式(for expression) +_for表达式_ 要么是个[for循环](#for-loop),可以迭代一个或多个集合,要么是个[for推解式](#for-comprehension),可以从一个或多个集合的元素中推解出一个新的集合。`for`表达式建于[生成器](#generator)、[过滤器](#filter)、变量定义和[yield](#yield)子句(针对[for推解式](#for-comprehension))基础之上, + +* #### for循环(for loop) +_for循环_ 是[for表达式](#for-expression)的一种,一般用来循环迭代一个或多个集合。因为`for`循环返回unit,所以经常被用来产生副作用。比如:`for (i <- 0 until 100) println(i)`打印数字0到99。 + +* #### 自由变量(free variable) +一个表达式的 _自由变量_ 指的是在表达式中使用但不定义在其中的变量。例如,在函数字面量表达式`(x: Int) => (x, y)`中,变量`x`和`y`都被用到了,但只有`y`是自由变量,因其未在表达式中定义。 + +* #### 函数(function) +_函数_ 可通过一列实参来[调用](#invoke)然后产生结果。函数一般具有参数列表、函数体和结果类型。作为类、特质或单例对象的函数叫做[方法](#method)。定义在其他函数内部的函数叫做[本地函数](#local-function)。结果类型为`Unit`的函数叫做[过程](#procedure)。源码里面的匿名函数叫做[函数字面量](#function-literal)。运行时,函数字面量被实例化为对象,叫做[函数值](#function-value)。 + +* #### 函数字面量(function literal) +在Scala源码中的无名函数,通过函数字面量语法来特别对待。比如:`(x: Int, y: Int) => x + y`。 + +* #### 函数值(function value) +可以像其他函数一样被调用的函数对象。函数值的类一般是继承了`scala`包中的`FunctionN`(比如`Function0`,`Function1`等)这类特质的其中之一,且在源码中常通过[函数字面量](#function-literal)语法来表示。当函数值的apply方法被调用时就说这个函数值被调用。捕获自由变量的函数值为[闭包](#closure)。 + +* #### 函数式风格(functional style) +_函数式风格_ 编程注重函数和求值结果而非操作发生的顺序。这种风格的特征是可传递函数值给循环方法、不可变数据、方法无副作用,是像Haskell和Erlang等这些语言的主要范式,与[命令式风格](#imperative-style)相对应。 + +* #### 生成器(generator) +生成器在[for表达式](#for-expression)中定义一个命名的val变量并赋予其一系列值。比如:`for(i <- 1 to 10)`的生成器是"`i <- 1 to 10`",`<-`右边的值是[generator表达式](#generator-expression)。 + +* #### 生成器表达式(generator expression) +生成器表达式在[for表达式](#for-expression)中生成一些列值。比如:`for(i <- 1 to 10)`的生成器表达式是"`1 to 10`"。 + +* #### 泛型类(generic class) +带有类型参数的类。例如,因`scala.List`带一类型参数,故其为泛型类。 + +* #### 泛型特质(generic trait) +带有类型参数的特质。例如,因`scala.collection.Set`带一类型参数,故其为泛型特质。 + +* #### 守卫(guard) +参见[过滤器](#filter). + +* #### 助手函数(helper function) +目的是为一个或多个其他邻近函数提供服务的函数。助手函数常实现为本地函数。 + +* #### 助手方法(helper method) +作为类成员的[助手函数](#helper-function)。助手方法常为私有方法。 + +* #### 不可变(immutable) +若对象的值在任何对客户端可见的方式下创建后不会被修改则称对象是 _不可变_ 的。对象既可以是不可变的,也可以是可变的。 + +* #### 命令式风格(imperative style) +_命令式风格_ 编程强调严谨的操作序列以令效用能在正确的顺序发生。这种风格的特征是循环迭代、适当变更数据、方法有副作用,是像C, C++, C#和Java等这些语言的主要范式,与[函数式风格](#functional-style)相对应。 + +* #### 初始化(initialize) +变量在Scala源码中被定义时,必须用对象对其进行初始化。 + +* #### 实例(instance) +_实例_ ,或叫类实例,是个对象,是个仅在运行时存在的概念 + +* #### 实例化(instantiate) +_实例化_ 类是根据类创建一个新对象,是仅在运行时发生的动作。 + +* #### 不变性(invariant) +_不变性_ 用在两个地方。首先在数据结构组织良好的情况下它可以表示某个属性始终为真。比如,若排序二叉树具有右子节点,则其各节点就会在其右子节点前完成排序,这就属于排序二叉树的不变性。其次有时不变性也作为非协变的同义词,如:"类`Array`在类型参数上具备不变性"。 + +* #### 调用(invoke) +在实参上 _调用_ 方法、函数或闭包,意即其方法体会在指定实参上执行。 + +* #### Java虚拟机(JVM) +_JVM_ 是Java虚拟机(#runtime)的缩写,或叫[运行时](#runtime),是运行Scala程序的宿主。 + +* #### 字面量(literal) +`1`,`"One"`,和`(x: Int) => x + 1`是 _字面量_ 的例子,字面量是描述对象的便捷方式,便捷在这种方式正好反映了所创建对象的结构。 + +* #### 本地函数(local function) +_本地函数_ 是块内`def`定义的,作为对比,同为`def`定义的作为类、特质或单例对象的成员则被称作[方法](#method)。 + +* #### 本地变量(local variable) +_本地变量_ 是块内`val`或`var`定义的。尽管函数参数和[本地变量](#local-variable)类似,但并不叫本地变量,而是去掉"本地"直接叫"参数"或"变量"。 + +* #### 成员(member) +_成员_ 是类、特质或单例对象模板中被命名的元素。成员可通过所有者名称,点及其简名访问。例如,定义在类的最顶层字段和方法是这个类的成员。定义在类中的特质是包围它的类的成员。类中通过type关键字定义的类型是这个类的成员。类是其定义所在的包的成员。相比之下,本地变量或本地函数就不是包围他们的块的成员。 + +* #### 消息(message) +Actor是通过给彼此之间发送 _消息_ 来进行通信的。发送消息不会打断接收者正在处理的事情,接收者可一直等到当前活动结束且其不变性被重建之后。 + +* #### 元编程(meta-programming) +元编程程序是指其输入是其自身程序的程序。编译器都是元程序,像`scaladoc`这样的工具也是。要用注解做任何事都需要元编程程序。 + +* #### 方法(method) +_方法_ 就是类、特质或单例对象的成员函数。 + +* #### 混入(mixin) +_混入_ 就是特质用在混入组合时的名称。换言之,在"`trait Hat`"里面,`Hat`仅为特质,而"`new Cat extends AnyRef with Hat`"里面的`Hat`就可叫混入。用作动词时,"混"和"入"("mix in")是两个词。比如,可 _混_ 特质 _入_ 至类或其他特质。 + +* #### 混入组合(mixin composition) +把特质混入类或其他特质的过程。_混入组合_ 与传统的多重继承不同之处在于父级引用的类型不是在特质定义时已知的,而是在每次特质每次混入到类或其他特质时才被重新确定。 + +* #### 修饰符(modifier) +用来以某种方式限定类、特质、字段或方法等的定义的关键字。比如,`private`修饰符表明被定义的类、特质、字段或方法是私有的。 + +* #### 多重定义(multiple definitions) +通过使用类似这样的语法`val v1, v2, v3 = exp`,同一个表达式根据 _多重定义_ 概念可被赋值给多个变量。 + +* #### 非协变(nonvariant) +类或特质的类型参数默认是 _非协变_ 的,故而参数变化并不会子类化相应的类或特质。比如,因类`Array`非协变于其类型参数,故`Array[String]`既非`Array[Any]`之子类,亦非其超类。 + +* #### 操作(operation) +在Scala中,每个 _操作_ 都是一个方法调用。方法也可以 _操作符符号_ 的方式被调用,像在`b + 2`里面符号`+`就是一个 _操作符_。 + +* #### 参数(parameter) +函数可带有零至多个 _参数_,每个参数都有名称和类型。参数与实参之间的区别在于函数调用时实参指向具体的对象,参数则是指向这些传入实参的变量。 + +* #### 无参函数(parameterless function) +不带参数的函数,其定义时没有任何空括号。无参函数可不带括号调用,这种方式符合[统一访问原则](#uniform-access-principle),就是在客户端不改变任何代码的情况下把`def`改成`val`。、 + +* #### 无参方法(parameterless method) +_无参方法_ 就是作为类、特质或单例对象成员的无参函数。 + +* #### 参数化字段(parametric field) +定义为类参数的字段。 + +* #### 偏应用函数(部分应用函数)(partially applied function) +用在表达式中,省掉某些参数的函数。例如:若函数`f`的类型为`Int => Int => Int`,则`f`和`f(1)`就是 _偏应用函数_。 + +* #### 路径依赖类型(path-dependent type) +类似`swiss.cow.Food`的一种类型,`swiss.cow`部分形成一个对象引用的路径。这种类型的含义对于用来访问它的路径是敏感的,比如,`swiss.cow.Food`和`fish.Food`这两个是不同的类型。 + +* #### 模式(pattern) +在`match`表达式的某个备选项中,_模式_ 跟在`case`关键字后,先于 _模式守卫_ 或`=>`符号二者之一。 + +* #### 模式守卫(pattern guard) +在`match`表达式的某个备选项中,_模式守卫_ 可跟在某个[模式](#pattern)后面。比如,"`case x if x % 2 == 0 => x + 1`"中的模式守卫为"`if x % 2 == 0`"。带有模式守卫的备选项(case)仅当其模式匹配了并且模式守卫为真的时候才会被选中。 + +* #### 断言(predicate) +断言是结果类型为`Boolean`的函数。 + +* #### 主构造器(primary constructor) +类的主要构造器,会调用超类构造器,如果有必要,也会初始化字段进行传值,并且会执行类的花括号内定义的的顶层(top-level)代码。字段仅由不传给超类构造器的值参数做初始化,那些类构造体内因未用到而被优化掉的除外。 + +* #### 过程(procedure) +_过程_ 是结果类型为`Unit`的函数,其存在的理由仅为产生副作用。 + +* #### 可重新赋值(reassignable) +变量可以是可重新赋值的,也可以不是可重新赋值的。`var`是可重新赋值的,而`val`则不是。 + +* #### 递归的(recursive) +若函数可调用自身就说它是 _递归的_。若函数调用自身的唯一位置是函数的最后一个表达式,则函数是[尾递归的](#tail-recursive) + +* #### 引用(reference) +_引用_ 是指针的Java抽象,可唯一确定存在JVM堆中的对象。引用类型变量持有对象的引用,因为引用类型(`AnyRef`的实例)是存在JVM堆上的Java对象实现的。相比之下,值类型变量有时会持有一个(装箱类型的)引用,也有时(当对象表示基础类型值的时候)不会。一般说来,Scala变量[指向](#refers)对象。术语"指向"比"持有引用"更加抽象。如果类型为`scala.Int`的变量当前代表Java基础类型`int`的值,则这个变量仍然指向`Int`对象,但并不涉及任何引用。 + +* #### 引用相等性(reference equality) +_引用相等性_ 意思是两个引用指向同一个Java对象。引用相等性仅针对引用类型有意义,是可以通过调用`AnyRef`中的`eq`来确定的(在Java程序中,引用相等性通过在Java[引用类型](#reference-type)上调用`==`来确定)。 + +* #### 引用类型(reference type) +_引用类型_ 是`AnyRef`的子类。在运行时,引用类型的实例常驻JVM堆中。 + +* #### 引用透明(referential transparency) +独立于临时上下文且无副作用的函数属性。对于特定输入,引用透明函数的调用可由其结果替换而不改变程序语义。 + +* #### 指向(refers) +运行的Scala程序中的变量常 _指向_ 某个对象。变量即使被赋为`null`,概念上也是指向`Null`对象。在运行时,对象可由Java对象或基础类型值来实现,不过Scala允许程序员在更高层次抽象代码以他们设想的方式运行。参见[引用](#reference). + +* #### 精化类型(refinement type) +通过提供基础类型及其构造体花括号内若干成员而形成的类型。花括号内的成员精细化了基础类型所体现的类型。比如,"食草动物"(animal that eats grass)的类型为`Animal { type SuitableFood = Grass }`。 +A type formed by supplying a base type a number of members inside curly braces. The members in the curly braces refine the types that are present in the base type. For example, the type of “animal that eats grass” is `Animal { type SuitableFood = Grass }`. + +* #### 结果(result) +Scala程序中的表达式会产生 _结果_。Scala中的每个表达式的结果都是对象。 + +* #### 结果类型(result type) +方法的 _结果类型_ 是调用方法所产生的值的类型。(在Java中,这个概念被称为返回类型) + +* #### 返回(return) +Scala程序中的函数会 _返回_ 值,可把这个值叫做函数的[结果](#result)。也可以说函数 _结果是_ 某个值。Scala中的每个函数结果都是一个对象。 +A function in a Scala program `returns` a value. You can call this value the [result](#result) of the function. You can also say the function _results in_ the value. The result of every function in Scala is an object. + +* #### 运行时(runtime) +正在运行Scala程序的宿主Java虚拟机,或宿主[JVM](#jvm)。运行时这个概念包含了Java虚拟机规范中定义的虚拟机以及Java API和标准Scala API的运行时库。在运行时的这个阶段,意味着程序正在运行中,与编译时是相对的概念。 + +* #### 运行时类型(runtime type) +对象在运行时的类型。相比之下,[静态类型](#static-type)指的是表达式在编译时的类型。多数运行时类型都是无类型参数的裸类,比如,`"Hi"`的运行时类型是`String`,`(x: Int) => x + 1`的运行时类型是`Function1`。运行时类型可通过`isInstanceOf`来检测。 + +* #### 脚本(script) +包含顶层定义和语句,可直接通过`scala`命令来跑而无需显式编译的文件就是脚本,脚本结尾必须是表达式,而不能是定义。 + +* #### 选择器(selector) +`match`表达式中被匹配的值。比如,在"`s match { case _ => }`"中,选择器是`s`。 + +* #### 自身类型(self type) +特质的 _自身类型_ 是特质中用到的接收者`this`的假想类型。任何混入特质的具体类必须要确保其类型符合特质的自身类型。自身类型常被用来把大类分解为若干个特质([Programming in Scala](http://www.artima.com/shop/programming_in_scala)第29章有述)。 + +* #### 半结构化数据(semi-structured data) +XML数据就是半结构化的,因其相比于普通的二进制文件或文本文件更加结构化,而又不像编程语言的数据结构具备完全结构化。 + +* #### 序列化(serialization) +可把对象 _序列化_ 成字节流,以便将其保存至文件或通过网络传输。之后可对字节流进行 _反序列化_ (可发生在不同计算机上)来获取和原始被序列化的对象一样的对象。 + +* #### 遮掩(shadow) +本地变量的重新声明会 _遮掩_ 作用域内相同名称的变量声明。 + +* #### 签名(signature) +_签名_ 是[类型签名](#type-signature)的简写。 + +* #### 单例对象(singleton object) +由object关键字定义的对象。每个单例对象有且仅有一个实例。与某个类共享名称且与这个类定义在同一源文件中的单例对象,叫这个类的[伴随对象](#companion-object),类则叫单列对象的[伴随类](#companion-class)。无伴随类的单例对象叫[独立对象](#standalone-object)。 + +* #### 独立对象(standalone object) +没有[伴生类](#companion-class)的[单例对象](#singleton-object)。 + +* #### 语句(statement) +指的是表达式、定义或包导入等这些可放到Scala源码的模板或块中的东西。 + +* #### 静态类型(static type) +参见[类型](#type)。 + +* #### 结构类型(structural type) +也是一种[精化类型](#refinement-type),只是精化的目标是未在基类型中的成员。比如`{ def close(): Unit }`就是结构类型,因其基类型是`AnyRef`,而`AnyRef`并无名为`close`的成员。 + +* #### 子类(subclass) +一个类是其所有[超类](#superclass)和[超特质](#supertrait)的 _子类_。 + +* #### 子特质(subtrait) +一个特质是其所有[超特质](#supertrait)的 _子特质_。 + +* #### 子类型(subtype) +Scala编译器允许任何类型在需要该类型的地方使用其 _子类型_ 作为替代。对不带类型参数的类和特质来说,子类型的关系会反映子类的关系。比如,若类`Cat`是抽象类`Animal`的子类,且也不带类型参数,则类型`Cat`就是类型`Animal`的子类型。同样,若特质`Apple`是特质`Fruit`的子特质且无类型参数,则类型`Apple`就是类型`Fruit`的子类型。而对于带有类型参数的类和特质来说,协变就起作用了。比如,由于抽象类`List`被声明为在其长类型参数上是协变的(例,`List`被声明为`List[+A]`),`List[Cat]`是`List[Animal]`的子类型,`List[Apple]`是`List[Fruit]`的子类型。尽管这些类型的类都是`List`,但其子类型的关系依旧是存在的。对比来看,因为`Set`未被声明在其类型参数上是协变的(例,`Set`被声明为`Set[A]`,不带加号),所以`Set[Cat]`并不是`Set[Animal]`的子类型。子类型应该正确实现其超类型的契约,以便应用里氏替换原则(Liskov Substitution Principle),不过编译器仅会在类型检查级别核验此属性。 + +* #### 超类(superclass) +一个类的 _超类_ 包括其直接超类,其直接超类的直接超类,等等一直到`Any`。 + +* #### 超特质(supertrait) +类或特质的 _超特质_,如果有的话,就包括所有直接混入类或特质或其任意超类的特质,以及这些特质的所有超特质。 + +* #### 超类型(supertype) +类型是其所有子类型的 _超类型_。 + +* #### 合成类(synthetic class) +合成类是编译器自动生成的而不是程序员手写的。 + +* #### 尾递归(tail recursive) +函数是 _尾递归_ 的,仅当函数调用自身的地方是函数的最后一条操作。 + +* #### 目标类型化(target typing) +_目标类型化_ 是参考所需类型来进行类型推导的一种形式。比如在`nums.filter((x) => x > 0)`中,Scala编译器能推导出`x`的类型是`nums`的元素类型,因为`filter`方法会在`nums`的每个元素上调用函数。 + +* #### 模板(template) +_模板_ 是类、特质或单例对象定义体,它定义了类、特质或对象的类型签名,行为以及初始状态。 + +* #### 特质(trait) +_特质_ 通过`trait`关键字定义,是像抽象类一样不带任何值参数,并且可通过被称为[混入组合](#mixin-composition)的过程"混入到"类或其他特质。当某个特质被混入到其他类或特质,它就被叫做[混入](#mixin)。特质可通过一个或多个类型参数化。用类型来参数化后,特质就形成了类型。比如,`Set`是带有单类型参数的特质,而`Set[Int]`却是一个类型。`Set`也被说成是类型`Set[Int]`的"特质"。 + +* #### 类型(type) +Scala程序中每个变量和表达式都有编译时确定的 _类型_。类型可以在运行时限定变量能指向的值和表达式所能产生的值。如果有必要从对象的[运行时类型](#runtime-type)的角度对变量和表达式的类型进行区分的话,他们也被称为 _静态类型_。换句话说,"类型"这个词本身意味着静态类型。类型与类是区分开的因为带有类型参数的类可以构成许多类型。比如,`List`是类不是类型,`List[T]`则是一个带有自由类型参数的类型,`List[Int]`和`List[String]`也是类型(称为实类型因为他们没有自由类型参数)。类型可以有"[类](#class)"或"[特质](#trait)",比如类型`List[Int]`的类是`List`,类型`Set[String]`的特质是`Set`。、 + +* #### 类型约束(type constraint) +有些[注解](#annotation)是 _类型约束_,意味着他们会对类型能够包含的取值增加额外的限制或约束。比如,`@positive`可以是类型`Int`的类型约束,用来限制32位整型的取值为正的整数。类型约束虽然不会被标准Scala编译器检查,但相应的必须可被额外的工具或编译器插件检查。 + +* #### 类型构造器(type constructor) +带类型参数的类或特质。 + +* #### 类型参数(type parameter) +必须被填入类型的泛型类或泛型方法的参数。比如,类`List`定义为"`class List[T] { . . . `",对象`Predef`的一个成员方法`identity`定义为"`def identity[T](x:T) = x`",二者定义中的`T`就是类型参数。 + +* #### 类型签名(type signature) +方法的 _类型签名_ 包括名称,参数(如果有的话)的数量、顺序和类型,以及结果类型。类、特质或单例对象的类型签名包括名称,所有成员和构造器的类型签名,及其声明的继承和混入关系。 + +* #### 统一访问原则(uniform access principle) +_统一访问原则_ 指的是变量和无参函数应以相同的语法来访问。Scala通过不允许在无参函数的调用点放置括号来支持该原则。这样的话,无参函数定义就可以改成`val`而不影响客户端代码,_反之亦然_。 + +* #### 不可达(unreachable) +在Scala层面,对象可以是 _不可达_ 的,此时其所占据的内存可被运行时回收。不可达并不一定意味着未被引用。引用类型(`AnyRef`的实例)被实现为驻于JVM堆上的对象。当引用类型的实例不可达后,它也确实不被引用了,且可被垃圾回收。值类型(`AnyVal`的实例)可被实现为驻于堆中的基础类型值或Java包装类型实例(如`java.lang.Integer`)。值类型实例可在指向他们的变量的整个生命周期内被装箱(从基础类型值转成包装类型对象)或拆箱(从包装类型对象转成基础类型值)。若表现为JVM堆上的包装类型对象的值类型实例不可达,那就确实不会被引用并且可被垃圾回收。但是若正在表现为基础类型值的值类型不可达,则其仍可被引用,因为此时它并不会以作为对象驻于JVM堆上。运行时可回收不可达对象所占据的内存,但是假如一个Int在运行时被实现为Java基础类型int,在一个运行中的方法的栈帧上占据了一些内存,则这个对象的内存将在方法运行完成且栈帧弹出时才被回收。引用类型的内存,比如`Strings`,可在不可达之后由JVM的垃圾收集器回收。 + +* #### 未引用(unreferenced) +参见[不可达](#unreachable)。 + +* #### 值(value) +Scala中的任何计算或表达式的结果都是一个 _值_,而Scala中的每个值都是一个对象。值这个术语本质上是指对象在内存中(在JVM堆或栈上)的镜像。 + +* #### 值类型(value type) +_值类型_ 是`AnyVal`的任意子类,像`Int`,`Double`或`Unit`。该术语具有Scala源码级别的意味。在运行时,对应于Java基础类型的值类型实例可由基础类型值或包装类型实例来实现,比如`java.lang.Integer`。在值类型实例的整个生命周期内,运行时可将其在基础类型和包装类型间来回转换(如,对其装箱和拆箱)。 + +* #### 变量(variable) +指向对象的命名实体。变量要么是`val`,要么是 `var`,`val`变量和`var`变量在定义时都必须被初始化,但仅`var`变量可被重新赋值来指向不同对象。 + +* #### 型变(variance) +类或特质的类型参数可用 _型变_ 标号来做标记,即[协变](#covariant)(+)或[逆变](#contravariant)(-)。这样的型变标号表明了泛型类或特质的子类化是如何开展的,比如,泛型类`List`在其类型参数上是协变的,因此`List[String]`就是`List[Any]`的子类型。默认情况下,即缺少标号`+`或`-`的类型参数是[非协变](#nonvariant)的。 + +* #### 产生(yield) +表达式可以 _产生_ 结果。`yield`关键字指定了[for推解式](#for-comprehension)的结果。 From cc8106fb900d9b9a60de9c8a72569e44fac85c2a Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Wed, 12 Jun 2019 22:29:31 +0800 Subject: [PATCH 0615/3174] Polish. --- _zh-cn/glossary/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md index bc7aff3156..37cedcbd39 100644 --- a/_zh-cn/glossary/index.md +++ b/_zh-cn/glossary/index.md @@ -218,7 +218,7 @@ _混入_ 就是特质用在混入组合时的名称。换言之,在"`trait Hat 函数可带有零至多个 _参数_,每个参数都有名称和类型。参数与实参之间的区别在于函数调用时实参指向具体的对象,参数则是指向这些传入实参的变量。 * #### 无参函数(parameterless function) -不带参数的函数,其定义时没有任何空括号。无参函数可不带括号调用,这种方式符合[统一访问原则](#uniform-access-principle),就是在客户端不改变任何代码的情况下把`def`改成`val`。、 +不带参数的函数,其定义时没有任何空括号。无参函数可不带括号调用,这种方式符合[统一访问原则](#uniform-access-principle),就是在客户端不改变任何代码的情况下把`def`改成`val`。 * #### 无参方法(parameterless method) _无参方法_ 就是作为类、特质或单例对象成员的无参函数。 @@ -358,7 +358,7 @@ _模板_ 是类、特质或单例对象定义体,它定义了类、特质或 _特质_ 通过`trait`关键字定义,是像抽象类一样不带任何值参数,并且可通过被称为[混入组合](#mixin-composition)的过程"混入到"类或其他特质。当某个特质被混入到其他类或特质,它就被叫做[混入](#mixin)。特质可通过一个或多个类型参数化。用类型来参数化后,特质就形成了类型。比如,`Set`是带有单类型参数的特质,而`Set[Int]`却是一个类型。`Set`也被说成是类型`Set[Int]`的"特质"。 * #### 类型(type) -Scala程序中每个变量和表达式都有编译时确定的 _类型_。类型可以在运行时限定变量能指向的值和表达式所能产生的值。如果有必要从对象的[运行时类型](#runtime-type)的角度对变量和表达式的类型进行区分的话,他们也被称为 _静态类型_。换句话说,"类型"这个词本身意味着静态类型。类型与类是区分开的因为带有类型参数的类可以构成许多类型。比如,`List`是类不是类型,`List[T]`则是一个带有自由类型参数的类型,`List[Int]`和`List[String]`也是类型(称为实类型因为他们没有自由类型参数)。类型可以有"[类](#class)"或"[特质](#trait)",比如类型`List[Int]`的类是`List`,类型`Set[String]`的特质是`Set`。、 +Scala程序中每个变量和表达式都有编译时确定的 _类型_。类型可以在运行时限定变量能指向的值和表达式所能产生的值。如果有必要从对象的[运行时类型](#runtime-type)的角度对变量和表达式的类型进行区分的话,他们也被称为 _静态类型_。换句话说,"类型"这个词本身意味着静态类型。类型与类是区分开的因为带有类型参数的类可以构成许多类型。比如,`List`是类不是类型,`List[T]`则是一个带有自由类型参数的类型,`List[Int]`和`List[String]`也是类型(称为实类型因为他们没有自由类型参数)。类型可以有"[类](#class)"或"[特质](#trait)",比如类型`List[Int]`的类是`List`,类型`Set[String]`的特质是`Set`。 * #### 类型约束(type constraint) 有些[注解](#annotation)是 _类型约束_,意味着他们会对类型能够包含的取值增加额外的限制或约束。比如,`@positive`可以是类型`Int`的类型约束,用来限制32位整型的取值为正的整数。类型约束虽然不会被标准Scala编译器检查,但相应的必须可被额外的工具或编译器插件检查。 From 0906818684e9063f423dd2d15c1cd411706d90a0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 12 Jun 2019 17:47:26 +0200 Subject: [PATCH 0616/3174] Fix links Fix the errors in CI: - ./_site/es/tour/annotations.html * External link https://www.scala-lang.org/api/current/scala/remote.html failed: 404 No error - ./_site/overviews/collections/trait-iterable.html * External link https://www.scala-lang.org/api/current/scala/collection/GenSetLike.html failed: 404 No error htmlproofer 3.9.1 | Error: HTML-Proofer found 2 failures! Use scala-212-version over "current" for the old(!) collections. --- _es/tour/annotations.md | 1 - _overviews/collections/trait-iterable.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/_es/tour/annotations.md b/_es/tour/annotations.md index abcd9654bc..4d42a6f406 100644 --- a/_es/tour/annotations.md +++ b/_es/tour/annotations.md @@ -27,7 +27,6 @@ El significado de las anotaciones _depende de la implementación_. En la platafo | [`scala.deprecated`](https://www.scala-lang.org/api/current/scala/deprecated.html) | [`java.lang.Deprecated`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Deprecated.html) | | [`scala.inline`](https://www.scala-lang.org/api/current/scala/inline.html) (desde 2.6.0) | sin equivalente | | [`scala.native`](https://www.scala-lang.org/api/current/scala/native.html) (desde 2.6.0) | [`native`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (palabra clave) | -| [`scala.remote`](https://www.scala-lang.org/api/current/scala/remote.html) | [`java.rmi.Remote`](http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/Remote.html) | | [`scala.throws`](https://www.scala-lang.org/api/current/scala/throws.html) | [`throws`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (palabra clave) | | [`scala.transient`](https://www.scala-lang.org/api/current/scala/transient.html) | [`transient`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (palabra clave) | | [`scala.unchecked`](https://www.scala-lang.org/api/current/scala/unchecked.html) (desde 2.4.0) | sin equivalente | diff --git a/_overviews/collections/trait-iterable.md b/_overviews/collections/trait-iterable.md index ed2938fe6d..e478f3d4d7 100644 --- a/_overviews/collections/trait-iterable.md +++ b/_overviews/collections/trait-iterable.md @@ -62,7 +62,7 @@ Trait `Iterable` also adds some other methods to `Traversable` that can be imple | **Comparison:** | | | `xs sameElements ys` |A test whether `xs` and `ys` contain the same elements in the same order| -In the inheritance hierarchy below Iterable you find three traits: [Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/current/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/current/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/current/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [GenSetLike](https://www.scala-lang.org/api/current/scala/collection/GenSetLike.html). +In the inheritance hierarchy below Iterable you find three traits: [Seq](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Seq.html), [Set](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Set.html), and [Map](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Map.html). `Seq` and `Map` implement the [PartialFunction](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/PartialFunction.html) trait with its `apply` and `isDefinedAt` methods, each implemented differently. `Set` gets its `apply` method from [GenSetLike](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/GenSetLike.html). For sequences, `apply` is positional indexing, where elements are always numbered from `0`. That is, `Seq(1, 2, 3)(1)` gives `2`. For sets, `apply` is a membership test. For instance, `Set('a', 'b', 'c')('b')` gives `true` whereas `Set()('a')` gives `false`. Finally for maps, `apply` is a selection. For instance, `Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')` gives `10`. From 494bffd50071cba60d72c51abe3ce9453934c371 Mon Sep 17 00:00:00 2001 From: Alfonso Ruzafa Date: Wed, 12 Jun 2019 18:20:53 +0200 Subject: [PATCH 0617/3174] add visual scala reference to learn page --- learn.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/learn.md b/learn.md index 720a2cb3c2..5a6f817518 100644 --- a/learn.md +++ b/learn.md @@ -52,3 +52,6 @@ There are a handful of websites where you can interactively run Scala code in yo ## ScalaCourses [Independent Courseware](http://getscala.com), online self-study or instructor-led Scala and Play courses for a fee. + +## Visual Scala Reference +[Visual Scala Reference](https://superruzafa.github.com/visual-scala-reference/), a guide to visually learn about Scala concepts and functions. From d3aac4ad5c3eb2fd329cd8b3f053d6ff61b5cf96 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Thu, 13 Jun 2019 09:03:28 +0800 Subject: [PATCH 0618/3174] Polish base on liufengyun's review. --- _zh-cn/glossary/index.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md index 37cedcbd39..1227db611c 100644 --- a/_zh-cn/glossary/index.md +++ b/_zh-cn/glossary/index.md @@ -80,7 +80,7 @@ match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。 可以通过 _声明_ 抽象的字段、方法或类型来赋给实体一个名称,但是没有具体实现。声明和定义最关键的差异就是定义会为命名实体创建具体实现,而声明则不会。 * #### 定义(define) -在Scala程序中若提到 _定义_ 什么东西,就是说给它赋个名称并给出实现。可以定义的东西包括类、特质、单例对象、字段、方法、本地函数、本地变量等。由于提到定义常常会涉及到某种具体实现,故而抽象成员应为声明而非定义。 +在Scala程序中若提到 _定义_ 什么东西,就是说给它赋个名称并给出实现。可以定义的东西包括类、特质、单例对象、字段、方法、局部函数、局部变量等。由于提到定义常常会涉及到某种具体实现,故而抽象成员应为声明而非定义。 * #### 直接子类(direct subclass) 类是其 _直接子类_ 的直接超类。 @@ -119,7 +119,7 @@ _for循环_ 是[for表达式](#for-expression)的一种,一般用来循环迭 一个表达式的 _自由变量_ 指的是在表达式中使用但不定义在其中的变量。例如,在函数字面量表达式`(x: Int) => (x, y)`中,变量`x`和`y`都被用到了,但只有`y`是自由变量,因其未在表达式中定义。 * #### 函数(function) -_函数_ 可通过一列实参来[调用](#invoke)然后产生结果。函数一般具有参数列表、函数体和结果类型。作为类、特质或单例对象的函数叫做[方法](#method)。定义在其他函数内部的函数叫做[本地函数](#local-function)。结果类型为`Unit`的函数叫做[过程](#procedure)。源码里面的匿名函数叫做[函数字面量](#function-literal)。运行时,函数字面量被实例化为对象,叫做[函数值](#function-value)。 +_函数_ 可通过一列实参来[调用](#invoke)然后产生结果。函数一般具有参数列表、函数体和结果类型。作为类、特质或单例对象的函数叫做[方法](#method)。定义在其他函数内部的函数叫做[局部函数](#local-function)。结果类型为`Unit`的函数叫做[过程](#procedure)。源码里面的匿名函数叫做[函数字面量](#function-literal)。运行时,函数字面量被实例化为对象,叫做[函数值](#function-value)。 * #### 函数字面量(function literal) 在Scala源码中的无名函数,通过函数字面量语法来特别对待。比如:`(x: Int, y: Int) => x + y`。 @@ -146,7 +146,7 @@ _函数式风格_ 编程注重函数和求值结果而非操作发生的顺序 参见[过滤器](#filter). * #### 助手函数(helper function) -目的是为一个或多个其他邻近函数提供服务的函数。助手函数常实现为本地函数。 +目的是为一个或多个其他邻近函数提供服务的函数。助手函数常实现为局部函数。 * #### 助手方法(helper method) 作为类成员的[助手函数](#helper-function)。助手方法常为私有方法。 @@ -178,14 +178,14 @@ _JVM_ 是Java虚拟机(#runtime)的缩写,或叫[运行时](#runtime),是运 * #### 字面量(literal) `1`,`"One"`,和`(x: Int) => x + 1`是 _字面量_ 的例子,字面量是描述对象的便捷方式,便捷在这种方式正好反映了所创建对象的结构。 -* #### 本地函数(local function) -_本地函数_ 是块内`def`定义的,作为对比,同为`def`定义的作为类、特质或单例对象的成员则被称作[方法](#method)。 +* #### 局部函数(local function) +_局部函数_ 是块内`def`定义的,作为对比,同为`def`定义的作为类、特质或单例对象的成员则被称作[方法](#method)。 -* #### 本地变量(local variable) -_本地变量_ 是块内`val`或`var`定义的。尽管函数参数和[本地变量](#local-variable)类似,但并不叫本地变量,而是去掉"本地"直接叫"参数"或"变量"。 +* #### 局部变量(local variable) +_局部变量_ 是块内`val`或`var`定义的。尽管函数参数和[局部变量](#local-variable)类似,但并不叫局部变量,而是去掉"局部"直接叫"参数"或"变量"。 * #### 成员(member) -_成员_ 是类、特质或单例对象模板中被命名的元素。成员可通过所有者名称,点及其简名访问。例如,定义在类的最顶层字段和方法是这个类的成员。定义在类中的特质是包围它的类的成员。类中通过type关键字定义的类型是这个类的成员。类是其定义所在的包的成员。相比之下,本地变量或本地函数就不是包围他们的块的成员。 +_成员_ 是类、特质或单例对象模板中被命名的元素。成员可通过所有者名称,点及其简名访问。例如,定义在类的最顶层字段和方法是这个类的成员。定义在类中的特质是包围它的类的成员。类中通过type关键字定义的类型是这个类的成员。类是其定义所在的包的成员。相比之下,局部变量或局部函数就不是包围他们的块的成员。 * #### 消息(message) Actor是通过给彼此之间发送 _消息_ 来进行通信的。发送消息不会打断接收者正在处理的事情,接收者可一直等到当前活动结束且其不变性被重建之后。 @@ -304,7 +304,7 @@ XML数据就是半结构化的,因其相比于普通的二进制文件或文 可把对象 _序列化_ 成字节流,以便将其保存至文件或通过网络传输。之后可对字节流进行 _反序列化_ (可发生在不同计算机上)来获取和原始被序列化的对象一样的对象。 * #### 遮掩(shadow) -本地变量的重新声明会 _遮掩_ 作用域内相同名称的变量声明。 +局部变量的重新声明会 _遮掩_ 作用域内相同名称的变量声明。 * #### 签名(signature) _签名_ 是[类型签名](#type-signature)的简写。 From 7616f33fe9ef0b7b98b468f09b6d78f558f66e2e Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Thu, 13 Jun 2019 09:07:12 +0800 Subject: [PATCH 0619/3174] Polish base on liufengyun's review 2. --- _zh-cn/glossary/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md index 1227db611c..79893b5298 100644 --- a/_zh-cn/glossary/index.md +++ b/_zh-cn/glossary/index.md @@ -145,11 +145,11 @@ _函数式风格_ 编程注重函数和求值结果而非操作发生的顺序 * #### 守卫(guard) 参见[过滤器](#filter). -* #### 助手函数(helper function) -目的是为一个或多个其他邻近函数提供服务的函数。助手函数常实现为局部函数。 +* #### 辅助函数(helper function) +目的是为一个或多个其他邻近函数提供服务的函数。辅助函数常实现为局部函数。 -* #### 助手方法(helper method) -作为类成员的[助手函数](#helper-function)。助手方法常为私有方法。 +* #### 辅助方法(helper method) +作为类成员的[辅助函数](#helper-function)。辅助方法常为私有方法。 * #### 不可变(immutable) 若对象的值在任何对客户端可见的方式下创建后不会被修改则称对象是 _不可变_ 的。对象既可以是不可变的,也可以是可变的。 From e37260db541f6971087c212a1e995c09b33ce974 Mon Sep 17 00:00:00 2001 From: abosshard <23498828+abosshard@users.noreply.github.com> Date: Sat, 15 Jun 2019 16:27:16 +0200 Subject: [PATCH 0620/3174] Update concrete-mutable-collection-classes.md As there is no immutable version of Stack in 2.13, I adjusted the description accordingly. --- .../collections-2.13/concrete-mutable-collection-classes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_overviews/collections-2.13/concrete-mutable-collection-classes.md b/_overviews/collections-2.13/concrete-mutable-collection-classes.md index f2cf39eb41..9ddd1242ef 100644 --- a/_overviews/collections-2.13/concrete-mutable-collection-classes.md +++ b/_overviews/collections-2.13/concrete-mutable-collection-classes.md @@ -81,7 +81,8 @@ Scala provides mutable queues in addition to immutable ones. You use a `mQueue` ## Stacks -You saw immutable stacks earlier. There is also a mutable version, supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Stack.html). It works exactly the same as the immutable version except that modifications happen in place. +A stack implements a data structure which allows to store and retrieve objects in a last-in-first-out (LIFO) fashion. +It is supported by class [mutable.Stack](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Stack.html). scala> val stack = new scala.collection.mutable.Stack[Int] stack: scala.collection.mutable.Stack[Int] = Stack() From 82bb519d421f07c512f4e9bd77e551b8bd62a78b Mon Sep 17 00:00:00 2001 From: Jim Van Horn Date: Sat, 15 Jun 2019 22:32:41 -0700 Subject: [PATCH 0621/3174] Update creating-collections-from-scratch.md edit for clarity --- .../collections-2.13/creating-collections-from-scratch.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/collections-2.13/creating-collections-from-scratch.md b/_overviews/collections-2.13/creating-collections-from-scratch.md index c86dd32db2..7f5a0b4ca2 100644 --- a/_overviews/collections-2.13/creating-collections-from-scratch.md +++ b/_overviews/collections-2.13/creating-collections-from-scratch.md @@ -27,7 +27,7 @@ You have syntax `List(1, 2, 3)` to create a list of three integers and `Map('A' List.apply(1.0, 2.0) -So this is a call to the `apply` method of the companion object of the `List` class. That method takes an arbitrary number of arguments and constructs a list from them. Every collection class in the Scala library has a companion object with such an `apply` method. It does not matter whether the collection class represents a concrete implementation, like `List`, or `LazyList` or `Vector`, do, or whether it is an abstract base class such as `Seq`, `Set` or `Iterable`. In the latter case, calling apply will produce some default implementation of the abstract base class. Examples: +So this is a call to the `apply` method of the companion object of the `List` class. That method takes an arbitrary number of arguments and constructs a list from them. Every collection class in the Scala library has a companion object with such an `apply` method. It does not matter whether the collection class represents a concrete implementation, like `List`, `LazyList` or `Vector`, or whether it is an abstract base class such as `Seq`, `Set` or `Iterable`. In the latter case, calling apply will produce some default implementation of the abstract base class. Examples: scala> List(1, 2, 3) res17: List[Int] = List(1, 2, 3) @@ -59,4 +59,4 @@ The operations provided by collection companion objects are summarized in the fo | `C.range(start, end)` | The collection of integers `start` ... `end-1`. | | `C.range(start, end, step)`| The collection of integers starting with `start` and progressing by `step` increments up to, and excluding, the `end` value. | | `C.iterate(x, n)(f)` | The collection of length `n` with elements `x`, `f(x)`, `f(f(x))`, ... | -| `C.unfold(init)(f)` | A collection that uses a function `f` to compute its next element and state, starting from the `init` state.| \ No newline at end of file +| `C.unfold(init)(f)` | A collection that uses a function `f` to compute its next element and state, starting from the `init` state.| From 07135b1bd8aac30b842fb485d1e7a724bba2aeff Mon Sep 17 00:00:00 2001 From: Jim Van Horn Date: Sat, 15 Jun 2019 23:04:18 -0700 Subject: [PATCH 0622/3174] Update seqs.md Corrected distinctBy example result. -jvh --- _overviews/collections-2.13/seqs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections-2.13/seqs.md b/_overviews/collections-2.13/seqs.md index d61f7e4f86..4cd3060b68 100644 --- a/_overviews/collections-2.13/seqs.md +++ b/_overviews/collections-2.13/seqs.md @@ -73,7 +73,7 @@ If a sequence is mutable, it offers in addition a side-effecting `update` method | `xs intersect ys` |The multi-set intersection of sequences `xs` and `ys` that preserves the order of elements in `xs`.| | `xs diff ys` |The multi-set difference of sequences `xs` and `ys` that preserves the order of elements in `xs`.| | `xs.distinct` |A subsequence of `xs` that contains no duplicated element.| -| `xs distinctBy f` |A subsequence of `xs` that contains no duplicated element after applying the transforming function `f`. For instance, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "bar")`| +| `xs distinctBy f` |A subsequence of `xs` that contains no duplicated element after applying the transforming function `f`. For instance, `List("foo", "bar", "quux").distinctBy(_.length) == List("foo", "quux")`| Trait [Seq](http://www.scala-lang.org/api/current/scala/collection/Seq.html) has two subtraits [LinearSeq](http://www.scala-lang.org/api/current/scala/collection/LinearSeq.html), and [IndexedSeq](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html). These do not add any new operations to the immutable branch, but each offers different performance characteristics: A linear sequence has efficient `head` and `tail` operations, whereas an indexed sequence has efficient `apply`, `length`, and (if mutable) `update` operations. Frequently used linear sequences are `scala.collection.immutable.List` and `scala.collection.immutable.LazyList`. Frequently used indexed sequences are `scala.Array` and `scala.collection.mutable.ArrayBuffer`. The `Vector` class provides an interesting compromise between indexed and linear access. It has both effectively constant time indexing overhead and constant time linear access overhead. Because of this, vectors are a good foundation for mixed access patterns where both indexed and linear accesses are used. You'll learn more on vectors [later](concrete-immutable-collection-classes.html). From 4905400e0fb84f54fc5fb66374251cf923d62dc6 Mon Sep 17 00:00:00 2001 From: Dima Kotobotov Date: Tue, 14 May 2019 00:15:26 +0300 Subject: [PATCH 0623/3174] :sparkles: Russian Collections introduction --- _overviews/collections/introduction.md | 2 +- _ru/overviews/collections/introduction.md | 70 +++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 _ru/overviews/collections/introduction.md diff --git a/_overviews/collections/introduction.md b/_overviews/collections/introduction.md index bf16363308..e026efafaa 100644 --- a/_overviews/collections/introduction.md +++ b/_overviews/collections/introduction.md @@ -9,7 +9,7 @@ overview-name: Collections num: 1 -languages: [ja, zh-cn] +languages: [ja, zh-cn, ru] permalink: /overviews/collections/:title.html --- diff --git a/_ru/overviews/collections/introduction.md b/_ru/overviews/collections/introduction.md new file mode 100644 index 0000000000..4f503f94d6 --- /dev/null +++ b/_ru/overviews/collections/introduction.md @@ -0,0 +1,70 @@ +--- +layout: multipage-overview +title: Введение + +discourse: false + +partof: collections +overview-name: Collections + +num: 1 + +language: ru +--- + +**Martin Odersky и Lex Spoon** + +Популярно мнение, что новые коллекции это самое значимое изменение в Scala версии 2.8. +В Scala и раньше были коллекции (и на самом деле, новая модель +во многом совместима с прежней). Но только начиная с версии 2.8 +появилась единая, общая и всеобъемлющая база для всех типов коллекций. + +Несмотря на то, что улучшения коллекций на первый взгляд едва заметны, они могут привести к существенному изменению в вашем стиле программирования. +Теперь чаще, при работе на высоком уровне, вся коллекция становится базовым строительным блоком вашей программы, а не её отдельные элементы. + +К такому стилю программирования необходимо небольшое привыкание. +К счастью, адаптация облегчается приятными свойствами характерными для новых коллекций Scala. +Они обладают простотой в использовании, лаконичностью, безопасностью и универсальностью. + +**Простота:** Небольшого набора из 20-50 методов достаточно для решения большинства задач. +Нет необходимости использовать запутанные циклы или рекурсии. +Персистентные коллекции и операции без побочных эффектов означают, +что вам не нужно беспокоиться о случайном повреждении существующих коллекций новыми данными. +Больше нет путаницы из-за использования итераторов и одновременного изменения коллекций. + +**Лаконичность:** Одной командой можно достичь, столько же, сколько обычно получают используя несколько вложенных операций с циклами. +Вы можете выразить функциональные операции с помощью простого синтаксиса и с легкостью сочетать операции, создавая ощущение +работы со специализированным под задачу языком. + +**Безопасность:** Требуется определенный опыт, чтоб погрузится в эту специфику. +Статически типизированная и функциональная природа коллекций Scala подразумевает, что подавляющее большинство ошибок, которые вы можете совершить, будут пойманы во время компиляции. +Это потому что: + 1. Коллекции сами по себе очень активно используются, поэтому хорошо протестированы. + 2. Использование операции в коллекциях создает явное описание того, что мы ожидаем для входящих данных и для результата. + 3. Это явное описание для входа и результата подвергается статической проверке типа. В результате подавляющее большинство проблем будет проявляться в виде ошибок типов. +Поэтому запуск программ из нескольких сотен строк, с первого раза, вполне типичная ситуация. + + +**Скорость:** Все операции в коллекциях уже настроены и оптимизированы. В результате, работа коллекций получается очень эффективной. +Можно конечно сделать немного более эффективную настройку структур данных и операций с ними, но при этом, +вероятно, вы получите хуже эффективность в непосредственной реализации и использовании. +Кроме того, коллекции оптимизированы для параллельного исполнения на нескольких ядрах. Параллельные коллекции поддерживают те же операции, что и последовательные, поэтому нет необходимости в изучении новых операций или переписывании кода. +Вы можете превратить последовательную коллекцию в параллельную просто вызвав метод `par`. + +**Универсальность:** Коллекции обеспечивают одинаковые операции на любом типе коллекций, где это имеет смысл. Таким образом, можно достичь многого, имея сравнительно небольшой набор операций. Например строка, в принципе, представляет собой последовательность символов. Следовательно, в коллекциях Scala строки поддерживают все операции которые есть у последовательностей (`Seq`). То же самое относится и к массивам. + +**Пример:** Вот лишь одна строчка кода, демонстрирующая преимущества Scala коллекций. + + val (minors, adults) = people partition (_.age < 18) + +Сразу становится понятно, что делает эта строчка: она разделяет коллекцию людей `people` на несовершеннолетних `minors` и взрослых `adults` в зависимости от возраста `age`. +Поскольку метод `partition` определен в базовом типе коллекции `TraversableLike`, этот код работает для любого типа коллекций, включая массивы. +Полученные в результате коллекции `minors` и `adults` будут иметь тот же тип, что и коллекция `people` . + +Этот код намного лаконичнее, чем несколько циклов, необходимых для того, чтоб провести обработку традиционным методом +(три цикла для массива, т.к. промежуточные результаты должны быть сохранены где-то в другом месте). +Как только вы освоите базовую схему работы с коллекциями, вы оцените на сколько проще и безопаснее написание такого кода, в отличии от более низкоуровневого кода с циклами. +Кроме того, сама операция `partition` работает довольно быстро и будет работать еще быстрее на многоядерных процессорах при использовании параллельных коллекций. (Параллельные коллекции стали частью Scala начиная с версии 2.9.) + +В этом разделе подробно рассматриваются API классов коллекций Scala с пользовательской точки зрения. +Вы также познакомитесь со всеми фундаментальными классами и методами, которые есть у коллекций. From 44032b5473103a5cf21a47552398910667898f0d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 19 Jun 2019 07:38:39 +0200 Subject: [PATCH 0624/3174] 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 e7b6030befe29b9c56eaf4641397d2513fee2223 Mon Sep 17 00:00:00 2001 From: Jorge Vicente Cantero Date: Fri, 21 Jun 2019 08:06:32 +0200 Subject: [PATCH 0625/3174] Migrate to ci.scala-lang Drone 8 instance --- .drone.yml | 1 - .drone.yml.sig | 1 - 2 files changed, 2 deletions(-) delete mode 100644 .drone.yml.sig diff --git a/.drone.yml b/.drone.yml index d36025ce89..7b74f75e3a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,6 +1,5 @@ pipeline: build: image: scalacenter/scala-rvm-jvm-coursier:2.0 - pull: true commands: - ./scripts/ci.sh diff --git a/.drone.yml.sig b/.drone.yml.sig deleted file mode 100644 index 8240a38b07..0000000000 --- a/.drone.yml.sig +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgYnVpbGQ6CiAgICBpbWFnZTogamRrLXJ2bS1jb3Vyc2llcjpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIHNvdXJjZSB-Ly5wcm9maWxlCiAgICAgIC0gYnVuZGxlIGluc3RhbGwKICAgICAgLSAuL3NjcmlwdHMvcnVuLXR1dC5zaAogICAgICAtIHJtIC1yIHR1dC10bXAKICAgICAgLSBidW5kbGUgZXhlYyBqZWt5bGwgYnVpbGQK.7Rp37FEwRqAo85EdFYZh1PoyU8mxpFdEnpchWaQkHCc From 2c87d8ff773632e9da0b1a760a9ee20c304b3fb6 Mon Sep 17 00:00:00 2001 From: mumutu66 <30490822+mumutu66@users.noreply.github.com> Date: Fri, 21 Jun 2019 14:16:43 +0800 Subject: [PATCH 0626/3174] Update breakOut.md fix the B type error --- _overviews/FAQ/breakout.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/FAQ/breakout.md b/_overviews/FAQ/breakout.md index 0a39214d55..b5ef234cda 100644 --- a/_overviews/FAQ/breakout.md +++ b/_overviews/FAQ/breakout.md @@ -154,7 +154,7 @@ chain, we find that the types passed to `TraversableLike`, and, thus, used by Going back to the example, the first map is receiving a function of type `((Int, String)) => (Int, Int)` and the second map is receiving a function of -type `((Int, String)) => Int`. I use the double parenthesis to emphasize it is +type `((Int, String)) => String`. I use the double parenthesis to emphasize it is a tuple being received, as that's the type of `A` as we saw. With that information, let's consider the other types. @@ -163,7 +163,7 @@ With that information, let's consider the other types. B = (Int, Int) map (_._2): - B = Int + B = String We can see that the type returned by the first `map` is `Map[Int,Int]`, and the second is `Iterable[String]`. Looking at `map`'s definition, it is easy to see From 9d5a769f68e6e1593943efb3549b1a158936e660 Mon Sep 17 00:00:00 2001 From: Jorge Vicente Cantero Date: Fri, 21 Jun 2019 09:12:43 +0200 Subject: [PATCH 0627/3174] Update CI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bed6ea16d7..93bf91952e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Scala Documentation # -[![Build Status](https://platform-ci.scala-lang.org/api/badges/scala/docs.scala-lang/status.svg)](https://platform-ci.scala-lang.org/scala/docs.scala-lang) +[![Build Status](https://ci.scala-lang.org/api/badges/scala/docs.scala-lang/status.svg)](https://platform-ci.scala-lang.org/scala/docs.scala-lang) This repository contains the source for the Scala documentation website, as well as the source for "Scala Improvement Process" (SIP) documents. From 7fb22d57689d82e20f7bdac4926bbba719d30448 Mon Sep 17 00:00:00 2001 From: cclaudiu81 Date: Fri, 21 Jun 2019 23:11:20 +0300 Subject: [PATCH 0628/3174] PR changes refactored OO info in the page intro & change small things based on the PR review. --- _tour/higher-order-functions.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/_tour/higher-order-functions.md b/_tour/higher-order-functions.md index d6d1681894..f080bb8350 100644 --- a/_tour/higher-order-functions.md +++ b/_tour/higher-order-functions.md @@ -19,6 +19,8 @@ The terminology can get a bit confusing at this point, and we use the phrase "higher order function" for both methods and functions that take functions as parameters or that return a function. +In a pure Object Oriented world a good practice is to avoid exposing methods parameterized with functions that might leak object's internal state. Leaking internal state might break the invariants of the object itself thus violating encapsulation. + One of the most common examples is the higher-order function `map` which is available for collections in Scala. ```tut @@ -58,10 +60,8 @@ case class WeeklyWeatherForecast(temperatures: Seq[Double]) { def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF) // <-- passing the method convertCtoF } ``` -Here the method `convertCtoF` is passed to `forecastInFahrenheit`. This is possible because the compiler coerces `convertCtoF` to the function `x => convertCtoF(x)` (note: `x` will +Here the method `convertCtoF` is passed to the higher order function `map`. This is possible because the compiler coerces `convertCtoF` to the function `x => convertCtoF(x)` (note: `x` will be a generated name which is guaranteed to be unique within its scope). - -In a pure Object Oriented world a good practice is to avoid exposing methods that are parameterized with functions that might escape the internal state of the objects. Leaking internal state might break the invariants of the object itself. ## Functions that accept functions One reason to use higher-order functions is to reduce redundant code. Let's say you wanted some methods that could raise someone's salaries by various factors. Without creating a higher-order function, @@ -104,6 +104,8 @@ object SalaryRaiser { The new method, `promotion`, takes the salaries plus a function of type `Double => Double` (i.e. a function that takes a Double and returns a Double) and returns the product. +Methods and functions usually express behaviours or data transformations, therefore having functions that compose based on other functions can help building generic mechanisms. Those generic operations defer to lock down the entire operation behaviour giving clients a way to control or further customize parts of the operation itself. + ## Functions that return functions There are certain cases where you want to generate a function. Here's an example From 2555a85e19ab9573529beb01f0b35a2d0d3596fe Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 21 Jun 2019 09:42:37 +0100 Subject: [PATCH 0629/3174] Fix some more links Pin some translated guides back to Scala 2.12, and drop scala.remote in the Korean docs. --- .../concrete-parallel-collections.md | 16 +++++----- .../concrete-immutable-collection-classes.md | 22 +++++++------- .../concrete-mutable-collection-classes.md | 30 +++++++++---------- _ja/overviews/collections/iterators.md | 6 ++-- _ja/overviews/collections/overview.md | 8 ++--- .../collections/trait-traversable.md | 4 +-- .../concrete-parallel-collections.md | 22 +++++++------- _ko/tour/annotations.md | 1 - _overviews/collections/trait-traversable.md | 2 +- _pl/tour/annotations.md | 1 - _pt-br/tour/annotations.md | 1 - _zh-cn/overviews/collections/overview.md | 4 +-- 12 files changed, 57 insertions(+), 60 deletions(-) diff --git a/_es/overviews/parallel-collections/concrete-parallel-collections.md b/_es/overviews/parallel-collections/concrete-parallel-collections.md index 158c923f6e..3cb5e36a94 100644 --- a/_es/overviews/parallel-collections/concrete-parallel-collections.md +++ b/_es/overviews/parallel-collections/concrete-parallel-collections.md @@ -13,7 +13,7 @@ language: es ## Array Paralelo -Una secuencia [ParArray](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParArray.html) contiene un conjunto de elementos contiguos lineales. Esto significa que los elementos pueden ser accedidos y actualizados (modificados) eficientemente al modificar la estructura subyacente (un array). El iterar sobre sus elementos es también muy eficiente por esta misma razón. Los Arrays Paralelos son como arrays en el sentido de que su tamaño es constante. +Una secuencia [ParArray](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParArray.html) contiene un conjunto de elementos contiguos lineales. Esto significa que los elementos pueden ser accedidos y actualizados (modificados) eficientemente al modificar la estructura subyacente (un array). El iterar sobre sus elementos es también muy eficiente por esta misma razón. Los Arrays Paralelos son como arrays en el sentido de que su tamaño es constante. scala> val pa = scala.collection.parallel.mutable.ParArray.tabulate(1000)(x => 2 * x + 1) pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 3, 5, 7, 9, 11, 13,... @@ -31,7 +31,7 @@ Al invocar el método `seq`, los arrays paralelos son convertidos al tipo de col ## Vector Paralelo -Un [ParVector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParVector.html) es una secuencia inmutable con un tiempo de acceso y modificación logarítimico bajo a constante. +Un [ParVector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParVector.html) es una secuencia inmutable con un tiempo de acceso y modificación logarítimico bajo a constante. scala> val pv = scala.collection.parallel.immutable.ParVector.tabulate(1000)(x => x) pv: scala.collection.parallel.immutable.ParVector[Int] = ParVector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,... @@ -41,11 +41,11 @@ Un [ParVector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/coll Los vectores inmutables son representados por árboles, por lo que los splitters dividen pasándose subárboles entre ellos. Los combiners concurrentemente mantienen un vector de elementos y son combinados al copiar dichos elementos de forma "retardada". Es por esta razón que los métodos tranformadores son menos escalables que sus contrapartes en arrays paralelos. Una vez que las operaciones de concatenación de vectores estén disponibles en una versión futura de Scala, los combiners podrán usar dichas características y hacer más eficientes los métodos transformadores. -Un vector paralelo es la contraparte paralela de un [Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html) secuencial, por lo tanto la conversión entre estas dos estructuras se efectúa en tiempo constante. +Un vector paralelo es la contraparte paralela de un [Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html) secuencial, por lo tanto la conversión entre estas dos estructuras se efectúa en tiempo constante. ## Rango (Range) Paralelo -Un [ParRange](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParRange.html) es una secuencia ordenada separada por intervalos iguales (ej: 1, 2, 3 o 1, 3, 5, 7). Un rango paralelo es creado de forma similar al [Rango](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html) secuencial: +Un [ParRange](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParRange.html) es una secuencia ordenada separada por intervalos iguales (ej: 1, 2, 3 o 1, 3, 5, 7). Un rango paralelo es creado de forma similar al [Rango](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html) secuencial: scala> 1 to 3 par res0: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3) @@ -61,7 +61,7 @@ Tal como los rangos secuenciales no tienen constructores, los rangos paralelos n ## Tablas Hash Paralelas -Las tablas hash paralelas almacenan sus elementos en un array subyacente y los almacenan en una posición determinada por el código hash del elemento respectivo. Las versiones mutables de los hash sets paralelos ([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParHashSet.html)) y los hash maps paraleos ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParHashMap.html)) están basados en tablas hash. +Las tablas hash paralelas almacenan sus elementos en un array subyacente y los almacenan en una posición determinada por el código hash del elemento respectivo. Las versiones mutables de los hash sets paralelos ([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParHashSet.html)) y los hash maps paraleos ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParHashMap.html)) están basados en tablas hash. scala> val phs = scala.collection.parallel.mutable.ParHashSet(1 until 2000: _*) phs: scala.collection.parallel.mutable.ParHashSet[Int] = ParHashSet(18, 327, 736, 1045, 773, 1082,... @@ -75,9 +75,9 @@ Los "Mapas Hash" (Hash Maps) y los "Conjuntos Hash" (Hash Sets) secuenciales pue ## Hash Tries Paralelos -Los Hash Tries paralelos son la contraparte paralela de los hash tries inmutables, que son usados para representar conjuntos y mapas inmutables de forma eficiente. Las clases involucradas son: [immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParHashSet.html) +Los Hash Tries paralelos son la contraparte paralela de los hash tries inmutables, que son usados para representar conjuntos y mapas inmutables de forma eficiente. Las clases involucradas son: [immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParHashSet.html) y -[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/immutable/ParHashMap.html). +[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/immutable/ParHashMap.html). scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _*) phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69, 809, 629, 365, 138, 760, 101, 479,... @@ -92,7 +92,7 @@ Los hash tries paralelos pueden ser convertidos hacia y desde hash tries secuenc ## Tries Paralelos Concurrentes -Un [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/concurrent/TrieMap.html) es un mapa thread-safe (seguro ante la utilización de múltiples hilos concurrentes) mientras que [mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParTrieMap.html) es su contraparte paralela. Si bien la mayoría de las estructuras de datos no garantizan una iteración consistente si la estructura es modificada en medio de dicha iteración, los tries concurrentes garantizan que las actualizaciones sean solamente visibles en la próxima iteración. Esto significa que es posible mutar el trie concurrente mientras se está iterando sobre este, como en el siguiente ejemplo, que computa e imprime las raíces cuadradas de los números entre 1 y 99: +Un [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/concurrent/TrieMap.html) es un mapa thread-safe (seguro ante la utilización de múltiples hilos concurrentes) mientras que [mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParTrieMap.html) es su contraparte paralela. Si bien la mayoría de las estructuras de datos no garantizan una iteración consistente si la estructura es modificada en medio de dicha iteración, los tries concurrentes garantizan que las actualizaciones sean solamente visibles en la próxima iteración. Esto significa que es posible mutar el trie concurrente mientras se está iterando sobre este, como en el siguiente ejemplo, que computa e imprime las raíces cuadradas de los números entre 1 y 99: scala> val numbers = scala.collection.parallel.mutable.ParTrieMap((1 until 100) zip (1 until 100): _*) map { case (k, v) => (k.toDouble, v.toDouble) } numbers: scala.collection.parallel.mutable.ParTrieMap[Double,Double] = ParTrieMap(0.0 -> 0.0, 42.0 -> 42.0, 70.0 -> 70.0, 2.0 -> 2.0,... diff --git a/_ja/overviews/collections/concrete-immutable-collection-classes.md b/_ja/overviews/collections/concrete-immutable-collection-classes.md index 508ca9a227..77a2a4880a 100644 --- a/_ja/overviews/collections/concrete-immutable-collection-classes.md +++ b/_ja/overviews/collections/concrete-immutable-collection-classes.md @@ -16,7 +16,7 @@ Scala は様々な具象不変コレクションクラス (concrete immutable co ## リスト -リスト ([`List`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html)) は有限の不変列だ。リストは最初の要素とリストの残りの部分に定数時間でアクセスでき、また、新たな要素をリストの先頭に追加する定数時間の cons 演算を持つ。他の多くの演算は線形時間で行われる。 +リスト ([`List`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/List.html)) は有限の不変列だ。リストは最初の要素とリストの残りの部分に定数時間でアクセスでき、また、新たな要素をリストの先頭に追加する定数時間の cons 演算を持つ。他の多くの演算は線形時間で行われる。 リストは Scala プログラミングの働き者であり続けてきたので、あえてここで語るべきことは多くない。Scala 2.8 での大きな変更点は `List` クラスはそのサブクラスである `::` とそのサブオブジェクトである `Nil` とともに、論理的にふさわしい `scala.collection.immutable` パッケージで定義されるようになったことだ。`scala` パッケージには `List`、`Nil`、および `::` へのエイリアスがあるため、ユーザの立場から見ると、リストは今まで通り使うことができる。 @@ -24,7 +24,7 @@ Scala は様々な具象不変コレクションクラス (concrete immutable co ## ストリーム -ストリーム ([`Stream`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Stream.html)) はリストに似ているが、要素は遅延評価される。そのため、ストリームは無限の長さをもつことができる。呼び出された要素のみが計算される。他の点においては、ストリームはリストと同じ性能特性をもつ。 +ストリーム ([`Stream`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stream.html)) はリストに似ているが、要素は遅延評価される。そのため、ストリームは無限の長さをもつことができる。呼び出された要素のみが計算される。他の点においては、ストリームはリストと同じ性能特性をもつ。 リストは `::` 演算子によって構築されるが、ストリームはそれに似た `#::` 演算子によって構築される。以下は、整数の 1, 2, 3 からなる簡単なストリームの例だ: @@ -52,7 +52,7 @@ Scala は様々な具象不変コレクションクラス (concrete immutable co リストはアルゴリズムが慎重にリストの先頭要素 (`head`) のみを処理する場合、非常に効率的だ。`head` の読み込み、追加、および削除は一定数時間で行われるのに対して、リストの後続の要素に対する読み込みや変更は、その要素の深さに依存した線形時間で実行される。 -ベクトル ([`Vector`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html)) は、ランダムアクセス時の非効率性を解決するために Scala 2.8 から導入された新しいコレクション型だ。ベクトルはどの要素の読み込みも「事実上」定数時間で行う。リストの `head` の読み込みや配列の要素読み込みに比べると大きい定数だが、定数であることには変りない。この結果、ベクトルを使ったアルゴリズムは列の `head` のみを読み込むことに神経質にならなくていい。任意の場所の要素を読み込んだり、変更したりできるため、コードを書くのに便利だ。 +ベクトル ([`Vector`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html)) は、ランダムアクセス時の非効率性を解決するために Scala 2.8 から導入された新しいコレクション型だ。ベクトルはどの要素の読み込みも「事実上」定数時間で行う。リストの `head` の読み込みや配列の要素読み込みに比べると大きい定数だが、定数であることには変りない。この結果、ベクトルを使ったアルゴリズムは列の `head` のみを読み込むことに神経質にならなくていい。任意の場所の要素を読み込んだり、変更したりできるため、コードを書くのに便利だ。 ベクトルは、他の列と同じように作成され、変更される。 @@ -79,14 +79,14 @@ Scala は様々な具象不変コレクションクラス (concrete immutable co 最後の行が示すように、`updated` の呼び出しは元のベクトル `vec` には一切影響しない。読み込みと同様に、ベクトルの関数型更新も「事実上定数時間」で実行される。ベクトルの真ん中にある要素を更新するには、その要素を格納するノードと、木構造の根ノードからを初めとする全ての親ノードをコピーすることによって行われる。これは関数型更新は、32以内の要素か部分木を格納する 1 〜 5個の ノードを作成することを意味する。これは、可変配列の in-place での上書きに比べると、ずっと時間のかかる計算であるが、ベクトル全体をコピーするよりはずっと安いものだ。 -ベクトルは高速なランダム読み込みと高速な関数型更新の丁度いいバランスを取れているため、不変添字付き列 ([`immutable.IndexedSeq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html)) トレイトのデフォルトの実装となっている: +ベクトルは高速なランダム読み込みと高速な関数型更新の丁度いいバランスを取れているため、不変添字付き列 ([`immutable.IndexedSeq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/IndexedSeq.html)) トレイトのデフォルトの実装となっている: scala> collection.immutable.IndexedSeq(1, 2, 3) res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3) ## 不変スタック -後入れ先出し (LIFO: last in first out) の列が必要ならば、スタック ([`Stack`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Stack.html)) がある。 `push` メソッドを使ってスタックに要素をプッシュ、`pop` を使ってポップ、そして`top` を使って削除することなく一番上の要素を読み込むことができる。これらの演算は、全て定数時間で行われる。 +後入れ先出し (LIFO: last in first out) の列が必要ならば、スタック ([`Stack`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stack.html)) がある。 `push` メソッドを使ってスタックに要素をプッシュ、`pop` を使ってポップ、そして`top` を使って削除することなく一番上の要素を読み込むことができる。これらの演算は、全て定数時間で行われる。 以下はスタックに対して行われる簡単な演算の例だ: @@ -105,7 +105,7 @@ Scala は様々な具象不変コレクションクラス (concrete immutable co ## 不変キュー -キュー ([`Queue`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Queue.html)) はスタックに似ているが、後入れ先出し (LIFO: last in first out) ではなく、先入れ先出し (FIFO: +キュー ([`Queue`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Queue.html)) はスタックに似ているが、後入れ先出し (LIFO: last in first out) ではなく、先入れ先出し (FIFO: first in first out) だ。 以下に空の不変キューの作り方を示す: @@ -134,7 +134,7 @@ first in first out) だ。 ## 範囲 -範囲 ([`Range`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html)) は順序付けされた等間隔の整数の列だ。例えば、「1、2、3」は範囲であり、「5、8、11、14」も範囲だ。Scala で範囲を作成するには、予め定義された `to` メソッドと `by` メソッドを使う。 +範囲 ([`Range`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html)) は順序付けされた等間隔の整数の列だ。例えば、「1、2、3」は範囲であり、「5、8、11、14」も範囲だ。Scala で範囲を作成するには、予め定義された `to` メソッドと `by` メソッドを使う。 scala> 1 to 3 res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3) @@ -150,7 +150,7 @@ first in first out) だ。 ## ハッシュトライ -ハッシュトライは不変集合と不変マップを効率的に実装する標準的な方法だ。ハッシュトライは、[`immutable.HashMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/HashMap.html) クラスによりサポートされている。データ構造は、全てのノードに 32個の要素か 32個の部分木があるという意味でベクトルに似ている。しかし、キーの選択はハッシュコードにより行われる。たとえば、マップから任意のキーを検索する場合、まずキーのハッシュコードを計算する。その後、最初の部分木を選択するのにハッシュコードの下位 5ビットが使われ、次の 5ビットで次の部分木が選択される、という具合だ。ノード内の全ての要素が、その階層までで選ばれているビット範囲内でお互いと異なるハッシュコードを持った時点で選択は終了する。 +ハッシュトライは不変集合と不変マップを効率的に実装する標準的な方法だ。ハッシュトライは、[`immutable.HashMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/HashMap.html) クラスによりサポートされている。データ構造は、全てのノードに 32個の要素か 32個の部分木があるという意味でベクトルに似ている。しかし、キーの選択はハッシュコードにより行われる。たとえば、マップから任意のキーを検索する場合、まずキーのハッシュコードを計算する。その後、最初の部分木を選択するのにハッシュコードの下位 5ビットが使われ、次の 5ビットで次の部分木が選択される、という具合だ。ノード内の全ての要素が、その階層までで選ばれているビット範囲内でお互いと異なるハッシュコードを持った時点で選択は終了する。 ハッシュトライは、サイズ相応の高速な検索と、相応に効率的な関数型加算 `(+)` と減算 `(-)` の調度良いバランスが取れている。そのため、ハッシュトライは Scala の不変マップと不変集合のデフォルトの実装を支えている。実は、Scala は要素が 5個未満の不変集合と不変マップに関して、更なる最適化をしている。1 〜 4個の要素を持つ集合とセットは、要素 (マップの場合は、キー/値のペア) をフィールドとして持つ単一のオブジェクトとして格納する。空の不変集合と、空の不変マップは、ぞれぞれ単一のオブジェクトである。空の不変集合や不変マップは、空であり続けるため、データ構造を複製する必要はない。 @@ -158,7 +158,7 @@ first in first out) だ。 赤黒木は、ノードが「赤」か「黒」に色付けされている平衡二分木の一種だ。他の平衡二分木と同様に演算は木のサイズのログ時間内に確実に完了する。 -Scala は内部で赤黒木を使った不変集合と不変マップの実装を提供する。[`TreeSet`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeSet.html) と [`TreeMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/TreeMap.html) クラスがそれだ。 +Scala は内部で赤黒木を使った不変集合と不変マップの実装を提供する。[`TreeSet`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/TreeSet.html) と [`TreeMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/TreeMap.html) クラスがそれだ。 scala> scala.collection.immutable.TreeSet.empty[Int] res11: scala.collection.immutable.TreeSet[Int] = TreeSet() @@ -170,7 +170,7 @@ Scala は内部で赤黒木を使った不変集合と不変マップの実装 ## 不変ビット集合 -ビット集合 ([`BitSet`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/BitSet.html)) は大きい整数のビットを小さな整数のコレクションを使って表す。例えば、3, 2, と 0 を格納するビット集合は二進法で整数の 1101、十進法で 13 を表す。 +ビット集合 ([`BitSet`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/BitSet.html)) は大きい整数のビットを小さな整数のコレクションを使って表す。例えば、3, 2, と 0 を格納するビット集合は二進法で整数の 1101、十進法で 13 を表す。 内部では、ビット集合は 64ビットの `Long` の配列を使っている。配列の最初の `Long` は 整数の 0〜63、二番目は 64〜127 という具合だ。そのため、ビット集合は最大値が数百以下の場合は非常にコンパクトだ。 @@ -187,7 +187,7 @@ Scala は内部で赤黒木を使った不変集合と不変マップの実装 ## リストマップ -リストマップ ([`ListMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/ListMap.html)) は、キー/値ペアの連結リスト (linked list) により実装されたマップを表す。一般的に、リストマップの演算はリスト全体を総なめする必要がある可能性がある。そのため、リストマップの演算はマップのサイズに対して線形時間をとる。標準の不変マップの方が常に高速なので Scala のリストマップが使われることはほとんど無い。唯一性能の差が出る可能性としては、マップが何らかの理由でリストの最初の要素が他の要素に比べてずっと頻繁に読み込まれるように構築された場合だ。 +リストマップ ([`ListMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/ListMap.html)) は、キー/値ペアの連結リスト (linked list) により実装されたマップを表す。一般的に、リストマップの演算はリスト全体を総なめする必要がある可能性がある。そのため、リストマップの演算はマップのサイズに対して線形時間をとる。標準の不変マップの方が常に高速なので Scala のリストマップが使われることはほとんど無い。唯一性能の差が出る可能性としては、マップが何らかの理由でリストの最初の要素が他の要素に比べてずっと頻繁に読み込まれるように構築された場合だ。 scala> val map = scala.collection.immutable.ListMap(1->"one", 2->"two") map: scala.collection.immutable.ListMap[Int,java.lang.String] = diff --git a/_ja/overviews/collections/concrete-mutable-collection-classes.md b/_ja/overviews/collections/concrete-mutable-collection-classes.md index 4889c7a559..8534783b1a 100644 --- a/_ja/overviews/collections/concrete-mutable-collection-classes.md +++ b/_ja/overviews/collections/concrete-mutable-collection-classes.md @@ -16,7 +16,7 @@ Scala が標準ライブラリで提供する不変コレクションで最も ## 配列バッファ -配列バッファ ([`ArrayBuffer`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayBuffer.html)) は、配列とサイズを格納するバッファだ。配列バッファの演算のほとんどは、単に内部の配列にアクセスして変更するだけなので、配列の演算と同じ速さで実行される。また、配列バッファは効率的にデータをバッファの最後に追加できる。配列バッファへの要素の追加はならし定数時間 (amortized constant time) で実行される。よって、配列バッファは要素が常に最後に追加される場合、大きいコレクションを効率的に構築するのに便利だ。 +配列バッファ ([`ArrayBuffer`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArrayBuffer.html)) は、配列とサイズを格納するバッファだ。配列バッファの演算のほとんどは、単に内部の配列にアクセスして変更するだけなので、配列の演算と同じ速さで実行される。また、配列バッファは効率的にデータをバッファの最後に追加できる。配列バッファへの要素の追加はならし定数時間 (amortized constant time) で実行される。よって、配列バッファは要素が常に最後に追加される場合、大きいコレクションを効率的に構築するのに便利だ。 scala> val buf = scala.collection.mutable.ArrayBuffer.empty[Int] buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() @@ -29,7 +29,7 @@ Scala が標準ライブラリで提供する不変コレクションで最も ## リストバッファ -リストバッファ ([`ListBuffer`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ListBuffer.html)) は、内部に配列の代わりに連結リストを使うこと以外は配列バッファに似ている。バッファを構築後にリストに変換する予定なら、配列バッファの代わりにリストバッファを使うべきだ。 +リストバッファ ([`ListBuffer`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ListBuffer.html)) は、内部に配列の代わりに連結リストを使うこと以外は配列バッファに似ている。バッファを構築後にリストに変換する予定なら、配列バッファの代わりにリストバッファを使うべきだ。 scala> val buf = scala.collection.mutable.ListBuffer.empty[Int] buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() @@ -42,7 +42,7 @@ Scala が標準ライブラリで提供する不変コレクションで最も ## 文字列ビルダ -配列バッファが配列を構築するのに便利で、リストバッファがリストを構築するのに便利なように、文字列ビルダ ([`StringBuilder`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html)) は文字列を構築するのに便利なものだ。文字列ビルダはあまりに頻繁に使われるため、デフォルトの名前空間に既にインポートされている。以下のように、単に `new StringBuilder` で文字列ビルダを作成することができる: +配列バッファが配列を構築するのに便利で、リストバッファがリストを構築するのに便利なように、文字列ビルダ ([`StringBuilder`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/StringBuilder.html)) は文字列を構築するのに便利なものだ。文字列ビルダはあまりに頻繁に使われるため、デフォルトの名前空間に既にインポートされている。以下のように、単に `new StringBuilder` で文字列ビルダを作成することができる: scala> val buf = new StringBuilder buf: StringBuilder = @@ -55,19 +55,19 @@ Scala が標準ライブラリで提供する不変コレクションで最も ## 連結リスト -連結リスト ([`LinkedList`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/LinkedList.html)) は、`next` ポインタにより連結されたノードから成る可変列だ。多くの言語では空の連結リストを表すのに `null` が選ばれるが、空の列も全ての列演算をサポートする必要があるため、Scala のコレクションでは `null` は都合が悪い。特に、`LinkedList.empty.isEmpty` は `true` を返すべきで、`NullPointerException` を発生させるべきではない。 代わりに、空の連結リストは `next` フィールドがノード自身を指すという特殊な方法で表現されている。不変リスト同様、連結リストは順列通りに探索するのに適している。また、連結リストは要素や他の連結リストを簡単に挿入できるように実装されている。 +連結リスト ([`LinkedList`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/LinkedList.html)) は、`next` ポインタにより連結されたノードから成る可変列だ。多くの言語では空の連結リストを表すのに `null` が選ばれるが、空の列も全ての列演算をサポートする必要があるため、Scala のコレクションでは `null` は都合が悪い。特に、`LinkedList.empty.isEmpty` は `true` を返すべきで、`NullPointerException` を発生させるべきではない。 代わりに、空の連結リストは `next` フィールドがノード自身を指すという特殊な方法で表現されている。不変リスト同様、連結リストは順列通りに探索するのに適している。また、連結リストは要素や他の連結リストを簡単に挿入できるように実装されている。 ## 双方向リスト -双方向リスト ([`DoubleLinkedList`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/DoubleLinkedList.html)) は、`next` の他に、現ノードの一つ前の要素を指す `prev` +双方向リスト ([`DoubleLinkedList`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/DoubleLinkedList.html)) は、`next` の他に、現ノードの一つ前の要素を指す `prev` というもう一つの可変フィールドがあることを除けば、単方向の連結リストに似ている。リンクが一つ増えたことで要素の削除が非常に高速になる。 ## 可変リスト -可変リスト ([`MutableList`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/MutableList.html)) は単方向連結リストとリスト終端の空ノードを参照するポインタから構成される。これにより、リストの最後への要素の追加が、終端ノードのためにリスト全体を探索しなくてよくなるため、定数時間の演算となる。[`MutableList`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/MutableList.html) は、現在 Scala の [`mutable.LinearSeq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/LinearSeq.html) トレイトの標準実装だ。 +可変リスト ([`MutableList`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/MutableList.html)) は単方向連結リストとリスト終端の空ノードを参照するポインタから構成される。これにより、リストの最後への要素の追加が、終端ノードのためにリスト全体を探索しなくてよくなるため、定数時間の演算となる。[`MutableList`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/MutableList.html) は、現在 Scala の [`mutable.LinearSeq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/LinearSeq.html) トレイトの標準実装だ。 ## キュー -Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Queue.html)) も提供する。可変キューは不変のものと同じように使えるが、`enqueue` の代わりに `+=` と `++=` 演算子を使って加算する。また、可変キューの `dequeue` は先頭の要素を削除して、それを返す。次に具体例で説明する: +Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/Queue.html)) も提供する。可変キューは不変のものと同じように使えるが、`enqueue` の代わりに `+=` と `++=` 演算子を使って加算する。また、可変キューの `dequeue` は先頭の要素を削除して、それを返す。次に具体例で説明する: scala> val queue = new scala.collection.mutable.Queue[String] queue: scala.collection.mutable.Queue[String] = Queue() @@ -84,13 +84,13 @@ Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.s ## 配列シーケンス -配列シーケンス ([`ArraySeq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArraySeq.html)) は、内部で要素を `Array[Object]` に格納する固定長の可変列だ。 +配列シーケンス ([`ArraySeq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArraySeq.html)) は、内部で要素を `Array[Object]` に格納する固定長の可変列だ。 -典型的には、配列の性能特性が欲しいが、要素の型が特定できず、実行時に `ClassManifest` も無く、ジェネリックな列を作成したい場合に [`ArraySeq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArraySeq.html) を使う。この問題は後ほど[配列の節](arrays.html)で説明する。 +典型的には、配列の性能特性が欲しいが、要素の型が特定できず、実行時に `ClassManifest` も無く、ジェネリックな列を作成したい場合に [`ArraySeq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArraySeq.html) を使う。この問題は後ほど[配列の節](arrays.html)で説明する。 ## スタック -既に不変スタックについては説明した。スタックには、[`mutable.Stack`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/Stack.html) クラスにより実装される可変バージョンもある。変更が上書き処理されるという違いの他は、不変バージョンと全く同じように動作する。 +既に不変スタックについては説明した。スタックには、[`mutable.Stack`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/Stack.html) クラスにより実装される可変バージョンもある。変更が上書き処理されるという違いの他は、不変バージョンと全く同じように動作する。 scala> val stack = new scala.collection.mutable.Stack[Int] stack: scala.collection.mutable.Stack[Int] = Stack() @@ -113,11 +113,11 @@ Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.s ## 配列スタック -配列スタック ([`ArrayStack`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/ArrayStack.html) ) は、内部に必要に応じて大きさを変えた `Array` を使った、可変スタックの代替実装だ。配列スタックは、高速な添字読み込みを提供し、他の演算に関しても普通の可変スタックに比べて少し効率的だ。 +配列スタック ([`ArrayStack`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/ArrayStack.html) ) は、内部に必要に応じて大きさを変えた `Array` を使った、可変スタックの代替実装だ。配列スタックは、高速な添字読み込みを提供し、他の演算に関しても普通の可変スタックに比べて少し効率的だ。 ## ハッシュテーブル -ハッシュテーブルは、内部で要素を配列に格納し、要素の位置はハッシュコードにより決められる。ハッシュテーブルへの要素の追加は、既に配列の中に同じハッシュコードを持つ他の要素が無い限り、定数時間で行われる。そのため、ハッシュコードの分布が適度である限り非常に高速だ。結果として、Scala の可変マップと可変集合のデフォルトの実装はハッシュテーブルに基づいており、[`mutable.HashSet`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashSet.html) クラスと [`mutable.HashMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/HashMap.html) クラスから直接アクセスできる。 +ハッシュテーブルは、内部で要素を配列に格納し、要素の位置はハッシュコードにより決められる。ハッシュテーブルへの要素の追加は、既に配列の中に同じハッシュコードを持つ他の要素が無い限り、定数時間で行われる。そのため、ハッシュコードの分布が適度である限り非常に高速だ。結果として、Scala の可変マップと可変集合のデフォルトの実装はハッシュテーブルに基づいており、[`mutable.HashSet`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/HashSet.html) クラスと [`mutable.HashMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/HashMap.html) クラスから直接アクセスできる。 ハッシュ集合とハッシュマップは他の集合やマップと変りなく使うことができる。以下に具体例で説明する: @@ -136,11 +136,11 @@ Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.s ## ウィークハッシュマップ -ウィークハッシュマップ([`WeakHashMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/WeakHashMap.html)) は、ガーベッジコレクタがマップから「弱キー」への参照を追跡しないという特殊なハッシュマップだ。他にキーを参照するものが無くなると、キーとその関連する値はマップから勝手にいなくなる。ウィークハッシュマップは、キーに対する時間のかかる計算結果を再利用するキャッシュのような用途に向いている。キーとその計算結果が普通のハッシュマップに格納された場合、そのマップは限りなく大きくなり続け、キーはガベージコレクタに永遠に回収されない。ウィークハッシュマップを使うことでこの問題を回避できる。キーオブジェクトが到達不可能になり次第、そのエントリーごとウィークハッシュマップから削除される。Scala のウィークハッシュマップは、Java による実装 `java.util.WeakHashMap` のラッパーである [`WeakHashMap`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/WeakHashMap.html) クラスにより実装されている。 +ウィークハッシュマップ([`WeakHashMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/WeakHashMap.html)) は、ガーベッジコレクタがマップから「弱キー」への参照を追跡しないという特殊なハッシュマップだ。他にキーを参照するものが無くなると、キーとその関連する値はマップから勝手にいなくなる。ウィークハッシュマップは、キーに対する時間のかかる計算結果を再利用するキャッシュのような用途に向いている。キーとその計算結果が普通のハッシュマップに格納された場合、そのマップは限りなく大きくなり続け、キーはガベージコレクタに永遠に回収されない。ウィークハッシュマップを使うことでこの問題を回避できる。キーオブジェクトが到達不可能になり次第、そのエントリーごとウィークハッシュマップから削除される。Scala のウィークハッシュマップは、Java による実装 `java.util.WeakHashMap` のラッパーである [`WeakHashMap`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/WeakHashMap.html) クラスにより実装されている。 ## 並行マップ -並行マップ (`ConcurrentMap`) は複数のスレッドから同時にアクセスすることできる。通常の[マップ](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Map.html)の演算の他に、以下のアトミックな演算を提供する: +並行マップ (`ConcurrentMap`) は複数のスレッドから同時にアクセスすることできる。通常の[マップ](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Map.html)の演算の他に、以下のアトミックな演算を提供する: ### ConcurrentMap クラスの演算 ### @@ -156,7 +156,7 @@ Scala は不変キューの他に可変キュー ([`mutable.Queue`](http://www.s ## 可変ビット集合 -可変ビット集合 ([`mutable.BitSet`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/BitSet.html)) は、変更が上書き処理される他は不変のものとほとんど同じだ。可変ビット集合は、変更しなかった `Long` をコピーしなくても済むぶん不変ビット集合に比べて少し効率的だ。 +可変ビット集合 ([`mutable.BitSet`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/BitSet.html)) は、変更が上書き処理される他は不変のものとほとんど同じだ。可変ビット集合は、変更しなかった `Long` をコピーしなくても済むぶん不変ビット集合に比べて少し効率的だ。 scala> val bits = scala.collection.mutable.BitSet.empty bits: scala.collection.mutable.BitSet = BitSet() diff --git a/_ja/overviews/collections/iterators.md b/_ja/overviews/collections/iterators.md index 4c2b700761..7ac3076e79 100644 --- a/_ja/overviews/collections/iterators.md +++ b/_ja/overviews/collections/iterators.md @@ -12,7 +12,7 @@ num: 15 language: ja --- -イテレータ ([`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html)) はコレクションではなく、コレクションから要素を1つづつアクセスするための方法だ。イテレータ `it` に対する基本的な演算として `next` と `hasNext` の2つがある。 `it.next()` を呼び出すことで、次の要素が返り、イテレータの内部状態が前進する。よって、同じイテレータに対して `next` を再び呼び出すと、前回返したものの次の要素が得られる。返す要素が無くなると、`next` の呼び出しは `NoSuchElementException` を発生させる。返す要素が残っているかは [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html) の `hasNext` メソッドを使って調べることができる。 +イテレータ ([`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html)) はコレクションではなく、コレクションから要素を1つづつアクセスするための方法だ。イテレータ `it` に対する基本的な演算として `next` と `hasNext` の2つがある。 `it.next()` を呼び出すことで、次の要素が返り、イテレータの内部状態が前進する。よって、同じイテレータに対して `next` を再び呼び出すと、前回返したものの次の要素が得られる。返す要素が無くなると、`next` の呼び出しは `NoSuchElementException` を発生させる。返す要素が残っているかは [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html) の `hasNext` メソッドを使って調べることができる。 イテレータ `it` が返す全ての要素を渡り歩くのに最も率直な方法は while ループを使うことだ: @@ -64,7 +64,7 @@ language: ja への呼び出しはイテレータ `it` と全く同じ要素を返すイテレータを**2つ**返す。この2つのイテレータは独立して作動するため、片方を前進しても他方は影響を受けない。一方、元のイテレータ `it` は `duplicate` により終端まで前進したため、使いものにならない。 要約すると、イテレータは**メソッドを呼び出した後、絶対にアクセスしなければ**コレクションのように振る舞う。Scala -コレクションライブラリは、[`Traversable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Traversable.html) と [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html) に共通の親クラスである [`TraversableOnce`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/TraversableOnce.html) を提供することで、明示的にこれを示す。名前が示す通り、 `TraversableOnce` は `foreach` を用いて一度だけ探索することができるが、探索後のそのオブジェクトの状態は指定されていない。`TraversableOnce` オブジェクトが `Iterator` ならば、探索後はその終端にあるし、もし `Traversable` ならば、そのオブジェクトは今まで通り存在する。 `TraversableOnce` のよく使われる事例としては、イテレータか `Traversable` を受け取ることができるメソッドの引数の型だ。その例として、 `Traversable` クラスの追加メソッド `++` がある。`TraversableOnce` パラメータを受け取るため、イテレータか `Traversable` なコレクションの要素を追加することができる。 +コレクションライブラリは、[`Traversable`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html) と [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html) に共通の親クラスである [`TraversableOnce`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/TraversableOnce.html) を提供することで、明示的にこれを示す。名前が示す通り、 `TraversableOnce` は `foreach` を用いて一度だけ探索することができるが、探索後のそのオブジェクトの状態は指定されていない。`TraversableOnce` オブジェクトが `Iterator` ならば、探索後はその終端にあるし、もし `Traversable` ならば、そのオブジェクトは今まで通り存在する。 `TraversableOnce` のよく使われる事例としては、イテレータか `Traversable` を受け取ることができるメソッドの引数の型だ。その例として、 `Traversable` クラスの追加メソッド `++` がある。`TraversableOnce` パラメータを受け取るため、イテレータか `Traversable` なコレクションの要素を追加することができる。 イテレータの全演算は次の表にまとめられている。 @@ -158,7 +158,7 @@ language: ja しかし、このコードを慎重に見ると間違っていることが分かるはずだ。コードは確かに先頭の空白文字列の続きを読み飛ばすが、`it` は最初の非空白文字列も追い越してしまっているのだ。 -この問題はバッファ付きイテレータを使うことで解決できる。[`BufferedIterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/BufferedIterator.html) トレイトは、`head` というメソッドを追加で提供する [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html) の子トレイトだ。バッファ付きイテレータに対して `head` を呼び出すことで、イテレータを前進させずに最初の要素を返すことができる。バッファ付きイテレータを使うと、空白文字列を読み飛ばすのは以下のように書ける。 +この問題はバッファ付きイテレータを使うことで解決できる。[`BufferedIterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/BufferedIterator.html) トレイトは、`head` というメソッドを追加で提供する [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html) の子トレイトだ。バッファ付きイテレータに対して `head` を呼び出すことで、イテレータを前進させずに最初の要素を返すことができる。バッファ付きイテレータを使うと、空白文字列を読み飛ばすのは以下のように書ける。 def skipEmptyWords(it: BufferedIterator[String]) = while (it.head.isEmpty) { it.next() } diff --git a/_ja/overviews/collections/overview.md b/_ja/overviews/collections/overview.md index 82a26ba556..83b514eb30 100644 --- a/_ja/overviews/collections/overview.md +++ b/_ja/overviews/collections/overview.md @@ -22,8 +22,8 @@ Scala のコレクションは、体系的に可変および不変コレクシ `scala.collection.mutable` パッケージのコレクションは、コレクションを上書き変更する演算がある。 だから可変コレクションを扱うということは、どのコードが、何時どのコレクションを変更したのかということを理解する必要があることを意味する。 -`scala.collection` パッケージのコレクションは、可変か不変かのどちらでもありうる。例えば [`collection.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IndexedSeq.html) -は、[`collection.immutable.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html) と [`collection.mutable.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/IndexedSeq.html) 両方の親クラスだ。一般的に、`scala.collection`パッケージの基底コレクションは不変コレクションと同じインターフェイスを定義し、`scala.collection.mutable` パッケージ内の可変コレクションは、副作用を伴う変更演算を不変インターフェイスに加える。 +`scala.collection` パッケージのコレクションは、可変か不変かのどちらでもありうる。例えば [`collection.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html) +は、[`collection.immutable.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/IndexedSeq.html) と [`collection.mutable.IndexedSeq[T]`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/IndexedSeq.html) 両方の親クラスだ。一般的に、`scala.collection`パッケージの基底コレクションは不変コレクションと同じインターフェイスを定義し、`scala.collection.mutable` パッケージ内の可変コレクションは、副作用を伴う変更演算を不変インターフェイスに加える。 基底コレクションと不変コレクションの違いは、不変なコレクションのクライアントは、他の誰もコレクションを変更しないという保証があるのに対し、基底コレクションのクライアントは自分ではコレクションを変更しなかったという約束しかできない。たとえ静的な型がコレクションを変更するような演算を提供していなくても、実行時の型は他のクライアントが手を加えることができる可変コレクションである可能性がある。 @@ -40,7 +40,7 @@ Scala のコレクションは、体系的に可変および不変コレクシ このパッケージには、コレクションを実装するための基本的なパーツが含まれている。 コレクションクラスがいくつかの演算を `generic` 内のクラスに委譲することはよくあるが、 フレームワークのユーザーが `generic` 内のクラスが必要になることは普通はありえない。 -利便性と後方互換性のために、いくつかの重要な型は `scala` パッケージ内に別名を定義してあるため、インポート無しで単純な名前でコレクションを使うことができる。[`List`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/List.html) 型が良い例で、以下の名前でもアクセスすることができる +利便性と後方互換性のために、いくつかの重要な型は `scala` パッケージ内に別名を定義してあるため、インポート無しで単純な名前でコレクションを使うことができる。[`List`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/List.html) 型が良い例で、以下の名前でもアクセスすることができる scala.collection.immutable.List // 定義元 scala.List // scala パッケージのエイリアス経由 @@ -48,7 +48,7 @@ Scala のコレクションは、体系的に可変および不変コレクシ // 常に自動的にインポートされるため エイリアスされているその他の型は次のとおり: -[`Traversable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Traversable.html)、[`Iterable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html)、[`Seq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Seq.html)、[`IndexedSeq`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IndexedSeq.html)、[`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html)、[`Stream`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Stream.html)、[`Vector`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html)、[`StringBuilder`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html)、[`Range`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html)。 +[`Traversable`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html)、[`Iterable`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterable.html)、[`Seq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Seq.html)、[`IndexedSeq`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html)、[`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html)、[`Stream`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stream.html)、[`Vector`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html)、[`StringBuilder`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/StringBuilder.html)、[`Range`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html)。 次の図は `scala.collection` パッケージ内の全てのコレクションを示す。 これらはすべて、高レベルの抽象クラスやトレイトで一般に可変と不変の両方の実装を持っている。 diff --git a/_ja/overviews/collections/trait-traversable.md b/_ja/overviews/collections/trait-traversable.md index eed29ac4de..52c14efb64 100644 --- a/_ja/overviews/collections/trait-traversable.md +++ b/_ja/overviews/collections/trait-traversable.md @@ -12,7 +12,7 @@ num: 3 language: ja --- -走査可能 ([`Traversable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Traversable.html))トレイトはコレクション階層の最上位に位置する。訳注: 木構造などでノードを一つづつ走査することを traverse と言う。また、-able で終わるトレイトは名詞としても使われるため、「走査可能なもの」という意味だ。 `Traversable` の抽象的な演算は `foreach` のみだ: +走査可能 ([`Traversable`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html))トレイトはコレクション階層の最上位に位置する。訳注: 木構造などでノードを一つづつ走査することを traverse と言う。また、-able で終わるトレイトは名詞としても使われるため、「走査可能なもの」という意味だ。 `Traversable` の抽象的な演算は `foreach` のみだ: def foreach[U](f: Elem => U) @@ -52,7 +52,7 @@ language: ja | **抽象メソッド:** | | | `xs foreach f` |`xs` 内の全ての要素に対して関数 `f` を実行する。 | | **加算:** | | -| `xs ++ ys` |`xs` と `ys` の両方の要素から成るコレクション。 `ys` は [`TraversableOnce`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/TraversableOnce.html) なコレクション、つまり [`Traversable`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Traversable.html) または [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html) だ。| +| `xs ++ ys` |`xs` と `ys` の両方の要素から成るコレクション。 `ys` は [`TraversableOnce`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/TraversableOnce.html) なコレクション、つまり [`Traversable`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html) または [`Iterator`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html) だ。| | **map 演算:** | | | `xs map f` |`xs` 内の全ての要素に関数 `f` を適用することによって得られるコレクション。| | `xs flatMap f` |`xs` 内の全ての要素に対してコレクション値を返す関数 `f` を適用し、その結果を連結したコレクション。| diff --git a/_ja/overviews/parallel-collections/concrete-parallel-collections.md b/_ja/overviews/parallel-collections/concrete-parallel-collections.md index 1681cfa468..4951280848 100644 --- a/_ja/overviews/parallel-collections/concrete-parallel-collections.md +++ b/_ja/overviews/parallel-collections/concrete-parallel-collections.md @@ -13,7 +13,7 @@ language: ja ## 並列配列 -並列配列 ([`ParArray`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParArray.html)) は、線形で連続的な要素の配列を保持する列だ。 +並列配列 ([`ParArray`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParArray.html)) は、線形で連続的な要素の配列を保持する列だ。 そのため、内部の配列を変更することで効率的な要素の読み込みや更新ができるようになる。 また、要素の走査も非常に効率的だ。 並列配列は、サイズが一定であるという意味で配列と似ている。 @@ -38,7 +38,7 @@ language: ja ## 並列ベクトル -並列ベクトル ([`ParVector`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParVector.html)) +並列ベクトル ([`ParVector`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParVector.html)) は、低い定数係数の対数時間で読み込みと書き込みを行う不変列だ。 scala> val pv = scala.collection.parallel.immutable.ParVector.tabulate(1000)(x => x) @@ -52,13 +52,13 @@ language: ja このため、変換メソッドは並列配列のそれに比べてスケーラビリティが低い。 ベクトルの連結が将来の Scala リリースで提供されるようになれば、コンバイナは連結を用いて合成できるようになり、変換メソッドはより効率的になる。 -並列ベクトルは、順次[ベクトル](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html)の並列版で、定数時間で一方から他方へと変換できる。 +並列ベクトルは、順次[ベクトル](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html)の並列版で、定数時間で一方から他方へと変換できる。 ## 並列範囲 -並列範囲 ([`ParRange`](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParRange.html)) +並列範囲 ([`ParRange`](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParRange.html)) は、順序付けされた等間隔の要素の列だ。 -並列範囲は、逐次版の [Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html) と同様に作成される: +並列範囲は、逐次版の [Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html) と同様に作成される: scala> 1 to 3 par res0: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3) @@ -74,8 +74,8 @@ language: ja 並列ハッシュテーブルは要素を内部の配列に格納し、各要素のハッシュコードにより格納する位置を決定する。 並列可変ハッシュ集合 ( -[mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParHashSet.html)) -と並列可変ハッシュマップ ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParHashMap.html)) +[mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParHashSet.html)) +と並列可変ハッシュマップ ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParHashMap.html)) はハッシュテーブルに基づいている。 scala> val phs = scala.collection.parallel.mutable.ParHashSet(1 until 2000: _*) @@ -100,8 +100,8 @@ language: ja ## 並列ハッシュトライ 並列ハッシュトライは、不変集合と不変マップを効率的に表す不変ハッシュトライの並列版だ。 -これらは、[immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParHashSet.html) クラスと -[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/immutable/ParHashMap.html) クラスにより提供される。 +これらは、[immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParHashSet.html) クラスと +[immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/immutable/ParHashMap.html) クラスにより提供される。 scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _*) phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69, 809, 629, 365, 138, 760, 101, 479,... @@ -115,9 +115,9 @@ language: ja ## 並列並行トライ -[concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/concurrent/TrieMap.html) +[concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/concurrent/TrieMap.html) は、複数のスレッドから同時にアクセスできる (concurrent thread-safe) マップだが、 -[mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParTrieMap.html) +[mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParTrieMap.html) は、その並列版だ。 並列データ構造の多くは、走査時にデータ構造が変更された場合に一貫性のある走査を保証しないが、並行トライは更新が次回の走査まで見えないことを保証する。 つまり以下の 1 から 99 の数の平方根を出力する例のように、並行トライを走査中に変更できるようになる: diff --git a/_ko/tour/annotations.md b/_ko/tour/annotations.md index 4e2cba3524..e4674f5bbc 100644 --- a/_ko/tour/annotations.md +++ b/_ko/tour/annotations.md @@ -27,7 +27,6 @@ previous-page: automatic-closures | [`scala.deprecated`](https://www.scala-lang.org/api/current/scala/deprecated.html) | [`java.lang.Deprecated`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Deprecated.html) | | [`scala.inline`](https://www.scala-lang.org/api/current/scala/inline.html) (2.6.0 부터) | 해당 없음 | | [`scala.native`](https://www.scala-lang.org/api/current/scala/native.html) (2.6.0 부터) | [`native`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (키워드) | -| [`scala.remote`](https://www.scala-lang.org/api/current/scala/remote.html) | [`java.rmi.Remote`](http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/Remote.html) | | [`scala.throws`](https://www.scala-lang.org/api/current/scala/throws.html) | [`throws`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (키워드) | | [`scala.transient`](https://www.scala-lang.org/api/current/scala/transient.html) | [`transient`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (키워드) | | [`scala.unchecked`](https://www.scala-lang.org/api/current/scala/unchecked.html) (2.4.0 부터) | 해당 없음 | diff --git a/_overviews/collections/trait-traversable.md b/_overviews/collections/trait-traversable.md index ad749d8097..fe048347ec 100644 --- a/_overviews/collections/trait-traversable.md +++ b/_overviews/collections/trait-traversable.md @@ -44,7 +44,7 @@ The `foreach` method is meant to traverse all elements of the collection, and ap | **Abstract Method:** | | | `xs foreach f` |Executes function `f` for every element of `xs`.| | **Addition:** | | -| `xs ++ ys` |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [TraversableOnce](http://www.scala-lang.org/api/current/scala/collection/TraversableOnce.html) collection, i.e., either a [Traversable](http://www.scala-lang.org/api/current/scala/collection/Traversable.html) or an [Iterator](http://www.scala-lang.org/api/current/scala/collection/Iterator.html).| +| `xs ++ ys` |A collection consisting of the elements of both `xs` and `ys`. `ys` is a [TraversableOnce](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/TraversableOnce.html) collection, i.e., either a [Traversable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html) or an [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html).| | **Maps:** | | | `xs map f` |The collection obtained from applying the function f to every element in `xs`.| | `xs flatMap f` |The collection obtained from applying the collection-valued function `f` to every element in `xs` and concatenating the results.| diff --git a/_pl/tour/annotations.md b/_pl/tour/annotations.md index 65921a156f..70feceffde 100644 --- a/_pl/tour/annotations.md +++ b/_pl/tour/annotations.md @@ -26,7 +26,6 @@ Znaczenie adnotacji jest zależne od implementacji. Na platformie Java poniższe | [`scala.deprecated`](https://www.scala-lang.org/api/current/scala/deprecated.html) | [`java.lang.Deprecated`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Deprecated.html) | | [`scala.inline`](https://www.scala-lang.org/api/current/scala/inline.html) (since 2.6.0) | brak odpowiednika | | [`scala.native`](https://www.scala-lang.org/api/current/scala/native.html) (since 2.6.0) | [`native`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | -| [`scala.remote`](https://www.scala-lang.org/api/current/scala/remote.html) | [`java.rmi.Remote`](http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/Remote.html) | | [`scala.throws`](https://www.scala-lang.org/api/current/scala/throws.html) | [`throws`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | [`scala.transient`](https://www.scala-lang.org/api/current/scala/transient.html) | [`transient`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | [`scala.unchecked`](https://www.scala-lang.org/api/current/scala/unchecked.html) (od 2.4.0) | brak odpowiednika | diff --git a/_pt-br/tour/annotations.md b/_pt-br/tour/annotations.md index 3b262897de..1ae94788c7 100644 --- a/_pt-br/tour/annotations.md +++ b/_pt-br/tour/annotations.md @@ -26,7 +26,6 @@ O significado das cláusulas de anotação é _dependente da implementação_. N | [`scala.deprecated`](https://www.scala-lang.org/api/current/scala/deprecated.html) | [`java.lang.Deprecated`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Deprecated.html) | | [`scala.inline`](https://www.scala-lang.org/api/current/scala/inline.html) (desde 2.6.0) | não há equivalente | | [`scala.native`](https://www.scala-lang.org/api/current/scala/native.html) (desde 2.6.0) | [`native`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (keyword) | -| [`scala.remote`](https://www.scala-lang.org/api/current/scala/remote.html) | [`java.rmi.Remote`](http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/Remote.html) | | [`scala.throws`](https://www.scala-lang.org/api/current/scala/throws.html) | [`throws`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (keyword) | | [`scala.transient`](https://www.scala-lang.org/api/current/scala/transient.html) | [`transient`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (keyword) | | [`scala.unchecked`](https://www.scala-lang.org/api/current/scala/unchecked.html) (since 2.4.0) | não há equivalente | diff --git a/_zh-cn/overviews/collections/overview.md b/_zh-cn/overviews/collections/overview.md index 26d5e90771..3d2391a12e 100644 --- a/_zh-cn/overviews/collections/overview.md +++ b/_zh-cn/overviews/collections/overview.md @@ -20,7 +20,7 @@ Scala 集合类系统地区分了可变的和不可变的集合。可变集合 `scala.collection.mutable`包的集合类则有一些操作可以修改集合。所以处理可变集合意味着你需要去理解哪些代码的修改会导致集合同时改变。 -`scala.collection`包中的集合,既可以是可变的,也可以是不可变的。例如:[collection.IndexedSeq[T]](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html)] 就是 [collection.immutable.IndexedSeq[T]](http://www.scala-lang.org/api/current/scala/collection/immutable/IndexedSeq.html) 和[collection.mutable.IndexedSeq[T]](http://www.scala-lang.org/api/current/scala/collection/mutable/IndexedSeq.html)这两类的超类。`scala.collection`包中的根集合类中定义了相同的接口作为不可变集合类,同时,`scala.collection.mutable`包中的可变集合类代表性的添加了一些有辅助作用的修改操作到这个immutable 接口。 +`scala.collection`包中的集合,既可以是可变的,也可以是不可变的。例如:[collection.IndexedSeq[T]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html)] 就是 [collection.immutable.IndexedSeq[T]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/IndexedSeq.html) 和[collection.mutable.IndexedSeq[T]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/IndexedSeq.html)这两类的超类。`scala.collection`包中的根集合类中定义了相同的接口作为不可变集合类,同时,`scala.collection.mutable`包中的可变集合类代表性的添加了一些有辅助作用的修改操作到这个immutable 接口。 根集合类与不可变集合类之间的区别是不可变集合类的客户端可以确保没有人可以修改集合。然而,根集合类的客户端仅保证不修改集合本身。即使这个集合类没有提供修改集合的静态操作,它仍然可能在运行时作为可变集合被其它客户端所修改。 @@ -41,7 +41,7 @@ Scala 集合类系统地区分了可变的和不可变的集合。可变集合 List // 因为scala._ // 总是是被自动导入。 -其它类型的别名有: [Traversable](http://www.scala-lang.org/api/current/scala/collection/Traversable.html), [Iterable](http://www.scala-lang.org/api/current/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/current/scala/collection/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/current/scala/collection/Iterator.html), [Stream](http://www.scala-lang.org/api/current/scala/collection/immutable/Stream.html), [Vector](http://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/current/scala/collection/mutable/StringBuilder.html), [Range](http://www.scala-lang.org/api/current/scala/collection/immutable/Range.html)。 +其它类型的别名有: [Traversable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html), [Iterable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html), [Stream](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stream.html), [Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/StringBuilder.html), [Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html)。 下面的图表显示了`scala.collection`包中所有的集合类。这些都是高级抽象类或特性,它们通常具备和不可变实现一样的可变实现。 From f6431aae58c113fe6a3be8a193892149887a977d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 11 Jun 2019 07:57:25 +0200 Subject: [PATCH 0630/3174] Reorder and retitle the collection guides --- _data/overviews.yml | 94 ++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index 0b5470023e..bfc4c293ed 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -2,53 +2,6 @@ - category: Standard Library description: "Guides and overviews covering the Scala standard library." overviews: - - title: Collections - by: Martin Odersky - icon: sitemap - url: "collections/introduction.html" - description: "Scala's Collection Library." - subdocs: - - title: Introduction - url: "collections/introduction.html" - - title: Mutable and Immutable Collections - url: "collections/overview.html" - - title: Trait Traversable - url: "collections/trait-traversable.html" - - title: Trait Iterable - url: "collections/trait-iterable.html" - - title: The sequence traits Seq, IndexedSeq, and LinearSeq - url: "collections/seqs.html" - - title: Sets - url: "collections/sets.html" - - title: Maps - url: "collections/maps.html" - - title: Concrete Immutable Collection Classes - url: "collections/concrete-immutable-collection-classes.html" - - title: Concrete Mutable Collection Classes - url: "collections/concrete-mutable-collection-classes.html" - - title: Arrays - url: "collections/arrays.html" - - title: Strings - url: "collections/strings.html" - - title: Performance Characteristics - url: "collections/performance-characteristics.html" - - title: Equality - url: "collections/equality.html" - - title: Views - url: "collections/views.html" - - title: Iterators - url: "collections/iterators.html" - - title: Creating Collections From Scratch - url: "collections/creating-collections-from-scratch.html" - - title: Conversions Between Java and Scala Collections - url: "collections/conversions-between-java-and-scala-collections.html" - - title: Migrating from Scala 2.7 - url: "collections/migrating-from-scala-27.html" - - title: The Architecture of Scala Collections - icon: building - url: "core/architecture-of-scala-collections.html" - by: Martin Odersky and Lex Spoon - description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - title: Scala 2.13’s Collections by: Martin Odersky and Julien Richard-Foy icon: sitemap @@ -102,6 +55,53 @@ url: "core/custom-collection-operations.html" by: Julien Richard-Foy description: "This guide shows how to write operations that can be applied to any collection type and return the same collection type, and how to write operations that can be parameterized by the type of collection to build." + - title: Scala 2.8 to 2.12’s Collections + by: Martin Odersky + icon: sitemap + url: "collections/introduction.html" + description: "Scala's Collection Library." + subdocs: + - title: Introduction + url: "collections/introduction.html" + - title: Mutable and Immutable Collections + url: "collections/overview.html" + - title: Trait Traversable + url: "collections/trait-traversable.html" + - title: Trait Iterable + url: "collections/trait-iterable.html" + - title: The sequence traits Seq, IndexedSeq, and LinearSeq + url: "collections/seqs.html" + - title: Sets + url: "collections/sets.html" + - title: Maps + url: "collections/maps.html" + - title: Concrete Immutable Collection Classes + url: "collections/concrete-immutable-collection-classes.html" + - title: Concrete Mutable Collection Classes + url: "collections/concrete-mutable-collection-classes.html" + - title: Arrays + url: "collections/arrays.html" + - title: Strings + url: "collections/strings.html" + - title: Performance Characteristics + url: "collections/performance-characteristics.html" + - title: Equality + url: "collections/equality.html" + - title: Views + url: "collections/views.html" + - title: Iterators + url: "collections/iterators.html" + - title: Creating Collections From Scratch + url: "collections/creating-collections-from-scratch.html" + - title: Conversions Between Java and Scala Collections + url: "collections/conversions-between-java-and-scala-collections.html" + - title: Migrating from Scala 2.7 + url: "collections/migrating-from-scala-27.html" + - title: The Architecture of Scala 2.8 to 2.12’s Collections + icon: building + url: "core/architecture-of-scala-collections.html" + by: Martin Odersky and Lex Spoon + description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - category: Language description: "Guides and overviews covering features in the Scala language." From 6e177b98b9752e80dd3cae77ff37ae37fb8738aa Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 24 Jun 2019 07:51:13 +0100 Subject: [PATCH 0631/3174] Fix links, take 3 --- _overviews/collections/overview.md | 8 ++++---- .../concrete-parallel-collections.md | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_overviews/collections/overview.md b/_overviews/collections/overview.md index a394241837..41bdf6ff39 100644 --- a/_overviews/collections/overview.md +++ b/_overviews/collections/overview.md @@ -41,10 +41,10 @@ mutable collection means you need to understand which code changes which collection when. A collection in package `scala.collection` can be either mutable or -immutable. For instance, [collection.IndexedSeq\[T\]](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html) -is a superclass of both [collection.immutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/current/scala/collection/immutable/IndexedSeq.html) +immutable. For instance, [collection.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html) +is a superclass of both [collection.immutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/IndexedSeq.html) and -[collection.mutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/current/scala/collection/mutable/IndexedSeq.html) +[collection.mutable.IndexedSeq\[T\]](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/IndexedSeq.html) Generally, the root collections in package `scala.collection` define the same interface as the immutable collections, and the mutable collections in package @@ -94,7 +94,7 @@ can be accessed alternatively as // is always automatically imported Other types aliased are -[Traversable](http://www.scala-lang.org/api/current/scala/collection/Traversable.html), [Iterable](http://www.scala-lang.org/api/current/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/current/scala/collection/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/current/scala/collection/Iterator.html), [Stream](http://www.scala-lang.org/api/current/scala/collection/immutable/Stream.html), [Vector](http://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/current/scala/collection/mutable/StringBuilder.html), and [Range](http://www.scala-lang.org/api/current/scala/collection/immutable/Range.html). +[Traversable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Traversable.html), [Iterable](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterable.html), [Seq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Seq.html), [IndexedSeq](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/IndexedSeq.html), [Iterator](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/Iterator.html), [Stream](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Stream.html), [Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html), [StringBuilder](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/mutable/StringBuilder.html), and [Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html). The following figure shows all collections in package `scala.collection`. These are all high-level abstract classes or traits, which diff --git a/_ru/overviews/parallel-collections/concrete-parallel-collections.md b/_ru/overviews/parallel-collections/concrete-parallel-collections.md index f0985016b8..7dc087e280 100644 --- a/_ru/overviews/parallel-collections/concrete-parallel-collections.md +++ b/_ru/overviews/parallel-collections/concrete-parallel-collections.md @@ -13,7 +13,7 @@ num: 2 ## Параллельный Массив -Последовательность [ParArray](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParArray.html) хранит линейный массив смежно хранимых элементов. Это означает, что получение доступа и обновление элементов эффективно, так как происходит путем изменения массива, лежащего в основе. По этой причине наиболее эффективна последовательная обработка элементов одного за другим. Параллельные массивы похожи на обычные в том отношении, что их размер постоянен. +Последовательность [ParArray](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParArray.html) хранит линейный массив смежно хранимых элементов. Это означает, что получение доступа и обновление элементов эффективно, так как происходит путем изменения массива, лежащего в основе. По этой причине наиболее эффективна последовательная обработка элементов одного за другим. Параллельные массивы похожи на обычные в том отношении, что их размер постоянен. scala> val pa = scala.collection.parallel.mutable.ParArray.tabulate(1000)(x => 2 * x + 1) pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 3, 5, 7, 9, 11, 13,... @@ -30,7 +30,7 @@ num: 2 ## Параллельный вектор -[ParVector](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/immutable/ParVector.html) является неизменяемой последовательностью, временная сложность доступа и обновления которой является логарифмической с низкой константой-множителем. +[ParVector](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/immutable/ParVector.html) является неизменяемой последовательностью, временная сложность доступа и обновления которой является логарифмической с низкой константой-множителем. scala> val pv = scala.collection.parallel.immutable.ParVector.tabulate(1000)(x => x) pv: scala.collection.parallel.immutable.ParVector[Int] = ParVector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,... @@ -41,11 +41,11 @@ num: 2 Неизменяемые векторы представлены 32-ичными деревьями (32-way trees), поэтому [разделители]({{ site.baseurl }}/ru/overviews/parallel-collections/architecture.html) разбивают их, назначая по поддереву каждому новому разделителю. [Компоновщики]({{ site.baseurl }}/ru/overviews/parallel-collections/architecture.html) в настоящий момент хранят вектор из элементов и компонуют путем отложенного копирования. По этой причине методы трансформации менее масштабируемы по сравнению с теми же методами параллельного массива. Как только в будущем релизе Scala станет доступной операция конкатенации векторов, компоновщики станут образовываться путем конкатенации, и от этого методы трансформации станут гораздо более эффективными. -Параллельный вектор является параллельным аналогом последовательной коллекции [Vector](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html), и преобразования одного в другое занимают постоянное время. +Параллельный вектор является параллельным аналогом последовательной коллекции [Vector](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Vector.html), и преобразования одного в другое занимают постоянное время. ## Параллельный диапазон -[ParRange](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParRange.html) представляет собой упорядоченную последовательность элементов, отстоящих друг от друга на одинаковые промежутки. Параллельный диапазон создается подобно последовательному [Range](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html): +[ParRange](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParRange.html) представляет собой упорядоченную последовательность элементов, отстоящих друг от друга на одинаковые промежутки. Параллельный диапазон создается подобно последовательному [Range](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html): scala> 1 to 3 par res0: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3) @@ -57,7 +57,7 @@ num: 2 ## Параллельные хэш-таблицы -В основе параллельной хэш-таблицы лежит массив, причем место элемента таблицы в этом массиве определяется хэш-кодом элемента. На хэш-таблицах основаны параллельные изменяемые хэш-множества ([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParHashSet.html)) и параллельные изменяемые ассоциативные хэш-массивы (хэш-отображения) ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/mutable/ParHashMap.html)). +В основе параллельной хэш-таблицы лежит массив, причем место элемента таблицы в этом массиве определяется хэш-кодом элемента. На хэш-таблицах основаны параллельные изменяемые хэш-множества ([mutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParHashSet.html)) и параллельные изменяемые ассоциативные хэш-массивы (хэш-отображения) ([mutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/mutable/ParHashMap.html)). scala> val phs = scala.collection.parallel.mutable.ParHashSet(1 until 2000: _*) phs: scala.collection.parallel.mutable.ParHashSet[Int] = ParHashSet(18, 327, 736, 1045, 773, 1082,... @@ -71,7 +71,7 @@ num: 2 ## Параллельные префиксные хэш-деревья (Hash Tries) -Параллельные префиксные хэш-деревья являются параллельным аналогом неизменяемых префиксных хэш-деревьев, которые используются для эффективного представления неизменяемых множеств и ассоциативных массивов. Последние представлены классами [immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/parallel/immutable/ParHashSet.html) и [immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/immutable/ParHashMap.html). +Параллельные префиксные хэш-деревья являются параллельным аналогом неизменяемых префиксных хэш-деревьев, которые используются для эффективного представления неизменяемых множеств и ассоциативных массивов. Последние представлены классами [immutable.ParHashSet](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParHashSet.html) и [immutable.ParHashMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/immutable/ParHashMap.html). scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _*) phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69, 809, 629, 365, 138, 760, 101, 479,... @@ -85,7 +85,7 @@ num: 2 ## Параллельные многопоточные префиксные деревья (Concurrent Tries) -Параллельным аналогом коллекции [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/concurrent/TrieMap.html), представляющей собой многопоточный и потокозащищеный ассоциативный массив, является коллекция [mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-version}}/scala/collection/parallel/mutable/ParTrieMap.html). В то время, как большинство многопоточных структур данных не гарантируют правильного перебора элементов в случае, если эта структура данных была изменена во время ее прохождения, многопоточные деревья `Ctries` гарантируют, что обновленные данные станут видны только при следующем прохождении. Это означает, что можно изменять многопоточное дерево прямо во время прохождения, как в следующем примере, в котором выводятся квадратные корни от 1 до 99: +Параллельным аналогом коллекции [concurrent.TrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/concurrent/TrieMap.html), представляющей собой многопоточный и потокозащищеный ассоциативный массив, является коллекция [mutable.ParTrieMap](http://www.scala-lang.org/api/{{ site.scala-212-version}}/scala/collection/parallel/mutable/ParTrieMap.html). В то время, как большинство многопоточных структур данных не гарантируют правильного перебора элементов в случае, если эта структура данных была изменена во время ее прохождения, многопоточные деревья `Ctries` гарантируют, что обновленные данные станут видны только при следующем прохождении. Это означает, что можно изменять многопоточное дерево прямо во время прохождения, как в следующем примере, в котором выводятся квадратные корни от 1 до 99: scala> val numbers = scala.collection.parallel.mutable.ParTrieMap((1 until 100) zip (1 until 100): _*) map { case (k, v) => (k.toDouble, v.toDouble) } numbers: scala.collection.parallel.mutable.ParTrieMap[Double,Double] = ParTrieMap(0.0 -> 0.0, 42.0 -> 42.0, 70.0 -> 70.0, 2.0 -> 2.0,... From 37f64a196bb756d7bc85ac845741b248d7ddd5c6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Sun, 23 Jun 2019 14:40:24 +0100 Subject: [PATCH 0632/3174] Rebrand MiMa & clarify recommended version scheme --- ...binary-compatibility-for-library-authors.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/_overviews/tutorials/binary-compatibility-for-library-authors.md b/_overviews/tutorials/binary-compatibility-for-library-authors.md index 655317c95d..79efcdc29b 100644 --- a/_overviews/tutorials/binary-compatibility-for-library-authors.md +++ b/_overviews/tutorials/binary-compatibility-for-library-authors.md @@ -143,11 +143,11 @@ How can we, as library authors, spare our users of runtime errors and dependency ## MiMa - Checking binary compatibility against previous library versions -The [Migration Manager for Scala](https://github.com/lightbend/migration-manager) (MiMa) is a tool for diagnosing binary incompatibilities between different library versions. +[MiMa](https://github.com/lightbend/mima) is a tool for diagnosing binary incompatibilities between different library versions. It works by comparing the class files of two provided JARs and report any binary incompatibilities found. Both backwards and forwards binary incompatibility can be detected by swapping input order of the JARs. -By incorporating MiMa's [sbt plugin](https://github.com/lightbend/migration-manager/wiki/sbt-plugin) into your sbt build, you can easily check whether +By incorporating MiMa's [sbt plugin](https://github.com/lightbend/mima/wiki/sbt-plugin) into your sbt build, you can easily check whether you have accidentally introduced binary incompatible changes. Detailed instruction on how to use the sbt plugin can be found in the link. We strongly encourage every library author to incorporate MiMa into their continuous integration and release workflow. @@ -175,7 +175,7 @@ Again, we recommend using MiMa to double check that you have not broken binary c ## Versioning Scheme - Communicating compatibility breakages -Library authors use versioning schemes to communicate compatibility guarantees between library releases to their users. Versioning schemes like [Semantic Versioning](http://semver.org/)(SemVer) allow +Library authors use versioning schemes to communicate compatibility guarantees between library releases to their users. Versioning schemes like [Semantic Versioning](http://semver.org/) (SemVer) allow users to easily reason about the impact of updating a library, without needing to read the detailed release notes. In the following section, we will outline a versioning scheme based on Semantic Versioning that we **strongly encourage** you to adopt for your libraries. The rules listed below are **in addition** to @@ -183,12 +183,16 @@ Semantic Versioning v2.0.0. ### Recommended Versioning Scheme -* If backward **binary compatibility** is broken, **major version number** must be increased. -* If backward **source compatibility** is broken, **minor version number** must be increased. -* A change in **patch version number** signals **neither binary nor source incompatibility**. +Given a version number MAJOR.MINOR.PATCH, you MUST increment the: + +1. MAJOR version if backward **binary compatibility** is broken, +2. MINOR version if backward **source compatibility** is broken, and +3. PATCH version to signal **neither binary nor source incompatibility**. + According to SemVer, patch versions should contain only bug fixes that fix incorrect behavior so major behavioral change in method/classes should result in a minor version bump. -* When major version is `0`, a minor version bump **may contain both source and binary breakages**. + +* When the major version is `0`, a minor version bump **may contain both source and binary breakages**. Some examples: From dc06ff3c20e7464a100fc65869b04294daee1296 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Mon, 24 Jun 2019 10:07:33 +0100 Subject: [PATCH 0633/3174] Drop the reference to SLIPs --- _sips/sip-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sips/sip-tutorial.md b/_sips/sip-tutorial.md index b5ed7e03ae..24d1577a0d 100644 --- a/_sips/sip-tutorial.md +++ b/_sips/sip-tutorial.md @@ -10,7 +10,7 @@ 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](http://github.com/scala/docs.scala-lang) and clone it. -* Create a new SIP file in the `sips/pending/_posts/`. 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/pending/_posts/`. Use the [SIP template](https://github.com/scala/docs.scala-lang/blob/master/_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](http://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. From 50f3d29704c7e05ca34583c6b83c5fb4c4f3f5c6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Mon, 24 Jun 2019 10:53:48 +0100 Subject: [PATCH 0634/3174] Add 2.13.0 to the JDK compatibility table --- _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 117e52b90b..57d9e3d7b3 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -18,8 +18,8 @@ This table shows the first Scala release in each series that works with each JVM | JVM version | Minimum Scala versions | |:-----------:|:----------------------------------------------------------------------------------------------| | 12 | see [below](#jdk-12-compatibility-notes) | -| 11 | 2.12.4, 2.11.12, 2.10.7 (but also, see [below](#jdk-11-compatibility-notes)) | -| 8 | 2.12.0, 2.11.0, 2.10.2 | +| 11 | 2.13.0, 2.12.4, 2.11.12, 2.10.7 (but also, see [below](#jdk-11-compatibility-notes)) | +| 8 | 2.13.0, 2.12.0, 2.11.0, 2.10.2 | | 7 | 2.11.0, 2.10.0 | | 6 | 2.11.0, 2.10.0 | From 5a501aa966675623c714bb848202eaaf545a5f0f Mon Sep 17 00:00:00 2001 From: alex-t-wix <47665163+alex-t-wix@users.noreply.github.com> Date: Mon, 24 Jun 2019 14:54:25 +0300 Subject: [PATCH 0635/3174] Clarifying first limitation of value-classes Phrase "... val parameter whose type is not a value class" seems wrong. You actually can have value class as a parameter but it must be a standard value class. I suggest using term "user-defined value class". --- _overviews/core/value-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/core/value-classes.md b/_overviews/core/value-classes.md index 9b9d0c06a4..06cba3d4cb 100644 --- a/_overviews/core/value-classes.md +++ b/_overviews/core/value-classes.md @@ -140,7 +140,7 @@ Full details on the implementation of value classes and their limitations may be A value class ... -1. ... must have only a primary constructor with exactly one public, val parameter whose type is not a value class. (From Scala 2.11.0, the parameter may be non-public.) +1. ... must have only a primary constructor with exactly one public, val parameter whose type is not a user-defined value class. (From Scala 2.11.0, the parameter may be non-public.) 2. ... may not have specialized type parameters. 3. ... may not have nested or local classes, traits, or objects 4. ... may not define a equals or hashCode method. From 2927896954776c1d3144078e4f742cab59ac4696 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Mon, 24 Jun 2019 14:07:38 +0100 Subject: [PATCH 0636/3174] Add 2.13.0 to JDK 11 compat notes --- _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 57d9e3d7b3..92ae69b088 100644 --- a/_overviews/jdk-compatibility/overview.md +++ b/_overviews/jdk-compatibility/overview.md @@ -43,7 +43,7 @@ Like the 2.12.x series, the Scala 2.13.x series will support Java 8 and higher. Although the table above jumps from 8 to 11, JDK 9 and 10 will probably also work wherever 11 does. But unlike 9 and 10, 11 is an LTS release, so 11 is what we actually test on and recommend. -As of Scala 2.12.8 and 2.11.12, **JDK 11 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. Scala 2.13.x will eventually provide [rudimentary support](https://github.com/scala/scala/pull/7218) for this, but likely only in nightlies built on Java 11. +As of Scala 2.13.0, 2.12.8 and 2.11.12, **JDK 11 support is incomplete**. Notably, `scalac` will not enforce the restrictions of the Java Platform Module System, which means that code that typechecks may incur linkage errors at runtime. Scala 2.13.x will eventually provide [rudimentary support](https://github.com/scala/scala/pull/7218) for this, but likely only in nightlies built on Java 11. JDK 11 support requires minimum sbt version 1.1.0, or 0.13.17 in the 0.13.x series. From 771034b0b2c2fed5e38e8775bc671948a4317887 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Tue, 25 Jun 2019 11:39:21 +0800 Subject: [PATCH 0637/3174] (overview) Fix zh-cn in pr#1398, with more fixes of the same page. --- _zh-cn/overviews/core/value-classes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_zh-cn/overviews/core/value-classes.md b/_zh-cn/overviews/core/value-classes.md index b731b9da0e..d19501d7e4 100644 --- a/_zh-cn/overviews/core/value-classes.md +++ b/_zh-cn/overviews/core/value-classes.md @@ -123,9 +123,9 @@ value类在以下情况下,需要真正实例化: 一个value类 ... -1. ... 必须只有一个public的构造函数。并有且只有一个public的,类型不为value类的val参数。 -2. ... 不能有特殊的类型参数. -3. ... 不能有嵌套或本地类、trait或对象。 +1. ... 必须只有一个主构造器。该构造器有且仅有一个public修饰的不可变(val)参数,且参数的类型不是用户自定义的value类。 +2. ... 不能有特殊的类型参数。 +3. ... 不能有嵌套或局部的类、特质或对象。 4. ... 不能定义equals或hashCode方法。 5. ... 必须是一个顶级类,或静态访问对象的一个成员 6. ... 仅能有def为成员。尤其是,成员不能有惰性val、val或者var 。 From 160c8358f543ac056236226dae59f6d8af9b87d2 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Tue, 25 Jun 2019 11:43:54 +0800 Subject: [PATCH 0638/3174] (overview) Fix zh-cn in pr#1398, with more polish-es. --- _zh-cn/overviews/core/value-classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/overviews/core/value-classes.md b/_zh-cn/overviews/core/value-classes.md index d19501d7e4..2a2366e4d7 100644 --- a/_zh-cn/overviews/core/value-classes.md +++ b/_zh-cn/overviews/core/value-classes.md @@ -127,8 +127,8 @@ value类在以下情况下,需要真正实例化: 2. ... 不能有特殊的类型参数。 3. ... 不能有嵌套或局部的类、特质或对象。 4. ... 不能定义equals或hashCode方法。 -5. ... 必须是一个顶级类,或静态访问对象的一个成员 -6. ... 仅能有def为成员。尤其是,成员不能有惰性val、val或者var 。 +5. ... 必须是一个顶级类,或静态访问对象的一个成员。 +6. ... 仅能有def为成员。尤其是,成员不能有惰性val、val或者var。 7. ... 不能被其它类继承。 ### 限制示例 From c9275510fb5547ef302480d7356470aa850c11eb Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Tue, 25 Jun 2019 19:58:42 +0800 Subject: [PATCH 0639/3174] (overview) Improve one statement, add 's for user perspective. --- _overviews/collections-2.13/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections-2.13/introduction.md b/_overviews/collections-2.13/introduction.md index a4ff432874..7d27aec31f 100644 --- a/_overviews/collections-2.13/introduction.md +++ b/_overviews/collections-2.13/introduction.md @@ -91,5 +91,5 @@ Furthermore, the `partition` operation is quite fast, and can be even faster on parallel collections on multiple cores. This document provides an in depth discussion of the APIs of the -Scala collections classes from a user perspective. It takes you on +Scala collections classes from a user's perspective. It takes you on a tour of all the fundamental classes and the methods they define. From d523cdec634ad56c0bbbdbbc07fae719f9a7043b Mon Sep 17 00:00:00 2001 From: take2 Date: Wed, 26 Jun 2019 07:33:08 +0900 Subject: [PATCH 0640/3174] Translation tour ja (#1387) Authored-By: take2webservice Reviewed by Yasuhiro Tatsuno and Eugene Yokota. --- _data/translations.yml | 2 +- _ja/tour/abstract-type-members.md | 79 ++++++ _ja/tour/annotations.md | 130 ++++++++++ _ja/tour/automatic-closures.md | 62 +++++ _ja/tour/basics.md | 325 ++++++++++++++++++++++++ _ja/tour/by-name-parameters.md | 45 ++++ _ja/tour/case-classes.md | 66 +++++ _ja/tour/classes.md | 131 ++++++++++ _ja/tour/compound-types.md | 54 ++++ _ja/tour/default-parameter-values.md | 50 ++++ _ja/tour/extractor-objects.md | 72 ++++++ _ja/tour/for-comprehensions.md | 77 ++++++ _ja/tour/generic-classes.md | 65 +++++ _ja/tour/higher-order-functions.md | 121 +++++++++ _ja/tour/implicit-conversions.md | 62 +++++ _ja/tour/implicit-parameters.md | 75 ++++++ _ja/tour/inner-classes.md | 91 +++++++ _ja/tour/lower-type-bounds.md | 76 ++++++ _ja/tour/mixin-class-composition.md | 84 ++++++ _ja/tour/multiple-parameter-lists.md | 79 ++++++ _ja/tour/named-arguments.md | 36 +++ _ja/tour/nested-functions.md | 40 +++ _ja/tour/operators.md | 88 +++++++ _ja/tour/package-objects.md | 73 ++++++ _ja/tour/packages-and-imports.md | 87 +++++++ _ja/tour/pattern-matching.md | 166 ++++++++++++ _ja/tour/polymorphic-methods.md | 39 +++ _ja/tour/regular-expression-patterns.md | 63 +++++ _ja/tour/self-types.md | 42 +++ _ja/tour/singleton-objects.md | 122 +++++++++ _ja/tour/tour-of-scala.md | 86 +++++++ _ja/tour/traits.md | 89 +++++++ _ja/tour/tuples.md | 79 ++++++ _ja/tour/type-inference.md | 74 ++++++ _ja/tour/unified-types.md | 97 +++++++ _ja/tour/upper-type-bounds.md | 60 +++++ _ja/tour/variances.md | 184 ++++++++++++++ 37 files changed, 3170 insertions(+), 1 deletion(-) create mode 100644 _ja/tour/abstract-type-members.md create mode 100644 _ja/tour/annotations.md create mode 100644 _ja/tour/automatic-closures.md create mode 100644 _ja/tour/basics.md create mode 100644 _ja/tour/by-name-parameters.md create mode 100644 _ja/tour/case-classes.md create mode 100644 _ja/tour/classes.md create mode 100644 _ja/tour/compound-types.md create mode 100644 _ja/tour/default-parameter-values.md create mode 100644 _ja/tour/extractor-objects.md create mode 100644 _ja/tour/for-comprehensions.md create mode 100644 _ja/tour/generic-classes.md create mode 100644 _ja/tour/higher-order-functions.md create mode 100644 _ja/tour/implicit-conversions.md create mode 100644 _ja/tour/implicit-parameters.md create mode 100644 _ja/tour/inner-classes.md create mode 100644 _ja/tour/lower-type-bounds.md create mode 100644 _ja/tour/mixin-class-composition.md create mode 100644 _ja/tour/multiple-parameter-lists.md create mode 100644 _ja/tour/named-arguments.md create mode 100644 _ja/tour/nested-functions.md create mode 100644 _ja/tour/operators.md create mode 100644 _ja/tour/package-objects.md create mode 100644 _ja/tour/packages-and-imports.md create mode 100644 _ja/tour/pattern-matching.md create mode 100644 _ja/tour/polymorphic-methods.md create mode 100644 _ja/tour/regular-expression-patterns.md create mode 100644 _ja/tour/self-types.md create mode 100644 _ja/tour/singleton-objects.md create mode 100644 _ja/tour/tour-of-scala.md create mode 100644 _ja/tour/traits.md create mode 100644 _ja/tour/tuples.md create mode 100644 _ja/tour/type-inference.md create mode 100644 _ja/tour/unified-types.md create mode 100644 _ja/tour/upper-type-bounds.md create mode 100644 _ja/tour/variances.md diff --git a/_data/translations.yml b/_data/translations.yml index 266b039905..56d0fd59cf 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] + languages: [ba, es, ko, pt-br, pl, zh-cn, th, ru, ja] diff --git a/_ja/tour/abstract-type-members.md b/_ja/tour/abstract-type-members.md new file mode 100644 index 0000000000..f5821a7b74 --- /dev/null +++ b/_ja/tour/abstract-type-members.md @@ -0,0 +1,79 @@ +--- +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 + +redirect_from: "/tutorials/tour/abstract-types.html" +redirect_from: "/tour/abstract-types.html" +--- + +トレイトや抽象クラスのような抽象型は抽象型メンバーを持つことができます。 +これは具体的な実装で実際の型を定義するという意味です。 +こちらが例です。 + +```tut +trait Buffer { + type T + val element: T +} +``` +こちらでは、抽象型`type T`を定義しています。それは`element`の型を記述するために使われます。このトレイトを抽象クラスで継承し、より具体的にするために上限型境界を`T`に追加することができます。 + +```tut +abstract class SeqBuffer extends Buffer { + type U + type T <: Seq[U] + def length = element.length +} +``` +`T`の上限型境界の定義に出てきた、更に別の抽象型`U`の使い方に気をつけてください。この`class SeqBuffer`はこのバッファーの中にシーケンスのみを保持することができます。それは型`T`は新しい抽象型`U`を使った`Seq[U]`のサブタイプであると記述しているからです。 + +抽象型メンバーを持つトレイトと[クラス](classes.html)は無名クラスのインスタンス化と組み合わせてよく使われます。 +これを説明するために、今から整数のリストを参照するシーケンスバッファーを扱うプログラムを見てみます。 + +```tut +abstract class IntSeqBuffer extends SeqBuffer { + type U = Int +} + + +def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = + new IntSeqBuffer { + type T = List[U] + val element = List(elem1, elem2) + } +val buf = newIntSeqBuf(7, 8) +println("length = " + buf.length) +println("content = " + buf.element) +``` +ここで、ファクトリー`newIntSeqBuf`は抽象型`T`を具体的な型`List[Int]`に設定するために、`IntSeqBuf`(つまり`new IntSeqBuffer`)を無名クラスで実装します。 + +抽象型メンバーをクラスの型パラメータに変えることも、その逆も可能です。以下は上記コードの型パラメータのみを使うバージョンです。 + +```tut +abstract class Buffer[+T] { + val element: T +} +abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { + def length = element.length +} + +def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = + new SeqBuffer[Int, List[Int]] { + val element = List(e1, e2) + } + +val buf = newIntSeqBuf(7, 8) +println("length = " + buf.length) +println("content = " + buf.element) +``` +ここでは(`+T <: Seq[U]`)をメソッド`newIntSeqBuf`から戻されるオブジェクトの具体的なシーケンス実装の型を隠すために [変位指定アノテーション](variances.html)を使わなければなりません。さらに、抽象型メンバをパラメータで置換することができないケースがあります。 diff --git a/_ja/tour/annotations.md b/_ja/tour/annotations.md new file mode 100644 index 0000000000..88114954f1 --- /dev/null +++ b/_ja/tour/annotations.md @@ -0,0 +1,130 @@ +--- +layout: tour +title: アノテーション +language: ja + +discourse: true + +partof: scala-tour + +num: 32 +next-page: default-parameter-values +previous-page: by-name-parameters + +redirect_from: "/tutorials/tour/annotations.html" +--- + +アノテーションはメタ情報と定義を関連づけます。例えば、メソッドの前のアノテーション`@deprecated`はメソッドが使われたらコンパイラに警告を出力させます。 +``` +object DeprecationDemo extends App { + @deprecated("deprecation message", "release # which deprecates method") + def hello = "hola" + + hello +} +``` +これはコンパイルされますが、コンパイラは警告"there was one deprecation warning"を出力します。 + +アノテーション句はそれに続く最初の定義か宣言に適用されます。定義と宣言の前には1つ以上のアノテーション句を置くことができます。これらの句の順番は重要ではありません。 + + +## エンコーディングの正確性を保証するアノテーション +条件が一致しない場合にコンパイルを失敗させるアノテーションもあります。例えば、アノテーション`@tailrec`はメソッドが[末尾再帰](https://en.wikipedia.org/wiki/Tail_call)であると保証します。末尾再帰ではメモリ使用量が一定になります。こちらは階乗を計算するメソッドの中での使われ方です。 +```tut +import scala.annotation.tailrec + +def factorial(x: Int): Int = { + + @tailrec + def factorialHelper(x: Int, accumulator: Int): Int = { + if (x == 1) accumulator else factorialHelper(x - 1, accumulator * x) + } + factorialHelper(x, 1) +} +``` +`factorialHelper`メソッドは`@tailrec`を持ちます。`@tailrec`はメソッドが実際に末尾再帰であると保証します。もし`factorialHelper`の実装を以下のように変更すれば、失敗し +``` +import scala.annotation.tailrec + +def factorial(x: Int): Int = { + @tailrec + def factorialHelper(x: Int): Int = { + if (x == 1) 1 else x * factorialHelper(x - 1) + } + factorialHelper(x) +} +``` +"Recursive call not in tail position"というメッセージを受け取ります。 + + +## コード生成に影響するアノテーション +`@inline`のようなアノテーションは生成されたコードに影響します(つまり、アノテーションを使わなかった場合とでjarファイルのバイト数が異なる場合があります)。インライン化とは、メソッドを呼び出している箇所にメソッド本体のコードを挿入することを意味します。結果のバイトコードはより長くなりますが、上手くいけば実行が早くなります。アノテーション`@inline`を使ってもメソッドのインライン化が保証されるわけではありません。しかし、生成されたコードのサイズに関するヒューリスティックスが満たされた場合に限りコンパイラにインライン化をさせます。 + +### Javaのアノテーション ### +Javaと相互運用するScalaのコードを書いている時、記述するアノテーション構文は少し違います。 + +**注:** Javaアノテーションを使う場合、`-target:jvm-1.8`オプションを使ってください。 + +Javaには[アノテーション](https://docs.oracle.com/javase/tutorial/java/annotations/)の形をしたユーザー定義メタデータがあります。Javaのアノテーションの特徴は、要素の初期化のために名前と値のペアを指定する必要があることです。例えば、クラスのソースを追いかけるためのアノテーションが必要なとき、以下のように定義するかもしれません。 + +``` +@interface Source { + public String URL(); + public String mail(); +} +``` + +そして、それは以下のように適用されます。 + +``` +@Source(URL = "http://coders.com/", + mail = "support@coders.com") +public class MyClass extends TheirClass ... +``` + +Scalaでのアノテーションの適用はコンストラクタの呼び出しと似ています。Javaのアノテーションをインスタンス化するためには名前付き引数を使う必要があります。 + +``` +@Source(URL = "http://coders.com/", + mail = "support@coders.com") +class MyScalaClass ... +``` + +アノテーションが(デフォルト値を除き)要素を1つだけ含む場合、この構文はかなり退屈です。そのため慣例により、名前が`value`と指定されていれば、コンストラクタのような構文でJavaに適用できます。 + +``` +@interface SourceURL { + public String value(); + public String mail() default ""; +} +``` + +そして以下のように適用します。 + +``` +@SourceURL("http://coders.com/") +public class MyClass extends TheirClass ... +``` + +この場合、Scalaでも同じことができます。 + +``` +@SourceURL("http://coders.com/") +class MyScalaClass ... +``` + +`mail`要素はデフォルト値つきで定義されているので、明示的に値を指定する必要がありません。しかしながら、もし値を指定する必要がある場合、Javaでは2つのスタイルを混ぜて組み合わせることはできません。 + +``` +@SourceURL(value = "http://coders.com/", + mail = "support@coders.com") +public class MyClass extends TheirClass ... +``` + +Scalaはこの点においてより柔軟です。 + +``` +@SourceURL("http://coders.com/", + mail = "support@coders.com") + class MyScalaClass ... +``` diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md new file mode 100644 index 0000000000..29ae0a8c00 --- /dev/null +++ b/_ja/tour/automatic-closures.md @@ -0,0 +1,62 @@ +--- +layout: tour +title: Automatic Type-Dependent Closure Construction +language: ja + +discourse: true + +partof: scala-tour +--- + +Scala allows parameterless function names as parameters of methods. When such a method is called, the actual parameters for parameterless function names are not evaluated and a nullary function is passed instead which encapsulates the computation of the corresponding parameter (so-called *call-by-name* evaluation). + +The following code demonstrates this mechanism: + + object TargetTest1 extends Application { + def whileLoop(cond: => Boolean)(body: => Unit): Unit = + if (cond) { + body + whileLoop(cond)(body) + } + var i = 10 + whileLoop (i > 0) { + println(i) + i -= 1 + } + } + +The function whileLoop takes two parameters `cond` and `body`. When the function is applied, the actual parameters do not get evaluated. But whenever the formal parameters are used in the body of `whileLoop`, the implicitly created nullary functions will be evaluated instead. Thus, our method `whileLoop` implements a Java-like while-loop with a recursive implementation scheme. + +We can combine the use of [infix/postfix operators](operators.html) with this mechanism to create more complex statements (with a nice syntax). + +Here is the implementation of a loop-unless statement: + + object TargetTest2 extends Application { + def loop(body: => Unit): LoopUnlessCond = + new LoopUnlessCond(body) + protected class LoopUnlessCond(body: => Unit) { + def unless(cond: => Boolean) { + body + if (!cond) unless(cond) + } + } + var i = 10 + loop { + println("i = " + i) + i -= 1 + } unless (i == 0) + } +The `loop` function just accepts a body of a loop and returns an instance of class `LoopUnlessCond` (which encapsulates this body object). Note that the body didn't get evaluated yet. Class `LoopUnlessCond` has a method `unless` which we can use as a *infix operator*. This way, we achieve a quite natural syntax for our new loop: `loop { < stats > } unless ( < cond > )`. + +Here's the output when `TargetTest2` gets executed: + + i = 10 + i = 9 + i = 8 + i = 7 + i = 6 + i = 5 + i = 4 + i = 3 + i = 2 + i = 1 diff --git a/_ja/tour/basics.md b/_ja/tour/basics.md new file mode 100644 index 0000000000..b14330f2b3 --- /dev/null +++ b/_ja/tour/basics.md @@ -0,0 +1,325 @@ +--- +layout: tour +title: 基本 +language: ja + +discourse: true + +partof: scala-tour + +num: 2 +next-page: unified-types +previous-page: tour-of-scala + +redirect_from: "/tutorials/tour/basics.html" +--- + +このページでは、Scalaの基本を取り扱います。 + +## Scalaをブラウザで試してみる + +ScalaFiddleを利用することでブラウザ上でScalaを実行することができます。 + +1. [https://scalafiddle.io](https://scalafiddle.io)を開きます。 +2. 左側のパネルに`println("Hello, world!")`を貼り付けます。 +3. "Run"ボタンを押すと、右側のパネルに出力が表示されます。 + +このサイトを使えば、簡単にセットアップせずScalaのコードの一部を試すことができます。 + +このドキュメントの多くのコードの例はScalaFiddleで開発されています。 +そのため、サンプルコード内のRunボタンをクリックするだけで、そのまま簡単にコードを試すことができます。 + +## 式 + +式は計算可能な文です。 + +``` +1 + 1 +``` +`println`を使うことで、式の結果を出力できます。 + +{% scalafiddle %} +```tut +println(1) // 1 +println(1 + 1) // 2 +println("Hello!") // Hello! +println("Hello," + " world!") // Hello, world! +``` +{% endscalafiddle %} + +### 値 + +`val`キーワードを利用することで、式の結果に名前を付けることができます。 + +```tut +val x = 1 + 1 +println(x) // 2 +``` + +ここでいうところの `x` のように、名前をつけられた結果は 値 と呼ばれます。 +値を参照した場合、その値は再計算されません。 + +値は再代入することができません。 + +```tut:fail +x = 3 // この記述はコンパイルされません。 +``` + +値の型は推測可能ですが、このように型を明示的に宣言することもできます。 + +```tut +val x: Int = 1 + 1 +``` + +型定義では`Int` は識別子`x`の後にくることに注意してください。そして`:`も必要となります。 + +### 変数 + +再代入ができることを除けば、変数は値と似ています。 +`var`キーワードを使うことで、変数は定義できます。 + +```tut +var x = 1 + 1 +x = 3 // "x"は"var"キーワードで宣言されているので、これはコンパイルされます。 +println(x * x) // 9 +``` + +値と同様に、型を宣言したければ、明示的に型を宣言することができます。 + +```tut +var x: Int = 1 + 1 +``` + + +## ブロック + +`{}`で囲むことで式をまとめることができます。これをブロックと呼びます。 + +ブロックの最後の式の結果はブロック全体の結果にもなります。 + +```tut +println({ + val x = 1 + 1 + x + 1 +}) // 3 +``` + +## 関数 + +関数はパラメーターを受け取る式です。 +ここでは与えられた数値に1を足す無名関数(すなわち名前が無い関数)を宣言しています。 + +```tut +(x: Int) => x + 1 +``` +`=>` の左側はパラメーターのリストです。右側はパラメーターを含む式です。 + +関数には名前をつけることもできます。 + +{% scalafiddle %} +```tut +val addOne = (x: Int) => x + 1 +println(addOne(1)) // 2 +``` +{% endscalafiddle %} + +関数は複数のパラメーターをとることもできます。 + +{% scalafiddle %} +```tut +val add = (x: Int, y: Int) => x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +またパラメーターを取らないこともありえます。 + +```tut +val getTheAnswer = () => 42 +println(getTheAnswer()) // 42 +``` + +## メソッド + +メソッドは関数と見た目、振る舞いがとても似ていますが、それらには違いがいくつかあります。 + +メソッドは `def` キーワードで定義されます。 `def` の後ろには名前、パラメーターリスト、戻り値の型、処理の内容が続きます。 + +{% scalafiddle %} +```tut +def add(x: Int, y: Int): Int = x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +戻り値の型は引数リストとコロンの「後ろ」に宣言することに注意してください。`: Int` + +メソッドは複数のパラメーターリストを受け取ることができます。 + +{% scalafiddle %} +```tut +def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier +println(addThenMultiply(1, 2)(3)) // 9 +``` +{% endscalafiddle %} + +また、パラメーターリストを一切受け取らないこともあります。 + +```tut +def name: String = System.getProperty("user.name") +println("Hello, " + name + "!") +``` +メソッドと関数には他にも違いがありますが、今のところは同じようなものと考えて大丈夫です。 + +メソッドは複数行の式も持つことができます。 +```tut +def getSquareString(input: Double): String = { + val square = input * input + square.toString +} +``` +メソッド本体にある最後の式はメソッドの戻り値になります。(Scalaには`return`キーワードはありますが、めったに使われません。) + +## クラス + +`class` キーワードとその後ろに名前、コンストラクタパラメーターを続けることで、クラスを定義することができます。 + +```tut +class Greeter(prefix: String, suffix: String) { + def greet(name: String): Unit = + println(prefix + name + suffix) +} +``` +`greet` メソッドの戻り値の型は`Unit`です。`Unit`は戻り値として意味がないことを示します。 +それはJavaやC言語の`void`と似たような使われ方をします。(`void`との違いは、全てのScalaの式は値を持つ必要があるため、 +実はUnit型のシングルトンで`()`と書かれる値があります。その値には情報はありません。) + +`new` キーワードを使うことで、クラスのインスタンスを生成することができます。 + +```tut +val greeter = new Greeter("Hello, ", "!") +greeter.greet("Scala developer") // Hello, Scala developer! +``` + +クラスについては[後で](classes.html)詳しく取り扱います。 + +## ケースクラス + +Scalaには"ケース"クラスという特別な種類のクラスがあります。デフォルトでケースクラスは不変であり、値で比較されます。 +`case class` キーワードを利用して、ケースクラスを定義できます。 + +```tut +case class Point(x: Int, y: Int) +``` +ケースクラスは、`new` キーワードなしでインスタンス化できます。 + +```tut +val point = Point(1, 2) +val anotherPoint = Point(1, 2) +val yetAnotherPoint = Point(2, 2) +``` + +ケースクラスは値で比較されます。 + +```tut +if (point == anotherPoint) { + println(point + " and " + anotherPoint + " are the same.") +} else { + println(point + " and " + anotherPoint + " are different.") +} // Point(1,2) と Point(1,2) は同じです。 + +if (point == yetAnotherPoint) { + println(point + " and " + yetAnotherPoint + " are the same.") +} else { + println(point + " and " + yetAnotherPoint + " are different.") +} // Point(1,2) と Point(2,2) は異なります。 +``` + +ケースクラスについて紹介すべきことはたくさんあり、あなたはケースクラスが大好きになると確信しています! +それらについては[後で](case-classes.html)詳しく取り扱います。 + +## オブジェクト + +オブジェクトはそれ自体が定義である単一のインスタンスです。そのクラスのシングルトンと考えることもできます。 + +`object`キーワードを利用してオブジェクトを定義することができます。 + +```tut +object IdFactory { + private var counter = 0 + def create(): Int = { + counter += 1 + counter + } +} +``` + +名前を参照してオブジェクトにアクセスすることができます。 + +```tut +val newId: Int = IdFactory.create() +println(newId) // 1 +val newerId: Int = IdFactory.create() +println(newerId) // 2 +``` + +オブジェクトについては [後で](singleton-objects.html)詳しく取り扱います。 + +## トレイト + +トレイトはいくつかのフィールドとメソッドを含む型です。複数のトレイトを結合することもできます。 + +`trait`キーワードでトレイトを定義することができます。 + +```tut +trait Greeter { + def greet(name: String): Unit +} +``` + +トレイトはデフォルトの実装を持つこともできます。 + +{% scalafiddle %} +```tut +trait Greeter { + def greet(name: String): Unit = + println("Hello, " + name + "!") +} +``` + +`extends`キーワードでトレイトを継承することも、`override` キーワードで実装をオーバーライドすることもできます。 + +```tut +class DefaultGreeter extends Greeter + +class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { + override def greet(name: String): Unit = { + println(prefix + name + postfix) + } +} + +val greeter = new DefaultGreeter() +greeter.greet("Scala developer") // Hello, Scala developer! + +val customGreeter = new CustomizableGreeter("How are you, ", "?") +customGreeter.greet("Scala developer") // How are you, Scala developer? +``` +{% endscalafiddle %} + +ここでは、`DefaultGreeter`は一つのトレイトだけを継承していますが、複数のトレイトを継承することもできます。 + +トレイトについては [後で](traits.html)詳しく取り扱います。 + +## メインメソッド + +メインメソッドはプログラムの始点になります。Javaバーチャルマシーンは`main`と名付けられたメインメソッドが必要で、 +それは文字列の配列を一つ引数として受け取ります。 + +オブジェクトを使い、以下のようにメインメソッドを定義することができます。 + +```tut +object Main { + def main(args: Array[String]): Unit = + println("Hello, Scala developer!") +} +``` diff --git a/_ja/tour/by-name-parameters.md b/_ja/tour/by-name-parameters.md new file mode 100644 index 0000000000..86325795ba --- /dev/null +++ b/_ja/tour/by-name-parameters.md @@ -0,0 +1,45 @@ +--- +layout: tour +title: 名前渡しパラメータ +language: ja + +discourse: true + +partof: scala-tour + +num: 31 +next-page: annotations +previous-page: operators + +redirect_from: "/tutorials/tour/by-name-parameters.html" +--- + +*名前渡しのパラメータ*は使用された時に評価されます。それらは*値渡しパラメータ*とは対照的です。名前渡しのパラメータを作るには、単純に`=>`を型の前につけます。 +```tut +def calculate(input: => Int) = input * 37 +``` + +名前渡しパラメータの利点は関数本体の中で使わなければ評価されない点です。一方で、値渡しパラメータの利点は1度しか評価されない点です。 + +こちらはwhileループをどのように実装するかの例です。 + +```tut +def whileLoop(condition: => Boolean)(body: => Unit): Unit = + if (condition) { + body + whileLoop(condition)(body) + } + +var i = 2 + +whileLoop (i > 0) { + println(i) + i -= 1 +} // prints 2 1 +``` + +このメソッド`whileLoop`は条件とループの本体を受け取るために複数パラメータリストを使います。もし`condition`がtrueならば、`body`が実行され、次にwhileLoopが再帰的に呼ばれます。`condition`がfalseならば、bodyは決して評価されません。それは`body`の型の前に`=>`をつけたからです。 + +ここで、`condition`に`i > 0`、`body`に`println(i); i-= 1`を渡した場合、多くの言語で一般的なwhileループと同じ振る舞いをします。 + +パラメータが使われるまで評価を遅延する機能はパフォーマンスの助けになることがあります。それはパラメータを評価するのに多くの計算が必要な場合や、URLの取得のような時間がかかるコードブロックの場合です。 diff --git a/_ja/tour/case-classes.md b/_ja/tour/case-classes.md new file mode 100644 index 0000000000..99a1b6e6f0 --- /dev/null +++ b/_ja/tour/case-classes.md @@ -0,0 +1,66 @@ +--- +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 + +redirect_from: "/tutorials/tour/case-classes.html" +--- + +ケースクラスはこれから論じるいくつかの差異はあるものの普通のクラスと似ています。 +ケースクラスは不変なデータを作るのに適しています。 +このツアーの次のステップでは、[パターンマッチング](pattern-matching.html)でのそれらの有用性を解説します。 + +## ケースクラスの宣言 + +最小のケースクラスにはキーワード`case class`、識別子、パラメータリスト(空かもしれません)が必要です。 +```tut +case class Book(isbn: String) + +val frankenstein = Book("978-0486282114") +``` +ケースクラス`Book`をインスタンス化する時キーワード`new`が使われていないことに気をつけてください。 +これはケースクラスがオブジェクトの生成を行う`apply`メソッドを標準で保有するためです。 + +パラメータ有りでケースクラスを作ると、パラメータはパブリックの`val`となります。 +``` +case class Message(sender: String, recipient: String, body: String) +val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?") + +println(message1.sender) // guillaume@quebec.ca が出力されます +message1.sender = "travis@washington.us" // この行はコンパイルされません +``` +`message1.sender` に再代入することはできません、なぜなら`val`(つまりイミュータブル)だからです。 +ケースクラスでは`var`も使うことができますが、推奨されません。 + +## 比較 +ケースクラスは参照ではなく、構造で比較されます。 +``` +case class Message(sender: String, recipient: String, body: String) + +val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val messagesAreTheSame = message2 == message3 // true +``` +たとえ`message2`と`message3`が異なるオブジェクトを参照していたとしても、それぞれのオブジェクトの値は等価となります。 + +## コピー +`copy`メソッドを使うことで簡単にケースクラスのインスタンスの(浅い)コピーを作ることができます。 +必要に応じて、コンストラクタ引数を変更することもできます。 +``` +case class Message(sender: String, recipient: String, body: String) +val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg") +val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr") +message5.sender // travis@washington.us +message5.recipient // claire@bourgogne.fr +message5.body // "Me zo o komz gant ma amezeg" +``` +`message4`のrecipientは`message5`のsenderとして使われますが、`message4`の定数`body`は直接コピーされます。 diff --git a/_ja/tour/classes.md b/_ja/tour/classes.md new file mode 100644 index 0000000000..0253f210f5 --- /dev/null +++ b/_ja/tour/classes.md @@ -0,0 +1,131 @@ +--- +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 + +redirect_from: "/tutorials/tour/classes.html" +--- + +Scalaにおけるクラスはオブジェクトを作るための設計図です。 +クラスはメソッド、値、変数、型、オブジェクト、トレイト、クラスを持ち、それらはまとめて _メンバー_ と呼ばれます。 +型、オブジェクト、トレイトはツアーで後ほど取り扱います。 + +## クラスを定義する + +最小のクラス定義は単純にキーワード`class`と識別子だけというものです。 +クラス名は大文字から始まるべきです。 + +```tut +class User + +val user1 = new User +``` +`new`キーワードはクラスのインスタンスを作るために使われます。 +`User`はコンストラクターが定義されていないので、引数なしのデフォルトコンストラクターを持ちます。 +しかしながら、コンストラクターとクラス本体は頻繁に欲しくなるでしょう。 +こちらは位置情報のクラス定義の例になります。 + +```tut +class Point(var x: Int, var y: Int) { + + def move(dx: Int, dy: Int): Unit = { + x = x + dx + y = y + dy + } + + override def toString: String = + s"($x, $y)" +} + +val point1 = new Point(2, 3) +point1.x // 2 +println(point1) // prints (2, 3) +``` +この`Point`クラスは4つのメンバーを持ちます。 +変数`x` と `y` そしてメソッド `move` と `toString`です。 +多くの他の言語とは異なり、プライマリコンストラクタはクラスのシグネチャ`(var x: Int, var y: Int)`です。 +`move` メソッドは2つの整数の引数を受け取り、情報を持たない Unit 値 `()` を返します。 +これは大雑把に言えば、Javaのような言語における`void`に対応します。 +その一方で`toString`は引数を受け取りませんが、`String`の値を返します。 +`toString`は[`AnyRef`](unified-types.html)の`toString`をオーバーライドしているので、`override`キーワードのタグが付いています。 + +## コンストラクター + +コンストラクターは次のようにデフォルト値を与えると省略可能なパラメーターを持つことができます。 + +```tut +class Point(var x: Int = 0, var y: Int = 0) + +val origin = new Point // x と y には共に0がセットされます。 +val point1 = new Point(1) +println(point1.x) // 1 が出力されます。 +``` +このバージョンの`Point`クラスでは、`x` と `y` はデフォルト値0を持ち、引数が必須ではありません。 +しかしながらコンストラクタは引数を左から右に読み込むため、もし`y`の値だけを渡したい場合は、パラメーターに名前をつける必要があります。 + +``` +class Point(var x: Int = 0, var y: Int = 0) +val point2 = new Point(y=2) +println(point2.y) // 2 が出力されます。 +``` + +これは明快さを高めるための良い習慣でもあります。 + +## プライベートメンバーとゲッター/セッター構文 +メンバーはデフォルトではパブリックになります。 +クラスの外から隠したい場合は`private`アクセス修飾詞を使いましょう。 + +```tut +class Point { + private var _x = 0 + private var _y = 0 + private val bound = 100 + + def x = _x + def x_= (newValue: Int): Unit = { + if (newValue < bound) _x = newValue else printWarning + } + + def y = _y + def y_= (newValue: Int): Unit = { + if (newValue < bound) _y = newValue else printWarning + } + + private def printWarning = println("WARNING: Out of bounds") +} + +val point1 = new Point +point1.x = 99 +point1.y = 101 // 警告が出力されます。 +``` +このバージョンの`Point`クラスでは、データはプライベート変数 `_x` と `_y` に保存されます。 +プライベートなデータにアクセスするためのメソッド`def x` と `def y` があります。 +`def x_=` と `def y_=` は `_x` と `_y` の値を検証し設定するためのものになります。 +セッターのための特別な構文に注意してください。 +セッターメソッドはゲッターメソッドの識別子に`_=`を追加し、その後ろにパラメーターを取ります。 + +プライマリコンストラクタの`val` と `var` を持つパラメーターはパブリックになります。 +しかしながら`val` は不変となるため、以下のように記述することはできません。 + +``` +class Point(val x: Int, val y: Int) +val point = new Point(1, 2) +point.x = 3 // <-- コンパイルされません。 +``` + +`val` や `var` が存在しないパラメーターはクラス内でだけで参照できるプライベートな値や変数となります。 +``` +class Point(x: Int, y: Int) +val point = new Point(1, 2) +point.x // <-- コンパイルされません。 +``` diff --git a/_ja/tour/compound-types.md b/_ja/tour/compound-types.md new file mode 100644 index 0000000000..6eeadc481d --- /dev/null +++ b/_ja/tour/compound-types.md @@ -0,0 +1,54 @@ +--- +layout: tour +title: 複合型 +language: ja + +discourse: true + +partof: scala-tour + +num: 24 +next-page: self-types +previous-page: abstract-type-members + +redirect_from: "/tutorials/tour/compound-types.html" +--- +ときどき、あるオブジェクトの型が、複数の他の型のサブタイプであると表現する必要が生じます。 +Scalaでは、これは*複合型*を用いて表現できます。複合型とはオブジェクトの型同士を重ねることです。 + +2つのトレイト`Cloneable`と`Resetable`があるとしましょう。 + +```tut +trait Cloneable extends java.lang.Cloneable { + override def clone(): Cloneable = { + super.clone().asInstanceOf[Cloneable] + } +} +trait Resetable { + def reset: Unit +} +``` + +今、関数`cloneAndReset`を書きたいとします。それはオブジェクトを受け取り、それをクローンして、元のオブジェクトをリセットします。 + +``` +def cloneAndReset(obj: ?): Cloneable = { + val cloned = obj.clone() + obj.reset + cloned +} +``` + +パラメータ`obj`の型は何かという疑問が生じます。もし`Cloneable`であれば、オブジェクトを`clone`することができますが、`reset`することはできません。もし`Resetable`であれば、`reset`することができますが、`clone`の操作はできません。そのような状態で型キャストを回避するために`obj`の型を`Cloneable`と`Resetable`の両方であると指定することができます。Scalaではこの複合型は`Cloneable with Resetable`のように書くことができます。 + +こちらが書き変えた関数です。 + +``` +def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { + //... +} +``` +複合型は複数のオブジェクトの型からなり、一つだけの細別型(refinement)を持てます。細別型は既存オブジェクトのメンバーのシグネチャを絞り込むのに使えます。 +一般的な形は`A with B with C ... { refinement }`です。 + +細別の使い方の例は[ミックスインを用いたクラス合成](mixin-class-composition.html)のページにあります。 diff --git a/_ja/tour/default-parameter-values.md b/_ja/tour/default-parameter-values.md new file mode 100644 index 0000000000..fe2da78c75 --- /dev/null +++ b/_ja/tour/default-parameter-values.md @@ -0,0 +1,50 @@ +--- +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 + +redirect_from: "/tutorials/tour/default-parameter-values.html" +--- + +Scalaはパラメータのデフォルト値を与えることができ、呼び出す側はこれらのパラメータを省略できます。 + +```tut +def log(message: String, level: String = "INFO") = println(s"$level: $message") + +log("System starting") // prints INFO: System starting +log("User not found", "WARNING") // prints WARNING: User not found +``` + +パラメータ`level`はデフォルト値を持つので、省略可能です。最終行では、引数`"WARNING"`はデフォルト値`"INFO"`を上書きします。Javaで同じ効果を得るのに、省略可能なパラメータをもつメソッドを複数使ってメソッドのオーバーロードをしたようなものです。しかしながら呼び出す側が引数をひとつ省略すると、以降全ての引数は名前つきにする必要があります。 + +```tut +class Point(val x: Double = 0, val y: Double = 0) + +val point1 = new Point(y = 1) +``` +ここでは、`y = 1`と書かなければなりません。 + +Scalaで定義したデフォルトパラメータはJavaのコードから呼び出される時はオプショナルではありません。 + +```tut +// Point.scala +class Point(val x: Double = 0, val y: Double = 0) +``` + +```java +// Main.java +public class Main { + public static void main(String[] args) { + Point point = new Point(1); // コンパイルされません + } +} +``` diff --git a/_ja/tour/extractor-objects.md b/_ja/tour/extractor-objects.md new file mode 100644 index 0000000000..2b12283764 --- /dev/null +++ b/_ja/tour/extractor-objects.md @@ -0,0 +1,72 @@ +--- +layout: tour +title: 抽出子オブジェクト +language: ja + +discourse: true + +partof: scala-tour + +num: 16 +next-page: for-comprehensions +previous-page: regular-expression-patterns + +redirect_from: "/tutorials/tour/extractor-objects.html" +--- + +抽出子オブジェクトは`unapply`メソッドを持つオブジェクトです。 +`apply`メソッドが引数を取り、オブジェクトを作るコンストラクタであるように、`unapply`は1つのオブジェクトを受け取り、引数を返そうとします。 +これはパターンマッチングと部分関数で最も頻繁に使われます。 + +```tut +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") +} +``` + +`apply`メソッドは`name`から`CustomerID`文字列を作ります。`unapply`は逆に`name`を返します。 + `CustomerID("Sukyoung")`は、`CustomerID.apply("Sukyoung")`を短く書く構文です。 + `case CustomerID(name) => println(name)`では、unapplyメソッドを呼んでいます。 + +値を定義する文で、パターン中に新しい変数を使うことができるので、抽出子は変数を初期化するのに使えます。この場合unapplyメソッドが初期値を与えます。 + +```tut +val customer2ID = CustomerID("Nico") +val CustomerID(name) = customer2ID +println(name) // prints Nico +``` +これは `val name = CustomerID.unapply(customer2ID).get`.と同じです。 + +```tut +val CustomerID(name2) = "--asdfasdfasdf" +``` +もし一致しない場合`scala.MatchError`が投げられます。 + +```tut:fail +val CustomerID(name3) = "-asdfasdfasdf" +``` + +`unapply`の戻り値型は以下のように選ばれなければなりません。 + +* ただのテストであれば、`Boolean`を返します。例えば`case even()`。 +* T型のサブバリュー1つを返すのであれば、`Option[T]`を返します。 +* いくつかのサブバリュー`T1,...,Tn`を返したいのであれば、オプショナルタプル`Option[(T1,...,Tn)]`でグループ化します。 + +時々、抽出する値の数が確定せず、入力に応じて任意の数の値を返したいことがあります。 +この場合は、`Option[Seq[T]]`を返す`unapplySeq`メソッドを持つ抽出子を定義することができます。 +これらのパターンと同様の例として以下のものがあります。 +`case List(x, y, z) =>`を使って`List`を分解する例や`case r(name, remainingFields @ _*) =>`.のように正規表現`Regex`を使って`String`を分解する例です。 diff --git a/_ja/tour/for-comprehensions.md b/_ja/tour/for-comprehensions.md new file mode 100644 index 0000000000..89bce4d42a --- /dev/null +++ b/_ja/tour/for-comprehensions.md @@ -0,0 +1,77 @@ +--- +layout: tour +title: for内包表記 +language: ja + +discourse: true + +partof: scala-tour + +num: 17 +next-page: generic-classes +previous-page: extractor-objects + +redirect_from: "/tutorials/tour/for-comprehensions.html" +--- + +Scalaは*シーケンス内包表記*を表現するための軽量な記法を提供します。 +内含表記は`for (enumerators) yield e`という形をとります。`enumerators`はセミコロンで区切られたEnumeratorのリストを指します。 +1つの*enumerator*は新しい変数を導き出すジェネレータかフィルタのどちらかです。 +内包表記はenumeratorsが生成する束縛一つ一つについて本体`e`を評価し、これらの値のシーケンスを返します。 + +こちらは例です。 + +```tut +case class User(name: String, age: Int) + +val userBase = List(User("Travis", 28), + User("Kelly", 33), + User("Jennifer", 44), + User("Dennis", 23)) + +val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30)) + yield user.name // これをリストに追加する + +twentySomethings.foreach(name => println(name)) // prints Travis Dennis +``` +この`yield`文と一緒に使われている`for`ループは実際には`List`を生成します。 +`yield user.name`を返しているので、型は`List[String]`になります。 +`user <- userBase`はジェネレータであり、`if (user.age >=20 && user.age < 30)`は20代ではないユーザーをフィルターするガードです。 + +こちらは2つのジェネレータを使ったより複雑な例です。 +合計が与えられた値`v`と等しくなる、`0`から`n-1`の全てのペアを計算します。 + +```tut +def foo(n: Int, v: Int) = + for (i <- 0 until n; + j <- 0 until n if i + j == v) + yield (i, j) + +foo(10, 10) foreach { + case (i, j) => + println(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5) (6, 4) (7, 3) (8, 2) (9, 1) +} + +``` +この例では`n == 10`で`v == 10`です。最初のイテレーションでは`i == 0`かつ`j == 0`で、`i + j != v`となるので、何も生成されません。 +`i`が`1`にインクリメントされるまでに、`j`はあと9回インクリメントされます。`if`ガードがなければ、単純に以下の内容が表示されます。 + +``` + +(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 0) ... +``` +内包表記はリストだけのものではありません。 +操作 `withFilter`、`map`、`flatMap`を(適切な型で)サポートする全てのデータ型は、シーケンス内包表記で使うことができます。 + +内包表記の中では`yield`を省略することができます。その場合、内包表記は`Unit`を返します。 +これは副作用をもたらす必要があるときに役立ちます。 +こちらは先に出たプログラムと同等のものですが、`yield`を使っていません。 + +```tut +def foo(n: Int, v: Int) = + for (i <- 0 until n; + j <- 0 until n if i + j == v) + println(s"($i, $j)") + +foo(10, 10) +``` diff --git a/_ja/tour/generic-classes.md b/_ja/tour/generic-classes.md new file mode 100644 index 0000000000..2535e31695 --- /dev/null +++ b/_ja/tour/generic-classes.md @@ -0,0 +1,65 @@ +--- +layout: tour +title: ジェネリッククラス +language: ja + +discourse: true + +partof: scala-tour + +num: 18 +next-page: variances +previous-page: for-comprehensions +assumed-knowledge: classes unified-types + +redirect_from: "/tutorials/tour/generic-classes.html" +--- +ジェネリッククラスはパラメータとして型を1つ受け取るクラスです。それらはコレクションクラスで特に役立ちます。 + +## ジェネリッククラスの定義 +ジェネリッククラスは角カッコ`[]`の中にパラメータとして型を1つ受け取ります。 +型パラメータの識別子として文字`A`を使う習慣がありますが、任意のパラメータ名を使うことができます。 +```tut +class Stack[A] { + private var elements: List[A] = Nil + def push(x: A) { elements = x :: elements } + def peek: A = elements.head + def pop(): A = { + val currentTop = peek + elements = elements.tail + currentTop + } +} +``` +この`Stack`クラスの実装はパラメータとして任意の型`A`を受け取ります。 +これはメンバーのリスト`var elements: List[A] = Nil`が型`A`の要素のみを格納できることを意味します。 +手続き`def push`は型`A`のオブジェクトのみを受け取ります +(注: `elements = x :: elements`は、`x`を現在の`elements`の先頭に追加した新しいリストを`elements`に割り当て直します)。 + +## 使い方 + +ジェネリッククラスを使うには、角カッコの中に`A`の代わりに型を入れます。 +``` +val stack = new Stack[Int] +stack.push(1) +stack.push(2) +println(stack.pop) // prints 2 +println(stack.pop) // prints 1 +``` +インスタンス`stack`はIntのみを受け取ることができます。 +しかしながら、型がサブタイプを持つ場合、それらは以下のように渡すことができます。 +``` +class Fruit +class Apple extends Fruit +class Banana extends Fruit + +val stack = new Stack[Fruit] +val apple = new Apple +val banana = new Banana + +stack.push(apple) +stack.push(banana) +``` +クラス`Apple`と`Banana`は共に`Fruit`を継承しています。そのため`Fruit`のスタックには`apple`と`banana`のインスタンスを追加できます。 + +_注意: ジェネリック型のサブタイプは*非変(invariant)*です。つまり`Stack[Char]`型の文字スタックがあるとき、それを`Stack[Int]`型の整数スタックとして使うことはできません。文字スタックに整数を入れることはできるので、このことは変に思えるかもしれません。結論としては、`B = A`の場合に限り、`Stack[A]`は`Stack[B]`の唯一のサブタイプとなります。これでは制限が強いので、ジェネリック型のサブタイプの振る舞いをコントロールするために、Scalaは[型引数アノテーションの仕組み](variances.html)を提供します。_ diff --git a/_ja/tour/higher-order-functions.md b/_ja/tour/higher-order-functions.md new file mode 100644 index 0000000000..57714202e8 --- /dev/null +++ b/_ja/tour/higher-order-functions.md @@ -0,0 +1,121 @@ +--- +layout: tour +title: 高階関数 +language: ja + +discourse: true + +partof: scala-tour + +num: 8 +next-page: nested-functions +previous-page: mixin-class-composition + +redirect_from: "/tutorials/tour/higher-order-functions.html" +--- + +高階関数は他の関数をパラメーターとして受け取る、もしくは結果として関数を返します。 +このようなことができるのは、Scalaでは関数が第一級値 (first-classs value) だからです。 +用語が少し紛らわしいかもしれませんが、 +ここでは"高階関数"というフレーズを関数をパラメーターとして受け取る、または関数を返すメソッドと関数の両方に対して使います。 + +もっとも一般的な例の1つは、Scalaのコレクションで利用可能な高階関数`map`です。 +```tut +val salaries = Seq(20000, 70000, 40000) +val doubleSalary = (x: Int) => x * 2 +val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000) +``` +`doubleSalary`はInt`x`を1つだけ受け取り、`x * 2`を返す関数です。 +一般的に、アロー`=>`の左側のタプルは引数リストであり、右側の式の値が返されます。 +3行目で、給与のリストのそれぞれの値に`doubleSalary`が適用されます。 + +コードを減らすため、以下のように無名関数を作ることができ、引数として直接mapに渡すことができます +``` +val salaries = Seq(20000, 70000, 40000) +val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000) +``` +上記例では`x`をIntとして宣言していないことに注意してください。 +それはmap関数が期待する型を基にコンパイラーが型を推論できるからです。 +さらに言えば、慣用的には同じコードを以下のように書きます。 + +```tut +val salaries = Seq(20000, 70000, 40000) +val newSalaries = salaries.map(_ * 2) +``` +Scalaコンパイラはパラメーターの型を(Intが1つだけと)既に知っているため、関数の右側を提供するだけでよいです。 +唯一の注意点はパラメータ名の代わりに`_`を使う必要があるということです(先の例では`x`でした)。 + +## メソッドを関数に強制変換 +高階関数には引数としてとしてメソッドを渡すことも可能で、それはScalaコンパイラがメソッドを関数に強制変換するからです。 +``` +case class WeeklyWeatherForecast(temperatures: Seq[Double]) { + + private def convertCtoF(temp: Double) = temp * 1.8 + 32 + + def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF) // <-- convertCtoFメソッドが渡されます +} +``` +ここで、メソッド`convertCtoF`が`forecastInFahrenheit`に渡されています。 +これはコンパイラが`convertCtoF`を関数`x => convertCtoF(x)`(注意点:`x`はスコープ内でユニークであることが保証された名前になります)に変換することで実現します。 + +## 関数を受け取る関数 +高階関数を使う理由の1つは余分なコードを削減することです。 +たとえば、何通りかの係数で人の給料を上げるメソッドが欲しいとしましょう。 +高階関数を作らないなら、こんな感じになるかもしれません。 + +```tut +object SalaryRaiser { + + def smallPromotion(salaries: List[Double]): List[Double] = + salaries.map(salary => salary * 1.1) + + def greatPromotion(salaries: List[Double]): List[Double] = + salaries.map(salary => salary * math.log(salary)) + + def hugePromotion(salaries: List[Double]): List[Double] = + salaries.map(salary => salary * salary) +} +``` + +3つのメソッドはそれぞれ掛け算の係数のみ異なることに気をつけてください。 +簡潔にするため、以下のように繰り返されているコードを高階関数に抽出することができます。 + +```tut +object SalaryRaiser { + + private def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] = + salaries.map(promotionFunction) + + def smallPromotion(salaries: List[Double]): List[Double] = + promotion(salaries, salary => salary * 1.1) + + def bigPromotion(salaries: List[Double]): List[Double] = + promotion(salaries, salary => salary * math.log(salary)) + + def hugePromotion(salaries: List[Double]): List[Double] = + promotion(salaries, salary => salary * salary) +} +``` +新しいメソッド`promotion`はsalariesと`Double => Double`型の関数(すなわち、Doubleを受け取り、Doubleを返す関数)を受け取り、積を返します。 + +## 関数を返す関数 + +関数を生成したい場合がいくつかあります。 +こちらは関数を返すメソッドの例になります。 + +```tut +def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = { + val schema = if (ssl) "https://" else "http://" + (endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query" +} + +val domainName = "www.example.com" +def getURL = urlBuilder(ssl=true, domainName) +val endpoint = "users" +val query = "id=1" +val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String +``` + +urlBuilderの戻り値型`(String, String) => String`に注意してください。 +これは返される無名関数はStringを2つ受け取り、Stringを1つ返すことを意味します。 +このケースでは返される無名関数は`(endpoint: String, query: String) => s"https://www.example.com/$endpoint?$query"`です。 diff --git a/_ja/tour/implicit-conversions.md b/_ja/tour/implicit-conversions.md new file mode 100644 index 0000000000..386ed3c500 --- /dev/null +++ b/_ja/tour/implicit-conversions.md @@ -0,0 +1,62 @@ +--- +layout: tour +title: 暗黙の変換 +language: ja + +discourse: true + +partof: scala-tour + +num: 27 +next-page: polymorphic-methods +previous-page: implicit-parameters + +redirect_from: "/tutorials/tour/implicit-conversions.html" +--- + +型`S`から型`T`への暗黙の変換は`S => T`という型のimplicit値や、その型に一致するimplicitメソッドで定義されます。 + +暗黙の変換は2つの状況で適用されます。 + +* もし式`e`が型`S`であり、`S`は式の期待する型`T`に適合しない場合 +* 型`S`の`e`を使う表記`e.m`があって、セレクター`m`が`S`のメンバーではない場合 + +最初のケースでは、`e`を渡せて、戻り値の型が`T`に適合するような変換`c`を検索します。 +2つ目のケースでは、`e`を渡せて、戻り値が`m`というメンバーを持つような変換`c`を検索します。 + +implicitなメソッド`List[A] => Ordered[List[A]]`と`Int => Ordered[Int]`がスコープの中にあれば、`List[Int]`型の2つのリストにおける以下の処理は正当なものになります。 + +``` +List(1, 2, 3) <= List(4, 5) +``` +implicitなメソッド`Int => Ordered[Int]`は`scala.Predef.intWrapper`を通じて自動的に提供されます。implicitなメソッドの例`List[A] => Ordered[List[A]]`は以下にあります。 + +```tut +import scala.language.implicitConversions + +implicit def list2ordered[A](x: List[A]) + (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] = + new Ordered[List[A]] { + //replace with a more useful implementation + def compare(that: List[A]): Int = 1 + } +``` +暗黙にインポートされているオブジェクト`scala.Predef`は、頻繁に使われる型(例えば`scala.collection.immutable.Map`は`Map`と別名づけられます)とメソッド(例えば`assert`)といくつかの暗黙の型変換を宣言しています。 + +例えば、`java.lang.Integer`を受け取るようなJavaのメソッドを呼び出す時、自由に`scala.Int`を代わりに渡すことができます。それはPredefオブジェクトが以下の暗黙の変換をを含んでいるからです。 + +```tut +import scala.language.implicitConversions + +implicit def int2Integer(x: Int) = + java.lang.Integer.valueOf(x) +``` + +暗黙の変換は見境なく使われると落とし穴になり得るため、暗黙の変換の定義をコンパイルしている時にコンパイラは警告を出します。 + +警告をオフにするには、次のいずれかの措置を講じてください。 + +* 暗黙の変換定義のスコープに`scala.language.implicitConversions`をインポートする。 +* コンパイラを`-language:implicitConversions`をつけて起動する + +コンパイラにより変換が適用された時、警告は出ません。 diff --git a/_ja/tour/implicit-parameters.md b/_ja/tour/implicit-parameters.md new file mode 100644 index 0000000000..38067f9e27 --- /dev/null +++ b/_ja/tour/implicit-parameters.md @@ -0,0 +1,75 @@ +--- +layout: tour +title: 暗黙のパラメータ +language: ja + +discourse: true + +partof: scala-tour + +num: 26 +next-page: implicit-conversions +previous-page: self-types + +redirect_from: "/tutorials/tour/implicit-parameters.html" +--- + +メソッドは _暗黙の_ パラメータのリストを持つことができ、パラメータリストの先頭には _implicit_ キーワードで印をつけます。 +もしそのパラメータリストの中のパラメータがいつものように渡らなければ、Scalaは正しい型の暗黙値を受け取ることができるかを確認し、可能であればそれを自動的に渡します。 + +Scalaがこれらのパラメータを探す場所は2つのカテゴリに分かれます。 + +* Scalaはまず最初に暗黙のパラメータブロックを持つメソッドが呼び出されている箇所で、直接(プレフィックスなしに)アクセスできる暗黙の定義と暗黙のパラメータを探します。 +* 次に、候補となる型に関連づけられた全てのコンパニオンオブジェクトの中でimplicitと宣言されているメンバーを探します。 + +Scalaがimplicitをどこから見つけるかについてのより詳しいガイドは[FAQ](//docs.scala-lang.org/tutorials/FAQ/finding-implicits.html)で見ることができます。 + +以下の例では、モノイドの`add`と`unit`の演算を使い、要素のリストの合計を計算するメソッド`sum`を定義しています。 +implicitの値をトップレベルには置けないことに注意してください。 + +```tut +abstract class Monoid[A] { + def add(x: A, y: A): A + def unit: A +} + +object ImplicitTest { + implicit val stringMonoid: Monoid[String] = new Monoid[String] { + def add(x: String, y: String): String = x concat y + def unit: String = "" + } + + implicit val intMonoid: Monoid[Int] = new Monoid[Int] { + def add(x: Int, y: Int): Int = x + y + def unit: Int = 0 + } + + def sum[A](xs: List[A])(implicit m: Monoid[A]): A = + if (xs.isEmpty) m.unit + else m.add(xs.head, sum(xs.tail)) + + def main(args: Array[String]): Unit = { + println(sum(List(1, 2, 3))) // intMonoidを暗に使用 + println(sum(List("a", "b", "c"))) // stringMonoidを暗に使用 + } +} +``` +`Monoid`はここでは`add`と呼ばれる処理を定義します。この処理は`A`のペアを結合して、別の`A`を返します。また、(特定の)`A`を作ることができる`unit`と呼ばれる処理も定義します。 + +暗黙のパラメータがどのように働くかを見るため、まずは文字列と整数のためにそれぞれモノイド`stringMonoid`と`intMonoid`を定義します。`implicit`キーワードは対応するオブジェクトが暗黙に使われうることを指し示します。 + +メソッド`sum`は`List[A]`を受け取り、`A`を返します。このメソッドは初期値`A`を`unit`から受け取り、リスト中の`A`を順番に`add`メソッドで結合します。ここでパラメータ`m`をimplicitにしているのは、そのメソッドを呼び出すとき、Scalaが暗黙のパラメータ`m`として暗黙の`Monoid[A]`を見つけることができるなら、私達は`xs`パラメータを提供するだけで良いということです。 + +`main`メソッドでは`sum`を2回呼んでいて、`xs`パラメータだけを渡しています。するとScalaは先に言及したスコープの中でimplicitを探します。最初の`sum`の呼び出しは`xs`として`List[Int]`を渡します。それは `A`が`Int`であることを意味します。暗黙のパラメータリスト`m`が省略されているので、Scalaは暗黙の`Monoid[Int]`を探します。最初の探索ルールはこうでした。 + +> Scalaはまず最初に暗黙のパラメータブロックを持つメソッドが呼び出されている箇所で、直接(プレフィックスなしに)アクセスできる暗黙の定義と暗黙のパラメータを探します。 + +`intMonoid`は`main`の中で直接アクセスできる暗黙の定義です。型も一致しているので、`sum`メソッドに自動的に渡されます。 + +`sum`の2回目の呼び出しは`List[String]`を渡します。それは`A`は`String`であることを意味します。暗黙の値の探索は`Int`の時と同様に動きますが、今回は `stringMonoid`を見つけ、`m`として自動的に渡します。 + +そのプログラムは以下を出力します。 +``` +6 +abc +``` diff --git a/_ja/tour/inner-classes.md b/_ja/tour/inner-classes.md new file mode 100644 index 0000000000..4bc373d8c8 --- /dev/null +++ b/_ja/tour/inner-classes.md @@ -0,0 +1,91 @@ +--- +layout: tour +title: 内部クラス +language: ja + +discourse: true + +partof: scala-tour + +num: 22 +next-page: abstract-type-members +previous-page: lower-type-bounds + +redirect_from: "/tutorials/tour/inner-classes.html" +--- + +Scalaではクラスが他のクラスをメンバーとして保持することが可能です。 +Javaのような、内部クラスが外側のクラスのメンバーとなる言語とは対照的に、Scalaでは、内部クラスは外側のオブジェクトに束縛されます。 +どのノードがどのグラフに属しているのかを私達が混同しないように、コンパイラがコンパイル時に防いでほしいのです。 +パス依存型はその解決策の1つです。 + +その違いを示すために、グラフデータ型の実装をさっと書きます。 + +```tut +class Graph { + class Node { + var connectedNodes: List[Node] = Nil + def connectTo(node: Node) { + if (connectedNodes.find(node.equals).isEmpty) { + connectedNodes = node :: connectedNodes + } + } + } + var nodes: List[Node] = Nil + def newNode: Node = { + val res = new Node + nodes = res :: nodes + res + } +} +``` +このプログラムはグラフをノードのリスト(`List[Node]`)で表現しています。いずれのノードも接続している他のノードへのリスト(`connectedNodes`)を保持します。`class Node`は `class Graph`の中にネストしているので、 _パス依存型_ です。 +そのため`connectedNodes`の中にある全てのノードは同じ`Graph`インスタンスから`newNode`を使用して作る必要があります。 + +```tut +val graph1: Graph = new Graph +val node1: graph1.Node = graph1.newNode +val node2: graph1.Node = graph1.newNode +val node3: graph1.Node = graph1.newNode +node1.connectTo(node2) +node3.connectTo(node1) +``` +わかりやすくするため`node1`、`node2`、`node3`の型を`graph1.Node`と明示的に宣言しましたが、なくてもコンパイラは推論できます。 +これは`new Node`を呼んでいる`graph1.newNode`を呼び出す時、メソッドが`Node`のインスタンス`graph1`を使用しているからです。 + +2つのグラフがあるとき、Scalaの型システムは1つのグラフの中で定義されたノードと別のグラフで定義されたノードを混ぜることを許しません。 +それは別のグラフのノードは別の型を持つからです。 +こちらは不正なプログラムです。 + +``` +val graph1: Graph = new Graph +val node1: graph1.Node = graph1.newNode +val node2: graph1.Node = graph1.newNode +node1.connectTo(node2) // legal +val graph2: Graph = new Graph +val node3: graph2.Node = graph2.newNode +node1.connectTo(node3) // illegal! +``` +型`graph1.Node`は`graph2.Node`とは異なります。Javaであれば先のプログラム例の最後の行は正しいでしょう。 +2つのグラフのノードに対して、Javaは同じ型`Graph.Node`を指定します。つまりクラス`Graph`は`Node`の接頭辞です。 +Scalaではそのような型も同様に表現することができ、`Graph#Node`と書きます。 +もし他のグラフのノードに接続できるようにしたければ、以下の方法で最初のグラフ実装の定義を変える必要があります。 + +```tut +class Graph { + class Node { + var connectedNodes: List[Graph#Node] = Nil + def connectTo(node: Graph#Node) { + if (connectedNodes.find(node.equals).isEmpty) { + connectedNodes = node :: connectedNodes + } + } + } + var nodes: List[Node] = Nil + def newNode: Node = { + val res = new Node + nodes = res :: nodes + res + } +} +``` diff --git a/_ja/tour/lower-type-bounds.md b/_ja/tour/lower-type-bounds.md new file mode 100644 index 0000000000..d461e31e5d --- /dev/null +++ b/_ja/tour/lower-type-bounds.md @@ -0,0 +1,76 @@ +--- +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 + +redirect_from: "/tutorials/tour/lower-type-bounds.html" +--- + + [上限型境界](upper-type-bounds.html) は型を別の型のサブタイプに制限しますが、*下限型境界*は型が別の型のスーパータイプであることを宣言します。表現`B >: A`はパラメータ`B`または抽象型`B`が型`A`のスーパータイプであることを表します。ほとんどのケースで`A`はそのクラスの型パラメータであり、`B`はメソッドの型パラメータになります。 + +以下はこれが役立つ場合の例です。 + +```tut:fail +trait Node[+B] { + def prepend(elem: B): Node[B] +} + +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 Nil[+B]() extends Node[B] { + def prepend(elem: B): ListNode[B] = ListNode(elem, this) +} +``` + +このプログラムは片方向リストを実装します。`Nil`は空の要素(すなわち空のリスト)を意味します。 +`class ListNode`は型`B` (`head`)の要素と、リストの残りの部分(`tail`)への参照を持つノードです。 +`class Node`とそのサブタイプは、`+B`とあるので、共変です。 + +しかしながら、このプログラムはコンパイル _されません_。`prepend`のパラメータ`elem`が、宣言時に*共* 変と宣言した型`B`になっているからです。 +なぜ通らないかというと、関数はそれらの型パラメータに対して*反*変であり、それらの結果型に対して*共*変だからです。 + +これを解決するためには、`prepend`のパラメータ`elem`の型の変位指定を逆転させる必要があります。 +これを実現するには、下限型境界として`B`を持つ新しい型パラメータ`U`を導入します。 + +```tut +trait Node[+B] { + def prepend[U >: B](elem: U): Node[U] +} + +case class ListNode[+B](h: B, t: 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) +} +``` + +すると、以下のようなことができます。 +```tut +trait Bird +case class AfricanSwallow() extends Bird +case class EuropeanSwallow() extends Bird + + +val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil()) +val birdList: Node[Bird] = africanSwallowList +birdList.prepend(new EuropeanSwallow) +``` +`Node[Bird]`は`africanSwallowList`をアサインできますが、その後`EuropeanSwallow`を受け入れられます。 + diff --git a/_ja/tour/mixin-class-composition.md b/_ja/tour/mixin-class-composition.md new file mode 100644 index 0000000000..9ec9fd65f4 --- /dev/null +++ b/_ja/tour/mixin-class-composition.md @@ -0,0 +1,84 @@ +--- +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 + +redirect_from: "/tutorials/tour/mixin-class-composition.html" +--- +ミックスインはクラスを構成するのに使われるトレイトです。 + +```tut +abstract class A { + val message: String +} +class B extends A { + val message = "I'm an instance of class B" +} +trait C extends A { + def loudMessage = message.toUpperCase() +} +class D extends B with C + +val d = new D +println(d.message) // I'm an instance of class B +println(d.loudMessage) // I'M AN INSTANCE OF CLASS B +``` +クラス`D`は スーパークラスを`B` とし、 ミックスイン`C`を持ちます。 +クラスは1つだけしかスーパークラスを持つことができませんが、ミックスインは複数持つことができます(キーワードはそれぞれ`extends`と`with`を使います)。 +ミックスインとスーパークラスは同じスーパータイプを持つことができます。 + +それでは抽象クラスから始まる興味深い例を見てみましょう。 + +```tut +abstract class AbsIterator { + type T + def hasNext: Boolean + def next(): T +} +``` +クラスは抽象型`T`と標準的なイテレーターのメソッドを持ちます。 +次に、(全ての抽象メンバー`T`, `hasNext`, `next`が実装を持つ)具象クラスを実装します。 + +```tut +class StringIterator(s: String) extends AbsIterator { + type T = Char + private var i = 0 + def hasNext = i < s.length + def next() = { + val ch = s charAt i + i += 1 + ch + } +} +``` +`StringIterator`は`String`を受け取り、そのStringを反復処理するために使われます。 +(例:Stringに特定の文字が含まれているかを確認するために) + +それでは`AbsIterator`を継承したトレイトも作ってみましょう。 + +```tut +trait RichIterator extends AbsIterator { + def foreach(f: T => Unit): Unit = while (hasNext) f(next()) +} +``` +このトレイトは(`while (hasNext)`で)要素がある限り、与えられた関数 `f: T => Unit`を次の要素(`next()`)に対し連続して呼び出す`foreach`メソッドを実装しています。 +`RichIterator`はトレイトなので、`RichIterator`はAbsIteratorの抽象メンバーを実装する必要がありません。 + +`StringIterator`と`RichIterator`の機能を1つのクラスに組み合わせてみましょう。 +```tut +class RichStringIter extends StringIterator("Scala") with RichIterator +val richStringIter = new RichStringIter +richStringIter foreach println +``` +新しいクラス`RichStringIter`は`StringIterator`をスーパークラスとし、`RichIterator`をミックスインとしています。 + +単一継承ではこのレベルの柔軟性を達成することはできないでしょう。 diff --git a/_ja/tour/multiple-parameter-lists.md b/_ja/tour/multiple-parameter-lists.md new file mode 100644 index 0000000000..a35bccf615 --- /dev/null +++ b/_ja/tour/multiple-parameter-lists.md @@ -0,0 +1,79 @@ +--- +layout: tour +title: 複数パラメータリスト(カリー化) +language: ja + +discourse: true + +partof: scala-tour + +num: 10 +next-page: case-classes +previous-page: nested-functions + +redirect_from: "/tutorials/tour/multiple-parameter-lists.html" +--- + +メソッドは複数のパラメータリストを持てます。 + +# 例 + +こちらはScalaのコレクションAPIの `TraversableOnce`トレイトで定義されている実例です。 + +``` +def foldLeft[B](z: B)(op: (B, A) => B): B +``` +`foldLeft`は、2つのパラメータを取る関数`op`を、初期値`z`とこのコレクションの全要素に対して左から右に適用していきます。 +以下はその使い方の例です。 + +初期値0から始まり、`foldLeft`はここではリスト内の各要素とその一つ前の累積値に関数`(m, n) => m + n`を適用します。 + +{% scalafiddle %} +```tut +val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +val res = numbers.foldLeft(0)((m, n) => m + n) +println(res) // 55 +``` +{% endscalafiddle %} + +### ユースケース +推奨される複数パラメータリストのユースケースは次の通りです。 + +#### パラメータに関数を一つ渡す場合 +パラメータに関数を一つだけ渡すのであれば、上記の`foldLeft`のケースでの`op`のように、複数パラメータリストを利用して簡潔な構文でメソッドに無名関数を渡すことができます。 +複数パラメータリストがない場合、このコードは以下のようになります。 + + +``` +numbers.foldLeft(0, (m: Int, n: Int) => m + n) +``` + +複数パラメータリストを使うことで、Scalaの型インターフェースの利点を享受でき、以下のようにコードをより簡潔にすることができるのです。 + +``` +numbers.foldLeft(0)(_ + _) +``` +単一のパラメータリストではScalaコンパイラが関数のパラメータを型推論できないので、このようなことはできません。 + +#### 暗黙のパラメータ +特定のパラメータだけを`implicit`として指定するには、`implicit`のパラメーターリストに入れなければなりません。 +こちらが例です。 + +``` +def execute(arg: Int)(implicit ec: scala.concurrent.ExecutionContext) = ??? +``` + +#### 部分適用 + +メソッドが少ない数のパラメータリストで呼び出された時、不足しているパラメータリストを引数として受け取る関数が生成されます。 +これは一般的に[部分適用](https://en.wikipedia.org/wiki/Partial_application)として知られています。 + +例えば +```tut +val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +val numberFunc = numbers.foldLeft(List[Int]()) _ +val squares = numberFunc((xs, x) => xs :+ x*x) +print(squares) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) +val cubes = numberFunc((xs, x) => xs :+ x*x*x) +print(cubes) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000) +``` diff --git a/_ja/tour/named-arguments.md b/_ja/tour/named-arguments.md new file mode 100644 index 0000000000..b7f0ca82a2 --- /dev/null +++ b/_ja/tour/named-arguments.md @@ -0,0 +1,36 @@ +--- +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 + +redirect_from: "/tutorials/tour/named-arguments.html" +--- + +メソッドを呼ぶ時、以下のように引数にパラメータ名でラベル付が可能です。 + +```tut +def printName(first: String, last: String): Unit = { + println(first + " " + last) +} + +printName("John", "Smith") // Prints "John Smith" +printName(first = "John", last = "Smith") // Prints "John Smith" +printName(last = "Smith", first = "John") // Prints "John Smith" +``` + +名前付き引数の順序はどのように並び替えられるかに気をつけましょう。ただし、名前つき引数と名前つきでない引数がある場合は、名前つきでない引数は引数リストの最初に置かれ、かつメソッドシグネチャのパラメーター順でなければなりません。 + +```tut:fail +printName(last = "Smith", "john") // error: positional after named argument +``` + +名前付き引数はJavaメソッドを呼び出す時には使えません。 diff --git a/_ja/tour/nested-functions.md b/_ja/tour/nested-functions.md new file mode 100644 index 0000000000..05a57a2fae --- /dev/null +++ b/_ja/tour/nested-functions.md @@ -0,0 +1,40 @@ +--- +layout: tour +title: ネストしたメソッド +language: ja + +discourse: true + +partof: scala-tour + +num: 9 +next-page: multiple-parameter-lists +previous-page: higher-order-functions + +redirect_from: "/tutorials/tour/nested-functions.html" +--- + +Scalaではメソッドの定義をネストする(_訳注:入れ子にする_)ことができます。 +以下のコードは与えられた数値の階乗を計算するための`factorial`メソッドを提供します。 + +{% scalafiddle %} +```tut + def factorial(x: Int): Int = { + def fact(x: Int, accumulator: Int): Int = { + if (x <= 1) accumulator + else fact(x - 1, x * accumulator) + } + fact(x, 1) + } + + println("Factorial of 2: " + factorial(2)) + println("Factorial of 3: " + factorial(3)) +``` +{% endscalafiddle %} + +このプログラムの出力は以下の通りです。 + +``` +Factorial of 2: 2 +Factorial of 3: 6 +``` diff --git a/_ja/tour/operators.md b/_ja/tour/operators.md new file mode 100644 index 0000000000..b61b229558 --- /dev/null +++ b/_ja/tour/operators.md @@ -0,0 +1,88 @@ +--- +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 + +redirect_from: "/tutorials/tour/operators.html" +--- +Scalaでは演算子はメソッドです。パラメータを1つだけ持つメソッドであれば*中置演算子*として使えます。例えば、`+`はドット記法で呼び出せます。 + +``` +10.+(1) +``` + +しかしながら、中置演算子の方が読みやすいです。 + +``` +10 + 1 +``` + +## 演算子の定義方法と使い方 + +有効な識別子であれば演算子として使用できます。これは `add`のような名前も`+`のような記号も含みます。 +```tut +case class Vec(val x: Double, val y: Double) { + def +(that: Vec) = new Vec(this.x + that.x, this.y + that.y) +} + +val vector1 = Vec(1.0, 1.0) +val vector2 = Vec(2.0, 2.0) + +val vector3 = vector1 + vector2 +vector3.x // 3.0 +vector3.y // 3.0 +``` +クラスVecはメソッド`+`を持ち、 `vector1`と`vector2`を足しわせるのに使います。丸括弧を用いて、複雑な式を読みやすい構文で作ることができます。 +こちらはクラス`MyBool`の定義です。クラス`MyBool`はメソッド`and`と`or`を含みます。 + +```tut +case class MyBool(x: Boolean) { + def and(that: MyBool): MyBool = if (x) that else this + def or(that: MyBool): MyBool = if (x) this else that + def negate: MyBool = MyBool(!x) +} +``` + +この時、`and`と`or`を中置演算子として使えます。 + +```tut +def not(x: MyBool) = x.negate +def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y) +``` + +これにより`xor`の定義がより読みやすくなります。 + +## 優先順位 + +式が複数の演算子を使う時、それらの演算子は最初の文字の(以下に挙げる)優先度に基づき評価されます。 +``` +(以下に表示されていない記号) +* / % ++ - +: += ! +< > +& +^ +| +(全ての文字) +``` +これはあなたが定義した関数にも適用できます。 +たとえば、以下の式 +``` +a + b ^? c ?^ d less a ==> b | c +``` +は以下と同じ意味です。 +``` +((a + b) ^? (c ?^ d)) less ((a ==> b) | c) +``` +`?^`は最も高い優先順位を持ちます。`?^`は`?`から始まるからです。`+`は二番目に高い優先順位を持ち、その後に`==>`、 `^?`、 `|`、 そして`less`が続きます。 diff --git a/_ja/tour/package-objects.md b/_ja/tour/package-objects.md new file mode 100644 index 0000000000..fd7eaced57 --- /dev/null +++ b/_ja/tour/package-objects.md @@ -0,0 +1,73 @@ +--- +layout: tour +title: パッケージオブジェクト +language: ja + +discourse: true + +partof: scala-tour + +num: 36 +previous-page: packages-and-imports +--- + +# パッケージオブジェクト + +Scalaはパッケージ全体を通して共有される便利なコンテナとしてパッケージオブジェクトを提供します。 + +パッケージオブジェクトは、変数やメソッド定義だけでなく、任意の定義を含むことができます。 +例えば、それらはパッケージ全体で使われる型エイリアスと暗黙の変換を保有するためによく使われます。 +パッケージオブジェクトはScalaクラスやトレイトを継承することもできます。 + +慣習として、パッケージオブジェクトのソースコードは通常`package.scala`という名のソースファイルに設置されます。 + +1つのパッケージはパッケージオブジェクトを1つ持てます。パッケージオブジェクト内の全ての定義はパッケージ自体のメンバーと見なされます。 + +以下の例を見てみましょう。まず1つのクラス`Fruit`と3つの`Fruit`オブジェクトがパッケージ`gardening.fruits`にあるとします。 + +``` +// ファイル gardening/fruits/Fruit.scala の中 +package gardening.fruits + +case class Fruit(name: String, color: String) +object Apple extends Fruit("Apple", "green") +object Plum extends Fruit("Plum", "blue") +object Banana extends Fruit("Banana", "yellow") +``` + +ここで、変数`planted`とメソッド`showFruit`を直接パッケージ`gardening.fruits`内に置きたいとします。 +こちらがその方法になります。 + +``` +// ファイル gardening/fruits/package.scala の中 +package gardening +package object fruits { + val planted = List(Apple, Plum, Banana) + def showFruit(fruit: Fruit): Unit = { + println(s"${fruit.name}s are ${fruit.color}") + } +} +``` + +利用側がどのようになるかの例としては、以下のオブジェクト`PrintPlanted`は、ワイルドカードインポートでクラス`Fruit`と全く同様に`planted`と`showFruit`をインポートしています。 + +``` +// ファイル PrintPlanted.scala の中 +import gardening.fruits._ +object PrintPlanted { + def main(args: Array[String]): Unit = { + for (fruit <- fruits.planted) { + showFruit(fruit) + } + } +} +``` + +パッケージオブジェクトは他のオブジェクトのように、継承を利用して構成できます。例えば、一つのパッケージオブジェクトが2つのトレイトをミックスインしている例を示します。 + +``` +package object fruits extends FruitAliases with FruitHelpers { + // ヘルパーと変数がここに続きます。 +} +``` +メソッドオーバーライドはパッケージオブジェクト内では動作しないので気をつけましょう。 diff --git a/_ja/tour/packages-and-imports.md b/_ja/tour/packages-and-imports.md new file mode 100644 index 0000000000..dd2e42f844 --- /dev/null +++ b/_ja/tour/packages-and-imports.md @@ -0,0 +1,87 @@ +--- +layout: tour +title: パッケージとインポート +language: ja + +discourse: true + +partof: scala-tour + +num: 35 +previous-page: named-arguments +next-page: package-objects +--- + +# パッケージとインポート +Scalaは名前空間を作るためにパッケージを使います。名前空間によりプログラムをモジュール化できます。 + +## パッケージの作成 +Scalaファイルの先頭で1つ以上のパッケージ名を宣言することでパッケージは作られます。 + +``` +package users + +class User +``` +パッケージとScalaファイルが含まれるディレクトリは同じ名前をつける習慣があります。しかし、Scalaはファイルのレイアウトには関知しません。`package users`を含むsbtプロジェクトのディレクトリ構成はこのようになるかもしれません。 + +``` +- ExampleProject + - build.sbt + - project + - src + - main + - scala + - users + User.scala + UserProfile.scala + UserPreferences.scala + - test +``` +`users`ディレクトリがどのように`scala`ディレクトリの中にあり、複数のScalaファイルがどのようにパッケージ内にあるのかに注意してください。パッケージ内のScalaファイルは同じパッケージ宣言を持ちます。パッケージ宣言の他の方法は波括弧を使い以下のようにします。 + +``` +package users { + package administrators { + class NormalUser + } + package normalusers { + class NormalUser + } +} +``` +見ての通り、この方法はパッケージのネストができ、スコープとカプセル化をより強くコントロールできます。 + +パッケージ名は全て小文字で書き、もしコードがwebサイトを持つ組織によって開発される場合、慣習として次のフォーマットであるべきです。`<トップレベルドメイン>.<ドメイン名>.<プロジェクト名>`。例えば、Googleが`SelfDrivingCar`と呼ばれるプロジェクトを持っている場合、パッケージ名はこんな風になるでしょう。 +``` +package com.google.selfdrivingcar.camera + +class Lens +``` +これは次のディレクトリ構成に対応します。`SelfDrivingCar/src/main/scala/com/google/selfdrivingcar/camera/Lens.scala` + +## インポート +`import`句は他パッケージのメンバー(クラス、トレイト、関数など)にアクセスするためのものです。同じパッケージのメンバーにアクセスするには`import`句は必要ありません。import句は以下のどれでも使えます。 +``` +import users._ // usersパッケージから全てをインポートする +import users.User // クラスUserをインポートする +import users.{User, UserPreferences} // 選択されたメンバーのみインポートする +import users.{UserPreferences => UPrefs} // インポートし利便性のために名前を変更する +``` +ScalaのJavaと異なる点の1つはインポートがどこでも使える点です。 + +```tut +def sqrtplus1(x: Int) = { + import scala.math.sqrt + sqrt(x) + 1.0 +} +``` +名前競合があり、プロジェクトのルートから何かをインポートする必要がある時、パッケージ名の前に`_root_`をつけます。 +``` +package accounts + +import _root_.users._ +``` + + +注:`scala`と`java.lang` パッケージは`object Predef`と同じように標準でインポートされています。 diff --git a/_ja/tour/pattern-matching.md b/_ja/tour/pattern-matching.md new file mode 100644 index 0000000000..d44d13e41b --- /dev/null +++ b/_ja/tour/pattern-matching.md @@ -0,0 +1,166 @@ +--- +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 + +redirect_from: "/tutorials/tour/pattern-matching.html" +--- + +パターンマッチングは値をパターンに照合するための仕組みです。 +マッチに成功すれば、一つの値をその構成要素のパーツに分解することもできます。 +Javaの`switch`文の強化バージョンで、if/else文の連続の代わりとして同様に使うことができます。 + +## 構文 + +マッチ式は値、キーワード`match`と少なくとも1つの`case`句を持ちます。 +```tut +import scala.util.Random + +val x: Int = Random.nextInt(10) + +x match { + case 0 => "zero" + case 1 => "one" + case 2 => "two" + case _ => "other" +} +``` +上記の`val x`は0から10の間のランダムな整数です。`x`は`match`演算子の左オペランドで、右側は4つのケースを持つ式です。 +最後のケース`_`は その他の取りうる整数値のための"全てを捕捉する"ケースです。 +ケースは*オルタナティブ*とも呼ばれます。 + +マッチ式は値を持ちます。 +```tut +def matchTest(x: Int): String = x match { + case 1 => "one" + case 2 => "two" + case _ => "other" +} +matchTest(3) // other +matchTest(1) // one +``` +全てのケースでStringを返しているので、このマッチ式はString型を持ちます。 +そのため関数`matchTest`はStringを返します。 + +## ケースクラスでのマッチング + +ケースクラスはパターンマッチングで特に役立ちます。 + +```tut +abstract class Notification + +case class Email(sender: String, title: String, body: String) extends Notification + +case class SMS(caller: String, message: String) extends Notification + +case class VoiceRecording(contactName: String, link: String) extends Notification + +``` +`Notification`は抽象スーパークラスで、ケースクラスの実装`Email`、 `SMS`、 `VoiceRecording`3つの具象クラスがあります。 +今、これらのケースクラスでパターンマッチングをすることができます。 + +``` +def showNotification(notification: Notification): String = { + notification match { + case Email(sender, title, _) => + s"You got an email from $sender with title: $title" + case SMS(number, message) => + s"You got an SMS from $number! Message: $message" + case VoiceRecording(name, link) => + s"you received a Voice Recording from $name! Click the link to hear it: $link" + } +} +val someSms = SMS("12345", "Are you there?") +val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123") + +println(showNotification(someSms)) // You got an SMS from 12345! Message: Are you there? が出力されます。 + +println(showNotification(someVoiceRecording)) // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123 が出力されます。 +``` +関数`showNotification`は抽象型`Notification`をパラメータとして受け取り、`Notification`の型でマッチします(すなわち`Email`、`SMS`、または `VoiceRecording`のいずれであるかを解決します)。 +`case Email(sender, title, _)` ではフィールド`sender`と`title`が戻り値として使われますが、`_`を使うことでフィールド`body`は無視されます。 + +## パターンガード +パターンガードはケースをより具体的にするために使われる簡単な真偽表現です。 +`if `をパターンの後ろに追加するだけです。 + +``` + +def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = { + notification match { + case Email(sender, _, _) if importantPeopleInfo.contains(sender) => + "You got an email from special someone!" + case SMS(number, _) if importantPeopleInfo.contains(number) => + "You got an SMS from special someone!" + case other => + showNotification(other) // 特別なものではなく、オリジナルのshowNotification関数に委譲します。 + } +} + +val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com") + +val someSms = SMS("867-5309", "Are you there?") +val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123") +val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!") +val importantSms = SMS("867-5309", "I'm here! Where are you?") + +println(showImportantNotification(someSms, importantPeopleInfo)) +println(showImportantNotification(someVoiceRecording, importantPeopleInfo)) +println(showImportantNotification(importantEmail, importantPeopleInfo)) +println(showImportantNotification(importantSms, importantPeopleInfo)) +``` + +`case Email(sender, _, _) if importantPeopleInfo.contains(sender)`では、パターンは`sender`が重要な人のリストに存在して初めてマッチします。 + +## 型のみでのマッチング + +以下のように型のみでマッチすることができます。 +```tut +abstract class Device +case class Phone(model: String) extends Device{ + def screenOff = "Turning screen off" +} +case class Computer(model: String) extends Device { + def screenSaverOn = "Turning screen saver on..." +} + +def goIdle(device: Device) = device match { + case p: Phone => p.screenOff + case c: Computer => c.screenSaverOn +} +``` +`def goIdle`は`Device`の型によって異なる振る舞いをします。 +これはケースがそのパターンのメソッドを呼び出す必要がある時に役立ちます。 +ケースの識別子には型の最初の一文字(この場合に`p`と`c`)を利用する慣習があります。 + +## シールドクラス +トレイトとクラスに`sealed`をつけると、全てのサブタイプは同一ファイル内で宣言されなければならないという意味になります。 +これは全てのサブタイプが既知であることを保証します。 + +```tut +sealed abstract class Furniture +case class Couch() extends Furniture +case class Chair() extends Furniture + +def findPlaceToSit(piece: Furniture): String = piece match { + case a: Couch => "Lie on the couch" + case b: Chair => "Sit on the chair" +} +``` +これは"全てに対応する"ケースを必要としなくて済むので、パターンマッチングで役立ちます。 + +## 注意 +Scalaのパターンマッチング文は[ケースクラス](case-classes.html)で表現される代数型のマッチングに最も役立ちます。 + + +Scalaでは[抽出子オブジェクト](extractor-objects.html)の`unapply`メソッドを使うと、ケースクラスのパターンを独自に定義することもできます。 diff --git a/_ja/tour/polymorphic-methods.md b/_ja/tour/polymorphic-methods.md new file mode 100644 index 0000000000..0770657246 --- /dev/null +++ b/_ja/tour/polymorphic-methods.md @@ -0,0 +1,39 @@ +--- +layout: tour +title: ポリモーフィックメソッド +language: ja + +discourse: true + +partof: scala-tour + +num: 28 + +next-page: type-inference +previous-page: implicit-conversions +prerequisite-knowledge: unified-types + +redirect_from: "/tutorials/tour/polymorphic-methods.html" +--- + +Scalaのメソッドは値と同様に型によってパラメータ化することができます。構文はジェネリッククラスの構文と似ています。 +値パラメータは丸括弧で囲まれるのに対して、型パラメータは角カッコで囲まれます。 + +こちらが例です。 + +```tut +def listOfDuplicates[A](x: A, length: Int): List[A] = { + if (length < 1) + Nil + else + x :: listOfDuplicates(x, length - 1) +} +println(listOfDuplicates[Int](3, 4)) // List(3, 3, 3, 3) +println(listOfDuplicates("La", 8)) // List(La, La, La, La, La, La, La, La) +``` + +メソッド`listOfDuplicates`は型パラメータ`A`と値パラメータ`x`と`length`を受け取ります。値`x`の型は`A`です。もし`length < 1`なら空のリストを返します。それ以外の場合は`x`を再帰呼び出しで返された複写リストの先頭に追加します。(`::`の意味は、左辺の要素を右辺のリストの先頭に追加することです。) + +最初の呼び出し例では、`[Int]`と書いて明示的に型引数を渡しています。そのため最初の引数は`Int`でなければならず、戻される型は`List[Int]`となります。 + +2つ目の呼び出し例では必ずしも明示的に型パラメータを渡す必要がないことを示しています。コンパイラは文脈または値引数の型に基づき、型パラメータを推論できることが多いです。この例では`"La"`が`String`なので、コンパイラは`A`が`String`に違いないことが分かります。 diff --git a/_ja/tour/regular-expression-patterns.md b/_ja/tour/regular-expression-patterns.md new file mode 100644 index 0000000000..21068d1de1 --- /dev/null +++ b/_ja/tour/regular-expression-patterns.md @@ -0,0 +1,63 @@ +--- +layout: tour +title: 正規表現パターン +language: ja + +discourse: true + +partof: scala-tour + +num: 15 + +next-page: extractor-objects +previous-page: singleton-objects + +redirect_from: "/tutorials/tour/regular-expression-patterns.html" +--- +正規表現はデータの中からパターン(またはその欠如)を探すために使うことができる文字列です。 +どんな文字列も`.r`メソッドを使うことで、正規表現に変換できます。 + +```tut +import scala.util.matching.Regex + +val numberPattern: Regex = "[0-9]".r + +numberPattern.findFirstMatchIn("awesomepassword") match { + case Some(_) => println("Password OK") + case None => println("Password must contain a number") +} +``` +上記の例では、`numberPattern`は`Regex`(正規表現)型で、パスワードに数字が含まれていることを確認するのに使います。 + +括弧を使うことで、正規表現のグループを探すこともできます。 + +```tut +import scala.util.matching.Regex + +val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r + +val input: String = + """background-color: #A03300; + |background-image: url(img/header100.png); + |background-position: top center; + |background-repeat: repeat-x; + |background-size: 2160px 108px; + |margin: 0; + |height: 108px; + |width: 100%;""".stripMargin + +for (patternMatch <- keyValPattern.findAllMatchIn(input)) + println(s"key: ${patternMatch.group(1)} value: ${patternMatch.group(2)}") +``` +ここでは、文字列のキーと値を解析しています。 +それぞれのマッチはサブマッチのグループを持ちます。こちらが出力結果です。 +``` +key: background-color value: #A03300 +key: background-image value: url(img/header100.png) +key: background-position value: top center +key: background-repeat value: repeat-x +key: background-size value: 2160px 108px +key: margin value: 0 +key: height value: 108px +key: width value: 100 +``` diff --git a/_ja/tour/self-types.md b/_ja/tour/self-types.md new file mode 100644 index 0000000000..836e4459ec --- /dev/null +++ b/_ja/tour/self-types.md @@ -0,0 +1,42 @@ +--- +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 + +redirect_from: "/tutorials/tour/self-types.html" +--- +自分型は、直接継承していなくてもトレイトが他のトレイトにミックスインされていることを宣言する方法です。 +これにより依存先のメンバーをimportなしで利用できます。 + +自分型は`this`、または`this`の別名となる他の識別子の型を絞り込む方法です。 +その構文は普通の関数構文のように見えますが、全く異なる意味があります。 + +トレイトで自分型を使うには、識別子、ミックスインする他のトレイトの型、`=>`を書きます(例えば `someIdentifier: SomeOtherTrait =>`)。 +```tut +trait User { + def username: String +} + +trait Tweeter { + this: User => // thisが再割り当てされます + def tweet(tweetText: String) = println(s"$username: $tweetText") +} + +class VerifiedTweeter(val username_ : String) extends Tweeter with User { // TweeterがUserを必要とするためミックスインします。 + def username = s"real $username_" +} + +val realBeyoncé = new VerifiedTweeter("Beyoncé") +realBeyoncé.tweet("Just spilled my glass of lemonade") // "real Beyoncé: Just spilled my glass of lemonade"と出力します。 +``` +`trait Tweeter`の中で`this: User =>`と記述したので、今は変数`username`は`tweet`メソッドのスコープ内にあります。これはさらに、`VerifiedTweeter`が`Tweeter`を継承する際、(`with User`を使って)`User`もミックスインしなければならいことを意味します。 diff --git a/_ja/tour/singleton-objects.md b/_ja/tour/singleton-objects.md new file mode 100644 index 0000000000..e920e884c9 --- /dev/null +++ b/_ja/tour/singleton-objects.md @@ -0,0 +1,122 @@ +--- +layout: tour +title: シングルトンオブジェクト +language: ja + +discourse: true + +partof: scala-tour + +num: 13 + +next-page: regular-expression-patterns +previous-page: pattern-matching +redirect_from: "/tutorials/tour/singleton-objects.html" +prerequisite-knowledge: classes, methods, private-methods, packages, option +--- +オブジェクトは丁度1つのインスタンスを持つクラスです。 +それはlazy valのように参照された際に遅れて作られます。 + +トップレベルにあるオブジェクトは、シングルトンです。 +クラスのメンバーやローカル変数としてのオブジェクトは、lazy valと全く同じように振る舞います。 + +# シングルトンオブジェクトの定義 +オブジェクトは値です。オブジェクトの定義はクラスのように見えますが、キーワード`object`を使います。 +```tut +object Box +``` +これはメソッドを持つオブジェクトの例です。 +``` +package logging + +object Logger { + def info(message: String): Unit = println(s"INFO: $message") +} +``` +`info`メソッドはプログラム上のどこからでもimportすることができます。 +このように便利なメソッドを作ることはシングルトンオブジェクトのユースケースと同じです。 + +他のパッケージで`info`がどのように使われるか見てみましょう。 + +``` +import logging.Logger.info + +class Project(name: String, daysToComplete: Int) + +class Test { + val project1 = new Project("TPS Reports", 1) + val project2 = new Project("Website redesign", 5) + info("Created projects") // Prints "INFO: Created projects" +} +``` + +import文`import logging.Logger.info`により、`info`メソッドが見えるようになります。 + +import文には取り込むシンボルへの"変動しないパス"が必要であり、オブジェクトは変動しないパスとなります。 + +注意:`object`がトップレベルではなく他のクラスやオブジェクトにネストされている時、そのオブジェクトは他のメンバーのように"経路依存性"があります。 +これは2種類の飲み物`class 牛乳`と`class オレンジジュース`が与えられた場合、クラスメンバーの`object 栄養素`はそれが属するインスタンス、すなわち牛乳またはオレンジジュースのいずれかに依存することを意味します。 +`milk.NutritionInfo`は`oj.NutritionInfo`とは全く異なります。 + +## コンパニオンオブジェクト + +クラスと同じ名前のオブジェクトは*コンパニオンオブジェクト*と呼ばれます。 +逆にそのクラスはオブジェクトのコンパニオンクラスと呼ばれます。 +コンパニオンクラスやコンパニオンオブジェクトは自身のコンパニオンのプライベートメンバーにアクセスできます。 +コンパニオンクラスのインスタンスに特定されないメソッドや値にはコンパニオンオブジェクトを使います。 + +``` +import scala.math._ + +case 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 = new Circle(5.0) + +circle1.area +``` + +`class Circle`は各インスタンスの固有のメンバー`area`を持ち、シングルトンオブジェクト`object Circle`は全てのインスタンスで利用できる`calculateArea`メソッドを持ちます。 + +コンパニオンオブジェクトはファクトリーメソッドを含むことができます。 +```tut +class Email(val username: String, val domainName: String) + +object Email { + def fromString(emailString: String): Option[Email] = { + emailString.split('@') match { + case Array(a, b) => Some(new Email(a, b)) + case _ => None + } + } +} + +val scalaCenterEmail = Email.fromString("scala.center@epfl.ch") +scalaCenterEmail match { + case Some(email) => println( + s"""Registered an email + |Username: ${email.username} + |Domain name: ${email.domainName} + """) + case None => println("Error: could not parse email") +} +``` +`object Email`はファクトリー`fromString`を持ち、Stringから`Email`インスタンスを作ります。 +パースエラーの場合も考えて、返り値の型を`Option[Email]`とします。 + +注意:クラスまたはオブジェクトがコンパニオンを持つ場合、クラス、オブジェクトの両方は同じファイルの中に定義されていなければなりません。 +REPL内でコンパニオンを定義する場合は、それらを同じ行で定義するか、`:paste`モードに入ります。 + +## Javaプログラマのための注意事項 ## + +Javaにおける`static`メンバーはScalaではコンパニオンオブジェクトの一般メンバーとして作られています。 + +Javaのコードからコンパニオンオブジェクトを使う場合、メンバーはコンパニオンクラス内で`static`識別子を用いて定義されます。 +これは*static forwarding*と呼ばれます。 +これはコンパニオンクラスを自分で定義していなかったとしても起きます。 diff --git a/_ja/tour/tour-of-scala.md b/_ja/tour/tour-of-scala.md new file mode 100644 index 0000000000..775c66557f --- /dev/null +++ b/_ja/tour/tour-of-scala.md @@ -0,0 +1,86 @@ +--- +layout: tour +title: 前書き +language: ja + +discourse: true + +partof: scala-tour + +num: 1 + +next-page: basics + +redirect_from: "/tutorials/tour/tour-of-scala.html" +--- + +## ようこそツアーへ +このツアーはScalaで最もよく使う機能を一口サイズで紹介をしています。 +これらはScala初心者を対象としています。 + +これはほんの短いツアーで、完全な言語のチュートリアルではありません。 +もしそれを望むなら、[こちらの本](/books.html) を手に入れるか、 +[その他の解決手段](/learn.html) での相談を検討してください。 + +## Scalaとは? +Scalaは一般的なプログラミング方法を簡潔かつエレガントかつ型安全な方法で表現するために設計されたモダンなマルチパラダイム言語です。 +それはオブジェクト指向言語と関数型言語の機能をスムーズに統合しています。 + +## Scalaはオブジェクト指向 ## +Scalaは[全ての値がオブジェクトである](unified-types.html) という意味では純粋オブジェクト指向言語です。 +型とオブジェクトの振る舞いは[クラス](classes.html) と[トレイト](traits.html) によって記述されます。 +クラスはサブクラス化と、多重継承を巧みに置き換える柔軟な[ミックスインを基にした合成](mixin-class-composition.html) 機構により拡張されます。 + +## Scalaは関数型 ## +Scalaは[すべての関数が値である](unified-types.html) という意味で関数型言語でもあります。 +Scalaは無名関数を定義するために[軽量な構文](basics.html#関数)を提供し、 +[高階関数](higher-order-functions.html) をサポートし、関数は[ネスト](nested-functions.html)しても良く、[カリー化](multiple-parameter-lists.html) をサポートします。 +Scalaの[ケースクラス](case-classes.html)には[パターンマッチング](pattern-matching.html)が組み込まれていることにより、多くの関数型プログラミング言語で使われる代数型を作ることができます。 +[シングルトンオブジェクト](singleton-objects.html) はクラスのメンバーではない関数をグループ化する便利な方法を提供します。 + +さらに、Scalaのパターンマッチングの概念は、[抽出子オブジェクト](extractor-objects.html) による一般的な拡張として、[右無視シーケンスパターン](regular-expression-patterns.html)の働きにより、自然に[XMLデータの処理](https://github.com/scala/scala-xml/wiki/XML-Processing) にまで拡張されています。 +(訳者註:現在のバージョンでは右無視シーケンスパターンの説明は正規表現のページから除かれています。[→古いバージョン](https://www.scala-lang.org/old/node/122)) +この文脈では、For内包表記はクエリの設計に役立ちます。 +これらの機能により、ScalaはWebサービスのようなアプリケーション開発に理想的なものとなっています。 + +## Scalaは静的型付け ## +Scalaは抽象化が安全で首尾一貫した方法で使われることをコンパイル時に強制する、表現力豊かな型システムを備えています。 +特にその型システムは以下をサポートします: + +* [ジェネリッククラス](generic-classes.html) +* [変位指定アノテーション](variances.html) +* [上限](upper-type-bounds.html) と [下限](lower-type-bounds.html) 型境界 +* [内部クラス](inner-classes.html) とオブジェクトメンバーとしての[抽象型メンバー](abstract-type-members.html) +* [複合型](compound-types.html) +* [明示的に型指定された自己参照](self-types.html) +* [暗黙パラメーター](implicit-parameters.html) と [暗黙の変換](implicit-conversions.html) +* [ポリモーフィックメソッド](polymorphic-methods.html) + +[型推論](type-inference.html) は、ユーザーがコードに冗長な型情報の注釈をつける必要はないことを意味します。 +これらの機能を組み合わせることにより、プログラミングの抽象化を安全に再利用でき、ソフトウェアを型安全に拡張できる強力な基盤となります。 + +## Scalaは拡張可能 ## + +実際問題として、ドメイン固有のアプリケーションの開発ではよくドメイン固有の言語拡張が必要となります。 +Scalaは言語メカニズムのユニークな組み合わせを提供します。それにより、新しい言語構成要素をライブラリという形で円滑に追加することを簡単にします。 + +多くのケースで、これはマクロのようなメタプログラミングの機能を使わずに実現できます。例えば、 + +* [暗黙のクラス](http://docs.scala-lang.org/overviews/core/implicit-classes.html) で既存の型に拡張メソッドを追加できます。 + +* [文字列補間](/ja/overviews/core/string-interpolation.html) はカスタム補間を使ってユーザー拡張可能です。 + +## Scalaの相互運用 + +Scalaは一般的なJava実行環境 (JRE) と相互運用するように設計されています。 +特に、主流であるオブジェクト指向のJavaプログラミング言語とのやり取りはできるだけスムーズになっています。 +ScalaではSAMs、[ラムダ](higher-order-functions.html) 、[アノテーション](annotations.html) 、[ジェネリクス](generic-classes.html) のようなJavaの新しい機能には直接の類似物があります。 + +[デフォルト引数](default-parameter-values.html) 、[名前付きパラメータ](named-arguments.html) +といった、Javaに類似物がないScalaの機能はできるだけ適切でJavaに近い形にコンパイルされます。 +ScalaはJavaのような同じコンパイルモデル(分割コンパイル、動的クラス読み込み) を持っており、数千の既存の高品質なライブラリにアクセスができます。 + +## ツアーを楽しんで! + +もっと読むには、目次メニューの[次のページ](basics.html) に進んでください。 + diff --git a/_ja/tour/traits.md b/_ja/tour/traits.md new file mode 100644 index 0000000000..1ea0b11809 --- /dev/null +++ b/_ja/tour/traits.md @@ -0,0 +1,89 @@ +--- +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 + +redirect_from: "/tutorials/tour/traits.html" +--- + +トレイトはクラス間でインターフェースとフィールドを共有するために使います。それらはJava 8のインターフェースと似ています。 +クラスとオブジェクトはトレイトを継承することができますが、トレイトはインスタンス化ができません、したがってパラメータを持ちません。 + +## トレイトを定義する +最小のトレイトはキーワード `trait` と識別子だけというものです。 + +```tut +trait HairColor +``` + +トレイトはジェネリック型として、抽象メソッドとあわせて使うと特に便利です。 +```tut +trait Iterator[A] { + def hasNext: Boolean + def next(): A +} +``` + +`trait Iterator[A]` を継承することは `A` 型と、`hasNext` と `next` メソッドの実装を必要とします。 + +## トレイトの使い方 +トレイトを継承するには `extends` キーワードを使います。その際に、 `override` キーワードを利用しすべての抽象メンバーを実装します。 +```tut +trait Iterator[A] { + def hasNext: Boolean + def next(): A +} + +class IntIterator(to: Int) extends Iterator[Int] { + private var current = 0 + override def hasNext: Boolean = current < to + override def next(): Int = { + if (hasNext) { + val t = current + current += 1 + t + } else 0 + } +} + + +val iterator = new IntIterator(10) +iterator.next() // returns 0 +iterator.next() // returns 1 +``` +ここでの `IntIterator` クラスは上限として引数 `to` を取ります。 +`extends Iterator[Int]` は `next` メソッドは Int を返さなければならないことを意味します。 + +## サブタイピング +あるトレイトが必要とされている場所に、代りにそのトレイトのサブタイプを使うことができます。 + +```tut +import scala.collection.mutable.ArrayBuffer + +trait Pet { + val name: String +} + +class Cat(val name: String) extends Pet +class Dog(val name: String) extends Pet + +val dog = new Dog("Harry") +val cat = new Cat("Sally") + +val animals = ArrayBuffer.empty[Pet] +animals.append(dog) +animals.append(cat) +animals.foreach(pet => println(pet.name)) // Prints Harry Sally +``` +`trait Pet` が持つ抽象フィールド `name`は、Cat と Dog のコンストラクタで実装されました。 +最終行では、`Pet` トレイトの全てのサブタイプの中で実装される必要がある `pet.name` を呼んでいます。 diff --git a/_ja/tour/tuples.md b/_ja/tour/tuples.md new file mode 100644 index 0000000000..0d67f6c5c1 --- /dev/null +++ b/_ja/tour/tuples.md @@ -0,0 +1,79 @@ +--- +layout: tour +title: タプル +language: ja + +discourse: true + +partof: scala-tour + +num: 6 +next-page: mixin-class-composition +previous-page: traits +topics: tuples + +redirect_from: "/tutorials/tour/tuples.html" +--- + +Scalaではタプルは決まった数の要素を含む値であり、各要素はそれぞれの型を持ちます。 +タプルは不変です。 + +タプルはメソッドから複数の値を返す際に特に役立ちます。 + +2つの要素を持つタプルは以下のように作ることができます。 + +```tut +val ingredient = ("Sugar" , 25) +``` +ここでは`String`要素を1つと`Int`要素を1つ含むタプルを作っています。 + +推論される`ingredient`の型は`(String, Int)`であり、これは`Tuple2[String, Int]`の簡単な表記法です。 + +タプルを表すために、Scalaは`Tuple2`, `Tuple3` … `Tuple22`までのクラス群を使います。 +それぞれのクラスは要素の数と同じ数の型パラメータを持ちます。 + +## 要素へのアクセス + +タプルの要素へのアクセス方法の1つとして、位置があります。 +個々の要素は`_1`、`_2`などと名付けられます。 + +```tut +println(ingredient._1) // Sugar +println(ingredient._2) // 25 +``` +## タプルでのパターンマッチング +タプルはパターンマッチングを使って分解することもできます。 + +```tut +val (name, quantity) = ingredient +println(name) // Sugar +println(quantity) // 25 +``` + +ここでは`name`に推論される型は`String`で、`quantity`に推論される型は`Int`です。 + +こちらはタプルのパターンマッチングの他の例です。 + +```tut +val planets = + List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6), + ("Mars", 227.9), ("Jupiter", 778.3)) +planets.foreach{ + case ("Earth", distance) => + println(s"Our planet is $distance million kilometers from the sun") + case _ => +} +``` + +また、`for`内包表記では以下のようになります。 + +```tut +val numPairs = List((2, 5), (3, -7), (20, 56)) +for ((a, b) <- numPairs) { + println(a * b) +} +``` + +## タプルとケースクラス +ユーザーは時々、タプルとケースクラスの選択を難しいと思うかもしれません。ケースクラスには名前付き要素があります。それらの名前によってコードの可読性を改善できる場合があります。 +上記の惑星の例ではタプルを使うより、`case class Planet(name: String, distance: Double)`を定義したほうがいいかもしれません。 diff --git a/_ja/tour/type-inference.md b/_ja/tour/type-inference.md new file mode 100644 index 0000000000..5a0dc8c4a7 --- /dev/null +++ b/_ja/tour/type-inference.md @@ -0,0 +1,74 @@ +--- +layout: tour +title: 型推論 +language: ja + +discourse: true + +partof: scala-tour + +num: 29 +next-page: operators +previous-page: polymorphic-methods +--- + +Scalaコンパイラが式の型を推論できることが多いので、明示的に型を宣言する必要はありません。 + +## 型の省略 + +```tut +val businessName = "Montreux Jazz Café" +``` +コンパイラは`businessName`がStringだと検知できます。これはメソッドでも同様に動きます。 + +```tut +def squareOf(x: Int) = x * x +``` +コンパイラは戻り値の型が`Int`だと推論できるので、明示的な戻り値の型は必要ありません。 + +再帰的メソッドでは、コンパイラは結果の型を推論できません。こちらはこの理由でコンパイラが失敗するプログラムです。 + +```tut:fail +def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) +``` + +[ポリモーフフィックメソッド](polymorphic-methods.html)が呼ばれる時や[ジェネリッククラス](generic-classes.html) がインスタンス化される場合も型パラメータの指定は強制ではありません。Scalaコンパイラは文脈あるいはメソッドやコンストラクタの実際の引数から、指定されていない型パラメータを推論します。 + +こちらは2つの例です。 + +```tut +case class MyPair[A, B](x: A, y: B); +val p = MyPair(1, "scala") // 型: MyPair[Int, String] + +def id[T](x: T) = x +val q = id(1) // 型: Int +``` +コンパイラは型`A`と`B`が何であるかを見つけ出すために`MyPair`の引数の型を使用します。`x`の型も同様です。 + +## パラメータ + +コンパイラはメソッドのパラメータ型を決して推論しません。しかし、関数が引数として渡されている場合は、無名関数のパラメータ型を推論できます。 + +```tut +Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8) +``` + +mapのパラメータは`f: A => B`です。`Seq`の中に整数が入っているので、コンパイラは`A`が`Int`だと知っています(つまり、この`x`は整数です)。したがってコンパイラは`x * 2`から`B`が型`Int`であると推論できます。 + +## 型推論に頼ら*ない*時 + +一般的には、パブリックなAPIで公開されているメンバーの型を宣言したほうが読みやすいと考えられています。そのため、ユーザーに公開するAPIではあなたのコードの型を明示することをお勧めします。 + +また、型推論は特定の型を推論することがあります。次のように書いたとします。 + +```tut +var obj = null +``` + +これ以上進められず、再割り当てができません。 + +```tut:fail +obj = new AnyRef +``` + +こちらはコンパイルできません。`obj`に推論された型は`Null`だからです。その型の唯一の値が`null`なので、他の値を代入できれません。 diff --git a/_ja/tour/unified-types.md b/_ja/tour/unified-types.md new file mode 100644 index 0000000000..98482b1c95 --- /dev/null +++ b/_ja/tour/unified-types.md @@ -0,0 +1,97 @@ +--- +layout: tour +title: 統合された型 +language: ja + +discourse: true + +partof: scala-tour + +num: 3 +next-page: classes +previous-page: basics +prerequisite-knowledge: classes, basics + +redirect_from: "/tutorials/tour/unified-types.html" +--- +Scalaでは数値や関数を含め、全ての値は型を持ちます。 +以下の図は型階層の一部を説明しています。 + +Scala Type Hierarchy + +## Scalaの型階層 ## + +[`Any`](http://www.scala-lang.org/api/2.12.1/scala/Any.html) は全ての型のスーパータイプであり、トップ型とも呼ばれます。 +Anyは `equals`、` hashCode`、そして `toString`のようないくつかの普遍的なメソッドを定義しています。 +そして`AnyVal`と`AnyRef` という2つの直系のサブクラスを持ちます。 + +`AnyVal` は値型に相当します。 +事前に定義された9つの値型が存在し、それら`Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit`,`Boolean`は +null非許容です。 +`Unit`は意味のある情報をもたない値型です。`Unit`型のインスタンスはただ1つだけあり、`()`というリテラルで宣言することができます。 +全ての関数は必ず何かを返さなければなりません。そのため`Unit`は戻り値の型として時々役立ちます。 + +`AnyRef` は参照型を意味します。全ての値型でない型は参照型として定義されます。Scalaでは全てのユーザー定義型は`AnyRef`のサブタイプになります。 +もしScalaがJava実行環境上で利用されるなら、`AnyRef` は `java.lang.Object` に相当します。 + +以下にstring、integer、character、boolean、関数が他のオブジェクトと同様に全てオブジェクトであるという例を示します。 + +```tut +val list: List[Any] = List( + "a string", + 732, // integer + 'c', // character + true, // boolean value + () => "文字列を返す無名関数" +) + +list.foreach(element => println(element)) +``` + +これは`List[Any]`型の`list`という値を定義します。 +このlistは様々な型の要素で初期化されています。しかしそれぞれの要素は `scala.Any` のインスタンスなのでlistに追加することができています。 + +こちらは先程のプログラムの出力です。 + +``` +a string +732 +c +true + +``` + +## 型キャスト +値型は以下の順序でキャストできます。 + +Scalaの型階層 + +例えば、 + +```tut +val x: Long = 987654321 +val y: Float = x // 9.8765434E8 (この場合精度が落ちることに注意してください) + +val face: Char = '☺' +val number: Int = face // 9786 +``` + +型変換は一方向です。これはコンパイルができないでしょう。 + +``` +val x: Long = 987654321 +val y: Float = x // 9.8765434E8 +val z: Long = y // 一致しない +``` + +参照型をサブタイプにキャストすることもできます。こちらはツアーの中で後ほど紹介します。 + +## Nothing と Null +`Nothing`は全ての型のサブタイプであり、ボトム型とも呼ばれます。`Nothing`型を持つ値は存在しません。 +一般的に例外のスロー、プログラム終了、無限ループなど終了していないことを示すのに使われます。 +(すなわち、値として評価されない式や正常に返らないメソッドなどです。) + + +`Null` は全ての参照型のサブタイプ(すなわち、全てのAnyRefのサブタイプ)です。`null`というキーワードリテラルが指す値を1つだけもちます。 +`Null` は、ほぼ他のJVM言語との相互運用性のためだけに提供されているので、Scalaのコード内ではほとんどの場合、使われるべきではありません。 +`null`の代替手段については、後のツアーで説明します。 diff --git a/_ja/tour/upper-type-bounds.md b/_ja/tour/upper-type-bounds.md new file mode 100644 index 0000000000..427dbe429f --- /dev/null +++ b/_ja/tour/upper-type-bounds.md @@ -0,0 +1,60 @@ +--- +layout: tour +title: 上限型境界 +language: ja + +discourse: true + +partof: scala-tour +categories: tour +num: 20 +next-page: lower-type-bounds +previous-page: variances + +redirect_from: "/tutorials/tour/upper-type-bounds.html" +--- + +Scalaでは [型パラメータ](generic-classes.html)と[抽象型メンバー](abstract-type-members.html) は型境界による制約をかけることができます。 +型境界は型変数に入れられる具象型を制限して、時にはそれらの型のメンバーについてより多くの情報を与えます。 +_上限型境界_ `T <: A` は型変数`T`が型`A`のサブタイプであるという宣言です。 + +こちらはクラス`PetContainer`の型パラメータの上限型境界を実演する例です。 + +```tut +abstract class Animal { + def name: String +} + +abstract class Pet extends Animal {} + +class Cat extends Pet { + override def name: String = "Cat" +} + +class Dog extends Pet { + override def name: String = "Dog" +} + +class Lion extends Animal { + override def name: String = "Lion" +} + +class PetContainer[P <: Pet](p: P) { + def pet: P = p +} + +val dogContainer = new PetContainer[Dog](new Dog) +val catContainer = new PetContainer[Cat](new Cat) +``` + +```tut:fail +// これはコンパイルされません +val lionContainer = new PetContainer[Lion](new Lion) +``` +`class PetContainer`は型パラメータ`P`を受け取ります。それは`Pet`のサブタイプである必要があります。 + `Dog`と`Cat`は`Pet`のサブタイプなので、新たな`PetContainer[Dog]`と`PetContainer[Cat]`を作ることができます。 + しかしながら、もし`PetContainer[Lion]`を作ろうとすると、以下のエラーが返ってきます。 + +`type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]` + +これは`Lion`は`Pet`のサブタイプではないからです。 diff --git a/_ja/tour/variances.md b/_ja/tour/variances.md new file mode 100644 index 0000000000..35f0d01de8 --- /dev/null +++ b/_ja/tour/variances.md @@ -0,0 +1,184 @@ +--- +layout: tour +title: 変位指定 +language: ja + +discourse: true + +partof: scala-tour + +num: 19 +next-page: upper-type-bounds +previous-page: generic-classes + +redirect_from: "/tutorials/tour/variances.html" +--- + +変位指定は複合型の間の継承関係とそれらの型パラメータ間の継承関係の相関です。 +Scalaは[ジェネリッククラス](generic-classes.html)の型パラメータの変位指定アノテーションをサポートしています。 +変位指定アノテーションにより共変、反変にでき、アノテーション無しなら非変になります。 +型システム上で変位指定を利用すると複合型間の直感的な繋がりを作ることができます。 +もし変位指定が無ければ、クラスを抽象化して再利用しにくくなるでしょう。 + + +```tut +class Foo[+A] // 共変クラス +class Bar[-A] // 反変クラス +class Baz[A] // 非変クラス +``` + +### 共変 + +ジェネリッククラスの型パラメータ`A`はアノテーション`+A`を使うと共変になります。 +`class List[+A]`では、`A`が共変になっているので、`A`が`B`のサブタイプであるような`A`と`B`に対して`List[A]`が`List[B]`のサブタイプであることを示します。 +これによりジェネリックを利用したとても便利で直感的なサブタイプの関係を作ることができます。 + +このシンプルなクラス構成を考えてみましょう。 + +```tut +abstract class Animal { + def name: String +} +case class Cat(name: String) extends Animal +case class Dog(name: String) extends Animal +``` +`Cat`と`Dog`は`Animal`のサブタイプです。 +Scala標準ライブラリにはイミュータブルなジェネリッククラス`sealed abstract class List[+A]`があり、型パラメータ`A`が共変です。 +これは`List[Cat]`は`List[Animal]`であり、`List[Dog]`も`List[Animal]`であることを意味します。 +猫のリストも犬のリストも動物のリストであり、どちらも`List[Animal]`の代わりにできる、というのは直感的に理解できます。 + +以下の例では、メソッド`printAnimalNames`は引数に動物のリストを受け取り、新しい行にそれらの名前をプリントします。 +もし`List[A]`が共変でなければ、最後の2つのメソッド呼び出しはコンパイルされず、`printAnimalNames`メソッドの使い勝手はひどく制限されます。 + +```tut +object CovarianceTest extends App { + def printAnimalNames(animals: List[Animal]): Unit = { + animals.foreach { animal => + println(animal.name) + } + } + + val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom")) + val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex")) + + printAnimalNames(cats) + // Whiskers + // Tom + + printAnimalNames(dogs) + // Fido + // Rex +} +``` + +### 反変 + +ジェネリッククラスの型パラメータ`A`はアノテーション`-A`を利用して反変にできます。 +これはクラスとその型パラメータの間で、共変と似ていますが反対の意味のサブタイプ関係を作ります。 + +`class Writer[-A]`では`A`が反変になっているので、`A`が`B`のサブタイプであるような`A`と`B`に対し、`Writer[B]`が`Writer[A]`のサブタイプであることを示します。 + +先に定義された`Cat`、`Dog`、`Animal`クラスを以下の例で検討してみます。 + +```tut +abstract class Printer[-A] { + def print(value: A): Unit +} +``` +`Printer[A]`はある型`A`をどのようにプリントするかを知っている簡単なクラスです。 +特定の型でいくつかのサブクラスを定義してみましょう。 + +```tut +class AnimalPrinter extends Printer[Animal] { + def print(animal: Animal): Unit = + println("The animal's name is: " + animal.name) +} + +class CatPrinter extends Printer[Cat] { + def print(cat: Cat): Unit = + println("The cat's name is: " + cat.name) +} +``` +`Printer[Cat]`はコンソールに任意の`Cat`をプリントする方法を知っています。 +そして`Printer[Animal]`はコンソールに任意の`Animal`をプリントする方法を知っています。 +それは`Printer[Animal]`も任意の`Cat`をプリントする方法を知っていることを意味します。 +逆の関係性は適用されません、それは`Printer[Cat]`がコンソールに任意の`Animal`をプリントする方法を知らないからです。 +したがって、私達は必要であれば`Printer[Animal]`を`Printer[Cat]`代わりに使うことができます。これは`Printer[A]`が反変であるからこそ可能なのです。 + +```tut +object ContravarianceTest extends App { + val myCat: Cat = Cat("Boots") + + def printMyCat(printer: Printer[Cat]): Unit = { + printer.print(myCat) + } + + val catPrinter: Printer[Cat] = new CatPrinter + val animalPrinter: Printer[Animal] = new AnimalPrinter + + printMyCat(catPrinter) + printMyCat(animalPrinter) +} +``` + +この出力結果は以下のようになります。 + +``` +The cat's name is: Boots +The animal's name is: Boots +``` + +### 非変 + +Scalaのジェネリッククラスは標準では非変です。 +これは共変でも反変でもないことを意味します。 +以下の例の状況では、`Container`クラスは非変です。`Container[Cat]`は`Container[Animal]`_ではなく_、逆もまた同様です。 + +```tut +class Container[A](value: A) { + private var _value: A = value + def getValue: A = _value + def setValue(value: A): Unit = { + _value = value + } +} +``` +`Container[Cat]`が `Container[Animal]`でもあることは自然なように思えるかもしれませんが、ミュータブルジェネリッククラスを共変にするのは安全ではありません。 +この例では、`Container`が非変であることは非常に重要です。`Container`が仮に共変だったとするとこのようなことが起こり得ます。 + +``` +val catContainer: Container[Cat] = new Container(Cat("Felix")) +val animalContainer: Container[Animal] = catContainer +animalContainer.setValue(Dog("Spot")) +val cat: Cat = catContainer.getValue // おっと、犬に猫に割り当ててしまった。 +``` + +幸いにも、実行する前にコンパイラが止めてくれます。 + +### 他の例 + +変位指定の理解を助けるもう一つの例はScala標準ライブラリの`trait Function1[-T, +R]`です。 +`Function1`は1つのパラメータを持つ関数を表します。1つ目の型パラメータ`T`はパラメータの型を表します。 +そして2つ目の型パラメータ`R`は戻り値の型を表します。 +`Function1`はその引数の型に対して反変であり、戻り値の型に対して共変です。 +この例では`Function1[A, B]`を表現するために`A => B`という文字での表記をします。 + +先ほど利用された`Cat`, `Dog`, `Animal`の継承ツリーに、以下のものを加えましょう: + +```tut +abstract class SmallAnimal extends Animal +case class Mouse(name: String) extends SmallAnimal +``` + +動物の種類を受け取り、それらが食べる食料の種類を返す関数がいくつかあるとしましょう。 +もし(猫は小動物を食べるので)`Cat => SmallAnimal`が欲しい場合に代わりに`Animal => Mouse`を与えられたとしても、私たちのプログラムはまだ動きます。 +直感的に、`Cat`は`Animal`なので、`Animal => Mouse` は`Cat`を引数として受け取ります。 +そして`SmallAnimal`である`Mouse`を返します。 + +安全に、そのままで前者に代えて後者を用いることができるため、`Animal => Mouse`は`Cat => SmallAnimal`のサブタイプと言うことができます。 + +### 他の言語との比較 + +Scalaに似たいくつかの言語で、変位指定はいろんな方法でサポートされています。 +例えば、Scalaの変位指定アノテーションはC#のそれと非常に似ています。C#ではクラスの抽象性を定義する時にアノテーションが追加されます(宣言時の変位指定)。 +しかしながら、Javaでは、クラスの抽象性を使う時に変位指定アノテーションが利用側のコードから与えられます(使用時の変位指定)。 From 3308d9fae3cdf58ea122d7de98bd2002c3b870c7 Mon Sep 17 00:00:00 2001 From: Eugene Kim Date: Thu, 27 Jun 2019 00:45:44 +0900 Subject: [PATCH 0641/3174] Fix deprecated method definition change a part of the source "def move(dx: Int, dy: Int) {" instead of "def move(dx: Int, dy: Int): Unit = {" "def main(args: Array[String]) {" ---> "def main(args: Array[String]): Unit = {" --- _ko/tour/classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_ko/tour/classes.md b/_ko/tour/classes.md index 0e3a54f558..e2aebe798b 100644 --- a/_ko/tour/classes.md +++ b/_ko/tour/classes.md @@ -19,7 +19,7 @@ previous-page: unified-types class Point(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc - def move(dx: Int, dy: Int) { + def move(dx: Int, dy: Int): Unit = { x = x + dx y = y + dy } @@ -33,7 +33,7 @@ previous-page: unified-types 클래스들은 아래의 예제가 보여주는 것처럼 새로운 기본형으로 초기화된다. object Classes { - def main(args: Array[String]) { + def main(args: Array[String]): Unit = { val pt = new Point(1, 2) println(pt) pt.move(10, 10) From 9b14836791fe9b15ff161b496491762aebe1cdee Mon Sep 17 00:00:00 2001 From: Patrick Moore Date: Wed, 26 Jun 2019 10:28:32 -0700 Subject: [PATCH 0642/3174] Update scala-for-java-programmers.md Java 8 has java.util.function package. Java 8 was released in 2014 (5 years ago). At this point in time, Java developers are *not* surprised about being able to manipulate functions as values and pass them as arguments. --- _overviews/tutorials/scala-for-java-programmers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/tutorials/scala-for-java-programmers.md b/_overviews/tutorials/scala-for-java-programmers.md index 3ed8305c2a..9daab8070e 100644 --- a/_overviews/tutorials/scala-for-java-programmers.md +++ b/_overviews/tutorials/scala-for-java-programmers.md @@ -155,7 +155,7 @@ Scala is a pure object-oriented language in the sense that *everything* is an object, including numbers or functions. It differs from Java in that respect, since Java distinguishes primitive types (such as `boolean` and `int`) from reference -types, and does not enable one to manipulate functions as values. +types. ### Numbers are objects @@ -190,7 +190,7 @@ prevents `1` from being interpreted as a `Double`. ### Functions are objects -Perhaps more surprising for the Java programmer, functions are also +Functions are also objects in Scala. It is therefore possible to pass functions as arguments, to store them in variables, and to return them from other functions. This ability to manipulate functions as values is one of From 0caa894bfe10fb4f50d5b0b9846f62781de90fd4 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Fri, 28 Jun 2019 14:04:08 +0800 Subject: [PATCH 0643/3174] (tutorials) Fix pr#1405 for zh-cn. --- _zh-cn/tutorials/scala-for-java-programmers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_zh-cn/tutorials/scala-for-java-programmers.md b/_zh-cn/tutorials/scala-for-java-programmers.md index f25a39db69..b5fcb5770e 100644 --- a/_zh-cn/tutorials/scala-for-java-programmers.md +++ b/_zh-cn/tutorials/scala-for-java-programmers.md @@ -87,7 +87,7 @@ Scala 的导入表达式跟 Java 非常像,但更为强大。如第一行, ## 一切都是对象 -Scala 是一个纯粹的面向对象语言,这句话的意思是说,*所有东西*都是对象,包括数字、函数。因为 Java 将基本类型 (如 `boolean` 与 `int` ) 跟参照类型分开,而且没有办法像操作变量一样操作函数,从这角度来看 Scala 跟 Java 是不同的。 +Scala 是一个纯粹的面向对象语言,意即包括数字、函数在内的*所有东西*都是对象。这跟 Java 不同,因为 Java 的基本类型 (如 `boolean` 与 `int` ) 和引用类型是有区别的。 ### 数字是对象 @@ -113,7 +113,7 @@ Scala 是一个纯粹的面向对象语言,这句话的意思是说,*所有 ### 函数是对象 -可能令 Java 程序员更为惊讶的会是,Scala 中函数也是对象。因此,将函数当做对象传递、把它们存入变量、从其他函数返回函数都是可能的。能够像操作变量一样的操作函数这点是*函数式编程*这一非常有趣的程序设计思想的基石之一。 +Scala 中的函数也是对象,所以将函数当做对象传递、把它们存入变量、从其他函数返回函数都是可能的。能够像操作变量一样的操作函数这点是*函数式编程*这一非常有趣的程序设计思想的基石之一。 为何把函数当做变量一样的操作会很有用呢,让我们考虑一个定时函数,功能是每秒执行一些动作。我们要怎么将这动作传给它?最直接的便是将这动作视为函数传入。应该有不少程序员对这种简单传递函数的行为很熟悉:通常在用户界面相关的程序上,用来注册一些当事件发生时被调用的回调函数。 From dbfeb680e2971536dda84e1643fea0ee91df4cad Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Fri, 28 Jun 2019 14:07:09 +0800 Subject: [PATCH 0644/3174] polish. --- _zh-cn/tutorials/scala-for-java-programmers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/tutorials/scala-for-java-programmers.md b/_zh-cn/tutorials/scala-for-java-programmers.md index b5fcb5770e..b42c241852 100644 --- a/_zh-cn/tutorials/scala-for-java-programmers.md +++ b/_zh-cn/tutorials/scala-for-java-programmers.md @@ -87,7 +87,7 @@ Scala 的导入表达式跟 Java 非常像,但更为强大。如第一行, ## 一切都是对象 -Scala 是一个纯粹的面向对象语言,意即包括数字、函数在内的*所有东西*都是对象。这跟 Java 不同,因为 Java 的基本类型 (如 `boolean` 与 `int` ) 和引用类型是有区别的。 +Scala 是一个纯粹的面向对象语言,意即包括数字、函数在内的*一切*都是对象。这跟 Java 不同,因为 Java 的基本类型 (如 `boolean` 与 `int` ) 和引用类型是有区别的。 ### 数字是对象 From 3bdfd8c2554d34573d4e7057a2dc9847ae844d30 Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Fri, 28 Jun 2019 14:39:17 +0800 Subject: [PATCH 0645/3174] Fix internal hashes. --- _zh-cn/glossary/index.md | 87 ++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md index 79893b5298..60df57c6eb 100644 --- a/_zh-cn/glossary/index.md +++ b/_zh-cn/glossary/index.md @@ -29,7 +29,7 @@ match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。 匿名类是由Scala编译器根据一种new表达式生成的合成子类,这种new表达式由类名或特质名后面紧跟一对花括号组成。花括号内包含了匿名子类的构造体,可为空,不过一旦跟在new后面名称指向的特质或类包含了抽象成员,则这些抽象成员就必须在其匿名子类的构造体内具化,即在花括号内要实现这些成员。 * #### 匿名函数(anonymous function) -[函数字面量](#function-literal)的另一种叫法。 +[函数字面量](#函数字面量function-literal)的另一种叫法。 * #### 应用(apply) 方法、函数或闭包应用于参数,意思是说通过这些实参来调用方法、函数或闭包。 @@ -44,7 +44,7 @@ match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。 在类定义体花括号里面定义的所有附加构造器,其形似名为`this`但无结果类型的方法定义。 * #### 块(block) -被花括号围起来的一个或多个表达式和声明。求值块的时候,块内所有表达式和声明会被顺序处理,然后会返回最后一个表达式的值作为其自身的值。块通常被用来作为构造体,诸如函数、[for表达式](#for-expression)、`while`循环以及其他任何需要把语句组织到一起的地方,都会用到块。更正式点说,块是一个只其副作用和结果值对外可见的封装构造体。因此,类或对象的花括号是不会形成块的,因其内部定义字段和方法均对外可见。这样的花括号形成的是模板。 +被花括号围起来的一个或多个表达式和声明。求值块的时候,块内所有表达式和声明会被顺序处理,然后会返回最后一个表达式的值作为其自身的值。块通常被用来作为构造体,诸如函数、[for表达式](#for表达式for-expression)、`while`循环以及其他任何需要把语句组织到一起的地方,都会用到块。更正式点说,块是一个只其副作用和结果值对外可见的封装构造体。因此,类或对象的花括号是不会形成块的,因其内部定义字段和方法均对外可见。这样的花括号形成的是模板。 * #### 绑定变量(bound variable) 表达式的绑定变量是定义和使用都在表达式内部的变量。例如,在函数字面量表达式`(x: Int) => (x, y)`里面,`x`和`y`都被用到了,但只有`x`被绑定了,因为它在表达式中被定义为一个`Int`变量,并且它也是表达式所描述函数的唯一实参。 @@ -86,10 +86,10 @@ match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。 类是其 _直接子类_ 的直接超类。 * #### 直接超类(direct superclass) -从某个类直接衍生出类或特质,或者说在继承层级结构最接近自己的上层的某个类,这样的类就是直接超类。若类`Child`的可选的extends子句中含有类`Parent`,则`Parent`就是`Child`的直接超类。若`Child`的可选extends子句中含有特质,则特质的直接超类也是`Child`的直接超类。若`Child`没有extends子句,则`AnyRef`就是`Child`的直接超类。若类的直接超类带有类型参数,比如`Child extends Parent[String]`,`Child`的直接超类依旧是`Parent`,而不是`Parent[String]`。另一方面,`Parent[String]`应该叫做`Child`的直接超类型。参见[超类型](#supertype)了解更多关于类和类型间的区别。 +从某个类直接衍生出类或特质,或者说在继承层级结构最接近自己的上层的某个类,这样的类就是直接超类。若类`Child`的可选的extends子句中含有类`Parent`,则`Parent`就是`Child`的直接超类。若`Child`的可选extends子句中含有特质,则特质的直接超类也是`Child`的直接超类。若`Child`没有extends子句,则`AnyRef`就是`Child`的直接超类。若类的直接超类带有类型参数,比如`Child extends Parent[String]`,`Child`的直接超类依旧是`Parent`,而不是`Parent[String]`。另一方面,`Parent[String]`应该叫做`Child`的直接超类型。参见[超类型](#超类型supertype)了解更多关于类和类型间的区别。 * #### 相等性(equality) -在没有条件限制的情况下使用时,_相等性_ 就是`==`所表达的两个值之间的关系。参见[引用相等性](#reference-equality)。 +在没有条件限制的情况下使用时,_相等性_ 就是`==`所表达的两个值之间的关系。参见[引用相等性](#引用相等性reference-equality)。 * #### 存在类型(existential type) 存在类型包含未知类型变量的引用。比如:`Array[T] forSome { type T }`是个存在类型,是`T`的数组,而`T`是某个完全未知的类型,关于`T`唯一能够假定的是它是确定存在的。尽管这个假定很虚,但是至少意味着`Array[T] forSome { type T }`确实是个数组,而不是香蕉什么的东西。 @@ -98,43 +98,43 @@ match表达式的一个分支,形如 “`case` _pattern_ => _expression_”。 任何能够得到结果的Scala代码,也可说成表达式求值为某个结果或结果为某个值。 * #### 过滤器(filter) -[for表达式](#for-expression)中的`if`及跟在其后的布尔表达式。在`for(i <- 1 to 10; if i % 2 == 0)`中,过滤器为"`if i % 2 == 0`"。`if`右边的值就是[过滤器表达式](#filter-expression),也称为守卫。 +[for表达式](#for表达式for-expression)中的`if`及跟在其后的布尔表达式。在`for(i <- 1 to 10; if i % 2 == 0)`中,过滤器为"`if i % 2 == 0`"。`if`右边的值就是[过滤器表达式](#过滤器表达式filter-expression),也称为守卫。 * #### 过滤器表达式(filter expression) -过滤器表达式就是[for表达式](#for-expression)里面跟在`if`后面的布尔表达式。`for( i <- 1 to 10 ; if i % 2 == 0)`的过滤器表达式为"`i % 2 == 0`"。 +过滤器表达式就是[for表达式](#for表达式for-expression)里面跟在`if`后面的布尔表达式。`for( i <- 1 to 10 ; if i % 2 == 0)`的过滤器表达式为"`i % 2 == 0`"。 * #### 头等函数(first-class function) -Scala支持 _头等函数_ ,意味着可以通过函数字面量语法来表达函数。如:`(x: Int) => x + 1`,并且函数可由对象来表达,叫做[函数值](#function-value)。 +Scala支持 _头等函数_ ,意味着可以通过函数字面量语法来表达函数。如:`(x: Int) => x + 1`,并且函数可由对象来表达,叫做[函数值](#函数值function-value)。 * #### for推解式(for comprehension) -_for推解式_ 是[for表达式](#for-expression)的一种,一般用来创建新的集合。对`for`推解式的每次迭代,[yield](#yield)子句都会定义新集合的一个元素。比如:`for (i <- (0 until 2); j <- (2 until 4)) yield (i, j)`将返回集合`Vector((0,2), (0,3), (1,2), (1,3))`。 +_for推解式_ 是[for表达式](#for表达式for-expression)的一种,一般用来创建新的集合。对`for`推解式的每次迭代,[yield](#产生yield)子句都会定义新集合的一个元素。比如:`for (i <- (0 until 2); j <- (2 until 4)) yield (i, j)`将返回集合`Vector((0,2), (0,3), (1,2), (1,3))`。 * #### for表达式(for expression) -_for表达式_ 要么是个[for循环](#for-loop),可以迭代一个或多个集合,要么是个[for推解式](#for-comprehension),可以从一个或多个集合的元素中推解出一个新的集合。`for`表达式建于[生成器](#generator)、[过滤器](#filter)、变量定义和[yield](#yield)子句(针对[for推解式](#for-comprehension))基础之上, +_for表达式_ 要么是个[for循环](#for循环for-loop),可以迭代一个或多个集合,要么是个[for推解式](#for推解式for-comprehension),可以从一个或多个集合的元素中推解出一个新的集合。`for`表达式建于[生成器](#生成器generator)、[过滤器](#过滤器filter)、变量定义和[yield](#产生yield)子句(针对[for推解式](#for推解式for-comprehension))基础之上, * #### for循环(for loop) -_for循环_ 是[for表达式](#for-expression)的一种,一般用来循环迭代一个或多个集合。因为`for`循环返回unit,所以经常被用来产生副作用。比如:`for (i <- 0 until 100) println(i)`打印数字0到99。 +_for循环_ 是[for表达式](#for表达式for-expression)的一种,一般用来循环迭代一个或多个集合。因为`for`循环返回unit,所以经常被用来产生副作用。比如:`for (i <- 0 until 100) println(i)`打印数字0到99。 * #### 自由变量(free variable) 一个表达式的 _自由变量_ 指的是在表达式中使用但不定义在其中的变量。例如,在函数字面量表达式`(x: Int) => (x, y)`中,变量`x`和`y`都被用到了,但只有`y`是自由变量,因其未在表达式中定义。 * #### 函数(function) -_函数_ 可通过一列实参来[调用](#invoke)然后产生结果。函数一般具有参数列表、函数体和结果类型。作为类、特质或单例对象的函数叫做[方法](#method)。定义在其他函数内部的函数叫做[局部函数](#local-function)。结果类型为`Unit`的函数叫做[过程](#procedure)。源码里面的匿名函数叫做[函数字面量](#function-literal)。运行时,函数字面量被实例化为对象,叫做[函数值](#function-value)。 +_函数_ 可通过一列实参来[调用](#调用invoke)然后产生结果。函数一般具有参数列表、函数体和结果类型。作为类、特质或单例对象的函数叫做[方法](#方法method)。定义在其他函数内部的函数叫做[局部函数](#局部函数local-function)。结果类型为`Unit`的函数叫做[过程](#过程procedure)。源码里面的匿名函数叫做[函数字面量](#函数字面量function-literal)。运行时,函数字面量被实例化为对象,叫做[函数值](#函数值function-value)。 * #### 函数字面量(function literal) 在Scala源码中的无名函数,通过函数字面量语法来特别对待。比如:`(x: Int, y: Int) => x + y`。 * #### 函数值(function value) -可以像其他函数一样被调用的函数对象。函数值的类一般是继承了`scala`包中的`FunctionN`(比如`Function0`,`Function1`等)这类特质的其中之一,且在源码中常通过[函数字面量](#function-literal)语法来表示。当函数值的apply方法被调用时就说这个函数值被调用。捕获自由变量的函数值为[闭包](#closure)。 +可以像其他函数一样被调用的函数对象。函数值的类一般是继承了`scala`包中的`FunctionN`(比如`Function0`,`Function1`等)这类特质的其中之一,且在源码中常通过[函数字面量](#函数字面量function-literal)语法来表示。当函数值的apply方法被调用时就说这个函数值被调用。捕获自由变量的函数值为[闭包](#闭包closure)。 * #### 函数式风格(functional style) -_函数式风格_ 编程注重函数和求值结果而非操作发生的顺序。这种风格的特征是可传递函数值给循环方法、不可变数据、方法无副作用,是像Haskell和Erlang等这些语言的主要范式,与[命令式风格](#imperative-style)相对应。 +_函数式风格_ 编程注重函数和求值结果而非操作发生的顺序。这种风格的特征是可传递函数值给循环方法、不可变数据、方法无副作用,是像Haskell和Erlang等这些语言的主要范式,与[命令式风格](#命令式风格imperative-style)相对应。 * #### 生成器(generator) -生成器在[for表达式](#for-expression)中定义一个命名的val变量并赋予其一系列值。比如:`for(i <- 1 to 10)`的生成器是"`i <- 1 to 10`",`<-`右边的值是[generator表达式](#generator-expression)。 +生成器在[for表达式](#for表达式for-expression)中定义一个命名的val变量并赋予其一系列值。比如:`for(i <- 1 to 10)`的生成器是"`i <- 1 to 10`",`<-`右边的值是[生成器表达式](#生成器表达式generator-expression)。 * #### 生成器表达式(generator expression) -生成器表达式在[for表达式](#for-expression)中生成一些列值。比如:`for(i <- 1 to 10)`的生成器表达式是"`1 to 10`"。 +生成器表达式在[for表达式](#for表达式for-expression)中生成一些列值。比如:`for(i <- 1 to 10)`的生成器表达式是"`1 to 10`"。 * #### 泛型类(generic class) 带有类型参数的类。例如,因`scala.List`带一类型参数,故其为泛型类。 @@ -143,19 +143,19 @@ _函数式风格_ 编程注重函数和求值结果而非操作发生的顺序 带有类型参数的特质。例如,因`scala.collection.Set`带一类型参数,故其为泛型特质。 * #### 守卫(guard) -参见[过滤器](#filter). +参见[过滤器](#过滤器filter). * #### 辅助函数(helper function) 目的是为一个或多个其他邻近函数提供服务的函数。辅助函数常实现为局部函数。 * #### 辅助方法(helper method) -作为类成员的[辅助函数](#helper-function)。辅助方法常为私有方法。 +作为类成员的[辅助函数](#辅助函数helper-function)。辅助方法常为私有方法。 * #### 不可变(immutable) 若对象的值在任何对客户端可见的方式下创建后不会被修改则称对象是 _不可变_ 的。对象既可以是不可变的,也可以是可变的。 * #### 命令式风格(imperative style) -_命令式风格_ 编程强调严谨的操作序列以令效用能在正确的顺序发生。这种风格的特征是循环迭代、适当变更数据、方法有副作用,是像C, C++, C#和Java等这些语言的主要范式,与[函数式风格](#functional-style)相对应。 +_命令式风格_ 编程强调严谨的操作序列以令效用能在正确的顺序发生。这种风格的特征是循环迭代、适当变更数据、方法有副作用,是像C, C++, C#和Java等这些语言的主要范式,与[函数式风格](#函数式风格functional-style)相对应。 * #### 初始化(initialize) 变量在Scala源码中被定义时,必须用对象对其进行初始化。 @@ -173,16 +173,16 @@ _不变性_ 用在两个地方。首先在数据结构组织良好的情况下 在实参上 _调用_ 方法、函数或闭包,意即其方法体会在指定实参上执行。 * #### Java虚拟机(JVM) -_JVM_ 是Java虚拟机(#runtime)的缩写,或叫[运行时](#runtime),是运行Scala程序的宿主。 +_JVM_ 是Java虚拟机(#runtime)的缩写,或叫[运行时](#运行时runtime),是运行Scala程序的宿主。 * #### 字面量(literal) `1`,`"One"`,和`(x: Int) => x + 1`是 _字面量_ 的例子,字面量是描述对象的便捷方式,便捷在这种方式正好反映了所创建对象的结构。 * #### 局部函数(local function) -_局部函数_ 是块内`def`定义的,作为对比,同为`def`定义的作为类、特质或单例对象的成员则被称作[方法](#method)。 +_局部函数_ 是块内`def`定义的,作为对比,同为`def`定义的作为类、特质或单例对象的成员则被称作[方法](#方法method)。 * #### 局部变量(local variable) -_局部变量_ 是块内`val`或`var`定义的。尽管函数参数和[局部变量](#local-variable)类似,但并不叫局部变量,而是去掉"局部"直接叫"参数"或"变量"。 +_局部变量_ 是块内`val`或`var`定义的。尽管函数参数和[局部变量](#局部变量local-variable)类似,但并不叫局部变量,而是去掉"局部"直接叫"参数"或"变量"。 * #### 成员(member) _成员_ 是类、特质或单例对象模板中被命名的元素。成员可通过所有者名称,点及其简名访问。例如,定义在类的最顶层字段和方法是这个类的成员。定义在类中的特质是包围它的类的成员。类中通过type关键字定义的类型是这个类的成员。类是其定义所在的包的成员。相比之下,局部变量或局部函数就不是包围他们的块的成员。 @@ -218,7 +218,7 @@ _混入_ 就是特质用在混入组合时的名称。换言之,在"`trait Hat 函数可带有零至多个 _参数_,每个参数都有名称和类型。参数与实参之间的区别在于函数调用时实参指向具体的对象,参数则是指向这些传入实参的变量。 * #### 无参函数(parameterless function) -不带参数的函数,其定义时没有任何空括号。无参函数可不带括号调用,这种方式符合[统一访问原则](#uniform-access-principle),就是在客户端不改变任何代码的情况下把`def`改成`val`。 +不带参数的函数,其定义时没有任何空括号。无参函数可不带括号调用,这种方式符合[统一访问原则](#统一访问原则uniform-access-principle),就是在客户端不改变任何代码的情况下把`def`改成`val`。 * #### 无参方法(parameterless method) _无参方法_ 就是作为类、特质或单例对象成员的无参函数。 @@ -236,7 +236,7 @@ _无参方法_ 就是作为类、特质或单例对象成员的无参函数。 在`match`表达式的某个备选项中,_模式_ 跟在`case`关键字后,先于 _模式守卫_ 或`=>`符号二者之一。 * #### 模式守卫(pattern guard) -在`match`表达式的某个备选项中,_模式守卫_ 可跟在某个[模式](#pattern)后面。比如,"`case x if x % 2 == 0 => x + 1`"中的模式守卫为"`if x % 2 == 0`"。带有模式守卫的备选项(case)仅当其模式匹配了并且模式守卫为真的时候才会被选中。 +在`match`表达式的某个备选项中,_模式守卫_ 可跟在某个[模式](#模式pattern)后面。比如,"`case x if x % 2 == 0 => x + 1`"中的模式守卫为"`if x % 2 == 0`"。带有模式守卫的备选项(case)仅当其模式匹配了并且模式守卫为真的时候才会被选中。 * #### 断言(predicate) 断言是结果类型为`Boolean`的函数。 @@ -251,13 +251,13 @@ _过程_ 是结果类型为`Unit`的函数,其存在的理由仅为产生副 变量可以是可重新赋值的,也可以不是可重新赋值的。`var`是可重新赋值的,而`val`则不是。 * #### 递归的(recursive) -若函数可调用自身就说它是 _递归的_。若函数调用自身的唯一位置是函数的最后一个表达式,则函数是[尾递归的](#tail-recursive) +若函数可调用自身就说它是 _递归的_。若函数调用自身的唯一位置是函数的最后一个表达式,则函数是[尾递归](#尾递归tail-recursive)的。 * #### 引用(reference) -_引用_ 是指针的Java抽象,可唯一确定存在JVM堆中的对象。引用类型变量持有对象的引用,因为引用类型(`AnyRef`的实例)是存在JVM堆上的Java对象实现的。相比之下,值类型变量有时会持有一个(装箱类型的)引用,也有时(当对象表示基础类型值的时候)不会。一般说来,Scala变量[指向](#refers)对象。术语"指向"比"持有引用"更加抽象。如果类型为`scala.Int`的变量当前代表Java基础类型`int`的值,则这个变量仍然指向`Int`对象,但并不涉及任何引用。 +_引用_ 是指针的Java抽象,可唯一确定存在JVM堆中的对象。引用类型变量持有对象的引用,因为引用类型(`AnyRef`的实例)是存在JVM堆上的Java对象实现的。相比之下,值类型变量有时会持有一个(装箱类型的)引用,也有时(当对象表示基础类型值的时候)不会。一般说来,Scala变量[指向](#指向refers)对象。术语"指向"比"持有引用"更加抽象。如果类型为`scala.Int`的变量当前代表Java基础类型`int`的值,则这个变量仍然指向`Int`对象,但并不涉及任何引用。 * #### 引用相等性(reference equality) -_引用相等性_ 意思是两个引用指向同一个Java对象。引用相等性仅针对引用类型有意义,是可以通过调用`AnyRef`中的`eq`来确定的(在Java程序中,引用相等性通过在Java[引用类型](#reference-type)上调用`==`来确定)。 +_引用相等性_ 意思是两个引用指向同一个Java对象。引用相等性仅针对引用类型有意义,是可以通过调用`AnyRef`中的`eq`来确定的(在Java程序中,引用相等性通过在Java[引用类型](#引用类型reference-type)上调用`==`来确定)。 * #### 引用类型(reference type) _引用类型_ 是`AnyRef`的子类。在运行时,引用类型的实例常驻JVM堆中。 @@ -266,7 +266,7 @@ _引用类型_ 是`AnyRef`的子类。在运行时,引用类型的实例常驻 独立于临时上下文且无副作用的函数属性。对于特定输入,引用透明函数的调用可由其结果替换而不改变程序语义。 * #### 指向(refers) -运行的Scala程序中的变量常 _指向_ 某个对象。变量即使被赋为`null`,概念上也是指向`Null`对象。在运行时,对象可由Java对象或基础类型值来实现,不过Scala允许程序员在更高层次抽象代码以他们设想的方式运行。参见[引用](#reference). +运行的Scala程序中的变量常 _指向_ 某个对象。变量即使被赋为`null`,概念上也是指向`Null`对象。在运行时,对象可由Java对象或基础类型值来实现,不过Scala允许程序员在更高层次抽象代码以他们设想的方式运行。参见[引用](#引用reference). * #### 精化类型(refinement type) 通过提供基础类型及其构造体花括号内若干成员而形成的类型。花括号内的成员精细化了基础类型所体现的类型。比如,"食草动物"(animal that eats grass)的类型为`Animal { type SuitableFood = Grass }`。 @@ -279,14 +279,13 @@ Scala程序中的表达式会产生 _结果_。Scala中的每个表达式的结 方法的 _结果类型_ 是调用方法所产生的值的类型。(在Java中,这个概念被称为返回类型) * #### 返回(return) -Scala程序中的函数会 _返回_ 值,可把这个值叫做函数的[结果](#result)。也可以说函数 _结果是_ 某个值。Scala中的每个函数结果都是一个对象。 -A function in a Scala program `returns` a value. You can call this value the [result](#result) of the function. You can also say the function _results in_ the value. The result of every function in Scala is an object. +Scala程序中的函数会 _返回_ 值,可把这个值叫做函数的[结果](#结果result)。也可以说函数 _结果是_ 某个值。Scala中的每个函数结果都是一个对象。 * #### 运行时(runtime) -正在运行Scala程序的宿主Java虚拟机,或宿主[JVM](#jvm)。运行时这个概念包含了Java虚拟机规范中定义的虚拟机以及Java API和标准Scala API的运行时库。在运行时的这个阶段,意味着程序正在运行中,与编译时是相对的概念。 +正在运行Scala程序的宿主Java虚拟机,或宿主[JVM](#java虚拟机jvm)。运行时这个概念包含了Java虚拟机规范中定义的虚拟机以及Java API和标准Scala API的运行时库。在运行时的这个阶段,意味着程序正在运行中,与编译时是相对的概念。 * #### 运行时类型(runtime type) -对象在运行时的类型。相比之下,[静态类型](#static-type)指的是表达式在编译时的类型。多数运行时类型都是无类型参数的裸类,比如,`"Hi"`的运行时类型是`String`,`(x: Int) => x + 1`的运行时类型是`Function1`。运行时类型可通过`isInstanceOf`来检测。 +对象在运行时的类型。相比之下,[静态类型](#静态类型static-type)指的是表达式在编译时的类型。多数运行时类型都是无类型参数的裸类,比如,`"Hi"`的运行时类型是`String`,`(x: Int) => x + 1`的运行时类型是`Function1`。运行时类型可通过`isInstanceOf`来检测。 * #### 脚本(script) 包含顶层定义和语句,可直接通过`scala`命令来跑而无需显式编译的文件就是脚本,脚本结尾必须是表达式,而不能是定义。 @@ -307,28 +306,28 @@ XML数据就是半结构化的,因其相比于普通的二进制文件或文 局部变量的重新声明会 _遮掩_ 作用域内相同名称的变量声明。 * #### 签名(signature) -_签名_ 是[类型签名](#type-signature)的简写。 +_签名_ 是[类型签名](#类型签名type-signature)的简写。 * #### 单例对象(singleton object) -由object关键字定义的对象。每个单例对象有且仅有一个实例。与某个类共享名称且与这个类定义在同一源文件中的单例对象,叫这个类的[伴随对象](#companion-object),类则叫单列对象的[伴随类](#companion-class)。无伴随类的单例对象叫[独立对象](#standalone-object)。 +由object关键字定义的对象。每个单例对象有且仅有一个实例。与某个类共享名称且与这个类定义在同一源文件中的单例对象,叫这个类的[伴随对象](#伴随对象companion-object),类则叫单列对象的[伴随类](#伴随类companion-class)。无伴随类的单例对象叫[独立对象](#独立对象standalone-object)。 * #### 独立对象(standalone object) -没有[伴生类](#companion-class)的[单例对象](#singleton-object)。 +没有[伴生类](#伴生类companion-class)的[单例对象](#单例对象singleton-object)。 * #### 语句(statement) 指的是表达式、定义或包导入等这些可放到Scala源码的模板或块中的东西。 * #### 静态类型(static type) -参见[类型](#type)。 +参见[类型](#类型type)。 * #### 结构类型(structural type) -也是一种[精化类型](#refinement-type),只是精化的目标是未在基类型中的成员。比如`{ def close(): Unit }`就是结构类型,因其基类型是`AnyRef`,而`AnyRef`并无名为`close`的成员。 +也是一种[精化类型](#精化类型refinement-type),只是精化的目标是未在基类型中的成员。比如`{ def close(): Unit }`就是结构类型,因其基类型是`AnyRef`,而`AnyRef`并无名为`close`的成员。 * #### 子类(subclass) -一个类是其所有[超类](#superclass)和[超特质](#supertrait)的 _子类_。 +一个类是其所有[超类](#超类superclass)和[超特质](#超特质supertrait)的 _子类_。 * #### 子特质(subtrait) -一个特质是其所有[超特质](#supertrait)的 _子特质_。 +一个特质是其所有[超特质](#超特质supertrait)的 _子特质_。 * #### 子类型(subtype) Scala编译器允许任何类型在需要该类型的地方使用其 _子类型_ 作为替代。对不带类型参数的类和特质来说,子类型的关系会反映子类的关系。比如,若类`Cat`是抽象类`Animal`的子类,且也不带类型参数,则类型`Cat`就是类型`Animal`的子类型。同样,若特质`Apple`是特质`Fruit`的子特质且无类型参数,则类型`Apple`就是类型`Fruit`的子类型。而对于带有类型参数的类和特质来说,协变就起作用了。比如,由于抽象类`List`被声明为在其长类型参数上是协变的(例,`List`被声明为`List[+A]`),`List[Cat]`是`List[Animal]`的子类型,`List[Apple]`是`List[Fruit]`的子类型。尽管这些类型的类都是`List`,但其子类型的关系依旧是存在的。对比来看,因为`Set`未被声明在其类型参数上是协变的(例,`Set`被声明为`Set[A]`,不带加号),所以`Set[Cat]`并不是`Set[Animal]`的子类型。子类型应该正确实现其超类型的契约,以便应用里氏替换原则(Liskov Substitution Principle),不过编译器仅会在类型检查级别核验此属性。 @@ -355,13 +354,13 @@ _目标类型化_ 是参考所需类型来进行类型推导的一种形式。 _模板_ 是类、特质或单例对象定义体,它定义了类、特质或对象的类型签名,行为以及初始状态。 * #### 特质(trait) -_特质_ 通过`trait`关键字定义,是像抽象类一样不带任何值参数,并且可通过被称为[混入组合](#mixin-composition)的过程"混入到"类或其他特质。当某个特质被混入到其他类或特质,它就被叫做[混入](#mixin)。特质可通过一个或多个类型参数化。用类型来参数化后,特质就形成了类型。比如,`Set`是带有单类型参数的特质,而`Set[Int]`却是一个类型。`Set`也被说成是类型`Set[Int]`的"特质"。 +_特质_ 通过`trait`关键字定义,是像抽象类一样不带任何值参数,并且可通过被称为[混入组合](#混入组合mixin-composition)的过程"混入到"类或其他特质。当某个特质被混入到其他类或特质,它就被叫做[混入](#混入mixin)。特质可通过一个或多个类型参数化。用类型来参数化后,特质就形成了类型。比如,`Set`是带有单类型参数的特质,而`Set[Int]`却是一个类型。`Set`也被说成是类型`Set[Int]`的"特质"。 * #### 类型(type) -Scala程序中每个变量和表达式都有编译时确定的 _类型_。类型可以在运行时限定变量能指向的值和表达式所能产生的值。如果有必要从对象的[运行时类型](#runtime-type)的角度对变量和表达式的类型进行区分的话,他们也被称为 _静态类型_。换句话说,"类型"这个词本身意味着静态类型。类型与类是区分开的因为带有类型参数的类可以构成许多类型。比如,`List`是类不是类型,`List[T]`则是一个带有自由类型参数的类型,`List[Int]`和`List[String]`也是类型(称为实类型因为他们没有自由类型参数)。类型可以有"[类](#class)"或"[特质](#trait)",比如类型`List[Int]`的类是`List`,类型`Set[String]`的特质是`Set`。 +Scala程序中每个变量和表达式都有编译时确定的 _类型_。类型可以在运行时限定变量能指向的值和表达式所能产生的值。如果有必要从对象的[运行时类型](#运行时类型runtime-type)的角度对变量和表达式的类型进行区分的话,他们也被称为 _静态类型_。换句话说,"类型"这个词本身意味着静态类型。类型与类是区分开的因为带有类型参数的类可以构成许多类型。比如,`List`是类不是类型,`List[T]`则是一个带有自由类型参数的类型,`List[Int]`和`List[String]`也是类型(称为实类型因为他们没有自由类型参数)。类型可以有"[类](#类class)"或"[特质](#特质trait)",比如类型`List[Int]`的类是`List`,类型`Set[String]`的特质是`Set`。 * #### 类型约束(type constraint) -有些[注解](#annotation)是 _类型约束_,意味着他们会对类型能够包含的取值增加额外的限制或约束。比如,`@positive`可以是类型`Int`的类型约束,用来限制32位整型的取值为正的整数。类型约束虽然不会被标准Scala编译器检查,但相应的必须可被额外的工具或编译器插件检查。 +有些[注解](#注解annotation)是 _类型约束_,意味着他们会对类型能够包含的取值增加额外的限制或约束。比如,`@positive`可以是类型`Int`的类型约束,用来限制32位整型的取值为正的整数。类型约束虽然不会被标准Scala编译器检查,但相应的必须可被额外的工具或编译器插件检查。 * #### 类型构造器(type constructor) 带类型参数的类或特质。 @@ -379,7 +378,7 @@ _统一访问原则_ 指的是变量和无参函数应以相同的语法来访 在Scala层面,对象可以是 _不可达_ 的,此时其所占据的内存可被运行时回收。不可达并不一定意味着未被引用。引用类型(`AnyRef`的实例)被实现为驻于JVM堆上的对象。当引用类型的实例不可达后,它也确实不被引用了,且可被垃圾回收。值类型(`AnyVal`的实例)可被实现为驻于堆中的基础类型值或Java包装类型实例(如`java.lang.Integer`)。值类型实例可在指向他们的变量的整个生命周期内被装箱(从基础类型值转成包装类型对象)或拆箱(从包装类型对象转成基础类型值)。若表现为JVM堆上的包装类型对象的值类型实例不可达,那就确实不会被引用并且可被垃圾回收。但是若正在表现为基础类型值的值类型不可达,则其仍可被引用,因为此时它并不会以作为对象驻于JVM堆上。运行时可回收不可达对象所占据的内存,但是假如一个Int在运行时被实现为Java基础类型int,在一个运行中的方法的栈帧上占据了一些内存,则这个对象的内存将在方法运行完成且栈帧弹出时才被回收。引用类型的内存,比如`Strings`,可在不可达之后由JVM的垃圾收集器回收。 * #### 未引用(unreferenced) -参见[不可达](#unreachable)。 +参见[不可达](#不可达unreachable)。 * #### 值(value) Scala中的任何计算或表达式的结果都是一个 _值_,而Scala中的每个值都是一个对象。值这个术语本质上是指对象在内存中(在JVM堆或栈上)的镜像。 @@ -391,7 +390,7 @@ _值类型_ 是`AnyVal`的任意子类,像`Int`,`Double`或`Unit`。该术 指向对象的命名实体。变量要么是`val`,要么是 `var`,`val`变量和`var`变量在定义时都必须被初始化,但仅`var`变量可被重新赋值来指向不同对象。 * #### 型变(variance) -类或特质的类型参数可用 _型变_ 标号来做标记,即[协变](#covariant)(+)或[逆变](#contravariant)(-)。这样的型变标号表明了泛型类或特质的子类化是如何开展的,比如,泛型类`List`在其类型参数上是协变的,因此`List[String]`就是`List[Any]`的子类型。默认情况下,即缺少标号`+`或`-`的类型参数是[非协变](#nonvariant)的。 +类或特质的类型参数可用 _型变_ 标号来做标记,即[协变](#协变covariant)(+)或[逆变](#逆变contravariant)(-)。这样的型变标号表明了泛型类或特质的子类化是如何开展的,比如,泛型类`List`在其类型参数上是协变的,因此`List[String]`就是`List[Any]`的子类型。默认情况下,即缺少标号`+`或`-`的类型参数是[非协变](#非协变nonvariant)的。 * #### 产生(yield) -表达式可以 _产生_ 结果。`yield`关键字指定了[for推解式](#for-comprehension)的结果。 +表达式可以 _产生_ 结果。`yield`关键字指定了[for推解式](#for推解式for-comprehension)的结果。 From 72add3cf5f67110884e1243dd5beb973de4b081d Mon Sep 17 00:00:00 2001 From: Dongxu Wang Date: Fri, 28 Jun 2019 14:53:56 +0800 Subject: [PATCH 0646/3174] Fix typo for internal hashes. --- _zh-cn/glossary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/glossary/index.md b/_zh-cn/glossary/index.md index 60df57c6eb..393593654d 100644 --- a/_zh-cn/glossary/index.md +++ b/_zh-cn/glossary/index.md @@ -309,7 +309,7 @@ XML数据就是半结构化的,因其相比于普通的二进制文件或文 _签名_ 是[类型签名](#类型签名type-signature)的简写。 * #### 单例对象(singleton object) -由object关键字定义的对象。每个单例对象有且仅有一个实例。与某个类共享名称且与这个类定义在同一源文件中的单例对象,叫这个类的[伴随对象](#伴随对象companion-object),类则叫单列对象的[伴随类](#伴随类companion-class)。无伴随类的单例对象叫[独立对象](#独立对象standalone-object)。 +由object关键字定义的对象。每个单例对象有且仅有一个实例。与某个类共享名称且与这个类定义在同一源文件中的单例对象,叫这个类的[伴生对象](#伴生对象companion-object),类则叫单列对象的[伴生类](#伴生类companion-class)。无伴随类的单例对象叫[独立对象](#独立对象standalone-object)。 * #### 独立对象(standalone object) 没有[伴生类](#伴生类companion-class)的[单例对象](#单例对象singleton-object)。 From 60011d873bfcd15b38e6445ccb51c32de28e9377 Mon Sep 17 00:00:00 2001 From: Anastasia Ostretsova Date: Fri, 28 Jun 2019 20:28:21 +0300 Subject: [PATCH 0647/3174] Translate "Partial application" part into russian --- _ru/tour/multiple-parameter-lists.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/_ru/tour/multiple-parameter-lists.md b/_ru/tour/multiple-parameter-lists.md index d1938cb4b0..f58066b0e8 100644 --- a/_ru/tour/multiple-parameter-lists.md +++ b/_ru/tour/multiple-parameter-lists.md @@ -78,3 +78,20 @@ numbers.foldRight(0)(_+_) // Форма с каррированием def execute(arg: Int)(implicit ec: ExecutionContext) = ??? ``` +#### Частичное применение + Когда метод вызывается с меньшим количеством списков параметров, то результатом будет функция, + которая принимает в качестве параметров недостающие списки. Это официально известно как + [частичное применение](https://ru.wikipedia.org/wiki/%D0%A7%D0%B0%D1%81%D1%82%D0%B8%D1%87%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5). + + Например, + + ```tut + val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + val numberFunc = numbers.foldLeft(List[Int]()) _ + + val squares = numberFunc((xs, x) => xs :+ x*x) + print(squares) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) + + val cubes = numberFunc((xs, x) => xs :+ x*x*x) + print(cubes) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000) + ``` \ No newline at end of file From e26fc4b0de48b9e7dee9eb545350c446f0000d49 Mon Sep 17 00:00:00 2001 From: Guannan Wei Date: Fri, 28 Jun 2019 17:08:16 -0400 Subject: [PATCH 0648/3174] update the compiler plugin example to Scala 2.13 --- _overviews/plugins/index.md | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/_overviews/plugins/index.md b/_overviews/plugins/index.md index 3b11e43164..ff9e3ffdc6 100644 --- a/_overviews/plugins/index.md +++ b/_overviews/plugins/index.md @@ -99,11 +99,6 @@ There are several steps to making the plugin. First you need to write and compile the source of the plugin itself. Here is the source code for it: - // IMPORTANT: - // this code was written for Scala 2.8. - // it needs to be updated for Scala 2.12. - // the changes required are modest. - package localhost import scala.tools.nsc @@ -126,11 +121,11 @@ it: def newPhase(_prev: Phase) = new DivByZeroPhase(_prev) class DivByZeroPhase(prev: Phase) extends StdPhase(prev) { override def name = DivByZero.this.name - def apply(unit: CompilationUnit) { + def apply(unit: CompilationUnit): Unit = { for ( tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body if rcvr.tpe <:< definitions.IntClass.tpe) { - unit.error(tree.pos, "definitely division by zero") + global.reporter.error(tree.pos, "definitely division by zero") } } } @@ -276,11 +271,6 @@ sure you got the help string looking right. Here is a complete plugin that has an option. This plugin has no behavior other than to print out its option. - // IMPORTANT: - // this code was written for Scala 2.8. - // it needs to be updated for Scala 2.12. - // the changes required are modest. - package localhost import scala.tools.nsc @@ -298,7 +288,7 @@ behavior other than to print out its option. var level = 1000000 - override def processOptions(options: List[String], error: String => Unit) { + override def processOptions(options: List[String], error: String => Unit): Unit = { for (option <- options) { if (option.startsWith("level:")) { level = option.substring("level:".length).toInt @@ -313,15 +303,13 @@ behavior other than to print out its option. private object Component extends PluginComponent { val global: Silly.this.global.type = Silly.this.global - val runsAfter = "refchecks" - // Using the Scala Compiler 2.8.x the runsAfter should be written as shown below - // val runsAfter = List[String]("refchecks"); + val runsAfter = List[String]("refchecks"); val phaseName = Silly.this.name def newPhase(_prev: Phase) = new SillyPhase(_prev) class SillyPhase(prev: Phase) extends StdPhase(prev) { override def name = Silly.this.name - def apply(unit: CompilationUnit) { + def apply(unit: CompilationUnit): Unit = { println("Silliness level: " + level) } } From 61cbc3266b2d32e23d689151a4ad53b1e056c57a Mon Sep 17 00:00:00 2001 From: Anastasia Ostretsova Date: Sat, 29 Jun 2019 13:06:37 +0300 Subject: [PATCH 0649/3174] Leave just an example --- _ru/tour/multiple-parameter-lists.md | 33 ++++++++++++---------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/_ru/tour/multiple-parameter-lists.md b/_ru/tour/multiple-parameter-lists.md index f58066b0e8..019f17d77d 100644 --- a/_ru/tour/multiple-parameter-lists.md +++ b/_ru/tour/multiple-parameter-lists.md @@ -15,6 +15,19 @@ previous-page: nested-functions Методы могут объявляться с несколькими списками параметров. При этом когда такой метод вызывается с меньшим количеством списков параметров, это приводит к созданию новой функции, которая ожидает на вход не достающий список параметров. Формально это называется [частичное применение](https://en.wikipedia.org/wiki/Partial_application). +Например, + + ```tut + val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + val numberFunc = numbers.foldLeft(List[Int]()) _ + + val squares = numberFunc((xs, x) => xs :+ x*x) + print(squares) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) + + val cubes = numberFunc((xs, x) => xs :+ x*x*x) + print(cubes) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000) + ``` + Рассмотрим такие примеры из класса [Traversable](/overviews/collections/trait-traversable.html) коллекции Scala: ``` @@ -76,22 +89,4 @@ numbers.foldRight(0)(_+_) // Форма с каррированием ``` def execute(arg: Int)(implicit ec: ExecutionContext) = ??? -``` - -#### Частичное применение - Когда метод вызывается с меньшим количеством списков параметров, то результатом будет функция, - которая принимает в качестве параметров недостающие списки. Это официально известно как - [частичное применение](https://ru.wikipedia.org/wiki/%D0%A7%D0%B0%D1%81%D1%82%D0%B8%D1%87%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5). - - Например, - - ```tut - val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - val numberFunc = numbers.foldLeft(List[Int]()) _ - - val squares = numberFunc((xs, x) => xs :+ x*x) - print(squares) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) - - val cubes = numberFunc((xs, x) => xs :+ x*x*x) - print(cubes) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000) - ``` \ No newline at end of file +``` \ No newline at end of file From 2feaa411073aa8d3ca96afad92f8fc00b14ff71c Mon Sep 17 00:00:00 2001 From: Dima Kotobotov Date: Sat, 29 Jun 2019 20:07:32 +0300 Subject: [PATCH 0650/3174] :pencil2: Fixing typos. --- _overviews/collections-2.13/equality.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/collections-2.13/equality.md b/_overviews/collections-2.13/equality.md index 42137a43ca..68f5f4141c 100644 --- a/_overviews/collections-2.13/equality.md +++ b/_overviews/collections-2.13/equality.md @@ -31,4 +31,4 @@ It does not matter for the equality check whether a collection is mutable or imm java.util.NoSuchElementException: key not found: ArrayBuffer(2, 2, 3) -In this example, the selection in the last line will most likely fail because the hash-code of the array `xs` has changed in the second-to-last line. Therefore, the hash-code-based lookup will look at a different place than the one where `xs` was stored. +In this example, the selection in the last line will most likely fail because the hash-code of the array `buf` has changed in the second-to-last line. Therefore, the hash-code-based lookup will look at a different place than the one where `buf` was stored. From f749e02964f2155db205a66c60e1cf6d242a5580 Mon Sep 17 00:00:00 2001 From: Taketo Iseki Date: Mon, 1 Jul 2019 20:14:23 +0900 Subject: [PATCH 0651/3174] translate tour/automatic-closures into Japanese --- _ja/tour/automatic-closures.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 29ae0a8c00..3bb7fa6935 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -1,6 +1,6 @@ --- layout: tour -title: Automatic Type-Dependent Closure Construction +title: 型依存クロージャの自動構築 language: ja discourse: true @@ -8,9 +8,9 @@ discourse: true partof: scala-tour --- -Scala allows parameterless function names as parameters of methods. When such a method is called, the actual parameters for parameterless function names are not evaluated and a nullary function is passed instead which encapsulates the computation of the corresponding parameter (so-called *call-by-name* evaluation). +Scalaはメソッドのパラメータにパラメータを受け取らない関数名が使えます。このようなメソッドが呼び出される時、パラメータを受け取らない関数名は実際に評価されず、代わりに対応するパラメーターの処理をカプセル化した、引数を取らない関数が渡されます(そのため *名前渡し*評価と呼ばれます)。 -The following code demonstrates this mechanism: +以下のコードはこの仕組みを説明しています。 object TargetTest1 extends Application { def whileLoop(cond: => Boolean)(body: => Unit): Unit = @@ -25,11 +25,11 @@ The following code demonstrates this mechanism: } } -The function whileLoop takes two parameters `cond` and `body`. When the function is applied, the actual parameters do not get evaluated. But whenever the formal parameters are used in the body of `whileLoop`, the implicitly created nullary functions will be evaluated instead. Thus, our method `whileLoop` implements a Java-like while-loop with a recursive implementation scheme. +関数 whileLoop は2つのパラメータ`cond`と`body`を受け取ります。関数が適用される時、実際のパラメータは評価されません。しかし形式上のパラメータが`whileLoop`の本体内で使われる度に、暗黙に生成された引数の無い関数が代わりに評価されます。このようにメソッド`whileLoop`はJavaのようなwhileループを再帰的な実装案で実装しています。 -We can combine the use of [infix/postfix operators](operators.html) with this mechanism to create more complex statements (with a nice syntax). +[中置/後置 演算子](operators.html)とこのメカニズムを組み合わせ利用し、より複雑な式を(より良い構文で)が作れます。 -Here is the implementation of a loop-unless statement: +こちらがloop-unless式の実装です。 object TargetTest2 extends Application { def loop(body: => Unit): LoopUnlessCond = @@ -46,9 +46,9 @@ Here is the implementation of a loop-unless statement: i -= 1 } unless (i == 0) } -The `loop` function just accepts a body of a loop and returns an instance of class `LoopUnlessCond` (which encapsulates this body object). Note that the body didn't get evaluated yet. Class `LoopUnlessCond` has a method `unless` which we can use as a *infix operator*. This way, we achieve a quite natural syntax for our new loop: `loop { < stats > } unless ( < cond > )`. +この`loop`関数はループ処理の本体を受け取り、クラス`LoopUnlessCond`(bodyのオブジェクトをカプセル化する)のインスタンスを返すだけです。bodyはまだ評価されていないことに気をつけてください。クラス`LoopUnlessCond`は中置演算子として使えるメソッド`unless`を持ちます。このようにより自然な構文で新しいループ処理`loop { < stats > } unless ( < cond > )`を作れます。 -Here's the output when `TargetTest2` gets executed: +こちらが`TargetTest2`を実行した時の出力です。 i = 10 i = 9 From 7c9abb1eee083ad094cc72b1b15bc656fa41a919 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 1 Jul 2019 17:17:33 +0200 Subject: [PATCH 0652/3174] =?UTF-8?q?Move=20guides=20of=202.12=E2=80=99s?= =?UTF-8?q?=20collections=20to=20the=20=E2=80=9CLegacy=E2=80=9D=20category?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove the Scala version number from the title of the current collection guide. --- _data/overviews.yml | 104 ++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/_data/overviews.yml b/_data/overviews.yml index bfc4c293ed..c84a29131c 100644 --- a/_data/overviews.yml +++ b/_data/overviews.yml @@ -2,7 +2,7 @@ - category: Standard Library description: "Guides and overviews covering the Scala standard library." overviews: - - title: Scala 2.13’s Collections + - title: Scala Collections by: Martin Odersky and Julien Richard-Foy icon: sitemap url: "collections-2.13/introduction.html" @@ -40,68 +40,21 @@ url: "core/collections-migration-213.html" description: "This page describes the main changes for collection users that migrate to Scala 2.13 and shows how to cross-build projects with Scala 2.11 / 2.12 and 2.13." - - title: The Architecture of Scala 2.13’s Collections + - title: The Architecture of Scala Collections icon: sitemap url: "core/architecture-of-scala-213-collections.html" by: Julien Richard-Foy description: "These pages describe the architecture of the collections framework introduced in Scala 2.13. Compared to the Collections API you will find out more about the internal workings of the framework." - - title: Implementing Custom Collections (Scala 2.13) + - title: Implementing Custom Collections icon: building url: "core/custom-collections.html" by: Martin Odersky, Lex Spoon and Julien Richard-Foy description: "In this document you will learn how the collections framework helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - - title: Adding Custom Collection Operations (Scala 2.13) + - title: Adding Custom Collection Operations icon: building url: "core/custom-collection-operations.html" by: Julien Richard-Foy description: "This guide shows how to write operations that can be applied to any collection type and return the same collection type, and how to write operations that can be parameterized by the type of collection to build." - - title: Scala 2.8 to 2.12’s Collections - by: Martin Odersky - icon: sitemap - url: "collections/introduction.html" - description: "Scala's Collection Library." - subdocs: - - title: Introduction - url: "collections/introduction.html" - - title: Mutable and Immutable Collections - url: "collections/overview.html" - - title: Trait Traversable - url: "collections/trait-traversable.html" - - title: Trait Iterable - url: "collections/trait-iterable.html" - - title: The sequence traits Seq, IndexedSeq, and LinearSeq - url: "collections/seqs.html" - - title: Sets - url: "collections/sets.html" - - title: Maps - url: "collections/maps.html" - - title: Concrete Immutable Collection Classes - url: "collections/concrete-immutable-collection-classes.html" - - title: Concrete Mutable Collection Classes - url: "collections/concrete-mutable-collection-classes.html" - - title: Arrays - url: "collections/arrays.html" - - title: Strings - url: "collections/strings.html" - - title: Performance Characteristics - url: "collections/performance-characteristics.html" - - title: Equality - url: "collections/equality.html" - - title: Views - url: "collections/views.html" - - title: Iterators - url: "collections/iterators.html" - - title: Creating Collections From Scratch - url: "collections/creating-collections-from-scratch.html" - - title: Conversions Between Java and Scala Collections - url: "collections/conversions-between-java-and-scala-collections.html" - - title: Migrating from Scala 2.7 - url: "collections/migrating-from-scala-27.html" - - title: The Architecture of Scala 2.8 to 2.12’s Collections - icon: building - url: "core/architecture-of-scala-collections.html" - by: Martin Odersky and Lex Spoon - description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." - category: Language description: "Guides and overviews covering features in the Scala language." @@ -303,7 +256,7 @@ - category: Legacy - description: "Guides covering features no longer relevant to recent Scala versions (2.11+)." + description: "Guides covering features no longer relevant to recent Scala versions (2.12+)." overviews: - title: The Scala Actors Migration Guide by: Vojin Jovanovic and Philipp Haller @@ -317,3 +270,50 @@ description: "This guide describes the API of the scala.actors package of Scala 2.8/2.9. The organization follows groups of types that logically belong together. The trait hierarchy is taken into account to structure the individual sections. The focus is on the run-time behavior of the various methods that these traits define, thereby complementing the existing Scaladoc-based API documentation." label-color: "#899295" label-text: deprecated + - title: Scala 2.8 to 2.12’s Collections + by: Martin Odersky + icon: sitemap + url: "collections/introduction.html" + description: "Scala's Collection Library." + subdocs: + - title: Introduction + url: "collections/introduction.html" + - title: Mutable and Immutable Collections + url: "collections/overview.html" + - title: Trait Traversable + url: "collections/trait-traversable.html" + - title: Trait Iterable + url: "collections/trait-iterable.html" + - title: The sequence traits Seq, IndexedSeq, and LinearSeq + url: "collections/seqs.html" + - title: Sets + url: "collections/sets.html" + - title: Maps + url: "collections/maps.html" + - title: Concrete Immutable Collection Classes + url: "collections/concrete-immutable-collection-classes.html" + - title: Concrete Mutable Collection Classes + url: "collections/concrete-mutable-collection-classes.html" + - title: Arrays + url: "collections/arrays.html" + - title: Strings + url: "collections/strings.html" + - title: Performance Characteristics + url: "collections/performance-characteristics.html" + - title: Equality + url: "collections/equality.html" + - title: Views + url: "collections/views.html" + - title: Iterators + url: "collections/iterators.html" + - title: Creating Collections From Scratch + url: "collections/creating-collections-from-scratch.html" + - title: Conversions Between Java and Scala Collections + url: "collections/conversions-between-java-and-scala-collections.html" + - title: Migrating from Scala 2.7 + url: "collections/migrating-from-scala-27.html" + - title: The Architecture of Scala 2.8 to 2.12’s Collections + icon: building + url: "core/architecture-of-scala-collections.html" + by: Martin Odersky and Lex Spoon + description: "These pages describe the architecture of the Scala collections framework in detail. Compared to the Collections API you will find out more about the internal workings of the framework. You will also learn how this architecture helps you define your own collections in a few lines of code, while reusing the overwhelming part of collection functionality from the framework." From 9a29e0c37f857dca7a712fd43b01ba4379b5ef15 Mon Sep 17 00:00:00 2001 From: take2 Date: Wed, 3 Jul 2019 01:09:30 +0900 Subject: [PATCH 0653/3174] Update _ja/tour/automatic-closures.md Co-Authored-By: Masanori Fujita --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 3bb7fa6935..3d21d052cd 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -8,7 +8,7 @@ discourse: true partof: scala-tour --- -Scalaはメソッドのパラメータにパラメータを受け取らない関数名が使えます。このようなメソッドが呼び出される時、パラメータを受け取らない関数名は実際に評価されず、代わりに対応するパラメーターの処理をカプセル化した、引数を取らない関数が渡されます(そのため *名前渡し*評価と呼ばれます)。 +Scalaはメソッドのパラメータとしてパラメータ無しの関数名を渡せます。そのようなメソッドが呼ばれると、パラメータ無しの関数名は実際に評価されず、代わりに対応するパラメーターの処理をカプセル化した、引数無しの関数が渡されます(いわゆる *名前渡し*評価です)。 以下のコードはこの仕組みを説明しています。 From 35e386e93a6aa6465514fab1f652501c31e6f166 Mon Sep 17 00:00:00 2001 From: take2 Date: Wed, 3 Jul 2019 01:09:55 +0900 Subject: [PATCH 0654/3174] Update _ja/tour/automatic-closures.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 実装案 => 方法 Co-Authored-By: Masanori Fujita --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 3d21d052cd..1d190d4cae 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -25,7 +25,7 @@ Scalaはメソッドのパラメータとしてパラメータ無しの関数名 } } -関数 whileLoop は2つのパラメータ`cond`と`body`を受け取ります。関数が適用される時、実際のパラメータは評価されません。しかし形式上のパラメータが`whileLoop`の本体内で使われる度に、暗黙に生成された引数の無い関数が代わりに評価されます。このようにメソッド`whileLoop`はJavaのようなwhileループを再帰的な実装案で実装しています。 +関数 whileLoop は2つのパラメータ`cond`と`body`を受け取ります。関数が適用される時、実際のパラメータは評価されません。しかし形式上のパラメータが`whileLoop`の本体内で使われる度に、暗黙に生成された引数の無い関数が代わりに評価されます。このようにメソッド`whileLoop`はJavaのようなwhileループを再帰的な方法で実装しています。 [中置/後置 演算子](operators.html)とこのメカニズムを組み合わせ利用し、より複雑な式を(より良い構文で)が作れます。 From 6a0d6ea2492a0ba551ac9db86277354d4a17be48 Mon Sep 17 00:00:00 2001 From: take2 Date: Wed, 3 Jul 2019 01:10:14 +0900 Subject: [PATCH 0655/3174] Update _ja/tour/automatic-closures.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不要ながを削除 Co-Authored-By: Masanori Fujita --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 1d190d4cae..a12b8e8742 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -27,7 +27,7 @@ Scalaはメソッドのパラメータとしてパラメータ無しの関数名 関数 whileLoop は2つのパラメータ`cond`と`body`を受け取ります。関数が適用される時、実際のパラメータは評価されません。しかし形式上のパラメータが`whileLoop`の本体内で使われる度に、暗黙に生成された引数の無い関数が代わりに評価されます。このようにメソッド`whileLoop`はJavaのようなwhileループを再帰的な方法で実装しています。 -[中置/後置 演算子](operators.html)とこのメカニズムを組み合わせ利用し、より複雑な式を(より良い構文で)が作れます。 +[中置/後置 演算子](operators.html)とこのメカニズムを組み合わせ利用し、より複雑な式を(より良い構文で)作れます。 こちらがloop-unless式の実装です。 From 3d67daf99b56fbef8c7dd45d847f23caeec12548 Mon Sep 17 00:00:00 2001 From: take2 Date: Wed, 3 Jul 2019 01:14:37 +0900 Subject: [PATCH 0656/3174] Update _ja/tour/automatic-closures.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bodyは素直に概念の説明にした方が日本語が読みやすい Co-Authored-By: Masanori Fujita --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index a12b8e8742..0b865b72fd 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -46,7 +46,7 @@ Scalaはメソッドのパラメータとしてパラメータ無しの関数名 i -= 1 } unless (i == 0) } -この`loop`関数はループ処理の本体を受け取り、クラス`LoopUnlessCond`(bodyのオブジェクトをカプセル化する)のインスタンスを返すだけです。bodyはまだ評価されていないことに気をつけてください。クラス`LoopUnlessCond`は中置演算子として使えるメソッド`unless`を持ちます。このようにより自然な構文で新しいループ処理`loop { < stats > } unless ( < cond > )`を作れます。 +この`loop`関数はループ処理の本体を受け取り、クラス`LoopUnlessCond`(この処理の本体をカプセル化する)のインスタンスを返すだけです。処理の本体はまだ評価されていないことに気をつけてください。クラス`LoopUnlessCond`は *中置演算子* として使えるメソッド`unless`を持ちます。このように、新しいループ処理: `loop { < stats > } unless ( < cond > )`のとても自然な構文を作れます。 こちらが`TargetTest2`を実行した時の出力です。 From 6e5434acba1e4ca38b33c31ccdad0924052ec17c Mon Sep 17 00:00:00 2001 From: Suraj Gharat Date: Wed, 3 Jul 2019 15:00:49 +0530 Subject: [PATCH 0657/3174] Update futures.md Correcting a statement that incorrectly refers future instead of promise. --- _overviews/core/futures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/core/futures.md b/_overviews/core/futures.md index a0eea92daf..9546e86c33 100644 --- a/_overviews/core/futures.md +++ b/_overviews/core/futures.md @@ -841,7 +841,7 @@ for a more precise description of the semantics. ## Promises So far we have only considered `Future` objects created by -asynchronous computations started using the `future` method. +asynchronous computations started using the `Future` method. However, futures can also be created using *promises*. While futures are defined as a type of read-only placeholder object @@ -935,7 +935,7 @@ has not been completed yet (e.g., there are several HTTP requests being executed from several different futures and the client is interested only in the first HTTP response - corresponding to the first future to complete the promise). For these reasons methods `tryComplete`, -`trySuccess` and `tryFailure` exist on future. The client should be +`trySuccess` and `tryFailure` exist on promise. The client should be aware that using these methods results in programs which are not deterministic, but depend on the execution schedule. From 131a53b860396a4f3392b57513eee368aafdecb4 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Wed, 3 Jul 2019 05:41:16 -0400 Subject: [PATCH 0658/3174] Fix page title for cheatsheet --- _ba/cheatsheets/index.md | 2 +- _fr/cheatsheets/index.md | 2 +- _ja/cheatsheets/index.md | 2 +- _overviews/cheatsheets/index.md | 2 +- _pt-br/cheatsheets/index.md | 2 +- _ru/cheatsheets/index.md | 2 +- _th/cheatsheets/index.md | 2 +- _zh-cn/cheatsheets/index.md | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/_ba/cheatsheets/index.md b/_ba/cheatsheets/index.md index 0a7e59790f..c311bf4b1e 100644 --- a/_ba/cheatsheets/index.md +++ b/_ba/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_fr/cheatsheets/index.md b/_fr/cheatsheets/index.md index 9cb47c6f8d..a75cc71141 100644 --- a/_fr/cheatsheets/index.md +++ b/_fr/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_ja/cheatsheets/index.md b/_ja/cheatsheets/index.md index b133ef48e4..cf7d670ced 100644 --- a/_ja/cheatsheets/index.md +++ b/_ja/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_overviews/cheatsheets/index.md b/_overviews/cheatsheets/index.md index 42c2b9c06b..07d96b55c8 100644 --- a/_overviews/cheatsheets/index.md +++ b/_overviews/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_pt-br/cheatsheets/index.md b/_pt-br/cheatsheets/index.md index 5d3176bda0..27e64f8d74 100644 --- a/_pt-br/cheatsheets/index.md +++ b/_pt-br/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_ru/cheatsheets/index.md b/_ru/cheatsheets/index.md index 83d2e9d7c4..98b883f9e4 100644 --- a/_ru/cheatsheets/index.md +++ b/_ru/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_th/cheatsheets/index.md b/_th/cheatsheets/index.md index 0b2faca68b..26b27062da 100644 --- a/_th/cheatsheets/index.md +++ b/_th/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet diff --git a/_zh-cn/cheatsheets/index.md b/_zh-cn/cheatsheets/index.md index 6fe47a86b2..b8178b3fd3 100644 --- a/_zh-cn/cheatsheets/index.md +++ b/_zh-cn/cheatsheets/index.md @@ -1,6 +1,6 @@ --- layout: cheatsheet -title: Scalacheat +title: Scala Cheatsheet partof: cheatsheet From 7290a257267acbc58ebe6be55df9dea0e6a07062 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Wed, 3 Jul 2019 06:46:06 -0400 Subject: [PATCH 0659/3174] Add contributing page for Scaladoc Move off of overview page. Mention Dottydoc. --- _overviews/scaladoc/contribute.md | 28 ++++++++++++++++++++++++++++ _overviews/scaladoc/overview.md | 11 ----------- 2 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 _overviews/scaladoc/contribute.md diff --git a/_overviews/scaladoc/contribute.md b/_overviews/scaladoc/contribute.md new file mode 100644 index 0000000000..e7fa785616 --- /dev/null +++ b/_overviews/scaladoc/contribute.md @@ -0,0 +1,28 @@ +--- +layout: multipage-overview +title: Contributing to Scaladoc + +discourse: true + +partof: scaladoc +overview-name: Scaladoc + +num: 5 + +permalink: /overviews/scaladoc/:title.html +--- + +If you are interested in contributing to the API documentation of the Scala +standard library (the documentation generated by Scaladoc), please read +[Generating Scaladoc]({{ site.baseurl }}/overviews/scaladoc/generate.html) and +[Scaladoc for Library Authors]({{ site.baseurl }}/overviews/scaladoc/basics.html) first. + +If you'd like to contribute to the actual Scaladoc documentation generation +tool itself, then please see the +[Hacker Set Up Guide](http://scala-lang.org/contribute/hacker-guide.html#2-set-up) +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. \ No newline at end of file diff --git a/_overviews/scaladoc/overview.md b/_overviews/scaladoc/overview.md index b31aea8ef5..92426fa0bf 100644 --- a/_overviews/scaladoc/overview.md +++ b/_overviews/scaladoc/overview.md @@ -22,14 +22,3 @@ There are three aspects of Scaladoc documentation: - **[Using the Scaladoc interface]({{ site.baseurl }}/overviews/scaladoc/interface.html)** – how to navigate and use generated Scaladoc documentation to learn more about a library. - **[Scaladoc for Library Authors]({{ site.baseurl }}/overviews/scaladoc/for-library-authors.html)** – how to add Scaladoc comments to generate documentation for your library. - **[Generating documentation for your library with Scaladoc]({{ site.baseurl }}/overviews/scaladoc/generate.html)** – how to use Scaladoc to generate documentation for your library. - -### Contributing to Scaladoc - -If you are interested in contributing to the API documentation of the Scala -standard library (the documentation generated by Scaladoc), please read the -[Scaladoc for Library Authors]({{ site.baseurl }}/overviews/scaladoc/basics.html) first. - -If you'd like to contribute to the actual Scaladoc documentation generation -tool itself, then please see the -[Hacker Set Up Guide](http://scala-lang.org/contribute/hacker-guide.html#2_set_up) -which covers the steps and workflow necessary work on the Scaladoc tool. From cb9c19f2f4225fadfc9029bb32335311aa322914 Mon Sep 17 00:00:00 2001 From: Parambir Singh Date: Thu, 4 Jul 2019 16:37:21 -0700 Subject: [PATCH 0660/3174] Update inner-classes.md Explicitly specify `Unit` return type in example code --- _tour/inner-classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_tour/inner-classes.md b/_tour/inner-classes.md index 172dd03bcd..fd99065542 100644 --- a/_tour/inner-classes.md +++ b/_tour/inner-classes.md @@ -21,7 +21,7 @@ To illustrate the difference, we quickly sketch the implementation of a graph da class Graph { class Node { var connectedNodes: List[Node] = Nil - def connectTo(node: Node) { + def connectTo(node: Node): Unit = { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } @@ -65,7 +65,7 @@ The type `graph1.Node` is distinct from the type `graph2.Node`. In Java, the las class Graph { class Node { var connectedNodes: List[Graph#Node] = Nil - def connectTo(node: Graph#Node) { + def connectTo(node: Graph#Node): Unit = { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } From edce11e76d7c3599d78d4d6b11aa89d40c530f03 Mon Sep 17 00:00:00 2001 From: take2 Date: Fri, 5 Jul 2019 12:51:56 +0900 Subject: [PATCH 0661/3174] Update _ja/tour/automatic-closures.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 「代わりに」の意味を明確にするため句点を追加 Co-Authored-By: TATSUNO Yasuhiro --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index 0b865b72fd..e40a3202fd 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -8,7 +8,7 @@ discourse: true partof: scala-tour --- -Scalaはメソッドのパラメータとしてパラメータ無しの関数名を渡せます。そのようなメソッドが呼ばれると、パラメータ無しの関数名は実際に評価されず、代わりに対応するパラメーターの処理をカプセル化した、引数無しの関数が渡されます(いわゆる *名前渡し*評価です)。 +Scalaはメソッドのパラメータとしてパラメータ無しの関数名を渡せます。そのようなメソッドが呼ばれると、パラメータ無しの関数名は実際に評価されず、代わりに、対応するパラメーターの処理をカプセル化した、引数無しの関数が渡されます(いわゆる *名前渡し*評価です)。 以下のコードはこの仕組みを説明しています。 From c8441a92ed310a6d37c128fadb58ca7df8ab7b9e Mon Sep 17 00:00:00 2001 From: take2 Date: Fri, 5 Jul 2019 12:55:56 +0900 Subject: [PATCH 0662/3174] Update _ja/tour/automatic-closures.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit statementは「式」ではなく「文」、文章の流れ的に「命令文」がより適切 Co-Authored-By: TATSUNO Yasuhiro --- _ja/tour/automatic-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/automatic-closures.md b/_ja/tour/automatic-closures.md index e40a3202fd..3b38e98178 100644 --- a/_ja/tour/automatic-closures.md +++ b/_ja/tour/automatic-closures.md @@ -27,7 +27,7 @@ Scalaはメソッドのパラメータとしてパラメータ無しの関数名 関数 whileLoop は2つのパラメータ`cond`と`body`を受け取ります。関数が適用される時、実際のパラメータは評価されません。しかし形式上のパラメータが`whileLoop`の本体内で使われる度に、暗黙に生成された引数の無い関数が代わりに評価されます。このようにメソッド`whileLoop`はJavaのようなwhileループを再帰的な方法で実装しています。 -[中置/後置 演算子](operators.html)とこのメカニズムを組み合わせ利用し、より複雑な式を(より良い構文で)作れます。 +[中置/後置 演算子](operators.html)とこのメカニズムを組み合わせて利用し、より複雑な命令文を(より良い構文で)作れます。 こちらがloop-unless式の実装です。 From 99ce16089c0874e4eba958cbcadb67f59533e442 Mon Sep 17 00:00:00 2001 From: Dima Kotobotov Date: Fri, 5 Jul 2019 00:34:44 +0300 Subject: [PATCH 0663/3174] :pencil2: Fixing typos. --- _overviews/collections-2.13/iterators.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_overviews/collections-2.13/iterators.md b/_overviews/collections-2.13/iterators.md index 55de58cb7e..7577377bb8 100644 --- a/_overviews/collections-2.13/iterators.md +++ b/_overviews/collections-2.13/iterators.md @@ -46,7 +46,7 @@ The other operations that `Iterator` has in common with `Iterable` have the same res4: Boolean = false As you can see, after the call to `it.map`, the `it` iterator hasn’t advanced to its end, but traversing the iterator -resulting from the call to `it.map` also traverses `it` and advances it to its end. +resulting from the call to `res1.foreach` also traverses `it` and advances it to its end. Another example is the `dropWhile` method, which can be used to find the first elements of an iterator that has a certain property. For instance, to find the first word in the iterator above that has at least two characters you could write: @@ -92,7 +92,7 @@ All operations on iterators are summarized below. | **Variations:** | | | `it.buffered` | A buffered iterator returning all elements of `it`. | | `it grouped size` | An iterator that yields the elements returned by `it` in fixed-sized sequence "chunks". | -| `xs sliding size` | An iterator that yields the elements returned by `it` in sequences representing a sliding fixed-sized window. | +| `it sliding size` | An iterator that yields the elements returned by `it` in sequences representing a sliding fixed-sized window. | | **Duplication:** | | | `it.duplicate` | A pair of iterators that each independently return all elements of `it`. | | **Additions:** | | @@ -100,7 +100,7 @@ All operations on iterators are summarized below. | `it.padTo(len, x)` | The iterator that first returns all elements of `it` and then follows that by copies of `x` until length `len` elements are returned overall. | | **Maps:** | | | `it map f` | The iterator obtained from applying the function `f` to every element returned from `it`. | -| `it flatMap f` | The iterator obtained from applying the iterator-valued function f to every element in `it` and appending the results. | +| `it flatMap f` | The iterator obtained from applying the iterator-valued function `f` to every element in `it` and appending the results. | | `it collect f` | The iterator obtained from applying the partial function `f` to every element in `it` for which it is defined and collecting the results. | | **Conversions:** | | | `it.toArray` | Collects the elements returned by `it` in an array. | @@ -118,7 +118,7 @@ All operations on iterators are summarized below. | `it.nonEmpty` | Test whether the collection contains elements (alias of `hasNext`). | | `it.size` | The number of elements returned by `it`. Note: `it` will be at its end after this operation! | | `it.length` | Same as `it.size`. | -| `xs.knownSize` |The number of elements, if this one is known without modifying the iterator’s state, otherwise `-1`. | +| `it.knownSize` |The number of elements, if this one is known without modifying the iterator’s state, otherwise `-1`. | | **Element Retrieval Index Search:**| | | `it find p` | An option containing the first element returned by `it` that satisfies `p`, or `None` is no element qualifies. Note: The iterator advances to after the element, or, if none is found, to the end. | | `it indexOf x` | The index of the first element returned by `it` that equals `x`. Note: The iterator advances past the position of this element. | @@ -157,7 +157,7 @@ All operations on iterators are summarized below. | **Update:** | | | `it.patch(i, jt, r)` | The iterator resulting from `it` by replacing `r` elements starting with `i` by the patch iterator `jt`. | | **Comparison:** | | -| `it sameElements jt` | A test whether iterators it and `jt` return the same elements in the same order. Note: Using the iterators after this operation is undefined and subject to change. | +| `it sameElements jt` | A test whether iterators `it` and `jt` return the same elements in the same order. Note: Using the iterators after this operation is undefined and subject to change. | | **Strings:** | | | `it.addString(b, start, sep, end)`| Adds a string to `StringBuilder` `b` which shows all elements returned by `it` between separators `sep` enclosed in strings `start` and `end`. `start`, `sep`, `end` are all optional. | | `it.mkString(start, sep, end)` | Converts the collection to a string which shows all elements returned by `it` between separators `sep` enclosed in strings `start` and `end`. `start`, `sep`, `end` are all optional. | From b24c5b23f55a03608d46848623eb2ff0f3575605 Mon Sep 17 00:00:00 2001 From: Philippus Date: Sun, 7 Jul 2019 17:36:40 +0200 Subject: [PATCH 0664/3174] Remove redirect_from from ja tour --- _ja/tour/abstract-type-members.md | 2 -- _ja/tour/annotations.md | 1 - _ja/tour/basics.md | 1 - _ja/tour/by-name-parameters.md | 1 - _ja/tour/case-classes.md | 1 - _ja/tour/classes.md | 1 - _ja/tour/compound-types.md | 1 - _ja/tour/default-parameter-values.md | 1 - _ja/tour/extractor-objects.md | 1 - _ja/tour/for-comprehensions.md | 1 - _ja/tour/generic-classes.md | 1 - _ja/tour/higher-order-functions.md | 1 - _ja/tour/implicit-conversions.md | 1 - _ja/tour/implicit-parameters.md | 1 - _ja/tour/inner-classes.md | 1 - _ja/tour/lower-type-bounds.md | 1 - _ja/tour/mixin-class-composition.md | 1 - _ja/tour/multiple-parameter-lists.md | 1 - _ja/tour/named-arguments.md | 1 - _ja/tour/nested-functions.md | 1 - _ja/tour/operators.md | 1 - _ja/tour/pattern-matching.md | 1 - _ja/tour/polymorphic-methods.md | 1 - _ja/tour/regular-expression-patterns.md | 1 - _ja/tour/self-types.md | 1 - _ja/tour/singleton-objects.md | 1 - _ja/tour/tour-of-scala.md | 1 - _ja/tour/traits.md | 1 - _ja/tour/tuples.md | 1 - _ja/tour/unified-types.md | 1 - _ja/tour/upper-type-bounds.md | 1 - _ja/tour/variances.md | 1 - 32 files changed, 33 deletions(-) diff --git a/_ja/tour/abstract-type-members.md b/_ja/tour/abstract-type-members.md index f5821a7b74..0a0a61f387 100644 --- a/_ja/tour/abstract-type-members.md +++ b/_ja/tour/abstract-type-members.md @@ -12,8 +12,6 @@ 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" --- トレイトや抽象クラスのような抽象型は抽象型メンバーを持つことができます。 diff --git a/_ja/tour/annotations.md b/_ja/tour/annotations.md index 88114954f1..5858105b01 100644 --- a/_ja/tour/annotations.md +++ b/_ja/tour/annotations.md @@ -11,7 +11,6 @@ num: 32 next-page: default-parameter-values previous-page: by-name-parameters -redirect_from: "/tutorials/tour/annotations.html" --- アノテーションはメタ情報と定義を関連づけます。例えば、メソッドの前のアノテーション`@deprecated`はメソッドが使われたらコンパイラに警告を出力させます。 diff --git a/_ja/tour/basics.md b/_ja/tour/basics.md index b14330f2b3..8eb67a0ddb 100644 --- a/_ja/tour/basics.md +++ b/_ja/tour/basics.md @@ -11,7 +11,6 @@ num: 2 next-page: unified-types previous-page: tour-of-scala -redirect_from: "/tutorials/tour/basics.html" --- このページでは、Scalaの基本を取り扱います。 diff --git a/_ja/tour/by-name-parameters.md b/_ja/tour/by-name-parameters.md index 86325795ba..411afa5957 100644 --- a/_ja/tour/by-name-parameters.md +++ b/_ja/tour/by-name-parameters.md @@ -11,7 +11,6 @@ num: 31 next-page: annotations previous-page: operators -redirect_from: "/tutorials/tour/by-name-parameters.html" --- *名前渡しのパラメータ*は使用された時に評価されます。それらは*値渡しパラメータ*とは対照的です。名前渡しのパラメータを作るには、単純に`=>`を型の前につけます。 diff --git a/_ja/tour/case-classes.md b/_ja/tour/case-classes.md index 99a1b6e6f0..5493a00790 100644 --- a/_ja/tour/case-classes.md +++ b/_ja/tour/case-classes.md @@ -12,7 +12,6 @@ next-page: pattern-matching previous-page: multiple-parameter-lists prerequisite-knowledge: classes, basics, mutability -redirect_from: "/tutorials/tour/case-classes.html" --- ケースクラスはこれから論じるいくつかの差異はあるものの普通のクラスと似ています。 diff --git a/_ja/tour/classes.md b/_ja/tour/classes.md index 0253f210f5..36cf3ec851 100644 --- a/_ja/tour/classes.md +++ b/_ja/tour/classes.md @@ -13,7 +13,6 @@ previous-page: unified-types topics: classes prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-interpolation, procedures -redirect_from: "/tutorials/tour/classes.html" --- Scalaにおけるクラスはオブジェクトを作るための設計図です。 diff --git a/_ja/tour/compound-types.md b/_ja/tour/compound-types.md index 6eeadc481d..061a5dc331 100644 --- a/_ja/tour/compound-types.md +++ b/_ja/tour/compound-types.md @@ -11,7 +11,6 @@ num: 24 next-page: self-types previous-page: abstract-type-members -redirect_from: "/tutorials/tour/compound-types.html" --- ときどき、あるオブジェクトの型が、複数の他の型のサブタイプであると表現する必要が生じます。 Scalaでは、これは*複合型*を用いて表現できます。複合型とはオブジェクトの型同士を重ねることです。 diff --git a/_ja/tour/default-parameter-values.md b/_ja/tour/default-parameter-values.md index fe2da78c75..dde76cdeaf 100644 --- a/_ja/tour/default-parameter-values.md +++ b/_ja/tour/default-parameter-values.md @@ -12,7 +12,6 @@ next-page: named-arguments previous-page: annotations prerequisite-knowledge: named-arguments, function syntax -redirect_from: "/tutorials/tour/default-parameter-values.html" --- Scalaはパラメータのデフォルト値を与えることができ、呼び出す側はこれらのパラメータを省略できます。 diff --git a/_ja/tour/extractor-objects.md b/_ja/tour/extractor-objects.md index 2b12283764..d3af5a18e7 100644 --- a/_ja/tour/extractor-objects.md +++ b/_ja/tour/extractor-objects.md @@ -11,7 +11,6 @@ num: 16 next-page: for-comprehensions previous-page: regular-expression-patterns -redirect_from: "/tutorials/tour/extractor-objects.html" --- 抽出子オブジェクトは`unapply`メソッドを持つオブジェクトです。 diff --git a/_ja/tour/for-comprehensions.md b/_ja/tour/for-comprehensions.md index 89bce4d42a..eccd124c8c 100644 --- a/_ja/tour/for-comprehensions.md +++ b/_ja/tour/for-comprehensions.md @@ -11,7 +11,6 @@ num: 17 next-page: generic-classes previous-page: extractor-objects -redirect_from: "/tutorials/tour/for-comprehensions.html" --- Scalaは*シーケンス内包表記*を表現するための軽量な記法を提供します。 diff --git a/_ja/tour/generic-classes.md b/_ja/tour/generic-classes.md index 2535e31695..7912d2be21 100644 --- a/_ja/tour/generic-classes.md +++ b/_ja/tour/generic-classes.md @@ -12,7 +12,6 @@ next-page: variances previous-page: for-comprehensions assumed-knowledge: classes unified-types -redirect_from: "/tutorials/tour/generic-classes.html" --- ジェネリッククラスはパラメータとして型を1つ受け取るクラスです。それらはコレクションクラスで特に役立ちます。 diff --git a/_ja/tour/higher-order-functions.md b/_ja/tour/higher-order-functions.md index 57714202e8..88d432aaf5 100644 --- a/_ja/tour/higher-order-functions.md +++ b/_ja/tour/higher-order-functions.md @@ -11,7 +11,6 @@ num: 8 next-page: nested-functions previous-page: mixin-class-composition -redirect_from: "/tutorials/tour/higher-order-functions.html" --- 高階関数は他の関数をパラメーターとして受け取る、もしくは結果として関数を返します。 diff --git a/_ja/tour/implicit-conversions.md b/_ja/tour/implicit-conversions.md index 386ed3c500..107979e2dc 100644 --- a/_ja/tour/implicit-conversions.md +++ b/_ja/tour/implicit-conversions.md @@ -11,7 +11,6 @@ num: 27 next-page: polymorphic-methods previous-page: implicit-parameters -redirect_from: "/tutorials/tour/implicit-conversions.html" --- 型`S`から型`T`への暗黙の変換は`S => T`という型のimplicit値や、その型に一致するimplicitメソッドで定義されます。 diff --git a/_ja/tour/implicit-parameters.md b/_ja/tour/implicit-parameters.md index 38067f9e27..53613be8ee 100644 --- a/_ja/tour/implicit-parameters.md +++ b/_ja/tour/implicit-parameters.md @@ -11,7 +11,6 @@ num: 26 next-page: implicit-conversions previous-page: self-types -redirect_from: "/tutorials/tour/implicit-parameters.html" --- メソッドは _暗黙の_ パラメータのリストを持つことができ、パラメータリストの先頭には _implicit_ キーワードで印をつけます。 diff --git a/_ja/tour/inner-classes.md b/_ja/tour/inner-classes.md index 4bc373d8c8..03450fdc14 100644 --- a/_ja/tour/inner-classes.md +++ b/_ja/tour/inner-classes.md @@ -11,7 +11,6 @@ num: 22 next-page: abstract-type-members previous-page: lower-type-bounds -redirect_from: "/tutorials/tour/inner-classes.html" --- Scalaではクラスが他のクラスをメンバーとして保持することが可能です。 diff --git a/_ja/tour/lower-type-bounds.md b/_ja/tour/lower-type-bounds.md index d461e31e5d..b6b98cebdb 100644 --- a/_ja/tour/lower-type-bounds.md +++ b/_ja/tour/lower-type-bounds.md @@ -12,7 +12,6 @@ next-page: inner-classes previous-page: upper-type-bounds prerequisite-knowledge: upper-type-bounds, generics, variance -redirect_from: "/tutorials/tour/lower-type-bounds.html" --- [上限型境界](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 9ec9fd65f4..c5d40ebe16 100644 --- a/_ja/tour/mixin-class-composition.md +++ b/_ja/tour/mixin-class-composition.md @@ -12,7 +12,6 @@ next-page: higher-order-functions previous-page: tuples prerequisite-knowledge: inheritance, traits, abstract-classes, unified-types -redirect_from: "/tutorials/tour/mixin-class-composition.html" --- ミックスインはクラスを構成するのに使われるトレイトです。 diff --git a/_ja/tour/multiple-parameter-lists.md b/_ja/tour/multiple-parameter-lists.md index a35bccf615..3cddffe859 100644 --- a/_ja/tour/multiple-parameter-lists.md +++ b/_ja/tour/multiple-parameter-lists.md @@ -11,7 +11,6 @@ num: 10 next-page: case-classes previous-page: nested-functions -redirect_from: "/tutorials/tour/multiple-parameter-lists.html" --- メソッドは複数のパラメータリストを持てます。 diff --git a/_ja/tour/named-arguments.md b/_ja/tour/named-arguments.md index b7f0ca82a2..eda94a0c8c 100644 --- a/_ja/tour/named-arguments.md +++ b/_ja/tour/named-arguments.md @@ -12,7 +12,6 @@ next-page: packages-and-imports previous-page: default-parameter-values prerequisite-knowledge: function-syntax -redirect_from: "/tutorials/tour/named-arguments.html" --- メソッドを呼ぶ時、以下のように引数にパラメータ名でラベル付が可能です。 diff --git a/_ja/tour/nested-functions.md b/_ja/tour/nested-functions.md index 05a57a2fae..2769c20674 100644 --- a/_ja/tour/nested-functions.md +++ b/_ja/tour/nested-functions.md @@ -11,7 +11,6 @@ num: 9 next-page: multiple-parameter-lists previous-page: higher-order-functions -redirect_from: "/tutorials/tour/nested-functions.html" --- Scalaではメソッドの定義をネストする(_訳注:入れ子にする_)ことができます。 diff --git a/_ja/tour/operators.md b/_ja/tour/operators.md index b61b229558..e6c2352ef2 100644 --- a/_ja/tour/operators.md +++ b/_ja/tour/operators.md @@ -12,7 +12,6 @@ next-page: by-name-parameters previous-page: type-inference prerequisite-knowledge: case-classes -redirect_from: "/tutorials/tour/operators.html" --- Scalaでは演算子はメソッドです。パラメータを1つだけ持つメソッドであれば*中置演算子*として使えます。例えば、`+`はドット記法で呼び出せます。 diff --git a/_ja/tour/pattern-matching.md b/_ja/tour/pattern-matching.md index d44d13e41b..dd032ed48e 100644 --- a/_ja/tour/pattern-matching.md +++ b/_ja/tour/pattern-matching.md @@ -13,7 +13,6 @@ next-page: singleton-objects previous-page: case-classes prerequisite-knowledge: case-classes, string-interpolation, subtyping -redirect_from: "/tutorials/tour/pattern-matching.html" --- パターンマッチングは値をパターンに照合するための仕組みです。 diff --git a/_ja/tour/polymorphic-methods.md b/_ja/tour/polymorphic-methods.md index 0770657246..7eac75ff39 100644 --- a/_ja/tour/polymorphic-methods.md +++ b/_ja/tour/polymorphic-methods.md @@ -13,7 +13,6 @@ next-page: type-inference previous-page: implicit-conversions prerequisite-knowledge: unified-types -redirect_from: "/tutorials/tour/polymorphic-methods.html" --- Scalaのメソッドは値と同様に型によってパラメータ化することができます。構文はジェネリッククラスの構文と似ています。 diff --git a/_ja/tour/regular-expression-patterns.md b/_ja/tour/regular-expression-patterns.md index 21068d1de1..a81168544c 100644 --- a/_ja/tour/regular-expression-patterns.md +++ b/_ja/tour/regular-expression-patterns.md @@ -12,7 +12,6 @@ num: 15 next-page: extractor-objects previous-page: singleton-objects -redirect_from: "/tutorials/tour/regular-expression-patterns.html" --- 正規表現はデータの中からパターン(またはその欠如)を探すために使うことができる文字列です。 どんな文字列も`.r`メソッドを使うことで、正規表現に変換できます。 diff --git a/_ja/tour/self-types.md b/_ja/tour/self-types.md index 836e4459ec..1bffbfe63c 100644 --- a/_ja/tour/self-types.md +++ b/_ja/tour/self-types.md @@ -13,7 +13,6 @@ previous-page: compound-types topics: self-types prerequisite-knowledge: nested-classes, mixin-class-composition -redirect_from: "/tutorials/tour/self-types.html" --- 自分型は、直接継承していなくてもトレイトが他のトレイトにミックスインされていることを宣言する方法です。 これにより依存先のメンバーをimportなしで利用できます。 diff --git a/_ja/tour/singleton-objects.md b/_ja/tour/singleton-objects.md index e920e884c9..feea0e5171 100644 --- a/_ja/tour/singleton-objects.md +++ b/_ja/tour/singleton-objects.md @@ -11,7 +11,6 @@ num: 13 next-page: regular-expression-patterns previous-page: pattern-matching -redirect_from: "/tutorials/tour/singleton-objects.html" prerequisite-knowledge: classes, methods, private-methods, packages, option --- オブジェクトは丁度1つのインスタンスを持つクラスです。 diff --git a/_ja/tour/tour-of-scala.md b/_ja/tour/tour-of-scala.md index 775c66557f..46658101bf 100644 --- a/_ja/tour/tour-of-scala.md +++ b/_ja/tour/tour-of-scala.md @@ -11,7 +11,6 @@ num: 1 next-page: basics -redirect_from: "/tutorials/tour/tour-of-scala.html" --- ## ようこそツアーへ diff --git a/_ja/tour/traits.md b/_ja/tour/traits.md index 1ea0b11809..5152af0fb0 100644 --- a/_ja/tour/traits.md +++ b/_ja/tour/traits.md @@ -13,7 +13,6 @@ previous-page: classes topics: traits prerequisite-knowledge: expressions, classes, generics, objects, companion-objects -redirect_from: "/tutorials/tour/traits.html" --- トレイトはクラス間でインターフェースとフィールドを共有するために使います。それらはJava 8のインターフェースと似ています。 diff --git a/_ja/tour/tuples.md b/_ja/tour/tuples.md index 0d67f6c5c1..822a6f5a72 100644 --- a/_ja/tour/tuples.md +++ b/_ja/tour/tuples.md @@ -12,7 +12,6 @@ next-page: mixin-class-composition previous-page: traits topics: tuples -redirect_from: "/tutorials/tour/tuples.html" --- Scalaではタプルは決まった数の要素を含む値であり、各要素はそれぞれの型を持ちます。 diff --git a/_ja/tour/unified-types.md b/_ja/tour/unified-types.md index 98482b1c95..c694663c59 100644 --- a/_ja/tour/unified-types.md +++ b/_ja/tour/unified-types.md @@ -12,7 +12,6 @@ next-page: classes previous-page: basics prerequisite-knowledge: classes, basics -redirect_from: "/tutorials/tour/unified-types.html" --- Scalaでは数値や関数を含め、全ての値は型を持ちます。 以下の図は型階層の一部を説明しています。 diff --git a/_ja/tour/upper-type-bounds.md b/_ja/tour/upper-type-bounds.md index 427dbe429f..ac6b1f2440 100644 --- a/_ja/tour/upper-type-bounds.md +++ b/_ja/tour/upper-type-bounds.md @@ -11,7 +11,6 @@ num: 20 next-page: lower-type-bounds previous-page: variances -redirect_from: "/tutorials/tour/upper-type-bounds.html" --- Scalaでは [型パラメータ](generic-classes.html)と[抽象型メンバー](abstract-type-members.html) は型境界による制約をかけることができます。 diff --git a/_ja/tour/variances.md b/_ja/tour/variances.md index 35f0d01de8..523820403f 100644 --- a/_ja/tour/variances.md +++ b/_ja/tour/variances.md @@ -11,7 +11,6 @@ num: 19 next-page: upper-type-bounds previous-page: generic-classes -redirect_from: "/tutorials/tour/variances.html" --- 変位指定は複合型の間の継承関係とそれらの型パラメータ間の継承関係の相関です。 From 4f0e54b1000e155cdd8d1ba3e6de7d7bd02eb933 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 4 Jul 2019 18:16:59 +0100 Subject: [PATCH 0665/3174] Tweak literal types spec part about asInstanceOf --- _sips/sips/2014-06-27-42.type.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/_sips/sips/2014-06-27-42.type.md b/_sips/sips/2014-06-27-42.type.md index afe0aeaeae..701c01c43c 100644 --- a/_sips/sips/2014-06-27-42.type.md +++ b/_sips/sips/2014-06-27-42.type.md @@ -23,6 +23,7 @@ Sabin** | Feb 9th 2017 | New author volunteered to update the SIP for review | | Nov 16th 2017 | Updated following implementation experience in Typelevel Scala | | Aug 7th 2018 | Updated to remove Symbol literals, which won't be supported in 3 | +| Jul 4th 2019 | Drop behaviour spec around asInstanceOf, which is a user assertion | ## Introduction @@ -104,7 +105,7 @@ Lightbend Scala compiler. narrow(23) // result is 23: 23 ``` -+ Pattern matching against literal types and `isInstanceOf`/`asInstanceOf` tests/conversions are ++ Pattern matching against literal types and `isInstanceOf` tests are implemented via equality/identity tests of the corresponding values. ``` (1: Any) match { @@ -112,8 +113,6 @@ Lightbend Scala compiler. case _ => false } // result is true (1: Any).isInstanceOf[1] // result is true - (1: Any).asInstanceOf[1] // result is 1: 1 - (1: Any).asInstanceOf[2] // ClassCastException ``` + A `scala.ValueOf[T]` type class and corresponding `scala.Predef.valueOf[T]` operator has been @@ -519,7 +518,7 @@ applications which work with large datasets. valueOf[23] // result is 23: 23 ``` -+ Pattern matching against literal types and `isInstanceOf`/`asInstanceOf` tests/conversions are ++ Pattern matching against literal types and `isInstanceOf` tests are implemented via equality/identity tests of the corresponding values. Pattern matching against typed patterns (see [8.1.2 Typed @@ -527,9 +526,9 @@ applications which work with large datasets. where the `TypePat` is a literal type is translated as a match against the subsuming non-singleton type followed by an equality test with the value corresponding to the literal type. - Where applied to literal types `isInstanceOf` and `asInstanceOf` are translated to a test against + Where applied to literal types `isInstanceOf` is translated to a test against the subsuming non-singleton type and an equality test with the value corresponding to the literal - type. In the case of `asInstanceOf` a `ClassCastException` is thrown if the test fails. + type. Examples, ``` @@ -538,10 +537,13 @@ applications which work with large datasets. case _ => false } // result is true (1: Any).isInstanceOf[1] // result is true - (1: Any).asInstanceOf[1] // result is 1: 1 - (1: Any).asInstanceOf[2] // ClassCastException ``` + Importantly, that doesn't include `asInstanceOf` as that is a user assertion to the compiler, with + the compiler inserting in the generated code just enough code for the underlying runtime to not + give a `ValidationError`. The compiler should not, for instance, generate code such that an + expression like `(1: Any).asInstanceOf[2]` would throw a `ClassCastException`. + + Default initialization for vars with literal types is forbidden. The default initializer for a var is already mandated to be it's natural zero element (`0`, 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 0666/3174] 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 7bc642cd5d844621e9bb08f9c0e8529960417c1b Mon Sep 17 00:00:00 2001 From: Srishti Jain Date: Thu, 11 Jul 2019 14:42:31 +0530 Subject: [PATCH 0667/3174] Update overview.md `TypeTags` -> `TypeTag`s --- _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 22b267acfa..037207df3e 100644 --- a/_overviews/reflection/overview.md +++ b/_overviews/reflection/overview.md @@ -69,7 +69,7 @@ means that if you were to inspect the runtime type of some instance, that you might not have access to all type information that the Scala compiler has available at compile time. -`TypeTags` can be thought of as objects which carry along all type information +`TypeTag`s can be thought of as objects which carry along all type information available at compile time, to runtime. Though, it's important to note that `TypeTag`s are always generated by the compiler. This generation is triggered whenever an implicit parameter or context bound requiring a `TypeTag` is used. From 2a2b92b1b6212f39b71a566532c2d605c4da3c68 Mon Sep 17 00:00:00 2001 From: Lucas Cardoso Date: Thu, 11 Jul 2019 10:18:34 -0300 Subject: [PATCH 0668/3174] Add Portuguese translation for Tuples --- _pt-br/tour/tuples.md | 73 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/_pt-br/tour/tuples.md b/_pt-br/tour/tuples.md index 8b81442317..15462f152e 100644 --- a/_pt-br/tour/tuples.md +++ b/_pt-br/tour/tuples.md @@ -1,15 +1,78 @@ --- layout: tour -title: Tuples +title: Tuplas -discourse: true +discourse: false partof: scala-tour -num: + +num: 6 next-page: mixin-class-composition previous-page: traits language: pt-br --- -(this section of the tour has not been translated yet. pull request -with translation welcome!) \ No newline at end of file +Em Scala, uma tupla é um valor que contém um número fixo de elementos, cada um com tipos distintos e as tuplas são imutaveis. + +Tuplas são sobretudo úteis para retornar múltiplos valores de um método. + +Uma Tupla com dois lementos pode ser criada dessa forma: + +```tut +val ingrediente = ("Açucar" , 25) +``` + +Isto cria uma tupla contendo dois elementos um `String` e o outro `Int`. + +O tipo inferido de `ingrediente` é `(String, Int)`, que é uma forma abreviada para `Tuple2[String, Int]` . + +Para representar tuplas, Scala usa uma serie de classes: `Tuple2`, `Tuple3`, etc., até `Tuple22` . Cada classe tem + +## Acessando os Elementos + +Uma maneira de acessar os elementos da tupla é pela sua respectiva posição. Os elementos individuais são nomeados _1 , _2 , e assim por diante. + +```tut +println(ingrediente._1) // Açucar +println(ingrediente._2) // 25 +``` + +## Correspondência de padrões em tuplas + +Uma tupla pode tambem ser desmembrada usando correspondência de padrões: + +```tut +val (nome, quantidade) = ingrediente +println(nome) // Açucar +println(quantidade) // 25 +``` + +Aqui `nome` é um tipo inferido `String` e `quantidade` é um tipo inferido `Int` . + +Outro exemplo de correspondência de padrões em uma tupla: + +```tut +val planetas = + List(("Mercurio", 57.9), ("Vénus", 108.2), ("Terra", 149.6), + ("Marte", 227.9), ("Júpiter", 778.3)) +planetas.foreach{ + case ("Terra", distancia) => + println(s"Nosso planeta está a $distancia milhões de kilometros do sol") + case _ => +} +``` + +ou, um exemplo com `for` : + +```tut +val numPars = List((2, 5), (3, -7), (20, 56)) +for ((a, b) <- numPars) { + println(a * b) +} +``` + +## Tuplas e classes case + +Desenvolvedores às vezes acham dificil escolher entre tuplas e classes case. Classes case tem elementos nomeados, e esses podem melhorar a leitura de alguns tipos de códigos. No planeta exemplo abaixo, nós poderiamos definir uma `case class Planeta(nome: String, distancia: Double)` ao invés de usar tuplas. + + From 95d2b37d36359933fdf2bcef31cb43188cee0eb1 Mon Sep 17 00:00:00 2001 From: TAKAHASHI Shuuji Date: Fri, 12 Jul 2019 04:09:02 +0900 Subject: [PATCH 0669/3174] Let match print messages to output comments --- _ja/tour/basics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_ja/tour/basics.md b/_ja/tour/basics.md index 8eb67a0ddb..cab1c3d171 100644 --- a/_ja/tour/basics.md +++ b/_ja/tour/basics.md @@ -222,15 +222,15 @@ val yetAnotherPoint = Point(2, 2) ```tut if (point == anotherPoint) { - println(point + " and " + anotherPoint + " are the same.") + println(point + " と " + anotherPoint + " は同じです。") } else { - println(point + " and " + anotherPoint + " are different.") + println(point + " と " + anotherPoint + " は異なります。") } // Point(1,2) と Point(1,2) は同じです。 if (point == yetAnotherPoint) { - println(point + " and " + yetAnotherPoint + " are the same.") + println(point + " と " + yetAnotherPoint + " は同じです。") } else { - println(point + " and " + yetAnotherPoint + " are different.") + println(point + " と " + yetAnotherPoint + " は異なります。") } // Point(1,2) と Point(2,2) は異なります。 ``` From 61bad7b8fea308f60be8be96f1570bcc52a6e3b7 Mon Sep 17 00:00:00 2001 From: TAKAHASHI Shuuji Date: Fri, 12 Jul 2019 04:31:48 +0900 Subject: [PATCH 0670/3174] =?UTF-8?q?Replace=20comma=20with=20reading=20po?= =?UTF-8?q?int=20(,=20=E2=86=92=20=E3=80=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _ja/tour/unified-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/unified-types.md b/_ja/tour/unified-types.md index c694663c59..ab65765d37 100644 --- a/_ja/tour/unified-types.md +++ b/_ja/tour/unified-types.md @@ -25,7 +25,7 @@ Anyは `equals`、` hashCode`、そして `toString`のようないくつかの そして`AnyVal`と`AnyRef` という2つの直系のサブクラスを持ちます。 `AnyVal` は値型に相当します。 -事前に定義された9つの値型が存在し、それら`Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit`,`Boolean`は +事前に定義された9つの値型が存在し、それら`Double`、`Float`、`Long`、`Int`、`Short`、`Byte`、`Char`、`Unit`、`Boolean`は null非許容です。 `Unit`は意味のある情報をもたない値型です。`Unit`型のインスタンスはただ1つだけあり、`()`というリテラルで宣言することができます。 全ての関数は必ず何かを返さなければなりません。そのため`Unit`は戻り値の型として時々役立ちます。 From 20b9bbc651c5c939b2e4bd199c700166bc7008ee Mon Sep 17 00:00:00 2001 From: TAKAHASHI Shuuji Date: Fri, 12 Jul 2019 04:55:40 +0900 Subject: [PATCH 0671/3174] Remove a unneeded space --- _ja/tour/unified-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_ja/tour/unified-types.md b/_ja/tour/unified-types.md index ab65765d37..0317f06fe4 100644 --- a/_ja/tour/unified-types.md +++ b/_ja/tour/unified-types.md @@ -21,7 +21,7 @@ Scalaでは数値や関数を含め、全ての値は型を持ちます。 ## Scalaの型階層 ## [`Any`](http://www.scala-lang.org/api/2.12.1/scala/Any.html) は全ての型のスーパータイプであり、トップ型とも呼ばれます。 -Anyは `equals`、` hashCode`、そして `toString`のようないくつかの普遍的なメソッドを定義しています。 +Anyは `equals`、`hashCode`、そして `toString`のようないくつかの普遍的なメソッドを定義しています。 そして`AnyVal`と`AnyRef` という2つの直系のサブクラスを持ちます。 `AnyVal` は値型に相当します。 From a5bdc323a457701a65852bc04e745870f7352b7d Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Thu, 11 Jul 2019 17:05:23 -0400 Subject: [PATCH 0672/3174] Move Scaladoc interface in menu as second --- _overviews/scaladoc/for-library-authors.md | 2 +- _overviews/scaladoc/interface.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/scaladoc/for-library-authors.md b/_overviews/scaladoc/for-library-authors.md index 9d3fc9e9a3..eb747c025c 100644 --- a/_overviews/scaladoc/for-library-authors.md +++ b/_overviews/scaladoc/for-library-authors.md @@ -7,7 +7,7 @@ discourse: true partof: scaladoc overview-name: Scaladoc -num: 2 +num: 3 permalink: /overviews/scaladoc/:title.html --- diff --git a/_overviews/scaladoc/interface.md b/_overviews/scaladoc/interface.md index f64417c2be..75a95d4f10 100644 --- a/_overviews/scaladoc/interface.md +++ b/_overviews/scaladoc/interface.md @@ -7,7 +7,7 @@ discourse: true partof: scaladoc overview-name: Scaladoc -num: 3 +num: 2 permalink: /overviews/scaladoc/:title.html --- From d7c05b665528136b17e0e86eafbfd27050c958e5 Mon Sep 17 00:00:00 2001 From: exoego Date: Fri, 5 Jul 2019 20:03:05 +0900 Subject: [PATCH 0673/3174] Do not remove language code from page.url --- _includes/sidebar-toc-multipage-overview.html | 2 +- _includes/sidebar-toc-singlepage-overview.html | 2 +- _layouts/cheatsheet.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_includes/sidebar-toc-multipage-overview.html b/_includes/sidebar-toc-multipage-overview.html index f454abc5e6..8d2e419efc 100644 --- a/_includes/sidebar-toc-multipage-overview.html +++ b/_includes/sidebar-toc-multipage-overview.html @@ -27,7 +27,7 @@
    Contents
    + {% assign orphanTranslation = page.orphanTranslation | default: false %} {% if page.languages %} - {% elsif page.language and page.orphanTranslation == false %} + {% elsif page.language and orphanTranslation == false %} {% assign engPath = page.id | remove_first: "/" | remove_first: page.language | append: '.html' %} {% assign engPg = site.overviews | where: 'partof', page.partof | first %} diff --git a/_includes/sidebar-toc-singlepage-overview.html b/_includes/sidebar-toc-singlepage-overview.html index 49d2a6971c..cead129be1 100644 --- a/_includes/sidebar-toc-singlepage-overview.html +++ b/_includes/sidebar-toc-singlepage-overview.html @@ -3,6 +3,7 @@
    Contents
    diff --git a/_overviews/scala3-book/scala-tools.md b/_overviews/scala3-book/scala-tools.md index 1b6badd809..230f7b74ae 100644 --- a/_overviews/scala3-book/scala-tools.md +++ b/_overviews/scala3-book/scala-tools.md @@ -3,7 +3,7 @@ title: Scala Tools type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. languages: [zh-cn] -num: 69 +num: 68 previous-page: concurrency next-page: tools-sbt --- diff --git a/_overviews/scala3-book/tools-sbt.md b/_overviews/scala3-book/tools-sbt.md index 8735cbce68..6fd9897a29 100644 --- a/_overviews/scala3-book/tools-sbt.md +++ b/_overviews/scala3-book/tools-sbt.md @@ -3,7 +3,7 @@ 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. languages: [zh-cn] -num: 70 +num: 69 previous-page: scala-tools next-page: tools-worksheets --- diff --git a/_overviews/scala3-book/tools-worksheets.md b/_overviews/scala3-book/tools-worksheets.md index 5c8dacf3e5..92f7fd66ca 100644 --- a/_overviews/scala3-book/tools-worksheets.md +++ b/_overviews/scala3-book/tools-worksheets.md @@ -3,7 +3,7 @@ title: Worksheets type: section description: This section looks at worksheets, an alternative to Scala projects. languages: [zh-cn] -num: 71 +num: 70 previous-page: tools-sbt next-page: interacting-with-java --- diff --git a/_overviews/scala3-book/types-type-classes.md b/_overviews/scala3-book/types-type-classes.md deleted file mode 100644 index 19c20fba89..0000000000 --- a/_overviews/scala3-book/types-type-classes.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Type Classes -type: section -description: This section introduces type classes in Scala 3. -languages: [zh-cn] -num: 60 -previous-page: ca-given-using-clauses -next-page: ca-context-bounds ---- - -A _type class_ is an abstract, parameterized type that lets you add new behavior to any closed data type without using sub-typing. -If you are coming from Java, you can think of type classes as something like [`java.util.Comparator[T]`][comparator]. - -> The paper [“Type Classes as Objects and Implicits”][typeclasses-paper] (2010) by Oliveira et al. discusses the basic ideas behind type classes in Scala. -> Even though the paper uses an older version of Scala, the ideas still hold to the current day. - -This style of programming is useful in multiple use-cases, for example: - -- Expressing how a type you don’t own---such as from the standard library or a third-party library---conforms to such behavior -- Adding behavior to multiple types without introducing sub-typing relationships between those types (i.e., one `extends` another) - -In Scala 3, _type classes_ are just _traits_ with one or more type parameters, like the following: -``` -trait Show[A]: - def show(a: A): String -``` -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 -class ShowInt extends Show[Int]: - def show(a: Int) = s"The number is ${a}!" -``` -We can write methods that work on arbitrary types `A` _constrained_ by `Show` as follows: - -```scala -def toHtml[A](a: A)(showA: Show[A]): String = - "

    " + showA.show(a) + "

    " -``` -That is, `toHtml` can be called with arbitrary `A` _as long_ as you can also provide an instance of `Show[A]`. -For example, we can call it like: -```scala -toHtml(42)(ShowInt()) -// results in "

    The number is 42!

    " -``` - -#### 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. - -[typeclasses-paper]: https://infoscience.epfl.ch/record/150280/files/TypeClasses.pdf -[typeclasses-chapter]: {% link _overviews/scala3-book/ca-type-classes.md %} -[comparator]: https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html diff --git a/_overviews/scala3-book/where-next.md b/_overviews/scala3-book/where-next.md index 43e9ec8424..41bdf27255 100644 --- a/_overviews/scala3-book/where-next.md +++ b/_overviews/scala3-book/where-next.md @@ -3,9 +3,9 @@ title: Where To Go Next type: chapter description: Where to go next after reading the Scala Book languages: [zh-cn] -num: 76 +num: 75 previous-page: scala-for-python-devs -next-page: +next-page: --- We hope you enjoyed this introduction to the Scala programming language, and we also hope we were able to share some of the beauty of the language. From d8f1ca2c570ddd3bbf8b28c722419c5360322099 Mon Sep 17 00:00:00 2001 From: Yael Bakker Date: Fri, 16 Dec 2022 14:09:43 +0100 Subject: [PATCH 2521/3174] fix 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 f141548bb0..6942cd124c 100644 --- a/_overviews/scala3-book/domain-modeling-fp.md +++ b/_overviews/scala3-book/domain-modeling-fp.md @@ -748,7 +748,7 @@ implicit class PizzaOps(p: Pizza) { ``` In the above code, we define the different methods on pizzas as methods in an _implicit class_. With `implicit class PizzaOps(p: Pizza)` then wherever `PizzaOps` is imported its methods will be available on -instances of `Pizza`. The reciever in this case is `p`. +instances of `Pizza`. The receiver in this case is `p`. {% endtab %} {% tab 'Scala 3' for=module_7 %} From 033e75b380cb64fcc73434be4e78109f9567d6fd Mon Sep 17 00:00:00 2001 From: Doehyun Baek Date: Tue, 20 Dec 2022 21:22:46 +0900 Subject: [PATCH 2522/3174] fix link to correct address. Two links in scala-for-java-programmers.md were misconfigured. I tested the change locally. --- _overviews/tutorials/scala-for-java-programmers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/tutorials/scala-for-java-programmers.md b/_overviews/tutorials/scala-for-java-programmers.md index 8a2e67084f..e6678ef729 100644 --- a/_overviews/tutorials/scala-for-java-programmers.md +++ b/_overviews/tutorials/scala-for-java-programmers.md @@ -26,11 +26,11 @@ next_resources: - title: Scala Book description: Learn Scala by reading a series of short lessons. icon: "fa fa-book-open" - link: /scala3/book/scala-for-java-devs.html + link: /scala3/book/introduction.html - title: Online Courses description: MOOCs to learn Scala, for beginners and experienced programmers. icon: "fa fa-cloud" - link: /scala3/book/scala-for-java-devs.html + link: /online-courses.html --- If you are coming to Scala with some Java experience already, this page should give a good overview of From e9c624b7de50e12a39ad9c9e4987f4b88e110631 Mon Sep 17 00:00:00 2001 From: Scala Improvement Bot Date: Thu, 22 Dec 2022 00:21:42 +0000 Subject: [PATCH 2523/3174] Update SIPs state --- ...nary-compatibility-of-the-scala-213-standard-library.md | 7 +++++++ _sips/sips/struct-classes.md | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 _sips/sips/drop-forwards-binary-compatibility-of-the-scala-213-standard-library.md diff --git a/_sips/sips/drop-forwards-binary-compatibility-of-the-scala-213-standard-library.md b/_sips/sips/drop-forwards-binary-compatibility-of-the-scala-213-standard-library.md new file mode 100644 index 0000000000..0e1f095a3d --- /dev/null +++ b/_sips/sips/drop-forwards-binary-compatibility-of-the-scala-213-standard-library.md @@ -0,0 +1,7 @@ +--- +title: SIP-51 - Drop Forwards Binary Compatibility of the Scala 2.13 Standard Library +status: under-review +pull-request-number: 54 +stage: design + +--- diff --git a/_sips/sips/struct-classes.md b/_sips/sips/struct-classes.md index a17dca1324..a9109fd45b 100644 --- a/_sips/sips/struct-classes.md +++ b/_sips/sips/struct-classes.md @@ -1,7 +1,6 @@ --- title: SIP-50 - Struct Classes -status: under-review +status: withdrawn pull-request-number: 50 -stage: design --- From 8f3d3df1602a4e07df2e9b26e91771ac6683496c Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Thu, 29 Dec 2022 22:38:09 +0800 Subject: [PATCH 2524/3174] add languages field in scala3-book. --- .../scala3-book/ca-context-bounds.md | 1 + .../ca-contextual-abstractions-intro.md | 1 + .../scala3-book/ca-extension-methods.md | 1 + .../overviews/scala3-book/ca-given-imports.md | 1 + .../scala3-book/ca-given-using-clauses.md | 1 + .../scala3-book/ca-implicit-conversions.md | 1 + .../scala3-book/ca-multiversal-equality.md | 1 + _zh-cn/overviews/scala3-book/ca-summary.md | 1 + .../overviews/scala3-book/ca-type-classes.md | 1 + .../scala3-book/collections-classes.md | 3 + .../scala3-book/collections-intro.md | 1 + .../scala3-book/collections-methods.md | 1 + .../scala3-book/collections-summary.md | 1 + _zh-cn/overviews/scala3-book/concurrency.md | 1 + .../scala3-book/control-structures.md | 1 + .../scala3-book/domain-modeling-fp.md | 1 + .../scala3-book/domain-modeling-intro.md | 1 + .../scala3-book/domain-modeling-oop.md | 1 + .../scala3-book/domain-modeling-tools.md | 1 + .../scala3-book/first-look-at-types.md | 2 +- .../fp-functional-error-handling.md | 1 + .../scala3-book/fp-functions-are-values.md | 7 + .../scala3-book/fp-immutable-values.md | 1 + _zh-cn/overviews/scala3-book/fp-intro.md | 1 + .../scala3-book/fp-pure-functions.md | 1 + _zh-cn/overviews/scala3-book/fp-summary.md | 1 + _zh-cn/overviews/scala3-book/fp-what-is-fp.md | 1 + .../scala3-book/fun-anonymous-functions.md | 1 + .../scala3-book/fun-eta-expansion.md | 1 + .../scala3-book/fun-function-variables.md | 1 + _zh-cn/overviews/scala3-book/fun-hofs.md | 1 + _zh-cn/overviews/scala3-book/fun-intro.md | 1 + _zh-cn/overviews/scala3-book/fun-summary.md | 1 + .../scala3-book/fun-write-map-function.md | 1 + .../fun-write-method-returns-function.md | 1 + .../scala3-book/interacting-with-java.md | 1 + _zh-cn/overviews/scala3-book/introduction.md | 1 + _zh-cn/overviews/scala3-book/methods-intro.md | 1 + .../scala3-book/methods-main-methods.md | 2 +- _zh-cn/overviews/scala3-book/methods-most.md | 1 + .../overviews/scala3-book/methods-summary.md | 1 + .../scala3-book/packaging-imports.md | 1 + .../overviews/scala3-book/scala-features.md | 436 +----------------- .../scala3-book/scala-for-java-devs.md | 1 + .../scala3-book/scala-for-javascript-devs.md | 1 + .../scala3-book/scala-for-python-devs.md | 1 + _zh-cn/overviews/scala3-book/scala-tools.md | 1 + .../scala3-book/taste-collections.md | 1 + .../taste-contextual-abstractions.md | 1 + .../scala3-book/taste-control-structures.md | 1 + .../overviews/scala3-book/taste-functions.md | 1 + .../scala3-book/taste-hello-world.md | 3 +- _zh-cn/overviews/scala3-book/taste-intro.md | 1 + _zh-cn/overviews/scala3-book/taste-methods.md | 1 + .../overviews/scala3-book/taste-modeling.md | 1 + _zh-cn/overviews/scala3-book/taste-objects.md | 1 + _zh-cn/overviews/scala3-book/taste-repl.md | 1 + _zh-cn/overviews/scala3-book/taste-summary.md | 1 + .../scala3-book/taste-toplevel-definitions.md | 1 + .../scala3-book/taste-vars-data-types.md | 3 +- _zh-cn/overviews/scala3-book/tools-sbt.md | 1 + .../overviews/scala3-book/tools-worksheets.md | 1 + .../overviews/scala3-book/types-adts-gadts.md | 1 + .../scala3-book/types-dependent-function.md | 1 + .../overviews/scala3-book/types-generics.md | 1 + .../overviews/scala3-book/types-inferred.md | 1 + .../scala3-book/types-intersection.md | 1 + .../scala3-book/types-introduction.md | 1 + .../scala3-book/types-opaque-types.md | 1 + _zh-cn/overviews/scala3-book/types-others.md | 1 + .../overviews/scala3-book/types-structural.md | 1 + .../scala3-book/types-type-classes.md | 1 + _zh-cn/overviews/scala3-book/types-union.md | 1 + .../overviews/scala3-book/types-variance.md | 1 + _zh-cn/overviews/scala3-book/where-next.md | 1 + _zh-cn/overviews/scala3-book/why-scala-3.md | 1 + 76 files changed, 90 insertions(+), 435 deletions(-) diff --git a/_zh-cn/overviews/scala3-book/ca-context-bounds.md b/_zh-cn/overviews/scala3-book/ca-context-bounds.md index 72b55ca94d..b47b9f5907 100644 --- a/_zh-cn/overviews/scala3-book/ca-context-bounds.md +++ b/_zh-cn/overviews/scala3-book/ca-context-bounds.md @@ -2,6 +2,7 @@ title: 上下文绑定 type: section description: This page demonstrates Context Bounds in Scala 3. +languages:[en] num: 61 previous-page: types-type-classes next-page: ca-given-imports diff --git a/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md b/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md index 0cb7bd80c1..65fb42fb01 100644 --- a/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md +++ b/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md @@ -2,6 +2,7 @@ title: 上下文抽象 type: chapter description: This chapter provides an introduction to the Scala 3 concept of Contextual Abstractions. +languages:[en] num: 58 previous-page: types-others next-page: ca-given-using-clauses diff --git a/_zh-cn/overviews/scala3-book/ca-extension-methods.md b/_zh-cn/overviews/scala3-book/ca-extension-methods.md index 8565811725..8a7f3154ef 100644 --- a/_zh-cn/overviews/scala3-book/ca-extension-methods.md +++ b/_zh-cn/overviews/scala3-book/ca-extension-methods.md @@ -2,6 +2,7 @@ title: 扩展方法 type: section description: This page demonstrates how Extension Methods work in Scala 3. +languages:[en] num: 63 previous-page: ca-given-imports next-page: ca-type-classes diff --git a/_zh-cn/overviews/scala3-book/ca-given-imports.md b/_zh-cn/overviews/scala3-book/ca-given-imports.md index 245cd1feec..63721bf920 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-imports.md +++ b/_zh-cn/overviews/scala3-book/ca-given-imports.md @@ -2,6 +2,7 @@ title: Given 导入 type: section description: This page demonstrates how 'given' import statements work in Scala 3. +languages:[en] num: 62 previous-page: ca-context-bounds next-page: ca-extension-methods diff --git a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md index f6c56c3897..888b749309 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md +++ b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md @@ -2,6 +2,7 @@ title: Given 实例和 Using 语句 type: section description: This page demonstrates how to use 'given' instances and 'using' clauses in Scala 3. +languages:[en] num: 59 previous-page: ca-contextual-abstractions-intro next-page: types-type-classes diff --git a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md index e79c252822..3108f639c4 100644 --- a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md +++ b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md @@ -2,6 +2,7 @@ title: 隐式转换 type: section description: This page demonstrates how to implement Implicit Conversions in Scala 3. +languages:[en] num: 66 previous-page: ca-multiversal-equality next-page: ca-summary diff --git a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md index 02170a260a..6878ecb2b1 100644 --- a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md +++ b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md @@ -2,6 +2,7 @@ title: 多元相等性 type: section description: This page demonstrates how to implement Multiversal Equality in Scala 3. +languages:[en] num: 65 previous-page: ca-type-classes next-page: ca-implicit-conversions diff --git a/_zh-cn/overviews/scala3-book/ca-summary.md b/_zh-cn/overviews/scala3-book/ca-summary.md index 04381a0ede..d66b9baa13 100644 --- a/_zh-cn/overviews/scala3-book/ca-summary.md +++ b/_zh-cn/overviews/scala3-book/ca-summary.md @@ -2,6 +2,7 @@ title: 总结 type: section description: This page provides a summary of the Contextual Abstractions lessons. +languages:[en] num: 67 previous-page: ca-implicit-conversions next-page: concurrency diff --git a/_zh-cn/overviews/scala3-book/ca-type-classes.md b/_zh-cn/overviews/scala3-book/ca-type-classes.md index 5cef98e383..46e36e4c4d 100644 --- a/_zh-cn/overviews/scala3-book/ca-type-classes.md +++ b/_zh-cn/overviews/scala3-book/ca-type-classes.md @@ -2,6 +2,7 @@ title: 实现类型类 type: section description: This page demonstrates how to create and use type classes in Scala 3. +languages:[en] num: 64 previous-page: ca-extension-methods next-page: ca-multiversal-equality diff --git a/_zh-cn/overviews/scala3-book/collections-classes.md b/_zh-cn/overviews/scala3-book/collections-classes.md index 2b494d7791..0a56e4e0ed 100644 --- a/_zh-cn/overviews/scala3-book/collections-classes.md +++ b/_zh-cn/overviews/scala3-book/collections-classes.md @@ -2,6 +2,7 @@ title: 集合类型 type: section description: This page introduces the common Scala 3 collections types and some of their methods. +languages:[en] num: 37 previous-page: collections-intro next-page: collections-methods @@ -371,7 +372,9 @@ val people = ArrayBuffer( ```scala val nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) +languages:[en] nums += 4 // ArrayBuffer(1, 2, 3, 4) +languages:[en] nums ++= List(5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) ``` diff --git a/_zh-cn/overviews/scala3-book/collections-intro.md b/_zh-cn/overviews/scala3-book/collections-intro.md index 2b8f83481e..41e596f14e 100644 --- a/_zh-cn/overviews/scala3-book/collections-intro.md +++ b/_zh-cn/overviews/scala3-book/collections-intro.md @@ -2,6 +2,7 @@ title: Scala 集合 type: chapter description: This page provides and introduction to the common collections classes and their methods in Scala 3. +languages:[en] num: 36 previous-page: packaging-imports next-page: collections-classes diff --git a/_zh-cn/overviews/scala3-book/collections-methods.md b/_zh-cn/overviews/scala3-book/collections-methods.md index 518754ad37..3dd16e82a6 100644 --- a/_zh-cn/overviews/scala3-book/collections-methods.md +++ b/_zh-cn/overviews/scala3-book/collections-methods.md @@ -2,6 +2,7 @@ title: 集合方法 type: section description: This page demonstrates the common methods on the Scala 3 collections classes. +languages:[en] num: 38 previous-page: collections-classes next-page: collections-summary diff --git a/_zh-cn/overviews/scala3-book/collections-summary.md b/_zh-cn/overviews/scala3-book/collections-summary.md index 45456d2557..63269efe24 100644 --- a/_zh-cn/overviews/scala3-book/collections-summary.md +++ b/_zh-cn/overviews/scala3-book/collections-summary.md @@ -2,6 +2,7 @@ title: 总结 type: section description: This page provides a summary of the Collections chapter. +languages:[en] num: 39 previous-page: collections-methods next-page: fp-intro diff --git a/_zh-cn/overviews/scala3-book/concurrency.md b/_zh-cn/overviews/scala3-book/concurrency.md index cd2b7e8fde..bbbeca4b0d 100644 --- a/_zh-cn/overviews/scala3-book/concurrency.md +++ b/_zh-cn/overviews/scala3-book/concurrency.md @@ -2,6 +2,7 @@ title: 并发 type: chapter description: This page discusses how Scala concurrency works, with an emphasis on Scala Futures. +languages:[en] num: 68 previous-page: ca-summary next-page: scala-tools diff --git a/_zh-cn/overviews/scala3-book/control-structures.md b/_zh-cn/overviews/scala3-book/control-structures.md index d552145c19..bc5bfc06ff 100644 --- a/_zh-cn/overviews/scala3-book/control-structures.md +++ b/_zh-cn/overviews/scala3-book/control-structures.md @@ -2,6 +2,7 @@ title: 控制结构 type: chapter 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. +languages:[en, ru] num: 18 previous-page: first-look-at-types next-page: domain-modeling-intro diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-fp.md b/_zh-cn/overviews/scala3-book/domain-modeling-fp.md index c218cb5439..4ba980d9d0 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-fp.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-fp.md @@ -2,6 +2,7 @@ title: 函数式领域建模 type: section description: This chapter provides an introduction to FP domain modeling with Scala 3. +languages:[en, ru] num: 22 previous-page: domain-modeling-oop next-page: methods-intro diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-intro.md b/_zh-cn/overviews/scala3-book/domain-modeling-intro.md index f2924f69a7..9a36b2894b 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-intro.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-intro.md @@ -2,6 +2,7 @@ title: 领域建模 type: chapter description: This chapter provides an introduction to domain modeling in Scala 3. +languages:[en, ru] num: 19 previous-page: control-structures next-page: domain-modeling-tools diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-oop.md b/_zh-cn/overviews/scala3-book/domain-modeling-oop.md index 47a238c169..204e1ce3c1 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-oop.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-oop.md @@ -2,6 +2,7 @@ title: OOP 领域建模 type: section description: This chapter provides an introduction to OOP domain modeling with Scala 3. +languages:[en, ru] num: 21 previous-page: domain-modeling-tools next-page: domain-modeling-fp diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-tools.md b/_zh-cn/overviews/scala3-book/domain-modeling-tools.md index 1cfcaab10d..42deec841b 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-tools.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-tools.md @@ -2,6 +2,7 @@ title: 工具 type: section description: This chapter provides an introduction to the available domain modeling tools in Scala 3, including classes, traits, enums, and more. +languages:[en, ru] num: 20 previous-page: domain-modeling-intro next-page: domain-modeling-oop diff --git a/_zh-cn/overviews/scala3-book/first-look-at-types.md b/_zh-cn/overviews/scala3-book/first-look-at-types.md index 5cc496806c..692e7707b8 100644 --- a/_zh-cn/overviews/scala3-book/first-look-at-types.md +++ b/_zh-cn/overviews/scala3-book/first-look-at-types.md @@ -2,6 +2,7 @@ title: 类型初探 type: chapter description: This page provides a brief introduction to Scala's built-in data types, including Int, Double, String, Long, Any, AnyRef, Nothing, and Null. +languages:[en, ru] num: 17 previous-page: taste-summary next-page: control-structures @@ -13,7 +14,6 @@ permalink: "/zh-cn/scala3/book/:title.html" --- - ## 所有值都有一个类型 在 Scala 中,所有值都有一个类型,包括数值和函数。 diff --git a/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md b/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md index d0c2dd8749..7cb70257ff 100644 --- a/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md +++ b/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md @@ -2,6 +2,7 @@ title: 函数式错误处理 type: section description: This section provides an introduction to functional error handling in Scala 3. +languages:[en] num: 45 previous-page: fp-functions-are-values next-page: fp-summary diff --git a/_zh-cn/overviews/scala3-book/fp-functions-are-values.md b/_zh-cn/overviews/scala3-book/fp-functions-are-values.md index e6ad2bcac3..1e5a571c9d 100644 --- a/_zh-cn/overviews/scala3-book/fp-functions-are-values.md +++ b/_zh-cn/overviews/scala3-book/fp-functions-are-values.md @@ -2,6 +2,7 @@ title: 函数是值 type: section description: This section looks at the use of functions as values in functional programming. +languages:[en] num: 44 previous-page: fp-pure-functions next-page: fp-functional-error-handling @@ -91,12 +92,18 @@ fruits.map(_.toUpperCase) // List(APPLE, PEAR) fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R) val nums = List(5, 1, 3, 11, 7) +languages:[en] nums.map(_ * 2) // List(10, 2, 6, 22, 14) +languages:[en] nums.filter(_ > 3) // List(5, 11, 7) +languages:[en] nums.takeWhile(_ < 6) // List(5, 1, 3) +languages:[en] nums.sortWith(_ < _) // List(1, 3, 5, 7, 11) +languages:[en] nums.sortWith(_ > _) // List(11, 7, 5, 3, 1) +languages:[en] nums.takeWhile(_ < 6).sortWith(_ < _) // List(1, 3, 5) ``` diff --git a/_zh-cn/overviews/scala3-book/fp-immutable-values.md b/_zh-cn/overviews/scala3-book/fp-immutable-values.md index 085161228f..27a192d7e6 100644 --- a/_zh-cn/overviews/scala3-book/fp-immutable-values.md +++ b/_zh-cn/overviews/scala3-book/fp-immutable-values.md @@ -2,6 +2,7 @@ title: 不可变值 type: section description: This section looks at the use of immutable values in functional programming. +languages:[en] num: 42 previous-page: fp-what-is-fp next-page: fp-pure-functions diff --git a/_zh-cn/overviews/scala3-book/fp-intro.md b/_zh-cn/overviews/scala3-book/fp-intro.md index 5af0f94021..39e500d187 100644 --- a/_zh-cn/overviews/scala3-book/fp-intro.md +++ b/_zh-cn/overviews/scala3-book/fp-intro.md @@ -2,6 +2,7 @@ title: 函数式编程 type: chapter description: This chapter provides an introduction to functional programming in Scala 3. +languages:[en] num: 40 previous-page: collections-summary next-page: fp-what-is-fp diff --git a/_zh-cn/overviews/scala3-book/fp-pure-functions.md b/_zh-cn/overviews/scala3-book/fp-pure-functions.md index 6e53e0f705..135a0c48bc 100644 --- a/_zh-cn/overviews/scala3-book/fp-pure-functions.md +++ b/_zh-cn/overviews/scala3-book/fp-pure-functions.md @@ -2,6 +2,7 @@ title: 纯函数 type: section description: This section looks at the use of pure functions in functional programming. +languages:[en] num: 43 previous-page: fp-immutable-values next-page: fp-functions-are-values diff --git a/_zh-cn/overviews/scala3-book/fp-summary.md b/_zh-cn/overviews/scala3-book/fp-summary.md index 5eb64f228a..6541bc074e 100644 --- a/_zh-cn/overviews/scala3-book/fp-summary.md +++ b/_zh-cn/overviews/scala3-book/fp-summary.md @@ -2,6 +2,7 @@ title: 总结 type: section description: This section summarizes the previous functional programming sections. +languages:[en] num: 46 previous-page: fp-functional-error-handling next-page: types-introduction diff --git a/_zh-cn/overviews/scala3-book/fp-what-is-fp.md b/_zh-cn/overviews/scala3-book/fp-what-is-fp.md index c7f05298a1..a4f5164926 100644 --- a/_zh-cn/overviews/scala3-book/fp-what-is-fp.md +++ b/_zh-cn/overviews/scala3-book/fp-what-is-fp.md @@ -2,6 +2,7 @@ title: 什么是函数式编程? type: section description: This section provides an answer to the question, what is functional programming? +languages:[en] num: 41 previous-page: fp-intro next-page: fp-immutable-values diff --git a/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md b/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md index 25de7d14c7..88f92897d5 100644 --- a/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md +++ b/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md @@ -2,6 +2,7 @@ title: 匿名函数 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. +languages:[en, ru] num: 28 previous-page: fun-intro next-page: fun-function-variables diff --git a/_zh-cn/overviews/scala3-book/fun-eta-expansion.md b/_zh-cn/overviews/scala3-book/fun-eta-expansion.md index bca25ec8fd..7db5c96729 100644 --- a/_zh-cn/overviews/scala3-book/fun-eta-expansion.md +++ b/_zh-cn/overviews/scala3-book/fun-eta-expansion.md @@ -2,6 +2,7 @@ title: Eta 扩展 type: section description: This page discusses Eta Expansion, the Scala technology that automatically and transparently converts methods into functions. +languages:[en, ru] num: 30 previous-page: fun-function-variables next-page: fun-hofs diff --git a/_zh-cn/overviews/scala3-book/fun-function-variables.md b/_zh-cn/overviews/scala3-book/fun-function-variables.md index 75d164d0e9..078467197b 100644 --- a/_zh-cn/overviews/scala3-book/fun-function-variables.md +++ b/_zh-cn/overviews/scala3-book/fun-function-variables.md @@ -2,6 +2,7 @@ title: 函数变量 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. +languages:[en, ru] num: 29 previous-page: fun-anonymous-functions next-page: fun-eta-expansion diff --git a/_zh-cn/overviews/scala3-book/fun-hofs.md b/_zh-cn/overviews/scala3-book/fun-hofs.md index b20c6212da..241f854966 100644 --- a/_zh-cn/overviews/scala3-book/fun-hofs.md +++ b/_zh-cn/overviews/scala3-book/fun-hofs.md @@ -2,6 +2,7 @@ title: 高阶函数 type: section description: This page demonstrates how to create and use higher-order functions in Scala. +languages:[en, ru] num: 31 previous-page: fun-eta-expansion next-page: fun-write-map-function diff --git a/_zh-cn/overviews/scala3-book/fun-intro.md b/_zh-cn/overviews/scala3-book/fun-intro.md index 4a84ebf631..f42b272885 100644 --- a/_zh-cn/overviews/scala3-book/fun-intro.md +++ b/_zh-cn/overviews/scala3-book/fun-intro.md @@ -2,6 +2,7 @@ title: 函数 type: chapter description: This chapter looks at all topics related to functions in Scala 3. +languages:[en, ru] num: 27 previous-page: methods-summary next-page: fun-anonymous-functions diff --git a/_zh-cn/overviews/scala3-book/fun-summary.md b/_zh-cn/overviews/scala3-book/fun-summary.md index f05694ee42..fb382d2bee 100644 --- a/_zh-cn/overviews/scala3-book/fun-summary.md +++ b/_zh-cn/overviews/scala3-book/fun-summary.md @@ -2,6 +2,7 @@ title: 总结 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. +languages:[en, ru] num: 34 previous-page: fun-write-method-returns-function next-page: packaging-imports diff --git a/_zh-cn/overviews/scala3-book/fun-write-map-function.md b/_zh-cn/overviews/scala3-book/fun-write-map-function.md index 8240830912..bb8e82b056 100644 --- a/_zh-cn/overviews/scala3-book/fun-write-map-function.md +++ b/_zh-cn/overviews/scala3-book/fun-write-map-function.md @@ -2,6 +2,7 @@ title: 自定义 map 函数 type: section description: This page demonstrates how to create and use higher-order functions in Scala. +languages:[en, ru] num: 32 previous-page: fun-hofs next-page: fun-write-method-returns-function diff --git a/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md b/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md index 5e223041d5..fa93960616 100644 --- a/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md +++ b/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md @@ -2,6 +2,7 @@ title: 创建可以返回函数的方法 type: section description: This page demonstrates how to create and use higher-order functions in Scala. +languages:[en, ru] num: 33 previous-page: fun-write-map-function next-page: fun-summary diff --git a/_zh-cn/overviews/scala3-book/interacting-with-java.md b/_zh-cn/overviews/scala3-book/interacting-with-java.md index dae978ba6e..0498d7919b 100644 --- a/_zh-cn/overviews/scala3-book/interacting-with-java.md +++ b/_zh-cn/overviews/scala3-book/interacting-with-java.md @@ -2,6 +2,7 @@ title: 与 Java 交互 type: chapter description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. +languages:[en] num: 72 previous-page: tools-worksheets next-page: scala-for-java-devs diff --git a/_zh-cn/overviews/scala3-book/introduction.md b/_zh-cn/overviews/scala3-book/introduction.md index 003e2e3987..06fb982d8e 100644 --- a/_zh-cn/overviews/scala3-book/introduction.md +++ b/_zh-cn/overviews/scala3-book/introduction.md @@ -2,6 +2,7 @@ title: 导言 type: chapter description: This page begins the overview documentation of the Scala 3 language. +languages:[en, ru] num: 1 previous-page: next-page: scala-features diff --git a/_zh-cn/overviews/scala3-book/methods-intro.md b/_zh-cn/overviews/scala3-book/methods-intro.md index f6d66d0686..fd6e1a6006 100644 --- a/_zh-cn/overviews/scala3-book/methods-intro.md +++ b/_zh-cn/overviews/scala3-book/methods-intro.md @@ -2,6 +2,7 @@ title: 方法 type: chapter description: This section introduces methods in Scala 3. +languages:[en, ru] num: 23 previous-page: domain-modeling-fp next-page: methods-most diff --git a/_zh-cn/overviews/scala3-book/methods-main-methods.md b/_zh-cn/overviews/scala3-book/methods-main-methods.md index fda3199aca..42cccddfd1 100644 --- a/_zh-cn/overviews/scala3-book/methods-main-methods.md +++ b/_zh-cn/overviews/scala3-book/methods-main-methods.md @@ -2,6 +2,7 @@ title: main 方法 type: section description: This page describes how 'main' methods and the '@main' annotation work in Scala 3. +languages:[en, ru] num: 25 previous-page: methods-most next-page: methods-summary @@ -13,7 +14,6 @@ permalink: "/zh-cn/scala3/book/:title.html" --- - Scala 3 提供了一种定义可以从命令行调用的程序的新方法:在方法中添加 `@main` 注释会将其变成可执行程序的入口点: ```scala diff --git a/_zh-cn/overviews/scala3-book/methods-most.md b/_zh-cn/overviews/scala3-book/methods-most.md index d9ad8e194d..c73453fd90 100644 --- a/_zh-cn/overviews/scala3-book/methods-most.md +++ b/_zh-cn/overviews/scala3-book/methods-most.md @@ -2,6 +2,7 @@ title: 方法特性 type: section description: This section introduces Scala 3 methods, including main methods, extension methods, and more. +languages:[en, ru] num: 24 previous-page: methods-intro next-page: methods-main-methods diff --git a/_zh-cn/overviews/scala3-book/methods-summary.md b/_zh-cn/overviews/scala3-book/methods-summary.md index c74f976cd2..20fd7cb68b 100644 --- a/_zh-cn/overviews/scala3-book/methods-summary.md +++ b/_zh-cn/overviews/scala3-book/methods-summary.md @@ -2,6 +2,7 @@ title: 总结 type: section description: This section summarizes the previous sections on Scala 3 methods. +languages:[en, ru] num: 26 previous-page: methods-main-methods next-page: fun-intro diff --git a/_zh-cn/overviews/scala3-book/packaging-imports.md b/_zh-cn/overviews/scala3-book/packaging-imports.md index c87cc51b3d..190796573a 100644 --- a/_zh-cn/overviews/scala3-book/packaging-imports.md +++ b/_zh-cn/overviews/scala3-book/packaging-imports.md @@ -2,6 +2,7 @@ title: 打包和导入 type: chapter description: A discussion of using packages and imports to organize your code, build related modules of code, control scope, and help prevent namespace collisions. +languages:[en] num: 35 previous-page: fun-summary next-page: collections-intro diff --git a/_zh-cn/overviews/scala3-book/scala-features.md b/_zh-cn/overviews/scala3-book/scala-features.md index 6d9362cf6b..0b9761fe17 100644 --- a/_zh-cn/overviews/scala3-book/scala-features.md +++ b/_zh-cn/overviews/scala3-book/scala-features.md @@ -2,6 +2,7 @@ title: Scala 3 特性 type: chapter description: This page discusses the main features of the Scala 3 programming language. +languages:[en, ru] num: 2 previous-page: introduction next-page: why-scala-3 @@ -13,24 +14,10 @@ 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 生态系统特性 @@ -39,36 +26,10 @@ _Scala_ 这个名字来源于 _scalable_ 一词。正如其名,Scala 语言被 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 %} - - 它是一种高级编程语言 - 它具有简明易读的语法 - 它是静态类型的(但使人感觉是动态的) @@ -81,34 +42,13 @@ Looking at Scala from the proverbial “30,000 foot view,” you can make the fo - 它与 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 中,您编写您想要 _“什么”_,而不是 _“如何”_ 去实现它。 也就是说,我们不会像这样编写命令式代码: @@ -146,11 +86,6 @@ val newNumbers = double(oldNumbers) {% endtab %} {% endtabs %} -{% 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 来编写高层次的函数式代码以计算出相同的结果: @@ -162,25 +97,10 @@ val newNumbers = oldNumbers.map(_ * 2) {% endtab %} {% endtabs %} -{% 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 具有简明易读的语法。例如,变量的创建十分简洁,其类型也很明确。 {% tabs scala-features-3 %} @@ -192,29 +112,24 @@ val p = Person("Martin", "Odersky") {% endtab %} {% endtabs %} - -{% comment %} -Higher-order functions and lambdas make for concise code that’s readable: -{% endcomment %} - 高阶函数与 lambda 使代码简明易读: {% tabs scala-features-4 %} {% tab 'Scala 2 and 3' for=scala-features-4 %} ```scala +languages:[en] nums.map(i => i * 2) // long form +languages:[en] nums.map(_ * 2) // short form +languages:[en] nums.filter(i => i > 1) +languages:[en] nums.filter(_ > 1) ``` {% endtab %} {% endtabs %} -{% comment %} -Traits, classes, and methods are defined with a clean, light syntax: -{% endcomment %} - 特质(Traits)、类(Class)和方法(Method)都是用简洁、轻巧的语法定义的。 {% tabs scala-features-5 class=tabs-scala-version %} @@ -249,26 +164,10 @@ class Dog extends Animal, HasTail: {% endtab %} {% endtabs %} - -{% 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 代码: {% tabs scala-features-6 class=tabs-scala-version %} @@ -298,26 +197,8 @@ val z = nums {% endtab %} {% endtabs %} -{% 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) 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 支持 - 可靠的代码补全 @@ -337,12 +218,6 @@ In that list: - Reliable code completion {% endcomment %} -{% comment %} - -### Expressive type system - -{% endcomment %} - ### 富有表现力的类型系统 {% comment %} @@ -355,36 +230,8 @@ In that list: * [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 _zh-cn/overviews/scala3-book/types-inferred.md %}) - [泛型类]({% link _zh-cn/overviews/scala3-book/types-generics.md %}) - [型变]({% link _zh-cn/overviews/scala3-book/types-variance.md %}) @@ -406,38 +253,12 @@ Scala 的类型系统在编译时强制要求以安全与连贯的方式使用 - [上下文函数]({{ 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 @@ -446,28 +267,11 @@ Scala 是一门函数式编程(FP)语言,也就是说: - 在标准库中有大量的不可变集合类 - 这些集合类带有许多函数式方法:它们不改变集合本身,而是返回数据的更新副本 -{% 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`)。 装箱与拆箱对用户来说是完全透明的。 @@ -478,27 +282,12 @@ Boxing and unboxing is completely transparent to the user. - 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 的本质是函数式编程和面向对象编程的融合: - 函数用于代表逻辑 @@ -506,27 +295,8 @@ 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). -{% endcomment %} - 继 Haskell 之后,Scala 是第二种具有某种形式的 _隐式_ 的流行语言。 在 Scala 3 中,这些概念经过了重新考虑并更清晰地实现。 @@ -538,26 +308,8 @@ Read about contextual abstractions in the [Reference documentation]({{ site.scal Scala 3 使此过程比以往任何时候都更加清晰。 请在[参考文档]({{ site.scala3ref }}/contextual)中阅读关于上下文抽象的内容。 -{% 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)上运行,因此您可以获得它的全部益处: - 安全性 @@ -568,27 +320,11 @@ Scala 代码在 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` 来读取文件: @@ -602,12 +338,6 @@ val br = BufferedReader(FileReader(filename)) {% endtab %} {% endtabs %} -{% 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 丰富的集合类方法与其一起使用,只需几行代码即可转换它们: @@ -621,26 +351,8 @@ val scalaList: Seq[Integer] = JavaClass.getJavaList().asScala.toSeq {% endtab %} {% endtabs %} -{% 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友好的架构 @@ -656,50 +368,11 @@ 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) @@ -789,52 +462,14 @@ DROPPED FEATURES 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 服务 @@ -842,10 +477,6 @@ Scala 拥有一个充满活力的生态系统,有满足各种需求的库和 - [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) @@ -853,10 +484,6 @@ HTTP(S) 库: - [Http4s](https://github.com/http4s/http4s) - [Sttp](https://github.com/softwaremill/sttp) -{% comment %} -JSON libraries: -{% endcomment %} - JSON 库: - [Argonaut](https://github.com/argonaut-io/argonaut) @@ -864,97 +491,44 @@ JSON 库: - [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 在高层、日常编程层面以及贯穿开发者生态系统都具有许多出色的编程语言特性。 diff --git a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md index c659559bb2..de7b4eea7a 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md @@ -2,6 +2,7 @@ title: 向 Java 开发者介绍Scala type: chapter description: This page is for Java developers who are interested in learning about Scala 3. +languages:[en] num: 73 previous-page: interacting-with-java next-page: scala-for-javascript-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md b/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md index 3e80ad15e9..c5f4b907bd 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md @@ -2,6 +2,7 @@ title: Scala for JavaScript Developers type: chapter description: This chapter provides an introduction to Scala 3 for JavaScript developers +languages:[en] num: 74 previous-page: scala-for-java-devs next-page: scala-for-python-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md index f3e17233f1..4ee6dee030 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md @@ -2,6 +2,7 @@ title: Scala for Python Developers type: chapter description: This page is for Python developers who are interested in learning about Scala 3. +languages:[en] num: 75 previous-page: scala-for-javascript-devs next-page: diff --git a/_zh-cn/overviews/scala3-book/scala-tools.md b/_zh-cn/overviews/scala3-book/scala-tools.md index 0362ffcc0e..4cd1637244 100644 --- a/_zh-cn/overviews/scala3-book/scala-tools.md +++ b/_zh-cn/overviews/scala3-book/scala-tools.md @@ -2,6 +2,7 @@ title: Scala 工具 type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. +languages:[en] num: 69 previous-page: concurrency next-page: tools-sbt diff --git a/_zh-cn/overviews/scala3-book/taste-collections.md b/_zh-cn/overviews/scala3-book/taste-collections.md index bd5f02cb01..589a498f0a 100644 --- a/_zh-cn/overviews/scala3-book/taste-collections.md +++ b/_zh-cn/overviews/scala3-book/taste-collections.md @@ -2,6 +2,7 @@ title: Collections type: section description: This page provides a high-level overview of the main features of the Scala 3 programming language. +languages:[en, ru] num: 13 previous-page: taste-objects next-page: taste-contextual-abstractions diff --git a/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md b/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md index b354a6a9f5..6d181d09fa 100644 --- a/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md +++ b/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md @@ -2,6 +2,7 @@ title: Contextual Abstractions type: section description: This section provides an introduction to Contextual Abstractions in Scala 3. +languages:[en, ru] num: 14 previous-page: taste-collections next-page: taste-toplevel-definitions diff --git a/_zh-cn/overviews/scala3-book/taste-control-structures.md b/_zh-cn/overviews/scala3-book/taste-control-structures.md index 5efa015ee3..e45fbd3849 100644 --- a/_zh-cn/overviews/scala3-book/taste-control-structures.md +++ b/_zh-cn/overviews/scala3-book/taste-control-structures.md @@ -2,6 +2,7 @@ title: 控制结构 type: section description: This section demonstrates Scala 3 control structures. +languages:[en, ru] num: 8 previous-page: taste-vars-data-types next-page: taste-modeling diff --git a/_zh-cn/overviews/scala3-book/taste-functions.md b/_zh-cn/overviews/scala3-book/taste-functions.md index 6947dfcb69..637dd40216 100644 --- a/_zh-cn/overviews/scala3-book/taste-functions.md +++ b/_zh-cn/overviews/scala3-book/taste-functions.md @@ -2,6 +2,7 @@ title: First-Class Functions type: section description: This page provides an introduction to functions in Scala 3. +languages:[en, ru] num: 11 previous-page: taste-methods next-page: taste-objects diff --git a/_zh-cn/overviews/scala3-book/taste-hello-world.md b/_zh-cn/overviews/scala3-book/taste-hello-world.md index 686e2187fc..2b8a8bd1b6 100644 --- a/_zh-cn/overviews/scala3-book/taste-hello-world.md +++ b/_zh-cn/overviews/scala3-book/taste-hello-world.md @@ -2,6 +2,7 @@ title: Hello, World! type: section description: This section demonstrates a Scala 3 'Hello, World!' example. +languages:[en, ru] num: 5 previous-page: taste-intro next-page: taste-repl @@ -198,4 +199,4 @@ import scala.io.StdIn.readLine - 您可以使用包含有用功能的代码库,该库可能是由其他人编写 - 您可以知道某个定义的来源(特别是如果它没有写入当前文件)。 -[scala_tools]: {% link _zh-cn/overviews/scala3-book/scala-tools.md %} \ No newline at end of file +[scala_tools]: {% link _zh-cn/overviews/scala3-book/scala-tools.md %} diff --git a/_zh-cn/overviews/scala3-book/taste-intro.md b/_zh-cn/overviews/scala3-book/taste-intro.md index 1aa0b92bcb..fc975520c5 100644 --- a/_zh-cn/overviews/scala3-book/taste-intro.md +++ b/_zh-cn/overviews/scala3-book/taste-intro.md @@ -2,6 +2,7 @@ title: Scala 的味道 type: chapter description: This chapter provides a high-level overview of the main features of the Scala 3 programming language. +languages:[en, ru] num: 4 previous-page: why-scala-3 next-page: taste-hello-world diff --git a/_zh-cn/overviews/scala3-book/taste-methods.md b/_zh-cn/overviews/scala3-book/taste-methods.md index fb1da65c2f..1743286235 100644 --- a/_zh-cn/overviews/scala3-book/taste-methods.md +++ b/_zh-cn/overviews/scala3-book/taste-methods.md @@ -2,6 +2,7 @@ title: Methods type: section description: This section provides an introduction to defining and using methods in Scala 3. +languages:[en, ru] num: 10 previous-page: taste-modeling next-page: taste-functions diff --git a/_zh-cn/overviews/scala3-book/taste-modeling.md b/_zh-cn/overviews/scala3-book/taste-modeling.md index 2ade36d68d..79fb6fa964 100644 --- a/_zh-cn/overviews/scala3-book/taste-modeling.md +++ b/_zh-cn/overviews/scala3-book/taste-modeling.md @@ -2,6 +2,7 @@ title: 领域建模 type: section description: This section provides an introduction to data modeling in Scala 3. +languages:[en, ru] num: 9 previous-page: taste-control-structures next-page: taste-methods diff --git a/_zh-cn/overviews/scala3-book/taste-objects.md b/_zh-cn/overviews/scala3-book/taste-objects.md index 10b5e80d47..f018639a04 100644 --- a/_zh-cn/overviews/scala3-book/taste-objects.md +++ b/_zh-cn/overviews/scala3-book/taste-objects.md @@ -2,6 +2,7 @@ title: 单例对象 type: section description: This section provides an introduction to the use of singleton objects in Scala 3. +languages:[en, ru] num: 12 previous-page: taste-functions next-page: taste-collections diff --git a/_zh-cn/overviews/scala3-book/taste-repl.md b/_zh-cn/overviews/scala3-book/taste-repl.md index 8e8599db9f..f79e289ee3 100644 --- a/_zh-cn/overviews/scala3-book/taste-repl.md +++ b/_zh-cn/overviews/scala3-book/taste-repl.md @@ -2,6 +2,7 @@ title: The REPL type: section description: This section provides an introduction to the Scala REPL. +languages:[en, ru] num: 6 previous-page: taste-hello-world next-page: taste-vars-data-types diff --git a/_zh-cn/overviews/scala3-book/taste-summary.md b/_zh-cn/overviews/scala3-book/taste-summary.md index dd320bea58..de94900bac 100644 --- a/_zh-cn/overviews/scala3-book/taste-summary.md +++ b/_zh-cn/overviews/scala3-book/taste-summary.md @@ -2,6 +2,7 @@ title: Summary type: section description: This page provides a summary of the previous 'Taste of Scala' sections. +languages:[en, ru] num: 16 previous-page: taste-toplevel-definitions next-page: first-look-at-types diff --git a/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md b/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md index e36a35adc6..f1999743c3 100644 --- a/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md +++ b/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md @@ -2,6 +2,7 @@ title: Toplevel Definitions type: section description: This page provides an introduction to top-level definitions in Scala 3 +languages:[en, ru] num: 15 previous-page: taste-contextual-abstractions next-page: taste-summary diff --git a/_zh-cn/overviews/scala3-book/taste-vars-data-types.md b/_zh-cn/overviews/scala3-book/taste-vars-data-types.md index 9ac7ab79b0..c1d0642427 100644 --- a/_zh-cn/overviews/scala3-book/taste-vars-data-types.md +++ b/_zh-cn/overviews/scala3-book/taste-vars-data-types.md @@ -2,6 +2,7 @@ title: 变量和数据类型 type: section description: This section demonstrates val and var variables, and some common Scala data types. +languages:[en, ru] num: 7 previous-page: taste-repl next-page: taste-control-structures @@ -289,4 +290,4 @@ val quote = """The essence of Scala: > 有关字符串插值器和多行字符串的更多详细信息,请参阅[“类型初探”章节][first-look]。 -[first-look]: {% link _zh-cn/overviews/scala3-book/first-look-at-types.md %} \ No newline at end of file +[first-look]: {% link _zh-cn/overviews/scala3-book/first-look-at-types.md %} diff --git a/_zh-cn/overviews/scala3-book/tools-sbt.md b/_zh-cn/overviews/scala3-book/tools-sbt.md index 7e19cb629f..6e7c588fd3 100644 --- a/_zh-cn/overviews/scala3-book/tools-sbt.md +++ b/_zh-cn/overviews/scala3-book/tools-sbt.md @@ -2,6 +2,7 @@ title: 使用 sbt 构建和测试 Scala 项目 type: section description: This section looks at a commonly-used build tool, sbt, and a testing library, ScalaTest. +languages:[en] num: 70 previous-page: scala-tools next-page: tools-worksheets diff --git a/_zh-cn/overviews/scala3-book/tools-worksheets.md b/_zh-cn/overviews/scala3-book/tools-worksheets.md index 811bc2763e..1de7f8a891 100644 --- a/_zh-cn/overviews/scala3-book/tools-worksheets.md +++ b/_zh-cn/overviews/scala3-book/tools-worksheets.md @@ -2,6 +2,7 @@ title: worksheet type: section description: This section looks at worksheets, an alternative to Scala projects. +languages:[en] num: 71 previous-page: tools-sbt next-page: interacting-with-java diff --git a/_zh-cn/overviews/scala3-book/types-adts-gadts.md b/_zh-cn/overviews/scala3-book/types-adts-gadts.md index 367e77394d..e311fb7a33 100644 --- a/_zh-cn/overviews/scala3-book/types-adts-gadts.md +++ b/_zh-cn/overviews/scala3-book/types-adts-gadts.md @@ -2,6 +2,7 @@ title: 代数数据类型 type: section description: This section introduces and demonstrates algebraic data types (ADTs) in Scala 3. +languages:[en] num: 52 previous-page: types-union next-page: types-variance diff --git a/_zh-cn/overviews/scala3-book/types-dependent-function.md b/_zh-cn/overviews/scala3-book/types-dependent-function.md index 1b9c29ebcf..d19e7abb6c 100644 --- a/_zh-cn/overviews/scala3-book/types-dependent-function.md +++ b/_zh-cn/overviews/scala3-book/types-dependent-function.md @@ -2,6 +2,7 @@ title: 依赖函数类型 type: section description: This section introduces and demonstrates dependent function types in Scala 3. +languages:[en] num: 56 previous-page: types-structural next-page: types-others diff --git a/_zh-cn/overviews/scala3-book/types-generics.md b/_zh-cn/overviews/scala3-book/types-generics.md index 484327c62c..bc7eb8f379 100644 --- a/_zh-cn/overviews/scala3-book/types-generics.md +++ b/_zh-cn/overviews/scala3-book/types-generics.md @@ -2,6 +2,7 @@ title: 泛型 type: section description: This section introduces and demonstrates generics in Scala 3. +languages:[en] num: 49 previous-page: types-inferred next-page: types-intersection diff --git a/_zh-cn/overviews/scala3-book/types-inferred.md b/_zh-cn/overviews/scala3-book/types-inferred.md index 8954a93cc4..db6c282662 100644 --- a/_zh-cn/overviews/scala3-book/types-inferred.md +++ b/_zh-cn/overviews/scala3-book/types-inferred.md @@ -2,6 +2,7 @@ title: 类型推断 type: section description: This section introduces and demonstrates inferred types in Scala 3 +languages:[en] num: 48 previous-page: types-introduction next-page: types-generics diff --git a/_zh-cn/overviews/scala3-book/types-intersection.md b/_zh-cn/overviews/scala3-book/types-intersection.md index 711ad81a01..870e0b6aac 100644 --- a/_zh-cn/overviews/scala3-book/types-intersection.md +++ b/_zh-cn/overviews/scala3-book/types-intersection.md @@ -2,6 +2,7 @@ title: 相交类型 type: section description: This section introduces and demonstrates intersection types in Scala 3. +languages:[en] num: 50 previous-page: types-generics next-page: types-union diff --git a/_zh-cn/overviews/scala3-book/types-introduction.md b/_zh-cn/overviews/scala3-book/types-introduction.md index 6a425da596..9c6e492976 100644 --- a/_zh-cn/overviews/scala3-book/types-introduction.md +++ b/_zh-cn/overviews/scala3-book/types-introduction.md @@ -2,6 +2,7 @@ title: 类型和类型系统 type: chapter description: This chapter provides an introduction to Scala 3 types and the type system. +languages:[en] num: 47 previous-page: fp-summary next-page: types-inferred diff --git a/_zh-cn/overviews/scala3-book/types-opaque-types.md b/_zh-cn/overviews/scala3-book/types-opaque-types.md index eab037e2c3..349a7272d7 100644 --- a/_zh-cn/overviews/scala3-book/types-opaque-types.md +++ b/_zh-cn/overviews/scala3-book/types-opaque-types.md @@ -2,6 +2,7 @@ title: 不透明类型 type: section description: This section introduces and demonstrates opaque types in Scala 3. +languages:[en] num: 54 previous-page: types-variance next-page: types-structural diff --git a/_zh-cn/overviews/scala3-book/types-others.md b/_zh-cn/overviews/scala3-book/types-others.md index 8861090281..61f3a14a57 100644 --- a/_zh-cn/overviews/scala3-book/types-others.md +++ b/_zh-cn/overviews/scala3-book/types-others.md @@ -2,6 +2,7 @@ title: 其他类型 type: section description: This section mentions other advanced types in Scala 3. +languages:[en] num: 57 previous-page: types-dependent-function next-page: ca-contextual-abstractions-intro diff --git a/_zh-cn/overviews/scala3-book/types-structural.md b/_zh-cn/overviews/scala3-book/types-structural.md index 3ea74afdda..bb7904c2c8 100644 --- a/_zh-cn/overviews/scala3-book/types-structural.md +++ b/_zh-cn/overviews/scala3-book/types-structural.md @@ -2,6 +2,7 @@ title: 结构化类型 type: section description: This section introduces and demonstrates structural types in Scala 3. +languages:[en] num: 55 previous-page: types-opaque-types next-page: types-dependent-function diff --git a/_zh-cn/overviews/scala3-book/types-type-classes.md b/_zh-cn/overviews/scala3-book/types-type-classes.md index 331b83f2ab..4a7007d9ab 100644 --- a/_zh-cn/overviews/scala3-book/types-type-classes.md +++ b/_zh-cn/overviews/scala3-book/types-type-classes.md @@ -2,6 +2,7 @@ title: Type Classes type: section description: This section introduces type classes in Scala 3. +languages:[en] num: 60 previous-page: ca-given-using-clauses next-page: ca-context-bounds diff --git a/_zh-cn/overviews/scala3-book/types-union.md b/_zh-cn/overviews/scala3-book/types-union.md index 826fc63acd..192c23fdee 100644 --- a/_zh-cn/overviews/scala3-book/types-union.md +++ b/_zh-cn/overviews/scala3-book/types-union.md @@ -2,6 +2,7 @@ title: 联合类型 type: section description: This section introduces and demonstrates union types in Scala 3. +languages:[en] num: 51 previous-page: types-intersection next-page: types-adts-gadts diff --git a/_zh-cn/overviews/scala3-book/types-variance.md b/_zh-cn/overviews/scala3-book/types-variance.md index 9b6274d6ec..e24949842f 100644 --- a/_zh-cn/overviews/scala3-book/types-variance.md +++ b/_zh-cn/overviews/scala3-book/types-variance.md @@ -2,6 +2,7 @@ title: 型变 type: section description: This section introduces and demonstrates variance in Scala 3. +languages:[en] num: 53 previous-page: types-adts-gadts next-page: types-opaque-types diff --git a/_zh-cn/overviews/scala3-book/where-next.md b/_zh-cn/overviews/scala3-book/where-next.md index 3cd5a6e729..c4e79341d0 100644 --- a/_zh-cn/overviews/scala3-book/where-next.md +++ b/_zh-cn/overviews/scala3-book/where-next.md @@ -2,6 +2,7 @@ title: 下一步去哪 type: chapter description: Where to go next after reading the Scala Book +languages:[en] num: 76 previous-page: scala-for-python-devs next-page: diff --git a/_zh-cn/overviews/scala3-book/why-scala-3.md b/_zh-cn/overviews/scala3-book/why-scala-3.md index ce9eba7084..207acf248e 100644 --- a/_zh-cn/overviews/scala3-book/why-scala-3.md +++ b/_zh-cn/overviews/scala3-book/why-scala-3.md @@ -2,6 +2,7 @@ title: 为什么是 Scala 3 ? type: chapter description: This page describes the benefits of the Scala 3 programming language. +languages:[en, ru] num: 3 previous-page: scala-features next-page: taste-intro From 470973607a3913ef7fd2adbe5d850d8f859d2c38 Mon Sep 17 00:00:00 2001 From: Scala Improvement Bot Date: Sat, 31 Dec 2022 00:21:11 +0000 Subject: [PATCH 2525/3174] Update SIPs state --- _sips/sips/wildcard-context-bounds.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 _sips/sips/wildcard-context-bounds.md diff --git a/_sips/sips/wildcard-context-bounds.md b/_sips/sips/wildcard-context-bounds.md new file mode 100644 index 0000000000..bdbcb76ebd --- /dev/null +++ b/_sips/sips/wildcard-context-bounds.md @@ -0,0 +1,7 @@ +--- +title: SIP-52 - Wildcard context bounds +status: under-review +pull-request-number: 55 +stage: design + +--- From 50701f2d7749630a45b784236d7fff95ea2b67d0 Mon Sep 17 00:00:00 2001 From: Mohammad Hossein Ghaffari <13206657+mhghaffari@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:03:33 +0330 Subject: [PATCH 2526/3174] Update pattern-matching.md The `VoiceRecording` case was not existed in the code to cause the warning. --- _tour/pattern-matching.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index 4ef988529b..60c00669a1 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -255,6 +255,8 @@ def showNotification(notification: Notification): String = { s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" + case VoiceRecording(contactName: String, link: String) => + s"You received a Voice Recording from $name! Click the link to hear it: $link" } } ``` @@ -267,6 +269,8 @@ def showNotification(notification: Notification): String = s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" + case VoiceRecording(contactName: String, link: String) => + s"You received a Voice Recording from $name! Click the link to hear it: $link" ``` {% endtab %} {% endtabs %} From 5af3d5ee7fd11585f92a0d660f8306a2e72fa116 Mon Sep 17 00:00:00 2001 From: Mohammad Hossein Ghaffari <13206657+mhghaffari@users.noreply.github.com> Date: Mon, 2 Jan 2023 18:04:44 +0330 Subject: [PATCH 2527/3174] Update _tour/pattern-matching.md Co-authored-by: Philippus Baalman --- _tour/pattern-matching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index 60c00669a1..8e3374c837 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -255,7 +255,7 @@ def showNotification(notification: Notification): String = { s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" - case VoiceRecording(contactName: String, link: String) => + case VoiceRecording(name, link) => s"You received a Voice Recording from $name! Click the link to hear it: $link" } } From 50c97d5d800e106f160e5bcc3a63b52fe0a64385 Mon Sep 17 00:00:00 2001 From: Mohammad Hossein Ghaffari <13206657+mhghaffari@users.noreply.github.com> Date: Mon, 2 Jan 2023 18:04:53 +0330 Subject: [PATCH 2528/3174] Update _tour/pattern-matching.md Co-authored-by: Philippus Baalman --- _tour/pattern-matching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index 8e3374c837..8086f51b06 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -269,7 +269,7 @@ def showNotification(notification: Notification): String = s"You got an email from $sender with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" - case VoiceRecording(contactName: String, link: String) => + case VoiceRecording(name, link) => s"You received a Voice Recording from $name! Click the link to hear it: $link" ``` {% endtab %} From 0b40560157bc4d94ac6e8f4eb4a438d4eb843d64 Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Tue, 3 Jan 2023 20:57:56 +0800 Subject: [PATCH 2529/3174] corrected to "language: zh-cn" --- _zh-cn/overviews/scala3-book/ca-context-bounds.md | 2 +- .../scala3-book/ca-contextual-abstractions-intro.md | 2 +- _zh-cn/overviews/scala3-book/ca-extension-methods.md | 2 +- _zh-cn/overviews/scala3-book/ca-given-imports.md | 2 +- _zh-cn/overviews/scala3-book/ca-given-using-clauses.md | 2 +- _zh-cn/overviews/scala3-book/ca-implicit-conversions.md | 2 +- _zh-cn/overviews/scala3-book/ca-multiversal-equality.md | 2 +- _zh-cn/overviews/scala3-book/ca-summary.md | 2 +- _zh-cn/overviews/scala3-book/ca-type-classes.md | 2 +- _zh-cn/overviews/scala3-book/collections-classes.md | 6 +++--- _zh-cn/overviews/scala3-book/collections-intro.md | 2 +- _zh-cn/overviews/scala3-book/collections-methods.md | 2 +- _zh-cn/overviews/scala3-book/collections-summary.md | 2 +- _zh-cn/overviews/scala3-book/concurrency.md | 2 +- _zh-cn/overviews/scala3-book/control-structures.md | 2 +- _zh-cn/overviews/scala3-book/domain-modeling-fp.md | 2 +- _zh-cn/overviews/scala3-book/domain-modeling-intro.md | 2 +- _zh-cn/overviews/scala3-book/domain-modeling-oop.md | 2 +- _zh-cn/overviews/scala3-book/domain-modeling-tools.md | 2 +- _zh-cn/overviews/scala3-book/first-look-at-types.md | 2 +- .../overviews/scala3-book/fp-functional-error-handling.md | 2 +- _zh-cn/overviews/scala3-book/fp-functions-are-values.md | 8 +------- _zh-cn/overviews/scala3-book/fp-immutable-values.md | 2 +- _zh-cn/overviews/scala3-book/fp-intro.md | 2 +- _zh-cn/overviews/scala3-book/fp-pure-functions.md | 2 +- _zh-cn/overviews/scala3-book/fp-summary.md | 2 +- _zh-cn/overviews/scala3-book/fp-what-is-fp.md | 2 +- _zh-cn/overviews/scala3-book/fun-anonymous-functions.md | 2 +- _zh-cn/overviews/scala3-book/fun-eta-expansion.md | 2 +- _zh-cn/overviews/scala3-book/fun-function-variables.md | 2 +- _zh-cn/overviews/scala3-book/fun-hofs.md | 2 +- _zh-cn/overviews/scala3-book/fun-intro.md | 2 +- _zh-cn/overviews/scala3-book/fun-summary.md | 2 +- _zh-cn/overviews/scala3-book/fun-write-map-function.md | 2 +- .../scala3-book/fun-write-method-returns-function.md | 2 +- _zh-cn/overviews/scala3-book/interacting-with-java.md | 2 +- _zh-cn/overviews/scala3-book/introduction.md | 2 +- _zh-cn/overviews/scala3-book/methods-intro.md | 2 +- _zh-cn/overviews/scala3-book/methods-main-methods.md | 2 +- _zh-cn/overviews/scala3-book/methods-most.md | 2 +- _zh-cn/overviews/scala3-book/methods-summary.md | 2 +- _zh-cn/overviews/scala3-book/packaging-imports.md | 2 +- _zh-cn/overviews/scala3-book/scala-features.md | 6 +----- _zh-cn/overviews/scala3-book/scala-for-java-devs.md | 2 +- _zh-cn/overviews/scala3-book/scala-for-javascript-devs.md | 2 +- _zh-cn/overviews/scala3-book/scala-for-python-devs.md | 2 +- _zh-cn/overviews/scala3-book/scala-tools.md | 2 +- _zh-cn/overviews/scala3-book/taste-collections.md | 2 +- .../scala3-book/taste-contextual-abstractions.md | 2 +- _zh-cn/overviews/scala3-book/taste-control-structures.md | 2 +- _zh-cn/overviews/scala3-book/taste-functions.md | 2 +- _zh-cn/overviews/scala3-book/taste-hello-world.md | 2 +- _zh-cn/overviews/scala3-book/taste-intro.md | 2 +- _zh-cn/overviews/scala3-book/taste-methods.md | 2 +- _zh-cn/overviews/scala3-book/taste-modeling.md | 2 +- _zh-cn/overviews/scala3-book/taste-objects.md | 2 +- _zh-cn/overviews/scala3-book/taste-repl.md | 2 +- _zh-cn/overviews/scala3-book/taste-summary.md | 2 +- .../overviews/scala3-book/taste-toplevel-definitions.md | 2 +- _zh-cn/overviews/scala3-book/taste-vars-data-types.md | 2 +- _zh-cn/overviews/scala3-book/tools-sbt.md | 2 +- _zh-cn/overviews/scala3-book/tools-worksheets.md | 2 +- _zh-cn/overviews/scala3-book/types-adts-gadts.md | 2 +- _zh-cn/overviews/scala3-book/types-dependent-function.md | 2 +- _zh-cn/overviews/scala3-book/types-generics.md | 2 +- _zh-cn/overviews/scala3-book/types-inferred.md | 2 +- _zh-cn/overviews/scala3-book/types-intersection.md | 2 +- _zh-cn/overviews/scala3-book/types-introduction.md | 2 +- _zh-cn/overviews/scala3-book/types-opaque-types.md | 2 +- _zh-cn/overviews/scala3-book/types-others.md | 2 +- _zh-cn/overviews/scala3-book/types-structural.md | 2 +- _zh-cn/overviews/scala3-book/types-type-classes.md | 2 +- _zh-cn/overviews/scala3-book/types-union.md | 2 +- _zh-cn/overviews/scala3-book/types-variance.md | 2 +- _zh-cn/overviews/scala3-book/where-next.md | 2 +- _zh-cn/overviews/scala3-book/why-scala-3.md | 2 +- 76 files changed, 78 insertions(+), 88 deletions(-) diff --git a/_zh-cn/overviews/scala3-book/ca-context-bounds.md b/_zh-cn/overviews/scala3-book/ca-context-bounds.md index b47b9f5907..2227899378 100644 --- a/_zh-cn/overviews/scala3-book/ca-context-bounds.md +++ b/_zh-cn/overviews/scala3-book/ca-context-bounds.md @@ -2,7 +2,7 @@ title: 上下文绑定 type: section description: This page demonstrates Context Bounds in Scala 3. -languages:[en] +language: zh-cn num: 61 previous-page: types-type-classes next-page: ca-given-imports diff --git a/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md b/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md index 65fb42fb01..80136106d6 100644 --- a/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md +++ b/_zh-cn/overviews/scala3-book/ca-contextual-abstractions-intro.md @@ -2,7 +2,7 @@ title: 上下文抽象 type: chapter description: This chapter provides an introduction to the Scala 3 concept of Contextual Abstractions. -languages:[en] +language: zh-cn num: 58 previous-page: types-others next-page: ca-given-using-clauses diff --git a/_zh-cn/overviews/scala3-book/ca-extension-methods.md b/_zh-cn/overviews/scala3-book/ca-extension-methods.md index 8a7f3154ef..43738e53d2 100644 --- a/_zh-cn/overviews/scala3-book/ca-extension-methods.md +++ b/_zh-cn/overviews/scala3-book/ca-extension-methods.md @@ -2,7 +2,7 @@ title: 扩展方法 type: section description: This page demonstrates how Extension Methods work in Scala 3. -languages:[en] +language: zh-cn num: 63 previous-page: ca-given-imports next-page: ca-type-classes diff --git a/_zh-cn/overviews/scala3-book/ca-given-imports.md b/_zh-cn/overviews/scala3-book/ca-given-imports.md index 63721bf920..4c95c35d52 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-imports.md +++ b/_zh-cn/overviews/scala3-book/ca-given-imports.md @@ -2,7 +2,7 @@ title: Given 导入 type: section description: This page demonstrates how 'given' import statements work in Scala 3. -languages:[en] +language: zh-cn num: 62 previous-page: ca-context-bounds next-page: ca-extension-methods diff --git a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md index 888b749309..9a492c25aa 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md +++ b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md @@ -2,7 +2,7 @@ title: Given 实例和 Using 语句 type: section description: This page demonstrates how to use 'given' instances and 'using' clauses in Scala 3. -languages:[en] +language: zh-cn num: 59 previous-page: ca-contextual-abstractions-intro next-page: types-type-classes diff --git a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md index 3108f639c4..5ab40c8064 100644 --- a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md +++ b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md @@ -2,7 +2,7 @@ title: 隐式转换 type: section description: This page demonstrates how to implement Implicit Conversions in Scala 3. -languages:[en] +language: zh-cn num: 66 previous-page: ca-multiversal-equality next-page: ca-summary diff --git a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md index 6878ecb2b1..9c6d2f422c 100644 --- a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md +++ b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md @@ -2,7 +2,7 @@ title: 多元相等性 type: section description: This page demonstrates how to implement Multiversal Equality in Scala 3. -languages:[en] +language: zh-cn num: 65 previous-page: ca-type-classes next-page: ca-implicit-conversions diff --git a/_zh-cn/overviews/scala3-book/ca-summary.md b/_zh-cn/overviews/scala3-book/ca-summary.md index d66b9baa13..60b1fd01a5 100644 --- a/_zh-cn/overviews/scala3-book/ca-summary.md +++ b/_zh-cn/overviews/scala3-book/ca-summary.md @@ -2,7 +2,7 @@ title: 总结 type: section description: This page provides a summary of the Contextual Abstractions lessons. -languages:[en] +language: zh-cn num: 67 previous-page: ca-implicit-conversions next-page: concurrency diff --git a/_zh-cn/overviews/scala3-book/ca-type-classes.md b/_zh-cn/overviews/scala3-book/ca-type-classes.md index 46e36e4c4d..1cd49103a3 100644 --- a/_zh-cn/overviews/scala3-book/ca-type-classes.md +++ b/_zh-cn/overviews/scala3-book/ca-type-classes.md @@ -2,7 +2,7 @@ title: 实现类型类 type: section description: This page demonstrates how to create and use type classes in Scala 3. -languages:[en] +language: zh-cn num: 64 previous-page: ca-extension-methods next-page: ca-multiversal-equality diff --git a/_zh-cn/overviews/scala3-book/collections-classes.md b/_zh-cn/overviews/scala3-book/collections-classes.md index 0a56e4e0ed..307395fba9 100644 --- a/_zh-cn/overviews/scala3-book/collections-classes.md +++ b/_zh-cn/overviews/scala3-book/collections-classes.md @@ -2,7 +2,7 @@ title: 集合类型 type: section description: This page introduces the common Scala 3 collections types and some of their methods. -languages:[en] +language: zh-cn num: 37 previous-page: collections-intro next-page: collections-methods @@ -372,9 +372,9 @@ val people = ArrayBuffer( ```scala val nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3) -languages:[en] +language: zh-cn nums += 4 // ArrayBuffer(1, 2, 3, 4) -languages:[en] +language: zh-cn nums ++= List(5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6) ``` diff --git a/_zh-cn/overviews/scala3-book/collections-intro.md b/_zh-cn/overviews/scala3-book/collections-intro.md index 41e596f14e..6d21b2f59b 100644 --- a/_zh-cn/overviews/scala3-book/collections-intro.md +++ b/_zh-cn/overviews/scala3-book/collections-intro.md @@ -2,7 +2,7 @@ title: Scala 集合 type: chapter description: This page provides and introduction to the common collections classes and their methods in Scala 3. -languages:[en] +language: zh-cn num: 36 previous-page: packaging-imports next-page: collections-classes diff --git a/_zh-cn/overviews/scala3-book/collections-methods.md b/_zh-cn/overviews/scala3-book/collections-methods.md index 3dd16e82a6..93ca03d15a 100644 --- a/_zh-cn/overviews/scala3-book/collections-methods.md +++ b/_zh-cn/overviews/scala3-book/collections-methods.md @@ -2,7 +2,7 @@ title: 集合方法 type: section description: This page demonstrates the common methods on the Scala 3 collections classes. -languages:[en] +language: zh-cn num: 38 previous-page: collections-classes next-page: collections-summary diff --git a/_zh-cn/overviews/scala3-book/collections-summary.md b/_zh-cn/overviews/scala3-book/collections-summary.md index 63269efe24..465f339f19 100644 --- a/_zh-cn/overviews/scala3-book/collections-summary.md +++ b/_zh-cn/overviews/scala3-book/collections-summary.md @@ -2,7 +2,7 @@ title: 总结 type: section description: This page provides a summary of the Collections chapter. -languages:[en] +language: zh-cn num: 39 previous-page: collections-methods next-page: fp-intro diff --git a/_zh-cn/overviews/scala3-book/concurrency.md b/_zh-cn/overviews/scala3-book/concurrency.md index bbbeca4b0d..169e1f1684 100644 --- a/_zh-cn/overviews/scala3-book/concurrency.md +++ b/_zh-cn/overviews/scala3-book/concurrency.md @@ -2,7 +2,7 @@ title: 并发 type: chapter description: This page discusses how Scala concurrency works, with an emphasis on Scala Futures. -languages:[en] +language: zh-cn num: 68 previous-page: ca-summary next-page: scala-tools diff --git a/_zh-cn/overviews/scala3-book/control-structures.md b/_zh-cn/overviews/scala3-book/control-structures.md index bc5bfc06ff..a639686f9c 100644 --- a/_zh-cn/overviews/scala3-book/control-structures.md +++ b/_zh-cn/overviews/scala3-book/control-structures.md @@ -2,7 +2,7 @@ title: 控制结构 type: chapter 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. -languages:[en, ru] +language: zh-cn num: 18 previous-page: first-look-at-types next-page: domain-modeling-intro diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-fp.md b/_zh-cn/overviews/scala3-book/domain-modeling-fp.md index 4ba980d9d0..e9f6933cad 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-fp.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-fp.md @@ -2,7 +2,7 @@ title: 函数式领域建模 type: section description: This chapter provides an introduction to FP domain modeling with Scala 3. -languages:[en, ru] +language: zh-cn num: 22 previous-page: domain-modeling-oop next-page: methods-intro diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-intro.md b/_zh-cn/overviews/scala3-book/domain-modeling-intro.md index 9a36b2894b..db31d9c528 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-intro.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-intro.md @@ -2,7 +2,7 @@ title: 领域建模 type: chapter description: This chapter provides an introduction to domain modeling in Scala 3. -languages:[en, ru] +language: zh-cn num: 19 previous-page: control-structures next-page: domain-modeling-tools diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-oop.md b/_zh-cn/overviews/scala3-book/domain-modeling-oop.md index 204e1ce3c1..a04c1fba41 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-oop.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-oop.md @@ -2,7 +2,7 @@ title: OOP 领域建模 type: section description: This chapter provides an introduction to OOP domain modeling with Scala 3. -languages:[en, ru] +language: zh-cn num: 21 previous-page: domain-modeling-tools next-page: domain-modeling-fp diff --git a/_zh-cn/overviews/scala3-book/domain-modeling-tools.md b/_zh-cn/overviews/scala3-book/domain-modeling-tools.md index 42deec841b..eb37e8e7f4 100644 --- a/_zh-cn/overviews/scala3-book/domain-modeling-tools.md +++ b/_zh-cn/overviews/scala3-book/domain-modeling-tools.md @@ -2,7 +2,7 @@ title: 工具 type: section description: This chapter provides an introduction to the available domain modeling tools in Scala 3, including classes, traits, enums, and more. -languages:[en, ru] +language: zh-cn num: 20 previous-page: domain-modeling-intro next-page: domain-modeling-oop diff --git a/_zh-cn/overviews/scala3-book/first-look-at-types.md b/_zh-cn/overviews/scala3-book/first-look-at-types.md index 692e7707b8..03604b8180 100644 --- a/_zh-cn/overviews/scala3-book/first-look-at-types.md +++ b/_zh-cn/overviews/scala3-book/first-look-at-types.md @@ -2,7 +2,7 @@ title: 类型初探 type: chapter description: This page provides a brief introduction to Scala's built-in data types, including Int, Double, String, Long, Any, AnyRef, Nothing, and Null. -languages:[en, ru] +language: zh-cn num: 17 previous-page: taste-summary next-page: control-structures diff --git a/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md b/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md index 7cb70257ff..d16d0eb80c 100644 --- a/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md +++ b/_zh-cn/overviews/scala3-book/fp-functional-error-handling.md @@ -2,7 +2,7 @@ title: 函数式错误处理 type: section description: This section provides an introduction to functional error handling in Scala 3. -languages:[en] +language: zh-cn num: 45 previous-page: fp-functions-are-values next-page: fp-summary diff --git a/_zh-cn/overviews/scala3-book/fp-functions-are-values.md b/_zh-cn/overviews/scala3-book/fp-functions-are-values.md index 1e5a571c9d..472abcead3 100644 --- a/_zh-cn/overviews/scala3-book/fp-functions-are-values.md +++ b/_zh-cn/overviews/scala3-book/fp-functions-are-values.md @@ -2,7 +2,7 @@ title: 函数是值 type: section description: This section looks at the use of functions as values in functional programming. -languages:[en] +language: zh-cn num: 44 previous-page: fp-pure-functions next-page: fp-functional-error-handling @@ -92,18 +92,12 @@ fruits.map(_.toUpperCase) // List(APPLE, PEAR) fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R) val nums = List(5, 1, 3, 11, 7) -languages:[en] nums.map(_ * 2) // List(10, 2, 6, 22, 14) -languages:[en] nums.filter(_ > 3) // List(5, 11, 7) -languages:[en] nums.takeWhile(_ < 6) // List(5, 1, 3) -languages:[en] nums.sortWith(_ < _) // List(1, 3, 5, 7, 11) -languages:[en] nums.sortWith(_ > _) // List(11, 7, 5, 3, 1) -languages:[en] nums.takeWhile(_ < 6).sortWith(_ < _) // List(1, 3, 5) ``` diff --git a/_zh-cn/overviews/scala3-book/fp-immutable-values.md b/_zh-cn/overviews/scala3-book/fp-immutable-values.md index 27a192d7e6..eb39d3daec 100644 --- a/_zh-cn/overviews/scala3-book/fp-immutable-values.md +++ b/_zh-cn/overviews/scala3-book/fp-immutable-values.md @@ -2,7 +2,7 @@ title: 不可变值 type: section description: This section looks at the use of immutable values in functional programming. -languages:[en] +language: zh-cn num: 42 previous-page: fp-what-is-fp next-page: fp-pure-functions diff --git a/_zh-cn/overviews/scala3-book/fp-intro.md b/_zh-cn/overviews/scala3-book/fp-intro.md index 39e500d187..f0862626d2 100644 --- a/_zh-cn/overviews/scala3-book/fp-intro.md +++ b/_zh-cn/overviews/scala3-book/fp-intro.md @@ -2,7 +2,7 @@ title: 函数式编程 type: chapter description: This chapter provides an introduction to functional programming in Scala 3. -languages:[en] +language: zh-cn num: 40 previous-page: collections-summary next-page: fp-what-is-fp diff --git a/_zh-cn/overviews/scala3-book/fp-pure-functions.md b/_zh-cn/overviews/scala3-book/fp-pure-functions.md index 135a0c48bc..ef4803036a 100644 --- a/_zh-cn/overviews/scala3-book/fp-pure-functions.md +++ b/_zh-cn/overviews/scala3-book/fp-pure-functions.md @@ -2,7 +2,7 @@ title: 纯函数 type: section description: This section looks at the use of pure functions in functional programming. -languages:[en] +language: zh-cn num: 43 previous-page: fp-immutable-values next-page: fp-functions-are-values diff --git a/_zh-cn/overviews/scala3-book/fp-summary.md b/_zh-cn/overviews/scala3-book/fp-summary.md index 6541bc074e..f9c4dfce8f 100644 --- a/_zh-cn/overviews/scala3-book/fp-summary.md +++ b/_zh-cn/overviews/scala3-book/fp-summary.md @@ -2,7 +2,7 @@ title: 总结 type: section description: This section summarizes the previous functional programming sections. -languages:[en] +language: zh-cn num: 46 previous-page: fp-functional-error-handling next-page: types-introduction diff --git a/_zh-cn/overviews/scala3-book/fp-what-is-fp.md b/_zh-cn/overviews/scala3-book/fp-what-is-fp.md index a4f5164926..6411b55c41 100644 --- a/_zh-cn/overviews/scala3-book/fp-what-is-fp.md +++ b/_zh-cn/overviews/scala3-book/fp-what-is-fp.md @@ -2,7 +2,7 @@ title: 什么是函数式编程? type: section description: This section provides an answer to the question, what is functional programming? -languages:[en] +language: zh-cn num: 41 previous-page: fp-intro next-page: fp-immutable-values diff --git a/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md b/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md index 88f92897d5..f86a953bae 100644 --- a/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md +++ b/_zh-cn/overviews/scala3-book/fun-anonymous-functions.md @@ -2,7 +2,7 @@ title: 匿名函数 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. -languages:[en, ru] +language: zh-cn num: 28 previous-page: fun-intro next-page: fun-function-variables diff --git a/_zh-cn/overviews/scala3-book/fun-eta-expansion.md b/_zh-cn/overviews/scala3-book/fun-eta-expansion.md index 7db5c96729..1c9ec31128 100644 --- a/_zh-cn/overviews/scala3-book/fun-eta-expansion.md +++ b/_zh-cn/overviews/scala3-book/fun-eta-expansion.md @@ -2,7 +2,7 @@ title: Eta 扩展 type: section description: This page discusses Eta Expansion, the Scala technology that automatically and transparently converts methods into functions. -languages:[en, ru] +language: zh-cn num: 30 previous-page: fun-function-variables next-page: fun-hofs diff --git a/_zh-cn/overviews/scala3-book/fun-function-variables.md b/_zh-cn/overviews/scala3-book/fun-function-variables.md index 078467197b..3113b83a37 100644 --- a/_zh-cn/overviews/scala3-book/fun-function-variables.md +++ b/_zh-cn/overviews/scala3-book/fun-function-variables.md @@ -2,7 +2,7 @@ title: 函数变量 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. -languages:[en, ru] +language: zh-cn num: 29 previous-page: fun-anonymous-functions next-page: fun-eta-expansion diff --git a/_zh-cn/overviews/scala3-book/fun-hofs.md b/_zh-cn/overviews/scala3-book/fun-hofs.md index 241f854966..3b5128e73f 100644 --- a/_zh-cn/overviews/scala3-book/fun-hofs.md +++ b/_zh-cn/overviews/scala3-book/fun-hofs.md @@ -2,7 +2,7 @@ title: 高阶函数 type: section description: This page demonstrates how to create and use higher-order functions in Scala. -languages:[en, ru] +language: zh-cn num: 31 previous-page: fun-eta-expansion next-page: fun-write-map-function diff --git a/_zh-cn/overviews/scala3-book/fun-intro.md b/_zh-cn/overviews/scala3-book/fun-intro.md index f42b272885..4bc7aceab3 100644 --- a/_zh-cn/overviews/scala3-book/fun-intro.md +++ b/_zh-cn/overviews/scala3-book/fun-intro.md @@ -2,7 +2,7 @@ title: 函数 type: chapter description: This chapter looks at all topics related to functions in Scala 3. -languages:[en, ru] +language: zh-cn num: 27 previous-page: methods-summary next-page: fun-anonymous-functions diff --git a/_zh-cn/overviews/scala3-book/fun-summary.md b/_zh-cn/overviews/scala3-book/fun-summary.md index fb382d2bee..f5bcecaaa2 100644 --- a/_zh-cn/overviews/scala3-book/fun-summary.md +++ b/_zh-cn/overviews/scala3-book/fun-summary.md @@ -2,7 +2,7 @@ title: 总结 type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. -languages:[en, ru] +language: zh-cn num: 34 previous-page: fun-write-method-returns-function next-page: packaging-imports diff --git a/_zh-cn/overviews/scala3-book/fun-write-map-function.md b/_zh-cn/overviews/scala3-book/fun-write-map-function.md index bb8e82b056..0a48d583ec 100644 --- a/_zh-cn/overviews/scala3-book/fun-write-map-function.md +++ b/_zh-cn/overviews/scala3-book/fun-write-map-function.md @@ -2,7 +2,7 @@ title: 自定义 map 函数 type: section description: This page demonstrates how to create and use higher-order functions in Scala. -languages:[en, ru] +language: zh-cn num: 32 previous-page: fun-hofs next-page: fun-write-method-returns-function diff --git a/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md b/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md index fa93960616..0272c5242e 100644 --- a/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md +++ b/_zh-cn/overviews/scala3-book/fun-write-method-returns-function.md @@ -2,7 +2,7 @@ title: 创建可以返回函数的方法 type: section description: This page demonstrates how to create and use higher-order functions in Scala. -languages:[en, ru] +language: zh-cn num: 33 previous-page: fun-write-map-function next-page: fun-summary diff --git a/_zh-cn/overviews/scala3-book/interacting-with-java.md b/_zh-cn/overviews/scala3-book/interacting-with-java.md index 0498d7919b..f2263d0bd2 100644 --- a/_zh-cn/overviews/scala3-book/interacting-with-java.md +++ b/_zh-cn/overviews/scala3-book/interacting-with-java.md @@ -2,7 +2,7 @@ title: 与 Java 交互 type: chapter description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. -languages:[en] +language: zh-cn num: 72 previous-page: tools-worksheets next-page: scala-for-java-devs diff --git a/_zh-cn/overviews/scala3-book/introduction.md b/_zh-cn/overviews/scala3-book/introduction.md index 06fb982d8e..2e82050a0e 100644 --- a/_zh-cn/overviews/scala3-book/introduction.md +++ b/_zh-cn/overviews/scala3-book/introduction.md @@ -2,7 +2,7 @@ title: 导言 type: chapter description: This page begins the overview documentation of the Scala 3 language. -languages:[en, ru] +language: zh-cn num: 1 previous-page: next-page: scala-features diff --git a/_zh-cn/overviews/scala3-book/methods-intro.md b/_zh-cn/overviews/scala3-book/methods-intro.md index fd6e1a6006..4c72c7e549 100644 --- a/_zh-cn/overviews/scala3-book/methods-intro.md +++ b/_zh-cn/overviews/scala3-book/methods-intro.md @@ -2,7 +2,7 @@ title: 方法 type: chapter description: This section introduces methods in Scala 3. -languages:[en, ru] +language: zh-cn num: 23 previous-page: domain-modeling-fp next-page: methods-most diff --git a/_zh-cn/overviews/scala3-book/methods-main-methods.md b/_zh-cn/overviews/scala3-book/methods-main-methods.md index 42cccddfd1..82d711b231 100644 --- a/_zh-cn/overviews/scala3-book/methods-main-methods.md +++ b/_zh-cn/overviews/scala3-book/methods-main-methods.md @@ -2,7 +2,7 @@ title: main 方法 type: section description: This page describes how 'main' methods and the '@main' annotation work in Scala 3. -languages:[en, ru] +language: zh-cn num: 25 previous-page: methods-most next-page: methods-summary diff --git a/_zh-cn/overviews/scala3-book/methods-most.md b/_zh-cn/overviews/scala3-book/methods-most.md index c73453fd90..b1aa18a6fc 100644 --- a/_zh-cn/overviews/scala3-book/methods-most.md +++ b/_zh-cn/overviews/scala3-book/methods-most.md @@ -2,7 +2,7 @@ title: 方法特性 type: section description: This section introduces Scala 3 methods, including main methods, extension methods, and more. -languages:[en, ru] +language: zh-cn num: 24 previous-page: methods-intro next-page: methods-main-methods diff --git a/_zh-cn/overviews/scala3-book/methods-summary.md b/_zh-cn/overviews/scala3-book/methods-summary.md index 20fd7cb68b..d406f100c0 100644 --- a/_zh-cn/overviews/scala3-book/methods-summary.md +++ b/_zh-cn/overviews/scala3-book/methods-summary.md @@ -2,7 +2,7 @@ title: 总结 type: section description: This section summarizes the previous sections on Scala 3 methods. -languages:[en, ru] +language: zh-cn num: 26 previous-page: methods-main-methods next-page: fun-intro diff --git a/_zh-cn/overviews/scala3-book/packaging-imports.md b/_zh-cn/overviews/scala3-book/packaging-imports.md index 190796573a..b121f8b99c 100644 --- a/_zh-cn/overviews/scala3-book/packaging-imports.md +++ b/_zh-cn/overviews/scala3-book/packaging-imports.md @@ -2,7 +2,7 @@ title: 打包和导入 type: chapter description: A discussion of using packages and imports to organize your code, build related modules of code, control scope, and help prevent namespace collisions. -languages:[en] +language: zh-cn num: 35 previous-page: fun-summary next-page: collections-intro diff --git a/_zh-cn/overviews/scala3-book/scala-features.md b/_zh-cn/overviews/scala3-book/scala-features.md index 0b9761fe17..3674c522e5 100644 --- a/_zh-cn/overviews/scala3-book/scala-features.md +++ b/_zh-cn/overviews/scala3-book/scala-features.md @@ -2,7 +2,7 @@ title: Scala 3 特性 type: chapter description: This page discusses the main features of the Scala 3 programming language. -languages:[en, ru] +language: zh-cn num: 2 previous-page: introduction next-page: why-scala-3 @@ -117,14 +117,10 @@ val p = Person("Martin", "Odersky") {% tabs scala-features-4 %} {% tab 'Scala 2 and 3' for=scala-features-4 %} ```scala -languages:[en] nums.map(i => i * 2) // long form -languages:[en] nums.map(_ * 2) // short form -languages:[en] nums.filter(i => i > 1) -languages:[en] nums.filter(_ > 1) ``` {% endtab %} diff --git a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md index de7b4eea7a..39e9761c61 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md @@ -2,7 +2,7 @@ title: 向 Java 开发者介绍Scala type: chapter description: This page is for Java developers who are interested in learning about Scala 3. -languages:[en] +language: zh-cn num: 73 previous-page: interacting-with-java next-page: scala-for-javascript-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md b/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md index c5f4b907bd..aaaaf68bba 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md +++ b/_zh-cn/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 -languages:[en] +language: zh-cn num: 74 previous-page: scala-for-java-devs next-page: scala-for-python-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md index 4ee6dee030..f04d664894 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md +++ b/_zh-cn/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. -languages:[en] +language: zh-cn num: 75 previous-page: scala-for-javascript-devs next-page: diff --git a/_zh-cn/overviews/scala3-book/scala-tools.md b/_zh-cn/overviews/scala3-book/scala-tools.md index 4cd1637244..822c3d428a 100644 --- a/_zh-cn/overviews/scala3-book/scala-tools.md +++ b/_zh-cn/overviews/scala3-book/scala-tools.md @@ -2,7 +2,7 @@ title: Scala 工具 type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. -languages:[en] +language: zh-cn num: 69 previous-page: concurrency next-page: tools-sbt diff --git a/_zh-cn/overviews/scala3-book/taste-collections.md b/_zh-cn/overviews/scala3-book/taste-collections.md index 589a498f0a..d6b987a7a6 100644 --- a/_zh-cn/overviews/scala3-book/taste-collections.md +++ b/_zh-cn/overviews/scala3-book/taste-collections.md @@ -2,7 +2,7 @@ title: Collections type: section description: This page provides a high-level overview of the main features of the Scala 3 programming language. -languages:[en, ru] +language: zh-cn num: 13 previous-page: taste-objects next-page: taste-contextual-abstractions diff --git a/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md b/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md index 6d181d09fa..d5610c6872 100644 --- a/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md +++ b/_zh-cn/overviews/scala3-book/taste-contextual-abstractions.md @@ -2,7 +2,7 @@ title: Contextual Abstractions type: section description: This section provides an introduction to Contextual Abstractions in Scala 3. -languages:[en, ru] +language: zh-cn num: 14 previous-page: taste-collections next-page: taste-toplevel-definitions diff --git a/_zh-cn/overviews/scala3-book/taste-control-structures.md b/_zh-cn/overviews/scala3-book/taste-control-structures.md index e45fbd3849..ea26f0ff42 100644 --- a/_zh-cn/overviews/scala3-book/taste-control-structures.md +++ b/_zh-cn/overviews/scala3-book/taste-control-structures.md @@ -2,7 +2,7 @@ title: 控制结构 type: section description: This section demonstrates Scala 3 control structures. -languages:[en, ru] +language: zh-cn num: 8 previous-page: taste-vars-data-types next-page: taste-modeling diff --git a/_zh-cn/overviews/scala3-book/taste-functions.md b/_zh-cn/overviews/scala3-book/taste-functions.md index 637dd40216..9c52d09213 100644 --- a/_zh-cn/overviews/scala3-book/taste-functions.md +++ b/_zh-cn/overviews/scala3-book/taste-functions.md @@ -2,7 +2,7 @@ title: First-Class Functions type: section description: This page provides an introduction to functions in Scala 3. -languages:[en, ru] +language: zh-cn num: 11 previous-page: taste-methods next-page: taste-objects diff --git a/_zh-cn/overviews/scala3-book/taste-hello-world.md b/_zh-cn/overviews/scala3-book/taste-hello-world.md index 2b8a8bd1b6..cebe30f7fa 100644 --- a/_zh-cn/overviews/scala3-book/taste-hello-world.md +++ b/_zh-cn/overviews/scala3-book/taste-hello-world.md @@ -2,7 +2,7 @@ title: Hello, World! type: section description: This section demonstrates a Scala 3 'Hello, World!' example. -languages:[en, ru] +language: zh-cn num: 5 previous-page: taste-intro next-page: taste-repl diff --git a/_zh-cn/overviews/scala3-book/taste-intro.md b/_zh-cn/overviews/scala3-book/taste-intro.md index fc975520c5..df7fed74bd 100644 --- a/_zh-cn/overviews/scala3-book/taste-intro.md +++ b/_zh-cn/overviews/scala3-book/taste-intro.md @@ -2,7 +2,7 @@ title: Scala 的味道 type: chapter description: This chapter provides a high-level overview of the main features of the Scala 3 programming language. -languages:[en, ru] +language: zh-cn num: 4 previous-page: why-scala-3 next-page: taste-hello-world diff --git a/_zh-cn/overviews/scala3-book/taste-methods.md b/_zh-cn/overviews/scala3-book/taste-methods.md index 1743286235..10e57ece93 100644 --- a/_zh-cn/overviews/scala3-book/taste-methods.md +++ b/_zh-cn/overviews/scala3-book/taste-methods.md @@ -2,7 +2,7 @@ title: Methods type: section description: This section provides an introduction to defining and using methods in Scala 3. -languages:[en, ru] +language: zh-cn num: 10 previous-page: taste-modeling next-page: taste-functions diff --git a/_zh-cn/overviews/scala3-book/taste-modeling.md b/_zh-cn/overviews/scala3-book/taste-modeling.md index 79fb6fa964..57981e10d3 100644 --- a/_zh-cn/overviews/scala3-book/taste-modeling.md +++ b/_zh-cn/overviews/scala3-book/taste-modeling.md @@ -2,7 +2,7 @@ title: 领域建模 type: section description: This section provides an introduction to data modeling in Scala 3. -languages:[en, ru] +language: zh-cn num: 9 previous-page: taste-control-structures next-page: taste-methods diff --git a/_zh-cn/overviews/scala3-book/taste-objects.md b/_zh-cn/overviews/scala3-book/taste-objects.md index f018639a04..e24d759a24 100644 --- a/_zh-cn/overviews/scala3-book/taste-objects.md +++ b/_zh-cn/overviews/scala3-book/taste-objects.md @@ -2,7 +2,7 @@ title: 单例对象 type: section description: This section provides an introduction to the use of singleton objects in Scala 3. -languages:[en, ru] +language: zh-cn num: 12 previous-page: taste-functions next-page: taste-collections diff --git a/_zh-cn/overviews/scala3-book/taste-repl.md b/_zh-cn/overviews/scala3-book/taste-repl.md index f79e289ee3..2b043bef03 100644 --- a/_zh-cn/overviews/scala3-book/taste-repl.md +++ b/_zh-cn/overviews/scala3-book/taste-repl.md @@ -2,7 +2,7 @@ title: The REPL type: section description: This section provides an introduction to the Scala REPL. -languages:[en, ru] +language: zh-cn num: 6 previous-page: taste-hello-world next-page: taste-vars-data-types diff --git a/_zh-cn/overviews/scala3-book/taste-summary.md b/_zh-cn/overviews/scala3-book/taste-summary.md index de94900bac..14c44c9bde 100644 --- a/_zh-cn/overviews/scala3-book/taste-summary.md +++ b/_zh-cn/overviews/scala3-book/taste-summary.md @@ -2,7 +2,7 @@ title: Summary type: section description: This page provides a summary of the previous 'Taste of Scala' sections. -languages:[en, ru] +language: zh-cn num: 16 previous-page: taste-toplevel-definitions next-page: first-look-at-types diff --git a/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md b/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md index f1999743c3..11b577896f 100644 --- a/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md +++ b/_zh-cn/overviews/scala3-book/taste-toplevel-definitions.md @@ -2,7 +2,7 @@ title: Toplevel Definitions type: section description: This page provides an introduction to top-level definitions in Scala 3 -languages:[en, ru] +language: zh-cn num: 15 previous-page: taste-contextual-abstractions next-page: taste-summary diff --git a/_zh-cn/overviews/scala3-book/taste-vars-data-types.md b/_zh-cn/overviews/scala3-book/taste-vars-data-types.md index c1d0642427..2c5a80e5a0 100644 --- a/_zh-cn/overviews/scala3-book/taste-vars-data-types.md +++ b/_zh-cn/overviews/scala3-book/taste-vars-data-types.md @@ -2,7 +2,7 @@ title: 变量和数据类型 type: section description: This section demonstrates val and var variables, and some common Scala data types. -languages:[en, ru] +language: zh-cn num: 7 previous-page: taste-repl next-page: taste-control-structures diff --git a/_zh-cn/overviews/scala3-book/tools-sbt.md b/_zh-cn/overviews/scala3-book/tools-sbt.md index 6e7c588fd3..3d4e78f4a1 100644 --- a/_zh-cn/overviews/scala3-book/tools-sbt.md +++ b/_zh-cn/overviews/scala3-book/tools-sbt.md @@ -2,7 +2,7 @@ title: 使用 sbt 构建和测试 Scala 项目 type: section description: This section looks at a commonly-used build tool, sbt, and a testing library, ScalaTest. -languages:[en] +language: zh-cn num: 70 previous-page: scala-tools next-page: tools-worksheets diff --git a/_zh-cn/overviews/scala3-book/tools-worksheets.md b/_zh-cn/overviews/scala3-book/tools-worksheets.md index 1de7f8a891..214b744d8b 100644 --- a/_zh-cn/overviews/scala3-book/tools-worksheets.md +++ b/_zh-cn/overviews/scala3-book/tools-worksheets.md @@ -2,7 +2,7 @@ title: worksheet type: section description: This section looks at worksheets, an alternative to Scala projects. -languages:[en] +language: zh-cn num: 71 previous-page: tools-sbt next-page: interacting-with-java diff --git a/_zh-cn/overviews/scala3-book/types-adts-gadts.md b/_zh-cn/overviews/scala3-book/types-adts-gadts.md index e311fb7a33..9d3e469333 100644 --- a/_zh-cn/overviews/scala3-book/types-adts-gadts.md +++ b/_zh-cn/overviews/scala3-book/types-adts-gadts.md @@ -2,7 +2,7 @@ title: 代数数据类型 type: section description: This section introduces and demonstrates algebraic data types (ADTs) in Scala 3. -languages:[en] +language: zh-cn num: 52 previous-page: types-union next-page: types-variance diff --git a/_zh-cn/overviews/scala3-book/types-dependent-function.md b/_zh-cn/overviews/scala3-book/types-dependent-function.md index d19e7abb6c..fa5c8d8c82 100644 --- a/_zh-cn/overviews/scala3-book/types-dependent-function.md +++ b/_zh-cn/overviews/scala3-book/types-dependent-function.md @@ -2,7 +2,7 @@ title: 依赖函数类型 type: section description: This section introduces and demonstrates dependent function types in Scala 3. -languages:[en] +language: zh-cn num: 56 previous-page: types-structural next-page: types-others diff --git a/_zh-cn/overviews/scala3-book/types-generics.md b/_zh-cn/overviews/scala3-book/types-generics.md index bc7eb8f379..45fb52865b 100644 --- a/_zh-cn/overviews/scala3-book/types-generics.md +++ b/_zh-cn/overviews/scala3-book/types-generics.md @@ -2,7 +2,7 @@ title: 泛型 type: section description: This section introduces and demonstrates generics in Scala 3. -languages:[en] +language: zh-cn num: 49 previous-page: types-inferred next-page: types-intersection diff --git a/_zh-cn/overviews/scala3-book/types-inferred.md b/_zh-cn/overviews/scala3-book/types-inferred.md index db6c282662..ba52c8a9ce 100644 --- a/_zh-cn/overviews/scala3-book/types-inferred.md +++ b/_zh-cn/overviews/scala3-book/types-inferred.md @@ -2,7 +2,7 @@ title: 类型推断 type: section description: This section introduces and demonstrates inferred types in Scala 3 -languages:[en] +language: zh-cn num: 48 previous-page: types-introduction next-page: types-generics diff --git a/_zh-cn/overviews/scala3-book/types-intersection.md b/_zh-cn/overviews/scala3-book/types-intersection.md index 870e0b6aac..085c92c893 100644 --- a/_zh-cn/overviews/scala3-book/types-intersection.md +++ b/_zh-cn/overviews/scala3-book/types-intersection.md @@ -2,7 +2,7 @@ title: 相交类型 type: section description: This section introduces and demonstrates intersection types in Scala 3. -languages:[en] +language: zh-cn num: 50 previous-page: types-generics next-page: types-union diff --git a/_zh-cn/overviews/scala3-book/types-introduction.md b/_zh-cn/overviews/scala3-book/types-introduction.md index 9c6e492976..2acc837a59 100644 --- a/_zh-cn/overviews/scala3-book/types-introduction.md +++ b/_zh-cn/overviews/scala3-book/types-introduction.md @@ -2,7 +2,7 @@ title: 类型和类型系统 type: chapter description: This chapter provides an introduction to Scala 3 types and the type system. -languages:[en] +language: zh-cn num: 47 previous-page: fp-summary next-page: types-inferred diff --git a/_zh-cn/overviews/scala3-book/types-opaque-types.md b/_zh-cn/overviews/scala3-book/types-opaque-types.md index 349a7272d7..f68f798641 100644 --- a/_zh-cn/overviews/scala3-book/types-opaque-types.md +++ b/_zh-cn/overviews/scala3-book/types-opaque-types.md @@ -2,7 +2,7 @@ title: 不透明类型 type: section description: This section introduces and demonstrates opaque types in Scala 3. -languages:[en] +language: zh-cn num: 54 previous-page: types-variance next-page: types-structural diff --git a/_zh-cn/overviews/scala3-book/types-others.md b/_zh-cn/overviews/scala3-book/types-others.md index 61f3a14a57..cb09102805 100644 --- a/_zh-cn/overviews/scala3-book/types-others.md +++ b/_zh-cn/overviews/scala3-book/types-others.md @@ -2,7 +2,7 @@ title: 其他类型 type: section description: This section mentions other advanced types in Scala 3. -languages:[en] +language: zh-cn num: 57 previous-page: types-dependent-function next-page: ca-contextual-abstractions-intro diff --git a/_zh-cn/overviews/scala3-book/types-structural.md b/_zh-cn/overviews/scala3-book/types-structural.md index bb7904c2c8..694da0c635 100644 --- a/_zh-cn/overviews/scala3-book/types-structural.md +++ b/_zh-cn/overviews/scala3-book/types-structural.md @@ -2,7 +2,7 @@ title: 结构化类型 type: section description: This section introduces and demonstrates structural types in Scala 3. -languages:[en] +language: zh-cn num: 55 previous-page: types-opaque-types next-page: types-dependent-function diff --git a/_zh-cn/overviews/scala3-book/types-type-classes.md b/_zh-cn/overviews/scala3-book/types-type-classes.md index 4a7007d9ab..88c39a5631 100644 --- a/_zh-cn/overviews/scala3-book/types-type-classes.md +++ b/_zh-cn/overviews/scala3-book/types-type-classes.md @@ -2,7 +2,7 @@ title: Type Classes type: section description: This section introduces type classes in Scala 3. -languages:[en] +language: zh-cn num: 60 previous-page: ca-given-using-clauses next-page: ca-context-bounds diff --git a/_zh-cn/overviews/scala3-book/types-union.md b/_zh-cn/overviews/scala3-book/types-union.md index 192c23fdee..204b1fcccb 100644 --- a/_zh-cn/overviews/scala3-book/types-union.md +++ b/_zh-cn/overviews/scala3-book/types-union.md @@ -2,7 +2,7 @@ title: 联合类型 type: section description: This section introduces and demonstrates union types in Scala 3. -languages:[en] +language: zh-cn num: 51 previous-page: types-intersection next-page: types-adts-gadts diff --git a/_zh-cn/overviews/scala3-book/types-variance.md b/_zh-cn/overviews/scala3-book/types-variance.md index e24949842f..f4b9ce2fa3 100644 --- a/_zh-cn/overviews/scala3-book/types-variance.md +++ b/_zh-cn/overviews/scala3-book/types-variance.md @@ -2,7 +2,7 @@ title: 型变 type: section description: This section introduces and demonstrates variance in Scala 3. -languages:[en] +language: zh-cn num: 53 previous-page: types-adts-gadts next-page: types-opaque-types diff --git a/_zh-cn/overviews/scala3-book/where-next.md b/_zh-cn/overviews/scala3-book/where-next.md index c4e79341d0..66c3afe639 100644 --- a/_zh-cn/overviews/scala3-book/where-next.md +++ b/_zh-cn/overviews/scala3-book/where-next.md @@ -2,7 +2,7 @@ title: 下一步去哪 type: chapter description: Where to go next after reading the Scala Book -languages:[en] +language: zh-cn num: 76 previous-page: scala-for-python-devs next-page: diff --git a/_zh-cn/overviews/scala3-book/why-scala-3.md b/_zh-cn/overviews/scala3-book/why-scala-3.md index 207acf248e..2259ad6c01 100644 --- a/_zh-cn/overviews/scala3-book/why-scala-3.md +++ b/_zh-cn/overviews/scala3-book/why-scala-3.md @@ -2,7 +2,7 @@ title: 为什么是 Scala 3 ? type: chapter description: This page describes the benefits of the Scala 3 programming language. -languages:[en, ru] +language: zh-cn num: 3 previous-page: scala-features next-page: taste-intro From 83add6d74bb508e28545c5f98ee966d23c40c71b Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Tue, 3 Jan 2023 21:12:25 +0800 Subject: [PATCH 2530/3174] delete types-type-classes.md in zh-cn. --- .../scala3-book/types-type-classes.md | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 _zh-cn/overviews/scala3-book/types-type-classes.md diff --git a/_zh-cn/overviews/scala3-book/types-type-classes.md b/_zh-cn/overviews/scala3-book/types-type-classes.md deleted file mode 100644 index 88c39a5631..0000000000 --- a/_zh-cn/overviews/scala3-book/types-type-classes.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Type Classes -type: section -description: This section introduces type classes in Scala 3. -language: zh-cn -num: 60 -previous-page: ca-given-using-clauses -next-page: ca-context-bounds - -partof: scala3-book -overview-name: "Scala 3 — Book" -layout: multipage-overview -permalink: "/zh-cn/scala3/book/:title.html" ---- - -A _type class_ is an abstract, parameterized type that lets you add new behavior to any closed data type without using sub-typing. -If you are coming from Java, you can think of type classes as something like [`java.util.Comparator[T]`][comparator]. - -> The paper [“Type Classes as Objects and Implicits”][typeclasses-paper] (2010) by Oliveira et al. discusses the basic ideas behind type classes in Scala. -> Even though the paper uses an older version of Scala, the ideas still hold to the current day. - -This style of programming is useful in multiple use-cases, for example: - -- Expressing how a type you don’t own---such as from the standard library or a third-party library---conforms to such behavior -- Adding behavior to multiple types without introducing sub-typing relationships between those types (i.e., one `extends` another) - -In Scala 3, _type classes_ are just _traits_ with one or more type parameters, like the following: -``` -trait Show[A]: - def show(a: A): String -``` -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 -class ShowInt extends Show[Int]: - def show(a: Int) = s"The number is ${a}!" -``` -We can write methods that work on arbitrary types `A` _constrained_ by `Show` as follows: - -```scala -def toHtml[A](a: A)(showA: Show[A]): String = - "

    " + showA.show(a) + "

    " -``` -That is, `toHtml` can be called with arbitrary `A` _as long_ as you can also provide an instance of `Show[A]`. -For example, we can call it like: -```scala -toHtml(42)(ShowInt()) -// results in "

    The number is 42!

    " -``` - -#### 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. - -[typeclasses-paper]: https://infoscience.epfl.ch/record/150280/files/TypeClasses.pdf -[typeclasses-chapter]: {% link _zh-cn/overviews/scala3-book/ca-type-classes.md %} -[comparator]: https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html From e6a6226b9da56c0bb3de21576711025634cf4645 Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Tue, 3 Jan 2023 21:42:58 +0800 Subject: [PATCH 2531/3174] change zh-cn files structure according to latest english version. --- _zh-cn/overviews/scala3-book/ca-extension-methods.md | 6 +++--- _zh-cn/overviews/scala3-book/ca-given-imports.md | 2 +- _zh-cn/overviews/scala3-book/ca-given-using-clauses.md | 6 +++--- _zh-cn/overviews/scala3-book/ca-implicit-conversions.md | 2 +- _zh-cn/overviews/scala3-book/ca-multiversal-equality.md | 2 +- _zh-cn/overviews/scala3-book/ca-summary.md | 2 +- _zh-cn/overviews/scala3-book/ca-type-classes.md | 4 ++-- _zh-cn/overviews/scala3-book/concurrency.md | 2 +- _zh-cn/overviews/scala3-book/interacting-with-java.md | 2 +- _zh-cn/overviews/scala3-book/scala-for-java-devs.md | 2 +- _zh-cn/overviews/scala3-book/scala-for-javascript-devs.md | 2 +- _zh-cn/overviews/scala3-book/scala-for-python-devs.md | 4 ++-- _zh-cn/overviews/scala3-book/scala-tools.md | 2 +- _zh-cn/overviews/scala3-book/tools-sbt.md | 2 +- _zh-cn/overviews/scala3-book/tools-worksheets.md | 2 +- _zh-cn/overviews/scala3-book/where-next.md | 2 +- 16 files changed, 22 insertions(+), 22 deletions(-) diff --git a/_zh-cn/overviews/scala3-book/ca-extension-methods.md b/_zh-cn/overviews/scala3-book/ca-extension-methods.md index 43738e53d2..7d780cae1f 100644 --- a/_zh-cn/overviews/scala3-book/ca-extension-methods.md +++ b/_zh-cn/overviews/scala3-book/ca-extension-methods.md @@ -3,9 +3,9 @@ title: 扩展方法 type: section description: This page demonstrates how Extension Methods work in Scala 3. language: zh-cn -num: 63 -previous-page: ca-given-imports -next-page: ca-type-classes +num: 59 +previous-page: ca-contextual-abstractions-intro +next-page: ca-given-using-clauses partof: scala3-book overview-name: "Scala 3 — Book" diff --git a/_zh-cn/overviews/scala3-book/ca-given-imports.md b/_zh-cn/overviews/scala3-book/ca-given-imports.md index 4c95c35d52..faf1e8569d 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-imports.md +++ b/_zh-cn/overviews/scala3-book/ca-given-imports.md @@ -5,7 +5,7 @@ description: This page demonstrates how 'given' import statements work in Scala language: zh-cn num: 62 previous-page: ca-context-bounds -next-page: ca-extension-methods +next-page: ca-type-classes partof: scala3-book overview-name: "Scala 3 — Book" diff --git a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md index 9a492c25aa..c562e5d167 100644 --- a/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md +++ b/_zh-cn/overviews/scala3-book/ca-given-using-clauses.md @@ -3,9 +3,9 @@ title: Given 实例和 Using 语句 type: section description: This page demonstrates how to use 'given' instances and 'using' clauses in Scala 3. language: zh-cn -num: 59 -previous-page: ca-contextual-abstractions-intro -next-page: types-type-classes +num: 60 +previous-page: ca-extension-methods +next-page: ca-context-bounds partof: scala3-book overview-name: "Scala 3 — Book" diff --git a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md index 5ab40c8064..69a12cba3e 100644 --- a/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md +++ b/_zh-cn/overviews/scala3-book/ca-implicit-conversions.md @@ -3,7 +3,7 @@ title: 隐式转换 type: section description: This page demonstrates how to implement Implicit Conversions in Scala 3. language: zh-cn -num: 66 +num: 65 previous-page: ca-multiversal-equality next-page: ca-summary diff --git a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md index 9c6d2f422c..aff8f1d53e 100644 --- a/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md +++ b/_zh-cn/overviews/scala3-book/ca-multiversal-equality.md @@ -3,7 +3,7 @@ title: 多元相等性 type: section description: This page demonstrates how to implement Multiversal Equality in Scala 3. language: zh-cn -num: 65 +num: 64 previous-page: ca-type-classes next-page: ca-implicit-conversions diff --git a/_zh-cn/overviews/scala3-book/ca-summary.md b/_zh-cn/overviews/scala3-book/ca-summary.md index 60b1fd01a5..c492e8f993 100644 --- a/_zh-cn/overviews/scala3-book/ca-summary.md +++ b/_zh-cn/overviews/scala3-book/ca-summary.md @@ -3,7 +3,7 @@ title: 总结 type: section description: This page provides a summary of the Contextual Abstractions lessons. language: zh-cn -num: 67 +num: 66 previous-page: ca-implicit-conversions next-page: concurrency diff --git a/_zh-cn/overviews/scala3-book/ca-type-classes.md b/_zh-cn/overviews/scala3-book/ca-type-classes.md index 1cd49103a3..3543f68a34 100644 --- a/_zh-cn/overviews/scala3-book/ca-type-classes.md +++ b/_zh-cn/overviews/scala3-book/ca-type-classes.md @@ -3,8 +3,8 @@ title: 实现类型类 type: section description: This page demonstrates how to create and use type classes in Scala 3. language: zh-cn -num: 64 -previous-page: ca-extension-methods +num: 63 +previous-page: ca-given-imports next-page: ca-multiversal-equality partof: scala3-book diff --git a/_zh-cn/overviews/scala3-book/concurrency.md b/_zh-cn/overviews/scala3-book/concurrency.md index 169e1f1684..1906f158ab 100644 --- a/_zh-cn/overviews/scala3-book/concurrency.md +++ b/_zh-cn/overviews/scala3-book/concurrency.md @@ -3,7 +3,7 @@ title: 并发 type: chapter description: This page discusses how Scala concurrency works, with an emphasis on Scala Futures. language: zh-cn -num: 68 +num: 67 previous-page: ca-summary next-page: scala-tools diff --git a/_zh-cn/overviews/scala3-book/interacting-with-java.md b/_zh-cn/overviews/scala3-book/interacting-with-java.md index f2263d0bd2..12682a9303 100644 --- a/_zh-cn/overviews/scala3-book/interacting-with-java.md +++ b/_zh-cn/overviews/scala3-book/interacting-with-java.md @@ -3,7 +3,7 @@ title: 与 Java 交互 type: chapter description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. language: zh-cn -num: 72 +num: 71 previous-page: tools-worksheets next-page: scala-for-java-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md index 39e9761c61..f4e20aa4c2 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-java-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-java-devs.md @@ -3,7 +3,7 @@ title: 向 Java 开发者介绍Scala type: chapter description: This page is for Java developers who are interested in learning about Scala 3. language: zh-cn -num: 73 +num: 72 previous-page: interacting-with-java next-page: scala-for-javascript-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md b/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md index aaaaf68bba..4563c43af4 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-javascript-devs.md @@ -3,7 +3,7 @@ title: Scala for JavaScript Developers type: chapter description: This chapter provides an introduction to Scala 3 for JavaScript developers language: zh-cn -num: 74 +num: 73 previous-page: scala-for-java-devs next-page: scala-for-python-devs diff --git a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md index f04d664894..e56d017fb0 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md @@ -3,9 +3,9 @@ title: Scala for Python Developers type: chapter description: This page is for Python developers who are interested in learning about Scala 3. language: zh-cn -num: 75 +num: 74 previous-page: scala-for-javascript-devs -next-page: +next-page: where-next partof: scala3-book overview-name: "Scala 3 — Book" diff --git a/_zh-cn/overviews/scala3-book/scala-tools.md b/_zh-cn/overviews/scala3-book/scala-tools.md index 822c3d428a..d773d0f837 100644 --- a/_zh-cn/overviews/scala3-book/scala-tools.md +++ b/_zh-cn/overviews/scala3-book/scala-tools.md @@ -3,7 +3,7 @@ title: Scala 工具 type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. language: zh-cn -num: 69 +num: 68 previous-page: concurrency next-page: tools-sbt diff --git a/_zh-cn/overviews/scala3-book/tools-sbt.md b/_zh-cn/overviews/scala3-book/tools-sbt.md index 3d4e78f4a1..362de902b4 100644 --- a/_zh-cn/overviews/scala3-book/tools-sbt.md +++ b/_zh-cn/overviews/scala3-book/tools-sbt.md @@ -3,7 +3,7 @@ title: 使用 sbt 构建和测试 Scala 项目 type: section description: This section looks at a commonly-used build tool, sbt, and a testing library, ScalaTest. language: zh-cn -num: 70 +num: 69 previous-page: scala-tools next-page: tools-worksheets diff --git a/_zh-cn/overviews/scala3-book/tools-worksheets.md b/_zh-cn/overviews/scala3-book/tools-worksheets.md index 214b744d8b..2e8270c996 100644 --- a/_zh-cn/overviews/scala3-book/tools-worksheets.md +++ b/_zh-cn/overviews/scala3-book/tools-worksheets.md @@ -3,7 +3,7 @@ title: worksheet type: section description: This section looks at worksheets, an alternative to Scala projects. language: zh-cn -num: 71 +num: 70 previous-page: tools-sbt next-page: interacting-with-java diff --git a/_zh-cn/overviews/scala3-book/where-next.md b/_zh-cn/overviews/scala3-book/where-next.md index 66c3afe639..e1d6052b6b 100644 --- a/_zh-cn/overviews/scala3-book/where-next.md +++ b/_zh-cn/overviews/scala3-book/where-next.md @@ -3,7 +3,7 @@ title: 下一步去哪 type: chapter description: Where to go next after reading the Scala Book language: zh-cn -num: 76 +num: 75 previous-page: scala-for-python-devs next-page: From 2f8cd56e32d65c880dce3c052d481669e6ee5b95 Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Tue, 3 Jan 2023 21:51:08 +0800 Subject: [PATCH 2532/3174] correct pre link in ca-context-bounds.md --- _zh-cn/overviews/scala3-book/ca-context-bounds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/overviews/scala3-book/ca-context-bounds.md b/_zh-cn/overviews/scala3-book/ca-context-bounds.md index 2227899378..56d948bad0 100644 --- a/_zh-cn/overviews/scala3-book/ca-context-bounds.md +++ b/_zh-cn/overviews/scala3-book/ca-context-bounds.md @@ -4,7 +4,7 @@ type: section description: This page demonstrates Context Bounds in Scala 3. language: zh-cn num: 61 -previous-page: types-type-classes +previous-page: ca-given-using-clauses next-page: ca-given-imports partof: scala3-book From 002ce463990ab984d5dfbdfbbb92e51191fb7e7b Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 3 Jan 2023 14:57:35 +0100 Subject: [PATCH 2533/3174] remove link to type classes page --- _zh-cn/overviews/scala3-book/scala-for-python-devs.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md index e56d017fb0..b1142e25d5 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md @@ -1310,7 +1310,9 @@ a.takeWhile(_ < 30) // List(10, 20) Scala 中的有些概念目前在 Python 中没有等效的功能。 请点击以下链接了解更多详情: -- 大多数与[上下文抽象][contextual]相关的概念,如[扩展方法][extension-methods]、[类型类][type-classes]、隐式值 + + +- 大多数与[上下文抽象][contextual]相关的概念,如[扩展方法][extension-methods]、类型类、隐式值 - Scala 允许多参数列表,从而实现部分应用函数等特性,以及创建自己的 DSL 的能力 - 样例类,对于函数式编程和模式匹配非常有用 - 创建自己的控制结构和 DSL 的能力 @@ -1355,6 +1357,6 @@ pip install -r requirements.txt [modeling-intro]: {% link _zh-cn/overviews/scala3-book/domain-modeling-intro.md %} [multiversal]: {% link _zh-cn/overviews/scala3-book/ca-multiversal-equality.md %} [toplevel]: {% link _zh-cn/overviews/scala3-book/taste-toplevel-definitions.md %} -[type-classes]: {% link _zh-cn/overviews/scala3-book/types-type-classes.md %} + [union-types]: {% link _zh-cn/overviews/scala3-book/types-union.md %} From 9d7607b256c0ebea131c13b25cebf93913b56ee5 Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Tue, 3 Jan 2023 21:59:36 +0800 Subject: [PATCH 2534/3174] delete invalid link in scala-for-python-devs.md --- _zh-cn/overviews/scala3-book/scala-for-python-devs.md | 1 - 1 file changed, 1 deletion(-) diff --git a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md index b1142e25d5..2ea3bacf3d 100644 --- a/_zh-cn/overviews/scala3-book/scala-for-python-devs.md +++ b/_zh-cn/overviews/scala3-book/scala-for-python-devs.md @@ -1357,6 +1357,5 @@ pip install -r requirements.txt [modeling-intro]: {% link _zh-cn/overviews/scala3-book/domain-modeling-intro.md %} [multiversal]: {% link _zh-cn/overviews/scala3-book/ca-multiversal-equality.md %} [toplevel]: {% link _zh-cn/overviews/scala3-book/taste-toplevel-definitions.md %} - [union-types]: {% link _zh-cn/overviews/scala3-book/types-union.md %} From 3aec13d88f2dce42ec3f49f2ccc1c405f28145bd Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 3 Jan 2023 16:17:06 +0100 Subject: [PATCH 2535/3174] find the corresponding english page to list languages --- _includes/sidebar-toc-multipage-overview.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/_includes/sidebar-toc-multipage-overview.html b/_includes/sidebar-toc-multipage-overview.html index 6b89191dd6..cf614c8da0 100644 --- a/_includes/sidebar-toc-multipage-overview.html +++ b/_includes/sidebar-toc-multipage-overview.html @@ -52,9 +52,12 @@
    Contents
    {% endfor %} {% elsif page.language and orphanTranslation == false %} + {% comment %} - {% assign engPath = page.id | remove_first: "/" | remove_first: page.language | append: '.html' %} - {% assign engPg = site.overviews | where: 'partof', page.partof | first %} + {% endcomment %} + {% assign engId = page.id | remove_first: "/" | remove_first: page.language %} + {% assign engPath = engId | append: '.html' %} + {% assign engPg = site.overviews | where: 'partof', page.partof | find: 'id', engId %}
    ! 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] =?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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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/3174] 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.

    -