-
Notifications
You must be signed in to change notification settings - Fork 29
SIP-74 Allow Partial Function Literals to be defined with Parentheses #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
lihaoyi
wants to merge
19
commits into
scala:main
Choose a base branch
from
lihaoyi:partial-function-parens
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+198
−0
Open
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
4e265a2
.
lihaoyi ba0543b
.
lihaoyi d7fa176
.
lihaoyi 603fa01
.
lihaoyi 5cfb86f
.
lihaoyi 74e0521
.
lihaoyi 2e6ba60
.
lihaoyi 086be15
.
lihaoyi 253346b
.
lihaoyi 46ebb63
Update content/partial-function-parens.md
lihaoyi 1c6e823
.
lihaoyi 18fbc9b
.
lihaoyi eb95d20
.
lihaoyi b57baa1
.
lihaoyi 51d09ed
.
lihaoyi 2fa1272
.
lihaoyi 79465dc
.
lihaoyi 7a2f6ce
.
lihaoyi e94d9d7
Update partial-function-parens.md
lihaoyi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| --- | ||
| layout: sip | ||
| permalink: /sips/:title.html | ||
| stage: implementation | ||
| status: under-review | ||
| title: SIP-XX Allow Partial Function Literals to be defined with Parentheses | ||
| --- | ||
|
|
||
| **By: Li Haoyi** | ||
|
|
||
| ## History | ||
|
|
||
| | Date | Version | | ||
| |---------------|--------------------| | ||
| | Aug 22nd 2025 | Initial Draft | | ||
|
|
||
| ## Summary | ||
|
|
||
| This proposal is to allow parens `(...)` to be used instead of curly braces `{...}` | ||
| when defining partial functions which have only one `case`: | ||
|
|
||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) // 3 | ||
| ``` | ||
|
|
||
| Currently this syntax is disallowed: | ||
|
|
||
| ```scala | ||
| scala> Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) | ||
| -- [E018] Syntax Error: -------------------------------------------------------- | ||
| 1 |Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) | ||
| | ^^^^ | ||
| | expression expected but case found | ||
| | | ||
| | longer explanation available when compiling with `-explain` | ||
| ``` | ||
|
|
||
| Partial function literals in other non-function-call contexts can be defined with parens as well, | ||
| as long as they have a single `case` block with a single expression on the right: | ||
|
|
||
| ```scala | ||
| val partial: PartialFunction[(Int, Int), Int] = (case (a, b) if b > 2 => a) | ||
| ``` | ||
|
|
||
| ## Motivation | ||
|
|
||
| With Scala 3's [Optional Braces](https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html), | ||
| and [SIP-44's Fewer Braces](https://docs.scala-lang.org/sips/fewer-braces.html), single-line | ||
| partial functions are one of the only remaining places where curly braces are mandatory in Scala | ||
| syntax. | ||
|
|
||
| Needing to swap between parens and curlies a common friction of converting a function to | ||
| a partial function: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).map((a, b) => a) // OK | ||
| Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) // BAD | ||
| Seq((1, 2), (3, 4)).collect{ case (a, b) if b > 2 => a } // OK | ||
| ``` | ||
|
|
||
| This also currently causes visual messiness in method call chains where some single-line | ||
| methods use parens and others use curlies: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4), (5, 6)) | ||
| .filter(_._1 < 5) // PARENS | ||
| .collect{ case (a, b) if b > 2 => a } // CURLIES | ||
| .reduce(_ + _) // PARENS | ||
| ``` | ||
|
|
||
| In the syntax of other expressions, curly braces are only | ||
| necessary to define "blocks" with multiple statements: `if`-`else`, `try`-`catch`-`finally`, | ||
| `for`-`yield`, `do`-`while`, method calls like `foo()` etc. all allow you to replace curly braces | ||
| with parentheses (or elide them altogether) when there is only a single expression present. | ||
| This is unlike other languages like Java that mandate curly braces in these syntactic constructs. | ||
| Furthermore, in most expressions, Optional Braces means you do not have to write the curlies | ||
| if you do not want to. | ||
|
|
||
| This proposal brings partial functions in-line with the rest of Scala syntax, with the curly | ||
| braces only being mandatory for multi-statement blocks, and made optional with Scala 3's | ||
| Optional Braces. | ||
|
|
||
| ## Limitations | ||
|
|
||
| If not using the Brace-free/Fewer-braces syntax, partial function literals with multiple | ||
| statements in one `case` block will still require curly braces, in line with how curly | ||
| braces are used to define multi-statement blocks in other contexts: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).collect { | ||
| case (a, b) if b > 2 => | ||
| println(b) | ||
| a | ||
| } | ||
| ``` | ||
|
|
||
| Partial functions with multiple `case` statements will also require braces: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).collect { | ||
| case (a, b) if b > 2 => a | ||
| case _ => ??? | ||
| } | ||
| ``` | ||
|
|
||
| Although with Scala 3's [Optional Braces](https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html), | ||
| we expect that most of these multi-statement constructs would be written without braces as well: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).collect: | ||
| case (a, b) if b > 2 => | ||
| println(b) | ||
| a | ||
| ``` | ||
|
|
||
| Partial functions with multiple `case` statements will also require braces: | ||
|
|
||
| ```scala | ||
| Seq((1, 2), (3, 4)).collect: | ||
| case (a, b) if b > 2 => a | ||
| case _ => ??? | ||
| ``` | ||
|
|
||
| This proposal does not affect `match` blocks, which typically have multiple lines, nor does | ||
| it affect `catch` blocks which already allow a curly-free `catch case e: Throwable =>` syntax. | ||
| These also can be written without braces in most multi-line scenarios | ||
|
|
||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.