Skip to content

fewerBraces: allow braceless lambdas as argument to an infix operator #17729

@sjrd

Description

@sjrd

The following example reproduces a very common idiom in Laminar:

class EventSource[A](elems: A*):
  def -->(dest: A => Unit): Unit = elems.foreach(dest)

object Test {
  def main(args: Array[String]): Unit =
    val source = new EventSource(5, 8, 10)
    source --> { x =>
      val y = x * x
      println(y)
    }
}

If we try to write the lambda using the braceless syntax of fewerBraces, as follows:

class EventSource[A](elems: A*):
  def -->(dest: A => Unit): Unit = elems.foreach(dest)

object Test {
  def main(args: Array[String]): Unit =
    val source = new EventSource(5, 8, 10)
    source --> x =>
      val y = x * x
      println(y)
}

we get an obscure error message:

-- Error: tests/run/hello.scala:7:11 -------------------------------------------
7 |    source --> x =>
  |    ^^^^^^^^^^^^
  |    not a legal formal parameter
-- [E006] Not Found Error: tests/run/hello.scala:8:14 --------------------------
8 |      val y = x * x
  |              ^
  |              Not found: x
  |
  | longer explanation available when compiling with `-explain`
2 errors found

Because of this limitation, typical Laminar code becomes very ugly if we try to use fewerBraces on them. Here is a diff coming from one of my personal projects:

diff --git a/src/main/scala/be/doeraene/barrage/mainui/Main.scala b/src/main/scala/be/doeraene/barrage/mainui/Main.scala
index e65467d..d187265 100644
--- a/src/main/scala/be/doeraene/barrage/mainui/Main.scala
+++ b/src/main/scala/be/doeraene/barrage/mainui/Main.scala
@@ -483,9 +483,9 @@ object Main:
         button(
           "Join",
           disabled <-- myClientUUID.signal.map(_.isEmpty),
-          composeEvents(onClick)(_.sample(myClientUUID.signal.combineWith(peerID))) --> { x =>
-            joinGame(x._1.get, x._2)
-          },
+          composeEvents(onClick)(_.sample(myClientUUID.signal.combineWith(peerID))) --> :
+            x =>
+              joinGame(x._1.get, x._2),
         ),
       ),
       h1("Create a game"),
@@ -545,11 +545,12 @@ object Main:
       h1("Joining game"),
       p(
         label("Your name: "),
-        input(typ := "text", defaultValue := "", onInput.mapToValue --> { displayName =>
-          if displayName != "" then
-            println(s"setting display name to $displayName")
-            uiEventBus.emit(UIEvent.SetDisplayName(displayName))
-        }),
+        input(typ := "text", defaultValue := "", onInput.mapToValue --> :
+          displayName =>
+            if displayName != "" then
+              println(s"setting display name to $displayName")
+              uiEventBus.emit(UIEvent.SetDisplayName(displayName))
+        ),
       ),
       p(
         button("Leave", onClick.mapTo(UIEvent.Leave) --> uiEventBus)

I suggest that the above syntax be allowed, i.e., that an infix operator may introduce a braceless lambda, just like a dotted call like .map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions