From 4e265a2176382dca1f35f33ef7b1c5305500514d Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:03:23 +0200 Subject: [PATCH 01/18] . --- content/no-curly-partial-match.md | 99 +++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 content/no-curly-partial-match.md diff --git a/content/no-curly-partial-match.md b/content/no-curly-partial-match.md new file mode 100644 index 00000000..544823c7 --- /dev/null +++ b/content/no-curly-partial-match.md @@ -0,0 +1,99 @@ +--- +layout: sip +permalink: /sips/:title.html +stage: implementation +status: under-review +title: SIP-XX - No-Curly Partial Functions and Matches +--- + +**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`, and eliding the `case` keyword: + + +```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` +``` + +## Motivation + +Allowing partial functions with only a single-expression to be defined using parentheses makes +the language more regular, and removes a common friction of converting a function to a partial +function and having to change all the parens to curlies: + +```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 +``` + +Partial functions and `match` statements are currently the only expressions where curly braces are +required and parentheses are disallowed. 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 + +Unlike `match` statements, partial functions are very commonly written in a single line with +a single expression as the result, and so having to put curlies around them is tedious and +irregular. Allowing them to use parentheses would make the language syntax more regular, +reduce friction of people converting between normal and partial functions, and make code +more regular and easier to read by associating curlies more strongly with multi-statement blocks +rather than multi-statement-blocks-and-also-partial-functions. + +## 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 more-complex constructs would be written without braces as well. \ No newline at end of file From ba0543b26e84a5c02ce94ff8334090189e23e280 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:07:35 +0200 Subject: [PATCH 02/18] . --- content/no-curly-partial-match.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/content/no-curly-partial-match.md b/content/no-curly-partial-match.md index 544823c7..bb618ef6 100644 --- a/content/no-curly-partial-match.md +++ b/content/no-curly-partial-match.md @@ -38,9 +38,13 @@ scala> Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) ## Motivation -Allowing partial functions with only a single-expression to be defined using parentheses makes -the language more regular, and removes a common friction of converting a function to a partial -function and having to change all the parens to curlies: +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 @@ -58,19 +62,16 @@ Seq((1, 2), (3, 4), (5, 6)) .reduce(_ + _) // PARENS ``` -Partial functions and `match` statements are currently the only expressions where curly braces are -required and parentheses are disallowed. In the syntax of other expressions, curly braces are only +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 +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. -Unlike `match` statements, partial functions are very commonly written in a single line with -a single expression as the result, and so having to put curlies around them is tedious and -irregular. Allowing them to use parentheses would make the language syntax more regular, -reduce friction of people converting between normal and partial functions, and make code -more regular and easier to read by associating curlies more strongly with multi-statement blocks -rather than multi-statement-blocks-and-also-partial-functions. +This proposal brings partial functions in-line with the rest of Scala syntax, with the curly +braces reserved for multi-statement blocks, and made optional. ## Limitations @@ -96,4 +97,7 @@ Seq((1, 2), (3, 4)).collect { ``` 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 more-complex constructs would be written without braces as well. \ No newline at end of file +we expect that most of these more-complex constructs would be written without braces as well. + +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. From d7fa176484b1fa8c8fda60a85e20b839a05a6155 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:07:58 +0200 Subject: [PATCH 03/18] . --- content/{no-curly-partial-match.md => no-curly-partials.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename content/{no-curly-partial-match.md => no-curly-partials.md} (100%) diff --git a/content/no-curly-partial-match.md b/content/no-curly-partials.md similarity index 100% rename from content/no-curly-partial-match.md rename to content/no-curly-partials.md From 603fa0112137ec1b4c5cea5239de7792c6f9bdff Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:11:10 +0200 Subject: [PATCH 04/18] . --- .../{no-curly-partials.md => partial-function-parens.md} | 9 +++++++++ 1 file changed, 9 insertions(+) rename content/{no-curly-partials.md => partial-function-parens.md} (92%) diff --git a/content/no-curly-partials.md b/content/partial-function-parens.md similarity index 92% rename from content/no-curly-partials.md rename to content/partial-function-parens.md index bb618ef6..84a3fa75 100644 --- a/content/no-curly-partials.md +++ b/content/partial-function-parens.md @@ -36,6 +36,13 @@ scala> Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) | 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), @@ -101,3 +108,5 @@ we expect that most of these more-complex constructs would be written without br 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. + + From 5cfb86f1300d4ff241a8092943875d03c76acf68 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:11:31 +0200 Subject: [PATCH 05/18] . --- content/partial-function-parens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 84a3fa75..1e1db35d 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -3,7 +3,7 @@ layout: sip permalink: /sips/:title.html stage: implementation status: under-review -title: SIP-XX - No-Curly Partial Functions and Matches +title: SIP-XX Allow Partial Function Literals to be defined with Parentheses --- **By: Li Haoyi** From 74e0521122c04142ad17a2e7f113ca88618156a2 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:11:50 +0200 Subject: [PATCH 06/18] . --- content/partial-function-parens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 1e1db35d..4a411378 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -17,7 +17,7 @@ title: SIP-XX Allow Partial Function Literals to be defined with Parentheses ## Summary This proposal is to allow parens `(...)` to be used instead of curly braces `{...}` -when defining partial functions which have only one `case`, and eliding the `case` keyword: +when defining partial functions which have only one `case`: ```scala From 2e6ba606604d88433e4b1a2b8849b1dc4fb0f7f3 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:13:10 +0200 Subject: [PATCH 07/18] . --- content/partial-function-parens.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 4a411378..36e5b0f7 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -78,7 +78,8 @@ Furthermore, in most expressions, Optional Braces means you do not have to write if you do not want to. This proposal brings partial functions in-line with the rest of Scala syntax, with the curly -braces reserved for multi-statement blocks, and made optional. +braces only being mandatory for multi-statement blocks, and made optional with Scala 3's +Optional Braces. ## Limitations From 086be155fe3e93068a95e7e0567bd7622019b95d Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 18:13:35 +0200 Subject: [PATCH 08/18] . --- content/partial-function-parens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 36e5b0f7..bb50dd70 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -105,7 +105,7 @@ Seq((1, 2), (3, 4)).collect { ``` 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 more-complex constructs would be written without braces as well. +we expect that most of these multi-statement constructs would be written without braces as well. 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. From 253346bb60e464a72f6445ff965db00f813da356 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 19:21:19 +0200 Subject: [PATCH 09/18] . --- content/partial-function-parens.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index bb50dd70..ea8f7556 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -105,9 +105,25 @@ Seq((1, 2), (3, 4)).collect { ``` 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. +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 From 46ebb63eed33b53727d8e16acd5b0a06ec14ef28 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 19:35:48 +0200 Subject: [PATCH 10/18] Update content/partial-function-parens.md Co-authored-by: Quentin Bernet --- content/partial-function-parens.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index ea8f7556..7c9cea89 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -114,7 +114,6 @@ Seq((1, 2), (3, 4)).collect: a ``` -Partial functions with multiple `case` statements will also require braces: ```scala Seq((1, 2), (3, 4)).collect: From 1c6e82303f22b489727277d194dc289405a84a00 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:34:02 +0200 Subject: [PATCH 11/18] . --- content/partial-function-parens.md | 57 +++++++++++++++++------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 7c9cea89..e6dbd15c 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -36,13 +36,42 @@ scala> Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) | longer explanation available when compiling with `-explain` ``` +Partial functions with multiple `case` blocks should also be allowed to use parentheses, +as long as every case block only contains a single expression: + + +```scala +Seq((1, 2), (3, 4)).collect( + case (a, b) if b > 2 => a + case _ => ??? +) +``` + +For consistency, we also allow parentheses to be used in `match` statements, again as long +as each branch of the match only has a single expression to the right of the arrow: + +```scala +(1, 2) match ( + case (a, b) if b > 2 => a + case _ => ??? +) +``` + 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) +val partial: PartialFunction[(Int, Int), Int] = case (a, b) if b > 2 => a ``` +This delimiter-less syntax is similar to what is already allowed today in `catch` blocks: + +```scala +try ??? +catch case e: Exception => ??? +``` + + ## Motivation With Scala 3's [Optional Braces](https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html), @@ -79,7 +108,9 @@ 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. +Optional Braces. With this proposal, curly braces are _only_ for opening multi-statement blocks, +_always_ in places that can be replaced by indentation-based blocks if the user wants to do so. +They are no longer also incidentally tied to partial-function syntax as they were before. ## Limitations @@ -95,15 +126,6 @@ Seq((1, 2), (3, 4)).collect { } ``` -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: @@ -113,16 +135,3 @@ Seq((1, 2), (3, 4)).collect: println(b) a ``` - - -```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 - - From 18fbc9be7a9511cd13b743f46acc3addd99591db Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:36:36 +0200 Subject: [PATCH 12/18] . --- content/partial-function-parens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index e6dbd15c..a9e43e8b 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -57,8 +57,8 @@ as each branch of the match only has a single expression to the right of the arr ) ``` -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: +Partial function literals should also be allowed to be defined without parentheses for +single-line scenarios such as: ```scala val partial: PartialFunction[(Int, Int), Int] = case (a, b) if b > 2 => a From eb95d20a02226f0055c9886f24631ff78809f93e Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:43:36 +0200 Subject: [PATCH 13/18] . --- content/partial-function-parens.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index a9e43e8b..da4e6a68 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -112,6 +112,32 @@ Optional Braces. With this proposal, curly braces are _only_ for opening multi-s _always_ in places that can be replaced by indentation-based blocks if the user wants to do so. They are no longer also incidentally tied to partial-function syntax as they were before. +With this change, all the snippets below are now valid: we can see how the syntax of `()`, `{}`, +or `.collect:` followed by indentation is now fully orthogonal to the partial function `case` +expression within them, resulting in a much more regular syntac than before when parentheses +were prohibited but the other syntaxes worked. + +```scala +Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) +Seq((1, 2), (3, 4)).collect { case (a, b) if b > 2 => a } +Seq((1, 2), (3, 4)).collect: + case (a, b) if b > 2 => a + +Seq((1, 2), (3, 4)).collect( + case (a, b) if b > 2 => a + case (a, b) if a > 2 => b +) + +Seq((1, 2), (3, 4)).collect { + case (a, b) if b > 2 => a + case (a, b) if a > 2 => b +} + +Seq((1, 2), (3, 4)).collect: + case (a, b) if b > 2 => a + case (a, b) if a > 2 => b + +``` ## Limitations If not using the Brace-free/Fewer-braces syntax, partial function literals with multiple From b57baa12120379b0a3d983e39caf1a52915ff6a2 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:43:56 +0200 Subject: [PATCH 14/18] . --- content/partial-function-parens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index da4e6a68..b62e8505 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -114,7 +114,7 @@ They are no longer also incidentally tied to partial-function syntax as they wer With this change, all the snippets below are now valid: we can see how the syntax of `()`, `{}`, or `.collect:` followed by indentation is now fully orthogonal to the partial function `case` -expression within them, resulting in a much more regular syntac than before when parentheses +expression within them, resulting in a much more regular syntax than before when parentheses were prohibited but the other syntaxes worked. ```scala From 51d09ed5337ed17d3f749d54bb17678d37c4ca11 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:49:57 +0200 Subject: [PATCH 15/18] . --- content/partial-function-parens.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index b62e8505..3bcf711f 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -79,6 +79,10 @@ and [SIP-44's Fewer Braces](https://docs.scala-lang.org/sips/fewer-braces.html), partial functions are one of the only remaining places where curly braces are mandatory in Scala syntax. +```scala +// No way to write this without curlies +Seq((1, 2), (3, 4)).collect{ case (a, b) if b > 2 => a } +``` Needing to swap between parens and curlies a common friction of converting a function to a partial function: From 2fa1272b68d09a801e8a016ace4a94ff14f872af Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 22 Aug 2025 23:50:34 +0200 Subject: [PATCH 16/18] . --- content/partial-function-parens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index 3bcf711f..e3f4f501 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -83,8 +83,8 @@ syntax. // No way to write this without curlies Seq((1, 2), (3, 4)).collect{ case (a, b) if b > 2 => a } ``` -Needing to swap between parens and curlies a common friction of converting a function to -a partial function: +Needing to swap between parens and curlies also adds friction of converting a function to +a partial function, which happens frequently: ```scala Seq((1, 2), (3, 4)).map((a, b) => a) // OK From 79465dc4d5d292263655d0ee06ea39cd0c7ed095 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 23 Aug 2025 05:50:35 +0200 Subject: [PATCH 17/18] . --- content/partial-function-parens.md | 63 +++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index e3f4f501..fcf2acc6 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -47,6 +47,24 @@ Seq((1, 2), (3, 4)).collect( ) ``` +Multi-line `case` blocks should work with parens as well, just like multi-line function +literals without `case` already work: + +```scala +Seq((1, 2), (3, 4)).collect( + case (a, b) => + println(b) + a +) + +// This already works today +Seq((1, 2), (3, 4)).collect( + (a, b) => + println(b) + a +) +``` + For consistency, we also allow parentheses to be used in `match` statements, again as long as each branch of the match only has a single expression to the right of the arrow: @@ -57,6 +75,18 @@ as each branch of the match only has a single expression to the right of the arr ) ``` +And we should allow multi-`case` single-line partial functions, just like you can already do +with `match` today: + +```scala +Seq((1, 2), (3, 4)).collect{ case (a, b) if b > 2 => a case (a, b) if a > 2 => b } +Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a case (a, b) if a > 2 => b) + +// This already works today +(1, 2) match { case (a, b) if b > 2 => a case _ => ??? } +``` + + Partial function literals should also be allowed to be defined without parentheses for single-line scenarios such as: @@ -141,27 +171,24 @@ Seq((1, 2), (3, 4)).collect: case (a, b) if b > 2 => a case (a, b) if a > 2 => b -``` -## 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) +Seq((1, 2), (3, 4)).collect( + case (a, b) => + println(b) a -} -``` +) -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: +Seq((1, 2), (3, 4)).map((a, b) => a) +Seq((1, 2), (3, 4)).map { (a, b) => a } +Seq((1, 2), (3, 4)).map: + (a, b) => a +Seq((1, 2), (3, 4)).map: + (a, b) => + println(b) + a -```scala -Seq((1, 2), (3, 4)).collect: +Seq((1, 2), (3, 4)).collect( case (a, b) if b > 2 => - println(b) + println(b) a +) ``` From 7a2f6cef54237e4699b538b9487bd26dce89c89a Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 23 Aug 2025 05:57:36 +0200 Subject: [PATCH 18/18] . --- content/partial-function-parens.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/content/partial-function-parens.md b/content/partial-function-parens.md index fcf2acc6..b8bce995 100644 --- a/content/partial-function-parens.md +++ b/content/partial-function-parens.md @@ -36,8 +36,8 @@ scala> Seq((1, 2), (3, 4)).collect(case (a, b) if b > 2 => a) | longer explanation available when compiling with `-explain` ``` -Partial functions with multiple `case` blocks should also be allowed to use parentheses, -as long as every case block only contains a single expression: +Partial functions with multiple `case` blocks should also be allowed to use parentheses +: ```scala @@ -65,8 +65,7 @@ Seq((1, 2), (3, 4)).collect( ) ``` -For consistency, we also allow parentheses to be used in `match` statements, again as long -as each branch of the match only has a single expression to the right of the arrow: +For consistency, we also allow parentheses to be used in `match` statements: ```scala (1, 2) match ( @@ -135,7 +134,7 @@ Seq((1, 2), (3, 4), (5, 6)) 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. +with parentheses or elide them altogether using indentation. 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.