3

If I omit the semicolon, this code doesn't compile.

def checkRadioButton(xml: DslBuilder): String => XmlTree = {
    val inputs = top(xml).\\*(hasLocalNameX("input"));
    { (buttonValue: String) =>
      // code omitted
    }
}

My guess is that, without the semicolon, scalac thinks that the partial function is another argument to the \\* method, instead of the return value. (It isn't actually a partial function, by the way, it's a total function.)

Can I do without the semicolon here? I've never had to use a semicolon at the end of a line before in Scala.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Robin Green
  • 32,079
  • 16
  • 104
  • 187
  • 2
    What is the compile error? And just out of curiosity: Does the ``\\*`` method take any second or implicit parameters? – Jens Egholm Jul 25 '13 at 09:21
  • 1
    Have you tried to use `locally { ... }` to separate the `val` line and the block ? – Beryllium Jul 25 '13 at 09:32
  • The compilation error is `scales.xml.XPath[List[scales.utils.Path[scales.xml.XmlItem,scales.xml.Elem,[T]scales.utils.ImmutableArrayProxy[T]]]] does not take parameters`, and no, it doesn't take any second or implicit parameters. There are some overloaded methods with the same name, but they don't either. – Robin Green Jul 25 '13 at 09:58
  • 1
    @Beryllium that also doesn't compile. – Robin Green Jul 25 '13 at 10:00
  • @Robin Green Have you tried to assign the result of the block to a `val` and return that one? – Beryllium Jul 25 '13 at 10:23

3 Answers3

2

Just add a second newline, which apparently is equivalent to the semicolon.

Still, I'm not entirely happy with this, as it seems fragile.

Robin Green
  • 32,079
  • 16
  • 104
  • 187
2

I’d write it like this instead:

def checkRadioButton(xml: DslBuilder): String => XmlTree = {
    val inputs = top(xml).\\*(hasLocalNameX("input"));
    (buttonValue: String) => { // <-- changed position of {
      // code omitted
    }
}
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
  • That can be simpler, see my answer. You can send the braces back to the parts bin and help keep la Suisse sweet. – som-snytt Aug 10 '13 at 06:52
2

Here is a simplification, explanation, and beautification.

Simplified,

scala> def f: String => String = {
     | val i = 7
     | { (x: String) =>
     |   "y"
     | }
     | }
<console>:9: error: Int(7) does not take parameters
       { (x: String) =>
       ^
<console>:12: error: type mismatch;
 found   : Unit
 required: String => String
       }
       ^

This fails because the newline after the 7 is not taken as a semicolon, for the reason that it might be a function application; you might want a DSL where the brace is on the next line. Here is the little nl in the syntax of an arg with braces.

Newline handling is described in 1.2 of the spec; a few spots like this one, where a single nl is accepted, are mentioned at the end of the section.

(Two newlines doesn't work, which is why that also fixes your problem.)

Notice that a nl is not accepted in front of a paren, so the following works (though with only parens, you get only one expression for your function literal):

scala> def g: String => String = {
     | val i = 7
     | ( (x: String) =>
     |   "y"
     | )
     | }
g: String => String

In fact, the best edit for the problem code is not more braces but fewer:

scala> def f: String => String = {
     | val i = 7
     | x: String =>
     | "y"
     | }
f: String => String

The reason for this nice syntax is that your method body is already a block expression, and when the result expression of a block is a function literal, you can simplify.

The type of x is also redundant.

scala> def f: String => String = {
     | val i = 7
     | x =>
     | val a = "a"
     | val b = "b"
     | a + i + x + b
     | }
f: String => String

And not surprisingly:

scala> def f: (String, Int) => String = {
     | val i = 7
     | (x, j) =>
     | x + (i + j)
     | }
f: (String, Int) => String

scala> f("bob",70)
res0: String = bob77
Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129