question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Braceless syntax with higher order functions and case

See original GitHub issue

Compiler version

3.0.0

Minimized code

object Foo:
  def joe(): List[(Int, Int)] =
    List((2, 3), (3, 4)).filter { case (a, b) => b > a }

Output (click arrow to expand)

If I remove the {} I get a parser error and exception. If I then wrap the case onto the next line and indent it doesn’t like that. I can replace the {} with () but then it doesn’t like the case so then I can remove the case and it seems fine with that. I can’t wrap the case or without the case to the next line. It is like () is required but is that going to work with a multi-line lambda?

I would expect that Scala 3 would still take the case syntax like Scala 2 but maybe warn because it it not needed.

I would also expect that I could wrap the (a, b) => b > a or other statements to the next line and indent.

The context of this investigation is related to the default in scalafmt that keeps the case on the same line as the HOF like foreach below where we would assume it should start on the next line. We think the current format is correct and that we should be able to remove the {} and it should “just work” in Scala 3.

-    times.foreach {
-      case (k, v) =>
-        val key = k.split(":")(1)
-        totalTimes(key) = totalTimes.getOrElse(key, 0L) + v
-        totalThreads(key) = totalThreads.getOrElse(key, 0L) + 1
+    times.foreach { case (k, v) =>
+      val key = k.split(":")(1)
+      totalTimes(key) = totalTimes.getOrElse(key, 0L) + v
+      totalThreads(key) = totalThreads.getOrElse(key, 0L) + 1

Note: couldn’t get details to work without code example getting unformatted.

[info] compiling 1 Scala source to /Users/eric/workspace/sconfig/sconfig/js/target/scala-3.0.0/classes ...
[error] -- [E040] Syntax Error: /Users/eric/workspace/sconfig/sconfig/shared/src/main/scala-3/org/ekrich/config/Foo.scala:3:33 
[error] 3 |    List((2, 3), (3, 4)).filter  case (a, b) => b > a 
[error]   |                                 ^^^^
[error]   |                                 unindent expected, but 'case' found
[error] -- [E040] Syntax Error: /Users/eric/workspace/sconfig/sconfig/shared/src/main/scala-3/org/ekrich/config/Foo.scala:4:0 
[error] 4 |
[error]   |^
[error]   |unindent expected, but eof found
[info] exception occurred while parsing /Users/eric/workspace/sconfig/sconfig/shared/src/main/scala-3/org/ekrich/config/Foo.scala
[info] exception occurred while compiling /Users/eric/workspace/sconfig/sconfig/shared/src/main/scala-3/org/ekrich/config/Foo.scala
java.lang.AssertionError: assertion failed: dotty.tools.dotc.parsing.Scanners$$anon$1@65705702 while compiling /Users/eric/workspace/sconfig/sconfig/shared/src/main/scala-3/org/ekrich/config/Foo.scala
[error] ## Exception when compiling 108 sources to /Users/eric/workspace/sconfig/sconfig/js/target/scala-3.0.0/classes
[error] java.lang.AssertionError: assertion failed: dotty.tools.dotc.parsing.Scanners$$anon$1@65705702
[error] scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error] dotty.tools.dotc.parsing.Scanners$Scanner.insert(Scanners.scala:360)
[error] dotty.tools.dotc.parsing.Scanners$Scanner.observeOutdented(Scanners.scala:586)
[error] dotty.tools.dotc.parsing.Parsers$Parser.acceptStatSepUnlessAtEnd(Parsers.scala:327)
[error] dotty.tools.dotc.parsing.Parsers$Parser.blockStatSeq$$anonfun$1(Parsers.scala:3938)
[error] dotty.tools.dotc.parsing.Parsers$Parser.checkNoEscapingPlaceholders(Parsers.scala:462)
[error] dotty.tools.dotc.parsing.Parsers$Parser.blockStatSeq(Parsers.scala:3941)
[error] dotty.tools.dotc.parsing.Parsers$Parser.block(Parsers.scala:2416)
[error] dotty.tools.dotc.parsing.Parsers$Parser.blockExpr$$anonfun$1(Parsers.scala:2408)
[error] dotty.tools.dotc.parsing.Parsers$Parser.enclosed(Parsers.scala:518)
[error] dotty.tools.dotc.parsing.Parsers$Parser.inBracesOrIndented(Parsers.scala:530)
[error] dotty.tools.dotc.parsing.Parsers$Parser.inDefScopeBraces(Parsers.scala:538)
[error] dotty.tools.dotc.parsing.Parsers$Parser.blockExpr(Parsers.scala:2406)
[error] dotty.tools.dotc.parsing.Parsers$Parser.simpleExpr(Parsers.scala:2235)
[error] dotty.tools.dotc.parsing.Parsers$Parser.$init$$$anonfun$6(Parsers.scala:2191)
[error] dotty.tools.dotc.parsing.Parsers$Parser.postfixExpr(Parsers.scala:2168)
[error] dotty.tools.dotc.parsing.Parsers$Parser.expr1(Parsers.scala:2013)
[error] dotty.tools.dotc.parsing.Parsers$Parser.expr(Parsers.scala:1892)
[error] dotty.tools.dotc.parsing.Parsers$Parser.$init$$$anonfun$5(Parsers.scala:1872)
[error] dotty.tools.dotc.parsing.Parsers$Parser.subPart(Parsers.scala:590)
[error] dotty.tools.dotc.parsing.Parsers$Parser.subExpr(Parsers.scala:1874)
[error] dotty.tools.dotc.parsing.Parsers$Parser.defDefOrDcl(Parsers.scala:3328)
[error] dotty.tools.dotc.parsing.Parsers$Parser.defOrDcl(Parsers.scala:3219)
[error] dotty.tools.dotc.parsing.Parsers$Parser.templateStatSeq$$anonfun$1(Parsers.scala:3851)
[error] dotty.tools.dotc.parsing.Parsers$Parser.checkNoEscapingPlaceholders(Parsers.scala:462)
[error] dotty.tools.dotc.parsing.Parsers$Parser.templateStatSeq(Parsers.scala:3861)
[error] dotty.tools.dotc.parsing.Parsers$Parser.$anonfun$33(Parsers.scala:3740)
[error] dotty.tools.dotc.parsing.Parsers$Parser.enclosed(Parsers.scala:518)
[error] dotty.tools.dotc.parsing.Parsers$Parser.inBracesOrIndented(Parsers.scala:530)
[error] dotty.tools.dotc.parsing.Parsers$Parser.inDefScopeBraces(Parsers.scala:538)
[error] dotty.tools.dotc.parsing.Parsers$Parser.templateBody(Parsers.scala:3740)
[error] dotty.tools.dotc.parsing.Parsers$Parser.templateBodyOpt(Parsers.scala:3733)
[error] dotty.tools.dotc.parsing.Parsers$Parser.template(Parsers.scala:3710)
[error] dotty.tools.dotc.parsing.Parsers$Parser.templateOpt(Parsers.scala:3722)
[error] dotty.tools.dotc.parsing.Parsers$Parser.objectDef(Parsers.scala:3474)
[error] dotty.tools.dotc.parsing.Parsers$Parser.tmplDef(Parsers.scala:3433)
[error] dotty.tools.dotc.parsing.Parsers$Parser.defOrDcl(Parsers.scala:3225)
[error] dotty.tools.dotc.parsing.Parsers$Parser.topStatSeq(Parsers.scala:3797)
[error] dotty.tools.dotc.parsing.Parsers$Parser.topstats$2(Parsers.scala:3977)
[error] dotty.tools.dotc.parsing.Parsers$Parser.compilationUnit$$anonfun$1(Parsers.scala:3982)
[error] dotty.tools.dotc.parsing.Parsers$Parser.checkNoEscapingPlaceholders(Parsers.scala:462)
[error] dotty.tools.dotc.parsing.Parsers$Parser.compilationUnit(Parsers.scala:3987)
[error] dotty.tools.dotc.parsing.Parsers$Parser.parse(Parsers.scala:175)
[error] dotty.tools.dotc.typer.FrontEnd.parse$$anonfun$1(FrontEnd.scala:57)
[error] dotty.tools.dotc.typer.FrontEnd.monitor(FrontEnd.scala:43)
[error] dotty.tools.dotc.typer.FrontEnd.parse(FrontEnd.scala:67)
[error] dotty.tools.dotc.typer.FrontEnd.runOn$$anonfun$1(FrontEnd.scala:108)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.immutable.List.foreach(List.scala:333)
[error] dotty.tools.dotc.typer.FrontEnd.runOn(FrontEnd.scala:108)
[error] dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:205)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
[error] dotty.tools.dotc.Run.runPhases$5(Run.scala:215)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:223)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:230)
[error] dotty.tools.dotc.Run.compileSources(Run.scala:166)
[error] dotty.tools.dotc.Run.compile(Run.scala:150)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
[error] dotty.tools.xsbt.CompilerBridgeDriver.run(CompilerBridgeDriver.java:88)
[error] dotty.tools.xsbt.CompilerBridge.run(CompilerBridge.java:22)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:186)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:241)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:176)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:157)
[error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:157)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:204)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:174)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:172)
[error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:457)
[error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:261)
[error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:412)
[error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:499)
[error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:399)
[error] sbt.internal.inc.Incremental$.apply(Incremental.scala:166)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:482)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2346)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2303)
[error] sbt.internal.io.Retry$.apply(Retry.scala:46)
[error] sbt.internal.io.Retry$.apply(Retry.scala:28)
[error] sbt.internal.io.Retry$.apply(Retry.scala:23)
[error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:31)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2299)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] sbt.Execute.work(Execute.scala:291)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[error] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
[error] java.lang.Thread.run(Thread.java:748)

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:12 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
smartercommented, May 25, 2021

No it’s not, I missed that part, could you open an issue just about that?

0reactions
ekrichcommented, May 25, 2021

I see now, Scala 3 supports both with and without the case so it is backward compatible.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Recitation 3 Higher-order and Anonymous Functions, Currying
Let us look at why it is useful to have higher-order functions. The first reason is that it allows you to write more...
Read more >
Optional Braces - Scala 3 - EPFL
Scala 3 enforces some rules on indentation and allows some occurrences of braces {...} to be optional: First, some badly indented programs are...
Read more >
Introducing Computer Science ch 8: Higher-Order Functions
A function that takes another function as one of its arguments, as every does, is called a higher-order function. If we focus our...
Read more >
Higher-Order Functions in C - Medium
A higher-order function is a function that accepts other functions as arguments or returns a function itself. Since C relies heavily on use...
Read more >
Decide on the role of : in indentation syntax #7136 - GitHub
The motivation for this second case is to make uses of library-defined operations close to native syntax. If native syntax allows to drop ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found