3

When I run an external process, looks like we need to add a blank line after the calling. Why it throws that error?

 class JobActor extends Actor {
  def receive = {
    case msg:String =>
       Process(msg)!
                       // here need a blank line, otherwise it throws error 
       sender ! "complete"
  } 
}

the error is

[error]  found   : akka.actor.ActorRef
[error]  required: scala.sys.process.ProcessLogger
[error]        sender ! "complete"
[error]        ^
[error] one error found
Daniel Wu
  • 5,853
  • 12
  • 42
  • 93

2 Answers2

5

You hit the exact reason of why postfix operators is a feature that generates a warning when you compile with the -feature flag.

Here's an extract that explains why such feature is still under discussion (emphasis added):

postfixOps. Only where enabled, postfix operator notation (expr op) will be allowed. Why keep the feature? Several DSLs written in Scala need the notation. Why control it? Postfix operators interact poorly with semicolon inference. Most programmers avoid them for this reason.

(source)

Process defines two methods

abstract def !: Int 
abstract def !(log: ProcessLogger): Int 

When you do

Process(msg)!

you mean to call the former, but since there's no unambiguous indication that the line should end (i.e. that a semicolon should be inferred), the parser starts reading the next line, it finds something can can syntactically be an argument (sender) and you end up calling the second version of ! instead.

The resulting code is actually:

Process(msg)! sender ! "complete"

i.e.

(Process(msg).!(sender)).!("complete")

hence the error: sender is not an instance of ProcessLogger.

In order to fix it, you have to untangle the ambiguity yourself. There's many ways of doing it, the simplest one being to avoid the postfix operator altogether:

Process(msg).!
sender ! "complete"

Actually, given this other question of yours, you can even just do

msg.!
sender ! "complete"
Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
4

This could be another case where Scala's grammar does not allow for postfix operators in any other place than the end of an expression.

The first one was described in "Why does this code need an empty line or a semicolon?"

Adding a semi-colon might also make the code compile, because of the semicolon inference.

Process(msg)!;
sender ! "complete"
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250